From be8d26848e7ba4e5dcffd6a857a8b58cadedb195 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Sun, 7 Jan 2024 23:58:22 +0100 Subject: [PATCH] GPL_TS-20110526-3.4.x --- Makefile | 1158 +- .../lib/debug/linux/gcc/glibc.so/readme.txt | 1 - .../lib/debug/linux/gcc/libc.so/readme.txt | 1 - .../lib/release/linux/gcc/glibc.so/readme.txt | 1 - .../lib/release/linux/gcc/libc.so/readme.txt | 1 - .../bios_emulator/scitech/src/common/makefile | 2 +- .../scitech/src/pm/os2/dossctl.obj | Bin 59 -> 0 bytes .../scitech/src/pm/tests/vftest.c | 4 +- board/barco/barco.c | 17 +- board/barco/barco_svc.h | 17 +- board/barco/flash.c | 17 +- board/barco/speed.h | 17 +- board/cray/L1/bootscript.hush | 2 +- board/gth/ee_dev.h | 2 +- board/jse/host_bridge.c | 2 +- board/mv_feroceon/USP/ethSwitch/mv_switch.c | 382 + board/mv_feroceon/USP/ethSwitch/mv_switch.h | 75 + .../mv_feroceon/USP/ethSwitch/mv_switchRegs.h | 109 + board/mv_feroceon/USP/jump.S | 250 + board/mv_feroceon/USP/mv_egiga.c | 550 + board/mv_feroceon/USP/mv_ext2_boot.c | 189 + board/mv_feroceon/USP/mv_flash.c | 1684 +++ board/mv_feroceon/USP/mv_fs.c | 2962 +++++ board/mv_feroceon/USP/mv_fs.h | 184 + board/mv_feroceon/USP/mv_i2c.c | 171 + board/mv_feroceon/USP/mv_ide.c | 1500 +++ board/mv_feroceon/USP/mv_loadnet.c | 233 + board/mv_feroceon/USP/mv_mon_init.c | 184 + board/mv_feroceon/USP/mv_mon_init.h | 36 + board/mv_feroceon/USP/mv_nand.c | 71 + board/mv_feroceon/USP/mv_pageTable.c | 592 + board/mv_feroceon/USP/mv_pci.c | 837 ++ board/mv_feroceon/USP/mv_protectionUnit.c | 1021 ++ board/mv_feroceon/USP/mv_rtc.c | 94 + board/mv_feroceon/USP/mv_serial.c | 158 + board/mv_feroceon/USP/mv_usb_dev.c | 379 + board/mv_feroceon/USP/mv_usb_host.c | 152 + board/mv_feroceon/USP/nBootloader.c | 253 + board/mv_feroceon/USP/sdio/mmc.c | 574 + board/mv_feroceon/USP/sdio/mustang_sdiodef.h | 211 + board/mv_feroceon/common/mv802_3.h | 207 + board/mv_feroceon/common/mvCommon.c | 277 + board/mv_feroceon/common/mvCommon.h | 308 + board/mv_feroceon/common/mvDebug.c | 326 + board/mv_feroceon/common/mvDebug.h | 178 + board/mv_feroceon/common/mvDeviceId.h | 173 + board/mv_feroceon/common/mvStack.c | 100 + board/mv_feroceon/common/mvStack.h | 140 + board/mv_feroceon/common/mvTypes.h | 245 + board/mv_feroceon/common/mvTypes.h.keep | 245 + board/mv_feroceon/config/Makefile | 82 + board/mv_feroceon/config/config.mk | 5 + board/mv_feroceon/config/config_16mb.mk | 4 + board/mv_feroceon/config/config_def.mk | 5 + board/mv_feroceon/config/config_nand.mk | 15 + board/mv_feroceon/config/config_prpmc.mk | 5 + board/mv_feroceon/config/mvRules.mk | 77 + board/mv_feroceon/config/u-boot-nand.lds | 64 + .../config/u-boot-sec128k-tiny.lds | 73 + board/mv_feroceon/config/u-boot-sec128k.lds | 79 + board/mv_feroceon/config/u-boot-sec256k.lds | 79 + .../config/u-boot-sec4k-header-tiny.lds | 75 + .../mv_feroceon/config/u-boot-sec4k-tiny.lds | 74 + board/mv_feroceon/config/u-boot-sec4k.lds | 74 + .../config/u-boot-sec64k-header-nand.lds | 75 + .../config/u-boot-sec64k-header.lds | 76 + .../mv_feroceon/config/u-boot-sec64k-tiny.lds | 72 + board/mv_feroceon/config/u-boot-sec64k.lds | 79 + board/mv_feroceon/config/u-boot.lds | 75 + board/mv_feroceon/config/u-boot_16mb.lds | 74 + board/mv_feroceon/config_dd/Makefile | 77 + board/mv_feroceon/config_dd/config.mk | 5 + board/mv_feroceon/config_dd/config_def.mk | 5 + board/mv_feroceon/config_dd/config_nand.mk | 15 + board/mv_feroceon/config_dd/mvRules.mk | 79 + board/mv_feroceon/config_dd/u-boot-nand.lds | 64 + .../mv_feroceon/config_dd/u-boot-sec128k.lds | 79 + board/mv_feroceon/config_dd/u-boot.lds | 79 + board/mv_feroceon/config_dd/u-boot_def.lds | 79 + board/mv_feroceon/config_kw/Makefile | 77 + board/mv_feroceon/config_kw/config.mk | 13 + board/mv_feroceon/config_kw/config_16mb.mk | 4 + board/mv_feroceon/config_kw/config_def.mk | 5 + board/mv_feroceon/config_kw/config_nand.mk | 8 + board/mv_feroceon/config_kw/config_prpmc.mk | 5 + board/mv_feroceon/config_kw/mvRules.mk | 80 + board/mv_feroceon/config_kw/u-boot-nand.lds | 64 + .../config_kw/u-boot-sec128k-tiny.lds | 73 + .../mv_feroceon/config_kw/u-boot-sec128k.lds | 77 + .../mv_feroceon/config_kw/u-boot-sec256k.lds | 77 + .../config_kw/u-boot-sec4k-header-tiny.lds | 75 + .../config_kw/u-boot-sec4k-tiny.lds | 74 + board/mv_feroceon/config_kw/u-boot-sec4k.lds | 74 + .../config_kw/u-boot-sec64k-header-nand.lds | 75 + .../config_kw/u-boot-sec64k-header.lds | 76 + .../config_kw/u-boot-sec64k-tiny.lds | 72 + board/mv_feroceon/config_kw/u-boot-sec64k.lds | 77 + board/mv_feroceon/config_kw/u-boot.lds | 77 + board/mv_feroceon/config_kw/u-boot_16mb.lds | 74 + .../mv_dd/dd_family/boardEnv/mvBoardEnvLib.c | 1420 +++ .../mv_dd/dd_family/boardEnv/mvBoardEnvLib.h | 192 + .../mv_dd/dd_family/boardEnv/mvBoardEnvSpec.c | 180 + .../mv_dd/dd_family/boardEnv/mvBoardEnvSpec.h | 361 + board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.c | 281 + board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.h | 101 + .../dd_family/ctrlEnv/mvCtrlEnvAddrDec.c | 427 + .../dd_family/ctrlEnv/mvCtrlEnvAddrDec.h | 126 + .../mv_dd/dd_family/ctrlEnv/mvCtrlEnvAsm.h | 94 + .../mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.c | 1202 ++ .../mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.h | 159 + .../mv_dd/dd_family/ctrlEnv/mvCtrlEnvSpec.h | 462 + .../mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.c | 894 ++ .../mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.h | 99 + .../dd_family/ctrlEnv/sys/mvAhbToMbusConfig.h | 74 + .../dd_family/ctrlEnv/sys/mvAhbToMbusRegs.h | 156 + .../mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.c | 1110 ++ .../mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.h | 119 + .../dd_family/ctrlEnv/sys/mvCpuIfConfig.h | 123 + .../mv_dd/dd_family/ctrlEnv/sys/mvCpuIfRegs.h | 245 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.c | 379 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.h | 100 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysDram.c | 363 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysDram.h | 82 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysGbe.c | 656 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysGbe.h | 111 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysIdma.c | 742 ++ .../mv_dd/dd_family/ctrlEnv/sys/mvSysIdma.h | 143 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysPex.c | 1620 +++ .../mv_dd/dd_family/ctrlEnv/sys/mvSysPex.h | 286 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysSata.c | 431 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysSata.h | 128 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysTdm.c | 464 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysTdm.h | 92 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysUart.c | 212 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysUart.h | 75 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysUsb.c | 498 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysUsb.h | 125 + .../mv_dd/dd_family/ctrlEnv/sys/mvSysXor.c | 701 ++ .../mv_dd/dd_family/ctrlEnv/sys/mvSysXor.h | 141 + .../mv_dd/dd_family/device/mvDevice.c | 375 + .../mv_dd/dd_family/device/mvDevice.h | 102 + .../mv_dd/dd_family/device/mvDeviceRegs.h | 481 + board/mv_feroceon/mv_dd/mvSysHwConfig.h | 455 + board/mv_feroceon/mv_dd/mv_cmd.c | 1171 ++ board/mv_feroceon/mv_dd/mv_dram.c | 316 + board/mv_feroceon/mv_dd/mv_main.c | 1414 +++ board/mv_feroceon/mv_dd/mv_service.c | 103 + board/mv_feroceon/mv_dd/mv_service.h | 71 + board/mv_feroceon/mv_dd/nBootstrap.S | 20 + board/mv_feroceon/mv_dd/nBootstrap.h | 213 + board/mv_feroceon/mv_dd/nBootstrap_LP.S | 335 + board/mv_feroceon/mv_dd/platform.S | 153 + .../mv_hal/audio/dac/mvCLAudioCodec.c | 500 + .../mv_hal/audio/dac/mvCLAudioCodec.h | 139 + .../mv_hal/audio/dac/mvCLAudioCodecRegs.h | 83 + board/mv_feroceon/mv_hal/audio/mvAudio.c | 1057 ++ board/mv_feroceon/mv_hal/audio/mvAudio.h | 342 + board/mv_feroceon/mv_hal/audio/mvAudioRegs.h | 411 + board/mv_feroceon/mv_hal/cesa/AES/mvAes.h | 62 + board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.c | 317 + board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.h | 19 + board/mv_feroceon/mv_hal/cesa/AES/mvAesApi.c | 312 + .../mv_hal/cesa/AES/mvAesBoxes.dat | 123 + board/mv_feroceon/mv_hal/cesa/mvCesa.c | 2942 +++++ board/mv_feroceon/mv_hal/cesa/mvCesa.c.keep | 2942 +++++ board/mv_feroceon/mv_hal/cesa/mvCesa.h | 402 + board/mv_feroceon/mv_hal/cesa/mvCesaDebug.c | 477 + board/mv_feroceon/mv_hal/cesa/mvCesaRegs.h | 357 + board/mv_feroceon/mv_hal/cesa/mvCesaTest.c | 3096 +++++ board/mv_feroceon/mv_hal/cesa/mvLru.c | 158 + board/mv_feroceon/mv_hal/cesa/mvLru.h | 112 + board/mv_feroceon/mv_hal/cesa/mvMD5.c | 349 + board/mv_feroceon/mv_hal/cesa/mvMD5.h | 93 + board/mv_feroceon/mv_hal/cesa/mvSHA1.c | 239 + board/mv_feroceon/mv_hal/cesa/mvSHA1.h | 88 + board/mv_feroceon/mv_hal/cntmr/mvCntmr.c | 373 + board/mv_feroceon/mv_hal/cntmr/mvCntmr.h | 121 + board/mv_feroceon/mv_hal/cntmr/mvCntmrRegs.h | 119 + board/mv_feroceon/mv_hal/ddr1_2/mvDram.c | 1476 +++ board/mv_feroceon/mv_hal/ddr1_2/mvDram.h | 191 + board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.c | 1599 +++ board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.h | 179 + .../mv_hal/ddr1_2/mvDramIfBasicInit.S | 988 ++ .../mv_hal/ddr1_2/mvDramIfConfig.S | 668 + .../mv_hal/ddr1_2/mvDramIfConfig.h | 192 + .../mv_feroceon/mv_hal/ddr1_2/mvDramIfRegs.h | 306 + board/mv_feroceon/mv_hal/ddr2/mvDramIf.c | 1787 +++ board/mv_feroceon/mv_hal/ddr2/mvDramIf.h | 170 + .../mv_hal/ddr2/mvDramIfBasicInit.S | 907 ++ .../mv_feroceon/mv_hal/ddr2/mvDramIfConfig.S | 513 + .../mv_feroceon/mv_hal/ddr2/mvDramIfConfig.h | 155 + board/mv_feroceon/mv_hal/ddr2/mvDramIfRegs.h | 421 + .../mv_hal/ddr2/mvDramIfStaticInit.h | 179 + board/mv_feroceon/mv_hal/ddr2/spd/mvSpd.c | 1474 +++ board/mv_feroceon/mv_hal/ddr2/spd/mvSpd.h | 192 + board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.c | 818 ++ board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.h | 90 + .../mv_feroceon/mv_hal/eth-phy/mvEthPhyRegs.h | 166 + board/mv_feroceon/mv_hal/eth/gbe/mvEth.c | 2940 +++++ board/mv_feroceon/mv_hal/eth/gbe/mvEthDebug.c | 746 ++ board/mv_feroceon/mv_hal/eth/gbe/mvEthGbe.h | 743 ++ board/mv_feroceon/mv_hal/eth/gbe/mvEthRegs.h | 676 ++ board/mv_feroceon/mv_hal/eth/mvEth.h | 356 + board/mv_feroceon/mv_hal/eth/nfp/mvNfp.c | 742 ++ board/mv_feroceon/mv_hal/eth/nfp/mvNfp.h | 471 + board/mv_feroceon/mv_hal/eth/nfp/mvNfpNat.c | 450 + .../mv_hal/ethfp/fast_path/mvFastPath.c | 655 + .../mv_hal/ethfp/fast_path/mvFastPath.h | 415 + .../mv_hal/ethfp/fast_path/mvFpNat.c | 450 + board/mv_feroceon/mv_hal/ethfp/gbe/mvEth.c | 2944 +++++ .../mv_feroceon/mv_hal/ethfp/gbe/mvEthDebug.c | 895 ++ board/mv_feroceon/mv_hal/ethfp/gbe/mvEthGbe.h | 741 ++ .../mv_feroceon/mv_hal/ethfp/gbe/mvEthRegs.h | 695 ++ board/mv_feroceon/mv_hal/ethfp/mvEth.h | 364 + board/mv_feroceon/mv_hal/ethfp/mvEthDebug.h | 113 + board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.c | 572 + board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.h | 139 + board/mv_feroceon/mv_hal/ethswitch/mvSwitch.c | 442 + board/mv_feroceon/mv_hal/ethswitch/mvSwitch.h | 75 + .../mv_hal/ethswitch/mvSwitchRegs.h | 109 + board/mv_feroceon/mv_hal/gpp/mvGpp.c | 395 + board/mv_feroceon/mv_hal/gpp/mvGpp.h | 118 + board/mv_feroceon/mv_hal/gpp/mvGppRegs.h | 116 + .../mv_feroceon/mv_hal/norflash/mvAmdFlash.c | 279 + .../mv_feroceon/mv_hal/norflash/mvAmdFlash.h | 168 + board/mv_feroceon/mv_hal/norflash/mvFlash.c | 1409 +++ board/mv_feroceon/mv_hal/norflash/mvFlash.h | 96 + .../mv_feroceon/mv_hal/norflash/mvFlashCom.c | 650 + .../mv_feroceon/mv_hal/norflash/mvFlashCom.h | 164 + .../mv_hal/norflash/mvIntelFlash.c | 518 + .../mv_hal/norflash/mvIntelFlash.h | 165 + board/mv_feroceon/mv_hal/pci-if/mvPciIf.c | 669 + board/mv_feroceon/mv_hal/pci-if/mvPciIf.h | 134 + board/mv_feroceon/mv_hal/pci-if/mvPciIfRegs.h | 245 + .../mv_hal/pci-if/pci_util/mvPciUtils.c | 1006 ++ .../mv_hal/pci-if/pci_util/mvPciUtils.h | 323 + board/mv_feroceon/mv_hal/pci/mvPci.c | 1047 ++ board/mv_feroceon/mv_hal/pci/mvPci.h | 185 + board/mv_feroceon/mv_hal/pci/mvPciRegs.h | 411 + board/mv_feroceon/mv_hal/pex/mvPex.c | 1089 ++ board/mv_feroceon/mv_hal/pex/mvPex.h | 163 + board/mv_feroceon/mv_hal/pex/mvPexRegs.h | 743 ++ board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.c | 580 + board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.h | 82 + .../mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c | 321 + .../mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h | 96 + .../mv_hal/rtc/ext_rtc/mvDS1339Reg.h | 368 + .../mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133x.c | 354 + .../mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h | 100 + .../mv_hal/rtc/ext_rtc/mvDS133xReg.h | 369 + .../mv_feroceon/mv_hal/rtc/integ_rtc/mvRtc.c | 231 + .../mv_feroceon/mv_hal/rtc/integ_rtc/mvRtc.h | 93 + .../mv_hal/rtc/integ_rtc/mvRtcReg.h | 118 + .../mv_hal/sata/CoreDriver/mvLog.c | 194 + .../mv_hal/sata/CoreDriver/mvLog.h | 187 + .../mv_hal/sata/CoreDriver/mvOsS.h | 90 + .../mv_hal/sata/CoreDriver/mvRegs.h | 416 + .../mv_hal/sata/CoreDriver/mvSata.c | 10135 ++++++++++++++++ .../mv_hal/sata/CoreDriver/mvSata.h | 774 ++ .../mv_hal/sata/CoreDriver/mvSataSoc.c | 114 + .../mv_hal/sata/CoreDriver/mvSataSoc.h | 86 + .../mv_hal/sata/CoreDriver/mvStorageDev.c | 2186 ++++ .../mv_hal/sata/CoreDriver/mvStorageDev.h | 355 + board/mv_feroceon/mv_hal/sflash/mvSFlash.c | 1518 +++ board/mv_feroceon/mv_hal/sflash/mvSFlash.h | 166 + .../mv_feroceon/mv_hal/sflash/mvSFlashSpec.h | 237 + board/mv_feroceon/mv_hal/spi/mvSpi.c | 573 + board/mv_feroceon/mv_hal/spi/mvSpi.h | 94 + board/mv_feroceon/mv_hal/spi/mvSpiCmnd.c | 250 + board/mv_feroceon/mv_hal/spi/mvSpiCmnd.h | 82 + board/mv_feroceon/mv_hal/spi/mvSpiSpec.h | 98 + board/mv_feroceon/mv_hal/ts/mvTsu.c | 1742 +++ board/mv_feroceon/mv_hal/ts/mvTsu.h | 830 ++ board/mv_feroceon/mv_hal/ts/mvTsuRegs.h | 267 + board/mv_feroceon/mv_hal/twsi/mvTwsi.c | 1026 ++ board/mv_feroceon/mv_hal/twsi/mvTwsi.h | 121 + board/mv_feroceon/mv_hal/twsi/mvTwsiEeprom.S | 457 + board/mv_feroceon/mv_hal/twsi/mvTwsiSpec.h | 160 + board/mv_feroceon/mv_hal/uart/mvUart.c | 184 + board/mv_feroceon/mv_hal/uart/mvUart.h | 159 + board/mv_feroceon/mv_hal/uart/mvUartRegs.h | 72 + board/mv_feroceon/mv_hal/usb/api/mvUsbCh9.h | 124 + board/mv_feroceon/mv_hal/usb/api/mvUsbDebug.h | 109 + board/mv_feroceon/mv_hal/usb/api/mvUsbDefs.h | 139 + .../mv_feroceon/mv_hal/usb/api/mvUsbDevApi.h | 159 + board/mv_feroceon/mv_hal/usb/api/mvUsbTypes.h | 238 + .../mv_feroceon/mv_hal/usb/common/mvUsbCore.h | 720 ++ .../mv_feroceon/mv_hal/usb/common/mvUsbDesc.h | 162 + .../mv_hal/usb/device/mvUsbDevCh9.c | 301 + .../mv_hal/usb/device/mvUsbDevMain.c | 768 ++ .../mv_hal/usb/device/mvUsbDevPrv.h | 267 + .../mv_hal/usb/device/mvUsbDevRecv.c | 99 + .../mv_hal/usb/device/mvUsbDevSend.c | 373 + .../mv_hal/usb/device/mvUsbDevUtl.c | 634 + .../mv_hal/usb/device/mvUsbHsDevCncl.c | 222 + .../mv_hal/usb/device/mvUsbHsDevMain.c | 1864 +++ .../mv_hal/usb/device/mvUsbHsDevUtl.c | 271 + board/mv_feroceon/mv_hal/usb/examples/disk.c | 2296 ++++ board/mv_feroceon/mv_hal/usb/examples/disk.h | 86 + board/mv_feroceon/mv_hal/usb/examples/mouse.c | 1709 +++ board/mv_feroceon/mv_hal/usb/examples/mouse.h | 29 + board/mv_feroceon/mv_hal/usb/mvUsb.c | 964 ++ board/mv_feroceon/mv_hal/usb/mvUsb.h | 98 + board/mv_feroceon/mv_hal/usb/mvUsbRegs.h | 191 + board/mv_feroceon/mv_hal/xor/mvXor.c | 641 + board/mv_feroceon/mv_hal/xor/mvXor.h | 230 + board/mv_feroceon/mv_hal/xor/mvXorRegs.h | 225 + board/mv_feroceon/mv_kw/bootstrap_def.h | 121 + .../mv_kw/kw_family/boardEnv/mvBoardEnvLib.c | 2470 ++++ .../mv_kw/kw_family/boardEnv/mvBoardEnvLib.h | 376 + .../mv_kw/kw_family/boardEnv/mvBoardEnvSpec.c | 576 + .../mv_kw/kw_family/boardEnv/mvBoardEnvSpec.h | 219 + board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.c | 319 + board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.h | 103 + .../kw_family/ctrlEnv/mvCtrlEnvAddrDec.c | 296 + .../kw_family/ctrlEnv/mvCtrlEnvAddrDec.h | 203 + .../mv_kw/kw_family/ctrlEnv/mvCtrlEnvAsm.h | 98 + .../mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.c | 1807 +++ .../mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.h | 185 + .../mv_kw/kw_family/ctrlEnv/mvCtrlEnvRegs.h | 409 + .../mv_kw/kw_family/ctrlEnv/mvCtrlEnvSpec.h | 249 + .../mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.c | 1050 ++ .../mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.h | 130 + .../kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h | 143 + .../mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.c | 1064 ++ .../mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.h | 120 + .../mv_kw/kw_family/ctrlEnv/sys/mvCpuIfInit.S | 163 + .../mv_kw/kw_family/ctrlEnv/sys/mvCpuIfRegs.h | 298 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.c | 324 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.h | 123 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysCesa.c | 378 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysCesa.h | 100 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysDram.c | 348 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysDram.h | 80 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysGbe.c | 658 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysGbe.h | 113 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysPex.c | 1697 +++ .../mv_kw/kw_family/ctrlEnv/sys/mvSysPex.h | 348 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysSata.c | 430 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysSata.h | 128 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysSdmmc.c | 427 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysSdmmc.h | 125 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysTdm.c | 464 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysTdm.h | 92 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysTs.c | 591 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysTs.h | 110 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysUsb.c | 497 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysUsb.h | 125 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysXor.c | 662 + .../mv_kw/kw_family/ctrlEnv/sys/mvSysXor.h | 140 + .../mv_kw/kw_family/device/mvDevice.c | 75 + .../mv_kw/kw_family/device/mvDevice.h | 74 + .../mv_kw/kw_family/device/mvDeviceRegs.h | 101 + board/mv_feroceon/mv_kw/mvSysHwConfig.h | 348 + board/mv_feroceon/mv_kw/mv_cmd.c | 1524 +++ board/mv_feroceon/mv_kw/mv_dram.c | 322 + board/mv_feroceon/mv_kw/mv_main.c | 1364 +++ board/mv_feroceon/mv_kw/nBootstrap.S | 20 + board/mv_feroceon/mv_kw/nBootstrap.h | 213 + board/mv_feroceon/mv_kw/platform.S | 106 + board/mv_feroceon/mv_orion/mv_cmd.c | 1162 ++ board/mv_feroceon/mv_orion/mv_dram.c | 395 + board/mv_feroceon/mv_orion/mv_main.c | 1781 +++ board/mv_feroceon/mv_orion/mv_service.c | 146 + board/mv_feroceon/mv_orion/mv_service.h | 71 + board/mv_feroceon/mv_orion/nBootstrap.S | 411 + board/mv_feroceon/mv_orion/nBootstrap.h | 382 + board/mv_feroceon/mv_orion/nBootstrap_LP.S | 335 + .../orion_family/boardEnv/mv88F1281BoardEnv.c | 132 + .../orion_family/boardEnv/mv88F1281BoardEnv.h | 85 + .../orion_family/boardEnv/mv88F5082BoardEnv.c | 272 + .../orion_family/boardEnv/mv88F5082BoardEnv.h | 112 + .../boardEnv/mv88F5180NBoardEnv.c | 161 + .../boardEnv/mv88F5180NBoardEnv.h | 87 + .../orion_family/boardEnv/mv88F5181BoardEnv.c | 858 ++ .../orion_family/boardEnv/mv88F5181BoardEnv.h | 182 + .../boardEnv/mv88F5181LBoardEnv.c | 354 + .../boardEnv/mv88F5181LBoardEnv.h | 115 + .../orion_family/boardEnv/mv88F5182BoardEnv.c | 355 + .../orion_family/boardEnv/mv88F5182BoardEnv.h | 117 + .../orion_family/boardEnv/mv88F6082BoardEnv.c | 441 + .../orion_family/boardEnv/mv88F6082BoardEnv.h | 119 + .../orion_family/boardEnv/mv88F6183BoardEnv.c | 275 + .../orion_family/boardEnv/mv88F6183BoardEnv.h | 104 + .../boardEnv/mv88F6183LBoardEnv.c | 143 + .../boardEnv/mv88F6183LBoardEnv.h | 88 + .../orion_family/boardEnv/mv88W8660BoardEnv.c | 297 + .../orion_family/boardEnv/mv88W8660BoardEnv.h | 106 + .../orion_family/boardEnv/mvBoardEnvLib.c | 2053 ++++ .../orion_family/boardEnv/mvBoardEnvLib.h | 308 + .../orion_family/boardEnv/mvBoardEnvSpec.c | 502 + .../orion_family/boardEnv/mvBoardEnvSpec.h | 167 + .../boardEnv/mvCustomerBoardEnv.c | 132 + .../boardEnv/mvCustomerBoardEnv.h | 87 + .../mv_orion/orion_family/cpu/mvCpu.h | 88 + .../mv_orion/orion_family/cpu/mvCpuArm.c | 166 + .../mv_orion/orion_family/cpu/mvCpuArm.h | 88 + .../orion_family/ctrlEnv/mv88F1281EnvSpec.h | 326 + .../orion_family/ctrlEnv/mv88F1X81EnvSpec.h | 291 + .../orion_family/ctrlEnv/mv88F5082EnvSpec.h | 372 + .../orion_family/ctrlEnv/mv88F5180NEnvSpec.h | 349 + .../orion_family/ctrlEnv/mv88F5181LEnvSpec.h | 380 + .../orion_family/ctrlEnv/mv88F5182EnvSpec.h | 386 + .../orion_family/ctrlEnv/mv88F5X81EnvSpec.h | 377 + .../orion_family/ctrlEnv/mv88F6082EnvSpec.h | 394 + .../orion_family/ctrlEnv/mv88F6183EnvSpec.h | 368 + .../orion_family/ctrlEnv/mv88F6183LEnvSpec.h | 330 + .../orion_family/ctrlEnv/mv88w8660EnvSpec.h | 367 + .../orion_family/ctrlEnv/mvCtrlEnvAddrDec.c | 296 + .../orion_family/ctrlEnv/mvCtrlEnvAddrDec.h | 201 + .../orion_family/ctrlEnv/mvCtrlEnvAsm.h | 217 + .../orion_family/ctrlEnv/mvCtrlEnvLib.c | 1266 ++ .../orion_family/ctrlEnv/mvCtrlEnvLib.h | 182 + .../ctrlEnv/mvCtrlEnvPadCalibration.c | 463 + .../ctrlEnv/mvCtrlEnvPadCalibration.h | 162 + .../orion_family/ctrlEnv/mvCtrlEnvSpec.h | 243 + .../orion_family/ctrlEnv/sys/mvAhbToMbus.c | 1051 ++ .../orion_family/ctrlEnv/sys/mvAhbToMbus.h | 130 + .../ctrlEnv/sys/mvAhbToMbusConfig.h | 74 + .../ctrlEnv/sys/mvAhbToMbusRegs.h | 188 + .../orion_family/ctrlEnv/sys/mvCpuIf.c | 1040 ++ .../orion_family/ctrlEnv/sys/mvCpuIf.h | 116 + .../orion_family/ctrlEnv/sys/mvCpuIfConfig.h | 138 + .../orion_family/ctrlEnv/sys/mvCpuIfInit.S | 191 + .../orion_family/ctrlEnv/sys/mvCpuIfRegs.h | 246 + .../orion_family/ctrlEnv/sys/mvSysAudio.c | 321 + .../orion_family/ctrlEnv/sys/mvSysAudio.h | 123 + .../orion_family/ctrlEnv/sys/mvSysCesa.c | 378 + .../orion_family/ctrlEnv/sys/mvSysCesa.h | 100 + .../orion_family/ctrlEnv/sys/mvSysGbe.c | 660 + .../orion_family/ctrlEnv/sys/mvSysGbe.h | 112 + .../orion_family/ctrlEnv/sys/mvSysIdma.c | 709 ++ .../orion_family/ctrlEnv/sys/mvSysIdma.h | 142 + .../orion_family/ctrlEnv/sys/mvSysPci.c | 1490 +++ .../orion_family/ctrlEnv/sys/mvSysPci.h | 277 + .../orion_family/ctrlEnv/sys/mvSysPex.c | 1696 +++ .../orion_family/ctrlEnv/sys/mvSysPex.h | 348 + .../orion_family/ctrlEnv/sys/mvSysSata.c | 427 + .../orion_family/ctrlEnv/sys/mvSysSata.h | 128 + .../orion_family/ctrlEnv/sys/mvSysTdm.c | 466 + .../orion_family/ctrlEnv/sys/mvSysTdm.h | 92 + .../orion_family/ctrlEnv/sys/mvSysUsb.c | 497 + .../orion_family/ctrlEnv/sys/mvSysUsb.h | 125 + .../orion_family/ctrlEnv/sys/mvSysXor.c | 663 + .../orion_family/ctrlEnv/sys/mvSysXor.h | 141 + .../mv_orion/orion_family/device/mvDevice.c | 318 + .../mv_orion/orion_family/device/mvDevice.h | 101 + .../orion_family/device/mvDeviceRegs.h | 223 + .../mv_orion/orion_sys/mv88F1281SysHwConfig.h | 182 + .../mv_orion/orion_sys/mv88F1X81SysHwConfig.h | 162 + .../mv_orion/orion_sys/mv88F5082SysHwConfig.h | 258 + .../orion_sys/mv88F5180NSysHwConfig.h | 221 + .../orion_sys/mv88F5181LSysHwConfig.h | 272 + .../mv_orion/orion_sys/mv88F5182SysHwConfig.h | 284 + .../mv_orion/orion_sys/mv88F5X81SysHwConfig.h | 330 + .../mv_orion/orion_sys/mv88F6082SysHwConfig.h | 291 + .../orion_sys/mv88F6183LSysHwConfig.h | 202 + .../mv_orion/orion_sys/mv88F6183SysHwConfig.h | 254 + .../mv_orion/orion_sys/mv88w8660SysHwConfig.h | 254 + .../mv_orion/orion_sys/mvSysHwConfig.h | 190 + board/mv_feroceon/mv_orion/platform.S | 1682 +++ board/mv_feroceon/uboot_oss/mvOs.c | 248 + board/mv_feroceon/uboot_oss/mvOs.h | 362 + board/mv_feroceon/uboot_oss/mvOsAsm.h | 134 + board/mv_feroceon/uboot_oss/mvOsSata.c | 31 + board/mv_feroceon/uboot_oss/mvOsSata.h | 194 + board/ns9750dev/led.c | 2 +- board/xilinx/common/xdma_channel_sg.c | 2 +- board/xilinx/common/xipif_v1_23_b.c | 2 +- board/xilinx/common/xipif_v1_23_b.h | 2 +- board/xilinx/xilinx_iic/xiic_l.c | 2 +- board/xilinx/xilinx_iic/xiic_l.h | 2 +- common/Makefile | 3 +- common/bedbug.c | 2 +- common/cmd_ace.c | 2 +- common/cmd_bootm.c | 47 +- common/cmd_doc.c | 2 +- common/cmd_eeprom.c | 4 + common/cmd_elf.c | 4 + common/cmd_ext2.c | 1 + common/cmd_flash.c | 8 +- common/cmd_i2c.c | 14 + common/cmd_ide.c | 4 + common/cmd_jffs2.c | 53 +- common/cmd_mem.c | 21 +- common/cmd_nand.c | 2492 ++-- common/cmd_net.c | 3 +- common/cmd_pci.c | 5 +- common/cmd_scsi.c | 16 +- common/console.c | 9 +- common/docecc.c | 2 +- common/env_common.c | 6 + common/env_flash.c | 14 +- common/env_nand.c | 222 +- common/exports.c | 8 + common/main.c | 83 +- common/qnap_rcvr.c | 85 + config.mk | 4 +- cpu/arm926ejs/Makefile | 1 + cpu/arm926ejs/config.mk | 25 +- cpu/arm926ejs/cpu.c | 57 +- cpu/arm926ejs/interrupts.c | 32 +- cpu/arm926ejs/start.S | 149 +- create_all_images.sh | 132 + disk/part_dos.c | 15 +- disk/part_dos.h | 4 + dramregs_200db_A.txt | 23 + dramregs_200rd_A.txt | 23 + dramregs_400_A.txt | 26 + drivers/Makefile | 4 +- drivers/ahci.c | 760 ++ drivers/cfi_flash.c | 509 +- drivers/eepro100.c | 7 +- drivers/nand/Makefile | 45 + drivers/nand/diskonchip.c | 1787 +++ drivers/nand/nand.c | 84 + drivers/nand/nand_base.c | 2705 +++++ drivers/nand/nand_bbt.c | 1052 ++ drivers/nand/nand_ecc.c | 244 + drivers/nand/nand_ecc_rs.c | 518 + drivers/nand/nand_ids.c | 126 + drivers/nand/nand_util.c | 862 ++ drivers/ns7520_eth.c | 2 +- drivers/ns9750_eth.c | 2 +- drivers/ns9750_serial.c | 2 +- drivers/pci.c | 10 +- drivers/pci_auto.c | 8 +- drivers/pci_indirect.c | 4 +- drivers/rtl8029.c | 356 + drivers/rtl8029.h | 119 + drivers/s3c4510b_eth.h | 2 +- drivers/s3c4510b_uart.c | 2 +- drivers/sk98lin/Makefile | 138 +- drivers/sk98lin/h/lm80.h | 44 +- drivers/sk98lin/h/skaddr.h | 140 +- drivers/sk98lin/h/skcsum.h | 56 +- drivers/sk98lin/h/skdebug.h | 72 +- drivers/sk98lin/h/skdrv1st.h | 144 +- drivers/sk98lin/h/skdrv2nd.h | 1244 +- drivers/sk98lin/h/skerror.h | 43 +- drivers/sk98lin/h/skgedrv.h | 53 +- drivers/sk98lin/h/skgehw.h | 2068 +++- drivers/sk98lin/h/skgehwt.h | 44 +- drivers/sk98lin/h/skgei2c.h | 13 +- drivers/sk98lin/h/skgeinit.h | 849 +- drivers/sk98lin/h/skgepnm2.h | 167 +- drivers/sk98lin/h/skgepnmi.h | 471 +- drivers/sk98lin/h/skgesirq.h | 149 +- drivers/sk98lin/h/skgetwsi.h | 243 + drivers/sk98lin/h/ski2c.h | 13 +- drivers/sk98lin/h/skqueue.h | 90 +- drivers/sk98lin/h/skrlmt.h | 185 +- drivers/sk98lin/h/sktimer.h | 74 +- drivers/sk98lin/h/sktwsi.h | 179 + drivers/sk98lin/h/sktypes.h | 84 +- drivers/sk98lin/h/skversion.h | 46 +- drivers/sk98lin/h/skvpd.h | 148 +- drivers/sk98lin/h/sky2le.h | 893 ++ drivers/sk98lin/h/xmac_ii.h | 942 +- drivers/sk98lin/skaddr.c | 628 +- drivers/sk98lin/skcsum.c | 100 +- drivers/sk98lin/skdim.c | 400 + drivers/sk98lin/skethtool.c | 1364 +++ drivers/sk98lin/skge.c | 6450 ++++++---- drivers/sk98lin/skgehwt.c | 159 +- drivers/sk98lin/skgeinit.c | 2550 ++-- drivers/sk98lin/skgemib.c | 291 +- drivers/sk98lin/skgepnmi.c | 4129 +++---- drivers/sk98lin/skgesirq.c | 2079 ++-- drivers/sk98lin/ski2c.c | 15 +- drivers/sk98lin/sklm80.c | 121 +- drivers/sk98lin/skproc.c | 802 +- drivers/sk98lin/skqueue.c | 283 +- drivers/sk98lin/skrlmt.c | 626 +- drivers/sk98lin/sktimer.c | 231 +- drivers/sk98lin/sktwsi.c | 1365 +++ drivers/sk98lin/skvpd.c | 289 +- drivers/sk98lin/skxmac2.c | 3712 ++++-- drivers/sk98lin/sky2.c | 2774 +++++ drivers/sk98lin/sky2le.c | 511 + drivers/sk98lin/uboot_drv.c | 103 +- drivers/sk98lin/uboot_skb.c | 41 +- examples/Makefile | 4 +- examples/stubs.c | 2 +- fs/ext2/dev.c | 3 +- fs/ext2/ext2fs.c | 6 +- fs/fat/fat.c | 2 +- fs/jffs2/compr_lzari.c | 2 +- fs/jffs2/compr_lzo.c | 2 +- fs/jffs2/compr_rtime.c | 2 +- fs/jffs2/compr_rubin.c | 2 +- fs/jffs2/compr_zlib.c | 2 +- fs/jffs2/jffs2_1pass.c | 37 +- fs/jffs2/jffs2_nand_1pass.c | 1036 ++ fs/jffs2/jffs2_nand_private.h | 133 + fs/jffs2/jffs2_private.h | 12 + fs/jffs2/mini_inflate.c | 2 +- include/_exports.h | 7 + include/ahci.h | 190 + include/asm-arm/arch-arm926ejs/vfp.h | 83 + include/asm-arm/arch-arm926ejs/vfpinstr.h | 82 + include/asm-arm/arch-pxa/mmc.h | 2 +- include/asm-arm/bitops.h | 9 + include/asm-arm/global_data.h | 12 +- include/asm-arm/io.h | 1 - include/asm-arm/setup.h | 21 + include/asm-mips/byteorder.h | 2 +- include/asm-mips/posix_types.h | 2 +- include/asm-mips/string.h | 2 +- include/asm-mips/types.h | 2 +- include/bedbug/bedbug.h | 2 +- include/bedbug/ppc.h | 2 +- include/bedbug/regs.h | 2 +- include/bedbug/tables.h | 2 +- include/cmd_confdefs.h | 2 +- include/common.h | 2 + include/configs/DB64360.h | 11 +- include/configs/DU405.h | 2 +- include/configs/KAREF.h | 2 +- include/configs/METROBOX.h | 11 +- include/configs/PCI405.h | 2 +- include/configs/WUH405.h | 2 +- include/configs/barco.h | 17 +- include/configs/mv_dd.h | 548 + include/configs/mv_feroceon.h | 806 ++ include/configs/mv_kw.h | 715 ++ include/exports.h | 6 + include/flash.h | 22 + include/i2c.h | 4 + include/ide.h | 8 + include/jffs2/compr_rubin.h | 2 +- include/jffs2/jffs2.h | 2 +- include/jffs2/load_kernel.h | 2 +- include/jffs2/mini_inflate.h | 2 +- include/linux/mtd/compat.h | 46 + include/linux/mtd/doc2000.h | 2 +- include/linux/mtd/mtd-abi.h | 99 + include/linux/mtd/mtd.h | 214 + include/linux/mtd/nand.h | 510 +- include/linux/mtd/nand_ecc.h | 30 + include/linux/mtd/nand_ecc_rs.h | 79 + include/linux/mtd/nand_ids.h | 7 +- include/linux/mtd/nand_legacy.h | 203 + include/linux/mtd/nftl.h | 2 +- include/linux_logo.h | 2 +- include/lxt971a.h | 2 +- include/malloc.h | 5 +- include/mmc.h | 2 +- include/nand.h | 124 + include/net.h | 2 +- include/ns7520_eth.h | 2 +- include/ns9750_bbus.h | 2 +- include/ns9750_eth.h | 2 +- include/ns9750_mem.h | 2 +- include/ns9750_ser.h | 2 +- include/ns9750_sys.h | 2 +- include/part.h | 1 + include/qnap.h | 11 + include/systemace.h | 2 +- lib_arm/armlinux.c | 126 +- lib_arm/board.c | 117 +- net/Makefile | 2 +- net/bootp.c | 32 +- net/eth.c | 23 +- net/net.c | 22 +- net/rcvr.c | 469 + net/rcvr.h | 125 + rules.mk | 35 + tools/Makefile | 19 +- tools/Makefile_doimage | 41 + tools/bootstrap_def.h | 122 + tools/bootstrap_os.h | 473 + tools/doimage | Bin 0 -> 19516 bytes tools/doimage.c | 1263 ++ u-boot.bin.410 | Bin 0 -> 466724 bytes 675 files changed, 235084 insertions(+), 15041 deletions(-) delete mode 100644 board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/glibc.so/readme.txt delete mode 100644 board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/libc.so/readme.txt delete mode 100644 board/MAI/bios_emulator/scitech/lib/release/linux/gcc/glibc.so/readme.txt delete mode 100644 board/MAI/bios_emulator/scitech/lib/release/linux/gcc/libc.so/readme.txt delete mode 100644 board/MAI/bios_emulator/scitech/src/pm/os2/dossctl.obj create mode 100644 board/mv_feroceon/USP/ethSwitch/mv_switch.c create mode 100644 board/mv_feroceon/USP/ethSwitch/mv_switch.h create mode 100644 board/mv_feroceon/USP/ethSwitch/mv_switchRegs.h create mode 100644 board/mv_feroceon/USP/jump.S create mode 100644 board/mv_feroceon/USP/mv_egiga.c create mode 100644 board/mv_feroceon/USP/mv_ext2_boot.c create mode 100644 board/mv_feroceon/USP/mv_flash.c create mode 100644 board/mv_feroceon/USP/mv_fs.c create mode 100644 board/mv_feroceon/USP/mv_fs.h create mode 100644 board/mv_feroceon/USP/mv_i2c.c create mode 100644 board/mv_feroceon/USP/mv_ide.c create mode 100644 board/mv_feroceon/USP/mv_loadnet.c create mode 100644 board/mv_feroceon/USP/mv_mon_init.c create mode 100644 board/mv_feroceon/USP/mv_mon_init.h create mode 100644 board/mv_feroceon/USP/mv_nand.c create mode 100644 board/mv_feroceon/USP/mv_pageTable.c create mode 100644 board/mv_feroceon/USP/mv_pci.c create mode 100644 board/mv_feroceon/USP/mv_protectionUnit.c create mode 100644 board/mv_feroceon/USP/mv_rtc.c create mode 100644 board/mv_feroceon/USP/mv_serial.c create mode 100644 board/mv_feroceon/USP/mv_usb_dev.c create mode 100644 board/mv_feroceon/USP/mv_usb_host.c create mode 100644 board/mv_feroceon/USP/nBootloader.c create mode 100644 board/mv_feroceon/USP/sdio/mmc.c create mode 100644 board/mv_feroceon/USP/sdio/mustang_sdiodef.h create mode 100644 board/mv_feroceon/common/mv802_3.h create mode 100644 board/mv_feroceon/common/mvCommon.c create mode 100644 board/mv_feroceon/common/mvCommon.h create mode 100644 board/mv_feroceon/common/mvDebug.c create mode 100644 board/mv_feroceon/common/mvDebug.h create mode 100644 board/mv_feroceon/common/mvDeviceId.h create mode 100644 board/mv_feroceon/common/mvStack.c create mode 100644 board/mv_feroceon/common/mvStack.h create mode 100644 board/mv_feroceon/common/mvTypes.h create mode 100644 board/mv_feroceon/common/mvTypes.h.keep create mode 100644 board/mv_feroceon/config/Makefile create mode 100644 board/mv_feroceon/config/config.mk create mode 100644 board/mv_feroceon/config/config_16mb.mk create mode 100644 board/mv_feroceon/config/config_def.mk create mode 100644 board/mv_feroceon/config/config_nand.mk create mode 100644 board/mv_feroceon/config/config_prpmc.mk create mode 100644 board/mv_feroceon/config/mvRules.mk create mode 100644 board/mv_feroceon/config/u-boot-nand.lds create mode 100644 board/mv_feroceon/config/u-boot-sec128k-tiny.lds create mode 100644 board/mv_feroceon/config/u-boot-sec128k.lds create mode 100644 board/mv_feroceon/config/u-boot-sec256k.lds create mode 100644 board/mv_feroceon/config/u-boot-sec4k-header-tiny.lds create mode 100644 board/mv_feroceon/config/u-boot-sec4k-tiny.lds create mode 100644 board/mv_feroceon/config/u-boot-sec4k.lds create mode 100644 board/mv_feroceon/config/u-boot-sec64k-header-nand.lds create mode 100644 board/mv_feroceon/config/u-boot-sec64k-header.lds create mode 100644 board/mv_feroceon/config/u-boot-sec64k-tiny.lds create mode 100644 board/mv_feroceon/config/u-boot-sec64k.lds create mode 100644 board/mv_feroceon/config/u-boot.lds create mode 100644 board/mv_feroceon/config/u-boot_16mb.lds create mode 100644 board/mv_feroceon/config_dd/Makefile create mode 100644 board/mv_feroceon/config_dd/config.mk create mode 100644 board/mv_feroceon/config_dd/config_def.mk create mode 100644 board/mv_feroceon/config_dd/config_nand.mk create mode 100644 board/mv_feroceon/config_dd/mvRules.mk create mode 100644 board/mv_feroceon/config_dd/u-boot-nand.lds create mode 100644 board/mv_feroceon/config_dd/u-boot-sec128k.lds create mode 100644 board/mv_feroceon/config_dd/u-boot.lds create mode 100644 board/mv_feroceon/config_dd/u-boot_def.lds create mode 100644 board/mv_feroceon/config_kw/Makefile create mode 100644 board/mv_feroceon/config_kw/config.mk create mode 100644 board/mv_feroceon/config_kw/config_16mb.mk create mode 100644 board/mv_feroceon/config_kw/config_def.mk create mode 100644 board/mv_feroceon/config_kw/config_nand.mk create mode 100644 board/mv_feroceon/config_kw/config_prpmc.mk create mode 100644 board/mv_feroceon/config_kw/mvRules.mk create mode 100644 board/mv_feroceon/config_kw/u-boot-nand.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec128k-tiny.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec128k.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec256k.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec4k-header-tiny.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec4k-tiny.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec4k.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec64k-header-nand.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec64k-header.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec64k-tiny.lds create mode 100644 board/mv_feroceon/config_kw/u-boot-sec64k.lds create mode 100644 board/mv_feroceon/config_kw/u-boot.lds create mode 100644 board/mv_feroceon/config_kw/u-boot_16mb.lds create mode 100644 board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAsm.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvSpec.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusConfig.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusRegs.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfConfig.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfRegs.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysGbe.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysGbe.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysIdma.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysIdma.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysTdm.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysTdm.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUart.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUart.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUsb.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUsb.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysXor.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysXor.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/device/mvDevice.c create mode 100644 board/mv_feroceon/mv_dd/dd_family/device/mvDevice.h create mode 100644 board/mv_feroceon/mv_dd/dd_family/device/mvDeviceRegs.h create mode 100644 board/mv_feroceon/mv_dd/mvSysHwConfig.h create mode 100644 board/mv_feroceon/mv_dd/mv_cmd.c create mode 100644 board/mv_feroceon/mv_dd/mv_dram.c create mode 100644 board/mv_feroceon/mv_dd/mv_main.c create mode 100644 board/mv_feroceon/mv_dd/mv_service.c create mode 100644 board/mv_feroceon/mv_dd/mv_service.h create mode 100644 board/mv_feroceon/mv_dd/nBootstrap.S create mode 100644 board/mv_feroceon/mv_dd/nBootstrap.h create mode 100644 board/mv_feroceon/mv_dd/nBootstrap_LP.S create mode 100644 board/mv_feroceon/mv_dd/platform.S create mode 100644 board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.c create mode 100644 board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.h create mode 100644 board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodecRegs.h create mode 100644 board/mv_feroceon/mv_hal/audio/mvAudio.c create mode 100644 board/mv_feroceon/mv_hal/audio/mvAudio.h create mode 100644 board/mv_feroceon/mv_hal/audio/mvAudioRegs.h create mode 100644 board/mv_feroceon/mv_hal/cesa/AES/mvAes.h create mode 100644 board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.c create mode 100644 board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.h create mode 100644 board/mv_feroceon/mv_hal/cesa/AES/mvAesApi.c create mode 100644 board/mv_feroceon/mv_hal/cesa/AES/mvAesBoxes.dat create mode 100644 board/mv_feroceon/mv_hal/cesa/mvCesa.c create mode 100644 board/mv_feroceon/mv_hal/cesa/mvCesa.c.keep create mode 100644 board/mv_feroceon/mv_hal/cesa/mvCesa.h create mode 100644 board/mv_feroceon/mv_hal/cesa/mvCesaDebug.c create mode 100644 board/mv_feroceon/mv_hal/cesa/mvCesaRegs.h create mode 100644 board/mv_feroceon/mv_hal/cesa/mvCesaTest.c create mode 100644 board/mv_feroceon/mv_hal/cesa/mvLru.c create mode 100644 board/mv_feroceon/mv_hal/cesa/mvLru.h create mode 100644 board/mv_feroceon/mv_hal/cesa/mvMD5.c create mode 100644 board/mv_feroceon/mv_hal/cesa/mvMD5.h create mode 100644 board/mv_feroceon/mv_hal/cesa/mvSHA1.c create mode 100644 board/mv_feroceon/mv_hal/cesa/mvSHA1.h create mode 100644 board/mv_feroceon/mv_hal/cntmr/mvCntmr.c create mode 100644 board/mv_feroceon/mv_hal/cntmr/mvCntmr.h create mode 100644 board/mv_feroceon/mv_hal/cntmr/mvCntmrRegs.h create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDram.c create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDram.h create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.c create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.h create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDramIfBasicInit.S create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.S create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.h create mode 100644 board/mv_feroceon/mv_hal/ddr1_2/mvDramIfRegs.h create mode 100644 board/mv_feroceon/mv_hal/ddr2/mvDramIf.c create mode 100644 board/mv_feroceon/mv_hal/ddr2/mvDramIf.h create mode 100644 board/mv_feroceon/mv_hal/ddr2/mvDramIfBasicInit.S create mode 100644 board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.S create mode 100644 board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.h create mode 100644 board/mv_feroceon/mv_hal/ddr2/mvDramIfRegs.h create mode 100644 board/mv_feroceon/mv_hal/ddr2/mvDramIfStaticInit.h create mode 100644 board/mv_feroceon/mv_hal/ddr2/spd/mvSpd.c create mode 100644 board/mv_feroceon/mv_hal/ddr2/spd/mvSpd.h create mode 100644 board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.c create mode 100644 board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.h create mode 100644 board/mv_feroceon/mv_hal/eth-phy/mvEthPhyRegs.h create mode 100644 board/mv_feroceon/mv_hal/eth/gbe/mvEth.c create mode 100644 board/mv_feroceon/mv_hal/eth/gbe/mvEthDebug.c create mode 100644 board/mv_feroceon/mv_hal/eth/gbe/mvEthGbe.h create mode 100644 board/mv_feroceon/mv_hal/eth/gbe/mvEthRegs.h create mode 100644 board/mv_feroceon/mv_hal/eth/mvEth.h create mode 100644 board/mv_feroceon/mv_hal/eth/nfp/mvNfp.c create mode 100644 board/mv_feroceon/mv_hal/eth/nfp/mvNfp.h create mode 100644 board/mv_feroceon/mv_hal/eth/nfp/mvNfpNat.c create mode 100644 board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.c create mode 100644 board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.h create mode 100644 board/mv_feroceon/mv_hal/ethfp/fast_path/mvFpNat.c create mode 100644 board/mv_feroceon/mv_hal/ethfp/gbe/mvEth.c create mode 100644 board/mv_feroceon/mv_hal/ethfp/gbe/mvEthDebug.c create mode 100644 board/mv_feroceon/mv_hal/ethfp/gbe/mvEthGbe.h create mode 100644 board/mv_feroceon/mv_hal/ethfp/gbe/mvEthRegs.h create mode 100644 board/mv_feroceon/mv_hal/ethfp/mvEth.h create mode 100644 board/mv_feroceon/mv_hal/ethfp/mvEthDebug.h create mode 100644 board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.c create mode 100644 board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.h create mode 100644 board/mv_feroceon/mv_hal/ethswitch/mvSwitch.c create mode 100644 board/mv_feroceon/mv_hal/ethswitch/mvSwitch.h create mode 100644 board/mv_feroceon/mv_hal/ethswitch/mvSwitchRegs.h create mode 100644 board/mv_feroceon/mv_hal/gpp/mvGpp.c create mode 100644 board/mv_feroceon/mv_hal/gpp/mvGpp.h create mode 100644 board/mv_feroceon/mv_hal/gpp/mvGppRegs.h create mode 100644 board/mv_feroceon/mv_hal/norflash/mvAmdFlash.c create mode 100644 board/mv_feroceon/mv_hal/norflash/mvAmdFlash.h create mode 100644 board/mv_feroceon/mv_hal/norflash/mvFlash.c create mode 100644 board/mv_feroceon/mv_hal/norflash/mvFlash.h create mode 100644 board/mv_feroceon/mv_hal/norflash/mvFlashCom.c create mode 100644 board/mv_feroceon/mv_hal/norflash/mvFlashCom.h create mode 100644 board/mv_feroceon/mv_hal/norflash/mvIntelFlash.c create mode 100644 board/mv_feroceon/mv_hal/norflash/mvIntelFlash.h create mode 100644 board/mv_feroceon/mv_hal/pci-if/mvPciIf.c create mode 100644 board/mv_feroceon/mv_hal/pci-if/mvPciIf.h create mode 100644 board/mv_feroceon/mv_hal/pci-if/mvPciIfRegs.h create mode 100644 board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.c create mode 100644 board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.h create mode 100644 board/mv_feroceon/mv_hal/pci/mvPci.c create mode 100644 board/mv_feroceon/mv_hal/pci/mvPci.h create mode 100644 board/mv_feroceon/mv_hal/pci/mvPciRegs.h create mode 100644 board/mv_feroceon/mv_hal/pex/mvPex.c create mode 100644 board/mv_feroceon/mv_hal/pex/mvPex.h create mode 100644 board/mv_feroceon/mv_hal/pex/mvPexRegs.h create mode 100644 board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.c create mode 100644 board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.h create mode 100644 board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c create mode 100644 board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h create mode 100644 board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339Reg.h create mode 100644 board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133x.c create mode 100644 board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h create mode 100644 board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133xReg.h create mode 100644 board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtc.c create mode 100644 board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtc.h create mode 100644 board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtcReg.h create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.c create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.h create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvOsS.h create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvRegs.h create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.c create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.h create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.c create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.h create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.c create mode 100644 board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.h create mode 100644 board/mv_feroceon/mv_hal/sflash/mvSFlash.c create mode 100644 board/mv_feroceon/mv_hal/sflash/mvSFlash.h create mode 100644 board/mv_feroceon/mv_hal/sflash/mvSFlashSpec.h create mode 100644 board/mv_feroceon/mv_hal/spi/mvSpi.c create mode 100644 board/mv_feroceon/mv_hal/spi/mvSpi.h create mode 100644 board/mv_feroceon/mv_hal/spi/mvSpiCmnd.c create mode 100644 board/mv_feroceon/mv_hal/spi/mvSpiCmnd.h create mode 100644 board/mv_feroceon/mv_hal/spi/mvSpiSpec.h create mode 100644 board/mv_feroceon/mv_hal/ts/mvTsu.c create mode 100644 board/mv_feroceon/mv_hal/ts/mvTsu.h create mode 100644 board/mv_feroceon/mv_hal/ts/mvTsuRegs.h create mode 100644 board/mv_feroceon/mv_hal/twsi/mvTwsi.c create mode 100644 board/mv_feroceon/mv_hal/twsi/mvTwsi.h create mode 100644 board/mv_feroceon/mv_hal/twsi/mvTwsiEeprom.S create mode 100644 board/mv_feroceon/mv_hal/twsi/mvTwsiSpec.h create mode 100644 board/mv_feroceon/mv_hal/uart/mvUart.c create mode 100644 board/mv_feroceon/mv_hal/uart/mvUart.h create mode 100644 board/mv_feroceon/mv_hal/uart/mvUartRegs.h create mode 100644 board/mv_feroceon/mv_hal/usb/api/mvUsbCh9.h create mode 100644 board/mv_feroceon/mv_hal/usb/api/mvUsbDebug.h create mode 100644 board/mv_feroceon/mv_hal/usb/api/mvUsbDefs.h create mode 100644 board/mv_feroceon/mv_hal/usb/api/mvUsbDevApi.h create mode 100644 board/mv_feroceon/mv_hal/usb/api/mvUsbTypes.h create mode 100644 board/mv_feroceon/mv_hal/usb/common/mvUsbCore.h create mode 100644 board/mv_feroceon/mv_hal/usb/common/mvUsbDesc.h create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbDevCh9.c create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbDevMain.c create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbDevPrv.h create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbDevRecv.c create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbDevSend.c create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbDevUtl.c create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevCncl.c create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevMain.c create mode 100644 board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevUtl.c create mode 100644 board/mv_feroceon/mv_hal/usb/examples/disk.c create mode 100644 board/mv_feroceon/mv_hal/usb/examples/disk.h create mode 100644 board/mv_feroceon/mv_hal/usb/examples/mouse.c create mode 100644 board/mv_feroceon/mv_hal/usb/examples/mouse.h create mode 100644 board/mv_feroceon/mv_hal/usb/mvUsb.c create mode 100644 board/mv_feroceon/mv_hal/usb/mvUsb.h create mode 100644 board/mv_feroceon/mv_hal/usb/mvUsbRegs.h create mode 100644 board/mv_feroceon/mv_hal/xor/mvXor.c create mode 100644 board/mv_feroceon/mv_hal/xor/mvXor.h create mode 100644 board/mv_feroceon/mv_hal/xor/mvXorRegs.h create mode 100644 board/mv_feroceon/mv_kw/bootstrap_def.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAsm.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvRegs.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvSpec.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfInit.S create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfRegs.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysCesa.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysCesa.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysGbe.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysGbe.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysPex.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysPex.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSdmmc.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSdmmc.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTdm.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTdm.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTs.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTs.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysUsb.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysUsb.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysXor.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysXor.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/device/mvDevice.c create mode 100644 board/mv_feroceon/mv_kw/kw_family/device/mvDevice.h create mode 100644 board/mv_feroceon/mv_kw/kw_family/device/mvDeviceRegs.h create mode 100644 board/mv_feroceon/mv_kw/mvSysHwConfig.h create mode 100644 board/mv_feroceon/mv_kw/mv_cmd.c create mode 100644 board/mv_feroceon/mv_kw/mv_dram.c create mode 100644 board/mv_feroceon/mv_kw/mv_main.c create mode 100644 board/mv_feroceon/mv_kw/nBootstrap.S create mode 100644 board/mv_feroceon/mv_kw/nBootstrap.h create mode 100644 board/mv_feroceon/mv_kw/platform.S create mode 100644 board/mv_feroceon/mv_orion/mv_cmd.c create mode 100644 board/mv_feroceon/mv_orion/mv_dram.c create mode 100644 board/mv_feroceon/mv_orion/mv_main.c create mode 100644 board/mv_feroceon/mv_orion/mv_service.c create mode 100644 board/mv_feroceon/mv_orion/mv_service.h create mode 100644 board/mv_feroceon/mv_orion/nBootstrap.S create mode 100644 board/mv_feroceon/mv_orion/nBootstrap.h create mode 100644 board/mv_feroceon/mv_orion/nBootstrap_LP.S create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/cpu/mvCpu.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1281EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1X81EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5082EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5180NEnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5181LEnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5182EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5X81EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6082EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183LEnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88w8660EnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAsm.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvSpec.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusRegs.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfInit.S create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfRegs.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysCesa.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysCesa.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysGbe.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysGbe.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysIdma.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysIdma.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysTdm.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysTdm.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysUsb.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysUsb.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysXor.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysXor.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/device/mvDevice.c create mode 100644 board/mv_feroceon/mv_orion/orion_family/device/mvDevice.h create mode 100644 board/mv_feroceon/mv_orion/orion_family/device/mvDeviceRegs.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F1281SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F1X81SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F5082SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F5180NSysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F5181LSysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F5182SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F5X81SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F6082SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F6183LSysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88F6183SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mv88w8660SysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/orion_sys/mvSysHwConfig.h create mode 100644 board/mv_feroceon/mv_orion/platform.S create mode 100644 board/mv_feroceon/uboot_oss/mvOs.c create mode 100644 board/mv_feroceon/uboot_oss/mvOs.h create mode 100644 board/mv_feroceon/uboot_oss/mvOsAsm.h create mode 100644 board/mv_feroceon/uboot_oss/mvOsSata.c create mode 100644 board/mv_feroceon/uboot_oss/mvOsSata.h create mode 100644 common/qnap_rcvr.c create mode 100644 create_all_images.sh create mode 100644 dramregs_200db_A.txt create mode 100644 dramregs_200rd_A.txt create mode 100644 dramregs_400_A.txt create mode 100644 drivers/ahci.c create mode 100644 drivers/nand/Makefile create mode 100644 drivers/nand/diskonchip.c create mode 100644 drivers/nand/nand.c create mode 100644 drivers/nand/nand_base.c create mode 100644 drivers/nand/nand_bbt.c create mode 100644 drivers/nand/nand_ecc.c create mode 100644 drivers/nand/nand_ecc_rs.c create mode 100644 drivers/nand/nand_ids.c create mode 100644 drivers/nand/nand_util.c create mode 100644 drivers/rtl8029.c create mode 100644 drivers/rtl8029.h create mode 100644 drivers/sk98lin/h/skgetwsi.h create mode 100644 drivers/sk98lin/h/sktwsi.h create mode 100644 drivers/sk98lin/h/sky2le.h create mode 100644 drivers/sk98lin/skdim.c create mode 100644 drivers/sk98lin/skethtool.c create mode 100644 drivers/sk98lin/sktwsi.c create mode 100644 drivers/sk98lin/sky2.c create mode 100644 drivers/sk98lin/sky2le.c create mode 100644 fs/jffs2/jffs2_nand_1pass.c create mode 100644 fs/jffs2/jffs2_nand_private.h create mode 100644 include/ahci.h create mode 100644 include/asm-arm/arch-arm926ejs/vfp.h create mode 100644 include/asm-arm/arch-arm926ejs/vfpinstr.h create mode 100644 include/configs/mv_dd.h create mode 100644 include/configs/mv_feroceon.h create mode 100644 include/configs/mv_kw.h create mode 100644 include/linux/mtd/compat.h create mode 100644 include/linux/mtd/mtd-abi.h create mode 100644 include/linux/mtd/mtd.h create mode 100644 include/linux/mtd/nand_ecc.h create mode 100644 include/linux/mtd/nand_ecc_rs.h create mode 100644 include/linux/mtd/nand_legacy.h create mode 100644 include/nand.h create mode 100644 include/qnap.h create mode 100644 net/rcvr.c create mode 100644 net/rcvr.h create mode 100644 rules.mk create mode 100644 tools/Makefile_doimage create mode 100644 tools/bootstrap_def.h create mode 100644 tools/bootstrap_os.h create mode 100644 tools/doimage create mode 100644 tools/doimage.c create mode 100644 u-boot.bin.410 diff --git a/Makefile b/Makefile index 9305cab..5d390e1 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,8 @@ VENDOR= TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) export TOPDIR - +SRCTREE := $(TOPDIR) +export SRCTREE ifeq (include/config.mk,$(wildcard include/config.mk)) # load ARCH, BOARD, and CPU configuration include include/config.mk @@ -57,8 +58,10 @@ ifeq ($(ARCH),ppc) CROSS_COMPILE = powerpc-linux- endif ifeq ($(ARCH),arm) +ifeq ($(CROSS),armlinux) CROSS_COMPILE = arm-linux- endif +endif ifeq ($(ARCH),i386) ifeq ($(HOSTARCH),i386) CROSS_COMPILE = @@ -118,6 +121,7 @@ LIBS += disk/libdisk.a LIBS += rtc/librtc.a LIBS += dtt/libdtt.a LIBS += drivers/libdrivers.a +LIBS += drivers/nand/libnand.a LIBS += drivers/sk98lin/libsk98lin.a LIBS += post/libpost.a post/cpu/libcpu.a LIBS += common/libcommon.a @@ -130,7 +134,6 @@ PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) - # The "tools" are needed early, so put this first # Don't include stuff already done in $(LIBS) SUBDIRS = tools \ - examples \ post \ post/cpu .PHONY : $(SUBDIRS) @@ -139,6 +142,17 @@ SUBDIRS = tools \ ######################################################################### ALL = u-boot.srec u-boot.bin System.map +BINCPY = cp -f u-boot.bin u-boot-${MV_OUTPUT}.bin +ELFCPY = cp -f u-boot u-boot-${MV_OUTPUT} +SRECCPY = cp -f u-boot.srec u-boot-${MV_OUTPUT}.srec + +DO_IMAGE_NAND = ./tools/doimage -T nand -D 0x600000 -E 0x670000 -P 2048 -R \ +dramregs_$(MV_DDR_FREQ)_A.txt u-boot-${MV_OUTPUT}.bin u-boot-${MV_OUTPUT}_$(MV_DDR_FREQ)_nand.bin +DO_IMAGE_UART = ./tools/doimage -T uart -D 0x600000 -E 0x670000 -R \ +dramregs_$(MV_DDR_FREQ)_A.txt u-boot-${MV_OUTPUT}.bin u-boot-${MV_OUTPUT}_$(MV_DDR_FREQ)_uart.bin +DO_IMAGE_FLASH = ./tools/doimage -T flash -D 0x600000 -E 0x670000 -R \ +dramregs_$(MV_DDR_FREQ)_A.txt u-boot-${MV_OUTPUT}.bin u-boot-${MV_OUTPUT}_$(MV_DDR_FREQ)_flash.bin + all: $(ALL) @@ -147,9 +161,18 @@ u-boot.hex: u-boot u-boot.srec: u-boot $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ + $(SRECCPY) u-boot.bin: u-boot $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ + $(BINCPY) +ifeq ($(NAND_BOOT), y) + $(DO_IMAGE_NAND) +endif +ifeq ($(SPI_BOOT), y) + $(DO_IMAGE_FLASH) +endif + $(DO_IMAGE_UART) u-boot.img: u-boot.bin ./tools/mkimage -A $(ARCH) -T firmware -C none \ @@ -161,6 +184,16 @@ u-boot.img: u-boot.bin u-boot.dis: u-boot $(OBJDUMP) -d $< > $@ + +nboot: $(NAND_OBJS) + $(LD) $(NAND_LDFLAGS) $(NAND_OBJS) --start-group $(LIBS) $(PLATFORM_LIBS) --end-group\ + -e nbootStart -Map nboot.map -o nboot + $(OBJCOPY) ${OBJCFLAGS} -O binary $@ $@.bin + $(OBJDUMP) -d $@ > $@.dis + +cnboot: + rm -f nboot* + u-boot: depend $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT) UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\ $(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) \ @@ -197,6 +230,7 @@ System.map: u-boot @$(NM) $< | \ grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \ sort > System.map + $(ELFCPY) ######################################################################### else @@ -1349,8 +1383,1121 @@ AmigaOneG3SE_config: unconfig BAB7xx_config: unconfig @./mkconfig $(@:_config=) ppc 74xx_7xx bab7xx eltec -CPCI750_config: unconfig - @./mkconfig CPCI750 ppc 74xx_7xx cpci750 esd +MV64XXX_PPC_LE_config \ +MV64XXX_PPC_config : unconfig + @./mkconfig MV64XXX_PPC ppc 74xx_7xx db64xxx_ppc Marvell + @[ -z "$(findstring LE,$@)" ] || \ + { echo "CONFIG_MARVELL_LE = y" >>include/config.mk ;\ + echo "export CONFIG_MARVELL_LE" >> include/config.mk ;\ + echo "** Little Endian ** config " ; \ + } + @[ -z "$(findstring MV64XXX_PPC,$@)" ] || \ + { echo "CROSS_COMPILE = powerpc-linux-" >> include/config.mk ;\ + echo "export CROSS_COMPILE" >> include/config.mk ; \ + echo "using powerpc-linux- cross compiler" ;\ + } + +######################################################################### +## Marvell KW based Socs +######################################################################### + +ifeq ($(CROSS),armlinux) +else +CSL = arm-none-linux-gnueabi- +CSLBE = armeb-none-linux-gnueabi- +endif + +rd88f6281a_config \ +db88f6281abp_config \ +rd88f6192a_config \ +db88f6192abp_config \ +db88f6180abp_config \ +rd88f6190a_config \ +db88f6190abp_config \ +: + @$(MAKE) -s mv_kw RULE=$@ + +mv_kw: unconfig + @./mkconfig $(@:_config=) arm arm926ejs config_kw mv_feroceon; + @cp board/mv_feroceon/config_kw/config_def.mk board/mv_feroceon/config_kw/config.mk; + @echo "MV_OUTPUT = $(RULE:_config=)" >> include/config.mk; \ +#======================= +# Soc Compilation flag +#======================= + @[ -z "$(findstring 6281,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV88F6281" >> include/config.mk; \ + echo "** MV_88F6281 image ** config " ; \ + } + @[ -z "$(findstring 6192,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV88F6192" >> include/config.mk; \ + echo "** MV_88F6192 image ** config " ; \ + } + @[ -z "$(findstring 6190,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV88F6190" >> include/config.mk; \ + echo "** MV_88F6190 image ** config " ; \ + } + @[ -z "$(findstring 6180,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV88F6180" >> include/config.mk; \ + echo "** MV_88F6180 image ** config " ; \ + } +#======================= +# Board Compilation flags +#======================= + @[ -z "$(findstring db88f6281abp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6281A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; \ + echo "MV_DDR_FREQ = 400" >> include/config.mk; \ + cp board/mv_feroceon/config_kw/u-boot-sec256k.lds board/mv_feroceon/config_kw/u-boot.lds; \ + echo "** DB 88F6281A BP ** config " ; \ + } + @[ -z "$(findstring rd88f6281a_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6281A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_256K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; \ + echo "MV_DDR_FREQ = 400" >> include/config.mk; \ + cp board/mv_feroceon/config_kw/u-boot-sec256k.lds board/mv_feroceon/config_kw/u-boot.lds; \ + echo "** RD 88F6281A ** config " ; \ + } + @[ -z "$(findstring db88f6192abp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6192A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_256K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; \ + echo "MV_DDR_FREQ = 200db" >> include/config.mk; \ + cp board/mv_feroceon/config_kw/u-boot-sec256k.lds board/mv_feroceon/config_kw/u-boot.lds; \ + echo "** DB 88F6192A BP ** config " ; \ + } + @[ -z "$(findstring rd88f6192a_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6192A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_256K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; \ + echo "MV_DDR_FREQ = 200rd" >> include/config.mk; \ + cp board/mv_feroceon/config_kw/u-boot-sec256k.lds board/mv_feroceon/config_kw/u-boot.lds; \ + echo "** RD 88F6192A ** config " ; \ + } + @[ -z "$(findstring db88f6180abp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6180A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_256K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; \ + echo "MV_DDR_FREQ = 200db" >> include/config.mk; \ + cp board/mv_feroceon/config_kw/u-boot-sec256k.lds board/mv_feroceon/config_kw/u-boot.lds; \ + echo "** DB 88F6180A BP ** config " ; \ + } + @[ -z "$(findstring db88f6190abp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6190A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_256K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; \ + echo "MV_DDR_FREQ = 200db" >> include/config.mk; \ + cp board/mv_feroceon/config_kw/u-boot-sec256k.lds board/mv_feroceon/config_kw/u-boot.lds; \ + echo "** DB 88F6190A BP ** config " ; \ + } + @[ -z "$(findstring rd88f6190a_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6190A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_256K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; \ + echo "MV_DDR_FREQ = 200rd" >> include/config.mk; \ + cp board/mv_feroceon/config_kw/u-boot-sec256k.lds board/mv_feroceon/config_kw/u-boot.lds; \ + echo "** RD 88F6190A ** config " ; \ + } + +#============================== +# Little Endian Cross Compiler +#============================== +ifeq ($(BE),) +ifeq ($(CSL),) + @echo "CROSS_COMPILE = arm-none-linux-gnueabi-" >> include/config.mk; +else + @echo "CROSS_COMPILE = $(CSL)" >> include/config.mk; +endif +endif +#============================== +# Big Endian Cross Compiler +#============================== +ifeq ($(BE),1) + @echo "MV_FLAGS += -mbig-endian -D__BE" >> include/config.mk; + @echo "BIG_ENDIAN =y" >> include/config.mk; + @echo "LDFLAGS += -EB" >> include/config.mk; +ifeq ($(CSLBE),) + @echo "CROSS_COMPILE = armeb-none-linux-gnueabi-" >> include/config.mk; +else + @echo "CROSS_COMPILE = $(CSLBE)" >> include/config.mk; +endif + @echo "** Big Endian ** config "; +endif + +#================= +# USB support +#================= +ifeq ($(USB),1) + @echo "MV_FLAGS += -DMV_USB" >> include/config.mk; + @echo "MV_USB=y" >> include/config.mk; + @echo "** With USB ** config " ; +endif +#================= +# NAND support +#================= +ifeq ($(NAND),1) + @echo "** NAND support image ** config " ; + @echo "MV_FLAGS += -DMV_NAND" >> include/config.mk; +endif +#================= +# Boot from NAND support +#================= +ifeq ($(NBOOT),1) + @echo "** Boot from NAND support image ** config " ; + @echo "MV_FLAGS += -DMV_NAND_BOOT" >> include/config.mk; + @echo "NAND_BOOT =y" >> include/config.mk; + @cat board/mv_feroceon/config_kw/config_nand.mk >> board/mv_feroceon/config_kw/config.mk; + cp board/mv_feroceon/config_kw/u-boot-sec128k.lds board/mv_feroceon/config_kw/u-boot.lds; +endif +#================= +# SPI support +#================= +ifeq ($(SPI),1) + @echo "** SPI support image ** config " ; + @echo "MV_FLAGS += -DMV_SPI" >> include/config.mk; +endif +ifeq ($(SPIBOOT),1) + @echo "** Boot from SPI support image ** config " ; + @echo "MV_FLAGS += -DMV_SPI" >> include/config.mk; + @echo "MV_FLAGS += -DMV_SPI_BOOT" >> include/config.mk; + @echo "SPI_BOOT =y" >> include/config.mk; +endif +#================= +# QNAP SECTOR SIZE +#================= +ifeq ($(SECSIZE),64) + @echo "MV_IMAGE_FLAGS += -DMV_SEC_64K" >> include/config.mk; +else + @echo "MV_IMAGE_FLAGS += -DMV_SEC_256K" >> include/config.mk; +endif +#================= +# QNAP NAS Support +#================= +ifeq ($(QNAPNAS),1) + @echo "** QNAP System NAS Feature Support " ; + @echo "MV_FLAGS += -DQNAPNAS" >> include/config.mk; +endif +#================= +# MFlash support +#================= +ifeq ($(MFLASH),1) + @echo "** MFLASH support image ** config " ; + @echo "MV_FLAGS += -DMV_FLASH" >> include/config.mk; +endif +ifeq ($(MFLASHBOOT),1) + @echo "** Boot from MFLASH support image ** config " ; + @echo "MV_FLAGS += -DMV_FLASH" >> include/config.mk; + @echo "MV_FLAGS += -DMV_FLASH_BOOT" >> include/config.mk; +endif +#================= +# BOOTROM support +#================= +#ifeq ($(BOOTROM),1) +# @echo "** BOOTROM support image ** config " ; +# @echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; +ifeq ($(NBOOT),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-nand.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-header.lds board/mv_feroceon/config/u-boot.lds; +endif +#endif +#=================== +# Tiny Image support +#=================== +ifneq ($(TINY),) + @echo "MV_FLAGS += -DMV_TINY_IMAGE" >> include/config.mk; + @echo "MV_TINY_IMAGE=y" >> include/config.mk; +ifeq ($(TINY),256K_32K) + @echo "** TINY image BootSize=256K SEC=32K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec32k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec32k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_32K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_256K" >> include/config.mk; +else +ifeq ($(TINY),256K_64K) + @echo "** TINY image BootSize=256K SEC=64K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_256K" >> include/config.mk; +else +ifeq ($(TINY),512K_64K) + @echo "** TINY image BootSize=512K SEC=64K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; +else +ifeq ($(TINY),4M_128K) + @echo "** TINY image BootSize=4M SEC=128K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec128k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec128k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_4M" >> include/config.mk; +else +ifeq ($(TINY),8M_128K) + @echo "** TINY image BootSize=8M SEC=128K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec128k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec128k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; +else +ifeq ($(TINY),16M_64K) + @echo "** TINY image BootSize=16M SEC=64K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; +else +ifeq ($(TINY),16M_128K) + @echo "** TINY image BootSize=16M SEC=128K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec128k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec128k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; +else +ifeq ($(TINY),256K_4K) + @echo "** TINY image BootSize=256K SEC=4K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec4k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec4k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_4K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_256K" >> include/config.mk; +else + @make mrproper; + @echo "" ; + @echo "** ERROR : Illegal TINY image configuration" ; + @echo "" ; + @echo "Legal values for TINY are :" ; + @echo "" ; + @echo "512K_64K, 16M_64K, 16M_128K, 256K_32K or 256K_4K" ; + @echo "" ; +endif +endif +endif +endif +endif +endif +endif +endif +endif +#============================= +# Summary of compilation flags +#============================= +# @echo -e "CPPFLAGS += \044(MV_IMAGE_FLAGS) \044(MV_FLAGS)" >> include/config.mk; + @echo "CPPFLAGS += \044(MV_IMAGE_FLAGS) \044(MV_FLAGS)" >> include/config.mk; +#================= +# QNAP MODEL Support +#================= +ifeq ($(MODEL),TS419) + @echo "** QNAP System NAS Model Support " ; + @echo "MV_FLAGS += -DTS419" >> include/config.mk; +else +ifeq ($(MODEL),TS119) + @echo "** QNAP System NAS Model Support " ; + @echo "MV_FLAGS += -DTS119" >> include/config.mk; +else +ifeq ($(MODEL),TS219) + @echo "** QNAP System NAS Model Support " ; + @echo "MV_FLAGS += -DTS219" >> include/config.mk; +else +ifeq ($(MODEL),TS118) + @echo "** QNAP System NAS Model Support " ; + @echo "MV_FLAGS += -DTS118" >> include/config.mk; +else +ifeq ($(MODEL),TS218) + @echo "** QNAP System NAS Model Support " ; + @echo "MV_FLAGS += -DTS218" >> include/config.mk; +else + @echo "ERROR:Please input MODEL flags ,eg. MODEL=TS219" ; + @rm -fr include/config.mk +endif +endif +endif +endif +endif + +######################################################################### +## END of Marvell KW based Socs +######################################################################### + +######################################################################### +## Marvell Feroceon based Socs +######################################################################### +# Parameters: Target Architecture CPU Board [VENDOR] [SOC] # +# + +rd78XX0_H3C_config \ +rd78XX0_MP_H3C_config \ +rd78XX0_AMC_config \ +rd78XX0_MP_AMC_config \ +rd78XX0_MASA_config \ +rd78XX0_MP_MASA_config \ +rd78XX0_MP_MASA_2DIMM_config \ +db78XX0_MP_config \ +db78XX0_config : + @$(MAKE) -s mv_dd RULE=$@ +mv_dd: unconfig + @./mkconfig $(@:_config=) arm arm926ejs config_dd mv_feroceon; + @cp -f board/mv_feroceon/config_dd/config_def.mk board/mv_feroceon/config_dd/config.mk; + @cp -f board/mv_feroceon/config_dd/u-boot_def.lds board/mv_feroceon/config_dd/u-boot.lds; + @echo "MV_OUTPUT = $(RULE:_config=)" >> include/config.mk; \ +#======================= +# Soc Compilation flag +#======================= + @[ -z "$(findstring 78XX0_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV78XX0" >> include/config.mk; \ + echo "** MV_78XX0 image ** config " ; \ + } + @[ -z "$(findstring 78XX0_MP,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV78200" >> include/config.mk; \ + echo "** MV78200 image ** config " ; \ + } +#======================= +# Board Compilation flags +#======================= + @[ -z "$(findstring db78XX0_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_MV78XX0" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + echo "** DB 78XX0 BP ** config " ; \ + } + @[ -z "$(findstring _AMC_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_MV78XX0_AMC" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + echo "** RD 78XX0 AMC ** config " ; \ + } + @[ -z "$(findstring _H3C_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_MV78XX0_H3C" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_2M" >> include/config.mk; \ + echo "** RD 78XX0 H3C ** config " ; \ + } + @[ -z "$(findstring _MASA_2DIMM_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_MV78XX0_MASA" >> include/config.mk; \ + echo "MV_FLAGS += -DRD_MV78XX0_MASA_2DIMM" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + echo "** RD 78XX0 MASA ** config " ; \ + } + @[ -z "$(findstring _MASA_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_MV78XX0_MASA" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + echo "** RD 78XX0 MASA ** config " ; \ + } + +#============================== +# Little Endian Cross Compiler +#============================== +ifeq ($(BE),) +ifeq ($(CSL),) + @echo "CROSS_COMPILE = arm-none-linux-gnueabi-" >> include/config.mk; +else + @echo "CROSS_COMPILE = $(CSL)" >> include/config.mk; +endif + @echo "CONFIG_MARVELL_LE = y" >>include/config.mk ; + @echo "export CONFIG_MARVELL_LE" >> include/config.mk ; + @echo "** Little Endian ** config " ; + @echo "MV_FLAGS += -D__LE" >> include/config.mk; +endif +#============================== +# Big Endian Cross Compiler +#============================== +ifeq ($(BE),1) + @echo "MV_FLAGS += -mbig-endian -D__BE" >> include/config.mk; + @echo "BIG_ENDIAN =y" >> include/config.mk; + @echo "LDFLAGS += -EB" >> include/config.mk; +ifeq ($(CSLBE),) + @echo "CROSS_COMPILE = armeb-none-linux-gnueabi-" >> include/config.mk; +else + @echo "CROSS_COMPILE = $(CSLBE)" >> include/config.mk; +endif + @echo "** Big Endian ** config "; +endif + +#================= +# Boot from NAND support +#================= +ifeq ($(NBOOT),1) + @echo "** Boot from NAND support image ** config " ; + @echo "MV_FLAGS += -DMV_NAND_BOOT" >> include/config.mk; + @echo "NAND_BOOT =y" >> include/config.mk; + @cat board/mv_feroceon/config_dd/config_nand.mk >> board/mv_feroceon/config_dd/config.mk; + @cp board/mv_feroceon/config_dd/u-boot-sec128k.lds board/mv_feroceon/config_dd/u-boot.lds; +endif +#================= +# Boot from SPI support +#================= +ifeq ($(SPIBOOT),1) + @echo "** Boot from SPI support image ** config " ; + @echo "MV_FLAGS += -DMV_SPI_BOOT" >> include/config.mk; + @echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; +endif +#============================= +# Summary of compilation flags +#============================= + @echo -e "CPPFLAGS += \044(MV_IMAGE_FLAGS) \044(MV_FLAGS)" >> include/config.mk; + + +######################################################################### +## Marvell Feroceon based Socs +######################################################################### + +ifeq ($(CROSS),armlinux) +else +CSL = arm-none-linux-gnueabi- +CSLBE = armeb-none-linux-gnueabi- +endif + +db88f1181_config \ +db88f5181L_VOIP2_config \ +rd88f5181L_VOIP2_FE_config \ +rd88f5181L_VOIP2_GE_config \ +rd88f5181L_FXO_GE_config \ +db88f5181_VOIP2_config \ +rd88f5181_GTW_FE_config \ +rd88f5181_GTW_GE_config \ +db88f5182_config \ +db88f5182_A_config \ +rd88f5182_NAS2_config \ +rd88f5182_NAS3_config \ +db88f5082_config \ +rd88f5082_NAS2_config \ +rd88f5082_NAS3_config \ +rd88w8660_config \ +db88w8660_config \ +rd88w8660_AP82S_config\ +db88f5181_POS_NAS_config \ +db88f5181_VOIP1_config \ +db88f5181_PRPMC_config \ +db88f5181_PEX_PCI_config \ +db88f5181_MNG_config \ +db88f5180n_config \ +db88f1281_config \ +db88f6082bp_config \ +db88f6082Lbp_config \ +db88f6082sa_config \ +rd88f6082nas_config \ +rd88f6082u_das_nas_config \ +rd88f6082das_plus_config \ +rd88f6082ge_sata_config \ +rd88f6082_dx243_24g_config \ +rd_88f5181L_Customer1_config \ +db88f5x8x_fpga_config \ +db88f6183Lbp_config \ +db88f6183_bp_config \ +db88f6183_bp_LargeSpi_config \ +rd88f6183_gp_config \ +rd88f6183_ap_config \ +db88f5181_old_config \ +db88f5181_config : + @$(MAKE) -s mv_feroceon RULE=$@ + +mv_feroceon: unconfig + @./mkconfig $(@:_config=) arm arm926ejs config mv_feroceon; + @cp board/mv_feroceon/config/config_def.mk board/mv_feroceon/config/config.mk; + @echo "MV_OUTPUT = $(RULE:_config=)" >> include/config.mk; \ +#======================= +# Soc Compilation flag +#======================= + @[ -z "$(findstring 1181_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F1181" >> include/config.mk; \ + echo "** MV_88F1181 image ** config " ; \ + } + @[ -z "$(findstring 1281_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F1281" >> include/config.mk; \ + echo "MV_88F1281=y" >> include/config.mk; \ + echo "** MV_88F1281 image ** config " ; \ + } + @[ -z "$(findstring 5181_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F5181" >> include/config.mk; \ + echo "** MV_88F5181 image ** config " ; \ + } + @[ -z "$(findstring 5182_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F5182" >> include/config.mk; \ + echo "** MV_88F5182 image ** config " ; \ + } + @[ -z "$(findstring 5082_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F5082" >> include/config.mk; \ + echo "** MV_88F5082 image ** config " ; \ + } + @[ -z "$(findstring 88w8660_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88W8660" >> include/config.mk; \ + echo "MV_88W8660=y" >> include/config.mk; \ + echo "** MV_88W8660 image ** config " ; \ + } + @[ -z "$(findstring 5181L_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F5181L" >> include/config.mk; \ + echo "** MV_88F5181L image ** config " ; \ + } + @[ -z "$(findstring 5180n_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F5180N" >> include/config.mk; \ + echo "** MV_88F5180N image ** config " ; \ + } + @[ -z "$(findstring 6082,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F6082" >> include/config.mk; \ + echo "MV_88F6082=y" >> include/config.mk; \ + echo "** MV_88F6082 image ** config " ; \ + } + @[ -z "$(findstring 6082L,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F6082L" >> include/config.mk; \ + echo "MV_88F6082L=y" >> include/config.mk; \ + echo "** MV_88F6082L image ** config " ; \ + } + @[ -z "$(findstring 5x8x,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F5181" >> include/config.mk; \ + echo "MV_88F5181=y" >> include/config.mk; \ + echo "** MV_88F5X8X image ** config " ; \ + } + @[ -z "$(findstring 6183_,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F6183" >> include/config.mk; \ + echo "MV_88F6183=y" >> include/config.mk; \ + echo "** MV_88F6183 image ** config " ; \ + } + @[ -z "$(findstring 6183L,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_88F6183L" >> include/config.mk; \ + echo "MV_88F6183L=y" >> include/config.mk; \ + echo "** MV_88F6183L image ** config " ; \ + } +#======================= +# Board Compilation flags +#======================= + @[ -z "$(findstring db88f1181_config,$(RULE))" ] || \ + { echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + } + @[ -z "$(findstring db88f1281_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F1281" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + } + @[ -z "$(findstring db88f5181_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F5181" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB88F5181 BP-A/B ** config " ; \ + } + @[ -z "$(findstring db88f5181_old_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F5181_OLD" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB88F5181 OLD BP ** config " ; \ + } + @[ -z "$(findstring db88f5x8x_fpga_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_FPGA" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB88F5X8X FPGA ** config " ; \ + } + @[ -z "$(findstring db88f5182_config,$(RULE))" ] || \ + { echo "CPPFLAGS += -DDB_88F5182" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F5182 ** config " ; \ + } + @[ -z "$(findstring db88f5182_A_config,$(RULE))" ] || \ + { echo "CPPFLAGS += -DDB_88F5182_A" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F5182 A ** config " ; \ + } + @[ -z "$(findstring rd88f5182_NAS2,$(RULE))" ] || \ + { echo "CPPFLAGS += -DRD_88F5182" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5182 ** config " ; \ + } + @[ -z "$(findstring rd88f5182_NAS3,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F5182_3" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5182_3 ** config " ; \ + } + @[ -z "$(findstring db88f5082_config,$(RULE))" ] || \ + { echo "CPPFLAGS += -DDB_88F5082" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F5082 ** config " ; \ + } + @[ -z "$(findstring rd88f5082_NAS2,$(RULE))" ] || \ + { echo "CPPFLAGS += -DRD_88F5082" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_4K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_256K" >> include/config.mk; \ + echo "** RD_88F5082 ** config " ; \ + } + @[ -z "$(findstring rd88f5082_NAS3,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F5082_3" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5082_3 ** config " ; \ + } + @[ -z "$(findstring Customer1,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_CUSTOMER1" >> include/config.mk; \ + echo "MV_FLAGS += -DDB_CUSTOMER" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_32M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** Customer 1 image ** config " ; \ + } + @[ -z "$(findstring POS_NAS,$(RULE))" ] || \ + { echo "MV_FLAGS += -DMV_POS_NAS" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** POS_NAS image ** config " ; \ + } + @[ -z "$(findstring PRPMC,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_PRPMC" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** PRPMC image ** config " ; \ + } + @[ -z "$(findstring MNG,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_MNG" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** MNG image ** config " ; \ + } + @[ -z "$(findstring PEX_PCI,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_PEX_PCI" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** PEX_PCI image ** config " ; \ + } + @[ -z "$(findstring db88f5181_VOIP1,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_VOIP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** VOIP1 image ** config " ; \ + } + @[ -z "$(findstring db88w8660_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88W8660" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + } + @[ -z "$(findstring rd88w8660_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88W8660" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88W8660 image ** config " ; \ + } + @[ -z "$(findstring rd88w8660_AP82S_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88W8660_AP82S" >> include/config.mk; \ + echo "MV_FLAGS += -DMV_DRAM_16M" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88W8660_AP82S image ** config " ; \ + } + @[ -z "$(findstring db88f5181_VOIP2,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_DB_88F5181L" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F5181L_VOIP2 image ** config " ; \ + } + @[ -z "$(findstring db88f5181L_VOIP2,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F5181L" >> include/config.mk; \ + echo "MV_FLAGS += -DRD_DB_88F5181L" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F5181L_VOIP2 image ** config " ; \ + } + @[ -z "$(findstring rd88f5181L_VOIP2_FE,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F5181L_FE" >> include/config.mk; \ + echo "MV_FLAGS += -DRD_DB_88F5181L" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5181L_FE image ** config " ; \ + } + @[ -z "$(findstring rd88f5181L_VOIP2_GE,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F5181L_GE" >> include/config.mk; \ + echo "MV_FLAGS += -DRD_DB_88F5181L" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5181L_GE image ** config " ; \ + } + @[ -z "$(findstring rd88f5181L_FXO_GE,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F5181L_FXO_GE" >> include/config.mk; \ + echo "MV_FLAGS += -DRD_DB_88F5181L" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5181L_FXO_GE image ** config " ; \ + } + @[ -z "$(findstring rd88f5181_GTW_FE,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F5181_GTWFE" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5181_GTW_FE image ** config " ; \ + } + @[ -z "$(findstring rd88f5181_GTW_GE,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F5181_GTWGE" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F5181_GTW_GE image ** config " ; \ + } + @[ -z "$(findstring db88f5180n_config,$(RULE))" ] || \ + { echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + } + @[ -z "$(findstring db88f6082bp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6082BP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F6082 image ** config " ; \ + } + @[ -z "$(findstring db88f6082bp_LP_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6082BP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_LARGE_PAGE" >> include/config.mk; \ + echo "NAND_LARGE_PAGE =y" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F6082 image ** config " ; \ + } + @[ -z "$(findstring db88f6082Lbp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6082LBP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F6082L image ** config " ; \ + } + @[ -z "$(findstring db88f6082sa_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6082SA" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F6082 image ** config " ; \ + } + @[ -z "$(findstring rd88f6082nas_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6082NAS" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F6082_NAS image ** config " ; \ + } + @[ -z "$(findstring rd88f6082u_das_nas_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6082MICRO_DAS_NAS" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F6082_MICRO_DAS_NAS image ** config " ; \ + } + @[ -z "$(findstring rd88f6082das_plus_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6082DAS_PLUS" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F6082_DAS_PLUS image ** config " ; \ + } + @[ -z "$(findstring rd88f6082ge_sata_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6082GE_SATA" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F6082_GE_SATA image ** config " ; \ + } + @[ -z "$(findstring db88f6183Lbp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6183LBP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F6183LBP image ** config " ; \ + } + @[ -z "$(findstring db88f6183_bp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6183BP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F6183BP image ** config " ; \ + } + @[ -z "$(findstring db88f6183_bp_LargeSpi_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DDB_88F6183BP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_256K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_MMC" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec256k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** DB_88F6183BP image ** config " ; \ + } + @[ -z "$(findstring rd88f6183_gp_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6183GP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_MMC" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F6183GP image ** config " ; \ + } + @[ -z "$(findstring rd88f6183_ap_config,$(RULE))" ] || \ + { echo "MV_FLAGS += -DRD_88F6183AP" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; \ + echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; \ + cp board/mv_feroceon/config/u-boot-sec64k.lds board/mv_feroceon/config/u-boot.lds; \ + echo "** RD_88F6183AP image ** config " ; \ + } + +#============================== +# Little Endian Cross Compiler +#============================== +ifeq ($(BE),) +ifeq ($(CSL),) + @echo "CROSS_COMPILE = arm-none-linux-gnueabi-" >> include/config.mk; +else + @echo "CROSS_COMPILE = $(CSL)" >> include/config.mk; +endif +endif +#============================== +# Big Endian Cross Compiler +#============================== +ifeq ($(BE),1) + @echo "MV_FLAGS += -mbig-endian -D__BE" >> include/config.mk; + @echo "BIG_ENDIAN =y" >> include/config.mk; + @echo "LDFLAGS += -EB" >> include/config.mk; +ifeq ($(CSLBE),) + @echo "CROSS_COMPILE = armeb-none-linux-gnueabi-" >> include/config.mk; +else + @echo "CROSS_COMPILE = $(CSLBE)" >> include/config.mk; +endif + @echo "** Big Endian ** config "; +endif + +#================= +# USB support +#================= +ifeq ($(USB),1) + @echo "MV_FLAGS += -DMV_USB" >> include/config.mk; + @echo "MV_USB=y" >> include/config.mk; + @echo "** With USB ** config " ; +endif +#================= +# NAND support +#================= +ifeq ($(NAND),1) + @echo "** NAND support image ** config " ; + @echo "MV_FLAGS += -DMV_NAND" >> include/config.mk; +endif +#================= +# Boot from NAND support +#================= +ifeq ($(NBOOT),1) + @echo "** Boot from NAND support image ** config " ; + @echo "MV_FLAGS += -DMV_NAND_BOOT" >> include/config.mk; + @echo "NAND_BOOT =y" >> include/config.mk; + @cat board/mv_feroceon/config/config_nand.mk >> board/mv_feroceon/config/config.mk; + cp board/mv_feroceon/config/u-boot-sec128k.lds board/mv_feroceon/config/u-boot.lds; +endif +#================= +# SPI support +#================= +ifeq ($(SPI),1) + @echo "** SPI support image ** config " ; + @echo "MV_FLAGS += -DMV_SPI" >> include/config.mk; +endif +ifeq ($(SPIBOOT),1) + @echo "** Boot from SPI support image ** config " ; + @echo "MV_FLAGS += -DMV_SPI" >> include/config.mk; + @echo "MV_FLAGS += -DMV_SPI_BOOT" >> include/config.mk; +endif +#================= +# MFlash support +#================= +ifeq ($(MFLASH),1) + @echo "** MFLASH support image ** config " ; + @echo "MV_FLAGS += -DMV_FLASH" >> include/config.mk; +endif +ifeq ($(MFLASHBOOT),1) + @echo "** Boot from MFLASH support image ** config " ; + @echo "MV_FLAGS += -DMV_FLASH" >> include/config.mk; + @echo "MV_FLAGS += -DMV_FLASH_BOOT" >> include/config.mk; +endif +#================= +# BOOTROM support +#================= +ifeq ($(BOOTROM),1) + @echo "** BOOTROM support image ** config " ; + @echo "MV_FLAGS += -DMV_BOOTROM" >> include/config.mk; +ifeq ($(NBOOT),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-nand.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-header.lds board/mv_feroceon/config/u-boot.lds; +endif +endif +#=================== +# Tiny Image support +#=================== +ifneq ($(TINY),) + @echo "MV_FLAGS += -DMV_TINY_IMAGE" >> include/config.mk; + @echo "MV_TINY_IMAGE=y" >> include/config.mk; +ifeq ($(TINY),256K_32K) + @echo "** TINY image BootSize=256K SEC=32K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec32k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec32k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_32K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_256K" >> include/config.mk; +else +ifeq ($(TINY),256K_64K) + @echo "** TINY image BootSize=256K SEC=64K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_256K" >> include/config.mk; +else +ifeq ($(TINY),512K_64K) + @echo "** TINY image BootSize=512K SEC=64K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_512K" >> include/config.mk; +else +ifeq ($(TINY),4M_128K) + @echo "** TINY image BootSize=4M SEC=128K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec128k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec128k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_4M" >> include/config.mk; +else +ifeq ($(TINY),8M_128K) + @echo "** TINY image BootSize=8M SEC=128K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec128k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec128k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_8M" >> include/config.mk; +else +ifeq ($(TINY),16M_64K) + @echo "** TINY image BootSize=16M SEC=64K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec64k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec64k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_64K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; +else +ifeq ($(TINY),16M_128K) + @echo "** TINY image BootSize=16M SEC=128K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec128k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec128k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_128K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_16M" >> include/config.mk; +else +ifeq ($(TINY),256K_4K) + @echo "** TINY image BootSize=256K SEC=4K" ; +ifeq ($(BOOTROM),1) + @cp board/mv_feroceon/config/u-boot-sec4k-header-tiny.lds board/mv_feroceon/config/u-boot.lds; +else + @cp board/mv_feroceon/config/u-boot-sec4k-tiny.lds board/mv_feroceon/config/u-boot.lds; +endif + @echo "MV_IMAGE_FLAGS = -DMV_SEC_4K" >> include/config.mk; + @echo "MV_IMAGE_FLAGS += -DMV_BOOTSIZE_256K" >> include/config.mk; +else + @make mrproper; + @echo "" ; + @echo "** ERROR : Illegal TINY image configuration" ; + @echo "" ; + @echo "Legal values for TINY are :" ; + @echo "" ; + @echo "512K_64K, 16M_64K, 16M_128K, 256K_32K or 256K_4K" ; + @echo "" ; +endif +endif +endif +endif +endif +endif +endif +endif +endif +#============================= +# Summary of compilation flags +#============================= + @echo -e "CPPFLAGS += \044(MV_IMAGE_FLAGS) \044(MV_FLAGS)" >> include/config.mk; + + +######################################################################### +## END of Marvell Feroceon based Socs +######################################################################### DB64360_config: unconfig @./mkconfig DB64360 ppc 74xx_7xx db64360 Marvell @@ -1840,10 +2987,13 @@ clobber: clean | xargs -0 rm -f rm -f $(OBJS) *.bak tags TAGS rm -fr *.*~ + rm -f nboot nboot.dis nboot.map rm -f u-boot u-boot.map u-boot.hex $(ALL) + rm -f u-boot-${MV_OUTPUT} rm -f tools/crc32.c tools/environment.c tools/env/crc32.c rm -f tools/inca-swap-bytes cpu/mpc824x/bedbug_603e.c rm -f include/asm/proc include/asm/arch include/asm + rm -fR images/* mrproper \ distclean: clobber unconfig diff --git a/board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/glibc.so/readme.txt b/board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/glibc.so/readme.txt deleted file mode 100644 index 0d87eff..0000000 --- a/board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/glibc.so/readme.txt +++ /dev/null @@ -1 +0,0 @@ -This file is just to ensure that the directory is created. diff --git a/board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/libc.so/readme.txt b/board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/libc.so/readme.txt deleted file mode 100644 index 0d87eff..0000000 --- a/board/MAI/bios_emulator/scitech/lib/debug/linux/gcc/libc.so/readme.txt +++ /dev/null @@ -1 +0,0 @@ -This file is just to ensure that the directory is created. diff --git a/board/MAI/bios_emulator/scitech/lib/release/linux/gcc/glibc.so/readme.txt b/board/MAI/bios_emulator/scitech/lib/release/linux/gcc/glibc.so/readme.txt deleted file mode 100644 index 0d87eff..0000000 --- a/board/MAI/bios_emulator/scitech/lib/release/linux/gcc/glibc.so/readme.txt +++ /dev/null @@ -1 +0,0 @@ -This file is just to ensure that the directory is created. diff --git a/board/MAI/bios_emulator/scitech/lib/release/linux/gcc/libc.so/readme.txt b/board/MAI/bios_emulator/scitech/lib/release/linux/gcc/libc.so/readme.txt deleted file mode 100644 index 0d87eff..0000000 --- a/board/MAI/bios_emulator/scitech/lib/release/linux/gcc/libc.so/readme.txt +++ /dev/null @@ -1 +0,0 @@ -This file is just to ensure that the directory is created. diff --git a/board/MAI/bios_emulator/scitech/src/common/makefile b/board/MAI/bios_emulator/scitech/src/common/makefile index 5aac038..ee2ae91 100644 --- a/board/MAI/bios_emulator/scitech/src/common/makefile +++ b/board/MAI/bios_emulator/scitech/src/common/makefile @@ -7,7 +7,7 @@ # DPMSLib library files. Requires Borland C++ 4.52 to build # some components. # -# $Date: 2002/10/02 15:35:20 $ $Author: hfrieden $ +# $Date: 2008-12-15 11:39:22 $ $Author: wokes $ # ############################################################################# diff --git a/board/MAI/bios_emulator/scitech/src/pm/os2/dossctl.obj b/board/MAI/bios_emulator/scitech/src/pm/os2/dossctl.obj deleted file mode 100644 index 5533346410ec6f20314d8a61bb302753005160fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59 zcmZqRX5e(mFAlCOb}q?z(jmpruz-;fA;RI}AMEVt;}e|2e7}Q(;lRI;$FDQ3-*hoC HFq8lQPdgO> diff --git a/board/MAI/bios_emulator/scitech/src/pm/tests/vftest.c b/board/MAI/bios_emulator/scitech/src/pm/tests/vftest.c index b7e3bb7..aa06615 100644 --- a/board/MAI/bios_emulator/scitech/src/pm/tests/vftest.c +++ b/board/MAI/bios_emulator/scitech/src/pm/tests/vftest.c @@ -22,7 +22,7 @@ * ======================================================================== * * Filename: $Workfile$ -* Version: $Revision: 1.1 $ +* Version: $Revision: 1.1.1.1 $ * * Language: ANSI C * Environment: any @@ -33,7 +33,7 @@ * VF_init() * VF_exit() * -* $Date: 2002/10/02 15:35:21 $ $Author: hfrieden $ +* $Date: 2008-12-15 11:39:22 $ $Author: wokes $ * ****************************************************************************/ diff --git a/board/barco/barco.c b/board/barco/barco.c index becbd0a..e890797 100644 --- a/board/barco/barco.c +++ b/board/barco/barco.c @@ -2,13 +2,22 @@ * * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms * - * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/barco.c,v $ - * $Revision: 1.4 $ - * $Author: mleeman $ - * $Date: 2005/03/02 16:40:20 $ + * $Source: /home/cvsroot/NasX86/Others/bootldr/u-boot-1.1.4_mv-3.4.4/board/barco/barco.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: wokes $ + * $Date: 2008-12-15 11:39:23 $ * * Last ChangeLog Entry * $Log: barco.c,v $ + * Revision 1.1.1.1 2008-12-15 11:39:23 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:13 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:18 wokes + * marvell 88f6281 u-boot + * * Revision 1.4 2005/03/02 16:40:20 mleeman * remove empty labels (3.4 complains) * diff --git a/board/barco/barco_svc.h b/board/barco/barco_svc.h index 088f61e..80fec8b 100644 --- a/board/barco/barco_svc.h +++ b/board/barco/barco_svc.h @@ -2,13 +2,22 @@ * * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms * - * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/barco_svc.h,v $ - * $Revision: 1.2 $ - * $Author: mleeman $ - * $Date: 2005/02/21 12:48:58 $ + * $Source: /home/cvsroot/NasX86/Others/bootldr/u-boot-1.1.4_mv-3.4.4/board/barco/barco_svc.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: wokes $ + * $Date: 2008-12-15 11:39:23 $ * * Last ChangeLog Entry * $Log: barco_svc.h,v $ + * Revision 1.1.1.1 2008-12-15 11:39:23 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:13 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:18 wokes + * marvell 88f6281 u-boot + * * Revision 1.2 2005/02/21 12:48:58 mleeman * update of copyright years (feedback wd) * diff --git a/board/barco/flash.c b/board/barco/flash.c index 6cb19b7..b6ae665 100644 --- a/board/barco/flash.c +++ b/board/barco/flash.c @@ -2,13 +2,22 @@ * * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms * - * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/flash.c,v $ - * $Revision: 1.3 $ - * $Author: mleeman $ - * $Date: 2005/02/21 12:48:58 $ + * $Source: /home/cvsroot/NasX86/Others/bootldr/u-boot-1.1.4_mv-3.4.4/board/barco/flash.c,v $ + * $Revision: 1.1.1.1 $ + * $Author: wokes $ + * $Date: 2008-12-15 11:39:23 $ * * Last ChangeLog Entry * $Log: flash.c,v $ + * Revision 1.1.1.1 2008-12-15 11:39:23 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:13 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:18 wokes + * marvell 88f6281 u-boot + * * Revision 1.3 2005/02/21 12:48:58 mleeman * update of copyright years (feedback wd) * diff --git a/board/barco/speed.h b/board/barco/speed.h index 46860e8..f7302ba 100644 --- a/board/barco/speed.h +++ b/board/barco/speed.h @@ -2,13 +2,22 @@ * * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms * - * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/board/barco/speed.h,v $ - * $Revision: 1.2 $ - * $Author: mleeman $ - * $Date: 2005/02/21 12:48:58 $ + * $Source: /home/cvsroot/NasX86/Others/bootldr/u-boot-1.1.4_mv-3.4.4/board/barco/speed.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: wokes $ + * $Date: 2008-12-15 11:39:23 $ * * Last ChangeLog Entry * $Log: speed.h,v $ + * Revision 1.1.1.1 2008-12-15 11:39:23 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:13 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:18 wokes + * marvell 88f6281 u-boot + * * Revision 1.2 2005/02/21 12:48:58 mleeman * update of copyright years (feedback wd) * diff --git a/board/cray/L1/bootscript.hush b/board/cray/L1/bootscript.hush index ec4839b..31a2f22 100644 --- a/board/cray/L1/bootscript.hush +++ b/board/cray/L1/bootscript.hush @@ -1,4 +1,4 @@ -# $Header$ +# $Header: /home/cvsroot/NasX86/Others/bootldr/u-boot-1.1.4_mv-3.4.4/board/cray/L1/bootscript.hush,v 1.1.1.1 2008-12-15 11:39:23 wokes Exp $ # hush bootscript for PPCBOOT on L1 # note: all #s are in hex, do _NOT_ prefix it with 0x diff --git a/board/gth/ee_dev.h b/board/gth/ee_dev.h index 417c7b6..7003c0d 100644 --- a/board/gth/ee_dev.h +++ b/board/gth/ee_dev.h @@ -1,5 +1,5 @@ /* By Thomas.Lange@Corelatus.com 001025 - $Revision: 1.6 $ + $Revision: 1.1.1.1 $ Definitions for EEPROM/VOLT METER DS2438 Copyright (C) 2000-2001 Corelatus AB */ diff --git a/board/jse/host_bridge.c b/board/jse/host_bridge.c index 363be97..701a686 100644 --- a/board/jse/host_bridge.c +++ b/board/jse/host_bridge.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id:$" +#ident "$Id: host_bridge.c,v 1.1.1.1 2008-12-15 11:39:24 wokes Exp $" # include # include diff --git a/board/mv_feroceon/USP/ethSwitch/mv_switch.c b/board/mv_feroceon/USP/ethSwitch/mv_switch.c new file mode 100644 index 0000000..ff6c84f --- /dev/null +++ b/board/mv_feroceon/USP/ethSwitch/mv_switch.c @@ -0,0 +1,382 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvOs.h" +#include "mv_switch.h" +#include "eth-phy/mvEthPhy.h" +#include "mv_switchRegs.h" +#include "mvCtrlEnvLib.h" + + +static void switchVlanInit(MV_U32 ethPortNum, + MV_U32 switchCpuPort, + MV_U32 switchMaxPortsNum, + MV_U32 switchPortsOffset, + MV_U32 switchEnabledPortsMask); + + +/******************************************************************************* +* mvEthE6065_61PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6065_61SwitchBasicInit(MV_U32 ethPortNum) +{ + switchVlanInit(ethPortNum, + MV_E6065_CPU_PORT, + MV_E6065_MAX_PORTS_NUM, + MV_E6065_PORTS_OFFSET, + MV_E6065_ENABLED_PORTS); +} + +/******************************************************************************* +* mvEthE6063PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6063SwitchBasicInit(MV_U32 ethPortNum) +{ + switchVlanInit(ethPortNum, + MV_E6063_CPU_PORT, + MV_E6063_MAX_PORTS_NUM, + MV_E6063_PORTS_OFFSET, + MV_E6063_ENABLED_PORTS); +} + +/******************************************************************************* +* mvEthE6131PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6131SwitchBasicInit(MV_U32 ethPortNum) +{ + + MV_U16 reg; + + /*Enable Phy power up*/ + mvEthPhyRegWrite (0,0,0x9140); + mvEthPhyRegWrite (1,0,0x9140); + mvEthPhyRegWrite (2,0,0x9140); + + + /*Enable PPU*/ + mvEthPhyRegWrite (0x1b,4,0x4080); + + + /*Enable Phy detection*/ + mvEthPhyRegRead (0x13,0,®); + reg &= ~(1<<12); + mvEthPhyRegWrite (0x13,0,reg); + + mvOsDelay(100); + mvEthPhyRegWrite (0x13,1,0x33); + + + switchVlanInit(ethPortNum, + MV_E6131_CPU_PORT, + MV_E6131_MAX_PORTS_NUM, + MV_E6131_PORTS_OFFSET, + MV_E6131_ENABLED_PORTS); + +} + + +/******************************************************************************* +* mvEthE6161PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6161SwitchBasicInit(void) +{ + + MV_U32 prt; + MV_U16 reg; + volatile MV_U32 timeout; + + /* The 6161/5 needs a delay */ + mvOsDelay(100); + + /* Init vlan */ + switchVlanInit(0, + MV_E6161_CPU_PORT, + MV_E6161_MAX_PORTS_NUM, + MV_E6161_PORTS_OFFSET, + MV_E6161_ENABLED_PORTS); + + /* Enable RGMII delay on Tx and Rx for CPU port */ + mvEthPhyRegWrite (0x14,0x1a,0x81e7); + mvEthPhyRegRead (0x15,0x1a,®); + mvEthPhyRegWrite (0x15,0x1a,0x18); + mvEthPhyRegWrite (0x14,0x1a,0xc1e7); + + for(prt=0; prt < MV_E6161_MAX_PORTS_NUM; prt++) + { + if (prt != MV_E6161_CPU_PORT) + { + /*Enable Phy power up*/ + mvEthPhyRegWrite (MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_DATA, 0x3360); + mvEthPhyRegWrite (MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND, (0x9410 | (prt << 5))); + + /*Make sure SMIBusy bit cleared before another SMI operation can take place*/ + timeout = E6161_PHY_TIMEOUT; + do + { + mvEthPhyRegRead(MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND,®); + if(timeout-- == 0) + { + mvOsPrintf("mvEthPhyRegRead: SMI busy timeout\n"); + return; + } + }while (reg & E6161_PHY_SMI_BUSY_MASK); + + mvEthPhyRegWrite (MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_DATA,0x1140); + mvEthPhyRegWrite (MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND,(0x9400 | (prt << 5))); + + /*Make sure SMIBusy bit cleared before another SMI operation can take place*/ + timeout = E6161_PHY_TIMEOUT; + do + { + mvEthPhyRegRead(MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND,®); + if(timeout-- == 0) + { + mvOsPrintf("mvEthPhyRegRead: SMI busy timeout\n"); + return; + } + }while (reg & E6161_PHY_SMI_BUSY_MASK); + + } + + /*Enable port*/ + mvEthPhyRegWrite (MV_E6161_PORTS_OFFSET + prt, 4, 0x7f); + } + + /*Force CPU port to RGMII FDX 1000Base*/ + mvEthPhyRegWrite (MV_E6161_PORTS_OFFSET + MV_E6161_CPU_PORT, 1, 0x3e); +} + +static void switchVlanInit(MV_U32 ethPortNum, + MV_U32 switchCpuPort, + MV_U32 switchMaxPortsNum, + MV_U32 switchPortsOffset, + MV_U32 switchEnabledPortsMask) +{ + MV_U32 prt; + MV_U16 reg; + + /* be sure all ports are disabled */ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,®); + reg &= ~0x3; + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,reg); + + } + + /* Set CPU port VID to 0x1 */ + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VID_REG,®); + reg &= ~0xfff; + reg |= 0x1; + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VID_REG,reg); + + + /* Setting Port default priority for all ports to zero */ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,®); + reg &= ~0xc000; + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,reg); + } + + /* Setting VID and VID map for all ports except CPU port */ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + + /* only for enabled ports */ + if ((1 << prt)& switchEnabledPortsMask) + { + /* skip CPU port */ + if (prt== switchCpuPort) continue; + + /* + * set Ports VLAN Mapping. + * port prt <--> MV_SWITCH_CPU_PORT VLAN #prt+1. + */ + + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,®); + reg &= ~0x0fff; + reg |= (prt+1); + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,reg); + + + /* Set Vlan map table for all ports to send only to MV_SWITCH_CPU_PORT */ + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VMAP_REG,®); + reg &= ~((1 << switchMaxPortsNum) - 1); + reg |= (1 << switchCpuPort); + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VMAP_REG,reg); + } + + } + + + /* Set Vlan map table for MV_SWITCH_CPU_PORT to see all ports*/ + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VMAP_REG,®); + reg &= ~((1 << switchMaxPortsNum) - 1); + reg |= switchEnabledPortsMask & ~(1 << switchCpuPort); + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VMAP_REG,reg); + + + /*enable only appropriate ports to forwarding mode - and disable the others*/ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + + if ((1 << prt)& switchEnabledPortsMask) + { + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,®); + reg |= 0x3; + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,reg); + + } + else + { + /* Disable port */ + mvEthPhyRegRead (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,®); + reg &= ~0x3; + mvEthPhyRegWrite (mvBoardPhyAddrGet(ethPortNum)+ MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,reg); + + } + } + + + return; + +} + + + + + + diff --git a/board/mv_feroceon/USP/ethSwitch/mv_switch.h b/board/mv_feroceon/USP/ethSwitch/mv_switch.h new file mode 100644 index 0000000..0963316 --- /dev/null +++ b/board/mv_feroceon/USP/ethSwitch/mv_switch.h @@ -0,0 +1,75 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCETHSWITCHH +#define __INCETHSWITCHH + +#include "mvTypes.h" + +MV_VOID mvEthE6063SwitchBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE6065_61SwitchBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE6131SwitchBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE6161SwitchBasicInit(void); + +#endif /* #ifndef __INCETHSWITCHH */ diff --git a/board/mv_feroceon/USP/ethSwitch/mv_switchRegs.h b/board/mv_feroceon/USP/ethSwitch/mv_switchRegs.h new file mode 100644 index 0000000..0d5f80b --- /dev/null +++ b/board/mv_feroceon/USP/ethSwitch/mv_switchRegs.h @@ -0,0 +1,109 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCethswitchregsh +#define __INCethswitchregsh + +#define MV_SWITCH_PORT_CONTROL_REG 0x4 +#define MV_SWITCH_PORT_VMAP_REG 0x6 +#define MV_SWITCH_PORT_VID_REG 0x7 + + +#define MV_SWITCH_PORT_OFFSET(port) (switchPortsOffset+port) + +/* E6063 related */ +#define MV_E6063_CPU_PORT 5 +#define MV_E6063_PORTS_OFFSET 0x8 +#define MV_E6063_MAX_PORTS_NUM 7 +#define MV_E6063_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)| \ + (1 << 3)|(1 << 4)|(1 << 5)) + +/* E6065 related */ +#define MV_E6065_CPU_PORT 5 +#define MV_E6065_PORTS_OFFSET 0x8 +#define MV_E6065_MAX_PORTS_NUM 6 +#define MV_E6065_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)) + +/* E6063 related */ +#define MV_E6131_CPU_PORT 0x3 +#define MV_E6131_PORTS_OFFSET 0x10 +#define MV_E6131_MAX_PORTS_NUM 8 +#define MV_E6131_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)| \ + (1 << 3)|(1 << 5)|(1 << 7)) +/* E6161 related */ +#define MV_E6161_CPU_PORT 0x5 +#define MV_E6161_PORTS_OFFSET 0x10 +#define MV_E6161_SMI_PHY_COMMAND 0x18 +#define MV_E6161_SMI_PHY_DATA 0x19 +#define MV_E6161_GLOBAL_2_REG_DEV_ADDR 0x1C +#define MV_E6161_MAX_PORTS_NUM 6 +#define MV_E6161_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)) +#define E6161_PHY_TIMEOUT 10000 +#define E6161_PHY_SMI_BUSY_BIT 15 /* Busy */ +#define E6161_PHY_SMI_BUSY_MASK (1 << ETH_PHY_SMI_BUSY_BIT) + + + + +#endif /* __INCethswitchregsh */ diff --git a/board/mv_feroceon/USP/jump.S b/board/mv_feroceon/USP/jump.S new file mode 100644 index 0000000..e48a13f --- /dev/null +++ b/board/mv_feroceon/USP/jump.S @@ -0,0 +1,250 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#define MV_ASMLANGUAGE +#include "mvSysHwConfig.h" +#include "mvBoardEnvSpec.h" +#include "mvOsAsm.h" +#include "pci/mvPciRegs.h" +#include "pex/mvPexRegs.h" +#include "mvCtrlEnvSpec.h" +#include "mvCtrlEnvAsm.h" +#include "sys/mvCpuIfRegs.h" + + +jumpStart: + +.section ".reset_vector_sect",#alloc, #execinstr +#if defined(MV_88F6082) || defined(MV_88F6183) || defined(DB_88F5181_OLD) || defined(DB_FPGA) || \ + defined(MV88F6281) || defined(MV88F6192) || defined(MV88F6180) || defined(MV_88F6183L) || \ + defined(MV88F6190) +#if defined(__BE) + /* disable I-Cache */ + .word 0x100f11ee /* mrc 15, 0, r0, cr1, cr0, {0} */ + .word 0x010ac0e3 /* bic r0, r0, #4096 ; 0x1000 */ + .word 0x0700c0e3 /* bic r0, r0, #7 ; 0x7 */ + .word 0x020080e3 /* orr r0, r0, #2 ; 0x2 */ + .word 0x100f01ee /* mcr 15, 0, r0, cr1, cr0, {0} */ + /* disable L2 prefetch */ + .word 0x110f3fee /* mrc p15, 1, r0, c15, c1 */ + .word 0x010480e3 /* orr r0, r0, #(1<<24) */ + .word 0x110f2fee /* mcr p15, 1, r0, c15, c1 */ + /* convert CPU to big endian */ + .word 0x100f11ee /* mrc p15, 0, r0, c1, c0 */ + .word 0x800080e3 /* orr r0, r0, #0x80 */ + .word 0x100f01ee /* mcr p15, 0, r0, c1, c0 */ + nop;nop;nop;nop; + nop;nop;nop;nop; + +#endif +#endif + + /* Check if we booted from DRAM. If we did someone already */ + /* initialize the DRAM controller */ + + adr r4, jumpStart /* r4 <- current position of code */ + ldr r5, =~0xff + and r4, r4, r5 + ldr r5, __start /* r5 <- linker results for _start */ + ldr r2, _jumpStart /* r2 <- linker results reset vector */ + sub r8, r2, r5 /* r8 <- (reset vector address - start address) */ + sub r8, r4, r8 /* r8 <- absolute address to jump to */ + /* r8 <- (current code address - */ + ldr sp, =0 + ldr lr, =0 + ldr r5, =CFG_RESET_ADDRESS /* test if we run from flash or RAM */ + cmp r4, r5 /* don't reloc during debug */ + beq romBoot + + mov r5, #1 + ldr r4, =dramBoot + str r5, [r4] /* We started executing from DRAM */ +romBoot: + +#if defined(MV78200) +/* Setting the PEX header device ID for MV78200 */ + MV_DV_REG_READ_ASM(r6, r1, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID)) + ldr r1, =MV_78200_DEV_ID + ldr r2, =0xffff + and r6, r6, r2 + orr r6, r6, r1, LSL #PXDAVI_DEV_ID_OFFS + MV_DV_REG_WRITE_ASM(r6, r1, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID)) +#endif + +#if defined(MV_88F1181) + + /* set gpp out en */ + ldr r2, = 0xf33 + MV_DV_REG_WRITE_ASM(r1, r1, 0x10104) + + /* turn on debug led to 2 */ + ldr r2, = 0x8 + MV_DV_REG_WRITE_ASM(r1, r1, 0x10100) + + ldr pc, = 0xfff90000 + +#else + +#if defined(DB_FPGA) + b device_cont +#endif /* DB_FPGA */ + + /* Read device ID */ + MV_DV_CTRL_MODEL_GET_ASM(r6, r1); + ldr r1, =0x5281 + cmp r6, r1 + beq device_5281 + + /* TC90 acts as Orion 2 C0 */ + ldr r1, =0x1281 + cmp r6, r1 + beq device_5281_C0 + + + /* 6183 & 6183L */ + ldr r1, =0x6183 + cmp r6, r1 + bne device_cont + +#if defined(MV_88F6183L) +/* Setting the PEX header device ID for 6183L */ + MV_DV_REG_READ_ASM(r6, r1, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID)) + ldr r1, =MV_6183L_DEV_ID + ldr r2, =0xffff + and r6, r6, r2 + orr r6, r6, r1, LSL #PXDAVI_DEV_ID_OFFS + MV_DV_REG_WRITE_ASM(r6, r1, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID)) +#endif /* MV_88F6183L */ + + + /* Read device revision */ + MV_DV_CTRL_REV_GET_ASM(r6, r1); + cmp r6, #0x3 /* 6183 == B0 */ + bne device_cont + +#if !defined(MV78XX0) + MV_DV_REG_READ_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) + ldr r1, =0x10000 + orr r6, r6, r1 + MV_DV_REG_WRITE_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) +#endif + + b device_cont + +device_5281: + + /* Read device revision */ + MV_DV_CTRL_REV_GET_ASM(r6, r1); + cmp r6, #0x0 /* Orion 2 == A0 */ + beq device_5281_A0 + + cmp r6, #0x1 /* Orion 2 == B0 */ + beq device_5281_B0 + + cmp r6, #0x2 /* Orion 2 == C0 */ + beq device_5281_C0 + + cmp r6, #0x4 /* Orion 2 == d0 */ + beq device_5281_D0 + + cmp r6, #0x5 /* Orion 2 == d1 */ + beq device_5281_D1 + + cmp r6, #0x6 /* Orion 2 == d2 */ + beq device_5281_D2 + + b device_cont + +device_5281_D0: +device_5281_D1: +device_5281_D2: +#if !defined(MV78XX0) + MV_DV_REG_READ_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) + + ldr r1, =0xFFFF8080 + and r6, r6, r1 + ldr r1, =0x1902 + orr r6, r6, r1 + + MV_DV_REG_WRITE_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) +#endif + b device_cont + +device_5281_C0: +#if !defined(MV78XX0) + MV_DV_REG_READ_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) + + ldr r1, =0xFFFF8080 + and r6, r6, r1 + ldr r1, =0x8308 + orr r6, r6, r1 + + MV_DV_REG_WRITE_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) +#endif + b device_cont + +device_5281_B0: +#if !defined(MV78XX0) + MV_DV_REG_READ_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) + + ldr r1, =0xFFFF8080 + and r6, r6, r1 + ldr r1, =0x821b + orr r6, r6, r1 + + MV_DV_REG_WRITE_ASM (r6, r1, CPU_FTDLL_CONFIG_REG) +#endif + b device_cont +device_5281_A0: +device_cont: + +#if defined(MV88F6190) +/* Setting the PEX header device ID for 6190 */ + MV_DV_REG_READ_ASM(r6, r1, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID)) + ldr r1, =MV_6190_DEV_ID + ldr r2, =0xffff + and r6, r6, r2 + orr r6, r6, r1, LSL #PXDAVI_DEV_ID_OFFS + MV_DV_REG_WRITE_ASM(r6, r1, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID)) +#endif /* MV_88F6190 */ + + mov lr, r8 + mov pc, lr + +#endif + + +__start: + .word _start + +.globl dramBoot +dramBoot: + .word 0 + +_jumpStart: + .word .reset_vector_sect + +.section ".dummy",#alloc, #execinstr + .long 0xffffffff + .long 0xffffffff + .long 0xffffffff + .long 0xffffffff + + diff --git a/board/mv_feroceon/USP/mv_egiga.c b/board/mv_feroceon/USP/mv_egiga.c new file mode 100644 index 0000000..52a1bb3 --- /dev/null +++ b/board/mv_feroceon/USP/mv_egiga.c @@ -0,0 +1,550 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include +#include + +#if defined (MV_INCLUDE_GIG_ETH) +#include "sys/mvSysGbe.h" +#include "mvOs.h" +#include "mvSysHwConfig.h" +#include "eth/mvEth.h" +#include "eth/gbe/mvEthGbe.h" +#include "eth-phy/mvEthPhy.h" +#include "ethswitch/mvSwitch.h" +#include "mvBoardEnvLib.h" + +/* #define MV_DEBUG */ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +/****************************************************** + * driver internal definitions -- * + ******************************************************/ +/* use only tx-queue0 and rx-queue0 */ +#define EGIGA_DEF_TXQ 0 +#define EGIGA_DEF_RXQ 0 + +/* rx buffer size */ +#define ETH_HLEN 14 +#define WRAP (2 + ETH_HLEN + 4 + 32) /* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch)*/ +#define MTU 1500 +#define RX_BUFFER_SIZE (MTU + WRAP) + +/* rings length */ +#define EGIGA_TXQ_LEN 20 +#define EGIGA_RXQ_LEN 20 + + +typedef struct _egigaPriv +{ + int port; + MV_VOID *halPriv; + MV_U32 rxqCount; + MV_U32 txqCount; + MV_BOOL devInit; +} egigaPriv; + + + +/****************************************************** + * functions prototype -- * + ******************************************************/ +static int mvEgigaLoad( int port, char *name, char *enet_addr ); + +static int mvEgigaInit( struct eth_device *dev, bd_t *p ); +static int mvEgigaHalt( struct eth_device *dev ); +static int mvEgigaTx( struct eth_device *dev, volatile MV_VOID *packet, int len ); +static int mvEgigaRx( struct eth_device *dev ); + +static MV_PKT_INFO* mvEgigaRxFill(MV_VOID); + + + +/*********************************************************** + * mv_eth_initialize -- * + * main driver initialization. loading the interfaces. * + ***********************************************************/ +int mv_eth_initialize( bd_t *bis ) +{ + + int port; + MV_8 *enet_addr; + MV_8 name[NAMESIZE+1]; + MV_8 enetvar[9]; + MV_8 ethPortNum = mvCtrlEthMaxPortGet(); + MV_U32 ctrlId = mvCtrlModelGet(); + + mvEthInit(); + + /* load interface(s) */ + for( port = BOARD_ETH_START_PORT_NUM; port < ethPortNum; port++ ) + { + if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) continue; + + + /* interface name */ + sprintf( name, "egiga%d", port ); + /* interface MAC addr extract */ + sprintf( enetvar, port ? "eth%daddr" : "ethaddr", port ); + enet_addr = getenv( enetvar ); + + if ( (MV_78100_DEV_ID == ctrlId) || (MV_78200_DEV_ID == ctrlId) || + (MV_6281_DEV_ID == ctrlId) || (MV_6192_DEV_ID == ctrlId) || + (MV_6190_DEV_ID == ctrlId) || (MV_6180_DEV_ID == ctrlId)) + mvEthPortPowerUp(port); + + MV_REG_WRITE(ETH_TX_QUEUE_COMMAND1_REG(port), 0x8); + mvEgigaLoad( port, name, enet_addr ); + } + +#ifdef RD_MV78XX0_AMC + /* Light on RDY led */ + mvEthPhyRegWrite(0, 0xb, 0x19, 0xc00); +#endif + return 0; +} + + +/*********************************************************** + * mvEgigaLoad -- * + * load a network interface into uboot network core. * + * initialize sw structures e.g. private, rings, etc. * + ***********************************************************/ +static int mvEgigaLoad( int port, char *name, char *enet_addr ) +{ + struct eth_device *dev = NULL; + egigaPriv *priv = NULL; + ETH_PORT_CTRL dummy_port_handle; + + DB( printf( "%s: %s load - ", __FUNCTION__, name ) ); + + + + dev = malloc( sizeof(struct eth_device) ); + priv = malloc( sizeof(egigaPriv) ); + + if( !dev ) { + DB( printf( "%s: %s falied to alloc eth_device (error)\n", __FUNCTION__, name ) ); + goto error; + } + + if( !priv ) { + DB( printf( "%s: %s falied to alloc egiga_priv (error)\n", __FUNCTION__, name ) ); + goto error; + } + + memset( priv, 0, sizeof(egigaPriv) ); + + /* init device methods */ + memcpy( dev->name, name, NAMESIZE ); + mvMacStrToHex(enet_addr, (MV_8 *)(dev->enetaddr)); + + /* set MAC addres even if port was not used yet. */ + dummy_port_handle.portNo = port; + mvEthMacAddrSet( &dummy_port_handle, dev->enetaddr, EGIGA_DEF_RXQ); + + dev->init = (void *)mvEgigaInit; + dev->halt = (void *)mvEgigaHalt; + dev->send = (void *)mvEgigaTx; + dev->recv = (void *)mvEgigaRx; + dev->priv = priv; + dev->iobase = 0; + priv->port = port; + + /* register the interface */ + eth_register(dev); + + + DB( printf( "%s: %s load ok\n", __FUNCTION__, name ) ); + return 0; + + error: + printf( "%s: %s load failed\n", __FUNCTION__, name ); + if( priv ) free( dev->priv ); + if( dev ) free( dev ); + return -1; +} + + +static MV_PKT_INFO* mvEgigaRxFill(MV_VOID) +{ + MV_BUF_INFO *pBufInfo; + MV_PKT_INFO *pPktInfo; + MV_U8 *buf = (MV_U8 *)memalign( 32, RX_BUFFER_SIZE ); /* align on 32B */ + if( !buf ) { + DB(printf("failed to alloc buffer\n")); + return NULL; + } + + if( ((MV_U32)buf) & 0xf ) + printf( "un-align rx buffer %x\n", (MV_U32)buf ); + + pPktInfo = malloc(sizeof(MV_PKT_INFO)); + if (pPktInfo == NULL) { + printf("Error: cannot allocate memory for pktInfo\n"); + free(buf); + return NULL; + } + + pBufInfo = malloc(sizeof(MV_BUF_INFO)); + if (pBufInfo == NULL) { + printf("Error: cannot allocate memory for bufInfo\n"); + free(buf); + free(pPktInfo); + return NULL; + } + pBufInfo->bufPhysAddr = mvOsIoVirtToPhy(NULL, buf); + pBufInfo->bufVirtPtr = buf; + pBufInfo->bufSize = RX_BUFFER_SIZE; + pBufInfo->dataSize = 0; + pPktInfo->osInfo = (MV_ULONG)buf; + pPktInfo->pFrags = pBufInfo; + pPktInfo->pktSize = RX_BUFFER_SIZE; /* how much to invalidate */ + pPktInfo->numFrags = 1; + pPktInfo->status = 0; + pPktInfo->srcIdx = -1; + return pPktInfo; +} + + +unsigned int egiga_init=0; + +static int mvEgigaInit( struct eth_device *dev, bd_t *p ) +{ + egigaPriv *priv = dev->priv; + MV_ETH_PORT_INIT halInitStruct; + MV_PKT_INFO *pktInfo; + MV_STATUS status; + int i; + + DB( printf( "%s: %s init - ", __FUNCTION__, dev->name ) ); + + /* egiga not ready */ + DB( printf ("mvBoardPhyAddrGet()=0x%x , priv->port =0x%x\n",mvBoardPhyAddrGet(priv->port),priv->port)); + + /* If speed is not auto then link is force */ + if (BOARD_MAC_SPEED_AUTO == mvBoardMacSpeedGet(priv->port)) + { + /* Check Link status on phy */ + if( mvEthPhyCheckLink( mvBoardPhyAddrGet(priv->port) ) == MV_FALSE ) { + printf( "%s no link\n", dev->name ); + return 0; + } + else DB( printf( "link up\n" ) ); + } + + egiga_init = 1; + + /* init the hal -- create internal port control structure and descriptor rings, */ + /* open address decode windows, disable rx and tx operations. mask interrupts. */ + halInitStruct.maxRxPktSize = RX_BUFFER_SIZE; + halInitStruct.rxDefQ = EGIGA_DEF_RXQ; + + halInitStruct.txDescrNum[0] = EGIGA_TXQ_LEN; + halInitStruct.rxDescrNum[0] = EGIGA_RXQ_LEN; + halInitStruct.osHandle = NULL; + + priv->halPriv = mvEthPortInit( priv->port, &halInitStruct ); + + if( !priv->halPriv ) { + DB( printf( "falied to init eth port (error)\n" ) ); + goto error; + } + + /* set new addr in hw */ + if( mvEthMacAddrSet( priv->halPriv, dev->enetaddr, EGIGA_DEF_RXQ) != MV_OK ) { + printf("%s: ethSetMacAddr failed\n", dev->name ); + goto error; + } + + priv->devInit = MV_TRUE; + + /* fill rx ring with buffers */ + for( i=0; ihalPriv, EGIGA_DEF_RXQ, pktInfo ); + if( status == MV_OK ) { + priv->rxqCount++; + } + else if( status == MV_FULL ) { + /* the ring is full */ + priv->rxqCount++; + DB( printf( "ring full\n" ) ); + break; + } + else { + printf( "error\n" ); + goto error; + } + } + +#ifdef MV_DEBUG + ethPortQueues(priv->port, EGIGA_DEF_RXQ, EGIGA_DEF_TXQ, 1); + + printf("%s : after calling ethPortQueues\n",__FUNCTION__); + +#endif + + + /* start the hal - rx/tx activity */ + /* Check if link is up for 2 Sec */ + for (i = 1; i < 100 ; i ++) + { + status = mvEthPortEnable( priv->halPriv ); + if (status == MV_OK) + break; + mvOsDelay(20); + } + + if( status != MV_OK ) { + printf( "%s: %s mvEthPortEnable failed (error)\n", __FUNCTION__, dev->name ); + goto error; + } + +#ifdef MV_DEBUG + ethRegs(priv->port); + ethPortRegs(priv->port); + ethPortStatus(priv->port); + + ethPortQueues(priv->port, EGIGA_DEF_RXQ, -1/*EGIGA_DEF_TXQ*/, 0); +#endif + + DB( printf( "%s: %s complete ok\n", __FUNCTION__, dev->name ) ); + return 1; + + error: + if( priv->devInit ) + mvEgigaHalt( dev ); + printf( "%s: %s failed\n", __FUNCTION__, dev->name ); + return 0; +} + +static int mvEgigaHalt( struct eth_device *dev ) +{ + + egigaPriv *priv = dev->priv; + MV_PKT_INFO *pktInfo; + + DB( printf( "%s: %s halt - ", __FUNCTION__, dev->name ) ); + if( priv->devInit == MV_TRUE ) { + + /* stop the port activity, mask all interrupts */ + if( mvEthPortDisable( priv->halPriv ) != MV_OK ) + printf( "mvEthPortDisable failed (error)\n" ); + + /* free the buffs in the rx ring */ + while( (pktInfo = mvEthPortForceRx( priv->halPriv, EGIGA_DEF_RXQ )) != NULL ) { + priv->rxqCount--; + if( pktInfo->osInfo ) + free( (void *)pktInfo->osInfo ); + else + printf( "mvEthPortForceRx failed (error)\n" ); + if( pktInfo->pFrags ) + free( (void *)pktInfo->pFrags ); + else + printf( "mvEthPortForceRx failed (error)\n" ); + free( (void *)pktInfo ); + } + + /* Clear Cause registers (must come before mvEthPortFinish) */ + MV_REG_WRITE(ETH_INTR_CAUSE_REG(((ETH_PORT_CTRL*)(priv->halPriv))->portNo),0); + MV_REG_WRITE(ETH_INTR_CAUSE_EXT_REG(((ETH_PORT_CTRL*)(priv->halPriv))->portNo),0); + + mvEthPortFinish( priv->halPriv ); + priv->devInit = MV_FALSE; + + } + egiga_init = 0; + + DB( printf( "%s: %s complete\n", __FUNCTION__, dev->name ) ); + return 0; +} + +static int mvEgigaTx( struct eth_device *dev, volatile void *buf, int len ) +{ + egigaPriv *priv = dev->priv; + MV_BUF_INFO bufInfo; + MV_PKT_INFO pktInfo; + MV_PKT_INFO *pPktInfo; + MV_STATUS status; + + DB( printf( "mvEgigaTx start\n" ) ); + /* if no link exist */ + if(!egiga_init) return 0; + + + pktInfo.osInfo = (MV_ULONG)0x44CAFE44; + pktInfo.pktSize = len; + pktInfo.pFrags = &bufInfo; + pktInfo.status = 0; + pktInfo.numFrags = 1; + bufInfo.bufVirtPtr = (MV_U8*)buf; + bufInfo.bufPhysAddr = mvOsIoVirtToPhy(NULL, buf); + bufInfo.dataSize = len; + + /* send the packet */ + status = mvEthPortTx( priv->halPriv, EGIGA_DEF_TXQ, &pktInfo ); + + if( status != MV_OK ) { + if( status == MV_NO_RESOURCE ) + DB( printf( "ring is full (error)\n" ) ); + else if( status == MV_ERROR ) + printf( "error\n" ); + else + printf( "unrecognize status (error) ethPortSend\n" ); + goto error; + } + else DB( printf( "ok\n" ) ); + + priv->txqCount++; + + /* release the transmitted packet(s) */ + while( 1 ) { + + DB( printf( "%s: %s tx-done - ", __FUNCTION__, dev->name ) ); + + /* get a packet */ + pPktInfo = mvEthPortTxDone( priv->halPriv, EGIGA_DEF_TXQ); + + if( pPktInfo != NULL ) { + + priv->txqCount--; + + /* validate skb */ + if( (pPktInfo != &pktInfo) || (pPktInfo->osInfo != 0x44CAFE44 ) ) { + printf( "error\n" ); + goto error; + } + + /* handle tx error */ + if( pPktInfo->status & (ETH_ERROR_SUMMARY_BIT) ) { + printf( "bad status (error)\n" ); + goto error; + } + DB( printf( "ok\n" ) ); + break; + } + else + DB(printf( "NULL pPktInfo\n" )); + } + + DB( printf( "%s: %s complete ok\n", __FUNCTION__, dev->name ) ); + return 0; + + error: + printf( "%s: %s failed\n", __FUNCTION__, dev->name ); + return 1; +} + + +static int mvEgigaRx( struct eth_device *dev ) +{ + egigaPriv* priv = dev->priv; + MV_PKT_INFO *pktInfo; + MV_STATUS status; + + /* if no link exist */ + if(!egiga_init) return 0; + + while( 1 ) { + + /* get rx packet from hal */ + pktInfo = mvEthPortRx( priv->halPriv, EGIGA_DEF_RXQ); + + if( pktInfo != NULL ) { + /*DB( printf( "good rx\n" ) );*/ + priv->rxqCount--; + + /* check rx error status */ + if( pktInfo->status & (ETH_ERROR_SUMMARY_MASK) ) { + MV_U32 err = pktInfo->status & ETH_RX_ERROR_CODE_MASK; + /*DB( printf( "bad rx status %08x, ", (MV_U32)pktInfo->cmdSts ) );*/ + if( err == ETH_RX_RESOURCE_ERROR ) + DB( printf( "(resource error)" ) ); + else if( err == ETH_RX_MAX_FRAME_LEN_ERROR ) + DB( printf( "(max frame length error)" ) ); + else if( err == ETH_RX_OVERRUN_ERROR ) + DB( printf( "(overrun error)" ) ); + else if( err == ETH_RX_CRC_ERROR ) + DB( printf( "(crc error)" ) ); + else { + DB( printf( "(unknown error)" ) ); + goto error; + } + DB( printf( "\n" ) ); + } + else { + + DB( printf( "%s: %s calling NetRecieve ", __FUNCTION__, dev->name) ); + DB( printf( "%s: calling NetRecieve pkInfo = 0x%x\n", __FUNCTION__, pktInfo) ); + DB( printf( "%s: calling NetRecieve osInfo = 0x%x\n", __FUNCTION__, pktInfo->osInfo) ); + DB( printf( "%s: calling NetRecieve pktSize = 0x%x\n", __FUNCTION__, pktInfo->pFrags->dataSize) ); + /* good rx - push the packet up (skip on two first empty bytes) */ + NetReceive( ((MV_U8 *)pktInfo->osInfo) + 2, (int)pktInfo->pFrags->dataSize); + } + + + DB( printf( "%s: %s refill rx buffer - ", __FUNCTION__, dev->name) ); + + /* give the buffer back to hal (re-init the buffer address) */ + pktInfo->pktSize = RX_BUFFER_SIZE; /* how much to invalidate */ + status = mvEthPortRxDone( priv->halPriv, EGIGA_DEF_RXQ, pktInfo ); + + if( status == MV_OK ) { + priv->rxqCount++; + } + else if( status == MV_FULL ) { + /* this buffer made the ring full */ + priv->rxqCount++; + DB( printf( "ring full\n" ) ); + break; + } + else { + printf( "error\n" ); + goto error; + } + + } else { + /* no more rx packets ready */ + /* DB( printf( "no more work\n" ) ); */ + break; + } + } + + /*DB( printf( "%s: %s complete ok\n", __FUNCTION__, dev->name ) );*/ + return 0; + + error: + DB( printf( "%s: %s failed\n", __FUNCTION__, dev->name ) ); + return 1; +} + +#endif /* #if defined (MV_INCLUDE_GIG_ETH) */ diff --git a/board/mv_feroceon/USP/mv_ext2_boot.c b/board/mv_feroceon/USP/mv_ext2_boot.c new file mode 100644 index 0000000..87c6841 --- /dev/null +++ b/board/mv_feroceon/USP/mv_ext2_boot.c @@ -0,0 +1,189 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include "xor/mvXor.h" + + +#if ((CONFIG_COMMANDS & CFG_CMD_IDE ) && (CONFIG_COMMANDS & CFG_CMD_EXT2)) + +#define DOS_PART_MAGIC_OFFSET 0x1fe +#define PARTITION_CRC_OFF 0x0 +#ifdef CONFIG_ISO_PARTITION +/* Make the buffers bigger if ISO partition support is enabled -- CD-ROMS + have 2048 byte blocks */ +#define DEFAULT_SECTOR_SIZE 2048 +#else +#define DEFAULT_SECTOR_SIZE 512 +#endif + +#define MAX_BOOT_PART 2 + +extern block_dev_desc_t * ide_get_dev(int dev); + +static char tmp_string[100]; +static char tmp_string1[100]; + +int do_bootext2 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + int dev,part,active_part= -1 ; + ulong addr; + volatile disk_partition_t info[2]; + volatile char *env,*env2; + block_dev_desc_t *dev_desc; + ulong boot_part[MAX_BOOT_PART]; + char *ep; + + if (argc != 5) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + dev = simple_strtoul(argv[1], &ep, 16); + if (*ep) { + if (*ep != ':') + { + printf ("Usage:\n%s\n", cmdtp->usage); + return(1); + } + + for (part=0 ; part < MAX_BOOT_PART-1 ; part++) + { + ep++; + boot_part[part] = (ulong)simple_strtoul(ep, &ep, 16); + if (*ep != ',') { + printf ("Usage:\n%s\n", cmdtp->usage); + return(1); + } + + } + boot_part[part] = (ulong)simple_strtoul(++ep, NULL, 16); + + } + else + { + puts ("\n** Invalid boot device, use `dev:boot_part1,boot_part2' **\n"); + return(1); + } + + addr = simple_strtoul(argv[2], NULL, 16); + + dev_desc = (dev >= CFG_IDE_MAXDEVICE) ? NULL : ide_get_dev(dev); + + if (dev_desc == NULL) + { + printf("Non valid dev number %x\n",dev); + return 1; + } + + + /* Initialize IDE */ + sprintf(tmp_string,"ide reset"); + run_command(tmp_string,0); + + + /* Search for Active partition in partition #1 and partition #2*/ + for (part = 0; part < MAX_BOOT_PART ;part++ ) + { + if (get_partition_info (dev_desc, + boot_part[part], + (disk_partition_t*)&info[part])) + { + continue; + } + + if (info[part].boot_ind ) + { + active_part = part; + break; + } + } + + /* If no active partition then return */ + if (active_part == -1) + { + printf("No active partition on %d and %d\n", + boot_part[0],boot_part[1]); + return 1; + } + + /* Load /boot/uImage from active_part to addr */ + sprintf(tmp_string,"ext2load ide %x:%x %x %s", dev, boot_part[active_part], addr,argv[3]); + printf("%s\n",tmp_string); + run_command(tmp_string,0); + + sprintf(tmp_string,"root=%s%d ro",argv[4],boot_part[active_part]); + setenv("bootargs_root",tmp_string); + + env = getenv("bootargs"); + env2 = getenv("bootargs_root"); + /* Save bootargs for secondary boot option if boot from active partition will fail */ + sprintf(tmp_string1,"%s",env); + sprintf(tmp_string,"%s %s",env,env2); + setenv("bootargs",tmp_string); + + sprintf(tmp_string,"bootm %x", addr); + + printf("%s\n",tmp_string); + run_command(tmp_string,0); + + /* If we get here then first boot fail */ + active_part = (active_part + 1)%MAX_BOOT_PART; + + sprintf(tmp_string,"ext2load ide %x:%x %x %s", dev, boot_part[active_part], addr,argv[3]); + printf("%s\n",tmp_string); + run_command(tmp_string,0); + + sprintf(tmp_string,"root=%s%d ro",argv[4],boot_part[active_part]); + setenv("bootargs_root",tmp_string); + env2 = getenv("bootargs_root"); + sprintf(tmp_string,"%s %s %s",tmp_string1,env2, "boot_failure"); + setenv("bootargs",tmp_string); + + sprintf(tmp_string,"bootm %x", addr); + + printf("Starting secondary boot...\n"); + printf("%s\n",tmp_string); + run_command(tmp_string,0); + printf("Secondary boot fail...\n"); + return 1; +} + +U_BOOT_CMD( + bootext2, 5, 0, do_bootext2, + "bootext2 dev:boot_part1,boot_part2 addr boot_image linux_dev_name \n", + "dev:boot_part1,boot_part2 addr boot_image linux_dev_name\n" + "- boot boot_image from active ext2 partition\n" +); + + +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_EXT2 & CFG_CMD_IDE) */ + + + diff --git a/board/mv_feroceon/USP/mv_flash.c b/board/mv_feroceon/USP/mv_flash.c new file mode 100644 index 0000000..d4cb150 --- /dev/null +++ b/board/mv_feroceon/USP/mv_flash.c @@ -0,0 +1,1684 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) +#include +#include "norflash/mvFlash.h" +#include "device/mvDeviceRegs.h" +#include "mvBoardEnvSpec.h" + +#include "mvOs.h" +#include "mvCtrlEnvLib.h" +#include "mvSysHwConfig.h" +#include "mvCpuIf.h" + +#if defined (MV_INCLUDE_INTEG_MFLASH) +#include "mvMFlash.h" +#include "mvMFlashSpec.h" +#include "mvSMFlash.h" +#include "mvPMFlash.h" +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) +#include "sflash/mvSFlash.h" +#endif + +/* #define MV_DEBUG */ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +#define FLASH_ROM 0xFFFD /* unknown flash type */ +#define FLASH_RAM 0xFFFE /* unknown flash type */ +#define FLASH_MAN_UNKNOWN 0xFFFF0000 +#define NL_HASHES_PER_LINE 65 + +#define CFI_CMDSET_INTEL_EXTENDED 1 +#define CFI_CMDSET_AMD_STANDARD 2 +#define CFI_CMDSET_INTEL_STANDARD 3 +#define CFI_CMDSET_AMD_EXTENDED 4 + +void flashInfoCopy(flash_info_t *flash_info, MV_FLASH_INFO *pFlash); +MV_U32 getMvFlashInfoNum(flash_info_t *flash_info); +MV_FLASH_INFO* getMvFlashInfo(int index); +int mv_flash_real_protect(flash_info_t *info, long sector, int prot); +int mv_flash_real_protect_bank(flash_info_t *info, int prot); +#if defined (MV_INCLUDE_INTEG_MFLASH) +void mflash_print_info (MV_MFLASH_INFO * pInfo); +unsigned long mflash_init (MV_MFLASH_INFO * mflInfo); +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) +void sflash_print_info (MV_SFLASH_INFO * pInfo); +unsigned long sflash_init (MV_SFLASH_INFO * sflInfo); +#endif + +/* use CFG_MAX_FLASH_BANKS_DETECT if defined */ +#ifdef CFG_MAX_FLASH_BANKS_DETECT +static MV_FLASH_INFO mvFlashInfo[CFG_MAX_FLASH_BANKS_DETECT]; +extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */ +extern int mv_board_num_flash_banks; +#else +static MV_FLASH_INFO mvFlashInfo[CFG_MAX_FLASH_BANKS]; +extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ +#endif + +/* Static Variables */ +#if defined (MV_INCLUDE_INTEG_MFLASH) +static MV_MFLASH_INFO mflash; +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) +static MV_SFLASH_INFO sflash = {0x0, 0, 0, 0, 0, 0, MV_INVALID_DEVICE_NUMBER}; +#endif + +static unsigned long norFlashBanksNum = 0; +static unsigned long mFlashBanksNum = 0; +static unsigned long sFlashBanksNum = 0; + +typedef enum +{ + MV_UNKNOWN_FLASH = 0, + MV_NOR_FLASH, + MV_MARVELL_FLASH, + MV_SPI_FLASH +} MV_FLASH_TYPE; + +/* return NULL in case didn't find a matching mvFlashInfo */ +MV_FLASH_INFO* getMvFlashInfo(int index) +{ + if (CFG_MAX_FLASH_BANKS < index) + return NULL; + return &mvFlashInfo[index]; +} + +/* based on index get the type of flash */ +static MV_FLASH_TYPE mvFlashTypeFromIndexGet(MV_U32 indx) +{ + if ((indx >= 0) && (indx < norFlashBanksNum)) + return MV_NOR_FLASH; + else if ((indx >= norFlashBanksNum) && \ + (indx < (norFlashBanksNum + mFlashBanksNum))) + return MV_MARVELL_FLASH; + else if ((indx >= (norFlashBanksNum + mFlashBanksNum)) && + (indx < (norFlashBanksNum + mFlashBanksNum + sFlashBanksNum))) + return MV_SPI_FLASH; + + return MV_UNKNOWN_FLASH; +} + +/* return 0xFFFFFFFF in case didn't find a matching mvFlashInfo */ +MV_U32 +getMvFlashInfoNum(flash_info_t * pFlash_info) +{ + MV_U32 i; + + DB(mvOsPrintf("%s\n", __FUNCTION__)); + if( pFlash_info->flash_id == FLASH_UNKNOWN ) + { + DB(printf("%s : ERROR didn't find mvFlashInfo matching to flash_info_t.\n", __FUNCTION__)); + return 0xFFFFFFFF; + } + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) + { + if (&flash_info[i] == pFlash_info) + { + DB(printf("getMvFlashInfoNum found mvFlashInfo %d \n",i)); + return i; + } + DB(mvOsPrintf(" %x %x \n",mvFlashBaseAddrGet(&mvFlashInfo[i]), mvFlashVenIdGet(&mvFlashInfo[i]))); + } + + DB(mvOsPrintf("%s(%d): ERROR didn't find mvFlashInfo matching to flash_info_t.\n", __FUNCTION__)); + + return 0xFFFFFFFF; +} + + +/* make sure that #define CFG_FLASH_PROTECTION present in MV64xx.h */ + +int +mv_flash_real_protect(flash_info_t *info, long sector, int prot) +{ + MV_U32 s; + s = getMvFlashInfoNum(info); + if(s >= CFG_MAX_FLASH_BANKS) + { + DB(printf("mv_flash_real_protect illegal mvFlashInfo \n")); + return 1; + } + + switch(mvFlashTypeFromIndexGet(s)) + { +#if defined (MV_INC_BOARD_NOR_FLASH) + case MV_NOR_FLASH: + if( mvFlashSecLockSet(&mvFlashInfo[s],sector,prot) != MV_OK) + return 1; /* Write was not completed */ + info->protect[sector] = prot; + break; +#endif + +#if defined (MV_INCLUDE_INTEG_MFLASH) + case MV_MARVELL_FLASH: + /* printf("MFlash WP modification per sector is not supported by this command!!\n"); */ + if(mv_flash_real_protect_bank(info, prot) != MV_OK) + return 1; + break; +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) + case MV_SPI_FLASH: + /* printf("SPI Flash WP modification per sector is not supported by this command!!\n"); */ + if(mv_flash_real_protect_bank(info, prot) != MV_OK) + return 1; + break; +#endif + + default: + return 1; + } + + return 0; /* write completed succefully */ +} + +int +mv_flash_real_protect_bank(flash_info_t *info, int prot) +{ + MV_U32 s; + MV_U32 i; + s = getMvFlashInfoNum(info); + if(s >= CFG_MAX_FLASH_BANKS) + { + DB(printf("mv_flash_real_protect_bank illegal mvFlashInfo \n")); + return 1; + } + + switch(mvFlashTypeFromIndexGet(s)) + { +#if defined (MV_INC_BOARD_NOR_FLASH) + case MV_NOR_FLASH: + for (i=0; isector_count; ++i) + { + if( mvFlashSecLockSet(&mvFlashInfo[s],i,prot) != MV_OK) + return 1; /* Write was not completed */ + + info->protect[i] = prot; + putc ('.'); + } + break; +#endif + +#if defined (MV_INCLUDE_INTEG_MFLASH) + case MV_MARVELL_FLASH: + if (mvMFlashWriteProtectSet(&mflash, prot) != MV_OK) + return 1; + + for (i=0; isector_count; ++i) + { + info->protect[i] = prot; +/* putc ('.'); + if (((i+1)%64) == 0) + printf("\n"); */ + } + break; +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) + case MV_SPI_FLASH: + if (prot) + { + if (mvSFlashWpRegionSet(&sflash, MV_WP_ALL) != MV_OK) + return 1; + } + else + { + if (mvSFlashWpRegionSet(&sflash, MV_WP_NONE) != MV_OK) + return 1; + } + + for (i=0; isector_count; ++i) + { + info->protect[i] = prot; + putc ('.'); + if (((i+1)%64) == 0) + printf("\n"); + } + break; +#endif + + default: + return 1; + } + + return 0; /* write completed succefully */ +} + +/******************************************************************** +* Copy global CFI info into Marvell FLash info +********************************************************************/ +void flashMvInfoCopy(flash_info_t *flash_info, MV_FLASH_INFO *pFlash) +{ + MV_U32 i; + + /* Check if flash_info containe CFI data */ + if(mvFlashVenIdGet(pFlash) != FLASH_UNKNOWN) + { + return; + } + + if(flash_info->flash_id == FLASH_UNKNOWN) + { + pFlash->flashSpec.flashVen = FLASH_UNKNOWN; + return; + } + + /* convert to MV_FLASH_INFO manufactor Id */ + switch (flash_info->vendor) + { + case CFI_CMDSET_INTEL_STANDARD: + case CFI_CMDSET_INTEL_EXTENDED: + pFlash->flashSpec.flashVen = INTEL_MANUF; + break; + case CFI_CMDSET_AMD_STANDARD: + case CFI_CMDSET_AMD_EXTENDED: + pFlash->flashSpec.flashVen = AMD_MANUF; + break; + default: + pFlash->flashSpec.flashVen = 0; + break; + } + + /* convert to MV_FLASH_INFO flash Id */ + pFlash->flashSpec.flashId = (flash_info->flash_id & FLASH_TYPEMASK); + + /* other flash info parameters */ + pFlash->flashSpec.size = (flash_info->size / (flash_info->portwidth / flash_info->chipwidth)); + pFlash->flashSpec.sectorNum = flash_info->sector_count; + pFlash->busWidth = flash_info->portwidth; + pFlash->devWidth = flash_info->chipwidth; + + /* sectors parameters */ + for(i = 0; i < flash_info->sector_count; i++) + { + pFlash->sector[i].baseOffs = flash_info->start[i] - flash_info->start[0]; + pFlash->sector[i].protect = flash_info->protect[i]; + if (i + 1 < flash_info->sector_count) + pFlash->sector[i].size = flash_info->start[i+1] - flash_info->start[i]; + else + pFlash->sector[i].size = (flash_info->start[0] + flash_info->size) - flash_info->start[i]; + } + + pFlash->baseAddr = flash_info->start[0]; + + return; +} + +void +flashInfoCopy(flash_info_t *flash_info, MV_FLASH_INFO *pFlash) +{ + MV_U32 i; + + /* Check if flash_info containe CFI data */ + if(flash_info->flash_id != FLASH_UNKNOWN) + { + return; + } + + if(mvFlashVenIdGet(pFlash) == FLASH_UNKNOWN) + { + flash_info->flash_id = FLASH_UNKNOWN; + return; + } + /* convert to U-Boot manufactor Id */ + flash_info->flash_id = ((mvFlashVenIdGet(pFlash) << 16) & FLASH_VENDMASK); + /* convert to U-Boot flash Id */ + flash_info->flash_id |= (mvFlashDevIdGet(pFlash) & FLASH_TYPEMASK); + + /* other flash info parameters */ + flash_info->size = mvFlashSizeGet(pFlash); + flash_info->sector_count = mvFlashNumOfSecsGet(pFlash); + flash_info->portwidth = mvFlashBusWidthGet(pFlash); + flash_info->chipwidth = mvFlashDevWidthGet(pFlash); + + /* sectors parameters */ + for(i = 0; i < mvFlashNumOfSecsGet(pFlash); i++) + { + flash_info->start[i] = mvFlashSecOffsGet(pFlash,i) + mvFlashBaseAddrGet(pFlash); + flash_info->protect[i] = mvFlashSecLockGet(pFlash,i); + } + + return; +} + +#if defined (MV_INCLUDE_INTEG_MFLASH) +void +mflashInfoCopy(flash_info_t *flash_info, MV_MFLASH_INFO *pFlash) +{ + MV_U32 i; + MV_U32 mfId; + MV_U16 devId; + MV_BOOL wp; + + /* Check if the Model was detected during the init stage and read the WP status */ + if ((pFlash->flashModel == MV_MFLASH_MODEL_UNKNOWN) || + (mvMFlashIdGet(pFlash, &mfId, &devId) != MV_OK) || + (mvMFlashWriteProtectGet(pFlash, &wp) != MV_OK)) + { + flash_info->flash_id = FLASH_UNKNOWN; + return; + } + + /* Discard the manufacturer ID and use the device ID alnoe because we lack 16 bits */ + flash_info->flash_id = devId; + + /* other flash info parameters */ + flash_info->size = (pFlash->sectorSize * pFlash->sectorNumber); + flash_info->sector_count = pFlash->sectorNumber; + flash_info->portwidth = 1; /* Assuming 8bit although that this parameter is not used */ + flash_info->chipwidth = 1; /* Assuming 8bit although that this parameter is not used */ + + /* sectors parameters */ + for(i = 0; i < pFlash->sectorNumber; i++) + { + flash_info->start[i] = (pFlash->baseAddr + (i * pFlash->sectorSize)); + flash_info->protect[i] = wp; + } + + return; +} +#endif /* #if defined (MV_INCLUDE_INTEG_MFLASH) */ + +#if defined (MV_INC_BOARD_SPI_FLASH) +void +sflashInfoCopy(flash_info_t *flash_info, MV_SFLASH_INFO *pFlash) +{ + MV_U32 i; + MV_SFLASH_WP_REGION wp; + MV_BOOL wpVal; + + /* Check if the Model was detected during the init stage and read thw WP status */ + if ((pFlash->manufacturerId == 0) || + (mvSFlashWpRegionGet(pFlash, &wp) != MV_OK)) + { + flash_info->flash_id = FLASH_UNKNOWN; + return; + } + + /* Discard the manufacturer ID and use the device ID alnoe because we lack 16 bits */ + flash_info->flash_id = ((pFlash->manufacturerId << 16) | pFlash->deviceId); + + /* other flash info parameters */ + flash_info->size = (pFlash->sectorSize * pFlash->sectorNumber); + flash_info->sector_count = pFlash->sectorNumber; + flash_info->portwidth = 0; /* Serial interface */ + flash_info->chipwidth = 0; /* Serial interface */ + + if (wp == MV_WP_ALL) + wpVal = MV_TRUE; + else + wpVal = MV_FALSE; + + /* sectors parameters */ + for(i = 0; i < pFlash->sectorNumber; i++) + { + flash_info->start[i] = (pFlash->baseAddr + (i * pFlash->sectorSize)); + flash_info->protect[i] = wpVal; + } + + return; +} +#endif + +unsigned long +mvFlash_init (void) +{ + + MV_U32 i; + unsigned long current_bank_size=0; + unsigned long flash_size=0; + +#if defined (MV_INC_BOARD_SPI_FLASH) || defined (MV_INCLUDE_INTEG_MFLASH) + MV_U32 bankIndx; +#endif /* defined (MV_INC_BOARD_SPI_FLASH) || defined (MV_INCLUDE_INTEG_MFLASH) */ + + /* Init: no FLASHes known */ + for (i=0; i CFG_MAX_FLASH_BANKS) + { + printf("%s ERROR: Number of flash devices exceeds the CFG_MAX_FLASH_BANKS=0x%x\n", __FUNCTION__,CFG_MAX_FLASH_BANKS); + return 0; + } + + for (i=0; i < norFlashBanksNum; ++i) + { + /* CFI driver detected the device */ + if (flash_info[i].flash_id != FLASH_UNKNOWN) + { + printf("[%ldkB@%x] ", flash_info[i].size/1024, flash_info[i].start[0]); + continue; + } + + mvFlashInfo[i].baseAddr = mvBoardGetDeviceBaseAddr(i, BOARD_DEV_NOR_FLASH); + DB(printf("mvFlashInfo[%d].baseAddr %x\n",i,mvFlashInfo[i].baseAddr);) + mvFlashInfo[i].busWidth = mvBoardGetDeviceBusWidth(i, BOARD_DEV_NOR_FLASH)/8; + DB(printf("mvFlashInfo[%d].busWidth %x\n",i,mvFlashInfo[i].busWidth);) + mvFlashInfo[i].devWidth = mvBoardGetDeviceWidth(i, BOARD_DEV_NOR_FLASH)/8; + DB(printf("mvFlashInfo[%d].devWidth %x\n",i,mvFlashInfo[i].devWidth);) + + if (mvFlashInfo[i].baseAddr == 0xffffffff) continue; + + current_bank_size = mvFlashInit(&mvFlashInfo[i]); + + flashInfoCopy(&flash_info[i], &mvFlashInfo[i]); + + printf("[%ldkB@%x] ", flash_info[i].size/1024, flash_info[i].start[0]); + + if (flash_info[i].flash_id == FLASH_UNKNOWN) + { + printf ("## Unknown FLASH at %08x: Size = 0x%08lx = %ld MB\n", + mvFlashInfo[i].baseAddr, current_bank_size, current_bank_size<<20); + } + + flash_size += current_bank_size; + } + + /* Copy from CFI to MV_FLASH_INFO the CFI data */ + for (i=0; i < norFlashBanksNum; ++i) + flashMvInfoCopy(&flash_info[i], &mvFlashInfo[i]); + +#endif /* #if defined (MV_INC_BOARD_NOR_FLASH) */ + +#if defined (MV_INCLUDE_INTEG_MFLASH) + +#ifdef MV_INCLUDE_INTEG_MFLASH_SPI + if (mvCtrlSpiBusModeSet(MV_SPI_CONN_TO_MFLASH) != MV_OK) + { + printf("Failed to set the SPI bus to the MFlash mode\n"); + } +#endif + mflash.ifMode = MV_SPI_CONN_UNKNOWN; /* to be detected from H/W */ + mflash.baseAddr = mvCpuIfTargetWinBaseLowGet(MFLASH_CS); + mflash.flashModel = MV_MFLASH_MODEL_UNKNOWN; /* will be detected in init */ + mflash.sectorSize = 0; /* will be detected in init */ + mflash.sectorNumber = 0; /* will be detected in init */ + mflash.infoSize = 0; /* will be detected in init */ + + /* Try to initialize the Marvell Flash - returns the size of flash detected */ + if (mflash_init(&mflash) != 0) + { + /* update the number of Marvell flashes detected to be used in index calculation */ + mFlashBanksNum = 1; + DB(printf("Number of Marvell flashes on board %d\n", mFlashBanksNum);) + + /* check that we did not exceed the MAX flash banks supported */ + if ((norFlashBanksNum + mFlashBanksNum) > CFG_MAX_FLASH_BANKS) + { + printf("%s ERROR: Number of flash devices exceeds the CFG_MAX_FLASH_BANKS\n", __FUNCTION__); + return 0; + } + + /* Set the default sector size to small - needed for saveenv in the UBoot */ + if (mvMFlashSectorSizeSet(&mflash, MV_MFLASH_SECTOR_SIZE_SMALL) != MV_OK) + { + printf("%s ERROR: Failed to set MFlash sector size to SMALL\n", __FUNCTION__); + return 0; + } + + current_bank_size = (mflash.sectorSize * mflash.sectorNumber); + + bankIndx = norFlashBanksNum; + mflashInfoCopy(&flash_info[bankIndx], &mflash); + + printf("[%ldkB@%x] ", current_bank_size/1024, mflash.baseAddr); + + if (mflash.flashModel == MV_MFLASH_MODEL_UNKNOWN) + { + printf ("## Unknown MFLASH at %08x: Size = 0x%08lx = %ld MB\n", + mflash.baseAddr, current_bank_size, current_bank_size<<20); + } + + flash_size += current_bank_size; + } + else + { + DB(printf("Failed to initialize the Marvell Flash!\n");) + } + +#endif /* #if defined (MV_INCLUDE_INTEG_MFLASH) */ + +#if defined (MV_INC_BOARD_SPI_FLASH) + sflash.baseAddr = mvCpuIfTargetWinBaseLowGet(SPI_CS); + sflash.manufacturerId = 0; /* will be detected in init */ + sflash.deviceId = 0; /* will be detected in init */ + sflash.sectorSize = 0; /* will be detected in init */ + sflash.sectorNumber = 0; /* will be detected in init */ + sflash.pageSize = 0; /* will be detected in init */ + sflash.index = MV_INVALID_DEVICE_NUMBER; /* will be detected in init */ + + /* Try to initialize an external SPI flash and retreive the size in case of success */ + if ((current_bank_size = sflash_init(&sflash)) != 0) + { + /* update the number of SPI flashes detected to be used in index calculation */ + sFlashBanksNum = 1; + DB(printf("Number of SPI flashes on board %d\n", sFlashBanksNum);) + + /* check that we did not exceed the MAX flash banks supported */ + if ((norFlashBanksNum + mFlashBanksNum + sFlashBanksNum) > CFG_MAX_FLASH_BANKS) + { + printf("%s ERROR: Number of flash devices exceeds the CFG_MAX_FLASH_BANKS\n", __FUNCTION__); + return 0; + } + + /* convert the SFlash structure into the Uboot structre */ + bankIndx = (norFlashBanksNum + mFlashBanksNum); + sflashInfoCopy(&flash_info[bankIndx], &sflash); + + printf("[%ldkB@%x] ", current_bank_size/1024, sflash.baseAddr); + + /* verify that the manufacturer Id was detected */ + if (sflash.manufacturerId == 0) + { + printf ("## Unknown SFLASH at %08x: Size = 0x%08lx = %ld MB\n", + sflash.baseAddr, current_bank_size, current_bank_size<<20); + } + + flash_size += current_bank_size; + } + else + { + DB(printf("Failed to initialize the SPI Flash!\n");) + } + +#endif /* #if defined (MV_INC_BOARD_SPI_FLASH) */ + + /* Set the write protection */ + if (norFlashBanksNum >= 1) + { + flash_protect (FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[0]); + + + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE, + &flash_info[0]); + } +//modfiy by QNAP: protect off all SPI flash +#if defined (MV_INC_BOARD_SPI_FLASH) + if (mvSFlashWpRegionSet(&sflash, MV_WP_NONE) != 0) + printf("\nIn mvFlash_init:Failed to set the write protection to NONE.\n"); +#endif +/////////// + return flash_size; + +} + + +/*----------------------------------------------------------------------- + */ +void +mv_flash_print_info (flash_info_t *info) +{ + MV_U32 s; + + s = getMvFlashInfoNum(info); + if(s >= CFG_MAX_FLASH_BANKS) + { + printf("missing or unknown FLASH type\n"); + return; + } + + switch(mvFlashTypeFromIndexGet(s)) + { +#if defined (MV_INC_BOARD_NOR_FLASH) + case MV_NOR_FLASH: + flashPrint(&mvFlashInfo[s]); + break; +#endif + +#if defined (MV_INCLUDE_INTEG_MFLASH) + case MV_MARVELL_FLASH: + mflash_print_info(&mflash); + break; +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) + case MV_SPI_FLASH: + sflash_print_info(&sflash); + break; +#endif + + default: + printf("Unknown flash type on selected bank!\n"); + } + + return; +} + +/*----------------------------------------------------------------------- + */ + + + +int +mv_flash_erase (flash_info_t *info, int s_first, int s_last) +{ + MV_U32 i,s; + MV_STATUS ret; +#if defined (MV_INCLUDE_INTEG_MFLASH) + MV_BOOL mvMFstatus; +#endif +#if defined (MV_INC_BOARD_SPI_FLASH) + MV_SFLASH_WP_REGION mvSFstatus; +#endif + + DB(printf("%s: sectors %d - %d \n", __FUNCTION__, s_first, s_last)); + s = getMvFlashInfoNum(info); + if(s >= CFG_MAX_FLASH_BANKS) + { + DB(printf("%s: illegal mvFlashInfo \n", __FUNCTION__)); + return 1; + } + printf("\n"); + + for(i = s_first; i <= s_last; i++) + { + switch(mvFlashTypeFromIndexGet(s)) + { +#if defined (MV_INC_BOARD_NOR_FLASH) + case MV_NOR_FLASH: + DB(printf("%s: calling mvFlashSecErase sector %d, base=%x, sec=%x\n", __FUNCTION__, i,mvFlashInfo[s].baseAddr, mvFlashInfo[s].sector[i].baseOffs)); + ret = mvFlashSecErase(&mvFlashInfo[s],i); + break; +#endif + +#if defined (MV_INCLUDE_INTEG_MFLASH) + case MV_MARVELL_FLASH: + DB(printf("%s: calling mvMFlashSecErase sector %d, base=%x, sec=%x\n", __FUNCTION__, i,mvFlashInfo[s].baseAddr, mvFlashInfo[s].sector[i].baseOffs)); + /* Check protect on/off */ + mvMFlashWriteProtectGet(&mflash,&mvMFstatus); + if (mvMFstatus == MV_TRUE) + { + ret = MV_FAIL; + break; + } + ret = mvMFlashSecErase(&mflash, i); + break; +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) + case MV_SPI_FLASH: + DB(printf("%s: calling mvSFlashSectorErase sector %d, base=%x, sec=%x\n", __FUNCTION__, i,mvFlashInfo[s].baseAddr, mvFlashInfo[s].sector[i].baseOffs)); + /* Check protect on/off */ + + mvSFlashWpRegionGet (&sflash, &mvSFstatus); + if (mvSFstatus == MV_WP_ALL) + { + ret = MV_FAIL; + break; + } + ret = mvSFlashSectorErase(&sflash, i); + break; +#endif + + default: + mv_flash_print_info(info); + return 1; + } + + if(ret != MV_OK) + { + printf("Erase fail!\n"); + mv_flash_print_info(info); + return 1; + } + + putc ('.'); + if (((i+1) % (NL_HASHES_PER_LINE)) == 0) + { + puts ("\n"); + } + } + puts("\n"); + + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int +mv_write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + unsigned int s = 0; + + s = getMvFlashInfoNum(info); + if(s >= CFG_MAX_FLASH_BANKS) + { + DB(printf("mv_write_buff illegal mvFlashInfo \n")); + return 1; + } + + switch(mvFlashTypeFromIndexGet(s)) + { +#if defined (MV_INC_BOARD_NOR_FLASH) + char *env; + + case MV_NOR_FLASH: + env = getenv("enaFlashBuf"); + if(( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) )) + { + if( mvFlashBlockWr(&mvFlashInfo[s],addr - mvFlashBaseAddrGet(&mvFlashInfo[s]) ,cnt,src) != cnt) + return 1; /* Write was not completed */ + } + else + { + if( mvFlashBlockUnbufWr(&mvFlashInfo[s],addr - mvFlashBaseAddrGet(&mvFlashInfo[s]) ,cnt,src) != cnt) + return 1; /* Write was not completed */ + } + break; +#endif + +#if defined (MV_INCLUDE_INTEG_MFLASH) + case MV_MARVELL_FLASH: + if (mvMFlashBlockWr(&mflash, (addr - mflash.baseAddr), cnt, src, MV_FALSE /* no compare */) != MV_OK) + return 1; /* Write was not completed */ + break; +#endif + +#if defined (MV_INC_BOARD_SPI_FLASH) + case MV_SPI_FLASH: + if (mvSFlashBlockWr(&sflash, (addr - sflash.baseAddr), src, cnt) != MV_OK) + return 1; /* Write was not completed */ + break; +#endif + + default: + return 1; + } + + return 0; /* write completed succefully */ +} + +#if (defined (MV_INCLUDE_INTEG_MFLASH)|| defined (MV_INC_BOARD_SPI_FLASH)) +/******************************************************************************* +* rangeStrDecode - Decode a range string into 2 integers +* +* DESCRIPTION: +* Decode a string indicating a range like M-N into 2 integers M and N. +* +********************************************************************************/ +static int rangeStrDecode (char * str, int * first, int * last, unsigned int sectNum) +{ + char * sl, * ep; + + if ((sl = strchr (str, '-')) == NULL) /* a single sector */ + { + /* only a single bank is specified */ + *first = simple_strtoul (str, &ep, 10); + if ((ep == str) || (*ep != '\0') || (*first >= sectNum) || (*first < 0)) + return -1; + + *last = *first; + return 0; + } + else /* we have a complete range M-N */ + { + *sl++ = '\0'; + *first = simple_strtoul (str, &ep, 10); + if ((ep == str) || (*ep != '\0') || (*first >= sectNum) || (*first < 0)) + return -1; + + *last = simple_strtoul (sl, &ep, 10); + if ((ep == str) || (*ep != '\0') || (*last >= sectNum) || (*last < 0)) + return -1; + } + + if (*first > *last) + return -1; + + return 0; +} +#endif /* (defined (MV_INCLUDE_INTEG_MFLASH)|| defined (MV_INC_BOARD_SPI_FLASH)) */ + +/*#############################################################################*/ +/*#############################################################################*/ +/*###################### MFLASH COMMANDS #############################*/ +/*#############################################################################*/ +/*#############################################################################*/ + +#if defined (MV_INCLUDE_INTEG_MFLASH) +/******************************************************************************* +* mflash_init - Detect and Initialize the Integrated Marvell Flash +* +* DESCRIPTION: +* Try to detect the Marvell Flash integrated in the SOC. Based on the +* model detected, determine the flash size +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +unsigned long mflash_init (MV_MFLASH_INFO * mflInfo) +{ + /* based on the SPI mode try to detect the Mflash device interface type */ + if (mvCtrlSpiBusModeDetect() == MV_SPI_CONN_TO_MFLASH) + mflInfo->ifMode = MV_MFLASH_SPI; + else + mflInfo->ifMode = MV_MFLASH_PARALLEL; + + /* Try to detect the flash and initialize it over the IF deteced */ + if (mvMFlashInit(mflInfo) != MV_OK) + { + printf("%s ERROR: MFlash init failed\n", __FUNCTION__); + return 0; + } + + return (mflInfo->sectorSize * mflInfo->sectorNumber); +} + +/******************************************************************************* +* mflash_print_info - Print the Marvell flash info +* +* DESCRIPTION: +* Print the flash information of the specified instance +* +* INPUT: +* pInfo: pointer to the instance flash information structure. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +void mflash_print_info (MV_MFLASH_INFO * pInfo) +{ + MV_U32 manf = 0; + MV_U16 dev = 0; + MV_BOOL wp; + + printf("\nFlash Base Address : 0x%08x",pInfo->baseAddr); + + if (pInfo->ifMode == MV_MFLASH_SPI) + printf("\nFlash Mode : SPI"); + else if (pInfo->ifMode == MV_MFLASH_PARALLEL) + printf("\nFlash Mode : Parallel"); + else + printf("\nFlash Mode : Unknown"); + + if (pInfo->flashModel != 0) + printf("\nFlash Model : SUNOL %d",(MV_U32)pInfo->flashModel); + else + printf("\nFlash Model : Unknown"); + + printf("\nSector Size : %dK", (pInfo->sectorSize / 1024)); + printf("\nNumber of sectors : %d", pInfo->sectorNumber); + + /* Get the Flash ID from the chip */ + if (mvMFlashIdGet(pInfo, &manf, &dev) != MV_OK) + { + printf("\n\nFailed to get the Manufacturer and Device IDs!\n"); + return; + } + + /* Get the WP status from the chip */ + if (mvMFlashWriteProtectGet(pInfo, &wp) != MV_OK) + { + printf("\n\nFailed to get the WP status!\n"); + return; + } + + printf("\nManufacturer ID : %08x", manf); + printf("\nDevice ID : %03x", (dev >> 4)); + printf("\nDevice Revision : %01x", (dev & 0xF)); + if (wp) + printf("\nWrite Protection : Enabled"); + else + printf("\nWrite Protection : Disabled"); + + printf("\n\n"); + +} + +/******************************************************************************* +* mflash_erase - Erase a set of sectors +* +* DESCRIPTION: +* Erase a set of sectors in the main flash region. +* +* INPUT: +* pInfo: pointer to the instance flash information structure. +* s_first: first sector to erase. +* s_last: last sector to erase. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +int mflash_erase (MV_MFLASH_INFO *pInfo, MV_U32 s_first, MV_U32 s_last) +{ + MV_U32 i; + + for (i=s_first; i<=s_last; i++) + { + /* perform the erase in serial mode */ + if (mvMFlashSecErase(pInfo, i) != MV_OK) + return 1; + } + + return 0; +} + +/******************************************************************************* +* mflash_cmd - mflash command implimentation +* +* DESCRIPTION: +* parse and decode the mflash command +* +* INPUT: +* cmdtp: command table pointer +* flag: flags +* argc: command argument count +* argv: command argument vector +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +*******************************************************************************/ +int mflash_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int first, last; + MV_U32 source, offset, size, dest; + MV_BOOL verify; + char * cp; + + if (mFlashBanksNum < 1) + { + printf ("No Marvell Flash detected!\n"); + return 1; + } + + if (argc < 2) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (strcmp(argv[1], "info") == 0) + { + /* check that we have the correct number of parameters */ + if (argc != 2) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + mflash_print_info(&mflash); + } + else if (strcmp(argv[1], "protect") == 0) + { + /* check that we have the correct number of parameters */ + if (argc != 3) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (strcmp(argv[2], "on") == 0) /* the whole chip */ + { + if (mvMFlashWriteProtectSet(&mflash, MV_TRUE) != 0) + printf("\nFailed to enable write protection!\n"); + } + else if (strcmp(argv[2], "off") == 0) /* the whole chip */ + { + if (mvMFlashWriteProtectSet(&mflash, MV_FALSE) != 0) + printf("\nFailed to disable write protection!\n"); + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + } + else if (strcmp(argv[1], "sector") == 0) + { + MV_U32 i,j; + + /* check that we have the correct number of parameters */ + if (argc != 3) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (strcmp(argv[2], "small") == 0) /* the whole chip */ + { + if (mvMFlashSectorSizeSet(&mflash, 0x1000) != 0) + { + printf("\nFailed to enable write protection!\n"); + return 1; + } + } + else if (strcmp(argv[2], "large") == 0) /* the whole chip */ + { + if (mvMFlashSectorSizeSet(&mflash, 0x8000) != 0) + { + printf("\nFailed to disable write protection!\n"); + return 1; + } + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + /* Find the Mflash entry and update the sector count and protection status */ + for (i=0; iusage); + return 1; + } + + if (strcmp(argv[2], "chip") == 0) /* the whole chip */ + { + if (mvMFlashChipErase(&mflash) != 0) + printf("\nFailed to erase the whole MFlash chip.\n", first, last); + } + else if (strcmp(argv[2], "main") == 0) /* only the main region */ + { + if (mvMFlashMainErase(&mflash) != 0) + printf("\nFailed to erase the main region.\n", first, last); + } + else if (strcmp(argv[2], "info") == 0) /* ony the information region */ + { + if (mvMFlashInfErase(&mflash) != 0) + printf("\nFailed to erase the information region\n", first, last); + } + else /* check if a range of sectors is specified */ + { + if (rangeStrDecode(argv[2], &first, &last, mflash.sectorNumber) == 0) + { + if (mflash_erase(&mflash, first, last) != 0) + printf("\nFailed to erase sectors %d-%d\n", first, last); + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + } + } + else if (strcmp(argv[1], "read") == 0) + { + /* check that we have the correct number of parameters */ + if (argc != 6) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + offset = simple_strtoul (argv[3], &cp, 16); + if ((cp == argv[3]) || (*cp != '\0') || (offset < 0)) + { + printf ("Invalid offset."); + return 1; + } + + dest = simple_strtoul (argv[4], &cp, 16); + if ((cp == argv[4]) || (*cp != '\0') || (size < 0)) + { + printf ("Invalid dest."); + return 1; + } + + size = simple_strtoul (argv[5], &cp, 16); + if ((cp == argv[5]) || (*cp != '\0') || (size < 0)) + { + printf ("Invalid size."); + return 1; + } + + if (strcmp(argv[2], "main") == 0) /* ony the information region */ + { + if (mvMFlashBlockRd(&mflash, offset, size, (MV_U8*) dest) != MV_OK) + printf ("Failed to read from the MFlash main region!\n"); + } + else if (strcmp(argv[2], "info") == 0) /* ony the information region */ + { + if (mvMFlashBlockInfRd(&mflash, offset, size, (MV_U8*) dest) != MV_OK) + printf ("Failed to read from the MFlash information region!\n"); + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + } + else if (strcmp(argv[1], "write") == 0) + { + /* check that we have the correct number of parameters */ + if ((argc != 6) && (argc != 7)) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + source = simple_strtoul (argv[3], &cp, 16); + if ((cp == argv[3]) || (*cp != '\0') || (source < 0)) + { + printf ("Invalid size!\n"); + return 1; + } + + offset = simple_strtoul (argv[4], &cp, 16); + if ((cp == argv[4]) || (*cp != '\0') || (offset < 0)) + { + printf ("Invalid offset!\n"); + return 1; + } + size = simple_strtoul (argv[5], &cp, 16); + if ((cp == argv[5]) || (*cp != '\0') || (size < 0)) + { + printf ("Invalid size!\n"); + return 1; + } + + /* check if the verify flag was used */ + if (argc == 7) + { + if (strcmp(argv[6], "verify") != 0) + { + printf("Invalid verify flag!\n"); + return 1; + } + + verify = MV_TRUE; + } + else + verify = MV_FALSE; + + if (strcmp(argv[2], "main") == 0) /* ony the information region */ + { + if (mvMFlashBlockWr(&mflash,offset, size, (MV_U8*) source, verify) != MV_OK) + { + printf ("Failed to write to the MFlash main region!\n"); + return 1; + } + } + else if (strcmp(argv[2], "info") == 0) /* ony the information region */ + { + if (mvMFlashInfBlockWr(&mflash,offset, size, (MV_U8*) source, verify) != MV_OK) + { + printf ("Failed to write to the MFlash information region!\n"); + return 1; + } + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + return 1; +} + +/*U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)*/ +U_BOOT_CMD( + mflash, 8, 1, mflash_cmd, + "mflash\t- read, write or erase the Marvell Flash.\n", + "info\n - Retreive the Marvell flash infomation.\n" + "mflash protect \n - Enable or disable write protect over the whole MFlash chip.\n" + "mflash sector \n - Set the sector size to small (4K).\n" + "mflash erase \n - Erase the whole chip, main or information region.\n" + "mflash erase SF[-SL]\n - Erase (set back to 0xFF) sectors SF-SL in main region.\n" + "mflash read
offset dest size\n - Read data from the main or info region into the destination address.\n" + "mflash write
source offset size [verify]\n - Write a buffer into the main or information region.\n" +); +#endif /* #if defined (MV_INCLUDE_INTEG_MFLASH) */ + + + +/*#############################################################################*/ +/*#############################################################################*/ +/*###################### SFLASH COMMANDS #############################*/ +/*#############################################################################*/ +/*#############################################################################*/ + +#if defined (MV_INC_BOARD_SPI_FLASH) +/******************************************************************************* +* sflash_init - Detect and Initialize an external SPI flash device +* +* DESCRIPTION: +* Try to detect the SPI Flash. Based on the model detected, determine +* the flash size. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +unsigned long sflash_init (MV_SFLASH_INFO * sflInfo) +{ +#if (defined (MV_INCLUDE_SPI) && defined (MV_INCLUDE_INTEG_MFLASH)) + /* First check that SIP mode is configured */ + if (mvCtrlSpiBusModeDetect() != MV_SPI_CONN_TO_EXT_FLASH) + { + mvOsPrintf("%s ERROR: SPI interface is not routed to external SPI flash!\n", __FUNCTION__); + return 0; + } +#endif + + /* Try to detect the flash and initialize it over SPI */ + if (mvSFlashInit(sflInfo) != MV_OK) + { + mvOsPrintf("%s ERROR: SFlash init falied!\n", __FUNCTION__); + return 0; + } + + /* return the size of the detected SFLash */ + return (mvSFlashSizeGet(sflInfo)); +} + +/******************************************************************************* +* sflash_print_info - Print the SPI flash info +* +* DESCRIPTION: +* Print the flash information of the specified instance +* +* INPUT: +* pInfo: pointer to the instance flash information structure. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +void sflash_print_info (MV_SFLASH_INFO * pInfo) +{ + MV_SFLASH_WP_REGION wp; + + printf("\nFlash Base Address : 0x%08x", pInfo->baseAddr); + printf("\nFlash Model : %s", mvSFlashModelGet(pInfo)); + printf("\nManufacturer ID : 0x%02x", pInfo->manufacturerId); + printf("\nDevice Id : 0x%04x", pInfo->deviceId); + printf("\nSector Size : %dK", (pInfo->sectorSize / 1024)); + printf("\nNumber of sectors : %d", pInfo->sectorNumber); + printf("\nPage Size : %d", pInfo->pageSize); + + if (mvSFlashWpRegionGet(pInfo, &wp) != MV_OK) + { + DB(mvOsPrintf("%s WARNING: Failed to get write protect mode!\n", __FUNCTION__);) + printf("\nWrite Protection : UNKNOWN"); + } + else + { + switch (wp) + { + case MV_WP_NONE: + printf("\nWrite Protection : Off"); + break; + case MV_WP_UPR_1OF64: + printf("\nWrite Protection : Upper 1 of 64"); + break; + case MV_WP_UPR_1OF32: + printf("\nWrite Protection : Upper 1 of 32"); + break; + case MV_WP_UPR_1OF16: + printf("\nWrite Protection : Upper 1 of 16"); + break; + case MV_WP_UPR_1OF8: + printf("\nWrite Protection : Upper 1 of 8"); + break; + case MV_WP_UPR_1OF4: + printf("\nWrite Protection : Upper 1 of 4"); + break; + case MV_WP_UPR_1OF2: + printf("\nWrite Protection : Upper 1 of 2"); + break; + case MV_WP_ALL: + printf("\nWrite Protection : All"); + break; + default: + DB(mvOsPrintf("%s WARNING: Invalid Write protect mode!\n", __FUNCTION__);) + printf("\nWrite Protection : UNKNOWN"); + break; + } + } + + printf("\n\n"); +} + +/******************************************************************************* +* sflash_erase - Erase a set of sectors +* +* DESCRIPTION: +* Erase a set of sectors in the SPI flash +* +* INPUT: +* pInfo: pointer to the instance flash information structure. +* s_first: first sector to erase. +* s_last: last sector to erase. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +int sflash_erase (MV_SFLASH_INFO *pInfo, MV_U32 s_first, MV_U32 s_last) +{ + MV_U32 i; + + for (i=s_first; i<=s_last; i++) + { + /* perform the erase in serial mode */ + if (mvSFlashSectorErase(pInfo, i) != MV_OK) + { + DB(mvOsPrintf("%s WARNING: Failed to erase sector %d in SFlash %s!\n", \ + __FUNCTION__, i, mvSFlashModelGet(pInfo));) + return 1; + } + } + + return 0; +} + +/***********************************************************************/ +/************************ U-Boot Commands ******************************/ +/***********************************************************************/ + +/******************************************************************************* +* sflash_cmd - sflash command implimentation +* +* DESCRIPTION: +* parse and decode the sflash command +* +* INPUT: +* cmdtp: command table pointer +* flag: flags +* argc: command argument count +* argv: command argument vector +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +*******************************************************************************/ +int sflash_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int first, last; + MV_U32 source, offset, size, dest; + char * cp; + + if (sFlashBanksNum < 1) + { + printf ("No SPI Flash detected!\n"); + return 1; + } + + if (argc < 2) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (strcmp(argv[1], "info") == 0) + { + /* check that we have the correct number of parameters */ + if (argc != 2) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + sflash_print_info(&sflash); + } + else if (strcmp(argv[1], "protect") == 0) + { + /* check that we have the correct number of parameters */ + if (argc != 3) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (strcmp(argv[2], "off") == 0) + { + if (mvSFlashWpRegionSet(&sflash, MV_WP_NONE) != 0) + printf("\nFailed to set the write protection to NONE.\n", first, last); + } + else if (strcmp(argv[2], "on") == 0) + { + if (mvSFlashWpRegionSet(&sflash, MV_WP_ALL) != 0) + printf("\nFailed to set the write protection to ALL.\n", first, last); + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + } + else if (strcmp(argv[1], "erase") == 0) /* erase command */ + { + /* check that we have the correct number of parameters */ + if (argc != 3) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (strcmp(argv[2], "all") == 0) /* the whole chip */ + { + if (mvSFlashChipErase(&sflash) != 0) + printf("\nFailed to erase the whole SPI flash chip.\n", first, last); + } + else /* check if a range of sectors is specified */ + { + if (rangeStrDecode(argv[2], &first, &last, sflash.sectorNumber) == 0) + { + if (sflash_erase(&sflash, first, last) != 0) + printf("\nFailed to erase sectors %d-%d\n", first, last); + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + } + } + else if (strcmp(argv[1], "read") == 0) + { + /* check that we have the correct number of parameters */ + if (argc != 5) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + offset = simple_strtoul (argv[2], &cp, 16); + if ((cp == argv[2]) || (*cp != '\0') || (offset < 0)) + { + printf ("Invalid offset."); + return 1; + } + + dest = simple_strtoul (argv[3], &cp, 16); + if ((cp == argv[3]) || (*cp != '\0') || (size < 0)) + { + printf ("Invalid size."); + return 1; + } + + size = simple_strtoul (argv[4], &cp, 16); + if ((cp == argv[4]) || (*cp != '\0') || (size < 0)) + { + printf ("Invalid size."); + return 1; + } + + if (mvSFlashBlockRd(&sflash, offset, (MV_U8*)dest, size) != MV_OK) + { + printf ("Failed to read from the SPI flash!\n"); + return 1; + } + } + else if (strcmp(argv[1], "write") == 0) + { + /* check that we have the correct number of parameters */ + if (argc != 5) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + source = simple_strtoul (argv[2], &cp, 16); + if ((cp == argv[2]) || (*cp != '\0') || (source < 0)) + { + printf ("Invalid size."); + return 1; + } + + offset = simple_strtoul (argv[3], &cp, 16); + if ((cp == argv[3]) || (*cp != '\0') || (offset < 0)) + { + printf ("Invalid offset."); + return 1; + } + size = simple_strtoul (argv[4], &cp, 16); + if ((cp == argv[4]) || (*cp != '\0') || (size < 0)) + { + printf ("Invalid size!\n"); + return 1; + } + + if (mvSFlashBlockWr(&sflash, offset, (MV_U8*) source, size) != MV_OK) + { + printf ("Failed to write to the SPI flash!\n"); + return 1; + } + } + else + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + return 1; +} + +/*U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)*/ +U_BOOT_CMD( + sflash, 6, 1, sflash_cmd, + "sflash\t- read, write or erase the external SPI Flash.\n", + "info\n - Retreive the SPI flash infomation.\n" + "sflash protect \n - Enable or diasble write protection over the whole SPI flash.\n" + "sflash erase all \n - Erase (set back to 0xFF) the whole chip.\n" + "sflash erase SF[-SL]\n - Erase (set back to 0xFF) sectors SF-SL.\n" + "sflash read offset dest size\n - Read data from the flash into the destination address.\n" + "sflash write source offset size\n - Program a buffer from the source address into the flash offset (size in bytes).\n" +); +#endif +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FLASH) */ + diff --git a/board/mv_feroceon/USP/mv_fs.c b/board/mv_feroceon/USP/mv_fs.c new file mode 100644 index 0000000..f0149c0 --- /dev/null +++ b/board/mv_feroceon/USP/mv_fs.c @@ -0,0 +1,2962 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +#include +#include +#include +#include +#include + +#include "mvSysHwConfig.h" +#if defined(MV_INCLUDE_MONT_EXT) && defined (MV_INCLUDE_MONT_FFS) + +#include "mvTypes.h" +#include "norflash/mvFlash.h" +#include "mvCpuIf.h" +/*#include "mv_mon.h"*/ +#include "mv_fs.h" + +#if CONFIG_COMMANDS & CFG_CMD_BSP + +/* #define DEBUG */ +#ifdef DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +static MV_FLASH_INFO *mvFlashInfo; + +/* File system data base variables */ +/* FAT signature */ +char FATsignature[] = "FAT024136764000"; +unsigned int initializationFlag; +unsigned int mvFSTimeStamp; +unsigned int operationMode; +unsigned int mvFSOffset; +unsigned int mvFSTopOffset; +unsigned int nextFreeBlock; +FS_FILE_TABLE_ENTRY mvFSEntries[FS_MAX_NUM_OF_ENTRIES]; +FS_FILE_CACHE_BLOCK mvFSCacheBlocks[FS_NUMBER_OF_BLOCKS_FOR_CACHE]; + +/* Functions */ +extern void d_i_cache_clean(unsigned int Address, unsigned int byteCount); +extern int load_net(MV_U32 *loadnet_addr); +extern unsigned int VIRTUAL_TO_PHY(unsigned int address); +extern void mv_go(unsigned long addr,int argc, char *argv[]); +extern MV_FLASH_INFO* getMvFlashInfo(int index); + +/******************************************************************************* +* mvFSFormat - Formats the mvFlash mvMemory for file system usage. +* +* DESCRIPTION: +* This function formats the flash memory for file system usage. It +* allocates 10 blocks for FAT in a form of a linked list and write the +* signature (signature defind in mvFS.h) in each FAT header block +* within the flash. The format starts from the ‘offset’ parameter value +* within the flash if the offset is aligned with one of the flash's +* sectors start address, otherwise it will be incremented to the nearest +* sector start address and then perform the format.The format can be +* accomplished in 2 modes as described below. +* +* INPUT: +* offset - Starting point of the format within the flash. +* +* mode - Defines whether an erasing counter will be enabled or not . +* When erasing counter is enabled , the function will allocate one +* block at the end of each sector to act as a counter for the +* number of erasures of that sector . The possible values : +* - ENABLE_ERASING_COUNTER +* - NO_ERASING_COUNTER +* OUTPUT: +* Initialized flash for file system usage. +* +* RETURN: +* The actual offset (after alignment to the nearest sector start address) +* or: +* FLASH_MEMORY_NOT_PRESENT - if no flash memory present . +* VALID_FILE_SYS_IN_LOWER_OFFSET - if a valid file system residing in a +* lower offset. +* +*******************************************************************************/ +unsigned int mvFSFormat(unsigned int offset,unsigned int mode) +{ + unsigned int i,sectorSize,tempOffset,limit,previousCount; + unsigned int erasingCounterWasEnabled = 0,status; + + DB(printf("start mvFSFormat\n")); + DB(printf("Flash base addr 0x%x\n",mvFlashInfo->baseAddr)); + + if(offset != mvFlashSecOffsGet(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset))) + { + offset = mvFlashSecOffsGet(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset) + 1); + } + if(offset != 0xffffffff) + { + if(mode == FS_ENABLE_ERASING_COUNTER) + { + tempOffset = mvFSSearchForSignature(); + if(tempOffset != FS_NO_VALID_FAT_STRING) + { + if(tempOffset < offset) + return FS_VALID_FILE_SYS_IN_LOWER_OFFSET; + if(mvFlash32Rd(mvFlashInfo, tempOffset + FS_ERSAING_COUNTER_FLAG_OFFSET) + == FS_ENABLE_ERASING_COUNTER) + { + erasingCounterWasEnabled = 1; + } + } + } + tempOffset = offset; + /* Eraseing the sectors dedicated for the file system */ + while(mvFlashInWhichSec(mvFlashInfo, offset) != 0xffffffff) + { + if(mode == FS_NO_ERASING_COUNTER) + { + DB(printf("mvFSFormat - mode = FS_NO_ERASING_COUNTER\n")); + i = mvFlashInWhichSec(mvFlashInfo, offset); + sectorSize = mvFlashSecSizeGet(mvFlashInfo, i); + limit = offset + sectorSize; + for(; offset < limit ; offset+=4) + { + if(mvFlash32Rd(mvFlashInfo, offset) != 0xffffffff) + { + DB(printf("mvFSFormat - Erase flash sector 0x%x\n", mvFlashInWhichSec(mvFlashInfo, offset))); + status = mvFlashSecErase(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset)); + if (status != MV_OK) + { + printf("mvFlashSecErase - FAIL!\n"); + return status; + } + + break; + } + } + offset += sectorSize; + } + else /* mode == FS_ENABLE_ERASING_COUNTER */ + { + DB(printf("mvFSFormat - mode = FS_ENABLE_ERASING_COUNTER\n")); + i = mvFlashInWhichSec(mvFlashInfo, offset); + sectorSize = mvFlashSecSizeGet(mvFlashInfo, i); + limit = offset + sectorSize - FS_BLOCK_SIZE; + previousCount = mvFlash32Rd(mvFlashInfo, limit); + for(; offset <= (limit + 4) ; offset+=4) + { + if(mvFlash32Rd(mvFlashInfo, offset) != 0xffffffff) + { + mvFlashSecErase(mvFlashInfo, mvFlashInWhichSec(mvFlashInfo, offset)); + if(erasingCounterWasEnabled) + { + /* Increment the counter */ + mvFlash32Wr(mvFlashInfo, limit, previousCount + 1); + mvFlash8Wr(mvFlashInfo, limit+FS_BLOCK_STATUS_FLAG_OFFSET, + FS_BLOCK_USED_FOR_ERASING_COUNTER); + } + break; + } + } + if(!erasingCounterWasEnabled) + { + /* Initialize the counter */ + mvFlash32Wr(mvFlashInfo, limit, 0); + mvFlash8Wr(mvFlashInfo, limit + FS_BLOCK_STATUS_FLAG_OFFSET, + FS_BLOCK_USED_FOR_ERASING_COUNTER); + } + offset = limit + FS_BLOCK_SIZE; + } + } + /* Fill the FAT's header */ + offset = tempOffset; + /* Update the status flag */ + mvFlash8Wr(mvFlashInfo, offset + FS_BLOCK_STATUS_FLAG_OFFSET,FS_FAT_BLOCK); + /* Write the FAT's signature */ + mvFlashBlockWr(mvFlashInfo, offset + FS_SIGNATURE_OFFSET, FS_FAT_SIGNATURE_SIZE, + (MV_U8 *)FATsignature); + /* Check if we were able to burn the mvFlash */ + for(i = 0 ; i < FS_FAT_SIGNATURE_SIZE ; i++) + { + if(mvFlash8Rd(mvFlashInfo, offset + FS_SIGNATURE_OFFSET + i) != FATsignature[i]) + return FS_FLASH_MEMORY_NOT_PRESENT; + } + if(mode == FS_ENABLE_ERASING_COUNTER) + { + mvFlash32Wr(mvFlashInfo, offset + FS_ERSAING_COUNTER_FLAG_OFFSET, + FS_ENABLE_ERASING_COUNTER); + } + mvFlash32Wr(mvFlashInfo, offset, offset + FS_BLOCK_SIZE); + /* Alocate 9 more blocks for the FAT */ + for(i = 1 ; i < (FS_MAX_NUM_OF_FAT_BLOCKS - 1) ; i++) + { + /* Next block pointer */ + mvFlash32Wr(mvFlashInfo, offset+(FS_BLOCK_SIZE*(i)),offset+ + (FS_BLOCK_SIZE*(i+1))); + /* Flag */ + mvFlash8Wr(mvFlashInfo, offset+(FS_BLOCK_SIZE*(i)) + + FS_BLOCK_STATUS_FLAG_OFFSET, FS_FAT_BLOCK); + } + /* The last block's next pointer is 0xffffffff since it is the last */ + mvFlash8Wr(mvFlashInfo, offset + (FS_BLOCK_SIZE * i) + + FS_BLOCK_STATUS_FLAG_OFFSET, FS_FAT_BLOCK); + } + return offset; +} + +/******************************************************************************* +* mvFSInit - Initializes the flash system's data base variables. +* +* DESCRIPTION: +* This function initializes the flash system's database variables residing +* in the systems dynamic memory (SDRAM) . It searches within the flash +* memory from the begining, for the first occurrence of a valid signature. +* If found, a valid file system is assumed to be exist starting from the +* sector the signature was found and all the database variables will than +* be initialized ,otherwise it returns NO_VALID_FAT_STRING or +* OFFSET_OUT_OF_RANGE to indicate that no valid file system was found +* within the flash .If a valid file system was found ,the function returns +* the number of files within the flash .The ‘mode’ parameter delivered to +* the function is for future needs to support two cache modes(cache mode, +* non - cache mode) and currently this feature is not implemented in this +* current version of this function. +* NOTE!!!!: +* It is a MUST to call this function before any attempt to use file-system +* driver. +* INPUT: +* mode - For future needs to support cache or non-cache modes (currently +* not implemented). +* +* OUTPUT: +* Initialized data base for the file system. +* +* RETURN: +* Number of files currently on the system or: +* NO_VALID_FAT_STRING - if no file system was found (Try to use +* ‘fileSysFormat’ function in this case). +* OFFSET_OUT_OF_RANGE - if there was an error finding a signature found is +* SYSTEM_ALREADY_INITIALIZED. +* +*******************************************************************************/ +unsigned int mvFSInit(unsigned int mode) +{ + /* Initially we are not going to support the FS_ENABLE_CACHE mode */ + unsigned int offset = 0,i = 0,numOfFiles,nextBlockOffset; + unsigned int fileEntryOffset,tempOffset; + + /* set the global flash info structure */ + mvFlashInfo = getMvFlashInfo(MAIN_FLASH_INDEX); + + /* Seek for the FAT signature */ + offset = mvFSSearchForSignature(); + if(offset == FS_NO_VALID_FAT_STRING) + return FS_NO_VALID_FAT_STRING; + if(offset >= mvFlashSizeGet(mvFlashInfo)) + return FS_OFFSET_OUT_OF_RANGE; + mvFSTopOffset = mvFlashSizeGet(mvFlashInfo); + + /* Check if the system is already initialized , if so we will not + re-initialize */ + if(initializationFlag == FS_FILE_SYSTEM_INITIALIZED) + return FS_SYSTEM_ALREADY_INITIALIZED; + + /* We found the FAT's signature, now we need to initialize the file system + data base and count the number of files */ + mvFSTimeStamp = 0; + operationMode = mode; + mvFSOffset = offset; + nextFreeBlock = 0xffffffff - FS_BLOCK_SIZE; + /* Initialize the files entries */ + for(i = 0 ; i < FS_MAX_NUM_OF_ENTRIES ; i++) + { + mvFSEntries[i].filePointer = 0; + mvFSEntries[i].statusFlag = FS_FREE_ENTRY; + mvFSEntries[i].mode[0] = '\0'; + mvFSEntries[i].pointerToFAT = 0xffffffff; + mvFSEntries[i].EOFpointer = 0; + } + /* Initialize the cache blocks */ + for(i = 0 ; i < FS_NUMBER_OF_BLOCKS_FOR_CACHE ; i++) + { + mvFSCacheBlocks[i].currentBlockAddress = 0xffffffff; + mvFSCacheBlocks[i].fileHandler = 0; + mvFSCacheBlocks[i].usageCounter = 0; + mvFSCacheBlocks[i].timeStamp = 0; + } + /* Count the number of files currently on the system */ + numOfFiles = 0; + nextBlockOffset = mvFSOffset; + while(nextBlockOffset != 0xffffffff) + { + /* Skip the block's header */ + fileEntryOffset = nextBlockOffset + FS_FAT_HEADER_SIZE; + for(i = 0 ; i < 15 ; i++) + { + if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_ENTRY_IN_USE) + numOfFiles++; + /* If we have files which were not properly closed we need to + to remove them from the system */ + if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_ENTRY_IN_UPDATE) + { + mvFlash8Wr(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET, + FS_FREE_DIRTY_ENTRY); + /* Free the file's data blocks */ + tempOffset = mvFlash32Rd(mvFlashInfo, fileEntryOffset); + while(tempOffset != 0xffffffff) + { + tempOffset = tempOffset & FS_BLOCK_OFFSET_MASK; + mvFlash8Wr(mvFlashInfo, tempOffset + FS_BLOCK_STATUS_FLAG_OFFSET, + FS_FREE_DIRTY_BLOCK); + tempOffset = mvFlash32Rd(mvFlashInfo, tempOffset); + } + } + /* point to the next entry */ + fileEntryOffset += FS_FAT_FILE_ENTRY_SIZE; + } + nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset); + } + initializationFlag = FS_FILE_SYSTEM_INITIALIZED; + return numOfFiles; +} + +/******************************************************************************* +* mvFSDelete - Deletes a file for the file system. +* +* DESCRIPTION: +* This function deletes a file in the file-system. The function actually +* marks the file's entry status flag as FREE_DIRTY_ENTRY and the file's +* status flag of each data block with the value FREE_DIRTY_BLOCKs to +* indicate that this entery and all the file’s data blocks are no longer +* associated by this file. If the file has valid handles associated with +* it the file will not be deleted . +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* +* INPUT: +* fileName - A string containing the file name. +* +* OUTPUT: +* On success the file will be deleted.. +* +* RETURN: +* On success - The return value will be FS_FILE_DELETED. +* On failure one of the following parameters: +* FS_FILE_NOT_FOUND - if the data base was initialized or file was not +* found. +* FS_FILE_IS_NOT_CLOSED - if the file has valid handles associated with +* it. +*******************************************************************************/ +unsigned int mvFSDelete(char * fileName) +{ + unsigned int fileOffset,numOfHandles,tempOffset; + + /* Check if the file system's data base was initialized */ + if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED) + return FS_FILE_NOT_FOUND; + + if((fileOffset = mvFSFileFind(fileName)) == FS_FILE_NOT_FOUND) + return FS_FILE_NOT_FOUND; + if((numOfHandles = mvFSNumOfHandles(fileName)) == FS_FILE_NOT_FOUND) + return FS_FILE_NOT_FOUND; + if(numOfHandles > 0) + return FS_FILE_IS_NOT_CLOSED; + + mvFlash8Wr(mvFlashInfo, fileOffset + FS_ENTRY_STATUS_FLAG_OFFSET, + FS_FREE_DIRTY_ENTRY); + /* Free the file's data blocks */ + tempOffset = mvFlash32Rd(mvFlashInfo, fileOffset); + while(tempOffset != 0xffffffff) + { + tempOffset = tempOffset & FS_BLOCK_OFFSET_MASK; + mvFlash8Wr(mvFlashInfo, tempOffset + FS_BLOCK_STATUS_FLAG_OFFSET, + FS_FREE_DIRTY_BLOCK); + tempOffset = mvFlash32Rd(mvFlashInfo, tempOffset); + } + return FS_FILE_DELETED; +} + +/******************************************************************************* +* mvFSFileFind - Check if a file exists in the file system. +* +* DESCRIPTION: +* This function checks if the file ‘fileName’ exists in the file system. +* The function will search for the file with the matching name and +* extension and if found , the file's entry offset in the FAT is returned. +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* +* INPUT: +* fileName - A string containing the file name. +* +* OUTPUT: +* None. +* +* RETURN: +* FILE_NOT_FOUND or the file's entery offset in the FAT. +* +*******************************************************************************/ +unsigned int mvFSFileFind(char * fileName) +{ + unsigned int nextBlockOffset,fileEntryOffset,index; + char tempString[20]; + + /* Check if the file system's data base was initialized */ + if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED) + return FS_FILE_NOT_FOUND; + nextBlockOffset = mvFSOffset; + while(nextBlockOffset != 0xffffffff) + { + /* Skip the block's header */ + for(fileEntryOffset = nextBlockOffset + FS_FAT_HEADER_SIZE; + fileEntryOffset < (nextBlockOffset + FS_BLOCK_SIZE); + fileEntryOffset += FS_FAT_FILE_ENTRY_SIZE) + { + index = 0; + if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_ENTRY_IN_USE) + { + /* Read the file's name */ + mvFSReadFileNameFromFATentry(fileEntryOffset,tempString); + if(strcmp(tempString,fileName) == 0) return fileEntryOffset; + /* else , try the next entry */ + } + } + nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset); + } + return FS_FILE_NOT_FOUND; +} + +/******************************************************************************* +* mvFSNumOfHandles - Counts the number of handles currently pointing to a file. +* +* DESCRIPTION: +* This function counts the number of handles currently associated to the +* file ‘fileName’.The entry table in the dynamic database is formed from +* an array of FILE_TABLE_ENTRY (structure defined in mvFS.h) and the +* file handler acts as the index of that array . The function counts each +* entry within the array that points to the file ‘fileName’ and return +* that value. +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* +* INPUT: +* fileName - A string containing the file name. +* +* OUTPUT: +* None. +* +* RETURN: +* on success , the Number of handlers currently associated to the file +* ‘fileName’. +* on failure , FS_FILE_NOT_FOUND. +* +*******************************************************************************/ +unsigned int mvFSNumOfHandles(char * fileName) +{ + unsigned int fileEntryOffset,i,numOfHandles; + if((fileEntryOffset = mvFSFileFind(fileName)) == 0xffffffff) + return FS_FILE_NOT_FOUND; + + numOfHandles = 0; + for(i = 0 ; i < FS_MAX_NUM_OF_ENTRIES ; i++) + { + if(fileEntryOffset == mvFSEntries[i].filePointer) + numOfHandles++; + } + return numOfHandles; +} + +/******************************************************************************* +* mvFSSearchForSignature - Searches for the FAT's signature string, if the +* string is found we are assuming a valid file system. +* +* DESCRIPTION: +* This function searches within the flash memory from the begining for the +* first occurrence of a valid signature .If found , it returns the sector +* offset on which the signature first occurred , otherwise it returns +* NO_VALID_FAT_STRING to indicate the flash is not formated , in that case +* you might want to use fileSysformat function. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* The offset of the sector in which the signature was found, +* otherwise FS_NO_VALID_FAT_STRING . +* +*******************************************************************************/ +unsigned int mvFSSearchForSignature(void) +{ + unsigned int offset = 0,i,sectorNumber; + + sectorNumber = mvFlashInWhichSec(mvFlashInfo, offset); + while((offset = mvFlashSecOffsGet(mvFlashInfo, sectorNumber)) != 0xffffffff) + { + for(i = 0 ; i < FS_FAT_SIGNATURE_SIZE ; i++) + { + if(mvFlash8Rd(mvFlashInfo, offset + FS_SIGNATURE_OFFSET + + i) != FATsignature[i]) + break; + } + if(i == FS_FAT_SIGNATURE_SIZE) break; + offset += mvFlashSecSizeGet(mvFlashInfo, sectorNumber); + sectorNumber = mvFlashInWhichSec(mvFlashInfo, offset); + if(sectorNumber == 0xffffffff) return FS_NO_VALID_FAT_STRING; + } + if(offset == 0xffffffff) return FS_NO_VALID_FAT_STRING; + return offset; +} + +/******************************************************************************* +* mvFSOpen - Opens a file for read/write/append. +* +* DESCRIPTION: +* This function opens a file for reading , writing or appending data .The +* function will act differantly upon each mode delivered by the parameter +* ‘mode’. +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* +* INPUT: +* mode - defines on which mode the file will be open .All possible values +* for ‘mode’ parameter are described below: +* +“ "r" - Opens the file for reading only . If the file does not +* exist or cannot be found , the function fails . After the +* file has been found , the function searches for an empty +* entry within the dynamic data base entry table and if it +* found one , it associates the file ‘fileName’ to that +* entry and returns the handler of the file. +* "r+" - Opens the file for both reading and writing. If the file +* does not exist or cannot be found , the function fails. +* After the file has been found , the function searches +* for an empty entry within the dynamic data base entry +* table and if found , it associates the file ‘fileName’ +* to that entry and returns the handler of the file . When +* a file is opened with the “r+” all write operations +* occur at the end of the file. The file pointer can be +* repositioned using fileSysSeek or fileSysRewind , but is +* always moved back to the end of the file before any write +* operation is carried out. Thus ,existing data cannot be +* overwritten. +* "w" - Opens an empty file for writing only. If the file does +* not exist the function will create it, otherwise if the +* given file exists the function will open it but its +* content will be destroyed . On both cases the function +* searches for an empty entry within the dynamic data base +* entry table and if found , it associates the file +* ‘fileName’ to that entry and returns the handler of the +* file . +* "w+" - Opens an empty file for both reading and writing data. If +* the given file exists, its contents is destroyed . When a +* file is opened with the "w+" access type , all write +* operations occur at the end of the file. The file pointer +* can be repositioned using fileSysSeek or fileSysRewind , +* but is always moved back to the end of the file before any +* write operation is carried out. Thus ,existing data cannot +* be overwritten. +* "a+" - Opens a file for reading and appending data. If the given +* file exists ,its contents is destroyed .The appending +* operation includes the removal of the EOF marker before +* new data is written to the file and the EOF marker is +* restored after the writing has completed . When a file is +* opened with the "a+" access type ,all write operations +* occur at the end of the file. The file pointer can be +* repositioned using fileSysSeek or fileSysRewind , but is +* always moved back to the end of the file before any write +* operation is carried out .Thus , existing data cannot be +* overwritten. +* fileName - A string containing the file name. +* +* OUTPUT: +* None. +* +* RETURN: +* File handler on success or FILE_OPEN_ERROR in one of the following +* reasons: +* - File system not initialized. +* - In cases of the modes "r" or "r+" and the file is not found. +* - No free entries in the file system's data base. +* - In modes "w" and w+" if we try to open a file which already exists it +* must be deleted first , an error can occur at the delete function. +* - No more free entries on the flash memory. +* - Not supported mode. +* +*******************************************************************************/ +FS_FILE_HANDLER mvFSOpen(char * fileName,char *mode) +{ + unsigned int fileFAToffset,fh; + + /* Check if the file system's data base was initialized */ + if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED) + { + return FS_FILE_OPEN_ERROR; + } + /* Mode == "r" or "r+" - the file must exist */ + if((mode[0] == 'r') && + (mode[1] == '\0'|| (mode[1] == '+' && mode[2] == '\0'))) + { + fileFAToffset = mvFSFileFind(fileName); + if(fileFAToffset == FS_FILE_NOT_FOUND) + return FS_FILE_OPEN_ERROR; + for(fh = 0 ; fh < FS_MAX_NUM_OF_ENTRIES ; fh++) + { + if(mvFSEntries[fh].statusFlag == FS_FREE_ENTRY) + { + mvFSEntries[fh].statusFlag = FS_ENTRY_IN_USE; + mvFSEntries[fh].filePointer = 0; + mvFSEntries[fh].mode[0] = mode[0]; + mvFSEntries[fh].mode[1] = mode[1]; + mvFSEntries[fh].mode[2] = mode[2]; + mvFSEntries[fh].pointerToFAT = fileFAToffset; + mvFSEntries[fh].EOFpointer = mvFSGetEOFoffset(fileName); + return fh; + } + } + return FS_FILE_OPEN_ERROR; + } + /* Mode == "w" ,"w+" or "a+" */ + if((mode[0] == 'w' || mode[0] == 'a') && + (mode[1] == '\0'||(mode[1] == '+' && mode[2] == '\0'))) + { + /* Check if the file exists on the system */ + fileFAToffset = mvFSFileFind(fileName); + if(fileFAToffset != FS_FILE_NOT_FOUND) + { + if( mode[0] != 'a') + { + if(mvFSDelete(fileName) != FS_FILE_DELETED) + return FS_FILE_OPEN_ERROR; + /* Get a free entry on the FAT */ + fileFAToffset = mvFSGetFreeEntry(); + if(fileFAToffset == FS_NO_FREE_ENTRIES) + return FS_FILE_OPEN_ERROR; + } + } + else + { + /* Get a free entry on the FAT */ + fileFAToffset = mvFSGetFreeEntry(); + if(fileFAToffset == FS_NO_FREE_ENTRIES) + return FS_FILE_OPEN_ERROR; + } + /* Search for a free entry on the file system's data base */ + for(fh = 0 ; fh < FS_MAX_NUM_OF_ENTRIES ; fh++) + { + if(mvFSEntries[fh].statusFlag == FS_FREE_ENTRY) + { + mvFSEntries[fh].statusFlag = FS_ENTRY_IN_USE; + mvFSEntries[fh].filePointer = 0; + mvFSEntries[fh].mode[0] = mode[0]; + mvFSEntries[fh].mode[1] = mode[1]; + mvFSEntries[fh].mode[2] = mode[2]; + mvFSEntries[fh].pointerToFAT= fileFAToffset; + mvFSEntries[fh].EOFpointer = mvFSGetEOFoffset(fileName); + /* Update the entry on the FAT */ + /* Write the file's name */ + mvFSWriteFileNameToFATentry(fileFAToffset,fileName); + /* Update the status flag */ + mvFlash8Wr(mvFlashInfo, fileFAToffset + FS_ENTRY_STATUS_FLAG_OFFSET, + FS_ENTRY_IN_UPDATE); + return fh; + } + } + return FS_FILE_OPEN_ERROR; + } + return FS_FILE_OPEN_ERROR; /* Has no meaning, just for the compiler */ +} + +/******************************************************************************* +* mvFSClose - Closes a file. +* +* DESCRIPTION: +* This function closes a file by removing the file's entry from the file +* system's data base , updating the file's FAT entry and data block's +* status flags and offset . After calling this function , the virtual EOF +* character is created by updating the last block’s 9 bits of the next +* block pointer if data was not appended to that block . If data was +* appended , the offset field of the last block of data will be updated +* (as described at the Introduction ). +* +* INPUT: +* fileName - A string containing the file name. +* +* OUTPUT: +* None. +* +* RETURN: +* The return value can be either FS_FILE_CLOSED on seccess or +* FILE_CLOSE_ERROR in one of the following reasons: +* - If the handler is out of range (bigger or equal to MAX_NUM_OF_ENTRIES +* defind in mvFS.h). +* - If the handler points to an entry with a FREE_ENTRY status. +* +*******************************************************************************/ +unsigned int mvFSClose(FS_FILE_HANDLER fileHandler) +{ + unsigned int FATentryOffset,nextBlockPointer,prevBlockPointer; + unsigned int offset; + + if(fileHandler >= FS_MAX_NUM_OF_ENTRIES) + return FS_FILE_CLOSE_ERROR; + if(mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY) + return FS_FILE_CLOSE_ERROR; + /* mode = "r" */ + if(mvFSEntries[fileHandler].mode[0] == 'r' && + mvFSEntries[fileHandler].mode[1] == '\0') + { + mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY; + return FS_FILE_CLOSED; + } + /* mode = "r+","w","w+" or "a+" */ + FATentryOffset = mvFSEntries[fileHandler].pointerToFAT; + /* Empty file => next block pointer == 0xFFFFFFFF */ + nextBlockPointer = mvFlash32Rd(mvFlashInfo, FATentryOffset); + if(nextBlockPointer == 0xffffffff) + { + if(mvFlash8Rd(mvFlashInfo, FATentryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) == + FS_ENTRY_IN_UPDATE) + { + /* Update the file's entry status flag */ + mvFlash8Wr(mvFlashInfo, FATentryOffset + FS_ENTRY_STATUS_FLAG_OFFSET, + FS_ENTRY_IN_USE); + } + mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY; + return FS_FILE_CLOSED; + } + /* search for the last block */ + prevBlockPointer = FATentryOffset; + while(mvFlash32Rd(mvFlashInfo, nextBlockPointer & + FS_BLOCK_OFFSET_MASK) != 0xffffffff) + { + prevBlockPointer = nextBlockPointer; + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & + FS_BLOCK_OFFSET_MASK); + } + + if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_STATUS_FLAG_OFFSET) == FS_BLOCK_IN_USE) + { + /* Old block, need to use the offset field */ + if(!((mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK) || + (mvFlash16Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_OFFSET) != 0xffff))) + { + /* File was modified */ + /* We need to update the offset field */ + if(prevBlockPointer == FATentryOffset) + { + offset = mvFlash32Rd(mvFlashInfo, prevBlockPointer) & FS_BLOCK_OFFSET; + } + else + { + offset = mvFlash32Rd(mvFlashInfo, prevBlockPointer & + FS_BLOCK_OFFSET_MASK) & FS_BLOCK_OFFSET; + } + offset = (mvFSEntries[fileHandler].EOFpointer + & FS_BLOCK_OFFSET) - offset; + mvFlash16Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_OFFSET,offset); + } + /* else - File not modified */ + mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY; + return FS_FILE_CLOSED; + } + else + { + /* Update the block's status flag */ + mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_STATUS_FLAG_OFFSET,FS_BLOCK_IN_USE); + /* Update the offset at the previous block's next block pointer */ + offset = mvFSEntries[fileHandler].EOFpointer & FS_BLOCK_OFFSET; + if(prevBlockPointer != FATentryOffset) + { + offset = (mvFlash32Rd(mvFlashInfo, prevBlockPointer & FS_BLOCK_OFFSET_MASK) + & FS_BLOCK_OFFSET_MASK) | offset; + mvFlash32Wr(mvFlashInfo, prevBlockPointer & FS_BLOCK_OFFSET_MASK,offset); + } + else /* prevBlockPointer == FATentryOffset */ + { + offset = (mvFlash32Rd(mvFlashInfo, prevBlockPointer) & FS_BLOCK_OFFSET_MASK) + | offset; + mvFlash32Wr(mvFlashInfo, prevBlockPointer, offset); + } + mvFSEntries[fileHandler].statusFlag = FS_FREE_ENTRY; + } + return FS_FILE_CLOSED; +} + +/******************************************************************************* +* mvFSFileSize - Counts the number of bytes the file consist of. +* +* DESCRIPTION: +* This function counts and return the number of bytes the file consist of. +* If the file handler delivered to the function is erroneous the function +* will return the value 0xFFFFFFFF. +* +* INPUT: +* fileHandler - The file handler to count its bytes. +* +* OUTPUT: +* None. +* +* RETURN: +* The file's number of bytes of the on success or 0xFFFFFFFF on failier. +* +*******************************************************************************/ +unsigned int mvFSFileSize(FS_FILE_HANDLER fileHandler) +{ + unsigned int numOfBytes = 0,nextBlockPointer; + + if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) || + (mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY)) + return 0xffffffff; + nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT); + if(nextBlockPointer == 0xffffffff) + return 0; + while(nextBlockPointer != 0xffffffff) + { + if(((nextBlockPointer & FS_BLOCK_OFFSET) + 1) != FS_BLOCK_SIZE) + { + if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK) + { + numOfBytes += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE); + } + else + { + if(mvFlash16Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_OFFSET) != 0xffff) + { + numOfBytes += ((nextBlockPointer & FS_BLOCK_OFFSET) + + mvFlash16Rd(mvFlashInfo, (nextBlockPointer & + FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_OFFSET) - + FS_BLOCK_HEADER_SIZE + 1); + } + else + { + numOfBytes += ((nextBlockPointer & FS_BLOCK_OFFSET) - + FS_BLOCK_HEADER_SIZE + 1); + } + } + } + else + { + if((mvFSEntries[fileHandler].EOFpointer & FS_BLOCK_OFFSET_MASK) == + (nextBlockPointer & FS_BLOCK_OFFSET_MASK)) /* Last block */ + { + numOfBytes += ((mvFSEntries[fileHandler].EOFpointer + & FS_BLOCK_OFFSET)- FS_BLOCK_HEADER_SIZE + 1); + } + else + { + numOfBytes += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE); + } + } + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & + FS_BLOCK_OFFSET_MASK); + } + if(numOfBytes == 0) + return 0; + return numOfBytes; +} + +/******************************************************************************* +* mvFSGetEOFoffset - Gets the file's EOF offset in the flash memory. +* +* DESCRIPTION: +* This function searches for the file’s EOF offset relatively to the +* begining of the last block offset . The EOF offset could be either the 9 +* least significant bits of the next block pointer or , if data was +* appended to last block , the offset field within that block . +* +* INPUT: +* fileName - The file name to get its EOF offset . +* +* OUTPUT: +* None. +* +* RETURN: +* The file's EOF offset or FILE_NOT_FOUND. +* +*******************************************************************************/ +unsigned int mvFSGetEOFoffset(char * fileName) +{ + unsigned int EOFoffset = 0,fileFAToffset,nextBlockOffset; + + fileFAToffset = mvFSFileFind(fileName); + if(fileFAToffset == FS_FILE_NOT_FOUND) + return FS_FILE_NOT_FOUND; + nextBlockOffset = mvFlash32Rd(mvFlashInfo, fileFAToffset); + if(nextBlockOffset == 0xffffffff) + return 0; + while(nextBlockOffset != 0xffffffff) + { + EOFoffset = nextBlockOffset; + nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset & + FS_BLOCK_OFFSET_MASK); + } + nextBlockOffset = EOFoffset & FS_BLOCK_OFFSET_MASK; + if(mvFlash8Rd(mvFlashInfo, nextBlockOffset + FS_BLOCK_OFFSET_FLAG_OFFSET) == + FS_FULL_BLOCK) + { + EOFoffset = nextBlockOffset + (FS_BLOCK_SIZE - + FS_BLOCK_HEADER_SIZE - 1); + } + else + { + if(mvFlash16Rd(mvFlashInfo, nextBlockOffset + FS_BLOCK_OFFSET_OFFSET) + != 0xffff) + { + EOFoffset = EOFoffset + mvFlash16Rd(mvFlashInfo, nextBlockOffset + + FS_BLOCK_OFFSET_OFFSET); + } + else + { + return EOFoffset; /* Not necessary - just for readability */ + } + } + return EOFoffset; +} + +/******************************************************************************* +* mvFSGetFreeBlockForWrite - Returns the offset of a free block (if found). +* +* DESCRIPTION: +* This function searches for a free block in more efficient way than +* ‘fileSysGetFreeBlock’ function by saving the last free block offset +* that was found in the previous search and searches from that point. In +* case it couldnt find a free block , it uses the function +* ‘fileSysGetFreeBlock’. +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* If during the copying of the sector containing the most free dirty block +* to the dynamic memory the system will loose power the file system will +* crash. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Offset to a free block , FS_NO_FREE_BLOCKS if there are no more free +* blocks or the file system was not initilized (use ‘fileSysInit’ before +* using this function in that case). +* +*******************************************************************************/ +unsigned int mvFSGetFreeBlockForWrite() +{ + unsigned char status; + + nextFreeBlock += FS_BLOCK_SIZE; + if((nextFreeBlock == 0xffffffff) || + ((nextFreeBlock != 0xffffffff) && (nextFreeBlock >= mvFSTopOffset))) + { + nextFreeBlock = mvFSGetFreeBlock(); + return nextFreeBlock; + } + else + { + while(1) + { + status = mvFlash8Rd(mvFlashInfo, nextFreeBlock + + FS_BLOCK_STATUS_FLAG_OFFSET); + if(status == FS_FREE_BLOCK) + { + return nextFreeBlock; + } + nextFreeBlock += FS_BLOCK_SIZE; + if(nextFreeBlock >= mvFSTopOffset || status == FS_FREE_DIRTY_BLOCK) + { + nextFreeBlock = mvFSGetFreeBlock(); + return nextFreeBlock; + } + } + } +} + +/******************************************************************************* +* mvFSGetFreeBlock - Returns the offset of a free block (if found). +* +* DESCRIPTION: +* This function searches for a free block from the begining of the file +* system ( from ‘fileSysOffset’ parameter initialized by ‘fileSysInit’ +* function ) to the last sector and return its offset in case it found +* one .While the function perform the search for a free block within each +* sector it also searches for the sector containing the most free dirty +* block in case a free block will not be found .If indeed a free block was +* not found ,the function erases that sector ( the one with the most free +* dirty blocks ) after copying it to a temporary buffer in the dynamic +* memory (SDRAM) and write back only the valid blocks to it .In that way +* the function free blocks from the sector containing the most free dirty +* blocks and return the next free block within that sector. +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* If during the copying of the sector containing the most free dirty block +* to the dynamic memory the system will loose power the file system will +* crash. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Offset to a free block , NO_FREE_BLOCKS if there are no more free blocks +* or the file system was not initilized (use ‘fileSysInit’ before using +* this function in that case). +* +*******************************************************************************/ +unsigned int mvFSGetFreeBlock() +{ + unsigned int freeBlockOffset,sectorTopOffset,i; + unsigned int maxFreeDirtyBlocks = 0,sectorNumber,lastSector; + unsigned int dirtyBlocksCounter = 0,dirtyBlocksSector,blockSize; + unsigned int sectorBaseOffset,previousCounter,counterOffset; + char * rmwBlockPointer,* tempBlockPointer; + + /* Check if the file system's data base was initialized */ + if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED) + return FS_NO_FREE_BLOCKS; + freeBlockOffset = mvFSOffset + FS_BLOCK_SIZE; + sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset); + lastSector = mvFlashNumOfSecsGet(mvFlashInfo); + dirtyBlocksSector = sectorNumber; + /* Search for a free block, while doing that I am searching for the sector + with the most dirty free blocks in case I will not find a free block */ + for(i = sectorNumber ; i < lastSector ; i++) + { + sectorTopOffset = mvFlashSecOffsGet(mvFlashInfo, sectorNumber) + + mvFlashSecSizeGet(mvFlashInfo, sectorNumber) - 1; + dirtyBlocksCounter = 0; + while(freeBlockOffset < sectorTopOffset) + { + if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET) + == FS_FREE_BLOCK) + { + return freeBlockOffset; + } + if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET) + == FS_FREE_DIRTY_BLOCK) dirtyBlocksCounter++; + freeBlockOffset += FS_BLOCK_SIZE; + } + if(dirtyBlocksCounter > maxFreeDirtyBlocks) + { + maxFreeDirtyBlocks = dirtyBlocksCounter; + dirtyBlocksSector = sectorNumber; + } + sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset); + } + /* We are here since we have'nt found a free block */ + /* Lets check if we have a free dirty block */ + if(maxFreeDirtyBlocks > 0) + { + /* Now we need to perform the read modify write dispensing the free + dirty blocks */ + blockSize = mvFlashSecSizeGet(mvFlashInfo, dirtyBlocksSector); + sectorBaseOffset = mvFlashSecOffsGet(mvFlashInfo, dirtyBlocksSector); + rmwBlockPointer = (char *)malloc(blockSize); + if(rmwBlockPointer == NULL) return FS_NO_FREE_BLOCKS; + /* Read the block */ + for(i = 0 ; i < blockSize ; i++) + { + rmwBlockPointer[i] = mvFlash8Rd(mvFlashInfo, sectorBaseOffset + i); + } + /* Erase the sector */ + if(mvFlash32Rd(mvFlashInfo, mvFSOffset + FS_ERSAING_COUNTER_FLAG_OFFSET) + == FS_ENABLE_ERASING_COUNTER) + { + counterOffset = sectorBaseOffset + blockSize - FS_BLOCK_SIZE; + previousCounter = mvFlash32Rd(mvFlashInfo, counterOffset); + mvFlashSecErase(mvFlashInfo, dirtyBlocksSector); + mvFlash32Wr(mvFlashInfo, counterOffset, previousCounter + 1); + mvFlash8Wr(mvFlashInfo, counterOffset + FS_BLOCK_STATUS_FLAG_OFFSET, + FS_BLOCK_USED_FOR_ERASING_COUNTER); + blockSize -= FS_BLOCK_SIZE; + } + else + { + mvFlashSecErase(mvFlashInfo, dirtyBlocksSector); + } + /* Write back only the valid blocks */ + for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE) + { + if(rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] == + FS_BLOCK_IN_USE || rmwBlockPointer[i + + FS_BLOCK_STATUS_FLAG_OFFSET] == FS_BLOCK_IN_UPDATE || + rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] == FS_FAT_BLOCK) + { + tempBlockPointer = rmwBlockPointer + i; + mvFlashBlockWr(mvFlashInfo, sectorBaseOffset + i, FS_BLOCK_SIZE, + (MV_U8 *)tempBlockPointer); + } + } + free(rmwBlockPointer); + for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE) + { + if(mvFlash8Rd(mvFlashInfo, sectorBaseOffset + i + + FS_BLOCK_STATUS_FLAG_OFFSET) + == FS_FREE_BLOCK) + return (sectorBaseOffset + i); + } + } + return FS_NO_FREE_BLOCKS; +} + +/******************************************************************************* +* mvFSGetFreeEntry - Finds a free entry in the FAT and returns its offset. +* +* DESCRIPTION: +* This function finds a free entry in the FAT and returns its offset. +* During the search for a free entry the function also finds the sector +* containing the most free dirty entries . If the fuction cant find any +* free entry within the FAT it copies the sector containing the most free +* dirty entries to the dynamic memory (SDRAM), erase that sector and write +* back only the valid entries. In that way the function free space for +* new entries and return the next free entry offset. +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* If during the copying of the sector containing the most free dirty +* enrties to the dynamic memory the system will loose power the file +* system will crash. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Offset to a free entry , NO_FREE_ENTRIES if there are no more free +* entries in the file system`s FAT or the file system was not initialized +* (use ‘fileSysInit’ before using this function in that case). +* +*******************************************************************************/ +unsigned int mvFSGetFreeEntry() +{ + unsigned int nextBlockOffset,sectorNumber,i,previousSector; + unsigned int dirtyEntriesCounter = 0,dirtyEntriesSector,blockSize,j; + unsigned int maxFreeDirtyBlocks = 0; + unsigned int sectorBaseOffset,previousCounter,counterOffset; + char * rmwBlockPointer,* tempBlockPointer; + + /* Check if the file system's data base was initialized */ + if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED) + return FS_NO_FREE_ENTRIES; + /* First FAT block */ + nextBlockOffset = mvFSOffset; + sectorNumber = mvFlashInWhichSec(mvFlashInfo, nextBlockOffset); + dirtyEntriesSector = sectorNumber; + previousSector = sectorNumber; + while(nextBlockOffset != 0xffffffff) + { + if(previousSector != sectorNumber) + { + if(dirtyEntriesSector > maxFreeDirtyBlocks) + { + maxFreeDirtyBlocks = dirtyEntriesSector; + dirtyEntriesSector = sectorNumber; + } + previousSector = sectorNumber; + dirtyEntriesSector = 0; + } + sectorNumber = mvFlashInWhichSec(mvFlashInfo, nextBlockOffset); + for(i = 0 ; i < FS_BLOCK_SIZE ; i += FS_FAT_FILE_ENTRY_SIZE) + { + if(mvFlash8Rd(mvFlashInfo, nextBlockOffset +i+ FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_FREE_ENTRY) + return (nextBlockOffset + i); + if(mvFlash8Rd(mvFlashInfo, nextBlockOffset +i+ FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_FREE_DIRTY_ENTRY) + dirtyEntriesCounter++; + } + nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset); + } + /* Now we need to perform the read modify write dispensing the free + dirty entries and blocks */ + blockSize = mvFlashSecSizeGet(mvFlashInfo, dirtyEntriesSector); + sectorBaseOffset = mvFlashSecOffsGet(mvFlashInfo, dirtyEntriesSector); + rmwBlockPointer = (char *)malloc(blockSize); + if(rmwBlockPointer == NULL) return FS_NO_FREE_ENTRIES; + /* Read the block */ + for(i = 0 ; i < blockSize ; i++) + { + rmwBlockPointer[i] = mvFlash8Rd(mvFlashInfo, sectorBaseOffset + i); + } + /* Erase the sector */ + if(mvFlash32Rd(mvFlashInfo, mvFSOffset + 20) == FS_ENABLE_ERASING_COUNTER) + { + counterOffset = sectorBaseOffset + blockSize - FS_BLOCK_SIZE; + previousCounter = mvFlash32Rd(mvFlashInfo, counterOffset); + mvFlashSecErase(mvFlashInfo, dirtyEntriesSector); + mvFlash32Wr(mvFlashInfo, counterOffset,previousCounter + 1); + mvFlash8Wr(mvFlashInfo, counterOffset + FS_BLOCK_STATUS_FLAG_OFFSET, + FS_BLOCK_USED_FOR_ERASING_COUNTER); + blockSize -= FS_BLOCK_SIZE; + } + else + { + mvFlashSecErase(mvFlashInfo, dirtyEntriesSector); + } + /* Write back only the valid blocks */ + for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE) + { + if(rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] == + FS_BLOCK_IN_USE || rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] + == FS_BLOCK_IN_UPDATE) + { + tempBlockPointer = rmwBlockPointer + i; + mvFlashBlockWr(mvFlashInfo, sectorBaseOffset + i, FS_BLOCK_SIZE, + (MV_U8 *)tempBlockPointer); + } + if(rmwBlockPointer[i + FS_BLOCK_STATUS_FLAG_OFFSET] == FS_FAT_BLOCK) + { + for(j = FS_FAT_FILE_ENTRY_SIZE ; j < FS_BLOCK_SIZE ; + j+= FS_FAT_FILE_ENTRY_SIZE) + { + if(rmwBlockPointer[j + FS_ENTRY_STATUS_FLAG_OFFSET] + == FS_ENTRY_IN_USE || + rmwBlockPointer[j + FS_ENTRY_STATUS_FLAG_OFFSET] + == FS_ENTRY_IN_UPDATE) + { + tempBlockPointer = rmwBlockPointer + j; + mvFlashBlockWr(mvFlashInfo, sectorBaseOffset + j, + FS_FAT_FILE_ENTRY_SIZE, (MV_U8 *)tempBlockPointer); + } + } + } + } + free(rmwBlockPointer); + for(i = 0 ; i < blockSize ; i += FS_BLOCK_SIZE) + { + if(mvFlash32Rd(mvFlashInfo, sectorBaseOffset + i + FS_BLOCK_STATUS_FLAG_OFFSET) + == FS_FAT_BLOCK) + { + for(j = i + FS_FAT_FILE_ENTRY_SIZE ; j < (i + FS_BLOCK_SIZE) ; + j+= FS_FAT_FILE_ENTRY_SIZE) + { + if(mvFlash32Rd(mvFlashInfo, sectorBaseOffset +j+ + FS_ENTRY_STATUS_FLAG_OFFSET) == FS_FREE_ENTRY) + return (sectorBaseOffset + j); + } + } + } + return FS_NO_FREE_ENTRIES; +} + +/******************************************************************************* +* mvFSWriteFileNameToFATentry - Write the file name to an entry in the FAT . +* +* DESCRIPTION: +* This function writes the file name to an entry in the FAT.The function +* extarcts the file name and extention and write it to the entry at +* ‘entryOffset’ within the FAT. +* +* INPUT: +* entryOffset - Pointer to the desired entry to write the file name at. +* fileName - The file name and extention. +* +* OUTPUT: +* None. +* +* RETURN: +* 0 for invalid file name, 1 for success. +* +*******************************************************************************/ +unsigned int mvFSWriteFileNameToFATentry(unsigned int entryOffset, + char * fileName) +{ + char name[FS_FILE_NAME_LENGTH]; + char ext[FS_FILE_EXT_LENGTH]; + unsigned int index,extIndex; + + /* Extract the name */ + for(index = 0 ; index < FS_FILE_NAME_LENGTH ; index++) + { + if(fileName[index] == '.' || fileName[index] == '\0') + { + break; + } + else + { + name[index] = fileName[index]; + } + } + /* Write the name */ + if(index != 0) + mvFlashBlockWr(mvFlashInfo, entryOffset + FS_FILE_NAME_OFFSET, index, (MV_U8 *)name); + if(index == 0 && fileName[index] == '\0') /* Not a valid name */ + return 0; + if(fileName[index] == '\0') /* No extension */ + return 1; + /* Extract the extension */ + index++; /* Skip the dot */ + for(extIndex = 0 ; extIndex < FS_FILE_EXT_LENGTH ; extIndex++) + { + if(fileName[index + extIndex] == '\0') + { + // ronen fix a bug ---> extIndex++; + break; + } + else + { + ext[extIndex] = fileName[index + extIndex]; + } + } + /* Write the extension */ + if(extIndex != 0) + mvFlashBlockWr(mvFlashInfo, entryOffset + FS_FILE_EXT_OFFSET, extIndex, (MV_U8 *)ext); + return 1; +} + +/******************************************************************************* +* mvFSReadFileNameFromFATentry - Read the file name from an entry in the FAT. +* +* DESCRIPTION: +* This function reads the file name from an entry in the FAT. If the given +* entry is not used by any file , the function will return 0 to remark a +* failier. +* +* INPUT: +* entryOffset - Pointer to the desired entry to read the file name from. +* fileName - pointer to an empty array to be filled by this functoin with +* the file name and extention. +* OUTPUT: +* None. +* +* RETURN: +* 0 for failure, 1 for success. +* +* +*******************************************************************************/ +unsigned int mvFSReadFileNameFromFATentry(unsigned int entryOffset, + char * fileName) +{ + unsigned int index = 0,offset; + unsigned char c; + + if( (mvFlash8Rd(mvFlashInfo, entryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_ENTRY_IN_USE) || + (mvFlash8Rd(mvFlashInfo, entryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_ENTRY_IN_UPDATE) ) + { + for(offset = 0 ; offset < FS_FILE_NAME_LENGTH ; offset++) + { + c = mvFlash8Rd(mvFlashInfo, entryOffset + FS_FILE_NAME_OFFSET + offset); + if(c == 0xff) + break; + fileName[index++] = c; + } + if(mvFlash8Rd(mvFlashInfo, entryOffset + FS_FILE_EXT_OFFSET) != 0xff) + { + fileName[index++] = '.'; + for(offset = 0 ; offset < FS_FILE_EXT_LENGTH ; offset++) + { + c = mvFlash8Rd(mvFlashInfo, entryOffset + FS_FILE_EXT_OFFSET + offset); + if(c == 0xff) break; + fileName[index++] = c; + } + } + fileName[index++] = '\0'; + return 1; + } + return 0; +} + +/******************************************************************************* +* mvFSWrite - Writes a block of data to an opened file. +* +* DESCRIPTION: +* This function writes a block of data to a file opened by all modes +* except mode “r” indicating the file is a read only file. The function +* will append the data to the last block ( if the offset flag is not set +* yet ) or to a new block if this is a new file , the function also takes +* care of updating the EOF pointer , updating the file's entry and data +* blocks status flags. During the write attempt , the function will +* return 0 value in the following cases: +* - if the given file handler is invalid that is , grater or equal to +* MAX_NUM_OF_ENTRIES (defined in mvFS.h). +* - if the entry of the file handler holds the status FREE_ENTRY. +* - if the ‘numberOfBytes’ parameter is 0. +* - if this is the first write attempt to the file ( new file ) , the +* function will allocate a new block for the data , in this case a +* failier can occur resulting from lack of free blocks. In all other +* cases the function will return the number of bytes actually written. +* Note that the number of bytes actually written returned by this +* function may not be equal to the ‘numberOfBytes’ parameter , in that +* case consider the write action as a fatal error and do not try to +* re-write the data. +* +* INPUT: +* fileHandler - The file handler of the file to be written. +* numOfBytes - The number of bytes to be written from the data array. +* block - The data array to write to the file. +* +* OUTPUT: +* None. +* +* RETURN: +* Returns the number of bytes actually written, if the number of +* bytes actually written is not equal to the numberOfBytes consider it as +* a fatal error, do not try to re-write the data. +* +*******************************************************************************/ +unsigned int mvFSWrite(FS_FILE_HANDLER fileHandler, + unsigned int numberOfBytes,char * block) +{ + unsigned int remainingBytes,nextBlockPointer,newBlockPointer,blockSize; + unsigned int freeBytesInBlock,writtenBytes,blockIndex = 0; + unsigned int totalWrittenBytes = 0,numberOfBlocks,i; + + blockSize = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE; + if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) || + (mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY) || + numberOfBytes == 0) + return 0; + if(mvFSEntries[fileHandler].mode[0] == 'r' && + mvFSEntries[fileHandler].mode[1] == '\0') + return 0; /* File was opened as read only */ + nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT); + remainingBytes = numberOfBytes; + if(nextBlockPointer == 0xffffffff) + { + /* New file, no blocks allocated yet */ + newBlockPointer = mvFSGetFreeBlock(); + mvFSEntries[fileHandler].blockPointer = newBlockPointer; + if(newBlockPointer == FS_NO_FREE_BLOCKS) + return 0; + /* Update the entry's status flag and next block pointer */ + mvFlash32Wr(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT, + newBlockPointer | FS_BLOCK_OFFSET); + mvFlash8Wr(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT + + FS_ENTRY_STATUS_FLAG_OFFSET, FS_ENTRY_IN_USE); + /* Start writing the data */ + if(numberOfBytes <= blockSize) + { + /* Only one block needed */ + /* Update the blocks status flag */ + mvFlash8Wr(mvFlashInfo, newBlockPointer + FS_BLOCK_STATUS_FLAG_OFFSET, + FS_BLOCK_IN_UPDATE); + /* Update the EOFpointer */ + mvFSEntries[fileHandler].EOFpointer = newBlockPointer + + numberOfBytes + FS_BLOCK_HEADER_SIZE - 1; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + /* Write the data */ + return + mvFlashBlockWr(mvFlashInfo, newBlockPointer + FS_BLOCK_HEADER_SIZE, + numberOfBytes, (MV_U8 *)block); + } + else /* More than one block is needed */ + { + /* I will take care of the first block in here, the rest + will be handled later in the fuction */ + /* Update the block's status flag */ + mvFlash8Wr(mvFlashInfo, newBlockPointer + FS_BLOCK_STATUS_FLAG_OFFSET, + FS_BLOCK_IN_USE);/* Fully exploited block */ + /* Write the data */ + writtenBytes = mvFlashBlockWr(mvFlashInfo, newBlockPointer + + FS_BLOCK_HEADER_SIZE, blockSize, (MV_U8 *)block); + /* Update the EOFpointer */ + mvFSEntries[fileHandler].EOFpointer = newBlockPointer + + writtenBytes + FS_BLOCK_HEADER_SIZE - 1; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + if(writtenBytes != blockSize) + return writtenBytes; /* Write operation failed */ + totalWrittenBytes += writtenBytes; + remainingBytes = numberOfBytes - blockSize; + nextBlockPointer = newBlockPointer; + blockIndex += blockSize; + } + } + /* Search for the last block */ + while(mvFlash32Rd(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK) != + 0xffffffff) + { + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & + FS_BLOCK_OFFSET_MASK); + mvFSEntries[fileHandler].blockPointer = nextBlockPointer; + } + freeBytesInBlock = FS_BLOCK_SIZE - 1 - + (mvFSEntries[fileHandler].EOFpointer & FS_BLOCK_OFFSET); + if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_STATUS_FLAG_OFFSET) == FS_BLOCK_IN_USE) + { + /* We can use the offset flag to append data, or the FS_FULL_BLOCK + flag in case the block will be fully exploited */ + if(freeBytesInBlock != 0) + { + if((remainingBytes < freeBytesInBlock) && + mvFlash16Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_OFFSET) == 0xffff) + { + writtenBytes = mvFlashBlockWr(mvFlashInfo, + mvFSEntries[fileHandler].EOFpointer + 1, + remainingBytes, (MV_U8 *)&block[blockIndex]); + mvFSEntries[fileHandler].EOFpointer += writtenBytes; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + if(remainingBytes == freeBytesInBlock) + { + mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_FLAG_OFFSET, FS_FULL_BLOCK); + } + /* else the OFFSET will be updated by mvFSClose */ + return writtenBytes; + } + else + { + if(remainingBytes >= freeBytesInBlock) + { + writtenBytes = mvFlashBlockWr(mvFlashInfo, + mvFSEntries[fileHandler].EOFpointer + 1, + freeBytesInBlock, (MV_U8 *)&block[blockIndex]); + mvFSEntries[fileHandler].EOFpointer += freeBytesInBlock; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + totalWrittenBytes += writtenBytes; + if(writtenBytes != freeBytesInBlock) /* error */ + return totalWrittenBytes; + mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_FLAG_OFFSET, FS_FULL_BLOCK); + remainingBytes -= freeBytesInBlock; + blockIndex += freeBytesInBlock; + } + } + } + } + else /* The block is not sealed yet, we can simply append the data */ + { + if(remainingBytes <= freeBytesInBlock) + { + writtenBytes = mvFlashBlockWr(mvFlashInfo, + mvFSEntries[fileHandler].EOFpointer + 1, + remainingBytes, (MV_U8 *)&block[blockIndex]); + mvFSEntries[fileHandler].EOFpointer += writtenBytes; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + if(remainingBytes == freeBytesInBlock) + { + mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_USE); + } + return writtenBytes; + } + else /* More blocks are needed */ + { + /* Fill the current block */ + writtenBytes = mvFlashBlockWr(mvFlashInfo, + mvFSEntries[fileHandler].EOFpointer + 1, + freeBytesInBlock, (MV_U8 *)&block[blockIndex]); + mvFSEntries[fileHandler].EOFpointer += writtenBytes; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + totalWrittenBytes += writtenBytes; + if(writtenBytes != freeBytesInBlock) /* error */ + return totalWrittenBytes; + mvFlash8Wr(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_USE); + remainingBytes -= freeBytesInBlock; + blockIndex += freeBytesInBlock; + } + } + numberOfBlocks = remainingBytes / blockSize; + for(i = 0 ; i < numberOfBlocks ; i++) + { + /* All the blocks in this loop will be fully exploited */ + newBlockPointer = mvFSGetFreeBlockForWrite(); + if(newBlockPointer == FS_NO_FREE_BLOCKS) + return totalWrittenBytes; + /* Update the nextBlockPointer */ + mvFlash32Wr(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK, + newBlockPointer | FS_BLOCK_OFFSET); + /* Update the status flag */ + mvFlash8Wr(mvFlashInfo, (newBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_USE); + /* Write The Data */ + writtenBytes = mvFlashBlockWr(mvFlashInfo, (newBlockPointer & + FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_HEADER_SIZE, blockSize, + (MV_U8 *)&block[blockIndex]); + blockIndex += blockSize; + totalWrittenBytes += writtenBytes; + /* Make sure the EOFpointer is set for error handling */ + mvFSEntries[fileHandler].EOFpointer = (newBlockPointer + & FS_BLOCK_OFFSET_MASK) + FS_BLOCK_HEADER_SIZE + writtenBytes - 1; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + if(writtenBytes != blockSize)/* Error */ + return totalWrittenBytes; + remainingBytes -= blockSize; + nextBlockPointer = newBlockPointer; + } + if(remainingBytes == 0) + return totalWrittenBytes; + /* Allocate a new block for the remaining bytes */ + newBlockPointer = mvFSGetFreeBlockForWrite(); + if(newBlockPointer == FS_NO_FREE_BLOCKS) + return totalWrittenBytes; + /* Update the nextBlockPointer */ + mvFlash32Wr(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK, + newBlockPointer | FS_BLOCK_OFFSET); + /* Update the status flag */ + mvFlash8Wr(mvFlashInfo, (newBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_STATUS_FLAG_OFFSET, FS_BLOCK_IN_UPDATE); + /* Write The Data */ + writtenBytes = mvFlashBlockWr(mvFlashInfo, (newBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_HEADER_SIZE, remainingBytes, + (MV_U8 *)&block[blockIndex]); + mvFSEntries[fileHandler].EOFpointer = (newBlockPointer + & FS_BLOCK_OFFSET_MASK) + FS_BLOCK_HEADER_SIZE + writtenBytes - 1; + /* Update the File pointer */ + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + totalWrittenBytes += writtenBytes; + return totalWrittenBytes; +} + +/******************************************************************************* +* mvFSGetNumOfValidBytes - Return the number of valid bytes from +* blockOffsetPointer to the end of the block. +* +* DESCRIPTION: +* None. +* +* INPUT: +* blockPointer - The offset of the block to read its valid bytes. +* blockOffsetPointer - The offset within the block to read the valid +* bytes from. +* EOFpointer - The EOF offset. +* OUTPUT: +* None. +* +* RETURN: +* Number of valid bytes. +* +*******************************************************************************/ +unsigned int mvFSGetNumOfValidBytes(unsigned int blockPointer, + unsigned int blockOffsetPointer, + unsigned int EOFpointer) +{ + if((blockOffsetPointer & FS_BLOCK_OFFSET_MASK) == + (EOFpointer & FS_BLOCK_OFFSET_MASK)) + { + /* This is the last block */ + if(EOFpointer > blockOffsetPointer) + return (EOFpointer - blockOffsetPointer); + else + return 0; + } + else + { + if((mvFlash8Rd(mvFlashInfo, (blockOffsetPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK) + || ((blockPointer & FS_BLOCK_OFFSET) == FS_BLOCK_OFFSET)) + { + return (FS_BLOCK_SIZE - 1 - (blockOffsetPointer & FS_BLOCK_OFFSET)); + } + else /* offset field is used */ + { + return ((blockPointer & FS_BLOCK_OFFSET) + mvFlash16Rd(mvFlashInfo, + (blockPointer & FS_BLOCK_OFFSET_MASK) + FS_BLOCK_OFFSET_OFFSET) + - (blockOffsetPointer & FS_BLOCK_OFFSET)); + } + } +} + +/******************************************************************************* +* mvFSRead - Read a block of data into block from a file. +* +* DESCRIPTION: +* This function reads a block of data from a file opened by all modes +* except “ w ” mode , into a given block (‘block’ parameter ) .While the +* file is opened , the function will start reading the file from the +* begining if its the first read attempt after opening the file or from +* the last point within the block of data were the previous read action +* ended .The read action will not exceed the EOF pointer if the +* ‘numberOfBytes’ parameter is larger than the whole file or the number of +* bytes left from the previous read action . During the read attempt , the +* function will return an error code or 0 in the following cases: +* +* - if the given file handler is invalid that is , grater or equal to +* MAX_NUM_OF_ENTRIES (defined in fileSys.h). +* - if the entry of the file handler within the dynamic database holds the +* status FREE_ENTRY . +* - if the mode of the opened file is write only - “ w” . +* - if the EOF pointer is equal to the file pointer that indicates the +* curruent position within the file. +* - if the ‘nextBlockPointer’ field within the entry in the FAT is equal +* to 0xFFFFFFFF indicating the file is empty. +* In a successfull read operation the function will return the number of +* bytes read , if this value is not equal to the ‘numberOfBytes’ +* parameter delivered to the function , the read action reached EOF. +* +* INPUT: +* fileHandler - The file handler of the file to be read. +* numOfBytes - The number of bytes to be read from the file to the data +* array. +* block - The data array to hold the read data from the file. +* +* OUTPUT: +* block filled with data from the file. +* +* RETURN: +* The number of bytes actually read . If this value is not equal to the +* ‘numberOfBytes’ parameter delivered to the function , the read action +* reached EOF.The function can also return the following values in case of +* an error : +* - FILE_READ_ERROR if the fileHandler is larger or equal to +* MAX_NUM_OF_ENTRIES defined in fileSys.h or if the status flag of the +* file entry in the dynamic database holds the value FREE_ENTRY. +* - 0 if the file was opened as write only , the EOF pointer is equal to +* the file pointer indicating the current loaction within the file or +* the ‘nextBlockPointer’ field within the file entry in the flash is +* equal to 0xFFFFFFFF (empty file). +* +*******************************************************************************/ +unsigned int mvFSRead(FS_FILE_HANDLER fileHandler, + unsigned int numberOfBytes,char * block) +{ + unsigned int blockIndex = 0,nextBlockPointer,EOFpointer; + unsigned int remainingBytes,freeBytesInBlock,bytesRead; + unsigned int totalBytesRead = 0,blockSize; + + if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) || + (mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY) || + numberOfBytes == 0) + return FS_FILE_READ_ERROR; + if(mvFSEntries[fileHandler].mode[0] == 'w' && + mvFSEntries[fileHandler].mode[1] == '\0') + return 0; /* File was opened as write only */ + if(mvFSEntries[fileHandler].EOFpointer == + mvFSEntries[fileHandler].filePointer) + return 0; + blockSize = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE; + EOFpointer = mvFSEntries[fileHandler].EOFpointer; + remainingBytes = numberOfBytes; + nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT); + if(nextBlockPointer == 0xffffffff) + return 0; /* An empty file */ + if(mvFSEntries[fileHandler].filePointer == 0) + { + /* Read one byte and set the filePointer to the first block */ + block[blockIndex] = mvFlash8Rd(mvFlashInfo, (nextBlockPointer + & FS_BLOCK_OFFSET_MASK) + FS_BLOCK_HEADER_SIZE); + remainingBytes--; + totalBytesRead++; + mvFSEntries[fileHandler].filePointer = (nextBlockPointer + & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_HEADER_SIZE; + blockIndex++; + mvFSEntries[fileHandler].blockPointer= nextBlockPointer; + } + else + { + /* update the block's file pointer */ + nextBlockPointer = mvFSEntries[fileHandler].blockPointer; + } + while(1) + { + if((mvFSEntries[fileHandler].filePointer & FS_BLOCK_OFFSET_MASK) != + (nextBlockPointer & FS_BLOCK_OFFSET_MASK)) + { /* Forward the file pointer to the current block */ + block[blockIndex] = mvFlash8Rd(mvFlashInfo, (nextBlockPointer + & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_HEADER_SIZE); + remainingBytes--; + totalBytesRead++; + mvFSEntries[fileHandler].filePointer = (nextBlockPointer + & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_HEADER_SIZE; + blockIndex++; + } + freeBytesInBlock = mvFSGetNumOfValidBytes(nextBlockPointer, + mvFSEntries[fileHandler].filePointer, + EOFpointer); + if(freeBytesInBlock <= remainingBytes) + { + bytesRead = mvFlashBlockRd(mvFlashInfo, mvFSEntries[fileHandler].filePointer + +1,freeBytesInBlock, (MV_U8 *)&block[blockIndex]); + remainingBytes -= bytesRead; + totalBytesRead += bytesRead; + mvFSEntries[fileHandler].filePointer += bytesRead; + blockIndex += bytesRead; + if(bytesRead != freeBytesInBlock) /* Fatal error */ + { + return totalBytesRead; + } + } + else + { + bytesRead = mvFlashBlockRd(mvFlashInfo, mvFSEntries[fileHandler].filePointer + +1,remainingBytes,(MV_U8 *)&block[blockIndex]); + totalBytesRead += bytesRead; + mvFSEntries[fileHandler].filePointer += bytesRead; + blockIndex += bytesRead; + if(bytesRead != remainingBytes) /* Fatal error */ + { + return totalBytesRead; + } + remainingBytes -= bytesRead; + } + if(((nextBlockPointer & FS_BLOCK_OFFSET_MASK) == + (EOFpointer & FS_BLOCK_OFFSET_MASK)) || remainingBytes == 0) + { /* Last valid block */ + return totalBytesRead; + } + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & + FS_BLOCK_OFFSET_MASK); + mvFSEntries[fileHandler].blockPointer = nextBlockPointer; + } + return totalBytesRead; +} + +/******************************************************************************* +* mvFSRewind - Set the file pointer the beginning of the file. +* +* DESCRIPTION: +* This function set the file pointer the beginning of the given file. +* +* INPUT: +* fileHandler - The file handler of the file to rewind its pointer. +* +* OUTPUT: +* None. +* +* RETURN: +* 0 on succes otherwise 0xffffffff. +* +*******************************************************************************/ +unsigned int mvFSRewind(FS_FILE_HANDLER fileHandler) +{ + if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) || + (mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY)) + return 0xffffffff; + mvFSEntries[fileHandler].filePointer = 0; + return 0; +} + +/******************************************************************************* +* mvFSSeek - Move the file pointer from the origin specified. +* +* DESCRIPTION: +* This function move’s the file-pointer associated with ‘filehandler’ to a +* new location that is ‘offset’ bytes from ‘origin’.The argument ‘origin’ +* must be one of the following constants , defined in mvFS.h : +* +* SEEK_CUR - Current position of file pointer. +* SEEK_END - End of file. +* SEEK_SET - Beginning of file. +* +* The ‘offset’ argument indicates the number of bytes to move relatively +* to ‘origin’. +* +* INPUT: +* fileHandler - The file-handler of the file to reposition its +* file-pointer. +* Offset - The number of bytes to move the file pointer from ‘origin’. +* Origin - The relative point within the file to move the file-pointer +* ‘offset’ bytes from it.Must be one of the three values +* described above. +* +* OUTPUT: +* File-pointer located on its new place ( on success ). +* +* RETURN: +* true on succes, 0xffffffff otherwise. +* +*******************************************************************************/ +unsigned int mvFSSeek(FS_FILE_HANDLER fileHandler,int offset,int origin) +{ + unsigned int nextBlockPointer,fileSize; + unsigned int validBytes,temp; + int tempSize = 0,tempOffset = 0; + + if((fileHandler >= FS_MAX_NUM_OF_ENTRIES) || + (mvFSEntries[fileHandler].statusFlag == FS_FREE_ENTRY)) + return 0xffffffff; + fileSize = mvFSFileSize(fileHandler); + if(fileSize == 0xffffffff || fileSize == 0) + return 0xffffffff; + nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT); + switch(origin) + { + case FS_SEEK_END: + if(offset <= 0) + return 1/*true*/; + if((unsigned int)offset >= fileSize) + { + mvFSEntries[fileHandler].filePointer = 0; + return 1/*true*/; + } + offset = fileSize - offset; + break; + case FS_SEEK_SET: + if(offset <= 0) + { + mvFSEntries[fileHandler].filePointer = 0; + return 1/*true*/; + } + if((unsigned int)offset >= fileSize) + { + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + return 1/*true*/; + } + while(tempOffset < offset) + { + validBytes = mvFSGetNumOfValidBytes(nextBlockPointer, + (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_HEADER_SIZE, + mvFSEntries[fileHandler].EOFpointer); + if((tempOffset + (int)validBytes) >= offset) + break; + tempOffset += validBytes; + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer + & FS_BLOCK_OFFSET_MASK); + mvFSEntries[fileHandler].blockPointer = nextBlockPointer; + } + mvFSEntries[fileHandler].filePointer = + (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + (offset - tempOffset) + FS_BLOCK_HEADER_SIZE - 1; + return 1/*true*/; + case FS_SEEK_CUR: /* In this case offset can be negative */ + if(offset == 0) + return 1/*true*/; + /* tempSize = Size in bytes up-to filePointer */ + temp = nextBlockPointer; + nextBlockPointer = + mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT); + mvFSEntries[fileHandler].blockPointer = nextBlockPointer; + while(nextBlockPointer != 0xffffffff) + { + if(mvFSEntries[fileHandler].filePointer == 0) + break; + if((mvFSEntries[fileHandler].filePointer & FS_BLOCK_OFFSET_MASK) == + (nextBlockPointer & FS_BLOCK_OFFSET_MASK)) /* Last block for us*/ + { + tempSize += (mvFSEntries[fileHandler].filePointer + & FS_BLOCK_OFFSET) - FS_BLOCK_HEADER_SIZE + 1; + break; + } + if(((nextBlockPointer & FS_BLOCK_OFFSET) + 1) != FS_BLOCK_SIZE) + { + if(mvFlash8Rd(mvFlashInfo, (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_FLAG_OFFSET) == FS_FULL_BLOCK) + { + tempSize += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE); + } + else + { + if(mvFlash16Rd(mvFlashInfo, (nextBlockPointer & + FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_OFFSET) != 0xffff) + { + tempSize += ((nextBlockPointer & FS_BLOCK_OFFSET) + + mvFlash16Rd(mvFlashInfo, (nextBlockPointer & + FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_OFFSET_OFFSET) - + FS_BLOCK_HEADER_SIZE + 1); + } + else + { + tempSize += ((nextBlockPointer & FS_BLOCK_OFFSET) - + FS_BLOCK_HEADER_SIZE + 1); + } + } + } + else + { + tempSize += (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE); + } + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & + FS_BLOCK_OFFSET_MASK); + mvFSEntries[fileHandler].blockPointer = nextBlockPointer; + } + nextBlockPointer = temp; + offset = tempSize + offset; + if(offset >= (int)fileSize) + { + mvFSEntries[fileHandler].filePointer = + mvFSEntries[fileHandler].EOFpointer; + return 1/*true*/; + } + if(offset <= (int)0) + { + mvFSEntries[fileHandler].filePointer = 0; + return 1/*true*/; + } + while(tempOffset < offset) + { + validBytes = mvFSGetNumOfValidBytes(nextBlockPointer, + (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + FS_BLOCK_HEADER_SIZE, + mvFSEntries[fileHandler].EOFpointer); + if((tempOffset + (int)validBytes) >= offset) + break; + tempOffset += validBytes; + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer + & FS_BLOCK_OFFSET_MASK); + mvFSEntries[fileHandler].blockPointer = nextBlockPointer; + } + mvFSEntries[fileHandler].filePointer = + (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + + (offset - tempOffset) + FS_BLOCK_HEADER_SIZE - 1; + return 1/*true*/; + default: + return 0xffffffff; + } + return 0xffffffff; +} + +/******************************************************************************* +* mvFSReadErasingCounter - Reads the value of the erasing counter (if +* implemented). +* +* DESCRIPTION: +* This function reads the value of the erasing counter ( if implemented ) +* of the given sector .The erasing counter is enabled by the function +* ‘fileSysFormat’ (by the ‘mode’ parameter) . It is implimented by +* allocating one block at the end of each sector and it helps monitoring +* the number of erasures of the sector the counter is at . +* NOTE: +* he file system's data base must be initialized by ‘fileSysInit’ function +* before using this function . +* +* INPUT: +* sectorNumber - The sector number to read its erasing counter +* (if implemented). +* +* OUTPUT: +* None. +* +* RETURN: +* The vlaue of the erasing counter, 0xffffffff in case the erasing +* counter was not implemented or the sector number is not valid. +* +*******************************************************************************/ +unsigned int mvFSReadErasingCounter(unsigned int sectorNumber) +{ + unsigned int counterValue,sectorBaseAddr,sectorSize; + + if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED) + return 0xffffffff; + if(mvFlash32Rd(mvFlashInfo, mvFSOffset + FS_ERSAING_COUNTER_FLAG_OFFSET) != + FS_ENABLE_ERASING_COUNTER) + return 0xffffffff; + if((sectorBaseAddr = mvFlashSecOffsGet(mvFlashInfo, sectorNumber)) == 0xffffffff) + return 0xffffffff; + if(sectorBaseAddr < mvFSOffset) + return 0xffffffff; + sectorSize = mvFlashSecSizeGet(mvFlashInfo, sectorNumber); + counterValue = mvFlash32Rd(mvFlashInfo, sectorBaseAddr + sectorSize - FS_BLOCK_SIZE); + return counterValue; +} + +/******************************************************************************* +* mvFSGetFreeSize - Returns the number of free bytes in the file system. +* +* DESCRIPTION: +* This function returns the number of free bytes in the entire file +* system. It counts the number of free blocks and dirty blocks ( blocks +* that are no longer in use by any file ) from the begining of the +* file-system to the end , and return that value multiply by block size +* (in bytes). +* NOTE: +* The file system's data base must be initialized by ‘fileSysInit’ +* function before using this function . +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Number of free bytes in the entire file-system on success, 0xFFFFFFFF +* otherwise. +* +*******************************************************************************/ +unsigned int mvFSGetFreeSize() +{ + unsigned int freeBlockOffset,sectorTopOffset,i; + unsigned int sectorNumber,lastSector; + unsigned int dirtyBlocksCounter = 0,dirtyBlocksSector; + unsigned int freeBlocksCounter = 0; + + /* Check if the file system's data base was initialized */ + if(initializationFlag != FS_FILE_SYSTEM_INITIALIZED) + return 0xffffffff; + freeBlockOffset = mvFSOffset + FS_BLOCK_SIZE; + sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset); + lastSector = mvFlashNumOfSecsGet(mvFlashInfo); + dirtyBlocksSector = sectorNumber; + for(i = sectorNumber ; i < lastSector ; i++) + { + sectorTopOffset = mvFlashSecOffsGet(mvFlashInfo, sectorNumber) + + mvFlashSecSizeGet(mvFlashInfo, sectorNumber) - 1; + while(freeBlockOffset < sectorTopOffset) + { + if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET) + == FS_FREE_BLOCK) freeBlocksCounter++; + if(mvFlash8Rd(mvFlashInfo, freeBlockOffset + FS_BLOCK_STATUS_FLAG_OFFSET) + == FS_FREE_DIRTY_BLOCK) dirtyBlocksCounter++; + freeBlockOffset += FS_BLOCK_SIZE; + } + sectorNumber = mvFlashInWhichSec(mvFlashInfo, freeBlockOffset); + } + return (freeBlocksCounter + dirtyBlocksCounter) * + (FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE); +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +/***********************************************************************/ +/* ask the user to give a file name and chck if the file already exist.*/ +/***********************************************************************/ +MV_VOID get_filename(MV_8 *fileName, MV_BOOL exeType) +{ + int i; + extern MV_8 console_buffer[]; + + while(1) + { + i = 0; + printf("Enter name & extension for the file (maximum %d characters for the name)\n", + FS_FILE_NAME_LENGTH); + readline(" # "); + + strcpy(fileName, console_buffer); + while( i < FS_FILE_NAME_LENGTH && + fileName[i] != '\0' && fileName[i] != ' ') i++; + fileName[i] = '\0'; + if(i == 0) + { + strcpy(fileName,"NoName"); + i = 6; + fileName[i] = '\0'; + } + /* if exe file type */ + if(exeType == MV_TRUE){ + i = 0; + while(fileName[i] != '.' && i < FS_FILE_NAME_LENGTH && + fileName[i] != '\0') i++; + fileName[i] = '.'; + fileName[i+1] = 'e'; + fileName[i+2] = 'x'; + fileName[i+3] = 'e'; + fileName[i+4] = '\0'; + } + + if (mvFSFileFind(fileName) != FS_FILE_NOT_FOUND) + { + printf("File already exists, overwrite? (Y/N)\n"); + readline(" ? "); + if(strcmp(console_buffer,"N") == 0 || strcmp(console_buffer,"no") == 0 || + strcmp(console_buffer,"n") == 0) + { + continue; + } + else + { + if(mvFSDelete(fileName) != FS_FILE_DELETED) + { + printf("File could not be deleted!\n"); + continue; + } + else + { + break; + } + } + } + else + { + break; + } + } + return; +} + +/***********************************************/ +/* load a file to the flash FS using the tftp. */ +/***********************************************/ +int +tftpfs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + int filesize; + MV_8 fileName[CFG_CBSIZE]; + MV_U32 status; + FS_FILE_HANDLER fileHandler; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + load_addr = 0x400000; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + status = mvFSInit(FS_NO_CACHE); + if(status == FS_NO_VALID_FAT_STRING) + { + printf("ERROR: FS_NO_VALID_FAT_STRING\n"); + return 0; + } + if(status == FS_OFFSET_OUT_OF_RANGE) + { + printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n"); + return 0; + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + /* done if no file was loaded (no errors though) */ + if (filesize <= 0) + return 0; + + /* get a file name from the user */ + get_filename(fileName,MV_FALSE); + + fileHandler = mvFSOpen(fileName,"w"); + if(fileHandler == FS_FILE_OPEN_ERROR) + { + printf("ERROR: Can't open file!\n"); + return 0; + } + if(mvFSWrite(fileHandler,filesize,(MV_8 *)load_addr) != filesize) + { + printf("ERROR: Writing data to file.\n"); + return 0; + } + printf("File loaded to file system successfully...\n"); + mvFSClose(fileHandler); + + return 1; +} + +U_BOOT_CMD( + FStftp, 2, 1, tftpfs_cmd, + "FStftp - tftp a file to the Flash MV FS\n", + " filename.\n" + "\tDownload a file through the network interface to the DRAM(0x400000) using\n" + "\ttftp, and copy the file to the MV Flash FS.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/***********************************************/ +/* load a file to the flash FS using the tftp. */ +/***********************************************/ +int +tftpefs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + char fileName[CFG_CBSIZE],c; + unsigned int status, entryAddress; + FS_FILE_HANDLER fileHandler; + unsigned char addressBuffer[8]; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 3) { + entryAddress = simple_strtoul(argv[1], NULL, 16); + load_addr = entryAddress; + copy_filename (BootFile, argv[2], sizeof(BootFile)); + + }else{ + printf ("Usage:\n%s %d\n", cmdtp->usage,argc); + return 0; + } + + status = mvFSInit(FS_NO_CACHE); + if(status == FS_NO_VALID_FAT_STRING) + { + printf("ERROR: FS_NO_VALID_FAT_STRING\n"); + return 0; + } + if(status == FS_OFFSET_OUT_OF_RANGE) + { + printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n"); + return 0; + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + /* done if no file was loaded (no errors though) */ + if (filesize <= 0) + return 0; + + /* get a file name from the user */ + get_filename(fileName,MV_TRUE); + + fileHandler = mvFSOpen(fileName,"w"); + if(fileHandler == FS_FILE_OPEN_ERROR) + { + printf("ERROR: Can't open file!\n"); + return 0; + } + + /* Set the entry address for the file */ + c = (entryAddress >> 28) & 0x0f; + if(c < 10) + addressBuffer[0] = c + '0'; + else + addressBuffer[0] = c + 'A' - 10; + c = (entryAddress >> 24) & 0x0f; + if(c < 10) + addressBuffer[1] = c + '0'; + else + addressBuffer[1] = c + 'A' - 10; + c = (entryAddress >> 20) & 0x0f; + if(c < 10) + addressBuffer[2] = c + '0'; + else + addressBuffer[2] = c + 'A' - 10; + c = (entryAddress >> 16) & 0x0f; + if(c < 10) + addressBuffer[3] = c + '0'; + else + addressBuffer[3] = c + 'A' - 10; + c = (entryAddress >> 12) & 0x0f; + if(c < 10) + addressBuffer[4] = c + '0'; + else + addressBuffer[4] = c + 'A' - 10; + c = (entryAddress >> 8) & 0x0f; + if(c < 10) + addressBuffer[5] = c + '0'; + else + addressBuffer[5] = c + 'A' - 10; + c = (entryAddress >> 4) & 0x0f; + if(c < 10) + addressBuffer[6] = c + '0'; + else + addressBuffer[6] = c + 'A' - 10; + c = (entryAddress) & 0x0f; + if(c < 10) + addressBuffer[7] = c + '0'; + else + addressBuffer[7] = c + 'A' - 10; + + if(mvFSWrite(fileHandler,8,(char *)addressBuffer)!= 8) + { + printf("ERROR: Writing data to file.\n"); + return 0; + } + + if(mvFSWrite(fileHandler,filesize,(char *)load_addr) != filesize) + { + printf("ERROR: Writing data to file.\n"); + return 0; + } + printf("File loaded to file system successfully...\n"); + mvFSClose(fileHandler); + + return 1; +} + +U_BOOT_CMD( + FStftpe, 3, 1, tftpefs_cmd, + "FStftpe - tftp an exe file to the Flash MV FS\n", + " entry_address filename.\n" + "\tDownload a file through the network interface to entry_address using\n" + "\ttftp, and copy the file to the MV Flash FS.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/**************************************************/ +/* load a file to the flash FS using the loadnet. */ +/**************************************************/ +#if 0 +int +loadfs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + int filesize; + MV_8 fileName[CFG_CBSIZE]; + MV_U32 status,addr = 0x20000; + FS_FILE_HANDLER fileHandler; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + status = mvFSInit(FS_NO_CACHE); + if(status == FS_NO_VALID_FAT_STRING) + { + printf("ERROR: FS_NO_VALID_FAT_STRING\n"); + return 0; + } + if(status == FS_OFFSET_OUT_OF_RANGE) + { + printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n"); + return 0; + } + + filesize = load_net(&addr); + printf("\nFile loaded successfully...\n"); + printf("File size: %d bytes.\n",filesize); + + + /* done if no file was loaded (no errors though) */ + if (filesize <= 0) + return 0; + + /* get a file name from the user */ + get_filename(fileName, MV_FALSE); + + fileHandler = mvFSOpen(fileName,"w"); + if(fileHandler == FS_FILE_OPEN_ERROR) + { + printf("ERROR: Can't open file!\n"); + return 0; + } + if(mvFSWrite(fileHandler,filesize,(MV_8 *)addr) != filesize) + { + printf("ERROR: Writing data to file.\n"); + return 0; + } + printf("File loaded to file system successfully...\n"); + mvFSClose(fileHandler); + + return 1; +} + +U_BOOT_CMD( + FSlf, 1, 1, loadfs_cmd, + "FSlf - Load a file to the Flash MV FS\n", + " \n" + "\tLoad S-Record file via the first available ethernet port, to the DRAM\n" + "\t(0x200000) and copy it to the MV Flash FS.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); +#endif + +/*******************************************************/ +/* load an exe file to the flash FS using the loadnet. */ +/*******************************************************/ +#if 0 +int +loadexefs_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + int filesize; + MV_8 fileName[CFG_CBSIZE],c; + MV_U32 status,entryAddress = 0x0; + FS_FILE_HANDLER fileHandler; + MV_U8 addressBuffer[8]; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + status = mvFSInit(FS_NO_CACHE); + if(status == FS_NO_VALID_FAT_STRING) + { + printf("ERROR: FS_NO_VALID_FAT_STRING\n"); + return 0; + } + if(status == FS_OFFSET_OUT_OF_RANGE) + { + printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n"); + return 0; + } + + filesize = load_net(&entryAddress); + printf("\nFile loaded successfully...\n"); + printf("File size: %d bytes.\n",filesize); + + + /* done if no file was loaded (no errors though) */ + if (filesize <= 0) + return 0; + + /* get a file name from the user */ + get_filename(fileName, MV_TRUE); + + fileHandler = mvFSOpen(fileName,"w"); + if(fileHandler == FS_FILE_OPEN_ERROR) + { + printf("ERROR: Can't open file!\n"); + return 0; + } + /* Set the entry address for the file */ + c = (entryAddress >> 28) & 0x0f; + if(c < 10) + addressBuffer[0] = c + '0'; + else + addressBuffer[0] = c + 'A' - 10; + c = (entryAddress >> 24) & 0x0f; + if(c < 10) + addressBuffer[1] = c + '0'; + else + addressBuffer[1] = c + 'A' - 10; + c = (entryAddress >> 20) & 0x0f; + if(c < 10) + addressBuffer[2] = c + '0'; + else + addressBuffer[2] = c + 'A' - 10; + c = (entryAddress >> 16) & 0x0f; + if(c < 10) + addressBuffer[3] = c + '0'; + else + addressBuffer[3] = c + 'A' - 10; + c = (entryAddress >> 12) & 0x0f; + if(c < 10) + addressBuffer[4] = c + '0'; + else + addressBuffer[4] = c + 'A' - 10; + c = (entryAddress >> 8) & 0x0f; + if(c < 10) + addressBuffer[5] = c + '0'; + else + addressBuffer[5] = c + 'A' - 10; + c = (entryAddress >> 4) & 0x0f; + if(c < 10) + addressBuffer[6] = c + '0'; + else + addressBuffer[6] = c + 'A' - 10; + c = (entryAddress) & 0x0f; + if(c < 10) + addressBuffer[7] = c + '0'; + else + addressBuffer[7] = c + 'A' - 10; + + if(mvFSWrite(fileHandler,8,(MV_8 *)addressBuffer)!= 8) + { + printf("ERROR: Writing data to file.\n"); + return 0; + } + + if(mvFSWrite(fileHandler,filesize,(MV_8 *)entryAddress)!= filesize) + { + printf("ERROR: Writing data to file.\n"); + return 0; + } + printf("File loaded to file system successfully...\n"); + mvFSClose(fileHandler); + return 1; +} + +U_BOOT_CMD( + FSlef, 1, 1, loadexefs_cmd, + "FSlef - Load an exe file to the Flash MV FS\n", + " \n" + "\tLoad S-Record EXE file via the first available ethernet port to the DRAM\n" + "\t(0x200000) and copy it to the MV Flash FS.\n" + "\tAfter load is complete the EXE file can be run by using: FSrun filename.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); +#endif + +/********************************************************************************* + * Load Exe file from the Flash FS. + *********************************************************************************/ +MV_U32 loadExe(MV_8 * fname) +{ + register MV_U32 byteCount; + register MV_U32 entryAddress = 0xffffffff; + MV_8 addressBuffer[9]; + FS_FILE_HANDLER fileHandler; + MV_U32 nextBlockPointer, sourceAddress, destAddress, status; + MV_U32 mvFlashBaseAddress; + + mvFlashBaseAddress = MV_BOARD_FLASH_BASE_ADRS; + + status = mvFSInit(FS_NO_CACHE); + if(status == FS_NO_VALID_FAT_STRING) + { + printf("ERROR: FS_NO_VALID_FAT_STRING\n"); + return entryAddress; + } + if(status == FS_OFFSET_OUT_OF_RANGE) + { + printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n"); + return entryAddress; + } + if((fileHandler = mvFSOpen(fname,"r")) == FS_FILE_OPEN_ERROR) + { + printf("ERROR in file open\n"); + return entryAddress; + } + + /* Extract the file's entry address */ + mvFSRead(fileHandler,8,addressBuffer); + addressBuffer[8]='\0'; + entryAddress = simple_strtoul(addressBuffer, NULL, 16); + debug("entryAddress = %x \n",entryAddress); + + nextBlockPointer = mvFlash32Rd(mvFlashInfo, mvFSEntries[fileHandler].pointerToFAT); + /* The First block contain the address, thus treated differently */ + byteCount = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE - 8 /* Address size */ ; + destAddress = entryAddress; + sourceAddress = (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + mvFlashBaseAddress + + FS_BLOCK_HEADER_SIZE + 8/* Address size */; + + /* Flush the block from the cache before executing it */ + debug("memcpy transfer src %x dst %x bytecnt %x\n",\ + sourceAddress,destAddress,byteCount); + memcpy((void *)destAddress, (void *)sourceAddress, byteCount); + destAddress += byteCount; + + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK); + byteCount = FS_BLOCK_SIZE - FS_BLOCK_HEADER_SIZE; + + while(nextBlockPointer != 0xffffffff) + { + sourceAddress = (nextBlockPointer & FS_BLOCK_OFFSET_MASK) + mvFlashBaseAddress + + FS_BLOCK_HEADER_SIZE; + + memcpy((MV_U32*)destAddress,(MV_U32*)sourceAddress,byteCount); + + destAddress += byteCount; + nextBlockPointer = mvFlash32Rd(mvFlashInfo, nextBlockPointer & FS_BLOCK_OFFSET_MASK); + } + mvFSClose(fileHandler); + return entryAddress; +} + +int runexeFS_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + MV_8 fileName[CFG_CBSIZE]; + MV_U32 i,entryAddress; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc >= 2) { + copy_filename(fileName, argv[1], sizeof(fileName)); + + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + for(i = 0 ; i < FS_FILE_NAME_LENGTH; i++) + { + if(fileName[i] == '.') + break; + if(fileName[i] == '\0') + { + fileName[i] = '.'; + fileName[i+1] = 'e'; + fileName[i+2] = 'x'; + fileName[i+3] = 'e'; + fileName[i+4] = 0; + break; + } + } + if((entryAddress = loadExe(fileName)) == 0xffffffff) + { + printf ("%s: Command not found.\n", fileName); + return 0; + } + mv_go(entryAddress, --argc, &argv[1]); + return 1; +} + +U_BOOT_CMD( + FSrun, CFG_MAXARGS, 1, runexeFS_cmd, + "FSrun - Load an exe file from the Flash MV FS and run it\n", + " filename\n" + "\tLoad an exe file 'filename' from the Flash MV FS and run it.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + + +/****************************************************************************** +* Functionality- The commands allows the user to view the contents of a file +* located in the file system. +*****************************************************************************/ +int type_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + MV_8 fileName[128]={},readBuffer[101],key; + FS_FILE_HANDLER fileHandler; + MV_U32 readCount=0, newLineCount=0, flagm,readCounttmp, lineCount=0,i; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 2) { + copy_filename(fileName, argv[1], sizeof(fileName)); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + fileHandler = mvFSOpen(fileName,"r"); + if(fileHandler != FS_FILE_OPEN_ERROR) + { + while(readCount < mvFSFileSize(fileHandler)) + { + readCounttmp = mvFSRead(fileHandler,100,readBuffer); + readBuffer[100] = '\0'; + if(readCounttmp < 100) + readBuffer[readCounttmp] = '\0'; + readCount += readCounttmp; + lineCount += readCounttmp; + for(i = 0 ; i <= readCounttmp ; i++) + if(readBuffer[i] == '\n') + newLineCount++; + printf("%s",readBuffer); + if(newLineCount >= 20 || lineCount > 1600) + { + flagm = 0; + while(1) + { + key = getc(); + switch(key) + { + case ' ': + flagm = 1; + newLineCount = 0; + lineCount = 0; + break; + case 'x': + mvFSClose(fileHandler); + printf("\n"); + return 1; + } + if(flagm == 1) + break; + } + } + } + } + mvFSClose(fileHandler); + printf("\n"); + return 1; +} + +U_BOOT_CMD( + FStype, CFG_MAXARGS, 1, type_cmd, + "FStype - cat file from the Flash MV FS\n", + " filename \n" + "\tDisplay an ascii file 'filename' found on the MV Flash FS.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + + + +/****************************************************************************** +* Functionality- Formats the mvFlash mvMemory at a given offset +*****************************************************************************/ +int format_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + MV_U32 offset =0,result; + extern MV_8 console_buffer[]; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 2) { + offset = simple_strtoul(argv[1], NULL, 16); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + printf("\a\a\aThis action will erase the FLASH Memory!!!\n"); + printf("Are you sure (y/n) "); + readline(" ? "); + + if(strcmp(console_buffer,"y") == 0 || strcmp(console_buffer,"yes") == 0 || strcmp(console_buffer,"Y") == 0) + { + if(offset == 0xffffffff) + { + printf("Bad offset!\n"); + } + result = mvFSFormat(offset,FS_NO_ERASING_COUNTER); + if(result == FS_VALID_FILE_SYS_IN_LOWER_OFFSET) + { + printf("ERROR: FS_VALID_FILE_SYS_IN_LOWER_OFFSET\n"); + return 0; + } + if(result == FS_FLASH_MEMORY_NOT_PRESENT) + { + printf("ERROR: FS_FLASH_MEMORY_NOT_PRESENT\n"); + return 1; + } + printf("Flash Memory formated successfully, actual offset is: %x\n" + ,result); + } + return 1; +} + +U_BOOT_CMD( + FSformat, 2, 1, format_cmd, + "FSformat- format the Flash MV FS\n", + " address \n" + "\tInitialize the MV Flash FS starting at offset 'address' in the Flash.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + + +/****************************************************************************** +* Functionality- Display the list of files currently on the system (file name + size) +*****************************************************************************/ +int dir_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + MV_U32 fileEntryOffset,nextBlockOffset,mvFSOffset; + MV_U32 status,i,j,spaces = 20; + FS_FILE_HANDLER fileHandler; + MV_8 fileName[20]; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + status = mvFSInit(FS_NO_CACHE); + if(status == FS_NO_VALID_FAT_STRING) + { + printf("ERROR: FS_NO_VALID_FAT_STRING\n"); + return 0; + } + if(status == FS_OFFSET_OUT_OF_RANGE) + { + printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n"); + return 0; + } + if(status != FS_SYSTEM_ALREADY_INITIALIZED) + { + printf("Number of files in system: %d\n",status); + } + + mvFSOffset = mvFSSearchForSignature(); + nextBlockOffset = mvFSOffset; + while(nextBlockOffset != 0xffffffff) + { + /* Skip the block's header */ + fileEntryOffset = nextBlockOffset + FS_FAT_HEADER_SIZE; + for(i = 0 ; i < 15 ; i++) + { + if(mvFlash8Rd(mvFlashInfo, fileEntryOffset + FS_ENTRY_STATUS_FLAG_OFFSET) + == FS_ENTRY_IN_USE) + { + mvFSReadFileNameFromFATentry(fileEntryOffset,fileName); + fileHandler = mvFSOpen(fileName,"r"); + printf("%s",fileName); + spaces = 22 - strlen(fileName); + for(j = 0 ; j < spaces ; j++) + printf(" "); + printf("size: %d bytes\n",mvFSFileSize(fileHandler)); + mvFSClose(fileHandler); + } + /* point to the next entry */ + fileEntryOffset += FS_FAT_FILE_ENTRY_SIZE; + } + nextBlockOffset = mvFlash32Rd(mvFlashInfo, nextBlockOffset); + } + printf("\n %d free bytes\n", + mvFSGetFreeSize()); + return 1; +} + + +U_BOOT_CMD( + FSdir, 1, 1, dir_cmd, + "FSdir - ls the Flash MV FS\n", + " \n" + "\tDisplay the MV Flash FS contents.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/****************************************************************************** +* Functionality- Deletes a file from the system +*****************************************************************************/ +int del_cmd(cmd_tbl_t *cmdtp, int flag, int argc, MV_8 *argv[]) +{ + MV_U32 status; + MV_8 cmd[30]; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 2) { + copy_filename (cmd, argv[1], sizeof(cmd)); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + status = mvFSInit(FS_NO_CACHE); + if(status == FS_NO_VALID_FAT_STRING) + { + printf("ERROR: FS_NO_VALID_FAT_STRING\n"); + return 0; + } + if(status == FS_OFFSET_OUT_OF_RANGE) + { + printf("ERROR: FS_OFFSET_OUT_OF_RANGE\n"); + return 0; + } + if(mvFSFileFind(cmd) != FS_FILE_NOT_FOUND) + { + if(mvFSDelete(cmd) == FS_FILE_DELETED) + { + printf("File deleted\n"); + } + } + else + { + printf("%s:No such file\n",cmd); + } + return 1; +} + +U_BOOT_CMD( + FSdel, 2, 1, del_cmd, + "FSdel - del a file from the Flash MV FS\n", + " filename \n" + "\tDelete a file 'filename' from the MV Flash FS.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + + +#endif /* CONFIG_COMMANDS & CFG_CMD_BSP */ + +#endif /* MV_INC_BOARD_NOR_FLASH */ diff --git a/board/mv_feroceon/USP/mv_fs.h b/board/mv_feroceon/USP/mv_fs.h new file mode 100644 index 0000000..8c0542b --- /dev/null +++ b/board/mv_feroceon/USP/mv_fs.h @@ -0,0 +1,184 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************** +* FileSys.h - Flash file system header +* +* DESCRIPTION: +* File system API for the flash unit integrated within the devices. +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmvFSh +#define __INCmvFSh + +#ifdef __cplusplus +extern "C" { +#endif + +/* defines */ +/* 10 Blocks are dedicated for the FAT, the first one includes the FAT + signature which is 32 Bytes, each file entry is 32 Bytes long , each block + has a header 8 bytes long (in the FAT block the other 24 are not used) => + FS_MAX_NUM_OF_ENTRIES = 150 */ +#define FS_FILE_HANDLER unsigned int +#define FS_MAX_NUM_OF_FAT_BLOCKS 10 +#define FS_MAX_NUM_OF_ENTRIES 150 +#define FS_FAT_SIGNATURE_SIZE 15 +#define FS_SIGNATURE_OFFSET 5 +#define FS_FAT_HEADER_SIZE 32 +#define FS_FAT_FILE_ENTRY_SIZE 32 +#define FS_FILE_SYSTEM_INITIALIZED 0x24136764 +#define FS_FILE_NAME_OFFSET 5 +#define FS_FILE_NAME_LENGTH 16 +#define FS_FILE_EXT_OFFSET (FS_FILE_NAME_OFFSET+ \ + FS_FILE_NAME_LENGTH) +#define FS_FILE_EXT_LENGTH 3 + +#define FS_BLOCK_SIZE 512 +#define FS_BLOCK_HEADER_SIZE 8 +#define FS_BLOCK_OFFSET_MASK 0xfffffe00 +#define FS_BLOCK_OFFSET (0xffffffff - FS_BLOCK_OFFSET_MASK) +#define FS_ERSAING_COUNTER_FLAG_OFFSET (FS_SIGNATURE_OFFSET+ \ + FS_FAT_SIGNATURE_SIZE) +#define FS_BLOCK_STATUS_FLAG_OFFSET 4 +#define FS_BLOCK_OFFSET_FLAG_OFFSET 5 +#define FS_BLOCK_OFFSET_OFFSET 6 +#define FS_NO_FREE_BLOCKS 0xffffffff +#define FS_FREE_BLOCK 0xff +#define FS_BLOCK_IN_UPDATE 0x7f +#define FS_FAT_BLOCK 0x3f +#define FS_BLOCK_IN_USE 0x1f +#define FS_BLOCK_USED_FOR_ERASING_COUNTER 0x01 +#define FS_FREE_DIRTY_BLOCK 0x00 +#define FS_FULL_BLOCK 0x0F + +#define FS_ENTRY_STATUS_FLAG_OFFSET 4 +#define FS_NO_FREE_ENTRIES 0xffffffff +#define FS_FREE_ENTRY 0xff +#define FS_ENTRY_IN_UPDATE 0x7f +#define FS_ENTRY_IN_USE 0x1f +#define FS_FREE_DIRTY_ENTRY 0x00 + +#define FS_FILE_NOT_FOUND 0xffffffff +#define FS_FILE_IS_NOT_CLOSED 0x1 +#define FS_FILE_DELETED 0x2 +#define FS_FILE_EXIST 0x3 +#define FS_ENABLE_ERASING_COUNTER 0X0000ffff +#define FS_NO_ERASING_COUNTER 0Xffffffff +#define FS_NO_VALID_FAT_STRING 0xffffffff +#define FS_OFFSET_OUT_OF_RANGE 0xfffffff0 +#define FS_FLASH_MEMORY_NOT_PRESENT 0xffffffff +#define FS_SYSTEM_ALREADY_INITIALIZED 0xfffffffc +#define FS_VALID_FILE_SYS_IN_LOWER_OFFSET 0xfffffff0 +#define FS_FILE_OPEN_ERROR 0xffffffff +#define FS_FILE_CLOSED 0x1 +#define FS_FILE_CLOSE_ERROR 0xffffffff +#define FS_FILE_READ_ERROR 0xffffffff +/* Cache size = 8 Kb */ +#define FS_NUMBER_OF_BLOCKS_FOR_CACHE 16 +/* Operation mode defined in the call to mvFSInit */ +#define FS_ENABLE_CACHE 1 +#define FS_NO_CACHE 0 +/* Defines for the seek operation */ +/* Beginning of file */ +#define FS_SEEK_SET 0 +/* End of file */ +#define FS_SEEK_END -1 +/* Current position of file pointer */ +#define FS_SEEK_CUR 1 + +/* File entry on the system's dynamic mvMemory */ +typedef struct _fileTableEntry +{ + char mode[4]; + unsigned int pointerToFAT; + unsigned int filePointer; + unsigned int blockPointer; /* For read optimization */ + unsigned int EOFpointer; + unsigned int statusFlag; +} FS_FILE_TABLE_ENTRY; +/* File entry on the FLASH mvMemory (FAT) - 32 Bytes long */ +typedef struct _fileEntry +{ + unsigned int nextBlockAddr; + unsigned int reserved1; + unsigned int reserved2; + char statusFlag; + char fileName[16]; + char fileExt[3]; +} FS_FILE_ENTRY; +/* 8 Bytes long */ +typedef struct _blockHeader +{ + unsigned int nextBlockAddr; + char statusFlag; + char offsetFlag; + unsigned short offset; +} FS_BLOCK_HEADER; +/* Cache properties defines */ +typedef struct _fileCacheBlock +{ + unsigned int fileHandler; + unsigned int currentBlockAddress; + unsigned int usageCounter; + unsigned int timeStamp; + char data[512]; +} FS_FILE_CACHE_BLOCK; + +/* Functions */ + +unsigned int mvFSFormat(unsigned int offset,unsigned int mode); +unsigned int mvFSInit(unsigned int mode); + +FS_FILE_HANDLER mvFSOpen(char * fileName,char *mode); +unsigned int mvFSClose(FS_FILE_HANDLER fileHandler); +unsigned int mvFSDelete(char * fileName); +unsigned int mvFSFileFind(char * fileName); +unsigned int mvFSFileSize(FS_FILE_HANDLER fileHandler); +unsigned int mvFSWrite(FS_FILE_HANDLER fileHandler, + unsigned int numberOfBytes,char * block); +unsigned int mvFSRead(FS_FILE_HANDLER fileHandler, + unsigned int numberOfBytes,char * block); +unsigned int mvFSSeek(FS_FILE_HANDLER fileHandler,int offset,int origin); +unsigned int mvFSRewind(FS_FILE_HANDLER fileHandler); +unsigned int mvFSReadErasingCounter(unsigned int sectorNumber); + +unsigned int mvFSNumOfHandles(char * fileName); +unsigned int mvFSSearchForSignature(void); +unsigned int mvFSGetEOFoffset(char * fileName); +unsigned int mvFSGetFreeEntry(void); +unsigned int mvFSGetFreeBlock(void); +unsigned int mvFSGetFreeBlockForWrite(void); +unsigned int mvFSWriteFileNameToFATentry(unsigned int entryOffset, + char * fileName); +unsigned int mvFSReadFileNameFromFATentry(unsigned int entryOffset, + char * fileName); +unsigned int mvFSGetFreeSize(void); +unsigned int mvFSFlushCache(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* __INCmvFSh */ + diff --git a/board/mv_feroceon/USP/mv_i2c.c b/board/mv_feroceon/USP/mv_i2c.c new file mode 100644 index 0000000..d26ead5 --- /dev/null +++ b/board/mv_feroceon/USP/mv_i2c.c @@ -0,0 +1,171 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +#include +#include +#include +#include +#include "twsi/mvTwsi.h" + +#if CONFIG_COMMANDS & CFG_CMD_I2C + +#define MAX_I2C_RETRYS 10 +#define I2C_DELAY 300 /* Should be at least the # of MHz of Tclk */ +#undef DEBUG_I2C +//#define DEBUG_I2C + +#ifdef DEBUG_I2C +#define DP(x) x +#else +#define DP(x) +#endif + +/* Assuming that there is only one master on the bus (us) */ + +void +i2c_init(MV_U8 chanNum, int speed, int slaveaddr) +{ + MV_TWSI_ADDR slave; + slave.type = ADDR7_BIT; + slave.address = slaveaddr; + mvTwsiInit(chanNum, speed, CFG_TCLK, &slave, 0); +} + +/* + * Read interface: + * dev_addr:I2C chip address, range 0..127 + * offset: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * data: Where to read the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int +i2c_read(MV_U8 chanNum, MV_U8 dev_addr, unsigned int offset, int alen, MV_U8* data, int len) +{ + MV_TWSI_SLAVE twsiSlave; + unsigned int i2cFreq = CFG_I2C_SPEED; + DP(puts("i2c_read\n")); + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.slaveAddr.address = dev_addr; + if(alen != 0){ + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = offset; + if(alen == 2) + { + twsiSlave.moreThen256 = MV_TRUE; + } + else + { + twsiSlave.moreThen256 = MV_FALSE; + } + } + + i2c_init(chanNum, i2cFreq,0); /* set the i2c frequency */ + return mvTwsiRead (chanNum, &twsiSlave, data, len); +} + +/* + * Write interface: + * dev_addr:I2C chip address, range 0..127 + * offset: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * data: Where to write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ + +uchar +i2c_write(MV_U8 chanNum, uchar dev_addr, unsigned int offset, int alen, uchar* data, int len) +{ + MV_TWSI_SLAVE twsiSlave; + unsigned int i2cFreq = CFG_I2C_SPEED; + DP(puts("i2c_write\n")); + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.slaveAddr.address = dev_addr; + if(alen != 0){ + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = offset; + if(alen == 2) + { + twsiSlave.moreThen256 = MV_TRUE; + } + else + { + twsiSlave.moreThen256 = MV_FALSE; + } + } + + i2c_init(chanNum, i2cFreq,0); /* set the i2c frequency */ + + return mvTwsiWrite (chanNum, &twsiSlave, data, len); +} + +/* function to determine if an I2C device is present */ +/* chip = device address of chip to check for */ +/* */ +/* returns 0 = sucessful, the device exists */ +/* anything other than zero is failure, no device */ +int i2c_probe (MV_U8 chanNum, uchar chip) +{ + + /* We are just looking for an back. */ + /* To see if the device/chip is there */ + + MV_TWSI_ADDR eepromAddress; + + unsigned int status = 0; + unsigned int i2cFreq = CFG_I2C_SPEED; + + DP(puts("i2c_probe\n")); + + i2c_init(chanNum, i2cFreq,0); /* set the i2c frequency */ + + status = mvTwsiStartBitSet(chanNum); + + if (status) { + DP(printf("Transaction start failed: 0x%02x\n", status)); + mvTwsiStopBitSet(chanNum); + return (int)status; + } + + eepromAddress.type = ADDR7_BIT; + eepromAddress.address = chip; + + status = mvTwsiAddrSet(chanNum, &eepromAddress, MV_TWSI_WRITE); /* send the slave address */ + if (status) { + DP(printf("Failed to set slave address: 0x%02x\n", status)); + mvTwsiStopBitSet(chanNum); + return (int)status; + } + DP(printf("address %#x returned %#x\n",chip,MV_REG_READ(TWSI_STATUS_BAUDE_RATE_REG(chanNum)))); + + /* issue a stop bit */ + mvTwsiStopBitSet(chanNum); + + DP(printf("*** successful completion \n")); + return 0; /* successful completion */ +} +#endif diff --git a/board/mv_feroceon/USP/mv_ide.c b/board/mv_feroceon/USP/mv_ide.c new file mode 100644 index 0000000..bba75d0 --- /dev/null +++ b/board/mv_feroceon/USP/mv_ide.c @@ -0,0 +1,1500 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +/* + * IDE support + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mvCtrlEnvLib.h" + +#if (CONFIG_COMMANDS & CFG_CMD_IDE) + +#include "sata/CoreDriver/mvOsS.h" +#include "sata/CoreDriver/mvSata.h" +#include "sata/CoreDriver/mvStorageDev.h" + +#ifdef MV_LOGGER +char *szModules[] = {"Core Driver", +"BIOS IAL" +}; +#endif + +#undef IDE_DEBUG + +#ifdef IDE_DEBUG +#define DP(fmt,args...) printf (fmt ,##args) +#else +#define DP(fmt,args...) +#endif + +#define SHOW_BOOT_PROGRESS(arg) + +#if defined(MV_INCLUDE_INTEG_SATA) +extern MV_STATUS mvSataWinInit(void); +#endif + +#ifndef MRVL_SATA_BUFF_BOUNDARY +#define MRVL_SATA_BUFF_BOUNDARY (1 << 24) +#endif /* MRVL_SATA_BUFF_BOUNDARY */ + +#define MRVL_SATA_BOUNDARY_MASK (MRVL_SATA_BUFF_BOUNDARY - 1) + +#if (__BE) +void swapATABuffer(unsigned short *buffer, ulong count); +#endif +/* ------------------------------------------------------------------------- */ + +/* Current I/O Device */ +static int curr_device = -1; + + +#define ATA_CURR_BASE(dev) (CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)]) +#define MV_PM 0xF + +typedef struct mvSataPMDeviceInfo +{ + MV_U16 vendorId; + MV_U16 deviceId; + MV_U8 productRevision; + MV_U8 PMSpecRevision:4; + MV_U8 numberOfPorts:4; +} MV_SATA_PM_DEVICE_INFO; + +typedef struct _MV_CHANNEL_INFO +{ + MV_SATA_DEVICE_TYPE deviceType; + MV_U8 numberOfPorts; + MV_U16 connected; +}MV_CHANNEL_INFO; +typedef struct _HW_ADAPTER_DESCRIPTION +{ + MV_BOOLEAN valid; + int devno; + MV_SATA_ADAPTER mvSataAdapter; /* CoreDriver Adapter data structure*/ + MV_SATA_CHANNEL mvSataChannels[MV_SATA_CHANNELS_NUM]; + MV_CHANNEL_INFO channelInfo[MV_SATA_PM_MAX_PORTS]; +} HW_ADAPTER_DESCRIPTION, *PHW_ADAPTER_DESCRIPTION; + +/* Data structure describing mvSata adapter and channels */ +/* The data structure describes 4 adapters */ +#define MAX_NUM_OF_ADAPTERS 4 +HW_ADAPTER_DESCRIPTION sataAdapters[CFG_IDE_MAXBUS]; +static block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE]; +static unsigned int ide_initiated=0,ide_detected=0; + +MV_SATA_EDMA_PRD_ENTRY prd_table[2] __attribute__ ((aligned(32))); +unsigned char request_q[MV_EDMA_REQUEST_ENTRY_SIZE] __attribute__ ((aligned(1024))); +unsigned char response_q[MV_EDMA_RESPONSE_ENTRY_SIZE] __attribute__ ((aligned(256))); + +/* ------------------------------------------------------------------------- */ + +static MV_BOOLEAN StartPM(HW_ADAPTER_DESCRIPTION *sataAdapter, MV_U8 channelIndex); + +static MV_BOOLEAN initDisk(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex, + MV_U8 port, block_dev_desc_t *dev_desc); + +static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); + +static ulong pio_read_write (MV_SATA_ADAPTER *pSataAdapter, + unsigned int channelIndex, + MV_U8 port, + lbaint_t blknr, ulong blkcnt, ulong *buffer, int read); +static +ulong dma_read_write (MV_SATA_ADAPTER *pSataAdapter, + unsigned int channelIndex, + MV_U8 port, + lbaint_t blknr, ulong blkcnt, ulong *buffer, int read); +static +ulong dma_read_write_cmd (MV_SATA_ADAPTER *pSataAdapter, + unsigned int channelIndex, + MV_U8 port, + lbaint_t blknr, ulong blkcnt, ulong *buffer, int read); +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_PCI + +static struct pci_device_id supported[] = { + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5080}, + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5081}, + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5040}, + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_5041}, + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_6041}, + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_6081}, + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_6042}, + {MV_SATA_VENDOR_ID, MV_SATA_DEVICE_ID_7042}, +}; + +#endif /* CONFIG_PCI */ + + +int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int rcode = 0; + + /* Check if we have already called reset or not */ + if (ide_initiated == 0) + { + /* If this is not a call to reset !!!! */ + if (!((argc==2)&&(strncmp(argv[1],"res",3) == 0))) + { + puts ("\nWarning: Please run 'ide reset' before running other ide commands \n\n"); + return 1; + } + } + else /* We have already called reset */ + { + if (ide_detected == 0) + { + puts ("\nno IDE devices available\n"); + return 1; + } + } + + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 2: + if (strncmp(argv[1],"res",3) == 0) { + puts ("\nReset IDE" +#ifdef CONFIG_IDE_8xx_DIRECT + " on PCMCIA " PCMCIA_SLOT_MSG +#endif + ": "); + + ide_init (); + return 0; + } else if (strncmp(argv[1],"inf",3) == 0) { + int i; + + putc ('\n'); + + for (i=0; i= CFG_IDE_MAXDEVICE)) { + puts ("\nno IDE devices available\n"); + return 1; + } + printf ("\nIDE device %x: ", curr_device); + dev_print(&ide_dev_desc[curr_device]); + return 0; + } else if (strncmp(argv[1],"part",4) == 0) { + int dev, ok; + + for (ok=0, dev=0; devusage); + return 1; + case 3: + if (strncmp(argv[1],"dev",3) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + printf ("\nIDE device %x: ", dev); + if (dev >= CFG_IDE_MAXDEVICE) { + puts ("unknown device\n"); + return 1; + } + dev_print(&ide_dev_desc[dev]); + /*ide_print (dev);*/ + + if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { + return 1; + } + + curr_device = dev; + + puts ("... is now current device\n"); + + return 0; + } else if (strncmp(argv[1],"part",4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) { + print_part(&ide_dev_desc[dev]); + } else { + printf ("\nIDE device %x not available\n", dev); + rcode = 1; + } + return rcode; + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + default: + /* at least 4 args */ + + if (strcmp(argv[1],"read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + + if (curr_device == -1) + { + printf ("\n\nIDE device not available\n"); + return 1; + } +#ifdef CFG_64BIT_STRTOUL + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf ("\nIDE read: device %x block # %qd, count %ld ... ", + curr_device, blk, cnt); +#else + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf ("\nIDE read: device %x block # %ld, count %ld ... ", + curr_device, blk, cnt); +#endif + + n = ide_dev_desc[curr_device].block_read (curr_device, + blk, cnt, + (ulong *)addr); + /* flush cache after read */ + flush_cache (addr, cnt*ide_dev_desc[curr_device].blksz); + + printf ("%ld blocks read: %s\n", + n, (n==cnt) ? "OK" : "ERROR"); + if (n==cnt) { + return 0; + } else { + return 1; + } + } else if (strcmp(argv[1],"write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + + if (curr_device == -1) + { + printf ("\n\nIDE device not available\n"); + return 1; + } +#ifdef CFG_64BIT_STRTOUL + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf ("\nIDE write: device %x block # %qd, count %ld ... ", + curr_device, blk, cnt); +#else + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf ("\nIDE write: device %x block # %ld, count %ld ... ", + curr_device, blk, cnt); +#endif + + n = ide_write (curr_device, blk, cnt, (ulong *)addr); + + printf ("%ld blocks written: %s\n", + n, (n==cnt) ? "OK" : "ERROR"); + if (n==cnt) { + return 0; + } else { + return 1; + } + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + rcode = 1; + } + + return rcode; + } +} + +int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *boot_device = NULL; + char *ep; + int dev, part = 0; + ulong cnt; + ulong addr; + disk_partition_t info; + image_header_t *hdr; + int rcode = 0; + + switch (argc) { + case 1: + addr = CFG_LOAD_ADDR; + boot_device = getenv ("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv ("bootdevice"); + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + break; + default: + printf ("Usage:\n%s\n", cmdtp->usage); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (!boot_device) { + puts ("\n** No boot device **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + dev = simple_strtoul(boot_device, &ep, 16); + + if (ide_dev_desc[dev].type==DEV_TYPE_UNKNOWN) { + printf ("\n** Device %x not available\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (*ep) { + if (*ep != ':') { + puts ("\n** Invalid boot device, use `dev[:part]' **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + part = simple_strtoul(++ep, NULL, 16); + } + if (get_partition_info (&ide_dev_desc[dev], part, &info)) { + SHOW_BOOT_PROGRESS (-1); + return 1; + } + if ((strncmp((const char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) && + (strncmp((const char *)info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)) { + printf ("\n** Invalid partition type \"%.32s\"" + " (expect \"" BOOT_PART_TYPE "\")\n", + info.type); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + printf ("\nLoading from IDE device %x, partition %d: " + "Name: %.32s Type: %.32s\n", + dev, part, info.name, info.type); + + DP ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", + info.start, info.size, info.blksz); + + if (ide_dev_desc[dev].block_read (dev, info.start, 1, (ulong *)addr) != 1) { + printf ("** Read error on %x:%d\n", dev, part); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + hdr = (image_header_t *)addr; + + if (ntohl(hdr->ih_magic) == IH_MAGIC) { + + print_image_hdr (hdr); + + cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); + cnt += info.blksz - 1; + cnt /= info.blksz; + cnt -= 1; + } else { + printf("\n** Bad Magic Number **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (ide_dev_desc[dev].block_read (dev, info.start+1, cnt, + (ulong *)(addr+info.blksz)) != cnt) { + printf ("** Read error on %x:%d\n", dev, part); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + + /* Loading ok, update default load address */ + + load_addr = addr; + + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { + char *local_args[2]; + extern int do_bootm (cmd_tbl_t *, int, int, char *[]); + + local_args[0] = argv[0]; + local_args[1] = NULL; + + printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + + do_bootm (cmdtp, 0, 1, local_args); + rcode = 1; + } + return rcode; +} + +/* ------------------------------------------------------------------------- */ +MV_SATA_DEVICE_TYPE mvGetSataDeviceType( + MV_STORAGE_DEVICE_REGISTERS *mvStorageDevRegisters) +{ + if (((mvStorageDevRegisters->sectorCountRegister & 0xff) != 1) || + ((mvStorageDevRegisters->lbaLowRegister & 0xff) != 1)) + { + return MV_SATA_DEVICE_TYPE_UNKNOWN; + } + if (((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0) && + ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0)) + { + return MV_SATA_DEVICE_TYPE_ATA_DISK; + } + if ((((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0x14) && + ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0xEB))/* || + (((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0x69) && + ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0x96))*/) + { + return MV_SATA_DEVICE_TYPE_ATAPI_DEVICE; + } + if (((mvStorageDevRegisters->lbaMidRegister & 0xff) == 0x69) && + ((mvStorageDevRegisters->lbaHighRegister & 0xff) == 0x96)) + { + return MV_SATA_DEVICE_TYPE_PM; + } + return MV_SATA_DEVICE_TYPE_UNKNOWN; +} + +MV_BOOLEAN mvGetPMDeviceInfo(MV_SATA_ADAPTER *pSataAdapter, + MV_U8 channelIndex, + MV_SATA_PM_DEVICE_INFO *pPMDeviceInfo) +{ + MV_U32 regVal; + + if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT, + MV_SATA_GSCR_ID_REG_NUM, ®Val, NULL) == MV_FALSE) + { + printf("Error [%d %d]: Failed to read PM GSCR ID register\n", + pSataAdapter->adapterId, channelIndex); + return MV_FALSE; + } + pPMDeviceInfo->vendorId = (MV_U16)(regVal & 0xffff); + pPMDeviceInfo->deviceId = (MV_U16)((regVal & 0xffff0000) >> 16); + + if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT, + MV_SATA_GSCR_REVISION_REG_NUM, ®Val, NULL)== MV_FALSE) + { + printf("Error:[%d %d]: Failed to read PM GSCR REVISION register\n", pSataAdapter->adapterId, + channelIndex); + return MV_FALSE; + } + pPMDeviceInfo->PMSpecRevision = (MV_U8)(regVal & 0xff); + pPMDeviceInfo->productRevision = (MV_U8)((regVal & 0xff00) >> 8); + + if (mvPMDevReadReg(pSataAdapter, channelIndex, MV_SATA_PM_CONTROL_PORT, + MV_SATA_GSCR_INFO_REG_NUM, ®Val, NULL)== MV_FALSE) + { + printf("Error: [%d %d]: Failed to read PM GSCR INFO\n", pSataAdapter->adapterId, + channelIndex); + return MV_FALSE; + } + pPMDeviceInfo->numberOfPorts = (MV_U8)(regVal & 0xf); + return MV_TRUE; +} + +static MV_BOOLEAN +StartPM(HW_ADAPTER_DESCRIPTION *sataAdapter, + MV_U8 channelIndex) +{ + MV_SATA_ADAPTER *pSataAdapter = &sataAdapter->mvSataAdapter; + MV_U8 PMPort; + MV_SATA_PM_DEVICE_INFO PMInfo; + + if (mvGetPMDeviceInfo(pSataAdapter, channelIndex, &PMInfo) == MV_FALSE) { + printf("Error: Failed to get PortMultiplier Info\n", + pSataAdapter->adapterId, channelIndex); + return MV_FALSE; + } + printf("Port Multiplier found @ %d %d. Vendor: %04x ports: %d\n", + pSataAdapter->adapterId, channelIndex, PMInfo.vendorId, + PMInfo.numberOfPorts); + + for (PMPort = 0; PMPort < PMInfo.numberOfPorts; PMPort++){ + MV_U32 SStatus; + /* + * Skip PMPort #0 - this should be already enabled due to legacy mode + * transition of PM + */ + if (PMPort > 0) { + if (mvPMDevEnableStaggeredSpinUp(pSataAdapter, channelIndex, + PMPort) == MV_FALSE){ + printf("Error:[%d %d %d]: EnableStaggeredSpinUp Failed\n", + pSataAdapter->adapterId, channelIndex, PMPort); + if (mvStorageDevATASoftResetDevice(pSataAdapter, channelIndex, + MV_SATA_PM_CONTROL_PORT, NULL) == MV_FALSE) + { + printf("Error: [%d %d]: failed to Soft Reset PM control port\n" + , pSataAdapter->adapterId, channelIndex); + } + continue; + } + } + if (mvPMDevReadReg(pSataAdapter, channelIndex, PMPort, + MV_SATA_PSCR_SSTATUS_REG_NUM, &SStatus, NULL) == + MV_FALSE) + { + printf("Error:[%d %d %d]: mvPMDevReadReg Failed\n", + pSataAdapter->adapterId, channelIndex, PMPort); + if (mvStorageDevATASoftResetDevice(pSataAdapter, channelIndex, + MV_SATA_PM_CONTROL_PORT, NULL) == MV_FALSE) + { + printf("Error: [%d %d]: failed to Soft Reset PM control port\n" + , pSataAdapter->adapterId, channelIndex); + } + continue; + } + DP("[%d %d %x]: S-Status: 0x%x\n", pSataAdapter->adapterId, + channelIndex, PMPort, SStatus); + if ((SStatus & 0xf) == 3){ + if (mvPMDevWriteReg(pSataAdapter, channelIndex, PMPort, + MV_SATA_PSCR_SERROR_REG_NUM, 0xffffffff, NULL) == + MV_FALSE) + { + printf("Error [%d %d %d]: PM Write SERROR Failed\n", + pSataAdapter->adapterId, channelIndex, PMPort); + continue; + } + + sataAdapter->channelInfo[channelIndex].connected |= 1 << PMPort; + } + } + sataAdapter->channelInfo[channelIndex].numberOfPorts = PMInfo.numberOfPorts; + return MV_TRUE; +} + + +static MV_BOOLEAN StartChannel(HW_ADAPTER_DESCRIPTION *sataAdapter, + MV_U8 channelIndex) +{ + MV_SATA_ADAPTER *pSataAdapter = &sataAdapter->mvSataAdapter; + MV_STORAGE_DEVICE_REGISTERS ATARegs; + MV_SATA_CHANNEL *pSataChannel; + MV_SATA_DEVICE_TYPE deviceType; + + pSataChannel = pSataAdapter->sataChannel[channelIndex]; + if (!pSataChannel) + { + printf ("Error in StartChannel - Channel data structure is null\n"); + return MV_FALSE; + } + if (mvStorageDevATASoftResetDevice(pSataAdapter, + channelIndex, MV_PM, &ATARegs) == MV_FALSE) + { + printf("Error - Failed initializing(SRST) drive on channel %d\n", channelIndex); + return MV_FALSE; + } + deviceType = mvGetSataDeviceType(&ATARegs); + mvStorageDevSetDeviceType(pSataAdapter, channelIndex,deviceType); + sataAdapter->channelInfo[channelIndex].deviceType = deviceType; + sataAdapter->channelInfo[channelIndex].numberOfPorts = 0; + sataAdapter->channelInfo[channelIndex].connected = 0; + switch(deviceType) + { + case MV_SATA_DEVICE_TYPE_UNKNOWN: + printf("Error - unknown device at channel %d\n", channelIndex); + return MV_FALSE; + case MV_SATA_DEVICE_TYPE_ATAPI_DEVICE: + printf("Error - unknown device at channel %d\n", channelIndex); + return MV_FALSE; + case MV_SATA_DEVICE_TYPE_ATA_DISK: + sataAdapter->channelInfo[channelIndex].numberOfPorts = 1; + sataAdapter->channelInfo[channelIndex].connected = 1; + return MV_TRUE; + case MV_SATA_DEVICE_TYPE_PM: + return StartPM(sataAdapter, channelIndex); + } + + return MV_TRUE; +} +static MV_BOOLEAN initDisk(MV_SATA_ADAPTER *pSataAdapter, MV_U8 channelIndex, + MV_U8 port, block_dev_desc_t *dev_desc) +{ + MV_STORAGE_DEVICE_REGISTERS ATARegs; + ulong identifyBuffer[ATA_SECTORWORDS]; + hd_driveid_t *iop = (hd_driveid_t *)identifyBuffer; + MV_U16_PTR iden = (MV_U16_PTR) identifyBuffer; + MV_U8 PIOMode; +//Patch by QNAP:fix SATA DOM issue + MV_U8 UDMAMode=0; +/////////////////////////////////// + MV_SATA_DEVICE_TYPE deviceType = mvStorageDevGetDeviceType(pSataAdapter,channelIndex); + if (deviceType == MV_SATA_DEVICE_TYPE_PM) + { + if (mvStorageDevATASoftResetDevice(pSataAdapter, + channelIndex, port, &ATARegs) == MV_FALSE) + { + printf("Error - SRST for port %d on channel %d failed\n", port, channelIndex); + return MV_FALSE; + } + if(mvGetSataDeviceType(&ATARegs) != MV_SATA_DEVICE_TYPE_ATA_DISK) + { + // printf("Error: device at %d %d %d not supported\n", pSataAdapter->adapterId, channelIndex, port); + + return MV_FALSE; + } + } + + /* identify device*/ + memset(&ATARegs, 0, sizeof(ATARegs)); + ATARegs.commandRegister = MV_ATA_COMMAND_IDENTIFY; + if (mvStorageDevATAIdentifyDevice(pSataAdapter, channelIndex, port, + (unsigned short *)identifyBuffer) == MV_FALSE) + { + printf("[%d %d %d]: failed to perform ATA Identify command\n", pSataAdapter->adapterId, + channelIndex, port); + return MV_FALSE; + } + /* Check if read look ahead is supported. If so enable it */ + if (iden[IDEN_SUPPORTED_COMMANDS1] & MV_BIT6) + { + if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, port, + MV_ATA_SET_FEATURES_ENABLE_RLA,0,0,0, 0) == MV_FALSE) + { + printf("[%d %d %d]: failed to perform Enable RLA command\n", pSataAdapter->adapterId, + channelIndex, port); + return MV_FALSE; + } + } + if ((iden[IDEN_VALID] & MV_BIT1) == 0) + { + printf("[%d %d %d]: Unable to find PIO Mode\n", pSataAdapter->adapterId, channelIndex, port); + return MV_FALSE; + } + else if (iden[IDEN_PIO_MODE_SPPORTED] & MV_BIT0) + { + PIOMode = MV_ATA_TRANSFER_PIO_3; + } + else if (iden[IDEN_PIO_MODE_SPPORTED] & MV_BIT1) + { + PIOMode = MV_ATA_TRANSFER_PIO_4; + } + else + { + printf("[%d %d %d]: PIO modes 3 and 4 are not supported\n", pSataAdapter->adapterId, channelIndex, port); + PIOMode = MV_ATA_TRANSFER_PIO_SLOW; + } + if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, port, + MV_ATA_SET_FEATURES_TRANSFER,PIOMode,0,0, 0) == MV_FALSE) + { + printf("[%d %d %d]: failed to enable PIO mode\n", + pSataAdapter->adapterId, channelIndex, port); + return MV_FALSE; + } + +//Patch by QNAP:fix SATA DOM issue +/* + if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, port, + MV_ATA_SET_FEATURES_TRANSFER, + MV_ATA_TRANSFER_UDMA_5, + 0,0, 0) == MV_FALSE) + { + printf("[%d %d %d]: failed to perform Enable DMA mode\n", + pSataAdapter->adapterId, channelIndex, port); + return MV_FALSE; + } +*/ + if ((iden[IDEN_VALID] & MV_BIT2) == 0) + { + printf("[%d %d %d]: Unable to find UDMA Mode\n", pSataAdapter->adapterId, channelIndex, port); + return MV_FALSE; + } + else if (iden[IDEN_UDMA_MODE] & MV_BIT6) + { + UDMAMode = MV_ATA_TRANSFER_UDMA_6; + } + else if (iden[IDEN_UDMA_MODE] & MV_BIT5) + { + UDMAMode = MV_ATA_TRANSFER_UDMA_5; + } + else if (iden[IDEN_UDMA_MODE] & MV_BIT4) + { + UDMAMode = MV_ATA_TRANSFER_UDMA_4; + } + else if (iden[IDEN_UDMA_MODE] & MV_BIT3) + { + UDMAMode = MV_ATA_TRANSFER_UDMA_3; + } + else if (iden[IDEN_UDMA_MODE] & MV_BIT2) + { + UDMAMode = MV_ATA_TRANSFER_UDMA_2; + } + else if (iden[IDEN_UDMA_MODE] & MV_BIT1) + { + UDMAMode = MV_ATA_TRANSFER_UDMA_1; + } + else if (iden[IDEN_UDMA_MODE] & MV_BIT0) + { + UDMAMode = MV_ATA_TRANSFER_UDMA_0; + } + if (UDMAMode != 0 && mvStorageDevATASetFeatures(pSataAdapter, channelIndex, port, + MV_ATA_SET_FEATURES_TRANSFER, + UDMAMode, + 0,0, 0) == MV_FALSE) + { + printf("[%d %d %d]: failed to perform Enable DMA mode\n", + pSataAdapter->adapterId, channelIndex, port); + return MV_FALSE; + } +///////////////////////////////// + printf("[%d %d %d]: Enable DMA mode\n", pSataAdapter->adapterId, channelIndex, port); + /* Continue parsing identify buffer*/ + int device; + device=dev_desc->dev; + printf (" Device %d @ %d %d", device, pSataAdapter->adapterId, channelIndex); + if(deviceType == MV_SATA_DEVICE_TYPE_PM) + printf(" %d:\n", port); + else + printf(":\n"); + + ident_cpy (dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision)); + ident_cpy (dev_desc->vendor, iop->model, sizeof(dev_desc->vendor)); + ident_cpy (dev_desc->product, iop->serial_no, sizeof(dev_desc->product)); + + if ((iop->config & 0x0080)==0x0080) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + +#ifdef __BIG_ENDIAN + /* swap shorts */ + dev_desc->lba = (iop->lba_capacity << 16) | (iop->lba_capacity >> 16); +#else /* ! __BIG_ENDIAN */ + dev_desc->lba = iop->lba_capacity; +#endif /* __BIG_ENDIAN */ + +#ifdef CONFIG_LBA48 + if (iop->command_set_2 & 0x0400) { /* LBA 48 support */ + dev_desc->lba48 = 1; + dev_desc->lba = (unsigned long long)iop->lba48_capacity[0] | + ((unsigned long long)iop->lba48_capacity[1] << 16) | + ((unsigned long long)iop->lba48_capacity[2] << 32) | + ((unsigned long long)iop->lba48_capacity[3] << 48); + } else { + dev_desc->lba48 = 0; + } +#endif /* CONFIG_LBA48 */ + + /* assuming HD */ + dev_desc->type=DEV_TYPE_HARDDISK; + dev_desc->blksz=ATA_BLOCKSIZE; + dev_desc->lun=0; /* just to fill something in... */ + + return MV_TRUE; +} + +void +InitChannel( + PHW_ADAPTER_DESCRIPTION HwDeviceExtension, + MV_U8 channelIndex) +{ + MV_SATA_ADAPTER *pSataAdapter = &(HwDeviceExtension->mvSataAdapter); + MV_SATA_CHANNEL *pSataChannel; + + pSataChannel = &HwDeviceExtension->mvSataChannels[channelIndex]; + pSataAdapter->sataChannel[channelIndex] = pSataChannel; + pSataChannel->channelNumber = channelIndex; + pSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *)request_q; + pSataChannel->requestQueuePciLowAddress = (MV_U32)request_q; + pSataChannel->requestQueuePciHiAddress = 0; + pSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *) response_q; + pSataChannel->responseQueuePciLowAddress = (MV_U32)response_q; + pSataChannel->responseQueuePciHiAddress = 0; +} + +MV_BOOLEAN +mvSataEventNotify(MV_SATA_ADAPTER *pSataAdapter, MV_EVENT_TYPE eventType, + MV_U32 param1, MV_U32 param2) +{ + + switch (eventType) + { + case MV_EVENT_TYPE_SATA_CABLE: + switch(param1) + { + case MV_SATA_CABLE_EVENT_CONNECT: + printf("[%d,%d]: device connected event received\n", + pSataAdapter->adapterId, param2); + break; + case MV_SATA_CABLE_EVENT_DISCONNECT: + printf("[%d,%d]: device disconnected event received \n", + pSataAdapter->adapterId, param2); + break; + case MV_SATA_CABLE_EVENT_PM_HOT_PLUG: + printf("[%d,%d]: Port Multiplier hotplug event received \n", + pSataAdapter->adapterId, param2); + break; + default: + printf( "illegal value for param1(%d) at " + "connect/disconect event, host=%d\n", param1, + pSataAdapter->adapterId ); + } + break; + case MV_EVENT_TYPE_ADAPTER_ERROR: + printf("DEVICE error event received, pci cause " + "reg=%x, don't know how to handle this\n", param1); + return MV_TRUE; + case MV_EVENT_TYPE_SATA_ERROR: + switch (param1) + { + case MV_SATA_RECOVERABLE_COMMUNICATION_ERROR: + printf(" [%d %d] sata recoverable error occured\n", + pSataAdapter->adapterId, param2); + break; + case MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR: + printf(" [%d %d] sata unrecoverable error occured, restart channel\n", + pSataAdapter->adapterId, param2); + break; + case MV_SATA_DEVICE_ERROR: + printf( " [%d %d] device error occured\n", + pSataAdapter->adapterId, param2); + break; + } + break; + default: + printf(" adapter %d unknown event %d" + " param1= %x param2 = %x\n", pSataAdapter->adapterId, + eventType - MV_EVENT_TYPE_ADAPTER_ERROR, param1, param2); + return MV_FALSE; + + }/*switch*/ + + return MV_TRUE; +} + +/* ------------------------------------------------------------------------- */ +#define bus_to_phys(devno, a) pci_mem_to_phys(devno, a) + +void ide_init (void) +{ + int j, numOfDrives; + int idx = 0; + unsigned int temp, initAdapterResult, pciCommand; + unsigned short stemp; + MV_SATA_ADAPTER *pMvSataAdapter; + int devno = 0; + unsigned char channelIndex; + unsigned int numOfIdeDev = 0; + unsigned int numOfAdapters = 0; + MV_BOOLEAN integratedSataDetected = MV_FALSE; + MV_BOOLEAN integratedSataInitialized = MV_FALSE; + +#ifdef MV_LOGGER +#if defined (MV_LOG_DEBUG) + mvLogRegisterModule(MV_CORE_DRIVER_LOG_ID, 0x1FF, + szModules[MV_CORE_DRIVER_LOG_ID]); +#elif defined (MV_LOG_ERROR) + mvLogRegisterModule(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + szModules[MV_CORE_DRIVER_LOG_ID]); +#endif +#endif + printf("\nMarvell Serial ATA Adapter\n"); + curr_device = -1; + + memset(sataAdapters,0, sizeof(HW_ADAPTER_DESCRIPTION)*CFG_IDE_MAXBUS); + /* Init ide structure */ + for(j = 0; j < CFG_IDE_MAXDEVICE; j++) + { + ide_dev_desc[j].type=DEV_TYPE_UNKNOWN; + ide_dev_desc[j].if_type=IF_TYPE_IDE; + ide_dev_desc[j].dev=j; + ide_dev_desc[j].part_type=PART_TYPE_UNKNOWN; + ide_dev_desc[j].blksz=0; + ide_dev_desc[j].lba=0; + ide_dev_desc[j].block_read=ide_read; + } + + while ((numOfIdeDev < CFG_IDE_MAXDEVICE) && (numOfAdapters < CFG_IDE_MAXBUS)) { + MV_BOOLEAN integratedSataDevice = MV_FALSE; + numOfDrives = 0; + + #if defined(MV_INCLUDE_INTEG_SATA) + + if (integratedSataInitialized != MV_TRUE) + { + if (MV_FALSE == mvCtrlPwrClckGet(SATA_UNIT_ID, 0)) + { + printf("Warning Integrated SATA is Powered Off\n"); + } + else + { + integratedSataDetected = MV_TRUE; + integratedSataDevice = MV_TRUE; + + mvSataWinInit(); + printf("Integrated Sata device found\n"); + } + } + + #endif + + +#ifdef CONFIG_PCI + if ((integratedSataDetected == MV_FALSE) || + (integratedSataInitialized == MV_TRUE)) + { + /* Find PCI device(s) */ + if ((devno = pci_find_devices(supported, idx++)) < 0) { + if(!numOfAdapters) printf("no device found \n"); + break; + } + } +#endif /* CONFIG_PCI */ + + integratedSataInitialized = MV_TRUE; + sataAdapters[numOfAdapters].devno = devno; + sataAdapters[numOfAdapters].valid = MV_TRUE; + + memset (&sataAdapters[numOfAdapters].mvSataAdapter, 0, sizeof(MV_SATA_ADAPTER)); + pMvSataAdapter = &sataAdapters[numOfAdapters].mvSataAdapter; + + if (integratedSataDevice == MV_TRUE){ + pMvSataAdapter->adapterIoBaseAddress = INTER_REGS_BASE + SATA_REG_BASE - 0x20000; + pMvSataAdapter->pciConfigDeviceId = mvCtrlModelGet(); + pMvSataAdapter->pciConfigRevisionId = 0; + } +#ifdef CONFIG_PCI + else{ + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0 ,&temp); + pMvSataAdapter->adapterIoBaseAddress = bus_to_phys(devno, (temp & 0xfffffff0)); + pci_read_config_word(devno, PCI_DEVICE_ID, &stemp); + pMvSataAdapter->pciConfigDeviceId = stemp; + pci_read_config_word(devno, PCI_REVISION_ID, &stemp); + pMvSataAdapter->pciConfigRevisionId = stemp & 0xff; + } +#endif /*CONFIG_PCI */ + + pMvSataAdapter->adapterId = numOfAdapters; + + pMvSataAdapter->intCoalThre[0]= 4; + pMvSataAdapter->intCoalThre[1]= 4; + pMvSataAdapter->intTimeThre[0] = 150*50 ; + pMvSataAdapter->intTimeThre[1] = 150*50; + pMvSataAdapter->mvSataEventNotify = mvSataEventNotify; + pMvSataAdapter->IALData = (void *)&sataAdapters[numOfAdapters]; + pMvSataAdapter->pciSerrMask = MV_PCI_SERR_MASK_REG_ENABLE_ALL; + pMvSataAdapter->pciInterruptMask = 0; + pMvSataAdapter->pciCommand = MV_PCI_COMMAND_REG_DEFAULT; + +#ifdef CONFIG_PCI + if (integratedSataDevice != MV_TRUE) { + /* Enable master / IO / Memory accesses */ + pci_read_config_dword(devno, PCI_COMMAND ,&pciCommand); + pci_write_config_dword(devno, PCI_COMMAND, pciCommand | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + printf("Found adapter at bus %d, device %d ... Scanning channels\n",PCI_BUS(devno), PCI_DEV(devno)); + } +#endif /*CONFIG_PCI */ + /* Init adapter */ + initAdapterResult = mvSataInitAdapter(pMvSataAdapter); + if (initAdapterResult == MV_FALSE){ + printf("Error Initializing SATA Adapter\n"); + sataAdapters[numOfAdapters].valid = MV_FALSE; + numOfAdapters ++; + continue; + } + + /* Enable staggered spin-up of all SATA channels */ + if (mvSataEnableStaggeredSpinUpAll(pMvSataAdapter) == MV_FALSE) { + printf("Error in mvSataEnableStaggeredSpinUpAll\n"); + sataAdapters[numOfAdapters].valid = MV_FALSE; + numOfAdapters ++; + continue; + } + /* when sending DMA command we poll interrupt for completion*/ + mvSataUnmaskAdapterInterrupt(pMvSataAdapter); + + /* find and init channels */ + for (channelIndex = 0 ; channelIndex < pMvSataAdapter->numberOfChannels ; channelIndex++) { + if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channelIndex, NULL) == + MV_TRUE){ + DP("Channel %x is connected ... ", channelIndex); + InitChannel(&sataAdapters[numOfAdapters], channelIndex); + if (mvSataConfigureChannel(pMvSataAdapter, channelIndex) == + MV_FALSE) + { + printf("Error in mvSataConfigureChannel on channel %d\n",channelIndex); + pMvSataAdapter->sataChannel[channelIndex] = NULL; + numOfIdeDev++; + + } + else if (StartChannel(&sataAdapters[numOfAdapters], + channelIndex) == MV_FALSE){ + printf ("Failed initializing storage deivce connected " + "to SATA channel %d\n",channelIndex); + pMvSataAdapter->sataChannel[channelIndex] = NULL; + numOfIdeDev++; + }else{ + int port; + MV_CHANNEL_INFO *channelInfo=&sataAdapters[numOfAdapters].channelInfo[channelIndex]; + for(port = 0; port < channelInfo->numberOfPorts; port++){ + if(!(channelInfo->connected & (1 << port))) + { + numOfIdeDev++; + continue; + } + + if(initDisk(pMvSataAdapter, channelIndex, port, &ide_dev_desc[numOfIdeDev]) == MV_FALSE){ + /* mark it as not connected */ + sataAdapters[numOfAdapters].channelInfo[channelIndex].connected &= ~(1 << port); + numOfIdeDev++; + continue; + } + // printf("OK\n"); + dev_print(&ide_dev_desc[numOfIdeDev]); + if ((ide_dev_desc[numOfIdeDev].lba > 0) && + (ide_dev_desc[numOfIdeDev].blksz > 0)) + { + init_part (&ide_dev_desc[numOfIdeDev]); /* initialize partition type */ + if (curr_device < 0) + curr_device = numOfIdeDev; + } + numOfDrives++; + numOfIdeDev++; + } + } + }else{ + pMvSataAdapter->sataChannel[channelIndex] = NULL; + sataAdapters[numOfAdapters].channelInfo[channelIndex].numberOfPorts = 1; + numOfIdeDev++; + } + + } + + numOfAdapters++; + } + + ide_detected = numOfIdeDev; + ide_initiated=1; + + putc ('\n'); +} + +/* ------------------------------------------------------------------------- */ + +block_dev_desc_t * ide_get_dev(int dev) +{ + return ((block_dev_desc_t *)&ide_dev_desc[dev]); +} + +/* ------------------------------------------------------------------------- */ + +ulong ide_read_write (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer, int read) +{ + MV_SATA_ADAPTER *pSataAdapter = NULL; + unsigned int channelIndex = 0; + unsigned int adapter; + int port; + char *env; + + /* read count is 0 no read is needed */ + if(blkcnt == 0) { + return 0; + } + + /* data buffer must be 2 bytes aligned */ + if((long)buffer & 1) { + printf("\nide error: address (0x%08p) is not 2 bytes aligned!\n",buffer); + return 0; + } + + + DP("ide %s: device %x, blknr %x blkcnt %x, buffer %x\n", + ((read)?"read":"write"),device, (unsigned int)blknr, blkcnt, (unsigned int)buffer); + /* find device */ + for(adapter = 0 ; adapter < CFG_IDE_MAXBUS; adapter++) + { + if(sataAdapters[adapter].valid == MV_FALSE) + continue; + + pSataAdapter = &(sataAdapters[adapter].mvSataAdapter); + + for(channelIndex = 0; channelIndex < pSataAdapter->numberOfChannels; channelIndex++) + { + for(port = 0; port < sataAdapters[adapter].channelInfo[channelIndex].numberOfPorts; port++) + { + if(device == 0) + goto found_device; + + device--; + } + } + } + +found_device: + if(adapter == CFG_IDE_MAXBUS) + { + printf("Error didn't find requested device (%d).\n", device); + return 0; + } + if(pSataAdapter->sataChannel[channelIndex] == NULL) + { + printf("Error No HD connection \n"); + return 0; + } + + env = getenv("sata_dma_mode"); + if(( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) )){ + return dma_read_write(pSataAdapter, channelIndex, port, + blknr, blkcnt, buffer, read); + }else { + return pio_read_write(pSataAdapter, channelIndex, port, + blknr, blkcnt, buffer, read); + } +} + +static +ulong pio_read_write (MV_SATA_ADAPTER *pSataAdapter, + unsigned int channelIndex, + MV_U8 port, + lbaint_t blknr, ulong blkcnt, ulong *buffer, int read) +{ + MV_STORAGE_DEVICE_REGISTERS inATARegs; + MV_STORAGE_DEVICE_REGISTERS outATARegs; + MV_BOOLEAN isExt = MV_FALSE; + unsigned int command; + ulong blk_transferred = 0; + + +#if (__BE) + if(read == 0) + swapATABuffer((unsigned short *)buffer, blkcnt * ATA_SECTOR_SIZE); +#endif + + /* read all blocks */ + while(blkcnt > 0) { + ulong cmd_blkcnt = (blkcnt > 128 ) ? 128 : blkcnt; + + /* Set transfer mode */ + memset(&inATARegs, 0, sizeof(inATARegs)); + memset(&outATARegs, 0, sizeof(outATARegs)); + inATARegs.commandRegister = (read)? MV_ATA_COMMAND_READ_SECTORS: MV_ATA_COMMAND_WRITE_SECTORS; + inATARegs.sectorCountRegister = cmd_blkcnt; + inATARegs.lbaLowRegister = ((blknr >> 0) & 0xFF); + inATARegs.lbaMidRegister = ((blknr >> 8) & 0xFF); + inATARegs.lbaHighRegister = ((blknr >> 16) & 0xFF); + inATARegs.deviceRegister = BIT6 | ((blknr >> 24) & 0xF); + +#ifdef CONFIG_LBA48 + /* more than 28 bits used, use 48bit mode */ + if (blknr & IDE_BLOCK_NUMBER_MASK) { + inATARegs.commandRegister = (read)? MV_ATA_COMMAND_READ_SECTORS_EXT : MV_ATA_COMMAND_WRITE_SECTORS_EXT; + inATARegs.lbaLowRegister |= ((blknr >> LBA_LOW_REG_SHIFT) & 0xFF) << 8; + inATARegs.lbaMidRegister |= ((blknr >> LBA_MID_REG_SHIFT) & 0xFF) << 8; + inATARegs.lbaHighRegister |= ((blknr >> LBA_HIGH_REG_SHIFT) & 0xFF) << 8; + inATARegs.deviceRegister = BIT6; + isExt = MV_TRUE; + } +#endif + command = (read)? MV_NON_UDMA_PROTOCOL_PIO_DATA_IN: MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT; + if (mvStorageDevExecutePIO(pSataAdapter, channelIndex, port, command, + isExt, (MV_U16 *)buffer, (cmd_blkcnt * 512)/2 , &inATARegs, &outATARegs) == MV_FALSE) + { + printf("[%d %d]: %s Fail for PIO\n", + pSataAdapter->adapterId, channelIndex, ((read)?"Read":"Write")); + return 0; + } + blknr += cmd_blkcnt; + blkcnt = blkcnt - cmd_blkcnt; + buffer += (cmd_blkcnt * ATA_SECTORWORDS); + blk_transferred += cmd_blkcnt; + } +#if (__BE) + swapATABuffer((unsigned short *)buffer, blkcnt * ATA_SECTOR_SIZE); +#endif + + return blk_transferred; +} +static int command_completed; +static MV_COMPLETION_TYPE completion_type; +static +MV_BOOLEAN cmd_callback(struct mvSataAdapter *pSataAdapter, + MV_U8 channel_index, + MV_COMPLETION_TYPE type, + MV_VOID_PTR command_id, MV_U16 edma_error_cause, + MV_U32 time_stamp, + struct mvStorageDevRegisters *deviceRegs){ + command_completed = 1; + completion_type = type; + return MV_TRUE; +} +ulong dma_read_write (MV_SATA_ADAPTER *pSataAdapter, + unsigned int channelIndex, + MV_U8 port, + lbaint_t blknr, ulong blkcnt, ulong *buffer, int read) +{ + int res = 0; + int transfered_blks = 0; + + /* we use single PRD table entry (limited to 64KB - 128 sector) */ + while(blkcnt){ + int chunk = (blkcnt > 128) ? 128: blkcnt; + + res = dma_read_write_cmd(pSataAdapter, channelIndex, port, blknr, chunk, + buffer, read) ; + + if(res != chunk) + return transfered_blks; + + transfered_blks += res; + buffer += res << 7; //buffer is in long + blknr += res; + blkcnt -= res; + } + return transfered_blks; +} + +static +ulong dma_read_write_cmd (MV_SATA_ADAPTER *pSataAdapter, + unsigned int channelIndex, + MV_U8 port, + lbaint_t blknr, ulong blkcnt, ulong *buffer, int read) +{ + MV_QUEUE_COMMAND_INFO q_cmd_info; + MV_UDMA_COMMAND_PARAMS *udmaCommand = &q_cmd_info.commandParams.udmaCommand; + MV_SATA_DEVICE_TYPE deviceType; + MV_U32 byte_count = blkcnt << 9; + MV_U32 buffer_addr = (MV_U32) buffer; + + if ( blkcnt > 128){ + printf("error in %s: blk count %d exceeded max limit\n", + __func__, blkcnt); + } + + // mvSataDisableChannelDma(pSataAdapter, channelIndex); + /* reset the request/response pointers as we allcated one entry*/ + /* but some info need to be preserved */ + deviceType = mvStorageDevGetDeviceType(pSataAdapter, channelIndex); + mvSataConfigureChannel(pSataAdapter, channelIndex); + mvStorageDevSetDeviceType(pSataAdapter, channelIndex,deviceType); + mvSataConfigEdmaMode(pSataAdapter, channelIndex, + MV_EDMA_MODE_NOT_QUEUED, 2); + mvSataEnableChannelDma(pSataAdapter, channelIndex); + + + memset(&q_cmd_info, 0, sizeof(MV_QUEUE_COMMAND_INFO)); + memset(prd_table, 0, 2 * sizeof(MV_SATA_EDMA_PRD_ENTRY)); + + /* buffer must not cross address decode window */ + if(((buffer_addr & MRVL_SATA_BOUNDARY_MASK) + byte_count) > MRVL_SATA_BUFF_BOUNDARY) + { + MV_U32 chunk_len = MRVL_SATA_BUFF_BOUNDARY - + (buffer_addr & MRVL_SATA_BOUNDARY_MASK); + + memset(prd_table + 1, 0, sizeof(MV_SATA_EDMA_PRD_ENTRY)); + prd_table[0].lowBaseAddr = cpu_to_le32(buffer_addr); + prd_table[0].byteCount = cpu_to_le16(chunk_len & 0xFFFF); + + byte_count -= chunk_len; + buffer_addr += chunk_len; + prd_table[1].lowBaseAddr = cpu_to_le32(buffer_addr); + prd_table[1].byteCount = cpu_to_le16(byte_count & 0xFFFF); + prd_table[1].flags = cpu_to_le16(MV_EDMA_PRD_EOT_FLAG); + + } + else + { + prd_table[0].lowBaseAddr = cpu_to_le32(buffer_addr); + prd_table[0].byteCount = cpu_to_le16(byte_count & 0xFFFF); + prd_table[0].flags = cpu_to_le16(MV_EDMA_PRD_EOT_FLAG); + } + + q_cmd_info.type = MV_QUEUED_COMMAND_TYPE_UDMA; + q_cmd_info.PMPort = port; + udmaCommand->readWrite = (read)? MV_UDMA_TYPE_READ : MV_UDMA_TYPE_WRITE; + udmaCommand->isEXT = MV_FALSE; + +#ifdef CONFIG_LBA48 + /* more than 28 bits used, use 48bit mode */ + if (blknr & IDE_BLOCK_NUMBER_MASK) { + udmaCommand->isEXT = MV_TRUE; + } +#endif + + udmaCommand->FUA = MV_FALSE; + udmaCommand->lowLBAAddress = blknr & 0xFFFFFFFF; + udmaCommand->highLBAAddress = (blknr >> 32 )& 0xFFFFFFFF; + udmaCommand->numOfSectors = blkcnt; + udmaCommand->prdLowAddr = (MV_U32)prd_table; + udmaCommand->callBack = cmd_callback; +#if 0 + printf("send dma command: %s lba %x sect %x addr %x\n", read?"read":"write", + udmaCommand->lowLBAAddress, udmaCommand->numOfSectors, + prd_table[0].lowBaseAddr); +#endif + command_completed = 0; + if(mvSataQueueCommand(pSataAdapter, + channelIndex, + &q_cmd_info) != MV_QUEUE_COMMAND_RESULT_OK){ + printf("error in mv_ide: queue command failed\n"); + mvSataDisableChannelDma(pSataAdapter, channelIndex); + return 0; + } + + do{ + mvSataInterruptServiceRoutine(pSataAdapter); + udelay(1000); + + }while(!command_completed); + + mvSataDisableChannelDma(pSataAdapter, channelIndex); + if(completion_type == MV_COMPLETION_TYPE_NORMAL) + return blkcnt; + else + return 0; +} + +/* ------------------------------------------------------------------------- */ +#if (__BE) +void swapATABuffer(unsigned short *buffer, ulong count) +{ + count >>= 1; + while(count--) + { + buffer[count] = MV_CPU_TO_LE16(buffer[count]); + } +} +#endif + +ulong ide_read (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer) +{ + return ide_read_write (device, blknr, blkcnt, buffer, MV_TRUE); +} + +ulong ide_write (int device, lbaint_t blknr, ulong blkcnt, ulong *buffer) +{ + return ide_read_write (device, blknr, blkcnt, buffer, MV_FALSE); +} + +/* ------------------------------------------------------------------------- */ + +/* + * copy src to dest, skipping leading and trailing blanks and null + * terminate the string + * "len" is the size of available memory including the terminating '\0' + */ +static void ident_cpy (unsigned char *dst, unsigned char *src, unsigned int len) +{ + unsigned char *end, *last; + + last = dst; + + /* Make sure lenis multiple of 2 + 1 for '\0'*/ + if( !(len % 2) || (len == 0)) + goto OUT; + + end = src + len - 1; + + while ((*src) && (src +#include +#include +#include "mvSysHwConfig.h" +#if defined(MV_INCLUDE_MONT_EXT) && defined (MV_INCLUDE_MONT_LOAD_NET) + +#if CONFIG_COMMANDS & CFG_CMD_BSP + +#include "mvTypes.h" +#include "idma/mvIdma.h" + + + +extern void d_i_cache_clean(unsigned int Address, unsigned int byteCount); +extern unsigned int VIRTUAL_TO_PHY(unsigned int address); + +/* defines relevant for the protocol between the loadnet and the fileloader.*/ +#define ENTRY_ADDR_OFFSET 0x2c - ETHER_HDR_SIZE - IP_HDR_SIZE +#define PKT_HEADER_SIZE 0x38 - ETHER_HDR_SIZE - IP_HDR_SIZE +#define LAST_PACKET_FLAG 0xffffffff + +#define NL_HASHES_PER_LINE 65 + +/* indication for loadnet reached EOF */ +static MV_BOOL loadnet_done; +/* the real load address */ +static MV_U32 loadnet_addr_gl; +/* the files Size that was receied by loadnet. */ +static MV_U32 fileSize; +/* in case we received an srec file, the srec program Entry. */ +static MV_U32 programAdressEntry; +/* for print banner */ +static MV_U32 NetloadBlock; + +/* This function will be called from the NetReceive (net.c) whenever we will receive + * a UDP packet with our IP address. + * This function know how to process the packets received from the Marvell file + * Loader utility. + * input - pointer to the packet buffer after stripping the IP header. + * (other input aren't relevant for us in this function) + * output - update the global parameters, see above. + */ +static void +mv_private_loadnet_handler(uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + + MV_U32 entryAddress,byteCount,sourceAddress,destAddress; + MV_U32 packetEnd; + + /* print progress.*/ + NetloadBlock++; + putc ('#'); + if ((NetloadBlock % (NL_HASHES_PER_LINE)) == 0) { + puts ("\n"); + } + + /* in case the file Loader transfer Srec to Bin it will send us the + entry address of each packet data. */ + /* fixed for MIPS alignment was: entryAddress = (*(MV_U32 *)(pkt + ENTRY_ADDR_OFFSET)); */ + entryAddress = 0; +#ifdef CONFIG_MV_LE + entryAddress |= *(unsigned char *)(pkt + ENTRY_ADDR_OFFSET + 0) << 24; + entryAddress |= *(unsigned char *)(pkt + ENTRY_ADDR_OFFSET + 1) << 16; + entryAddress |= *(unsigned char *)(pkt + ENTRY_ADDR_OFFSET + 2) << 8; + entryAddress |= *(unsigned char *)(pkt + ENTRY_ADDR_OFFSET + 3) << 0; +#else + { + int i; + for(i = 0; i < 2; i++ ){ + entryAddress |= (*(unsigned short *)(pkt + ENTRY_ADDR_OFFSET + i*2)) << ((1-i)*16);} + } +#endif + /* last packet of a received file is marked. */ + if(entryAddress == LAST_PACKET_FLAG){ + loadnet_done = 1; + return;} + /* the byte count of the packet data */ +#ifdef CONFIG_MV_LE + byteCount = 0; + byteCount |= *(unsigned char *)(pkt + ENTRY_ADDR_OFFSET +6) << 8; + byteCount |= *(unsigned char *)(pkt + ENTRY_ADDR_OFFSET +7); +#else + byteCount = (*(short *)(pkt + ENTRY_ADDR_OFFSET +6)) ; +#endif + packetEnd = entryAddress + byteCount; + + /* should be set only in the first time */ + if(programAdressEntry == 0x0){ + programAdressEntry = entryAddress; + debug("programAdressEntry = %x\n",programAdressEntry);} + if(loadnet_addr_gl == 0x0){ + loadnet_addr_gl = entryAddress; + debug("loadnet_addr_gl = %x\n",loadnet_addr_gl);} + + destAddress = (MV_U32)(entryAddress - programAdressEntry + + loadnet_addr_gl); + sourceAddress = (MV_U32)(pkt + PKT_HEADER_SIZE); + + debug(" Transfering from Source %x to Dest %x %x bytes\n",\ + sourceAddress,destAddress,byteCount); + + memcpy((MV_U32*)destAddress,(MV_U32*)sourceAddress,byteCount); + + fileSize = packetEnd - programAdressEntry; + + return; +} +/* load a file through the network interface, using UDP protocol only!! + * ( this function is basically the client for Marvell fileLoader utility. ) + * this function doesn't transmit any thing, only receive!! + * input - the address you want the file to be loaded to. + * if set to 0, the file will be loaded to the address given by the file + * loader according to the srec entry address. + * output - the address that the file was loaded to. + * return - the file size received from the file loader. + */ +int load_net(MV_U32 *loadnet_addr){ + + DECLARE_GLOBAL_DATA_PTR; + bd_t *bd = gd->bd; + + /* delay for MIPS LE stuck issue - probably unstable board. ??? */ + printf("\n"); + eth_halt(); + /* initilize the ethernet port */ + if(eth_init(bd) < 0) + return(-1); + /* set the Network parameters */ + memcpy (NetOurEther, bd->bi_enetaddr, 6); + NetCopyIP(&NetOurIP, &bd->bi_ip_addr); + NetOurGatewayIP = getenv_IPaddr ("gatewayip"); + NetOurSubnetMask= getenv_IPaddr ("netmask"); + NetServerIP = getenv_IPaddr ("serverip"); + /* set the Rx handler */ + NetSetHandler (mv_private_loadnet_handler); + /* initialize global parameters. */ + programAdressEntry = 0; + loadnet_done = 0; + fileSize = 0; + loadnet_addr_gl = *loadnet_addr; + NetloadBlock = 0; + + printf("Load File - Send your file when ready...\n"); + /* main loop */ + for (;;) { + /* Check the ethernet for a new packet. The ethernet + * receive routine will process it. */ + eth_rx(); + + /* Abort if ctrl-c was pressed. */ + if (ctrlc()) { + eth_halt(); + printf("\nAbort\n"); + return (-1); + } + /* if load net detected EOF*/ + if(loadnet_done == 1) break; + } + /* close the ethernet port */ + eth_halt(); + *loadnet_addr = loadnet_addr_gl; + return fileSize; +} + +int +loadnet_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int size; + MV_U32 tmp = 0; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + size = load_net(&tmp); + printf("\nFile loaded successfully...\n"); + printf("Entry Address: 0x%x\n",tmp); + printf("File size: %d bytes.\n",size); + return 1; + +} + + +U_BOOT_CMD( + ln, 1, 1, loadnet_cmd, + "ln - Load S-Record executable file through the network interface. \n", + "\t \n" + "\tLoad S-Record executable file via thr first avilable ethernet port.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +#endif + +#endif /* #if defined(MV_INCLUDE_MONT_EXT) */ diff --git a/board/mv_feroceon/USP/mv_mon_init.c b/board/mv_feroceon/USP/mv_mon_init.c new file mode 100644 index 0000000..a1df9b8 --- /dev/null +++ b/board/mv_feroceon/USP/mv_mon_init.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2001 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + /* + * Dink_command.c - driver for special Marvell coammnds taken from Dink. + */ + +#include +#include +#include + +#include "mvSysHwConfig.h" +#if defined(MV_INCLUDE_MONT_EXT) + +#include "mvTypes.h" +#include "mvCtrlEnvLib.h" +#include "mvCpuIf.h" +#include "cpu/mvCpu.h" +#include "mv_fs.h" + +#if defined(MV_INCLUDE_MONT_MMU) +extern void pageTableInit(void); +#endif +#if defined(MV_INCLUDE_MONT_MPU) +extern void MPU_Init(void); +#endif + +#if defined(MV_INCLUDE_MONT_MMU) + +/***********************************************************************************/ +/* hook function that is called after CPU detection and Serial init and before */ +/* initializing of the DRAM. */ +/***********************************************************************************/ + +int PTexist(void) +{ + char *env; +#ifdef CFG_MV_PT + env = getenv("enaPT"); +#ifdef CONFIG_MV_LE + /* if LE page table disable is the default. ( MIPS - unstable, PPC need to change the page settings) */ + if( ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ){ +#else + /* if BE page table enable is the default. */ + if(!env || ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ){ +#endif + return 1; + } +#endif + return 0; +} +#endif +/***********************************************************************************/ +/* hook function that is called after rellocating to the DRAM, Flash Init, PCI init*/ +/* and malloc init are done, and before Gig port init. */ +/***********************************************************************************/ +#if defined(MV78200) +extern MV_VOID mvDramIfCpuWinCopy(MV_VOID); +#endif +void mon_extension_after_relloc(void) +{ +#if defined(MV_INCLUDE_MONT_FFS) + unsigned int status; +#endif +#if defined(MV78XX0) && defined(MV78200) + char *env; + if (whoAmI() == MASTER_CPU) + { + /* default no MP */ + env = getenv("enaMP"); + if(env && ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + { + if (IS_CPU1_ENABLED) + { + /* Copy CPU 0 address map to CPU 1 */ + mvAhbToMbusCpuWinCopy(); + /* Copy CPU 0 DRAM address map to CPU 1 */ + mvDramIfCpuWinCopy(); + /* kick of the second CPU!! */ + MV_REG_BIT_RESET(CPU_CTRL_STAT_REG(1), BIT3); + //sleep(2000); + setenv("enaMP","yes"); + } + } + else +#endif + { + setenv("enaMP","no"); + } +#if defined(MV78XX0) && defined(MV78200) + } +#endif + +#if defined(MV_INCLUDE_MONT_MMU) + if ((mvOsCpuPartGet() == CPU_PART_ARM926) || + (mvOsCpuPartGet() == CPU_PART_MRVL131)) + { + /* Page Table */ + if(PTexist() ) + { + pageTableInit(); + + /* set the stack to be cachable */ + __asm__ __volatile__ ( " orr sp, sp, #0x80000000 " : ); + setenv("enaPT","yes"); + } + else + setenv("enaPT","no"); + } +#endif /* MV_INCLUDE_MONT_MMU */ +#ifndef MV_TINY_IMAGE + +#if defined(MV_INCLUDE_MONT_MPU) + else if (mvOsCpuPartGet() == CPU_PART_ARM946) + { + char *env; + env = getenv("enaMPU"); + + if ((!env)||( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) )) + { + setenv("enaMPU","yes"); + MPU_Init(); + } + } +#endif /* MV_INCLUDE_MONT_MPU */ + +#if CONFIG_COMMANDS & CFG_CMD_BSP + #if defined(MV_INCLUDE_MONT_FFS) + if (whoAmI() == MASTER_CPU) + { + status = mvFSInit(FS_NO_CACHE); + + + if(!(status == FS_NO_VALID_FAT_STRING || status == FS_OFFSET_OUT_OF_RANGE)) + { + printf("File system present and initialized on the main Flash Memory\n"); + } + } + else + { + printf("No File system on the main Flash Memory\n"); + } + #endif /* MV_INCLUDE_MONT_FFS */ +#endif +#endif + return; +} +#endif /* #if defined(MV_INCLUDE_MONT_EXT) */ + diff --git a/board/mv_feroceon/USP/mv_mon_init.h b/board/mv_feroceon/USP/mv_mon_init.h new file mode 100644 index 0000000..a4e0825 --- /dev/null +++ b/board/mv_feroceon/USP/mv_mon_init.h @@ -0,0 +1,36 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#ifndef __INCmvMONEXTh +#define __INCmvMONEXTh + +#ifdef __cplusplus +extern "C" { +#endif + +void mon_extension_before_relloc(void); +void mon_extension_after_relloc(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCmvMONEXTh */ + diff --git a/board/mv_feroceon/USP/mv_nand.c b/board/mv_feroceon/USP/mv_nand.c new file mode 100644 index 0000000..cbcfe4b --- /dev/null +++ b/board/mv_feroceon/USP/mv_nand.c @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2005 2N TELEKOMUNIKACE, Ladislav Michl + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include +#include +#include "mvBoardEnvLib.h" + +/* + * hardware specific access to control-lines + */ +#define MASK_CLE 0x01 +#define MASK_ALE 0x02 + + +static void mv_nand_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *this = mtd->priv; + ulong IO_ADDR_W = (ulong) this->IO_ADDR_W; + /* TODO add auto detect for nand width */ + MV_U32 shift = 0; + + if (shift == MV_ERROR) + { + printf("No NAND detection\n"); + shift = 0; + } + + IO_ADDR_W &= ~((MASK_ALE|MASK_CLE) << shift); + switch (cmd) { + case NAND_CTL_SETCLE: IO_ADDR_W |= (MASK_CLE << shift); break; + case NAND_CTL_SETALE: IO_ADDR_W |= (MASK_ALE << shift); break; + } + this->IO_ADDR_W = (void *) IO_ADDR_W; +} + + +int board_nand_init(struct nand_chip *nand) +{ +#if defined(MV_LARGE_PAGE) + nand->options = NAND_SAMSUNG_LP_OPTIONS; +#endif + + nand->eccmode = NAND_ECC_SOFT; + nand->hwcontrol = mv_nand_hwcontrol; + nand->chip_delay = 1000; + return 0; +} +#endif diff --git a/board/mv_feroceon/USP/mv_pageTable.c b/board/mv_feroceon/USP/mv_pageTable.c new file mode 100644 index 0000000..26ade6a --- /dev/null +++ b/board/mv_feroceon/USP/mv_pageTable.c @@ -0,0 +1,592 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +/* Code for setting up pagetables or the protection unit, + * and enabling the cache. */ + +#include +#include +#include +#include + +#include "mvSysHwConfig.h" +#if defined(MV_INCLUDE_MONT_EXT) && defined (MV_INCLUDE_MONT_MMU) + +#include "mvCpuIf.h" +#include "cpu/mvCpu.h" + + +int mpuMap(void); + +/* This file refers to the A.R.M.--The ARM Architecture Reference Manual */ + +enum access +{ + NO_ACCESS, + NO_USR_W, + SVC_RW, + ALL_ACCESS +}; + +enum entrytype +{ + INVALID, + PAGE, + SECTION +}; + +#define U_BIT 16 +#define C_BIT 8 +#define B_BIT 4 + +#define WRITE_BACK (C_BIT|B_BIT) +#define WRITE_THROUGH (C_BIT) + +#define L1Entry(type,addr,dom,ucb,acc) \ + ( (type == SECTION) ? ( ((addr) & 0xfff00000) | \ + ((acc) << 10) | ((dom) << 5) | \ + (ucb) | (type) ) : \ + (type == PAGE) ? ( ((addr) &0xfffffc00) | \ + ((dom) << 5) | \ + ((ucb) & U_BIT) | (type) ) : \ + 0) + +#define L1EntryAddr(type, entry) \ + ( (type == SECTION) ? ((entry) & 0xfff00000): \ + (type == PAGE) ? ((entry) &0xfffffc00):0) + +#define L1EntryAcc(type, entry) \ + (((entry) & 0xc00) >> 10) + +#define L1EntryUcb(type, entry) \ + ((entry) & 0x1c) + +#define L1EntryType(type, entry) \ + ((entry) & 0x3) + +static void detectPageTable(void) +{ + int i; + unsigned int *p = (unsigned int *)CFG_PT_BASE; + unsigned int entry; + unsigned int ucb; + unsigned int acc; + unsigned int nextEntry; + char* envCacheMode = getenv("cacheMode"); + unsigned int startVirAddr = 0; + unsigned int startPhyAddr = 0; + + + if(envCacheMode && (strcmp(envCacheMode,"write-through") == 0)) + { + + printf("Cache Mode - write-through\n"); + } + else /*"write-back"*/ + { + printf("Cache Mode - write-back\n"); + } + + printf("page table:\n"); + for (i = 0; i < 4096; i++) + { + entry = *p; + nextEntry = *(++p); + ucb = L1EntryUcb(SECTION, entry); + acc = L1EntryAcc(SECTION, entry); + if ( (ucb != L1EntryUcb(SECTION, nextEntry))|| + (acc != L1EntryAcc(SECTION, nextEntry))|| + (L1EntryAddr(SECTION, entry) > L1EntryAddr(SECTION, nextEntry)) || + ((L1EntryAddr(SECTION, entry) + _1M) < L1EntryAddr(SECTION, nextEntry))) + { + printf("Section (0x%08x - 0x%08x) =>",startPhyAddr, ((i << 20)| 0xfffff)); + printf(" (0x%08x - 0x%08x)",startVirAddr, (L1EntryAddr(SECTION, entry)| 0xfffff)); + if (ucb & C_BIT) + printf(" Cachable/Bufferable"); + else + printf(" Non-Cachable/Bufferable"); + + switch(acc){ + case(NO_ACCESS): + printf("\tNO_ACCESS"); + break; + case(NO_USR_W): + printf("\tNO_USR_W"); + break; + case(SVC_RW): + printf("\tSVC_RW"); + break; + case(ALL_ACCESS): + printf("\tALL_ACCESS"); + break; + default: + printf("\tALL_ACCESS"); + break; + } + printf("\n"); + startVirAddr = L1EntryAddr(SECTION, nextEntry); + startPhyAddr = ((i+1) << 20); + } + } +} + +static unsigned int createPageTable(void) +{ + int i; + unsigned int *p = 0; + unsigned int entry; + char* envCacheMode = getenv("cacheMode"); + unsigned int cacheMode; + +#if defined(MV78XX0) + if (whoAmI() == MASTER_CPU) + p = (unsigned int *)CFG_PT_BASE; + else + p = (unsigned int *)CFG_PT_BASE_SLAVE_CPU; +#else + p = (unsigned int *)CFG_PT_BASE; +#endif + + if(envCacheMode && (strcmp(envCacheMode,"write-through") == 0)) + { + setenv("cacheMode","write-through"); + cacheMode = WRITE_THROUGH; + } + else /*"write-back"*/ + { + setenv("cacheMode","write-back"); + cacheMode = WRITE_BACK; + } + + /* first region 0 MB - 0x10000000(256MB) none cacheable/bufferable */ + entry = L1Entry(SECTION, 0, 0, U_BIT, ALL_ACCESS); + for (i = 0; i < 256; i++) + { + *p++ = (entry | (i << 20)); + } + + /* second region 0x10000000 (256MB) - 0x80000000 (2GB) cacheable/bufferable */ + entry = L1Entry(SECTION, 0, 0, U_BIT|cacheMode, ALL_ACCESS); + for (; i < 2048 ; i++) + { + *p++ = (entry | (i << 20)); + } + + /* 3rd region 0x80000000 (2GB) - 0x90000000 cacheable/ bufferable to 0x0*/ + entry = L1Entry(SECTION, 0, 0, U_BIT|cacheMode, ALL_ACCESS); + for (; i < 2304; i++) + { + *p++ = (entry | ((i - 2048) << 20)); + } + + /* 4rd region 0x90000000 - 0xa0000000 not cacheable/not bufferable */ + entry = L1Entry(SECTION, 0, 0, U_BIT, ALL_ACCESS); + for (; i < 2560; i++) + { + *p++ = (entry | (i << 20)); + } + + /* 5th region 0xa0000000 - 0xb0000000 cacheable/bufferable to 0x90000000 */ + entry = L1Entry(SECTION, 0, 0, U_BIT|cacheMode, ALL_ACCESS); + for (; i < 2816; i++) + { + *p++ = (entry | ((i - 256) << 20)); + } + + /* 6th region 0xb0000000 - 0xe0000000 cacheable/bufferable */ + entry = L1Entry(SECTION, 0, 0, U_BIT|cacheMode, ALL_ACCESS); + for (; i < 3584; i++) + { + *p++ = (entry | (i << 20)); + } + + /* 7th region 0xe0000000 - 0xf0000000 cacheable/bufferable to 0xf0000000 */ + entry = L1Entry(SECTION, 0, 0, U_BIT|cacheMode, ALL_ACCESS); + for (; i < 3840; i++) + { + *p++ = (entry | ((i+256) << 20)); + } + + /* 8th region 0xf0000000 - 0xffffffff none cacheable/bufferable */ + entry = L1Entry(SECTION, 0, 0, U_BIT, ALL_ACCESS); + for (; i < 4096; i++) + { + *p++ = (entry | (i << 20)); + } + +#if defined(MV78XX0) + if (whoAmI() == MASTER_CPU) + return CFG_PT_BASE; + else + return CFG_PT_BASE_SLAVE_CPU; +#else + return CFG_PT_BASE; +#endif +} + +extern int PTexist(void); +int cpumap_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + printf("CPU Memory mapping :\n"); + if ((mvOsCpuPartGet() == CPU_PART_ARM926) || + (mvOsCpuPartGet() == CPU_PART_MRVL131)) + { + if(enaMonExt()) + { + if(PTexist()) + { + detectPageTable(); + } + else + printf("No page table. \n"); + } + else + printf("No page table. \n"); + + + } +#ifndef MV_TINY_IMAGE +#if defined(MV_INCLUDE_MONT_EXT) && defined (MV_INCLUDE_MONT_MPU) + else if (mvOsCpuPartGet() == CPU_PART_ARM946) + { + mpuMap(); + } +#endif +#endif + return 1; +} + +U_BOOT_CMD( + cpumap, 1, 1, cpumap_cmd, + "cpumap - Display CPU memory mapping settings.\n", + " \n" + "\tdisplay CPU memory mapping settings.\n" +); + +/* These are all the bits currently defined for the control register */ +/* A.R.M. 7.4.2 */ +#define MMU_V 0x2000 +#define MMU_I 0x1000 +#define MMU_Z 0x0800 +#define MMU_F 0x0400 +#define MMU_R 0x0200 +#define MMU_S 0x0100 +#define MMU_B 0x0080 +#define MMU_RES 0x50078 /* reserved bits should be 1 */ +#define MMU_C 0x0004 +#define MMU_A 0x0002 +#define MMU_M 0x0001 + + + +/* + * The functions below take arguments to specify which "caches" the + * action is to be directed at. For the I-cache, pass "MMU_I". For + * the D-cache, "MMU_C". For both, pass "MMU_ID". For combined ID-Cache + * processors, use "MMU_C" + */ +#define MMU_ID (MMU_I + MMU_C) + +/* + * Inline functions for MMU functions + */ + +/* Set the page tables base register: register 2 (A.R.M. 7.4.3) */ +inline void mmuSetPageTabBase(unsigned int pagetab) +{ + __asm__ __volatile__( + "mcr p15, 0, %0, c2, c0\n" + : + : "r" (pagetab)); +} + +/* Set the domain access-control register: register 3 (A.R.M. 7.4.4) */ +inline void mmuSetDomainAccessControl(unsigned long flags) +{ + __asm__ __volatile__( + "mcr p15, 0, %0, c3, c0\n" + : + : "r" (flags)); +} + +/* Flush the cache(s). + */ +inline void mmuInvCache(unsigned caches) +{ + unsigned long dummy = 0; + + switch (caches) + { + case MMU_C: + __asm__ __volatile__( + "mcr p15, 0, %0, c7, c6, 0\n" + : + : "r" (dummy)); + break; + case MMU_I: + __asm__ __volatile__( + "mcr p15, 0, %0, c7, c5, 0\n" + : + : "r" (dummy)); + + break; + case MMU_ID: + __asm__ __volatile__( + "mcr p15, 0, %0, c7, c7, 0\n" + : + : "r" (dummy)); + break; + } +} + +/* Flush the TLB(s) + */ +inline void mmuFlushTLB( unsigned tlbs) +{ + unsigned long dummy = 0; + + /* flush TLB(s): write to register 8, with flags (A.R.M. 7.4.9) */ + switch (tlbs) + { + case MMU_C: + __asm__ __volatile__( + "mcr p15, 0, %0, c8, c6, 0\n" + : + : "r" (dummy)); + break; + case MMU_I: + __asm__ __volatile__( + "mcr p15, 0, %0, c8, c5, 0\n" + : + : "r" (dummy)); + break; + case MMU_ID: + __asm__ __volatile__( + "mcr p15, 0, %0, c8, c7, 0\n" + : + : "r" (dummy)); + break; + } +} + +/* Enable the cache/MMU/TLB etc. + */ +inline void cpuCfgEnable(unsigned long flags, MV_BOOL enable) +{ + unsigned long tmp; + + if (enable == MV_TRUE) + { + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (tmp)); + tmp |= flags; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (tmp)); + } + else + { + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (tmp)); + tmp &= ~flags; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (tmp)); + } +} + +/* Disable the I/D cache. + */ + +inline void disableIDCache(void) +{ + unsigned long tmp; + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (tmp)); + tmp &= ~MMU_ID; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (tmp)); + + /* invalidate I/D-cache */ + tmp = 0; + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (tmp)); +} + +/* return 0 in case cache is absent */ +inline unsigned long getDCacheAssociativity(void) +{ + + unsigned long tmp, dassoc, mul; + + /* Read cache type information */ + /* Bit[11:0] - I cache size */ + /* Bit[23:12] - D cache size */ + /* Bit 24 - if '1' Seperate I-cache and D-cache */ + /* bit[28:24] - ctype */ + asm ("mrc p15, 0, %0, c0, c0, 1":"=r" (tmp)); + + /* D cache data only */ + /* Bit[1:0] - cache line length */ + /* Bit2 - M */ + /* Bit[5:3] - cache associativity */ + /* Bit[9:6] - cache size */ + tmp = (tmp >> 12) & 0xfff; + + /* Detect cache associativity - the formulae are teken from ARM DDI reference manual */ + mul = 2 + ((tmp >> 2) & 1); + dassoc = ((tmp >> 3) & 0x7); + if ((dassoc == 0) && (mul == 2)) + dassoc = 1; + else + { + if ((dassoc == 0) && (mul == 3)) + dassoc = 0; + else + dassoc = mul << (dassoc - 1); + } + + return dassoc; +} + +inline unsigned long getDCacheSize(void) +{ + + unsigned long tmp, dsize, mul; + + /* Read cache type information */ + /* Bit[11:0] - I cache size */ + /* Bit[23:12] - D cache size */ + /* Bit 24 - if '1' Seperate I-cache and D-cache */ + /* bit[28:24] - ctype */ + asm ("mrc p15, 0, %0, c0, c0, 1":"=r" (tmp)); + + /* D cache data only */ + /* Bit[1:0] - cache line length */ + /* Bit2 - M */ + /* Bit[5:3] - cache associativity */ + /* Bit[9:6] - cache size */ + tmp = (tmp >> 12) & 0xfff; + + /* Detect cache size - the formulae are teken from ARM DDI reference manual */ + mul = 2 + ((tmp >> 2) & 1); + dsize = ((tmp >> 6) & 0xf); + dsize = mul << (dsize + 8); + + return dsize; +} + +inline unsigned long getDCacheLine(void) +{ + + unsigned long tmp, dline; + + /* Read cache type information */ + /* Bit[11:0] - I cache size */ + /* Bit[23:12] - D cache size */ + /* Bit 24 - if '1' Seperate I-cache and D-cache */ + /* bit[28:24] - ctype */ + asm ("mrc p15, 0, %0, c0, c0, 1":"=r" (tmp)); + + /* D cache data only */ + /* Bit[1:0] - cache line length */ + /* Bit2 - M */ + /* Bit[5:3] - cache associativity */ + /* Bit[9:6] - cache size */ + tmp = (tmp >> 12) & 0xfff; + + /* Detect cache line - the formulae are teken from ARM DDI reference manual */ + dline = 1 << ((tmp & 0x3) + 3); + + return dline; +} + +extern ulong _dcache_index_max; +extern ulong _dcache_index_inc; +extern ulong _dcache_set_max; +extern ulong _dcache_set_index; + +void pageTableInit(void) +{ + unsigned long dsize, dassoc, dline, log2Assoc, tmp; + + printf("D-Cache type information\n"); + + /* Detect cache size */ + dsize = getDCacheSize(); + /* Detect cache number of way */ + dassoc = getDCacheAssociativity(); + /* Detect cache number of way */ + dline = getDCacheLine(); + + /* Detected cache absent */ + if (dassoc == 0) + { + printf("DCache absent!\n"); + return; + } + else + { + printf("DCache size: %dKB\n",dsize/1024); + printf("DCache associativity: %d way\n",dassoc); + printf("DCache line length: %dB\n",dline); + } + + + /* Calc num of digits for assoc representation */ + log2Assoc = 0; + tmp = dassoc - 1; + do + { + log2Assoc++; + tmp = tmp >> 1; + }while (tmp > 0); + + printf("Intializing Page Table..."); + + /* The num of assoc is set in the ip address from bit 31 backward */ + if (dassoc == 1) + { + _dcache_index_max = 0; + _dcache_index_inc = 0; + } + else + { + _dcache_index_max = ~ ((1 << (31 - log2Assoc + 1)) - 1); + _dcache_index_inc = (1 << (31 - log2Assoc + 1)); + } + + _dcache_set_max = (dsize/dassoc) - dline; + _dcache_set_index = dline; + + disableIDCache(); + /* Disable D cache and MMU. */ + cpuCfgEnable(MMU_C+MMU_M, MV_FALSE); + /* set up the page table, domain control registers */ + mmuSetPageTabBase(createPageTable()); + mmuSetDomainAccessControl(3); + /* flush caches and TLBs */ + mmuInvCache(MMU_ID); + mmuFlushTLB(MMU_ID); + /* write to control register :- + * I-cache on, 32-bit data and program space, + * write-buffer on, D-cache on, MMU on + */ + cpuCfgEnable(MMU_I+MMU_RES+MMU_C+MMU_M, MV_TRUE); + + printf("Done \n"); + return ; +} + +#endif /* defined(MV_INCLUDE_MONT_EXT) */ + + + diff --git a/board/mv_feroceon/USP/mv_pci.c b/board/mv_feroceon/USP/mv_pci.c new file mode 100644 index 0000000..bf94852 --- /dev/null +++ b/board/mv_feroceon/USP/mv_pci.c @@ -0,0 +1,837 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +/* PCI.c - PCI functions */ + +#include +#include +#include +#if (CONFIG_COMMANDS & CFG_CMD_PCI) + + +#include +#include "pci-if/mvPciIf.h" +#include "mvCpuIf.h" +#include "pci-if/pci_util/mvPciUtils.h" + + +#ifdef DEBUG +#define DB(x) x +#else +#define DB(x) +#endif /* DEBUG */ + +/* global definetion */ +#define REG_NUM_MASK (0x3F << 2) +/* global indicate wether we are in the scan process */ +unsigned int bus_scan = 0; + + +#if CONFIG_COMMANDS & CFG_CMD_BSP + +/****************************************************************************** +* Category - PCI0 +* Functionality- Scans PCI0 for devices and prints relevant information +* Need modifications (Yes/No) - No +*****************************************************************************/ +MV_BOOL scanPci(MV_U32 host) +{ + MV_U32 index,numOfElements=4*8,barIndex; + MV_PCI_DEVICE pciDevices[4*8]; //3 slots and us,Max 8 functions per slot + + memset (&pciDevices,0,12*sizeof(MV_PCI_DEVICE)); + + if (mvPciScan(host, pciDevices , &numOfElements) != MV_OK ) + { + printf("scanPci:mvPciScan failed for host %d \n",host); + return MV_FALSE; + } + + + for(index = 0; index < numOfElements ; index++) + { + printf("\nBus: %x Device: %x Func: %x Vendor ID: %x Device ID: %x\n", + pciDevices[index].busNumber, + pciDevices[index].deviceNum, + pciDevices[index].function, + pciDevices[index].venID, + pciDevices[index].deviceID); + + printf("-------------------------------------------------------------------\n"); + + printf("Class: %s\n",pciDevices[index].type); + + /* check if we are bridge*/ + if ((pciDevices[index].baseClassCode == PCI_BRIDGE_CLASS)&& + (pciDevices[index].subClassCode == P2P_BRIDGE_SUB_CLASS_CODE)) + { + printf("Primary Bus:0x%x \tSecondary Bus:0x%x \tSubordinate Bus:0x%x\n", + pciDevices[index].p2pPrimBusNum, + pciDevices[index].p2pSecBusNum, + pciDevices[index].p2pSubBusNum); + + printf("IO Base:0x%x \t\tIO Limit:0x%x",pciDevices[index].p2pIObase, + pciDevices[index].p2pIOLimit); + + (pciDevices[index].bIO32)? (printf(" (32Bit IO)\n")): + (printf(" (16Bit IO)\n")); + + printf("Memory Base:0x%x \tMemory Limit:0x%x\n",pciDevices[index].p2pMemBase, + pciDevices[index].p2pMemLimit); + + printf("Pref Memory Base:0x%x \tPref Memory Limit:0x%x", + pciDevices[index].p2pPrefMemBase, + pciDevices[index].p2pPrefMemLimit); + + (pciDevices[index].bPrefMem64)? (printf(" (64Bit PrefMem)\n")): + (printf(" (32Bit PrefMem)\n")); + if (pciDevices[index].bPrefMem64) + { + printf("Pref Base Upper 32bit:0x%x \tPref Limit Base Upper32 bit:0x%x\n", + pciDevices[index].p2pPrefBaseUpper32Bits, + pciDevices[index].p2pPrefLimitUpper32Bits); + } + } + + for (barIndex = 0 ; barIndex < pciDevices[index].barsNum ; barIndex++) + { + + if (pciDevices[index].pciBar[barIndex].barType == PCI_64BIT_BAR) + { + printf("PCI_BAR%d (%s-%s) base: %x%08x%s",barIndex, + (pciDevices[index].pciBar[barIndex].barMapping == PCI_MEMORY_BAR)?"Mem":"I/O", + "64bit", + pciDevices[index].pciBar[barIndex].barBaseHigh, + pciDevices[index].pciBar[barIndex].barBaseLow, + (pciDevices[index].pciBar[barIndex].barBaseLow == 0)?"\t\t":"\t"); + } + else if (pciDevices[index].pciBar[barIndex].barType == PCI_32BIT_BAR) + { + printf("PCI_BAR%d (%s-%s) base: %x%s",barIndex, + (pciDevices[index].pciBar[barIndex].barMapping == PCI_MEMORY_BAR)?"Mem":"I/O", + "32bit", + pciDevices[index].pciBar[barIndex].barBaseLow, + (pciDevices[index].pciBar[barIndex].barBaseLow == 0)?"\t\t\t":"\t\t"); + } + + if(pciDevices[index].pciBar[barIndex].barSizeHigh != 0) + printf("size: %d%08d bytes\n",pciDevices[index].pciBar[barIndex].barSizeHigh, + pciDevices[index].pciBar[barIndex].barSizeLow); + else + printf("size: %d bytes\n", pciDevices[index].pciBar[barIndex].barSizeLow); + } + } + return MV_TRUE; +} + + +int sp_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 host = 0; + + + if (argc > 1) { + host = simple_strtoul (argv[1], NULL, 10); + } + if(host >= mvCtrlPciIfMaxIfGet()){ + printf("PCI %d doesn't exist\n",host); + return 1; + } + if( scanPci(host) == MV_FALSE) + printf("PCI %d Scan - FAILED!!.\n",host); + return 1; +} + +U_BOOT_CMD( + sp, 2, 1, sp_cmd, + "sp - Scan PCI bus.\n", + " [0/1] \n" + "\tScan and detecect all devices on mvPCI bus 0/1 \n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +int me_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 host = 0; + if (argc > 1) + { + host = simple_strtoul (argv[1], NULL, 10); + } + + if(host >= mvCtrlPciIfMaxIfGet()) + { + printf("Master %d doesn't exist\n",host); + return 1; + } + + if(mvPciIfMasterEnable(host,MV_TRUE) == MV_OK) + printf("PCI %d Master enabled.\n",host); + else + printf("PCI %d Master enabled -FAILED!!\n",host); + + return 1; +} + +U_BOOT_CMD( + me, 2, 1, me_cmd, + "me - PCI master enable\n", + " [0/1] \n" + "\tEnable the MV device as Master on PCI 0/1. \n" +); + +int se_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 host=0,dev = 0,bus=0; + + if(argc != 4) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + host = simple_strtoul (argv[1], NULL, 10); + bus = simple_strtoul (argv[2], NULL, 16); + dev = simple_strtoul (argv[3], NULL, 16); + + if(host >= mvCtrlPciIfMaxIfGet()) + { + printf("PCI %d doesn't exist\n",host); + return 1; + } + if(mvPciIfSlaveEnable(host,bus,dev,MV_TRUE) == MV_OK ) + printf("PCI %d Bus %d Slave 0x%x enabled.\n",host,bus,dev); + else + printf("PCI %d Bus %d Slave 0x%x enabled - FAILED!!.\n",host,bus,dev); + return 1; +} + +U_BOOT_CMD( + se, 4, 1, se_cmd, + "se - PCI Slave enable\n", + " [0/1] bus dev \n" + "\tEnable the PCI device as Slave on PCI 0/1. \n" +); + +/****************************************************************************** +* Functionality- The commands changes the pci remap register and displays the +* address to be used in order to access PCI 0. +*****************************************************************************/ +int mapPci_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + MV_ADDR_WIN pciWin; + MV_TARGET target=0; + MV_U32 host=0,effectiveBaseAddress=0; + + pciWin.baseLow=0; + pciWin.baseHigh=0; + + if (argc > 1) { + host = simple_strtoul(argv[1], NULL, 10); + } + if(argc > 2) { + pciWin.baseLow = simple_strtoul(argv[2], NULL, 16); + } + if(host >= mvCtrlPciIfMaxIfGet()){ + printf("PCI %d doesn't exist\n",host); + return 1; + } + + target = PCI0_MEM0 + (2 * host); + + printf("mapping pci %x to address 0x%x\n",host,pciWin.baseLow); + +#if defined(MV_INCLUDE_PEX) || defined(MV_INCLUDE_PCI) + effectiveBaseAddress = mvCpuIfPciIfRemap(target,&pciWin); +#endif + + if ( effectiveBaseAddress == 0xffffffff) + { + printf("Error remapping\n"); + return 1; + } + + printf("PCI %x Access base address : %x\n",host,effectiveBaseAddress); + return 1; +} + +U_BOOT_CMD( + mp, 3, 1, mapPci_cmd, + "mp - map PCI BAR\n", + " [0/1] address \n" + "\tChange the remap of PCI 0/1 window 0 to address 'addrress'.\n" + "\tIt also displays the new access address, since the remap is not always\n" + "\tthe same as requested. \n" +); + +#endif + +MV_U32 mv_mem_ctrl_dev(MV_U32 pciIf, MV_U32 bus,MV_U32 dev) +{ + MV_U32 ven, class; + ven = mvPciIfConfigRead(pciIf,bus,dev,0,PCI_VENDOR_ID) & 0xffff; + class = (mvPciIfConfigRead(pciIf,bus,dev,0,PCI_REVISION_ID) >> 16 ) & 0xffff; + /* if we got any other Marvell PCI cards ignore it. */ + if(((ven == 0x11ab) && (class == PCI_CLASS_MEMORY_OTHER))|| + ((ven == 0x11ab) && (class == PCI_CLASS_BRIDGE_HOST))) + { + return 1; + } + return 0; +} + +static int mv_read_config_dword(struct pci_controller *hose, + pci_dev_t dev, + int offset, u32* value) +{ + MV_U32 bus,func,regOff,dev_no; + char *env; + + bus = PCI_BUS(dev); + dev_no = PCI_DEV(dev); + + func = (MV_U32)PCI_FUNC(dev); + regOff = (MV_U32)offset & REG_NUM_MASK; + + /* We will scan only ourselves and the PCI slots that exist on the + board, because we may have a case that we have one slot that has + a Cardbus connector, and because CardBus answers all IDsels we want + to scan only this slot and ourseleves. + */ + + #if defined(MV_INCLUDE_PCI) + env = getenv("pciMode"); + if ((PCI_IF_TYPE_CONVEN_PCIX == mvPciIfTypeGet((MV_U32)hose->cfg_addr)) && + ((strcmp(env,"host") == 0) || (strcmp(env,"Host") == 0))) + { + if ( !mvBoardIsOurPciSlot(bus, dev_no) && + (mvBoardIdGet() != DB_88F5181_DDR1_MNG) && + (DB_88F5181_DDR1_PRPMC != mvBoardIdGet()) && + (DB_88F5181_DDR1_PEXPCI != mvBoardIdGet())) + { + *value = 0xffffffff; + return 0; + } + } + #endif /* defined(MV_INCLUDE_PCI) */ + + if( bus_scan == 1 ) + { + env = getenv("disaMvPnp"); + if(env && ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + { + if( mv_mem_ctrl_dev((MV_U32)hose->cfg_addr, bus, dev_no) ) + { + *value = 0xffffffff; + return 0; + } + } + } + DB(printf("mv_read_config_dword hose->cfg_addr %x\n",hose->cfg_addr);) + DB(printf("mv_read_config_dword bus %x\n",bus);) + DB(printf("mv_read_config_dword dev_no %x\n",dev_no);) + DB(printf("mv_read_config_dword func %x\n",func);) + DB(printf("mv_read_config_dword regOff %x\n",regOff);) + + *value = (u32) mvPciIfConfigRead((MV_U32)hose->cfg_addr,bus,dev_no,func,regOff); + + DB(printf("mv_read_config_dword value %x\n",*value);) + + return 0; +} + +static int mv_write_config_dword(struct pci_controller *hose, + pci_dev_t dev, + int offset, u32 value) +{ + MV_U32 bus,func,regOff,dev_no; + + bus = PCI_BUS(dev); + dev_no = PCI_DEV(dev); + func = (MV_U32)PCI_FUNC(dev); + regOff = offset & REG_NUM_MASK; + mvPciIfConfigWrite((MV_U32)hose->cfg_addr,bus,dev_no,func,regOff,value); + + return 0; +} + + + +static void mv_setup_ide(struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ + static const int ide_bar[]={8,4,8,4,16,1024}; + u32 bar_response, bar_value; + int bar; + + for (bar=0; bar<6; bar++) + { + /*ronen different function for 3rd bank.*/ + unsigned int offset = (bar < 2)? bar*8: 0x100 + (bar-2)*8; + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, 0x0); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &bar_response); + + pciauto_region_allocate(bar_response & PCI_BASE_ADDRESS_SPACE_IO ? + hose->pci_io : hose->pci_mem, ide_bar[bar], &bar_value); + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, bar_value); + } +} + +static void mv_setup_host(struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ + //skip our host + DB(printf("skipping :bus=%x dev=%x fun=%x\n", + (unsigned int)PCI_BUS(dev), + (unsigned int)PCI_DEV(dev), + (unsigned int)PCI_FUNC(dev))); + return; +} + + +static void mv_pci_bus_mode_display(MV_U32 host) +{ + + + + if (PCI_IF_TYPE_PEX == mvPciIfTypeGet(host)) + { + #if defined(MV_INCLUDE_PEX) + + MV_PEX_MODE pexMode; + + if (mvPexModeGet(mvPciRealIfNumGet(host),&pexMode) != MV_OK) + { + printf("mv_pci_bus_mode_display: mvPexModeGet failed\n"); + } + + switch (pexMode.pexType) + { + case MV_PEX_ROOT_COMPLEX: + printf("PCI %d: PCI Express Root Complex Interface\n",host); + break; + case MV_PEX_END_POINT: + printf("PCI %d: PCI Express End Point Interface\n",host); + break; + } + + if (!(pexMode.pexLinkUp)) + { + printf("PEX interface detected no Link.\n"); + } + else + { + if (MV_PEX_WITDH_X1 == pexMode.pexWidth) + { + printf("PEX interface detected Link X1\n"); + } + else + { + printf("PEX interface detected Link X4\n"); + } + } + + return ; + + #endif /* MV_INCLUDE_PEX */ + } + + + + + + if (PCI_IF_TYPE_CONVEN_PCIX == mvPciIfTypeGet(host)) + { + #if defined(MV_INCLUDE_PCI) + + MV_PCI_MODE pciMode; + + if (mvPciModeGet(mvPciRealIfNumGet(host),&pciMode) != MV_OK) + { + printf("mv_pci_bus_mode_display: mvPciIfModeGet failed\n"); + + } + + switch (pciMode.pciType) + { + case MV_PCI_CONV: + + printf("PCI %d: Conventional PCI",host); + break; + + case MV_PCIX: + + printf("PCI %d: PCI-X",host); + break; + + default: + printf("PCI %d: Unknown",host); + return; + break; + + } + + printf(", speed = %d\n",pciMode.pciSpeed); + + #endif /* #if defined(MV_INCLUDE_PCI) */ + } + + + +} + +struct pci_config_table mv_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, mv_setup_ide}, + + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, mv_setup_host}, //PCI host + + {} + +}; + + +/* Defines for more modularity of the pci_init_board function */ + +struct pci_controller pci_hose[8]; + + +#if (MV_PCI_IF_MAX_IF == 2) + +#define PCI_IF_MEM(pciIf) ((pciIf==0)?PCI_IF0_MEM0:PCI_IF1_MEM0) +#define PCI_IF_REMAPED_MEM_BASE(pciIf) ((pciIf==0)?PCI_IF0_REMAPED_MEM_BASE:PCI_IF1_REMAPED_MEM_BASE) +#define PCI_IF_MEM_BASE(pciIf) ((pciIf==0)?PCI_IF0_MEM0_BASE:PCI_IF1_MEM0_BASE) +#define PCI_IF_MEM_SIZE(pciIf) ((pciIf==0)?PCI_IF0_MEM0_SIZE:PCI_IF1_MEM0_SIZE) +#define PCI_IF_IO_BASE(pciIf) ((pciIf==0)?PCI_IF0_IO_BASE:PCI_IF1_IO_BASE) +#define PCI_IF_IO_SIZE(pciIf) ((pciIf==0)?PCI_IF0_IO_SIZE:PCI_IF1_IO_SIZE) + +#else + +#define PCI_IF_MEM(pciIf) (PCI_IF0_MEM0) +#define PCI_IF_REMAPED_MEM_BASE(pciIf) (PCI_IF0_REMAPED_MEM_BASE) +#define PCI_IF_MEM_BASE(pciIf) (PCI_IF0_MEM0_BASE) +#define PCI_IF_MEM_SIZE(pciIf) (PCI_IF0_MEM0_SIZE) +#define PCI_IF_IO_BASE(pciIf) (PCI_IF0_IO_BASE) +#define PCI_IF_IO_SIZE(pciIf) (PCI_IF0_IO_SIZE) + +#endif + +/* because of CIV tem needs we are gonna do a remap to PCI memory */ +#define PCI_IF0_REMAPED_MEM_BASE 0x40000000 +#define PCI_IF1_REMAPED_MEM_BASE 0x40000000 + +void +pci_init_board(void) +{ + MV_U32 pciIfNum = mvCtrlPciIfMaxIfGet(); + MV_U32 pciIf=0; + MV_U32 regVal=0; + MV_ADDR_WIN rempWin; + char *env; + int first_busno=0; + int status; + MV_CPU_DEC_WIN cpuAddrDecWin; + PCI_IF_MODE pciIfMode = PCI_IF_MODE_HOST; + + env = getenv("disaMvPnp"); + + if(env && ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + printf("Warning: skip configuration of Marvell devices!!!\n"); +#if defined(MV_INCLUDE_PEX) && defined(MV78XX0) + /* Power down the none lanes 0.1, 0.2, and 0.3 if PEX0 is X4 */ + if ( !(PCI0_IS_QUAD_X1) ) + { + for (pciIf = 1; pciIf < 4; pciIf++) + mvCtrlPwrClckSet(PEX_UNIT_ID, mvPciRealIfNumGet(pciIf),MV_FALSE); + } + + /* Power down the none lanes 1.1, 1.2, and 1.3 if PEX1 is X4 */ + if ( !(PCI1_IS_QUAD_X1) ) + { + for (pciIf = 5; pciIf < 8; pciIf++) + mvCtrlPwrClckSet(PEX_UNIT_ID, mvPciRealIfNumGet(pciIf),MV_FALSE); + } +#endif + for (pciIf = 0; pciIf < pciIfNum; pciIf++) + { + pci_hose[pciIf].config_table = mv_config_table; + if (PCI_IF_TYPE_PEX == mvPciIfTypeGet(pciIf)) + { + if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, mvPciRealIfNumGet(pciIf))) + { + continue; + } + } +#if defined(MV_INCLUDE_PCI) + else + { + if (MV_FALSE == mvCtrlPwrClckGet(PCI_UNIT_ID, mvPciRealIfNumGet(pciIf))) + { + continue; + } + } +#endif + /* device or host ? */ + if (PCI_IF_TYPE_PEX == mvPciIfTypeGet(pciIf)) + { +#if defined(MV_INCLUDE_PEX) +#if !defined(MV_88F6183) && !defined(MV_88F6183L) && !defined(MV_88F6082) && !defined(MV88F6281) && \ + !defined(MV88F6192) && !defined(MV88F6180) && !defined(MV88F6190) + MV_PEX_MODE pexMode; + + if (mvPexModeGet(mvPciRealIfNumGet(pciIf),&pexMode) != MV_OK) + { + printf("pci_init_board: mvPexModeGet failed\n"); + } + + if (MV_PEX_ROOT_COMPLEX == pexMode.pexType) + pciIfMode = PCI_IF_MODE_HOST; + else + pciIfMode = PCI_IF_MODE_DEVICE; + +#else + /* Set pex mode incase S@R not exist */ + env = getenv("pexMode"); + if( env && ( ((strcmp(env,"EP") == 0) || (strcmp(env,"ep") == 0) ))) + { + pciIfMode = PCI_IF_MODE_DEVICE; + } + else + { + pciIfMode = PCI_IF_MODE_HOST; + } +#endif +#endif + } + else /* PCI */ + { + #if defined(MV_INCLUDE_PCI) + char *env; + env = getenv("pciMode"); + if((!env) || (strcmp(env,"host") == 0) || (strcmp(env,"Host") == 0) ) + { + pciIfMode = PCI_IF_MODE_HOST; + } + else + { + pciIfMode = PCI_IF_MODE_DEVICE; + } + #endif + } + + + if ((status = mvPciIfInit(pciIf, pciIfMode)) == MV_ERROR) + { + printf("pci_init_board:Error calling mvPciIfInit for pciIf %d\n",pciIf); + } + else + { + if (status == MV_OK) + mv_pci_bus_mode_display(pciIf); + else + { + /* Interface with no link */ + printf("PEX %d: interface detected no Link.\n", pciIf); + return; + } + } + + if (PCI_IF_TYPE_CONVEN_PCIX == mvPciIfTypeGet(pciIf)) + { + #if defined(MV_INCLUDE_PCI) + if(enaMonExt()) + { + /* WA for first PCI interface */ + /* mvPciWaFix(mvPciRealIfNumGet(pciIf)); */ + } + #endif /* MV_INCLUDE_PCI */ + + if (pciIfMode == PCI_IF_MODE_DEVICE) + { + mvPciIfLocalDevNumSet(pciIf, 0x1f); + } + } + +#if defined(DB_PRPMC) + mvPciIfLocalDevNumSet(pciIf, 0x1f); +#endif + + /* start Uboot PCI scan */ + if (pciIf == 0) + pci_hose[pciIf].first_busno = 0; + else + pci_hose[pciIf].first_busno = pci_hose[pciIf-1].last_busno + 1; + + /* start Uboot PCI scan */ + pci_hose[pciIf].current_busno = pci_hose[pciIf].first_busno; + pci_hose[pciIf].last_busno = 0xff; + + if (mvPciIfLocalBusNumSet(pciIf,pci_hose[pciIf].first_busno) != MV_OK) + { + printf("pci_init_board:Error calling mvPciIfLocalBusNumSet for pciIf %d\n",pciIf); + } + + /* If no link on the interface it will not be scan */ + if (status == MV_NO_SUCH) + { + pci_hose[pciIf].last_busno =pci_hose[pciIf].first_busno; + continue; + } + +#ifdef PCI_DIS_INTERFACE + /* The disable interface will not be scan */ + if (pciIf == PCI_DIS_INTERFACE) + { + printf("***Interface is disable***\n"); + pci_hose[pciIf].last_busno =pci_hose[pciIf].first_busno; + continue; + } +#endif + if (MV_OK != mvCpuIfTargetWinGet(PCI_MEM(pciIf, 0), &cpuAddrDecWin)) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return ; + } + + rempWin.baseLow = ((cpuAddrDecWin.addrWin.baseLow & 0x0fffffff) | PCI_IF_REMAPED_MEM_BASE(pciIf)); + rempWin.baseHigh = 0; + + /* perform a remap for the PEX0 interface*/ + if (0xffffffff == mvCpuIfPciIfRemap(PCI_MEM(pciIf, 0),&rempWin)) + { + printf("%s:mvCpuIfPciIfRemap failed\n",__FUNCTION__); + return; + } + + /* PCI memory space */ + pci_set_region(pci_hose[pciIf].regions + 0, + rempWin.baseLow, /* bus address */ + cpuAddrDecWin.addrWin.baseLow, + cpuAddrDecWin.addrWin.size, + PCI_REGION_MEM); + + if (MV_OK != mvCpuIfTargetWinGet(PCI_IO(pciIf), &cpuAddrDecWin)) + { + /* No I/O space */ + pci_hose[pciIf].region_count = 1; + } + else + { + + /* PCI I/O space */ + pci_set_region(pci_hose[pciIf].regions + 1, + cpuAddrDecWin.addrWin.baseLow, + cpuAddrDecWin.addrWin.baseLow, + cpuAddrDecWin.addrWin.size, + PCI_REGION_IO); + pci_hose[pciIf].region_count = 2; + } + + pci_set_ops(&pci_hose[pciIf], + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + mv_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + mv_write_config_dword); + + pci_hose[pciIf].cfg_addr = (unsigned int*) pciIf; + + pci_hose[pciIf].config_table[1].bus = mvPciIfLocalBusNumGet(pciIf); + pci_hose[pciIf].config_table[1].dev = mvPciIfLocalDevNumGet(pciIf); + + pci_register_hose(&pci_hose[pciIf]); + + if (pciIfMode == PCI_IF_MODE_HOST) + { + MV_U32 pciData=0,baseClassCode=0,subClassCode; + + bus_scan = 1; + + pci_hose[pciIf].last_busno = pci_hose_scan(&pci_hose[pciIf]); + bus_scan = 0; + + pciData = mvPciIfConfigRead(pciIf,pci_hose[pciIf].first_busno,1,0, PCI_CLASS_CODE_AND_REVISION_ID); + + baseClassCode = (pciData & PCCRIR_BASE_CLASS_MASK) >> PCCRIR_BASE_CLASS_OFFS; + subClassCode = (pciData & PCCRIR_SUB_CLASS_MASK) >> PCCRIR_SUB_CLASS_OFFS; + + + if ((baseClassCode == PCI_BRIDGE_CLASS) && + (subClassCode == P2P_BRIDGE_SUB_CLASS_CODE)) + { + + /* In rthe bridge : We want to open its memory and + IO to the maximum ! after the u-boot Scan */ + /* first the IO */ + pciData = mvPciIfConfigRead(pciIf,pci_hose[pciIf].first_busno,1,0,P2P_IO_BASE_LIMIT_SEC_STATUS); + /* keep the secondary status */ + pciData &= PIBLSS_SEC_STATUS_MASK; + /* set to the maximum - 0 - 0xffff */ + pciData |= 0xff00; + mvPciIfConfigWrite(pciIf,pci_hose[pciIf].first_busno,1,0,P2P_IO_BASE_LIMIT_SEC_STATUS,pciData); + + /* the the Memory */ + pciData = mvPciIfConfigRead(pciIf,pci_hose[pciIf].first_busno,1,0,P2P_MEM_BASE_LIMIT); + /* set to the maximum - PCI_IF_REMAPED_MEM_BASE(pciIf) - 0xf000000 */ + pciData = 0xEFF00000 | (PCI_IF_REMAPED_MEM_BASE(pciIf) >> 16); + mvPciIfConfigWrite(pciIf,pci_hose[pciIf].first_busno,1,0,P2P_MEM_BASE_LIMIT,pciData); + } + + } + else /* PCI_IF_MODE_HOST */ + { + pci_hose[pciIf].last_busno = pci_hose[pciIf].first_busno; + } + + first_busno = pci_hose[pciIf].last_busno + 1; + } +#ifdef DB_FPGA + MV_REG_BIT_RESET(PCI_BASE_ADDR_ENABLE_REG(0), BIT10); +#endif +} + +#endif /* CONFIG_PCI */ + diff --git a/board/mv_feroceon/USP/mv_protectionUnit.c b/board/mv_feroceon/USP/mv_protectionUnit.c new file mode 100644 index 0000000..37817c2 --- /dev/null +++ b/board/mv_feroceon/USP/mv_protectionUnit.c @@ -0,0 +1,1021 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +/* Code for setting up pagetables or the protection unit, + * and enabling the cache. */ + +#include +#include +#include +#include + +#include "mvSysHwConfig.h" +#if defined(MV_INCLUDE_MONT_EXT) && defined (MV_INCLUDE_MONT_MPU) + + +#include "mvTypes.h" +#include "mvCtrlEnvLib.h" +#include "mvCpuIf.h" +#include "cpu/mvCpu.h" + + +#ifndef MV_TINY_IMAGE + +/* This file refers to the A.R.M.--The ARM Architecture Reference Manual */ + + +typedef enum _access_type{ + + /* priveliged - user */ + NO_NO = 0 , /* No access _ No Access */ + RW_NO = 1, /* Read/Write _ No Access */ + RW_RO = 2 , /* Read/Write _ Read Only */ + RW_RW = 3, /* Read/Write _ Read/Write */ + RO_NO = 5 , /* Read Only _ No Access */ + RO_RO = 6 /* Read Only _ Read Only */ + +}ACCESS_TYPE; + + +typedef enum _region_size{ + + REG_4KB = 0xB, + REG_8KB = 0xC, + REG_16KB = 0xD, + REG_32KB = 0xE, + REG_64KB = 0xF, + REG_128KB = 0x10, + REG_256KB = 0x11, + REG_512KB = 0x12, + REG_1MB = 0x13, + REG_2MB = 0x14, + REG_4MB = 0x15, + REG_8MB = 0x16, + REG_16MB = 0x17, + REG_32MB = 0x18, + REG_64MB = 0x19, + REG_128MB = 0x1A, + REG_256MB = 0x1B, + REG_512MB = 0x1C, + REG_1GB = 0x1D, + REG_2GB = 0x1E, + REG_4GB = 0x1F + +}REGION_SIZE; + +typedef unsigned char bool; + +typedef struct _mpu_region +{ + unsigned int base; + REGION_SIZE size; + bool iCache; + bool dCache; + bool wb; + ACCESS_TYPE dAccess; + ACCESS_TYPE iAccess; + +}MPU_REGION; + + +typedef enum _cache_type{ + + D_CACHE, + I_CACHE + +}CACHE_TYPE; + + +typedef enum _mem_type{ + + D_MEM, + I_MEM + +}MEM_TYPE; + +static unsigned int sizeToBits(unsigned int size) +{ + + switch (size) + { + case 0x00001000: + return REG_4KB; + break; + case 0x00002000: + return REG_8KB; + break; + case 0x00004000: + return REG_16KB; + break; + case 0x00008000: + return REG_32KB; + break; + case 0x00010000: + return REG_64KB; + break; + case 0x00020000: + return REG_128KB; + break; + case 0x00040000: + return REG_256KB; + break; + case 0x00080000: + return REG_512KB; + break; + case 0x00100000: + return REG_1MB; + break; + case 0x00200000: + return REG_2MB; + break; + case 0x00400000: + return REG_4MB; + break; + case 0x00800000: + return REG_8MB; + break; + case 0x01000000: + return REG_16MB; + break; + case 0x02000000: + return REG_32MB; + break; + case 0x04000000: + return REG_64MB; + break; + case 0x08000000: + return REG_128MB; + break; + case 0x10000000: + return REG_256MB; + break; + case 0x20000000: + return REG_512MB; + break; + case 0x40000000: + return REG_1GB; + break; + case 0x80000000: + return REG_2GB; + break; + + } + return 0; +} + +static void printSizeOfRegion(REGION_SIZE bits) +{ + + switch (bits) + { + case REG_4KB: + printf("4KB"); + break; + case REG_8KB: + printf("8KB"); + break; + case REG_16KB: + printf("16KB"); + break; + case REG_32KB: + printf("32KB"); + break; + case REG_64KB: + printf("64KB"); + break; + case REG_128KB: + printf("128KB"); + break; + case REG_256KB: + printf("256KB"); + break; + case REG_512KB: + printf("512KB"); + break; + case REG_1MB: + printf("1MB"); + break; + case REG_2MB: + printf("2MB"); + break; + case REG_4MB: + printf("4MB"); + break; + case REG_8MB: + printf("8MB"); + break; + case REG_16MB: + printf("16MB"); + break; + case REG_32MB: + printf("32MB"); + break; + case REG_64MB: + printf("64MB"); + break; + case REG_128MB: + printf("128MB"); + break; + case REG_256MB: + printf("256MB"); + break; + case REG_512MB: + printf("512MB"); + break; + case REG_1GB: + printf("1GB"); + case REG_2GB: + printf("2GB"); + break; + case REG_4GB: + printf("4GB"); + break; + } +} + +/* + get Control register +*/ +unsigned int get_control(void) +{ + unsigned int value; + + __asm__ __volatile__( + "mrc p15, 0, %0, c1, c0, 0\n" + : "=r" (value) + : + : "memory"); + + return value; + + +} + +/* + set Control register +*/ +void set_control(unsigned int value) +{ + + __asm__ __volatile__( + "mcr p15, 0, %0, c1, c0, 0\n" + : + : "r" (value)); + + +} + +/* + get Write Buffer Configuration +*/ +static unsigned int get_wb(void) +{ + unsigned int value; + + __asm__ __volatile__( + "mrc p15, 0, %0, c3, c0, 0\n" + : "=r" (value) + : + : "memory"); + + return value; + + +} + +/* + set Write Buffer Configuration +*/ +static void set_wb(unsigned int value) +{ + + __asm__ __volatile__( + "mcr p15, 0, %0, c3, c0, 0\n" + : + : "r" (value)); + + +} + +/* + Read cache configuration +*/ + +static unsigned int get_cache_config(CACHE_TYPE type) +{ + unsigned int value = 0; + + switch (type) + { + case D_CACHE: + __asm__ __volatile__( + "mrc p15, 0, %0, c2, c0, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case I_CACHE: + __asm__ __volatile__( + "mrc p15, 0, %0, c2, c0, 1\n" + : "=r" (value) + : + : "memory"); + + break; + + } + + return value; + + +} + +/* + Write cache configuration +*/ + +static void set_cache_config(CACHE_TYPE type,unsigned int value) +{ + + switch (type) + { + case D_CACHE: + __asm__ __volatile__( + "mcr p15, 0, %0, c2, c0, 0\n" + : + : "r" (value)); + + + break; + case I_CACHE: + __asm__ __volatile__( + "mcr p15, 0, %0, c2, c0, 1\n" + : + : "r" (value)); + + break; + + } + + + +} + + + + + + + +/* + Read access permision +*/ + +static unsigned int get_access(MEM_TYPE type) +{ + unsigned int value = 0; + + switch (type) + { + case D_MEM: + __asm__ __volatile__( + "mrc p15, 0, %0, c5, c0, 2\n" + : "=r" (value) + : + : "memory"); + + break; + case I_MEM: + __asm__ __volatile__( + "mrc p15, 0, %0, c5, c0, 3\n" + : "=r" (value) + : + : "memory"); + + break; + + } + + return value; + + +} + +/* + Write cache configuration +*/ + +static void set_access(MEM_TYPE type,unsigned int value) +{ + + switch (type) + { + case D_MEM: + __asm__ __volatile__( + "mcr p15, 0, %0, c5, c0, 2\n" + : + : "r" (value)); + + break; + case I_MEM: + __asm__ __volatile__( + "mcr p15, 0, %0, c5, c0, 3\n" + : + : "r" (value)); + + break; + + } + + + +} + +/* + get protection region size\base\enable +*/ + +unsigned int get_prot_attrib(int region) +{ + unsigned int value = 0; + + switch (region) + { + case 0: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c0, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case 1: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c1, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case 2: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c2, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case 3: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c3, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case 4: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c4, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case 5: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c5, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case 6: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c6, 0\n" + : "=r" (value) + : + : "memory"); + + break; + case 7: + + __asm__ __volatile__( + "mrc p15, 0, %0, c6, c7, 0\n" + : "=r" (value) + : + : "memory"); + + break; + + + + } + + return value; +} + +/* + set protection region size\base\enable +*/ + +static void set_prot_attrib(int region,unsigned int value) +{ + switch (region) + { + case 0: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c0, 0\n" + : + : "r" (value)); + + + break; + case 1: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c1, 0\n" + : + : "r" (value)); + + break; + case 2: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c2, 0\n" + : + : "r" (value)); + + break; + case 3: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c3, 0\n" + : + : "r" (value)); + + break; + case 4: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c4, 0\n" + : + : "r" (value)); + + break; + case 5: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c5, 0\n" + : + : "r" (value)); + + break; + case 6: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c6, 0\n" + : + : "r" (value)); + + break; + case 7: + + __asm__ __volatile__( + "mcr p15, 0, %0, c6, c7, 0\n" + : + : "r" (value)); + + break; + + + + } + +} + + +static void createMPUEntry(int region,MPU_REGION *mpuEntry) +{ + unsigned int value = 0; + + /* set data cache attributes */ + value = get_cache_config(D_CACHE); + + if (mpuEntry->dCache) + { + value |= (1<< region); + } + else + { + value &= ~(1<< region); + } + + set_cache_config(D_CACHE,value); + + /* set instruction cache attributes */ + value = get_cache_config(I_CACHE); + + if (mpuEntry->iCache) + { + value |= (1<< region); + } + else + { + value &= ~(1<< region); + } + + set_cache_config(I_CACHE,value); + + /* set write buffer */ + + value = get_wb(); + + if (mpuEntry->wb) + { + value |= (1<< region); + } + else + { + value &= ~(1<< region); + } + + set_wb(value); + + /* set access permision for data accesses*/ + + value = get_access(D_MEM); + value &= ~(0xf << (region*4)); + value |= (mpuEntry->dAccess << (region*4)); + set_access(D_MEM , value); + + /* set access permision for instruction accesses*/ + + value = get_access(I_MEM); + value &= ~(0xf << (region*4)); + value |= (mpuEntry->iAccess << (region*4)); + set_access(I_MEM, value); + + + + /*set base and size and enable*/ + value = 0; + value |= (mpuEntry->base) & (0xFFFFF << 12); + value |= ( mpuEntry->size << 1); + value |= 1; + + set_prot_attrib(region,value); + + + +} + + +/* These are all the bits currently defined for the control register */ +/* A.R.M. 7.4.2 */ +#define MPU_V 0x2000 /* alternae vector select */ +#define MPU_I 0x1000 /* Instruction cache */ +#define MPU_B 0x0080 /* big endian */ +#define MPU_RES 0x00F79 /* reserved bits should be 1 */ +#define MPU_C 0x0004 /* data cache */ +#define MPU_P 0x0001 /* protection unit */ + + + +/* + * The functions below take arguments to specify which "caches" the + * action is to be directed at. For the I-cache, pass "MMU_I". For + * the D-cache, "MMU_C". For both, pass "MMU_ID". For combined ID-Cache + * processors, use "MMU_C" + */ +#define MPU_ID (MPU_I + MPU_C) + + +int mpuMap(void) +{ + + unsigned int value; + int region; + + value = get_control(); + + if (value & MPU_P) + { + printf("\nProtection Unit:\n"); + + for (region = 1 ; region < 8 ; region++) + { + value = get_prot_attrib(region); + /* check if region is enabled */ + if (value & 1) + { + printf("region %d base=0x%08x size =",region,value & (0xFFFFF << 12)); + printSizeOfRegion(((value & (0x1f << 1)) >> 1)); + + value = get_cache_config(D_CACHE); + + if (value & (1 << region)) + { + printf(" :DCache enabled - "); + } + else + { + printf(" :DCache disabled - "); + } + + value = get_cache_config(I_CACHE); + + if (value & (1 << region)) + { + printf("ICache enabled - "); + } + else + { + printf("ICache disabled - "); + } + + value = get_wb(); + + if (value & (1 << region)) + { + printf("Bufferable"); + } + else + { + printf("non Bufferable"); + } + + printf("\n"); + + + + } + + } + + } + else + { + printf("MPU is disabled\n"); + } + + return 1; +} + + + +/* Flush the cache(s). + */ +inline void mpuInvCache(unsigned caches) +{ + unsigned long dummy = 0; + + switch (caches) + { + case MPU_C: + __asm__ __volatile__( + "mcr p15, 0, %0, c7, c6, 0\n" + : + : "r" (dummy)); + break; + case MPU_I: + __asm__ __volatile__( + "mcr p15, 0, %0, c7, c5, 0\n" + : + : "r" (dummy)); + break; + case MPU_ID: + __asm__ __volatile__( + "mcr p15, 0, %0, c7, c7, 0\n" + : + : "r" (dummy)); + break; + } +} + + +/* Enable the cache/MMU/TLB etc. + */ +inline void _cpuCfgEnable(unsigned long flags, MV_BOOL enable) +{ + unsigned long tmp; + + if (enable == MV_TRUE) + { + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (tmp)); + tmp |= flags; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (tmp)); + } + else + { + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (tmp)); + tmp &= ~flags; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (tmp)); + } +} + +/* Disable the I/D cache. + */ + +inline void _disableIDCache(void) +{ + unsigned long tmp; + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (tmp)); + tmp &= ~MPU_ID; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (tmp)); + + /* invalidate I/D-cache */ + tmp = 0; + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (tmp)); + +} + + +void MPU_Init(void) +{ + MPU_REGION mpuEntry; +#if defined(MV_INCLUDE_SDRAM_CS1) + MV_CPU_DEC_WIN win; + MV_TARGET target; + unsigned int totalSize=0; +#endif + int region=0; + char *env; + + printf("Intializing Protection Unit\n"); + _disableIDCache(); + + /* enable I cache - doesn't need MPU enabling */ + /*_enable(MPU_RES);*/ + + /* set region 0 - include all memory and have I and D caches disabled + and write buffer disabled */ + + mpuEntry.base = 0; + mpuEntry.size = REG_4GB; + mpuEntry.dCache = 0; + mpuEntry.iCache = 0; + mpuEntry.wb = 0; + mpuEntry.iAccess = NO_NO; + mpuEntry.dAccess = NO_NO; + + createMPUEntry(region++ , &mpuEntry); + + + + /* set region 1 - CS0 DRAM region */ + + mpuEntry.base = mvCpuIfTargetWinBaseLowGet(SDRAM_CS0); + + mpuEntry.size = sizeToBits(mvCpuIfTargetWinSizeGet(SDRAM_CS0)); + + mpuEntry.dCache = 0; + mpuEntry.iCache = 1; + mpuEntry.wb = 0; + + mpuEntry.iAccess = RW_RW; + mpuEntry.dAccess = RW_RW; + + createMPUEntry(region++ , &mpuEntry); + + + /* set region 2 - CS0-CS3 DRAM region */ +#if defined(MV_INCLUDE_SDRAM_CS1) + for (target = SDRAM_CS1 ; target < MV_DRAM_MAX_CS ; target++) + { + mvCpuIfTargetWinGet(target, &win); + + if (win.enable) break; + } + + target = SDRAM_CS1; + mpuEntry.base = mvCpuIfTargetWinBaseLowGet(target); + + for (target = SDRAM_CS1; target < MV_DRAM_MAX_CS ; target++) + { + totalSize += mvCpuIfTargetWinSizeGet(target); + } + + + mpuEntry.size = sizeToBits(totalSize); + + mpuEntry.dCache = 0; + mpuEntry.iCache = 0; + mpuEntry.wb = 0; + + mpuEntry.iAccess = RW_RW; + mpuEntry.dAccess = RW_RW; +#endif + + env = getenv("dramCached"); + + if((!env)||( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) )) + { + setenv("dramCached","yes"); + + mpuEntry.dCache = 1; + mpuEntry.iCache = 1; + mpuEntry.wb = 1; + + } + + createMPUEntry(region++ , &mpuEntry); + + /* set region 3 - devices region */ + mpuEntry.base = 0xF0000000; + + mpuEntry.size = REG_256MB; + + mpuEntry.dCache = 0; + mpuEntry.iCache = 0; + mpuEntry.wb = 0; + + mpuEntry.iAccess = RW_RW; + mpuEntry.dAccess = RW_RW; + + createMPUEntry(region++ , &mpuEntry); + + /* set region 4 - pci region */ + mpuEntry.base = 0x90000000; + + mpuEntry.size = REG_256MB; + + mpuEntry.dCache = 0; + mpuEntry.iCache = 0; + mpuEntry.wb = 0; + + mpuEntry.iAccess = RW_RW; + mpuEntry.dAccess = RW_RW; + + env = getenv("pciCached"); + + if(!env) + setenv("pciCached","no"); + else + { + if( ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + { + mpuEntry.dCache = 1; + mpuEntry.iCache = 1; + mpuEntry.wb = 1; + + } + + } + + createMPUEntry(region++ , &mpuEntry); + + /* set region 5 - stack pointer */ + mpuEntry.base = 0xF00000; + + mpuEntry.size = REG_64KB; + + mpuEntry.dCache = 1; + mpuEntry.iCache = 1; + mpuEntry.wb = 1; + + mpuEntry.iAccess = RW_RW; + mpuEntry.dAccess = RW_RW; + + + createMPUEntry(region++ , &mpuEntry); + + + /*mpuInvCache(MPU_ID);*/ + /* write to control register :- + * I-cache on, 32-bit data and program space, + * write-buffer on, D-cache on, MMU on + */ + _cpuCfgEnable((MPU_I|MPU_C|MPU_P|MPU_RES), MV_TRUE); + + return ; +} +#endif + +#endif /* MV_INCLUDE_MONT_EXT */ + diff --git a/board/mv_feroceon/USP/mv_rtc.c b/board/mv_feroceon/USP/mv_rtc.c new file mode 100644 index 0000000..4feba29 --- /dev/null +++ b/board/mv_feroceon/USP/mv_rtc.c @@ -0,0 +1,94 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +/* #define RTC_DEBUG */ + +#include +#include +#include + +#ifdef MV_INCLUDE_RTC +#include "rtc/integ_rtc/mvRtc.h" +#elif defined(CONFIG_RTC_DS1338_DS1339) +#include "rtc/ext_rtc/mvDS133x.h" +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_DATE) + +/* since this rtc dosen't support century we will use 20 as default */ +#define CENTURY 20 + +void rtc_get( struct rtc_time *tmp ) +{ + MV_RTC_TIME time; +#ifdef MV_INCLUDE_RTC + mvRtcTimeGet(&time); +#elif defined(CONFIG_RTC_DS1338_DS1339) + mvRtcDS133xTimeGet(&time); +#endif + tmp->tm_year = (CENTURY * 100) + time.year; + tmp->tm_mon = time.month; + tmp->tm_mday = time.date; + tmp->tm_wday = time.day; + tmp->tm_hour = time.hours; + tmp->tm_min = time.minutes; + tmp->tm_sec = time.seconds; + tmp->tm_yday = 0; + tmp->tm_isdst= 0; +#ifdef RTC_DEBUG + printf( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec ); +#endif +} + +void rtc_set( struct rtc_time *tmp ) +{ + MV_RTC_TIME time; +#ifdef RTC_DEBUG + printf( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); +#endif + time.month = tmp->tm_mon; + time.date = tmp->tm_mday; + time.day = tmp->tm_wday; + time.hours = tmp->tm_hour; + time.minutes = tmp->tm_min; + time.seconds = tmp->tm_sec; + if((tmp->tm_year/100) != CENTURY) + printf("Warning: century isn't supported to be set(always %d) \n",CENTURY); + time.year = tmp->tm_year%100; +#ifdef MV_INCLUDE_RTC + mvRtcTimeSet(&time); +#elif defined(CONFIG_RTC_DS1338_DS1339) + mvRtcDS133xTimeSet(&time); +#endif +} + +void rtc_reset (void) +{ + /* No need for init in any of the devices */ + /* The OSC enable bit in the DS1338 is clear at the first date set */ +} + + +#endif /* CFG_CMD_DATE */ diff --git a/board/mv_feroceon/USP/mv_serial.c b/board/mv_feroceon/USP/mv_serial.c new file mode 100644 index 0000000..f07dee2 --- /dev/null +++ b/board/mv_feroceon/USP/mv_serial.c @@ -0,0 +1,158 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +/* + * serial.c - serial support. + */ + +#include +#include +#include "uart/mvUart.h" + +#if defined(MV78XX0) +extern unsigned int whoAmI(void); +#endif + +extern void print_mvBanner(void); +extern void print_dev_id(void); + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + +#if defined(MV78XX0) + if (whoAmI() == MASTER_CPU) +#endif + { + int clock_divisor = (CFG_TCLK / 16)/gd->baudrate; + +#ifdef QNAPNAS + int clock_divisor2 = (CFG_TCLK / 16) / 19200; +#endif /* QNAPNAS */ + +#ifdef CFG_INIT_CHAN1 + mvUartInit(0, clock_divisor, mvUartBase(0)); +#endif +#ifdef CFG_INIT_CHAN2 +/* Richard Chen 20090105, Initiate PIC */ +# ifdef QNAPNAS + mvUartInit(1, clock_divisor2, mvUartBase(1)); +# else + mvUartInit(1, clock_divisor, mvUartBase(1)); +# endif /* QNAPNAS */ +#endif + } + /* print banner */ + print_mvBanner(); + print_dev_id(); + + return (0); +} + +void +serial_putc(const char c) +{ +#if defined(CONFIG_MV_SMP) || (defined(MV78XX0) && defined(MV78200)) + if (c == '\n') + mvUartPutc((whoAmI())%2, '\r'); + + mvUartPutc((whoAmI())%2, c); +#else + if (c == '\n') + mvUartPutc(CFG_DUART_CHAN, '\r'); + + mvUartPutc(CFG_DUART_CHAN, c); +#endif +} + +int +serial_getc(void) +{ +#if defined(CONFIG_MV_SMP) || (defined(MV78XX0) && defined(MV78200)) + return mvUartGetc((whoAmI())%2); +#else + return mvUartGetc(CFG_DUART_CHAN); +#endif +} + +int +serial_tstc(void) +{ +#if defined(CONFIG_MV_SMP) || (defined(MV78XX0) && defined(MV78200)) + return mvUartTstc((whoAmI())%2); +#else + return mvUartTstc(CFG_DUART_CHAN); +#endif +} + +void +serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = (CFG_TCLK / 16)/gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + mvUartInit(0, clock_divisor, mvUartBase(0)); +#endif +#ifdef CFG_INIT_CHAN2 + mvUartInit(1, clock_divisor, mvUartBase(1)); +#endif +} + + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +void +kgdb_serial_init(void) +{ +} + +void +putDebugChar (int c) +{ + serial_putc (c); +} + +void +putDebugStr (const char *str) +{ + serial_puts (str); +} + +int +getDebugChar (void) +{ + return serial_getc(); +} + +void +kgdb_interruptible (int yes) +{ + return; +} +#endif /* CFG_CMD_KGDB */ diff --git a/board/mv_feroceon/USP/mv_usb_dev.c b/board/mv_feroceon/USP/mv_usb_dev.c new file mode 100644 index 0000000..88abf73 --- /dev/null +++ b/board/mv_feroceon/USP/mv_usb_dev.c @@ -0,0 +1,379 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include + +#include "mvOs.h" +#include "mvCommon.h" +#include "mvDebug.h" +#include "mvBoardEnvSpec.h" +#include "mvUsb.h" +#include "mvUsbDevApi.h" +#include "disk.h" +#include "mouse.h" + +#define USB_DISK_DEFAULT_SIZE 2048 + +extern MV_U32 mvUsbGetCapRegAddr(int devNo); + +typedef struct +{ + _usb_device_handle handle; + MV_BOOL isMouse; + int gppNo; + +} MV_USB_DEVICE; + +MV_BOOL mvUsbIsFirst = MV_TRUE; +MV_USB_DEVICE mvUsbDevice[MV_BOARD_MAX_USB_IF]; + + +USB_IMPORT_FUNCS usbImportFuncs = +{ + printf, + mvOsSPrintf, + mvOsIoUncachedMalloc, + mvOsIoUncachedFree, + mvOsMalloc, + mvOsFree, + memset, + memcpy, + mvOsCacheFlush, + mvOsCacheInvalidate, + mvOsIoVirtToPhy, + NULL, + NULL, + mvUsbGetCapRegAddr, + NULL +}; + + +static void print_args(int argc, char** argv) +{ + int i; + + for(i=0; i= 1000000) + { /* Body */ + usbMousePeriodicResume(mvUsbDevice[dev].handle); + } + } /* Endbody */ + } + if( (counter & 0xFFFFF) == 0) + mvOsPrintf("."); + + if (ctrlc()) + { + puts ("\nAbort\n"); + return; + } + } /* Endwhile */ +} + +static void mvUsbUnload(int dev) +{ + if(mvUsbDevice[dev].handle == NULL) + { + mvOsPrintf("USB-%d Device is not loaded\n", dev); + return; + } + + mvOsPrintf("Unload USB=%d Device: handle=%p\n", + dev, mvUsbDevice[dev].handle); + if(mvUsbDevice[dev].isMouse) + { + usbMouseUnload(mvUsbDevice[dev].handle); + } + else + { + usbDiskUnload(mvUsbDevice[dev].handle); + } + mvUsbDevice[dev].handle = NULL; + mvUsbDevice[dev].gppNo = -1; + mvUsbDevice[dev].isMouse = MV_FALSE; +} + + +static void mvUsbDisk(int dev, int diskSize) +{ + if(mvUsbDevice[dev].handle != NULL) + { + mvOsPrintf("USB-%d device already in use\n", dev); + return; + } + + if(diskSize == 0) + diskSize = USB_DISK_DEFAULT_SIZE; + + mvOsPrintf("Load USB-%d Disk example: disk size is %d Kbytes\n", + dev, diskSize); + + mvUsbDevice[dev].handle = usbDiskLoad(dev, diskSize); + if(mvUsbDevice[dev].handle == NULL) + { + mvOsPrintf("usbDiskLoad-%d FAILED\n", dev); + return; + } + mvUsbPolling(); +} + +static void mvUsbMouse(int dev) +{ + if(mvUsbDevice[dev].handle != NULL) + { + mvOsPrintf("USB-%d device is already in use\n", dev); + return; + } + + mvOsPrintf("Load USB-%d Mouse example\n", dev); + + mvUsbDevice[dev].handle = usbMouseLoad(dev); + if(mvUsbDevice[dev].handle == NULL) + { + mvOsPrintf("usbMouseLoad-%d FAILED\n", dev); + return; + } + mvUsbDevice[dev].isMouse = MV_TRUE; + mvUsbPolling(); +} + +int mvUsbCmdMain(int argc, char *argv[]) +{ + _usb_device_handle handle = NULL; + int i, mode, dev; + + if(mvUsbIsFirst == MV_TRUE) + { + mvUsbDevsInit(); + mvUsbIsFirst = MV_FALSE; + } + if(argc <= 1) + { + mvOsPrintf("usbTest: not enough parameters\n"); + return 2; + } + print_args(argc, argv); + + if(memcmp(argv[1], "flags", strlen(argv[1])) == 0) + { + mvOsPrintf("USB old debug flags = 0x%x\n", _usb_debug_get_flags()); + if(argc > 2) + { + mode = strtol(argv[2], NULL, 16); + _usb_debug_set_flags(mode); + mvOsPrintf("USB new debug flags = 0x%x\n", _usb_debug_get_flags()); + } + return 0; + } + if(memcmp(argv[1], "poll", strlen(argv[1])) == 0) + { + mvUsbPolling(); + return 0; + } + + dev = 0; + if(argc > 2) + dev = strtol(argv[2], NULL, 10); + + handle = mvUsbDevice[dev].handle; + if(handle == NULL) + { + mvOsPrintf("USB Device core is not initialized\n"); + return 3; + } + + if(memcmp(argv[1], "show", strlen(argv[1])) == 0) + { + mode = 0; + if(argc > 3) + mode = strtol(argv[3], NULL, 16); + + if( MV_BIT_CHECK(mode, 0) ) + _usb_regs(handle); + + if( MV_BIT_CHECK(mode, 1) ) + _usb_status(handle); + + if( MV_BIT_CHECK(mode, 2) ) + _usb_stats(handle); + + if( MV_BIT_CHECK(mode, 3) ) + _usb_debug_print_trace_log(); + + for(i=0; i<_usb_device_get_max_endpoint(handle); i++) + { + if( MV_BIT_CHECK(mode, (8+i)) ) + { + _usb_ep_status(handle, i, ARC_USB_RECV); + _usb_ep_status(handle, i, ARC_USB_SEND); + } + } + return 0; + } + + if(memcmp(argv[1], "test", strlen(argv[1])) == 0) + { + /* Set Test mode */ + mode = 0; + if(argc > 3) + mode = strtol(argv[3], NULL, 10); + + mvOsPrintf("USB test: set test mode %d\n", mode); + _usb_dci_vusb20_set_test_mode(handle, (mode & 0x7) << 8); + + return 0; + } + + mvOsPrintf("USB test: Unexpected command %s\n", argv[1]); + return 3; +} + +int mvUsbDevMain(int argc, char *argv[]) +{ + int dev, diskSize = 0; + + if(mvUsbIsFirst == MV_TRUE) + { + mvUsbDevsInit(); + mvUsbIsFirst = MV_FALSE; + } + + dev = strtol(argv[1], NULL, 10); + + if(memcmp(argv[2], "disk", strlen(argv[2])) == 0) + { + if(argc > 3) + diskSize = strtol(argv[3], NULL, 10); + + mvUsbDisk(dev, diskSize); + return 0; + } + + if(memcmp(argv[2], "mouse", strlen(argv[2])) == 0) + { + mvUsbMouse(dev); + return 0; + } + + if( memcmp(argv[2], "unload", strlen(argv[2])) == 0) + { + mvUsbUnload(dev); + return 0; + } + + mvOsPrintf("usbDev unknown command\n"); + return 1; +} + +int mvUsbCmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if( (argc == 0) || (argc == 1) ) + { + mvOsPrintf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + return mvUsbCmdMain(argc, argv); +} + +int mvUsbDev(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if(argc < 2) + { + mvOsPrintf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + return mvUsbDevMain(argc, argv); +} + + +U_BOOT_CMD( + usbCmd, 4, 1, mvUsbCmd, + "usbCmd - USB Device sub-system\n", + "\n" + "\t usbCmd flags [mask] - Get/Set debug flags\n" + "\t usbCmd poll - Polling IRQs for all USB devices for never\n" + "\t usbCmd show [mask] - Print out USB device information\n" + "\t usbCmd test [mode] - Set USB device to test mode\n" +); + +U_BOOT_CMD( + usbDev, 5, 0, mvUsbDev, + "usbDev - Load/Unload USB Devices\n", + "\t usbDev disk [kBytes] - Load USB Disk device\n" + "\t usbDev mouse - Load USB Mouse device\n" + "\t usbDev unload - Unload USB device\n" +); diff --git a/board/mv_feroceon/USP/mv_usb_host.c b/board/mv_feroceon/USP/mv_usb_host.c new file mode 100644 index 0000000..1162cba --- /dev/null +++ b/board/mv_feroceon/USP/mv_usb_host.c @@ -0,0 +1,152 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include + +#include "mvOs.h" +#include "mvDebug.h" +#include "mvBoardEnvSpec.h" +#include "mvCtrlEnvLib.h" + +#include "mvUsbHostApi.h" + +extern USB_HOST_STATE_STRUCT_PTR usb_host_state_struct_ptr; +extern void _usb_hci_vusb20_isr(void); +extern void hidMouseMain(void); + +static void print_args(int argc, char** argv) +{ + int i; + + for(i=0; i 2) + mode = strtol(argv[2], NULL, 16); + + if( MV_BIT_CHECK(mode, 3) ) + ARC_PRINT_DEBUG_TRACE(); + + return 0; + } + + if( (usb_host_state_struct_ptr != NULL) && + (memcmp(argv[1], "poll", strlen(argv[1])) == 0)) + { + i = 0; + while(TRUE) + { + if( (i & 0xFFFFF) == 0) + { + mvOsPrintf("."); + } + _usb_hci_vusb20_isr(); + i++; + + if (ctrlc()) + { + puts ("\nAbort\n"); + return 0; + } + } + mvOsPrintf("\n"); + + return 0; + } + + if( (usb_host_state_struct_ptr == NULL) && + (memcmp(argv[1], "mouse", strlen(argv[1])) == 0)) + { + mvOsPrintf("Start hidmouse driver\n"); + MV_REG_WRITE(MV_USB_CORE_MODE_REG, 0x3); + hidMouseMain(); + return 0; + } + + mvOsPrintf("USB test: Unexpected command %s\n", argv[1]); + return 3; +} + +int mvUsbHost(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if( (argc == 0) || (argc == 1) ) + { + mvOsPrintf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + mvUsbHostMain(argc, argv); + return 1; +} + +U_BOOT_CMD( + usbHost, 5, 0, mvUsbHost, + "usbHost - USB Host specific commands\n", + "\t usbHost mouse <1 | 0> - Load/Unload USB HID mouse driver\n" + "\t usbHost show [mask] - Print out all USB information\n" +); diff --git a/board/mv_feroceon/USP/nBootloader.c b/board/mv_feroceon/USP/nBootloader.c new file mode 100644 index 0000000..1406023 --- /dev/null +++ b/board/mv_feroceon/USP/nBootloader.c @@ -0,0 +1,253 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include "cntmr/mvCntmr.h" +#include "uart/mvUart.h" +#include "nBootstrap.h" +#include + +#define CFG_NAND_READ_DELAY \ + { volatile int dummy; int i; for (i=0; i<10000; i++) dummy = i; } + +typedef void (*VOIDFUNCPTR) (void); /* ptr to function returning void */ + +extern void board_nand_init(struct nand_chip *nand); +extern void mv_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd); +static void mv_nand_write_byte(struct mtd_info *mtd, u_char byte); +static u_char mv_nand_read_byte(struct mtd_info *mtd); + + +static int nand_is_bad_block(struct mtd_info *mtd, int block) +{ + struct nand_chip *this = mtd->priv; + int page_addr = block * CFG_NAND_PAGE_COUNT; + + /* Begin command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_SETCLE); +#ifdef MV_LARGE_PAGE + this->write_byte(mtd, NAND_CMD_READ0); +#else + this->write_byte(mtd, NAND_CMD_READOOB); +#endif + /* Set ALE and clear CLE to start address cycle */ + this->hwcontrol(mtd, NAND_CTL_CLRCLE); + this->hwcontrol(mtd, NAND_CTL_SETALE); +#ifdef MV_LARGE_PAGE + /* Column address */ + this->write_byte(mtd, CFG_NAND_BAD_BLOCK_POS); /* A[7:0] */ + this->write_byte(mtd, 8); /* A[11:8] */ + /* Row address */ + this->write_byte(mtd, (uchar)(page_addr & 0xff)); /* A[19:12] */ + this->write_byte(mtd, (uchar)((page_addr >> 8) & 0xff)); /* A[27:20] */ + this->write_byte(mtd, (uchar)((page_addr >> 16) & 0x03)); /* A[29:28] */ +#else + /* Column address */ + this->write_byte(mtd, CFG_NAND_BAD_BLOCK_POS); /* A[7:0] */ + /* Row address */ + this->write_byte(mtd, (uchar)(page_addr & 0xff)); /* A[16:9] */ + this->write_byte(mtd, (uchar)((page_addr >> 8) & 0xff)); /* A[24:17] */ +#endif + /* Latch in address */ + this->hwcontrol(mtd, NAND_CTL_CLRALE); +#ifdef MV_LARGE_PAGE + /* Set command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_SETCLE); + this->write_byte(mtd, NAND_CMD_READSTART); + /* Clear CLE to latch command cycle */ + this->hwcontrol(mtd, NAND_CTL_CLRCLE); +#endif + + /* + * Wait a while for the data to be ready + */ + if (this->dev_ready) + this->dev_ready(mtd); + else + CFG_NAND_READ_DELAY; + + /* + * Read on byte + */ + if (this->read_byte(mtd) != 0xff) + return 1; + + return 0; +} + +static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst) +{ + struct nand_chip *this = mtd->priv; + int page_addr = page + block * CFG_NAND_PAGE_COUNT; + int i; + + /* Begin command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_SETCLE); + this->write_byte(mtd, NAND_CMD_READ0); + /* Set ALE and clear CLE to start address cycle */ + this->hwcontrol(mtd, NAND_CTL_CLRCLE); + this->hwcontrol(mtd, NAND_CTL_SETALE); +#ifdef MV_LARGE_PAGE + /* Column address */ + this->write_byte(mtd, 0); /* A[7:0] */ + this->write_byte(mtd, 0); /* A[11:8] */ + /* Row address */ + this->write_byte(mtd, (uchar)(page_addr & 0xff)); /* A[19:12] */ + this->write_byte(mtd, (uchar)((page_addr >> 8) & 0xff)); /* A[27:20] */ + this->write_byte(mtd, (uchar)((page_addr >> 16) & 0x03)); /* A[29:28] */ +#else + /* Column address */ + this->write_byte(mtd, 0); /* A[7:0] */ + /* Row address */ + this->write_byte(mtd, (uchar)(page_addr & 0xff)); /* A[16:9] */ + this->write_byte(mtd, (uchar)((page_addr >> 8) & 0xff)); /* A[24:17] */ +#endif + /* Latch in address */ + this->hwcontrol(mtd, NAND_CTL_CLRALE); +#ifdef MV_LARGE_PAGE + /* End command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_SETCLE); + this->write_byte(mtd, NAND_CMD_READSTART); + /* Set clear CLE to start address cycle */ + this->hwcontrol(mtd, NAND_CTL_CLRCLE); +#endif + + /* + * Wait a while for the data to be ready + */ + if (this->dev_ready) + this->dev_ready(mtd); + else + CFG_NAND_READ_DELAY; + + /* + * Read page into buffer + */ + for (i=0; iread_byte(mtd); + + return 0; +} + +static int nand_load(struct mtd_info *mtd, int offs, int uboot_size, uchar *dst) +{ + int block; + int blockcopy_count; + int page; + + /* + * offs has to be aligned to a block address! + */ + block = offs / CFG_NAND_BLOCK_SIZE; + blockcopy_count = 0; + + while (blockcopy_count < (uboot_size / CFG_NAND_BLOCK_SIZE)) { + if (!nand_is_bad_block(mtd, block)) { + /* + * Skip bad blocks + */ + for (page = 0; page < CFG_NAND_PAGE_COUNT; page++) { + nand_read_page(mtd, block, page, dst); + dst += CFG_NAND_PAGE_SIZE; + } + + blockcopy_count++; + } + + block++; + /* End of NAND device */ + if (block >= NUM_BLOCKS) + return -1; + } + + return 0; +} + +void nand_boot(void) +{ + + ulong mem_size; + struct nand_chip nand_chip; + nand_info_t nand_info; + int ret; + + /* + * DRAM was init in nBootstrap.S so we have access to memory + */ + mem_size = 0x08000000; + + /* + * Init board specific nand support + */ + nand_info.priv = &nand_chip; + nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W = (void __iomem *)CFG_NAND_BASE; + nand_chip.dev_ready = NULL; /* preset to NULL */ + board_nand_init(&nand_chip); + + /* Add write and read byte functions */ + nand_chip.write_byte = mv_nand_write_byte; + nand_chip.read_byte = mv_nand_read_byte; + + /* + * Load U-Boot image from NAND into RAM + */ + ret = nand_load(&nand_info, CFG_NAND_U_BOOT_OFFS, CFG_NAND_U_BOOT_SIZE, + (uchar *)CFG_NAND_U_BOOT_DST); + if (ret != 0) + /* Error reading NAND */ + while(1); + + /* + * Jump to U-Boot image + */ +#if defined(MV_LARGE_PAGE) + VOIDFUNCPTR ubootStart = (VOIDFUNCPTR)(CFG_NAND_U_BOOT_START + 0x90000); +#else + VOIDFUNCPTR ubootStart = (VOIDFUNCPTR)(CFG_NAND_U_BOOT_START + 0x90000); +#endif + (*ubootStart)(); +} + +/** + * mv_nand_read_byte - [DEFAULT] read one byte to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * Default read function for 8it buswith + */ +static u_char mv_nand_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + return readb(this->IO_ADDR_R); +} + +/** + * nand_write_byte - [DEFAULT] write one byte to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * Default write function for 8it buswith + */ +static void mv_nand_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + writeb(byte, this->IO_ADDR_W); +} diff --git a/board/mv_feroceon/USP/sdio/mmc.c b/board/mv_feroceon/USP/sdio/mmc.c new file mode 100644 index 0000000..031e0b0 --- /dev/null +++ b/board/mv_feroceon/USP/sdio/mmc.c @@ -0,0 +1,574 @@ +/* + * (C) Copyright 2003 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 +#include +#include "mustang_sdiodef.h" +#include +#include +#include +#include "mvOs.h" + +#ifdef CONFIG_MMC +#define DELAY 50 +//#define debug printf +extern int +fat_register_device(block_dev_desc_t *dev_desc, int part_no); + +static block_dev_desc_t mmc_dev; + +block_dev_desc_t * mmc_get_dev(int dev) +{ + return ((block_dev_desc_t *)&mmc_dev); +} + +/* + * FIXME needs to read cid and csd info to determine block size + * and other parameters + */ +static uchar mmc_buf[MMC_BLOCK_SIZE]; +static mmc_csd_t mmc_csd; +static int mmc_ready = 0; +static int rca ; + + + +static uchar * +/****************************************************/ +mmc_cmd(ulong cmd, ulong arg, ushort xfermode, ushort resptype, ushort waittype) +/****************************************************/ +{ + static ulong resp[4]; + int count ; + ushort done ; + int err = 0 ; + + debug("mmc_cmd %x, arg: %x,xfer: %x,resp: %x, wait : %x\n", cmd, arg, xfermode, resptype, waittype); + //clear status + SDIO_REG_WRITE16(SDIO_ERR_INTR_EN, SDIO_REG_READ16(SDIO_ERR_INTR_STATUS)); + SDIO_REG_WRITE16(SDIO_NOR_INTR_EN, SDIO_REG_READ16(SDIO_NOR_INTR_STATUS)); + //disable interrupts + SDIO_REG_WRITE16(SDIO_NOR_INTR_EN, 0); + SDIO_REG_WRITE16(SDIO_ERR_INTR_EN, 0); + + udelay(2000); +/* count = 10000 ; + while((SDIO_REG_READ16(SDIO_PRESENT_STATE0) & CARD_BUSY)) { + udelay(DELAY); + if (--count <= 0 ) { + // card busy, can't sent cmd + printf("card too busy \n"); + return 0; + } + } +*/ + SDIO_REG_WRITE16(SDIO_ARG_LOW, (ushort)(arg&0xffff) ); + SDIO_REG_WRITE16(SDIO_ARG_HI, (ushort)(arg>>16) ); + SDIO_REG_WRITE16(SDIO_XFER_MODE, xfermode); + if( (cmd == MMC_CMD_READ_BLOCK) || (cmd == 25) ) + { + SDIO_REG_WRITE16(SDIO_CMD, ((cmd << 8) | resptype | 0x3c ) ); + debug("cmd reg : %x\n", SDIO_REG_READ16( SDIO_CMD )) ; + } + else + { + SDIO_REG_WRITE16(SDIO_CMD, ((cmd << 8) | resptype ) ); + } + + done = SDIO_REG_READ16(SDIO_NOR_INTR_STATUS) & waittype; + count = 10000 ; + + while( done!=waittype) + { +// udelay(DELAY); + udelay(2000); + done = SDIO_REG_READ16(SDIO_NOR_INTR_STATUS) & waittype; +/* if( SDIO_REG_READ16(SDIO_NOR_INTR_STATUS) & 0x8000 ) + { + printf("Error! cmd : %d, err : %x\n", cmd, SDIO_REG_READ16(SDIO_ERR_INTR_STATUS) ) ; + return 0 ; // error happen + } + if( --count <= 0 ) + { + debug("cmd timeout, status : %x\n", SDIO_REG_READ16(SDIO_NOR_INTR_STATUS)); + debug("xfer mode : %x\n", SDIO_REG_READ16(SDIO_XFER_MODE)); + err = 1 ; + break; + //return 0 ; + } +*/ + } + + // write clear the status + SDIO_REG_WRITE16(SDIO_NOR_INTR_STATUS, waittype); + //SDIO_REG_WRITE16(SDIO_NOR_INTR_EN, SDIO_REG_READ16(SDIO_NOR_INTR_STATUS)); + + switch (resptype & 0x3) { + case SDIO_CMD_RSP_48: + case SDIO_CMD_RSP_48BUSY: + resp[0] = ( SDIO_REG_READ16(SDIO_RSP0) << (16+6)) | + (SDIO_REG_READ16(SDIO_RSP1) << 6) | + ((SDIO_REG_READ16(SDIO_RSP2))& 0x3f) ; + break; + + case SDIO_CMD_RSP_136: + resp[0] = ( SDIO_REG_READ16(SDIO_RSP5) << (16+14)) | + (SDIO_REG_READ16(SDIO_RSP6) << 14) | + ((SDIO_REG_READ16(SDIO_RSP7))& 0x3fff) ; + resp[1] = ( SDIO_REG_READ16(SDIO_RSP3) << (16+14)) | + (SDIO_REG_READ16(SDIO_RSP4) << 14) | + ((SDIO_REG_READ16(SDIO_RSP5)>> 2 )& 0x3fff) ; + resp[2] = ( SDIO_REG_READ16(SDIO_RSP1) << (16+14)) | + (SDIO_REG_READ16(SDIO_RSP2) << 14) | + ((SDIO_REG_READ16(SDIO_RSP3)>> 2 )& 0x3fff) ; + resp[3] = (SDIO_REG_READ16(SDIO_RSP0) << 14) | + ((SDIO_REG_READ16(SDIO_RSP1)>> 2 )& 0x3fff) ; + break; + default: + return 0; + } +#ifdef MMC_DEBUG + int i; + printf("MMC resp :"); + for (i=0; i<4; ++i ) { + printf(" %08x", resp[i]); + } + printf("\n"); +#endif + if( err ) + return 0 ; + else + return (uchar*)resp; +} + +int +/****************************************************/ +mmc_block_read(uchar *dst, ulong src, ulong len) +/****************************************************/ +{ + uchar *resp; + //ushort argh, argl; + //ulong status; + + if (len == 0) { + return 0; + } + + debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong)dst, src, len); + + //mmc_cmd(ulong cmd, ulong arg, ushort xfermode, ushort resptype, ushort waittype); + /* set block len */ + resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); + + // prepare for dma transfer + //SDIO_REG_WRITE16(SDIO_SYS_ADDR_LOW,((ulong)(dst)>>16)&0xffff); + SDIO_REG_WRITE16(SDIO_SYS_ADDR_LOW,((ulong)(dst))&0xffff); + //SDIO_REG_WRITE16(SDIO_SYS_ADDR_HI,((ulong)(dst))&0xffff); + SDIO_REG_WRITE16(SDIO_SYS_ADDR_HI,(0x8000 | ((ulong)(dst)>>16)&0xffff)); + SDIO_REG_WRITE16(SDIO_BLK_SIZE,len); + SDIO_REG_WRITE16(SDIO_BLK_COUNT,1); + + + /* send read command */ + resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, 0x10 , // 0x12, + SDIO_CMD_RSP_48, SDIO_NOR_DMA_INI); + + return 0; +} + +int +/****************************************************/ +mmc_block_write(ulong dst, uchar *src, int len) +/****************************************************/ +{ + //uchar *resp; + //ushort argh, argl; + //ulong status; + return -1 ; +#if 0 + if (len == 0) { + return 0; + } + + debug("mmc_block_wr dst %lx src %lx len %d\n", dst, (ulong)src, len); + + argh = len >> 16; + argl = len & 0xffff; + + /* set block len */ + resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1); + + /* send write command */ + argh = dst >> 16; + argl = dst & 0xffff; + MMC_STRPCL = MMC_STRPCL_STOP_CLK; + MMC_NOB = 1; + MMC_BLKLEN = len; + resp = mmc_cmd(MMC_CMD_WRITE_BLOCK, argh, argl, + MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN); + + MMC_I_MASK = ~MMC_I_MASK_TXFIFO_WR_REQ; + while (len) { + if (MMC_I_REG & MMC_I_REG_TXFIFO_WR_REQ) { + int i, bytes = min(32,len); + + for (i=0; iid[0], cid->id[1], cid->id[2]); + printf("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev); + cid->hwrev = cid->fwrev = 0; /* null terminate string */ + printf("Product Name = %s\n",cid->name); + printf("Serial Number = %02x%02x%02x\n", + cid->sn[0], cid->sn[1], cid->sn[2]); + printf("Month = %d\n",cid->month); + printf("Year = %d\n",1997 + cid->year); + } + /* fill in device description */ + mmc_dev.if_type = IF_TYPE_MMC; + mmc_dev.part_type = PART_TYPE_DOS; + mmc_dev.dev = 0; + mmc_dev.lun = 0; + mmc_dev.type = 0; + /* FIXME fill in the correct size (is set to 128MByte) */ + mmc_dev.blksz = 512; + mmc_dev.lba = 0x40000; + printf(mmc_dev.vendor,"Man %02x%02x%02x Snr %02x%02x%02x", + cid->id[0], cid->id[1], cid->id[2], + cid->sn[0], cid->sn[1], cid->sn[2]); + printf(mmc_dev.product,"%s",cid->name); + printf(mmc_dev.revision,"%x %x",cid->hwrev, cid->fwrev); + mmc_dev.removable = 0; + mmc_dev.block_read = mmc_bread; + + //mmc_cmd(ulong cmd, ulong arg, ushort xfermode, ushort resptype, ushort waittype); + /* MMC exists, get CSD too */ + resp = mmc_cmd(MMC_CMD_SET_RCA, 0, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); + rca = resp[2] | (resp[3] << 8 ) ; + resp = mmc_cmd(MMC_CMD_SEND_CSD, rca<<16, 0, SDIO_CMD_RSP_136,SDIO_NOR_CMD_DONE ); + if (resp) { + mmc_csd_t *csd = (mmc_csd_t *)resp; + memcpy(&mmc_csd, csd, sizeof(csd)); + debug("cmd 9 resp 0 : %x %x %x %x\n", resp[0], resp[1], resp[2], resp[3] ); + debug("cmd 9 resp 1 : %x %x %x %x\n", resp[4], resp[5], resp[6], resp[7] ); + debug("cmd 9 resp 2 : %x %x %x %x\n", resp[8], resp[9], resp[10], resp[11] ); + debug("cmd 9 resp 3 : %x %x %x %x\n", resp[12], resp[13], resp[14], resp[15] ); + rc = 0; + /* Calc device size */ + debug("cmd 9 csd->c_size : %x\n", csd->c_size ); + debug("cmd 9 csd->c_size_mult1 : %x\n", csd->c_size_mult1 ); + debug("cmd 9 csd->read_bl_len : %x\n", csd->read_bl_len ); + debug("cmd 9 csd->tran_speed : %x\n", csd->tran_speed ); + debug("cmd 9 csd->nsac : %x\n", csd->nsac ); + debug("cmd 9 csd->taac : %x\n", csd->taac ); + /* FIXME add verbose printout for csd */ + mmc_ready = 1; + } + } + + resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca<<16, 0, SDIO_CMD_RSP_48BUSY, SDIO_NOR_CMD_DONE); +#if 0 + resp = mmc_cmd(MMC_CMD_SELECT_CARD, 0, 0, SDIO_CMD_RSP_48BUSY, SDIO_NOR_CMD_DONE); + + resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca<<16, 0, SDIO_CMD_RSP_48BUSY, SDIO_NOR_CMD_DONE); +#endif + resp = mmc_cmd(55, rca<<16, 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); + + resp = mmc_cmd(6, (rca<<16) | 0x2 , 0, SDIO_CMD_RSP_48, SDIO_NOR_CMD_DONE ); + +#if 0 + // prepare for dma transfer + SDIO_REG_WRITE16(SDIO_BLK_SIZE,8); + SDIO_REG_WRITE16(SDIO_BLK_COUNT,1); + SDIO_REG_WRITE16(SDIO_SYS_ADDR_LOW,((ulong)(scrs))&0xffff); + SDIO_REG_WRITE16(SDIO_SYS_ADDR_HI,((ulong)(scrs)>>16)&0xffff); + //ACMD 51 + resp = mmc_cmd(51, 0, 0x12, SDIO_CMD_RSP_48, SDIO_NOR_DMA_INI ); + + printf("scrs : %x %x %x %x %x %x %x %x\n", scrs[0], scrs[1], scrs[2], scrs[3], scrs[4], scrs[5], scrs[6], scrs[7] ); +#endif + fat_register_device(&mmc_dev,1); /* partitions start counting with 1 */ + + return rc; +} + +int +mmc_ident(block_dev_desc_t *dev) +{ + return 0; +} + +int +mmc2info(ulong addr) +{ + /* FIXME hard codes to 256 MB device */ + if (addr >= CFG_MMC_BASE && addr < CFG_MMC_BASE + 0xffffffff) { + return 1; + } + return 0; +} + +#endif /* CONFIG_MMC */ diff --git a/board/mv_feroceon/USP/sdio/mustang_sdiodef.h b/board/mv_feroceon/USP/sdio/mustang_sdiodef.h new file mode 100644 index 0000000..ab92d5a --- /dev/null +++ b/board/mv_feroceon/USP/sdio/mustang_sdiodef.h @@ -0,0 +1,211 @@ + + +#define MUSTANG_SDHC_BASE 0xf1080000 // from 00-4c +#define INTEGRATOR_GPIO_BASE 0x1b000000 +//#define SC_BASE + +#define P(x) (MUSTANG_SDHC_BASE + (2 * x)) + +#define GPIO_REG_READ32(addr) (*(volatile unsigned int*)(INTEGRATOR_GPIO_BASE+addr)) +#define GPIO_REG_WRITE32(addr, val) (*(volatile unsigned int*)(INTEGRATOR_GPIO_BASE+addr)=val) + +#define SDIO_REG_WRITE16(addr,val) (*(volatile unsigned short*)(P(addr)) = val) +#define SDIO_REG_READ16(addr) (*(volatile unsigned short*)(P(addr))) + +/* SDIO register offset */ +#define SDIO_SYS_ADDR_LOW 0x000 +#define SDIO_SYS_ADDR_HI 0x002 +#define SDIO_BLK_SIZE 0x004 +#define SDIO_BLK_COUNT 0x006 +#define SDIO_ARG_LOW 0x008 +#define SDIO_ARG_HI 0x00A +#define SDIO_XFER_MODE 0x00C +#define SDIO_CMD 0x00E +#define SDIO_RSP0 0x010 +#define SDIO_RSP1 0x012 +#define SDIO_RSP2 0x014 +#define SDIO_RSP3 0x016 +#define SDIO_RSP4 0x018 +#define SDIO_RSP5 0x01A +#define SDIO_RSP6 0x01C +#define SDIO_RSP7 0x01E +#define SDIO_BUF_DATA_PORT 0x020 +#define SDIO_RSVED 0x022 +#define SDIO_PRESENT_STATE0 0x024 +#define CARD_BUSY ((unsigned short)(0x1 << 1)) +#define SDIO_PRESENT_STATE1 0x026 +#define SDIO_HOST_CTRL 0x028 +#define SDIO_BLK_GAP_CTRL 0x02A +#define SDIO_CLK_CTRL 0x02C +#define SDIO_SW_RESET 0x02E +#define SDIO_NOR_INTR_STATUS 0x030 +#define SDIO_ERR_INTR_STATUS 0x032 +#define SDIO_NOR_STATUS_EN 0x034 +#define SDIO_ERR_STATUS_EN 0x036 +#define SDIO_NOR_INTR_EN 0x038 +#define SDIO_ERR_INTR_EN 0x03A +#define SDIO_AUTOCMD12_ERR_STATUS 0x03C +#define SDIO_CURR_BLK_SIZE 0x03E +#define SDIO_CURR_BLK_COUNT 0x040 +#define SDIO_AUTOCMD12_ARG_LOW 0x042 +#define SDIO_AUTOCMD12_ARG_HI 0x044 +#define SDIO_AUTOCMD12_INDEX 0x046 +#define SDIO_AUTO_RSP0 0x048 +#define SDIO_AUTO_RSP1 0x04A +#define SDIO_AUTO_RSP2 0x04C + +/************** SDIO_HOST_CTRL ****/ +#define SDIO_HOST_CTRL_PUSH_PULL_EN 1 +#define SDIO_HOST_CTRL_CARD_TYPE_MEM_ONLY 0 +#define SDIO_HOST_CTRL_CARD_TYPE_IO_ONLY (1<<1) +#define SDIO_HOST_CTRL_CARD_TYPE_IO_MEM_COMBO (2<<1) +#define SDIO_HOST_CTRL_CARD_TYPE_IO_MMC (3<<1) +#define SDIO_HOST_CTRL_BIG_ENDAN (1<<3) +#define SDIO_HOST_CTRL_LSB_FIRST (1<<4) +#define SDIO_HOST_CTRL_ID_MODE_LOW_FREQ (1<<5) +#define SDIO_HOST_CTRL_HALF_SPEED (1<<6) +#define SDIO_HOST_CTRL_DATA_WIDTH_4_BITS (1<<9) +#define SDIO_HOST_CTRL_HI_SPEED_EN (1<<10) +#define SDIO_HOST_CTRL_TMOUT_SHIFT 11 +#define SDIO_HOST_CTRL_TMOUT_EN (1<<15) + +#define SDIO_HOST_CTRL_DFAULT_OPEN_DRAIN (0xF< EXTINT1 (IRQ24) a can be used as SD_CARD_IN +// GPIO6 => can be used as SD_WP +// GPIO7 => can be used as SD_ON + +#define SDHC_GPIO_CARD_IN 0x00000002 +#define SDHC_GPIO_WP 0x00000040 +#define SDHC_GPIO_POWER 0x00000080 + +#define MUSTANG_GPIO_DIRECTION_OFFSET 8 +#define MUSTANG_GPIO_CLEAR_OFFSET 4 +#define MUSTANG_GPIO_SET_OFFSET 0 +#define MUSTANG_GPIO_DATAIN 0 + +//SC Flag bit 0 for Card Detection +// if bit 0 of 0x11000030 is zero, +// Card Insertion interrupt will be detected +// if bit 0 of 0x11000030 is 1 +// card Removal interrupt will be detected +#define MUSTANG_SCFLAG_STATUS_OFFSET 0x0 +#define MUSTANG_SCFLAG_SET_OFFSET 0x0 +#define MUSTANG_SCFLAG_CLEAR_OFFSET 0x4 + +#define MUSTANG_SD_CARDDET_TOGGLE_BIT 0x1 + +typedef struct mmc_cid +{ + /* FIXME: BYTE_ORDER */ + uchar year:4, + month:4; + uchar sn[3]; + uchar fwrev:4, + hwrev:4; + uchar name[6]; + uchar id[3]; +} mmc_cid_t; + +typedef struct mmc_csd +{ + uchar ecc:2, + file_format:2, + tmp_write_protect:1, + perm_write_protect:1, + copy:1, + file_format_grp:1; + uint64_t content_prot_app:1, + rsvd3:4, + write_bl_partial:1, + write_bl_len:4, + r2w_factor:3, + default_ecc:2, + wp_grp_enable:1, + wp_grp_size:5, + erase_grp_mult:5, + erase_grp_size:5, + c_size_mult1:3, + vdd_w_curr_max:3, + vdd_w_curr_min:3, + vdd_r_curr_max:3, + vdd_r_curr_min:3, + c_size:12, + rsvd2:2, + dsr_imp:1, + read_blk_misalign:1, + write_blk_misalign:1, + read_bl_partial:1; + ushort read_bl_len:4, + ccc:12; + uchar tran_speed; + uchar nsac; + uchar taac; + uchar rsvd1:2, + spec_vers:4, + csd_structure:2; +} mmc_csd_t; + diff --git a/board/mv_feroceon/common/mv802_3.h b/board/mv_feroceon/common/mv802_3.h new file mode 100644 index 0000000..0d7ea0e --- /dev/null +++ b/board/mv_feroceon/common/mv802_3.h @@ -0,0 +1,207 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmv802_3h +#define __INCmv802_3h + + +/* includes */ +#include "mvTypes.h" + +/* Defines */ +#define MV_MAX_ETH_DATA 1500 + +/* 802.3 types */ +#define MV_IP_TYPE 0x0800 +#define MV_IP_ARP_TYPE 0x0806 +#define MV_APPLE_TALK_ARP_TYPE 0x80F3 +#define MV_NOVELL_IPX_TYPE 0x8137 +#define MV_EAPOL_TYPE 0x888e + + + +/* Encapsulation header for RFC1042 and Ethernet_tunnel */ + +#define MV_RFC1042_SNAP_HEADER {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00} + +#define MV_ETH_SNAP_LSB 0xF8 + + +#define MV_MAC_ADDR_SIZE (6) +#define MV_MAC_STR_SIZE (20) +#define MV_VLAN_HLEN (4) + +/* This macro checks for a multicast mac address */ +#define MV_IS_MULTICAST_MAC(mac) (((mac)[0] & 0x1) == 1) + + +/* This macro checks for an broadcast mac address */ +#define MV_IS_BROADCAST_MAC(mac) \ + (((mac)[0] == 0xFF) && \ + ((mac)[1] == 0xFF) && \ + ((mac)[2] == 0xFF) && \ + ((mac)[3] == 0xFF) && \ + ((mac)[4] == 0xFF) && \ + ((mac)[5] == 0xFF)) + + +/* Typedefs */ +typedef struct +{ + MV_U8 pDA[MV_MAC_ADDR_SIZE]; + MV_U8 pSA[MV_MAC_ADDR_SIZE]; + MV_U16 typeOrLen; + +} MV_802_3_HEADER; + +enum { + MV_IP_PROTO_NULL = 0, /* Dummy protocol for TCP */ + MV_IP_PROTO_ICMP = 1, /* Internet Control Message Protocol */ + MV_IP_PROTO_IGMP = 2, /* Internet Group Management Protocol */ + MV_IP_PROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ + MV_IP_PROTO_TCP = 6, /* Transmission Control Protocol */ + MV_IP_PROTO_EGP = 8, /* Exterior Gateway Protocol */ + MV_IP_PROTO_PUP = 12, /* PUP protocol */ + MV_IP_PROTO_UDP = 17, /* User Datagram Protocol */ + MV_IP_PROTO_IDP = 22, /* XNS IDP protocol */ + MV_IP_PROTO_DCCP = 33, /* Datagram Congestion Control Protocol */ + MV_IP_PROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ + MV_IP_PROTO_RSVP = 46, /* RSVP protocol */ + MV_IP_PROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ + MV_IP_PROTO_ESP = 50, /* Encapsulation Security Payload protocol */ + MV_IP_PROTO_AH = 51, /* Authentication Header protocol */ + MV_IP_PROTO_BEETPH = 94, /* IP option pseudo header for BEET */ + MV_IP_PROTO_PIM = 103, + MV_IP_PROTO_COMP = 108, /* Compression Header protocol */ + MV_IP_PROTO_ZERO_HOP = 114, /* Any 0 hop protocol (IANA) */ + MV_IP_PROTO_SCTP = 132, /* Stream Control Transport Protocol */ + MV_IP_PROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ + + MV_IP_PROTO_RAW = 255, /* Raw IP packets */ + MV_IP_PROTO_MAX +}; + +typedef struct +{ + MV_U8 version; + MV_U8 tos; + MV_U16 totalLength; + MV_U16 identifier; + MV_U16 fragmentCtrl; + MV_U8 ttl; + MV_U8 protocol; + MV_U16 checksum; + MV_U32 srcIP; + MV_U32 dstIP; + +} MV_IP_HEADER; + +#define MV_ICMP_ECHOREPLY 0 /* Echo Reply */ +#define MV_ICMP_DEST_UNREACH 3 /* Destination Unreachable */ +#define MV_ICMP_SOURCE_QUENCH 4 /* Source Quench */ +#define MV_ICMP_REDIRECT 5 /* Redirect (change route) */ +#define MV_ICMP_ECHO 8 /* Echo Request */ +#define MV_ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ +#define MV_ICMP_PARAMETERPROB 12 /* Parameter Problem */ +#define MV_ICMP_TIMESTAMP 13 /* Timestamp Request */ +#define MV_ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */ +#define MV_ICMP_INFO_REQUEST 15 /* Information Request */ +#define MV_ICMP_INFO_REPLY 16 /* Information Reply */ +#define MV_ICMP_ADDRESS 17 /* Address Mask Request */ +#define MV_ICMP_ADDRESSREPLY 18 /* Address Mask Reply */ + +typedef struct +{ + MV_U8 type; + MV_U8 code; + MV_U16 checksum; + MV_U16 id; + MV_U16 sequence; + +} MV_ICMP_ECHO_HEADER; + +typedef struct +{ + MV_U16 source; + MV_U16 dest; + MV_U32 seq; + MV_U32 ack_seq; + MV_U16 flags; + MV_U16 window; + MV_U16 chksum; + MV_U16 urg_offset; + +} MV_TCP_HEADER; + +typedef struct +{ + MV_U16 source; + MV_U16 dest; + MV_U16 len; + MV_U16 check; + +} MV_UDP_HEADER; + +#endif /* __INCmv802_3h */ diff --git a/board/mv_feroceon/common/mvCommon.c b/board/mv_feroceon/common/mvCommon.c new file mode 100644 index 0000000..dc0e0cf --- /dev/null +++ b/board/mv_feroceon/common/mvCommon.c @@ -0,0 +1,277 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvOs.h" +#include "mv802_3.h" +#include "mvCommon.h" + + +/******************************************************************************* +* mvMacStrToHex - Convert MAC format string to hex. +* +* DESCRIPTION: +* This function convert MAC format string to hex. +* +* INPUT: +* macStr - MAC address string. Fornat of address string is +* uu:vv:ww:xx:yy:zz, where ":" can be any delimiter. +* +* OUTPUT: +* macHex - MAC in hex format. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvMacStrToHex(const char* macStr, MV_U8* macHex) +{ + int i; + char tmp[3]; + + for(i = 0; i < MV_MAC_ADDR_SIZE; i++) + { + tmp[0] = macStr[(i * 3) + 0]; + tmp[1] = macStr[(i * 3) + 1]; + tmp[2] = '\0'; + macHex[i] = (MV_U8) (strtol(tmp, NULL, 16)); + } + return MV_OK; +} + +/******************************************************************************* +* mvMacHexToStr - Convert MAC in hex format to string format. +* +* DESCRIPTION: +* This function convert MAC in hex format to string format. +* +* INPUT: +* macHex - MAC in hex format. +* +* OUTPUT: +* macStr - MAC address string. String format is uu:vv:ww:xx:yy:zz. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvMacHexToStr(MV_U8* macHex, char* macStr) +{ + int i; + + for(i = 0; i < MV_MAC_ADDR_SIZE; i++) + { + mvOsSPrintf(&macStr[i * 3], "%02x:", macHex[i]); + } + macStr[(i * 3) - 1] = '\0'; + + return MV_OK; +} + +/******************************************************************************* +* mvSizePrint - Print the given size with size unit description. +* +* DESCRIPTION: +* This function print the given size with size unit description. +* FOr example when size paramter is 0x180000, the function prints: +* "size 1MB+500KB" +* +* INPUT: +* size - Size in bytes. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvSizePrint(MV_U32 size) +{ + mvOsOutput("size "); + + if(size >= _1G) + { + mvOsOutput("%3dGB ", size / _1G); + size %= _1G; + if(size) + mvOsOutput("+"); + } + if(size >= _1M ) + { + mvOsOutput("%3dMB ", size / _1M); + size %= _1M; + if(size) + mvOsOutput("+"); + } + if(size >= _1K) + { + mvOsOutput("%3dKB ", size / _1K); + size %= _1K; + if(size) + mvOsOutput("+"); + } + if(size > 0) + { + mvOsOutput("%3dB ", size); + } +} + +/******************************************************************************* +* mvHexToBin - Convert hex to binary +* +* DESCRIPTION: +* This function Convert hex to binary. +* +* INPUT: +* pHexStr - hex buffer pointer. +* size - Size to convert. +* +* OUTPUT: +* pBin - Binary buffer pointer. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvHexToBin(const char* pHexStr, MV_U8* pBin, int size) +{ + int j, i; + char tmp[3]; + MV_U8 byte; + + for(j=0, i=0; j> 1; + result++; + } + return result; +} + + diff --git a/board/mv_feroceon/common/mvCommon.h b/board/mv_feroceon/common/mvCommon.h new file mode 100644 index 0000000..c8e9ce1 --- /dev/null +++ b/board/mv_feroceon/common/mvCommon.h @@ -0,0 +1,308 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + + +#ifndef __INCmvCommonh +#define __INCmvCommonh + +#include "mvTypes.h" + +/* Swap tool */ + +/* 16bit nibble swap. For example 0x1234 -> 0x2143 */ +#define MV_NIBBLE_SWAP_16BIT(X) (((X&0xf) << 4) | \ + ((X&0xf0) >> 4) | \ + ((X&0xf00) << 4) | \ + ((X&0xf000) >> 4)) + +/* 32bit nibble swap. For example 0x12345678 -> 0x21436587 */ +#define MV_NIBBLE_SWAP_32BIT(X) (((X&0xf) << 4) | \ + ((X&0xf0) >> 4) | \ + ((X&0xf00) << 4) | \ + ((X&0xf000) >> 4) | \ + ((X&0xf0000) << 4) | \ + ((X&0xf00000) >> 4) | \ + ((X&0xf000000) << 4) | \ + ((X&0xf0000000) >> 4)) + +/* 16bit byte swap. For example 0x1122 -> 0x2211 */ +#define MV_BYTE_SWAP_16BIT(X) ((((X)&0xff)<<8) | (((X)&0xff00)>>8)) + +/* 32bit byte swap. For example 0x11223344 -> 0x44332211 */ +#define MV_BYTE_SWAP_32BIT(X) ((((X)&0xff)<<24) | \ + (((X)&0xff00)<<8) | \ + (((X)&0xff0000)>>8) | \ + (((X)&0xff000000)>>24)) + +/* 64bit byte swap. For example 0x11223344.55667788 -> 0x88776655.44332211 */ +#define MV_BYTE_SWAP_64BIT(X) ((l64) ((((X)&0xffULL)<<56) | \ + (((X)&0xff00ULL)<<40) | \ + (((X)&0xff0000ULL)<<24) | \ + (((X)&0xff000000ULL)<<8) | \ + (((X)&0xff00000000ULL)>>8) | \ + (((X)&0xff0000000000ULL)>>24) | \ + (((X)&0xff000000000000ULL)>>40) | \ + (((X)&0xff00000000000000ULL)>>56))) + +/* Endianess macros. */ +#if defined(MV_CPU_LE) + #define MV_16BIT_LE(X) (X) + #define MV_32BIT_LE(X) (X) + #define MV_64BIT_LE(X) (X) + #define MV_16BIT_BE(X) MV_BYTE_SWAP_16BIT(X) + #define MV_32BIT_BE(X) MV_BYTE_SWAP_32BIT(X) + #define MV_64BIT_BE(X) MV_BYTE_SWAP_64BIT(X) +#elif defined(MV_CPU_BE) + #define MV_16BIT_LE(X) MV_BYTE_SWAP_16BIT(X) + #define MV_32BIT_LE(X) MV_BYTE_SWAP_32BIT(X) + #define MV_64BIT_LE(X) MV_BYTE_SWAP_64BIT(X) + #define MV_16BIT_BE(X) (X) + #define MV_32BIT_BE(X) (X) + #define MV_64BIT_BE(X) (X) +#else + #error "CPU endianess isn't defined!\n" +#endif + + +/* Bit field definitions */ +#define NO_BIT 0x00000000 +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +/* Handy sizes */ +#define _1K 0x00000400 +#define _2K 0x00000800 +#define _4K 0x00001000 +#define _8K 0x00002000 +#define _16K 0x00004000 +#define _32K 0x00008000 +#define _64K 0x00010000 +#define _128K 0x00020000 +#define _256K 0x00040000 +#define _512K 0x00080000 + +#define _1M 0x00100000 +#define _2M 0x00200000 +#define _4M 0x00400000 +#define _8M 0x00800000 +#define _16M 0x01000000 +#define _32M 0x02000000 +#define _64M 0x04000000 +#define _128M 0x08000000 +#define _256M 0x10000000 +#define _512M 0x20000000 + +#define _1G 0x40000000 +#define _2G 0x80000000 + +/* Tclock and Sys clock define */ +#define _100MHz 100000000 +#define _125MHz 125000000 +#define _133MHz 133333334 +#define _150MHz 150000000 +#define _160MHz 160000000 +#define _166MHz 166666667 +#define _175MHz 175000000 +#define _178MHz 178000000 +#define _183MHz 183333334 +#define _187MHz 187000000 +#define _192MHz 192000000 +#define _194MHz 194000000 +#define _200MHz 200000000 +#define _233MHz 233333334 +#define _250MHz 250000000 +#define _266MHz 266666667 +#define _300MHz 300000000 + +/* For better address window table readability */ +#define EN MV_TRUE +#define DIS MV_FALSE +#define N_A -1 /* Not applicable */ + +/* Cache configuration options for memory (DRAM, SRAM, ... ) */ + +/* Memory uncached, HW or SW cache coherency is not needed */ +#define MV_UNCACHED 0 +/* Memory cached, HW cache coherency supported in WriteThrough mode */ +#define MV_CACHE_COHER_HW_WT 1 +/* Memory cached, HW cache coherency supported in WriteBack mode */ +#define MV_CACHE_COHER_HW_WB 2 +/* Memory cached, No HW cache coherency, Cache coherency must be in SW */ +#define MV_CACHE_COHER_SW 3 + + +/* Macro for testing aligment. Positive if number is NOT aligned */ +#define MV_IS_NOT_ALIGN(number, align) ((number) & ((align) - 1)) + +/* Macro for alignment up. For example, MV_ALIGN_UP(0x0330, 0x20) = 0x0340 */ +#define MV_ALIGN_UP(number, align) \ +(((number) & ((align) - 1)) ? (((number) + (align)) & ~((align)-1)) : (number)) + +/* Macro for alignment down. For example, MV_ALIGN_UP(0x0330, 0x20) = 0x0320 */ +#define MV_ALIGN_DOWN(number, align) ((number) & ~((align)-1)) + +/* This macro returns absolute value */ +#define MV_ABS(number) (((int)(number) < 0) ? -(int)(number) : (int)(number)) + + +/* Bit fields manipulation macros */ + +/* An integer word which its 'x' bit is set */ +#define MV_BIT_MASK(bitNum) (1 << (bitNum) ) + +/* Checks wheter bit 'x' in integer word is set */ +#define MV_BIT_CHECK(word, bitNum) ( (word) & MV_BIT_MASK(bitNum) ) + +/* Clear (reset) bit 'x' in integer word (RMW - Read-Modify-Write) */ +#define MV_BIT_CLEAR(word, bitNum) ( (word) &= ~(MV_BIT_MASK(bitNum)) ) + +/* Set bit 'x' in integer word (RMW) */ +#define MV_BIT_SET(word, bitNum) ( (word) |= MV_BIT_MASK(bitNum) ) + +/* Invert bit 'x' in integer word (RMW) */ +#define MV_BIT_INV(word, bitNum) ( (word) ^= MV_BIT_MASK(bitNum) ) + +/* Get the min between 'a' or 'b' */ +#define MV_MIN(a,b) (((a) < (b)) ? (a) : (b)) + +/* Get the max between 'a' or 'b' */ +#define MV_MAX(a,b) (((a) < (b)) ? (b) : (a)) + +/* Temporary */ +#define mvOsDivide(num, div) \ +({ \ + int i=0, rem=(num); \ + \ + while(rem >= (div)) \ + { \ + rem -= (div); \ + i++; \ + } \ + (i); \ +}) + +/* Temporary */ +#define mvOsReminder(num, div) \ +({ \ + int rem = (num); \ + \ + while(rem >= (div)) \ + rem -= (div); \ + (rem); \ +}) + +#define MV_IP_QUAD(ipAddr) ((ipAddr >> 24) & 0xFF), ((ipAddr >> 16) & 0xFF), \ + ((ipAddr >> 8) & 0xFF), ((ipAddr >> 0) & 0xFF) + +#define MV_IS_POWER_OF_2(num) ((num != 0) && ((num & (num - 1)) == 0)) + +#ifndef MV_ASMLANGUAGE +/* mvCommon API list */ + +MV_VOID mvHexToBin(const char* pHexStr, MV_U8* pBin, int size); +void mvAsciiToHex(const char* asciiStr, char* hexStr); +void mvBinToHex(const MV_U8* bin, char* hexStr, int size); +void mvBinToAscii(const MV_U8* bin, char* asciiStr, int size); + +MV_STATUS mvMacStrToHex(const char* macStr, MV_U8* macHex); +MV_STATUS mvMacHexToStr(MV_U8* macHex, char* macStr); +void mvSizePrint(MV_U32); + +MV_U32 mvLog2(MV_U32 num); + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __INCmvCommonh */ diff --git a/board/mv_feroceon/common/mvDebug.c b/board/mv_feroceon/common/mvDebug.c new file mode 100644 index 0000000..087f36d --- /dev/null +++ b/board/mv_feroceon/common/mvDebug.c @@ -0,0 +1,326 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + + +/* includes */ +#include "mvOs.h" +#include "mv802_3.h" +#include "mvCommon.h" +#include "mvDebug.h" + +/* Global variables effect on behave MV_DEBUG_PRINT and MV_DEBUG_CODE macros + * mvDebug - map of bits (one for each module) bit=1 means enable + * debug code and messages for this module + * mvModuleDebug - array of 32 bits varables one for each module + */ +MV_U32 mvDebug = 0; +MV_U32 mvDebugModules[MV_MODULE_MAX]; + +/* Init mvModuleDebug array to default values */ +void mvDebugInit(void) +{ + int bit; + + mvDebug = 0; + for(bit=0; bit 0) + { + mvOsPrintf("%08x: ", memAddr); + i = 0; + /* 32 bytes in the line */ + while(i < 32) + { + if(memAddr >= (MV_U32)addr) + { + switch(access) + { + case 1: + if( memAddr == CPU_PHY_MEM(memAddr) ) + { + mvOsPrintf("%02x ", MV_MEMIO8_READ(memAddr)); + } + else + { + mvOsPrintf("%02x ", *((MV_U8*)memAddr)); + } + break; + + case 2: + if( memAddr == CPU_PHY_MEM(memAddr) ) + { + mvOsPrintf("%04x ", MV_MEMIO16_READ(memAddr)); + } + else + { + mvOsPrintf("%04x ", *((MV_U16*)memAddr)); + } + break; + + case 4: + if( memAddr == CPU_PHY_MEM(memAddr) ) + { + mvOsPrintf("%08x ", MV_MEMIO32_READ(memAddr)); + } + else + { + mvOsPrintf("%08x ", *((MV_U32*)memAddr)); + } + break; + } + } + else + { + for(j=0; j<(access*2+1); j++) + mvOsPrintf(" "); + } + i += access; + memAddr += access; + size -= access; + if(size <= 0) + break; + } + mvOsPrintf("\n"); + } +} + +void mvDebugPrintBufInfo(BUF_INFO* pBufInfo, int size, int access) +{ + if(pBufInfo == NULL) + { + mvOsPrintf("\n!!! pBufInfo = NULL\n"); + return; + } + mvOsPrintf("\n*** pBufInfo=0x%x, cmdSts=0x%08x, pBuf=0x%x, bufSize=%d\n", + (unsigned int)pBufInfo, + (unsigned int)pBufInfo->cmdSts, + (unsigned int)pBufInfo->pBuff, + (unsigned int)pBufInfo->bufSize); + mvOsPrintf("pData=0x%x, byteCnt=%d, pNext=0x%x, uInfo1=0x%x, uInfo2=0x%x\n", + (unsigned int)pBufInfo->pData, + (unsigned int)pBufInfo->byteCnt, + (unsigned int)pBufInfo->pNextBufInfo, + (unsigned int)pBufInfo->userInfo1, + (unsigned int)pBufInfo->userInfo2); + if(pBufInfo->pData != NULL) + { + if(size > pBufInfo->byteCnt) + size = pBufInfo->byteCnt; + mvDebugMemDump(pBufInfo->pData, size, access); + } +} + +void mvDebugPrintPktInfo(MV_PKT_INFO* pPktInfo, int size, int access) +{ + int frag, len; + + if(pPktInfo == NULL) + { + mvOsPrintf("\n!!! pPktInfo = NULL\n"); + return; + } + mvOsPrintf("\npPkt=%p, stat=0x%08x, numFr=%d, size=%d, pFr=%p, osInfo=0x%lx\n", + pPktInfo, pPktInfo->status, pPktInfo->numFrags, pPktInfo->pktSize, + pPktInfo->pFrags, pPktInfo->osInfo); + + for(frag=0; fragnumFrags; frag++) + { + mvOsPrintf("#%2d. bufVirt=%p, bufSize=%d\n", + frag, pPktInfo->pFrags[frag].bufVirtPtr, + pPktInfo->pFrags[frag].bufSize); + if(size > 0) + { + len = MV_MIN((int)pPktInfo->pFrags[frag].bufSize, size); + mvDebugMemDump(pPktInfo->pFrags[frag].bufVirtPtr, len, access); + size -= len; + } + } + +} + +void mvDebugPrintIpAddr(MV_U32 ipAddr) +{ + mvOsPrintf("%d.%d.%d.%d", ((ipAddr >> 24) & 0xFF), ((ipAddr >> 16) & 0xFF), + ((ipAddr >> 8) & 0xFF), ((ipAddr >> 0) & 0xFF)); +} + +void mvDebugPrintMacAddr(const MV_U8* pMacAddr) +{ + int i; + + mvOsPrintf("%02x", (unsigned int)pMacAddr[0]); + for(i=1; ibegin = 0; + pTimeEntry->count = count; + pTimeEntry->end = 0; + pTimeEntry->left = pTimeEntry->count; + pTimeEntry->total = 0; + pTimeEntry->min = 0xFFFFFFFF; + pTimeEntry->max = 0x0; + strncpy(pTimeEntry->name, pName, sizeof(pTimeEntry->name)-1); + pTimeEntry->name[sizeof(pTimeEntry->name)-1] = '\0'; +} + +/* Print out MV_DEBUG_TIMES entry */ +void mvDebugPrintTimeEntry(MV_DEBUG_TIMES* pTimeEntry, MV_BOOL isTitle) +{ + int num; + + if(isTitle == MV_TRUE) + mvOsPrintf("Event NumOfEvents TotalTime Average Min Max\n"); + + num = pTimeEntry->count-pTimeEntry->left; + if(num > 0) + { + mvOsPrintf("%-11s %6u 0x%08lx %6lu %6lu %6lu\n", + pTimeEntry->name, num, pTimeEntry->total, pTimeEntry->total/num, + pTimeEntry->min, pTimeEntry->max); + } +} + +/* Update MV_DEBUG_TIMES entry */ +void mvDebugUpdateTimeEntry(MV_DEBUG_TIMES* pTimeEntry) +{ + MV_U32 delta; + + if(pTimeEntry->left > 0) + { + if(pTimeEntry->end <= pTimeEntry->begin) + { + delta = pTimeEntry->begin - pTimeEntry->end; + } + else + { + delta = ((MV_U32)0x10000 - pTimeEntry->end) + pTimeEntry->begin; + } + pTimeEntry->total += delta; + + if(delta < pTimeEntry->min) + pTimeEntry->min = delta; + + if(delta > pTimeEntry->max) + pTimeEntry->max = delta; + + pTimeEntry->left--; + } +} + diff --git a/board/mv_feroceon/common/mvDebug.h b/board/mv_feroceon/common/mvDebug.h new file mode 100644 index 0000000..e4975be --- /dev/null +++ b/board/mv_feroceon/common/mvDebug.h @@ -0,0 +1,178 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + + +#ifndef __INCmvDebugh +#define __INCmvDebugh + +/* includes */ +#include "mvTypes.h" + +typedef enum +{ + MV_MODULE_INVALID = -1, + MV_MODULE_ETH = 0, + MV_MODULE_IDMA, + MV_MODULE_XOR, + MV_MODULE_TWASI, + MV_MODULE_MGI, + MV_MODULE_USB, + MV_MODULE_CESA, + + MV_MODULE_MAX +}MV_MODULE_ID; + +/* Define generic flags useful for most of modules */ +#define MV_DEBUG_FLAG_ALL (0) +#define MV_DEBUG_FLAG_INIT (1 << 0) +#define MV_DEBUG_FLAG_RX (1 << 1) +#define MV_DEBUG_FLAG_TX (1 << 2) +#define MV_DEBUG_FLAG_ERR (1 << 3) +#define MV_DEBUG_FLAG_TRACE (1 << 4) +#define MV_DEBUG_FLAG_DUMP (1 << 5) +#define MV_DEBUG_FLAG_CACHE (1 << 6) +#define MV_DEBUG_FLAG_IOCTL (1 << 7) +#define MV_DEBUG_FLAG_STATS (1 << 8) + +extern MV_U32 mvDebug; +extern MV_U32 mvDebugModules[MV_MODULE_MAX]; + +#ifdef MV_DEBUG +# define MV_DEBUG_PRINT(module, flags, msg) mvOsPrintf msg +# define MV_DEBUG_CODE(module, flags, code) code +#elif defined(MV_RT_DEBUG) +# define MV_DEBUG_PRINT(module, flags, msg) \ + if( (mvDebug & (1<<(module))) && \ + ((mvDebugModules[(module)] & (flags)) == (flags)) ) \ + mvOsPrintf msg +# define MV_DEBUG_CODE(module, flags, code) \ + if( (mvDebug & (1<<(module))) && \ + ((mvDebugModules[(module)] & (flags)) == (flags)) ) \ + code +#else +# define MV_DEBUG_PRINT(module, flags, msg) +# define MV_DEBUG_CODE(module, flags, code) +#endif + + + +/* typedefs */ + +/* time measurement structure used to check how much time pass between + * two points + */ +typedef struct { + char name[20]; /* name of the entry */ + unsigned long begin; /* time measured on begin point */ + unsigned long end; /* time measured on end point */ + unsigned long total; /* Accumulated time */ + unsigned long left; /* The rest measurement actions */ + unsigned long count; /* Maximum measurement actions */ + unsigned long min; /* Minimum time from begin to end */ + unsigned long max; /* Maximum time from begin to end */ +} MV_DEBUG_TIMES; + + +/* mvDebug.h API list */ + +/****** Error Recording ******/ + +/* Dump memory in specific format: + * address: X1X1X1X1 X2X2X2X2 ... X8X8X8X8 + */ +void mvDebugMemDump(void* addr, int size, int access); + +void mvDebugPrintBufInfo(BUF_INFO* pBufInfo, int size, int access); + +void mvDebugPrintPktInfo(MV_PKT_INFO* pPktInfo, int size, int access); + +void mvDebugPrintIpAddr(MV_U32 ipAddr); + +void mvDebugPrintMacAddr(const MV_U8* pMacAddr); + +/**** There are three functions deals with MV_DEBUG_TIMES structure ****/ + +/* Reset MV_DEBUG_TIMES entry */ +void mvDebugResetTimeEntry(MV_DEBUG_TIMES* pTimeEntry, int count, char* name); + +/* Update MV_DEBUG_TIMES entry */ +void mvDebugUpdateTimeEntry(MV_DEBUG_TIMES* pTimeEntry); + +/* Print out MV_DEBUG_TIMES entry */ +void mvDebugPrintTimeEntry(MV_DEBUG_TIMES* pTimeEntry, MV_BOOL isTitle); + + +/******** General ***********/ + +/* Change value of mvDebugPrint global variable */ + +void mvDebugInit(void); +void mvDebugModuleEnable(MV_MODULE_ID module, MV_BOOL isEnable); +void mvDebugModuleSetFlags(MV_MODULE_ID module, MV_U32 flags); +void mvDebugModuleClearFlags(MV_MODULE_ID module, MV_U32 flags); + + +#endif /* __INCmvDebug.h */ + diff --git a/board/mv_feroceon/common/mvDeviceId.h b/board/mv_feroceon/common/mvDeviceId.h new file mode 100644 index 0000000..ebc14ec --- /dev/null +++ b/board/mv_feroceon/common/mvDeviceId.h @@ -0,0 +1,173 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDeviceIdh +#define __INCmvDeviceIdh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines */ +#define MARVELL_VEN_ID 0x11ab + +/* Disco-3 */ +#define MV64460_DEV_ID 0x6480 +#define MV64460B_DEV_ID 0x6485 +#define MV64430_DEV_ID 0x6420 + +/* Disco-5 */ +#define MV64560_DEV_ID 0x6450 + +/* Disco-6 */ +#define MV64660_DEV_ID 0x6460 + +/* Orion */ +#define MV_1181_DEV_ID 0x1181 +#define MV_5181_DEV_ID 0x5181 +#define MV_5281_DEV_ID 0x5281 +#define MV_5182_DEV_ID 0x5182 +#define MV_8660_DEV_ID 0x8660 +#define MV_5180_DEV_ID 0x5180 +#define MV_5082_DEV_ID 0x5082 +#define MV_1281_DEV_ID 0x1281 +#define MV_6082_DEV_ID 0x6082 +#define MV_6183_DEV_ID 0x6183 +#define MV_6183L_DEV_ID 0x6083 + +#define MV_5281_D0_REV 0x4 +#define MV_5281_D0_ID ((MV_5281_DEV_ID << 16) | MV_5281_D0_REV) +#define MV_5281_D0_NAME "88F5281 D0" + +#define MV_5281_D1_REV 0x5 +#define MV_5281_D1_ID ((MV_5281_DEV_ID << 16) | MV_5281_D1_REV) +#define MV_5281_D1_NAME "88F5281 D1" + +#define MV_5281_D2_REV 0x6 +#define MV_5281_D2_ID ((MV_5281_DEV_ID << 16) | MV_5281_D2_REV) +#define MV_5281_D2_NAME "88F5281 D2" + + +#define MV_5181L_A0_REV 0x8 /* need for PCIE Er */ +#define MV_5181_A1_REV 0x1 /* for USB Er ..*/ +#define MV_5181_B0_REV 0x2 +#define MV_5181_B1_REV 0x3 +#define MV_5182_A1_REV 0x1 +#define MV_5180N_B1_REV 0x3 +#define MV_5181L_A0_ID ((MV_5181_DEV_ID << 16) | MV_5181L_A0_REV) + + + +/* kw */ +#define MV_6281_DEV_ID 0x6281 +#define MV_6192_DEV_ID 0x6192 +#define MV_6190_DEV_ID 0x6190 +#define MV_6180_DEV_ID 0x6180 + +#define MV_6281_A0_REV 0x2 +#define MV_6281_A0_ID ((MV_6281_DEV_ID << 16) | MV_6281_A0_REV) +#define MV_6281_A0_NAME "88F6281 A0" + +#define MV_6192_A0_REV 0x2 +#define MV_6192_A0_ID ((MV_6192_DEV_ID << 16) | MV_6192_A0_REV) +#define MV_6192_A0_NAME "88F6192 A0" + +#define MV_6190_A0_REV 0x2 +#define MV_6190_A0_ID ((MV_6190_DEV_ID << 16) | MV_6190_A0_REV) +#define MV_6190_A0_NAME "88F6190 A0" + +#define MV_6180_A0_REV 0x2 +#define MV_6180_A0_ID ((MV_6180_DEV_ID << 16) | MV_6180_A0_REV) +#define MV_6180_A0_NAME "88F6180 A0" + +/* Disco-Duo */ +#define MV_78XX0_ZY_DEV_ID 0x6381 +#define MV_78XX0_ZY_NAME "MV78X00" + +#define MV_78XX0_Z0_REV 0x1 +#define MV_78XX0_Z0_ID ((MV_78XX0_ZY_DEV_ID << 16) | MV_78XX0_Z0_REV) +#define MV_78XX0_Z0_NAME "78X00 Z0" + +#define MV_78XX0_Y0_REV 0x2 +#define MV_78XX0_Y0_ID ((MV_78XX0_ZY_DEV_ID << 16) | MV_78XX0_Y0_REV) +#define MV_78XX0_Y0_NAME "78X00 Y0" + +#define MV_78XX0_DEV_ID 0x7800 +#define MV_78XX0_NAME "MV78X00" + +#define MV_78200_DEV_ID 0x7820 +#define MV_78100_DEV_ID 0x7810 +#define MV_78XX0_A0_REV 0x1 + +#define MV_78100_NAME "MV78100" +#define MV_78200_NAME "MV78200" + +#define MV_78100_A0_ID ((MV_78100_DEV_ID << 16) | MV_78XX0_A0_REV) +#define MV_78200_A0_ID ((MV_78200_DEV_ID << 16) | MV_78XX0_A0_REV) + +#define MV_78100_A0_NAME "MV78100 A0" +#define MV_78200_A0_NAME "MV78200 A0" +#define MV_78XX0_A0_NAME "MV78XX0 A0" + +#endif /* __INCmvDeviceIdh */ diff --git a/board/mv_feroceon/common/mvStack.c b/board/mv_feroceon/common/mvStack.c new file mode 100644 index 0000000..ec5fbb5 --- /dev/null +++ b/board/mv_feroceon/common/mvStack.c @@ -0,0 +1,100 @@ +/******************************************************************************* +* Copyright 2003, Marvell Semiconductor Israel LTD. * +* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL. * +* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT * +* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE * +* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL. * +* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED, * +* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE. * +* * +* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, * +* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL * +* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K. * +* (MJKK), MARVELL SEMICONDUCTOR ISRAEL LTD (MSIL). * +******************************************************************************** +* mvQueue.c +* +* FILENAME: $Workfile: mvStack.c $ +* REVISION: $Revision: 1.1.1.1 $ +* LAST UPDATE: $Modtime: $ +* +* DESCRIPTION: +* This file implements simple Stack LIFO functionality. +*******************************************************************************/ + +/* includes */ +#include "mvOs.h" +#include "mvTypes.h" +#include "mvDebug.h" +#include "mvStack.h" + +/* defines */ + + +/* Public functions */ + + +/* Purpose: Create new stack + * Inputs: + * - MV_U32 noOfElements - maximum number of elements in the stack. + * Each element 4 bytes size + * Return: void* - pointer to created stack. + */ +void* mvStackCreate(int numOfElements) +{ + MV_STACK* pStack; + MV_U32* pStackElements; + + pStack = (MV_STACK*)mvOsMalloc(sizeof(MV_STACK)); + pStackElements = (MV_U32*)mvOsMalloc(numOfElements*sizeof(MV_U32)); + if( (pStack == NULL) || (pStackElements == NULL) ) + { + mvOsPrintf("mvStack: Can't create new stack\n"); + return NULL; + } + memset(pStackElements, 0, numOfElements*sizeof(MV_U32)); + pStack->numOfElements = numOfElements; + pStack->stackIdx = 0; + pStack->stackElements = pStackElements; + + return pStack; +} + +/* Purpose: Delete existing stack + * Inputs: + * - void* stackHndl - Stack handle as returned by "mvStackCreate()" function + * + * Return: MV_STATUS MV_NOT_FOUND - Failure. StackHandle is not valid. + * MV_OK - Success. + */ +MV_STATUS mvStackDelete(void* stackHndl) +{ + MV_STACK* pStack = (MV_STACK*)stackHndl; + + if( (pStack == NULL) || (pStack->stackElements == NULL) ) + return MV_NOT_FOUND; + + mvOsFree(pStack->stackElements); + mvOsFree(pStack); + + return MV_OK; +} + + +/* PrintOut status of the stack */ +void mvStackStatus(void* stackHndl, MV_BOOL isPrintElements) +{ + int i; + MV_STACK* pStack = (MV_STACK*)stackHndl; + + mvOsPrintf("StackHandle=%p, pElements=%p, numElements=%d, stackIdx=%d\n", + stackHndl, pStack->stackElements, pStack->numOfElements, + pStack->stackIdx); + if(isPrintElements == MV_TRUE) + { + for(i=0; istackIdx; i++) + { + mvOsPrintf("%3d. Value=0x%x\n", i, pStack->stackElements[i]); + } + } +} diff --git a/board/mv_feroceon/common/mvStack.h b/board/mv_feroceon/common/mvStack.h new file mode 100644 index 0000000..0498696 --- /dev/null +++ b/board/mv_feroceon/common/mvStack.h @@ -0,0 +1,140 @@ +/******************************************************************************* +* Copyright 2003, Marvell Semiconductor Israel LTD. * +* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL. * +* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT * +* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE * +* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL. * +* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED, * +* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE. * +* * +* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, * +* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL * +* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K. * +* (MJKK), MARVELL SEMICONDUCTOR ISRAEL LTD (MSIL). * +******************************************************************************** +* mvStack.h - Header File for : +* +* FILENAME: $Workfile: mvStack.h $ +* REVISION: $Revision: 1.1.1.1 $ +* LAST UPDATE: $Modtime: $ +* +* DESCRIPTION: +* This file defines simple Stack (LIFO) functionality. +* +*******************************************************************************/ + +#ifndef __mvStack_h__ +#define __mvStack_h__ + + +/* includes */ +#include "mvTypes.h" + + +/* defines */ + + +/* typedefs */ +/* Data structure describes general purpose Stack */ +typedef struct +{ + int stackIdx; + int numOfElements; + MV_U32* stackElements; +} MV_STACK; + +static INLINE MV_BOOL mvStackIsFull(void* stackHndl) +{ + MV_STACK* pStack = (MV_STACK*)stackHndl; + + if(pStack->stackIdx == pStack->numOfElements) + return MV_TRUE; + + return MV_FALSE; +} + +static INLINE MV_BOOL mvStackIsEmpty(void* stackHndl) +{ + MV_STACK* pStack = (MV_STACK*)stackHndl; + + if(pStack->stackIdx == 0) + return MV_TRUE; + + return MV_FALSE; +} +/* Purpose: Push new element to stack + * Inputs: + * - void* stackHndl - Stack handle as returned by "mvStackCreate()" function. + * - MV_U32 value - New element. + * + * Return: MV_STATUS MV_FULL - Failure. Stack is full. + * MV_OK - Success. Element is put to stack. + */ +static INLINE void mvStackPush(void* stackHndl, MV_U32 value) +{ + MV_STACK* pStack = (MV_STACK*)stackHndl; + +#ifdef MV_RT_DEBUG + if(pStack->stackIdx == pStack->numOfElements) + { + mvOsPrintf("mvStackPush: Stack is FULL\n"); + return; + } +#endif /* MV_RT_DEBUG */ + + pStack->stackElements[pStack->stackIdx] = value; + pStack->stackIdx++; +} + +/* Purpose: Pop element from the top of stack and copy it to "pValue" + * Inputs: + * - void* stackHndl - Stack handle as returned by "mvStackCreate()" function. + * - MV_U32 value - Element in the top of stack. + * + * Return: MV_STATUS MV_EMPTY - Failure. Stack is empty. + * MV_OK - Success. Element is removed from the stack and + * copied to pValue argument + */ +static INLINE MV_U32 mvStackPop(void* stackHndl) +{ + MV_STACK* pStack = (MV_STACK*)stackHndl; + +#ifdef MV_RT_DEBUG + if(pStack->stackIdx == 0) + { + mvOsPrintf("mvStackPop: Stack is EMPTY\n"); + return 0; + } +#endif /* MV_RT_DEBUG */ + + pStack->stackIdx--; + return pStack->stackElements[pStack->stackIdx]; +} + +static INLINE int mvStackIndex(void* stackHndl) +{ + MV_STACK* pStack = (MV_STACK*)stackHndl; + + return pStack->stackIdx; +} + +static INLINE int mvStackFreeElements(void* stackHndl) +{ + MV_STACK* pStack = (MV_STACK*)stackHndl; + + return (pStack->numOfElements - pStack->stackIdx); +} + +/* mvStack.h API list */ + +/* Create new Stack */ +void* mvStackCreate(int numOfElements); + +/* Delete existing stack */ +MV_STATUS mvStackDelete(void* stackHndl); + +/* Print status of the stack */ +void mvStackStatus(void* stackHndl, MV_BOOL isPrintElements); + +#endif /* __mvStack_h__ */ + diff --git a/board/mv_feroceon/common/mvTypes.h b/board/mv_feroceon/common/mvTypes.h new file mode 100644 index 0000000..772a969 --- /dev/null +++ b/board/mv_feroceon/common/mvTypes.h @@ -0,0 +1,245 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvTypesh +#define __INCmvTypesh + +/* Defines */ + +/* The following is a list of Marvell status */ +#define MV_ERROR (-1) +#define MV_OK (0x00) /* Operation succeeded */ +#define MV_FAIL (0x01) /* Operation failed */ +#define MV_BAD_VALUE (0x02) /* Illegal value (general) */ +#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */ +#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */ +#define MV_BAD_PTR (0x05) /* Illegal pointer value */ +#define MV_BAD_SIZE (0x06) /* Illegal size */ +#define MV_BAD_STATE (0x07) /* Illegal state of state machine */ +#define MV_SET_ERROR (0x08) /* Set operation failed */ +#define MV_GET_ERROR (0x09) /* Get operation failed */ +#define MV_CREATE_ERROR (0x0A) /* Fail while creating an item */ +#define MV_NOT_FOUND (0x0B) /* Item not found */ +#define MV_NO_MORE (0x0C) /* No more items found */ +#define MV_NO_SUCH (0x0D) /* No such item */ +#define MV_TIMEOUT (0x0E) /* Time Out */ +#define MV_NO_CHANGE (0x0F) /* Parameter(s) is already in this value */ +#define MV_NOT_SUPPORTED (0x10) /* This request is not support */ +#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented */ +#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */ +#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */ +#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */ +#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */ +#define MV_INIT_ERROR (0x16) /* Error occured while INIT process */ +#define MV_HW_ERROR (0x17) /* Hardware error */ +#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */ +#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */ +#define MV_NOT_READY (0x1A) /* The other side is not ready yet */ +#define MV_ALREADY_EXIST (0x1B) /* Tried to create existing item */ +#define MV_OUT_OF_CPU_MEM (0x1C) /* Cpu memory allocation failed. */ +#define MV_NOT_STARTED (0x1D) /* Not started yet */ +#define MV_BUSY (0x1E) /* Item is busy. */ +#define MV_TERMINATE (0x1F) /* Item terminates it's work. */ +#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */ +#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */ +#define MV_WRITE_PROTECT (0x22) /* Write protected */ + + +#define MV_INVALID (int)(-1) + +#define MV_FALSE 0 +#define MV_TRUE (!(MV_FALSE)) + + +#ifndef NULL +#define NULL ((void*)0) +#endif + + +#ifndef MV_ASMLANGUAGE +/* typedefs */ + +typedef char MV_8; +typedef unsigned char MV_U8; + +typedef int MV_32; +typedef unsigned int MV_U32; + +typedef short MV_16; +typedef unsigned short MV_U16; + +#ifdef MV_PPC64 +typedef long MV_64; +typedef unsigned long MV_U64; +#else +typedef long long MV_64; +typedef unsigned long long MV_U64; +#endif + +typedef long MV_LONG; /* 32/64 */ +typedef unsigned long MV_ULONG; /* 32/64 */ + +typedef int MV_STATUS; +typedef int MV_BOOL; +typedef void MV_VOID; +typedef float MV_FLOAT; + +typedef int (*MV_FUNCPTR) (void); /* ptr to function returning int */ +typedef void (*MV_VOIDFUNCPTR) (void); /* ptr to function returning void */ +typedef double (*MV_DBLFUNCPTR) (void); /* ptr to function returning double*/ +typedef float (*MV_FLTFUNCPTR) (void); /* ptr to function returning float */ + +typedef MV_U32 MV_KHZ; +typedef MV_U32 MV_MHZ; +typedef MV_U32 MV_HZ; + + +/* This enumerator describes the set of commands that can be applied on */ +/* an engine (e.g. IDMA, XOR). Appling a comman depends on the current */ +/* status (see MV_STATE enumerator) */ +/* Start can be applied only when status is IDLE */ +/* Stop can be applied only when status is IDLE, ACTIVE or PAUSED */ +/* Pause can be applied only when status is ACTIVE */ +/* Restart can be applied only when status is PAUSED */ +typedef enum _mvCommand +{ + MV_START, /* Start */ + MV_STOP, /* Stop */ + MV_PAUSE, /* Pause */ + MV_RESTART /* Restart */ +} MV_COMMAND; + +/* This enumerator describes the set of state conditions. */ +/* Moving from one state to other is stricted. */ +typedef enum _mvState +{ + MV_IDLE, + MV_ACTIVE, + MV_PAUSED, + MV_UNDEFINED_STATE +} MV_STATE; + + +/* This structure describes address space window. Window base can be */ +/* 64 bit, window size up to 4GB */ +typedef struct _mvAddrWin +{ + MV_U32 baseLow; /* 32bit base low */ + MV_U32 baseHigh; /* 32bit base high */ + MV_U32 size; /* 32bit size */ +}MV_ADDR_WIN; + +/* This binary enumerator describes protection attribute status */ +typedef enum _mvProtRight +{ + ALLOWED, /* Protection attribute allowed */ + FORBIDDEN /* Protection attribute forbidden */ +}MV_PROT_RIGHT; + +/* Unified struct for Rx and Tx packet operations. The user is required to */ +/* be familier only with Tx/Rx descriptor command status. */ +typedef struct _bufInfo +{ + MV_U32 cmdSts; /* Tx/Rx command status */ + MV_U16 byteCnt; /* Size of valid data in the buffer */ + MV_U16 bufSize; /* Total size of the buffer */ + MV_U8 *pBuff; /* Pointer to Buffer */ + MV_U8 *pData; /* Pointer to data in the Buffer */ + MV_U32 userInfo1; /* Tx/Rx attached user information 1 */ + MV_U32 userInfo2; /* Tx/Rx attached user information 2 */ + struct _bufInfo *pNextBufInfo; /* Next buffer in packet */ +} BUF_INFO; + +/* This structure contains information describing one of buffers + * (fragments) they are built Ethernet packet. + */ +typedef struct +{ + MV_U8* bufVirtPtr; + MV_ULONG bufPhysAddr; + MV_U32 bufSize; + MV_U32 dataSize; + + MV_U32 memHandle; +} MV_BUF_INFO; + +/* This structure contains information describing Ethernet packet. + * The packet can be divided for few buffers (fragments) + */ +typedef struct +{ + MV_ULONG osInfo; + MV_BUF_INFO *pFrags; + MV_U32 status; + MV_U16 pktSize; + MV_U16 numFrags; + char srcIdx; + MV_U32 fragIP; +} MV_PKT_INFO; + +#endif /* MV_ASMLANGUAGE */ + +#endif /* __INCmvTypesh */ + diff --git a/board/mv_feroceon/common/mvTypes.h.keep b/board/mv_feroceon/common/mvTypes.h.keep new file mode 100644 index 0000000..772a969 --- /dev/null +++ b/board/mv_feroceon/common/mvTypes.h.keep @@ -0,0 +1,245 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvTypesh +#define __INCmvTypesh + +/* Defines */ + +/* The following is a list of Marvell status */ +#define MV_ERROR (-1) +#define MV_OK (0x00) /* Operation succeeded */ +#define MV_FAIL (0x01) /* Operation failed */ +#define MV_BAD_VALUE (0x02) /* Illegal value (general) */ +#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */ +#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */ +#define MV_BAD_PTR (0x05) /* Illegal pointer value */ +#define MV_BAD_SIZE (0x06) /* Illegal size */ +#define MV_BAD_STATE (0x07) /* Illegal state of state machine */ +#define MV_SET_ERROR (0x08) /* Set operation failed */ +#define MV_GET_ERROR (0x09) /* Get operation failed */ +#define MV_CREATE_ERROR (0x0A) /* Fail while creating an item */ +#define MV_NOT_FOUND (0x0B) /* Item not found */ +#define MV_NO_MORE (0x0C) /* No more items found */ +#define MV_NO_SUCH (0x0D) /* No such item */ +#define MV_TIMEOUT (0x0E) /* Time Out */ +#define MV_NO_CHANGE (0x0F) /* Parameter(s) is already in this value */ +#define MV_NOT_SUPPORTED (0x10) /* This request is not support */ +#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented */ +#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */ +#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */ +#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */ +#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */ +#define MV_INIT_ERROR (0x16) /* Error occured while INIT process */ +#define MV_HW_ERROR (0x17) /* Hardware error */ +#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */ +#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */ +#define MV_NOT_READY (0x1A) /* The other side is not ready yet */ +#define MV_ALREADY_EXIST (0x1B) /* Tried to create existing item */ +#define MV_OUT_OF_CPU_MEM (0x1C) /* Cpu memory allocation failed. */ +#define MV_NOT_STARTED (0x1D) /* Not started yet */ +#define MV_BUSY (0x1E) /* Item is busy. */ +#define MV_TERMINATE (0x1F) /* Item terminates it's work. */ +#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */ +#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */ +#define MV_WRITE_PROTECT (0x22) /* Write protected */ + + +#define MV_INVALID (int)(-1) + +#define MV_FALSE 0 +#define MV_TRUE (!(MV_FALSE)) + + +#ifndef NULL +#define NULL ((void*)0) +#endif + + +#ifndef MV_ASMLANGUAGE +/* typedefs */ + +typedef char MV_8; +typedef unsigned char MV_U8; + +typedef int MV_32; +typedef unsigned int MV_U32; + +typedef short MV_16; +typedef unsigned short MV_U16; + +#ifdef MV_PPC64 +typedef long MV_64; +typedef unsigned long MV_U64; +#else +typedef long long MV_64; +typedef unsigned long long MV_U64; +#endif + +typedef long MV_LONG; /* 32/64 */ +typedef unsigned long MV_ULONG; /* 32/64 */ + +typedef int MV_STATUS; +typedef int MV_BOOL; +typedef void MV_VOID; +typedef float MV_FLOAT; + +typedef int (*MV_FUNCPTR) (void); /* ptr to function returning int */ +typedef void (*MV_VOIDFUNCPTR) (void); /* ptr to function returning void */ +typedef double (*MV_DBLFUNCPTR) (void); /* ptr to function returning double*/ +typedef float (*MV_FLTFUNCPTR) (void); /* ptr to function returning float */ + +typedef MV_U32 MV_KHZ; +typedef MV_U32 MV_MHZ; +typedef MV_U32 MV_HZ; + + +/* This enumerator describes the set of commands that can be applied on */ +/* an engine (e.g. IDMA, XOR). Appling a comman depends on the current */ +/* status (see MV_STATE enumerator) */ +/* Start can be applied only when status is IDLE */ +/* Stop can be applied only when status is IDLE, ACTIVE or PAUSED */ +/* Pause can be applied only when status is ACTIVE */ +/* Restart can be applied only when status is PAUSED */ +typedef enum _mvCommand +{ + MV_START, /* Start */ + MV_STOP, /* Stop */ + MV_PAUSE, /* Pause */ + MV_RESTART /* Restart */ +} MV_COMMAND; + +/* This enumerator describes the set of state conditions. */ +/* Moving from one state to other is stricted. */ +typedef enum _mvState +{ + MV_IDLE, + MV_ACTIVE, + MV_PAUSED, + MV_UNDEFINED_STATE +} MV_STATE; + + +/* This structure describes address space window. Window base can be */ +/* 64 bit, window size up to 4GB */ +typedef struct _mvAddrWin +{ + MV_U32 baseLow; /* 32bit base low */ + MV_U32 baseHigh; /* 32bit base high */ + MV_U32 size; /* 32bit size */ +}MV_ADDR_WIN; + +/* This binary enumerator describes protection attribute status */ +typedef enum _mvProtRight +{ + ALLOWED, /* Protection attribute allowed */ + FORBIDDEN /* Protection attribute forbidden */ +}MV_PROT_RIGHT; + +/* Unified struct for Rx and Tx packet operations. The user is required to */ +/* be familier only with Tx/Rx descriptor command status. */ +typedef struct _bufInfo +{ + MV_U32 cmdSts; /* Tx/Rx command status */ + MV_U16 byteCnt; /* Size of valid data in the buffer */ + MV_U16 bufSize; /* Total size of the buffer */ + MV_U8 *pBuff; /* Pointer to Buffer */ + MV_U8 *pData; /* Pointer to data in the Buffer */ + MV_U32 userInfo1; /* Tx/Rx attached user information 1 */ + MV_U32 userInfo2; /* Tx/Rx attached user information 2 */ + struct _bufInfo *pNextBufInfo; /* Next buffer in packet */ +} BUF_INFO; + +/* This structure contains information describing one of buffers + * (fragments) they are built Ethernet packet. + */ +typedef struct +{ + MV_U8* bufVirtPtr; + MV_ULONG bufPhysAddr; + MV_U32 bufSize; + MV_U32 dataSize; + + MV_U32 memHandle; +} MV_BUF_INFO; + +/* This structure contains information describing Ethernet packet. + * The packet can be divided for few buffers (fragments) + */ +typedef struct +{ + MV_ULONG osInfo; + MV_BUF_INFO *pFrags; + MV_U32 status; + MV_U16 pktSize; + MV_U16 numFrags; + char srcIdx; + MV_U32 fragIP; +} MV_PKT_INFO; + +#endif /* MV_ASMLANGUAGE */ + +#endif /* __INCmvTypesh */ + diff --git a/board/mv_feroceon/config/Makefile b/board/mv_feroceon/config/Makefile new file mode 100644 index 0000000..f0467ac --- /dev/null +++ b/board/mv_feroceon/config/Makefile @@ -0,0 +1,82 @@ +include mvRules.mk + + +# Objects list + +COMMON_OBJS = $(COMMON_DIR)/mvCommon.o + +OSSERVICES_OBJS = $(OSSERVICES_DIR)/mvOs.o $(OSSERVICES_DIR)/mvOsSata.o + +BOARD_OBJS = $(BOARD_ENV_DIR)/mvBoardEnvLib.o $(BOARD_ENV_DIR)/mvBoardEnvSpec.o + +HAL_OBJS = $(HAL_FLASH_DIR)/mvFlash.o $(HAL_FLASH_DIR)/mvAmdFlash.o $(HAL_FLASH_DIR)/mvIntelFlash.o \ + $(HAL_FLASH_DIR)/mvFlashCom.o $(HAL_DRAM_DIR)/mvDram.o $(HAL_DRAM_DIR)/mvDramIf.o \ + $(HAL_SATA_CORE_DIR)/mvSata.o $(HAL_SATA_CORE_DIR)/mvStorageDev.o \ + $(HAL_SATA_CORE_DIR)/mvLog.o $(HAL_SFLASH_DIR)/mvSFlash.o \ + $(HAL_ETHPHY_DIR)/mvEthPhy.o $(HAL_RTC_DIR)/mvDS133x.o \ + $(HAL_CNTMR_DIR)/mvCntmr.o $(HAL_TWSI_DIR)/mvTwsi.o \ + $(HAL_UART_DIR)/mvUart.o $(HAL_GPP_DIR)/mvGpp.o \ + $(HAL_MFLASH_DIR)/mvMFlash.o $(HAL_SPI_DIR)/mvSpi.o \ + $(HAL_MFLASH_DIR)/mvSMFlash.o $(HAL_MFLASH_DIR)/mvPMFlash.o \ + $(HAL_SPI_DIR)/mvSpiCmnd.o $(HAL_PCI_DIR)/mvPci.o $(HAL_USB_DIR)/mvUsb.o \ + $(HAL_IDMA_DIR)/mvIdma.o $(HAL_XOR_DIR)/mvXor.o \ + $(HAL_ETH_GBE_DIR)/mvEth.o $(HAL_PCIIF_DIR)/mvPciIf.o \ + $(HAL_PEX_DIR)/mvPex.o $(HAL_ETH_SWITCH_DIR)/mvSwitch.o + +SOC_OBJS = $(SOC_DIR)/mv_cmd.o $(SOC_DIR)/mv_dram.o $(SOC_DIR)/mv_main.o \ + $(SOC_ENV_DIR)/mvCtrlEnvLib.o $(SOC_ENV_DIR)/mvCtrlEnvPadCalibration.o \ + $(SOC_ENV_DIR)/mvCtrlEnvAddrDec.o $(SOC_SYS_DIR)/mvAhbToMbus.o \ + $(SOC_SYS_DIR)/mvCpuIf.o $(SOC_SYS_DIR)/mvSysXor.o \ + $(SOC_SYS_DIR)/mvSysGbe.o $(SOC_SYS_DIR)/mvSysIdma.o $(SOC_SYS_DIR)/mvSysPci.o \ + $(SOC_SYS_DIR)/mvSysPex.o $(SOC_SYS_DIR)/mvSysSata.o $(SOC_SYS_DIR)/mvSysUsb.o \ + $(SOC_CPU_DIR)/mvCpuArm.o $(SOC_DEVICE_DIR)/mvDevice.o + +ifneq ($(MV_TINY_IMAGE), y) +SOC_OBJS += $(HAL_PCIIF_DIR)/pci_util/mvPciUtils.o +endif + +USP_OBJS = $(USP_DIR)/mv_flash.o $(USP_DIR)/mv_serial.o \ + $(USP_DIR)/mv_pageTable.o $(USP_DIR)/mv_rtc.o $(USP_DIR)/mv_mon_init.o \ + $(USP_DIR)/mv_pci.o $(USP_DIR)/mv_nand.o \ + $(USP_DIR)/mv_ide.o $(USP_DIR)/mv_egiga.o \ + $(USP_DIR)/mv_fs.o $(USP_DIR)/mv_loadnet.o $(USP_DIR)/mv_protectionUnit.o \ + $(USP_DIR)/mv_i2c.o $(USP_DIR)/mv_ext2_boot.o + +ifeq ($(NAND_BOOT), y) +USP_OBJS += $(USP_DIR)/nBootloader.o +endif + +SOBJS = ../USP/jump.o \ + ../mv_orion/platform.o \ + $(HAL_DRAM_DIR)/mvDramIfBasicInit.o \ + $(HAL_DRAM_DIR)/mvDramIfConfig.o \ + $(HAL_DIR)/twsi/mvTwsiEeprom.o \ + $(SOC_SYS_DIR)/mvCpuIfInit.o + +ifeq ($(NAND_BOOT), y) +ifeq ($(NAND_LARGE_PAGE), y) +SOBJS += ../mv_orion/nBootstrap_LP.o +else +SOBJS += ../mv_orion/nBootstrap.o +endif +endif + + +OBJS = $(COMMON_OBJS) $(OSSERVICES_OBJS) $(HAL_OBJS) $(SOC_OBJS) $(BOARD_OBJS) $(USP_OBJS) + +LIB = lib$(BOARD).a + +all: $(LIB) + +$(LIB): .depend $(SOBJS) $(OBJS) + $(AR) crv $@ $(SOBJS) $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) $(USB_OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) $(USB_OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### + diff --git a/board/mv_feroceon/config/config.mk b/board/mv_feroceon/config/config.mk new file mode 100644 index 0000000..695d9aa --- /dev/null +++ b/board/mv_feroceon/config/config.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x00f10000 +# + +TEXT_BASE = 0x00200000 diff --git a/board/mv_feroceon/config/config_16mb.mk b/board/mv_feroceon/config/config_16mb.mk new file mode 100644 index 0000000..9452ff9 --- /dev/null +++ b/board/mv_feroceon/config/config_16mb.mk @@ -0,0 +1,4 @@ +# +# image should be loaded at 0x00c00000 +# +TEXT_BASE = 0x00c10000 diff --git a/board/mv_feroceon/config/config_def.mk b/board/mv_feroceon/config/config_def.mk new file mode 100644 index 0000000..695d9aa --- /dev/null +++ b/board/mv_feroceon/config/config_def.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x00f10000 +# + +TEXT_BASE = 0x00200000 diff --git a/board/mv_feroceon/config/config_nand.mk b/board/mv_feroceon/config/config_nand.mk new file mode 100644 index 0000000..c16140f --- /dev/null +++ b/board/mv_feroceon/config/config_nand.mk @@ -0,0 +1,15 @@ + +BOOT_TEXT_BASE = 0x00020000 + +NAND_LDSCRIPT = ./board/$(BOARDDIR)/u-boot-nand.lds + +NAND_LDFLAGS += -Bdynamic -T $(NAND_LDSCRIPT) -Ttext $(BOOT_TEXT_BASE) $(PLATFORM_LDFLAGS) + + +ifeq ($(NAND_LARGE_PAGE), y) +NAND_OBJS = ./board/mv_feroceon/USP/nBootstrap_LP.o +else +NAND_OBJS = ./board/mv_feroceon/USP/nBootstrap.o +endif + +NAND_OBJS += ./board/mv_feroceon/USP/nBootloader.o diff --git a/board/mv_feroceon/config/config_prpmc.mk b/board/mv_feroceon/config/config_prpmc.mk new file mode 100644 index 0000000..ac0295c --- /dev/null +++ b/board/mv_feroceon/config/config_prpmc.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x02f00000 +# + +TEXT_BASE = 0x02f10000 diff --git a/board/mv_feroceon/config/mvRules.mk b/board/mv_feroceon/config/mvRules.mk new file mode 100644 index 0000000..8efe975 --- /dev/null +++ b/board/mv_feroceon/config/mvRules.mk @@ -0,0 +1,77 @@ +# This flags will be used only by the Marvell arch files compilation. +include $(TOPDIR)/config.mk +include $(TOPDIR)/include/config.mk + + +# General definitions +CPU_ARCH = ARM +CHIP = orion +VENDOR = Marvell +ENDIAN = LE +LD_ENDIAN = -EL + +ifeq ($(BIG_ENDIAN),y) +ENDIAN = BE +LD_ENDIAN = -EB +endif + + +# Main directory structure +SRC_PATH = $(TOPDIR)/board/mv_feroceon +HAL_DIR = $(SRC_PATH)/mv_hal +COMMON_DIR = $(SRC_PATH)/common +USP_DIR = $(SRC_PATH)/USP +SOC_DIR = $(SRC_PATH)/mv_$(CHIP) +SYS_DIR = $(SRC_PATH)/mv_$(CHIP)/$(CHIP)_sys +ORION_FAM_DIR = $(SOC_DIR)/$(CHIP)_family +SOC_ENV_DIR = $(ORION_FAM_DIR)/ctrlEnv +SOC_SYS_DIR = $(ORION_FAM_DIR)/ctrlEnv/sys +SOC_CPU_DIR = $(ORION_FAM_DIR)/cpu +SOC_DEVICE_DIR = $(ORION_FAM_DIR)/device +BOARD_ENV_DIR = $(ORION_FAM_DIR)/boardEnv + +# HAL components +HAL_DRAM_DIR = $(HAL_DIR)/ddr1_2 +HAL_ETHPHY_DIR = $(HAL_DIR)/eth-phy +HAL_ETH_SWITCH_DIR = $(HAL_DIR)/ethswitch +HAL_FLASH_DIR = $(HAL_DIR)/norflash +HAL_PCI_DIR = $(HAL_DIR)/pci +HAL_PCIIF_DIR = $(HAL_DIR)/pci-if +HAL_RTC_DIR = $(HAL_DIR)/rtc/ext_rtc +HAL_SFLASH_DIR = $(HAL_DIR)/sflash +HAL_SATA_CORE_DIR = $(HAL_DIR)/sata/CoreDriver/ +HAL_CNTMR_DIR = $(HAL_DIR)/cntmr +HAL_GPP_DIR = $(HAL_DIR)/gpp +HAL_IDMA_DIR = $(HAL_DIR)/idma +HAL_PEX_DIR = $(HAL_DIR)/pex +HAL_TWSI_DIR = $(HAL_DIR)/twsi +HAL_ETH_DIR = $(HAL_DIR)/eth +HAL_ETH_GBE_DIR = $(HAL_DIR)/eth/gbe +HAL_UART_DIR = $(HAL_DIR)/uart +HAL_XOR_DIR = $(HAL_DIR)/xor +HAL_USB_DIR = $(HAL_DIR)/usb +HAL_SATA_DIR = $(HAL_DIR)/sata +HAL_MFLASH_DIR = $(HAL_DIR)/mflash +HAL_SPI_DIR = $(HAL_DIR)/spi + +# OS services +OSSERVICES_DIR = $(SRC_PATH)/uboot_oss + +# Internal definitions +MV_DEFINE = -DMV_UBOOT -DMV_CPU_$(ENDIAN) -DMV_$(CPU_ARCH) + +# Internal include path +HAL_PATH = -I$(HAL_DIR) -I$(HAL_SATA_CORE_DIR) +COMMON_PATH = -I$(COMMON_DIR) +OSSERVICES_PATH = -I$(OSSERVICES_DIR) +USP_PATH = -I$(USP_DIR) +SOC_PATH = -I$(ORION_FAM_DIR) -I$(SOC_DIR) -I$(SOC_ENV_DIR) -I$(SOC_SYS_DIR) -I$(SOC_CPU_DIR) -I$(SOC_DEVICE_DIR) +BOARD_PATH = -I$(BOARD_ENV_DIR) +SYS_PATH = -I$(SYS_DIR) + +CFLAGS += $(MV_DEFINE) $(OSSERVICES_PATH) $(HAL_PATH) $(COMMON_PATH) \ + $(USP_PATH) $(SOC_PATH) $(BOARD_PATH) $(SYS_PATH) + +AFLAGS += $(MV_DEFINE) $(OSSERVICES_PATH) $(HAL_PATH) $(COMMON_PATH) \ + $(USP_PATH) $(SOC_PATH) $(BOARD_PATH) $(SYS_PATH) + diff --git a/board/mv_feroceon/config/u-boot-nand.lds b/board/mv_feroceon/config/u-boot-nand.lds new file mode 100644 index 0000000..bd515d5 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-nand.lds @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : { *(.text) } + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + __u_boot_cmd_end = .; + + . = ALIGN(4); + _bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot-sec128k-tiny.lds b/board/mv_feroceon/config/u-boot-sec128k-tiny.lds new file mode 100644 index 0000000..9df76fa --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec128k-tiny.lds @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x20000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = _start + 0x30000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot-sec128k.lds b/board/mv_feroceon/config/u-boot-sec128k.lds new file mode 100644 index 0000000..3e8ec79 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec128k.lds @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x20000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x70000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot-sec256k.lds b/board/mv_feroceon/config/u-boot-sec256k.lds new file mode 100644 index 0000000..203ff14 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec256k.lds @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x40000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x70000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot-sec4k-header-tiny.lds b/board/mv_feroceon/config/u-boot-sec4k-header-tiny.lds new file mode 100644 index 0000000..fc85653 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec4k-header-tiny.lds @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x3ec00; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = _start + 0x3ee00; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot-sec4k-tiny.lds b/board/mv_feroceon/config/u-boot-sec4k-tiny.lds new file mode 100644 index 0000000..988fbd9 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec4k-tiny.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = _start + 0x30000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x3c000; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot-sec4k.lds b/board/mv_feroceon/config/u-boot-sec4k.lds new file mode 100644 index 0000000..47712f8 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec4k.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x70000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot-sec64k-header-nand.lds b/board/mv_feroceon/config/u-boot-sec64k-header-nand.lds new file mode 100644 index 0000000..f292c75 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec64k-header-nand.lds @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7DC00; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = _start + 0x7DE00; + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mv_feroceon/config/u-boot-sec64k-header.lds b/board/mv_feroceon/config/u-boot-sec64k-header.lds new file mode 100644 index 0000000..3685db3 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec64k-header.lds @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = _start + 0x6FE00; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + + . = _start + 0x7DE00; + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mv_feroceon/config/u-boot-sec64k-tiny.lds b/board/mv_feroceon/config/u-boot-sec64k-tiny.lds new file mode 100644 index 0000000..d3bece6 --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec64k-tiny.lds @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x10000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = _start + 0x30000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mv_feroceon/config/u-boot-sec64k.lds b/board/mv_feroceon/config/u-boot-sec64k.lds new file mode 100644 index 0000000..353b77d --- /dev/null +++ b/board/mv_feroceon/config/u-boot-sec64k.lds @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x10000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x60000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = _start + 0x6FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config/u-boot.lds b/board/mv_feroceon/config/u-boot.lds new file mode 100644 index 0000000..f292c75 --- /dev/null +++ b/board/mv_feroceon/config/u-boot.lds @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7DC00; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = _start + 0x7DE00; + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mv_feroceon/config/u-boot_16mb.lds b/board/mv_feroceon/config/u-boot_16mb.lds new file mode 100644 index 0000000..5ce504e --- /dev/null +++ b/board/mv_feroceon/config/u-boot_16mb.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .dummy 0x00c00000 : { board/mv_feroceon/USP/jump.o (.dummy) } + . = 0x0c10000; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + .reset_vector_sect 0x00c70000 : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_dd/Makefile b/board/mv_feroceon/config_dd/Makefile new file mode 100644 index 0000000..493a6ee --- /dev/null +++ b/board/mv_feroceon/config_dd/Makefile @@ -0,0 +1,77 @@ +include mvRules.mk + + +# Objects list + +COMMON_OBJS = $(COMMON_DIR)/mvCommon.o + +OSSERVICES_OBJS = $(OSSERVICES_DIR)/mvOs.o $(OSSERVICES_DIR)/mvOsSata.o + +BOARD_OBJS = $(BOARD_ENV_DIR)/mvBoardEnvLib.o $(BOARD_ENV_DIR)/mvBoardEnvSpec.o + +HAL_OBJS = $(HAL_FLASH_DIR)/mvFlash.o $(HAL_FLASH_DIR)/mvAmdFlash.o $(HAL_FLASH_DIR)/mvIntelFlash.o \ + $(HAL_FLASH_DIR)/mvFlashCom.o $(HAL_SPD_DIR)/mvSpd.o $(HAL_DRAM_DIR)/mvDramIf.o \ + $(HAL_SATA_CORE_DIR)/mvSata.o $(HAL_SATA_CORE_DIR)/mvStorageDev.o \ + $(HAL_SATA_CORE_DIR)/mvLog.o $(HAL_SFLASH_DIR)/mvSFlash.o \ + $(HAL_ETHPHY_DIR)/mvEthPhy.o $(HAL_RTC_DIR)/mvDS133x.o \ + $(HAL_CNTMR_DIR)/mvCntmr.o $(HAL_TWSI_DIR)/mvTwsi.o \ + $(HAL_UART_DIR)/mvUart.o $(HAL_GPP_DIR)/mvGpp.o \ + $(HAL_MFLASH_DIR)/mvMFlash.o $(HAL_SPI_DIR)/mvSpi.o \ + $(HAL_MFLASH_DIR)/mvSMFlash.o $(HAL_MFLASH_DIR)/mvPMFlash.o \ + $(HAL_SPI_DIR)/mvSpiCmnd.o $(HAL_USB_DIR)/mvUsb.o \ + $(HAL_IDMA_DIR)/mvIdma.o $(HAL_XOR_DIR)/mvXor.o \ + $(HAL_ETH_GBE_DIR)/mvEth.o $(HAL_PCIIF_DIR)/mvPciIf.o \ + $(HAL_ETH_GBE_DIR)/mvEthDebug.o $(HAL_PEX_DIR)/mvPex.o \ + $(HAL_CESA_DIR)/mvMD5.o + + +SOC_OBJS = $(SOC_DIR)/mv_cmd.o $(SOC_DIR)/mv_dram.o $(SOC_DIR)/mv_main.o \ + $(SOC_DIR)/mv_service.o $(SOC_ENV_DIR)/mvCtrlEnvLib.o \ + $(SOC_ENV_DIR)/mvCtrlEnvAddrDec.o $(SOC_SYS_DIR)/mvAhbToMbus.o \ + $(SOC_SYS_DIR)/mvCpuIf.o $(SOC_SYS_DIR)/mvSysXor.o $(SOC_SYS_DIR)/mvSysDram.o\ + $(SOC_SYS_DIR)/mvSysGbe.o $(SOC_SYS_DIR)/mvSysIdma.o \ + $(SOC_SYS_DIR)/mvSysPex.o $(SOC_SYS_DIR)/mvSysSata.o $(SOC_SYS_DIR)/mvSysUsb.o \ + $(SOC_DEVICE_DIR)/mvDevice.o $(SOC_CPU_DIR)/mvCpu.o $(HAL_PCIIF_DIR)/pci_util/mvPciUtils.o + +USP_OBJS = $(USP_DIR)/mv_flash.o $(USP_DIR)/mv_serial.o \ + $(USP_DIR)/mv_pageTable.o $(USP_DIR)/mv_rtc.o $(USP_DIR)/mv_mon_init.o \ + $(USP_DIR)/mv_pci.o $(USP_DIR)/mv_nand.o \ + $(USP_DIR)/mv_ide.o $(USP_DIR)/mv_egiga.o \ + $(USP_DIR)/mv_fs.o $(USP_DIR)/mv_loadnet.o $(USP_DIR)/mv_protectionUnit.o \ + $(USP_DIR)/mv_i2c.o $(USP_DIR)/mv_ext2_boot.o \ + $(USP_DIR)/ethSwitch/mv_switch.o + +ifeq ($(NAND_BOOT), y) +USP_OBJS += $(USP_DIR)/nBootloader.o +endif + +SOBJS = $(USP_DIR)/jump.o \ + $(SOC_DIR)/platform.o \ + $(HAL_DRAM_DIR)/mvDramIfBasicInit.o \ + $(HAL_DRAM_DIR)/mvDramIfConfig.o \ + $(HAL_TWSI_DIR)/mvTwsiEeprom.o +# $(SOC_SYS_DIR)/mvCpuIfInit.o + +ifeq ($(NAND_BOOT), y) +SOBJS += $(USP_DIR)/nBootstrap.o +endif + + +OBJS = $(COMMON_OBJS) $(OSSERVICES_OBJS) $(HAL_OBJS) $(SOC_OBJS) $(BOARD_OBJS) $(USP_OBJS) + +LIB = lib$(BOARD).a + +all: $(LIB) + +$(LIB): .depend $(SOBJS) $(OBJS) + $(AR) crv $@ $(SOBJS) $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) $(USB_OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) $(USB_OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### + diff --git a/board/mv_feroceon/config_dd/config.mk b/board/mv_feroceon/config_dd/config.mk new file mode 100644 index 0000000..1e65e79 --- /dev/null +++ b/board/mv_feroceon/config_dd/config.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x00f10000 +# + +TEXT_BASE = 0x00600000 diff --git a/board/mv_feroceon/config_dd/config_def.mk b/board/mv_feroceon/config_dd/config_def.mk new file mode 100644 index 0000000..1e65e79 --- /dev/null +++ b/board/mv_feroceon/config_dd/config_def.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x00f10000 +# + +TEXT_BASE = 0x00600000 diff --git a/board/mv_feroceon/config_dd/config_nand.mk b/board/mv_feroceon/config_dd/config_nand.mk new file mode 100644 index 0000000..45789bf --- /dev/null +++ b/board/mv_feroceon/config_dd/config_nand.mk @@ -0,0 +1,15 @@ + +BOOT_TEXT_BASE = 0x00020000 + +NAND_LDSCRIPT = ./board/$(BOARDDIR)/u-boot-nand.lds + +NAND_LDFLAGS += -Bdynamic -T $(NAND_LDSCRIPT) -Ttext $(BOOT_TEXT_BASE) $(PLATFORM_LDFLAGS) + + +ifeq ($(NAND_LARGE_PAGE), y) +NAND_OBJS = ./board/disco/USP/nBootstrap_LP.o +else +NAND_OBJS = ./board/disco/USP/nBootstrap.o +endif + +NAND_OBJS += ./board/disco/USP/nBootloader.o diff --git a/board/mv_feroceon/config_dd/mvRules.mk b/board/mv_feroceon/config_dd/mvRules.mk new file mode 100644 index 0000000..e7b43a8 --- /dev/null +++ b/board/mv_feroceon/config_dd/mvRules.mk @@ -0,0 +1,79 @@ +# This flags will be used only by the Marvell arch files compilation. +include $(TOPDIR)/config.mk +include $(TOPDIR)/include/config.mk + + +# General definitions +CPU_ARCH = ARM +CHIP = dd +VENDOR = Marvell +ENDIAN = LE +LD_ENDIAN = -EL + +ifeq ($(BIG_ENDIAN),y) +ENDIAN = BE +LD_ENDIAN = -EB +endif + + +# Main directory structure +SRC_PATH = $(TOPDIR)/board/mv_feroceon +HAL_DIR = $(SRC_PATH)/mv_hal +COMMON_DIR = $(SRC_PATH)/common +USP_DIR = $(SRC_PATH)/USP +SOC_DIR = $(SRC_PATH)/mv_$(CHIP) +ORION_FAM_DIR = $(SOC_DIR)/$(CHIP)_family +SOC_ENV_DIR = $(ORION_FAM_DIR)/ctrlEnv +SOC_SYS_DIR = $(ORION_FAM_DIR)/ctrlEnv/sys +SOC_CPU_DIR = $(ORION_FAM_DIR)/cpu +SOC_DEVICE_DIR = $(ORION_FAM_DIR)/device +BOARD_ENV_DIR = $(ORION_FAM_DIR)/boardEnv + +# HAL components +HAL_DRAM_DIR = $(HAL_DIR)/ddr2 +HAL_SPD_DIR = $(HAL_DRAM_DIR)/spd +HAL_ETHPHY_DIR = $(HAL_DIR)/eth-phy +HAL_FLASH_DIR = $(HAL_DIR)/norflash +HAL_PCI_DIR = $(HAL_DIR)/pci +HAL_PCIIF_DIR = $(HAL_DIR)/pci-if +HAL_RTC_DIR = $(HAL_DIR)/rtc/ext_rtc +HAL_SFLASH_DIR = $(HAL_DIR)/sflash +HAL_SATA_CORE_DIR = $(HAL_DIR)/sata/CoreDriver/ +HAL_CNTMR_DIR = $(HAL_DIR)/cntmr +HAL_GPP_DIR = $(HAL_DIR)/gpp +HAL_IDMA_DIR = $(HAL_DIR)/idma +HAL_PEX_DIR = $(HAL_DIR)/pex +HAL_TWSI_DIR = $(HAL_DIR)/twsi +HAL_TWSI_ARCH_DIR = $(HAL_TWSI_DIR)/Arch$(CPU_ARCH) +HAL_ETH_DIR = $(HAL_DIR)/eth +HAL_ETH_GBE_DIR = $(HAL_ETH_DIR)/gbe +HAL_UART_DIR = $(HAL_DIR)/uart +HAL_XOR_DIR = $(HAL_DIR)/xor +HAL_USB_DIR = $(HAL_DIR)/usb +HAL_SATA_DIR = $(HAL_DIR)/sata +HAL_MFLASH_DIR = $(HAL_DIR)/mflash +HAL_SPI_DIR = $(HAL_DIR)/spi +HAL_TS_DIR = $(HAL_DIR)/ts +HAL_AUDIO_DIR = $(HAL_DIR)/audio +HAL_CESA_DIR = $(HAL_DIR)/cesa + +# OS services +OSSERVICES_DIR = $(SRC_PATH)/uboot_oss + +# Internal definitions +MV_DEFINE = -DMV_UBOOT -DMV_CPU_$(ENDIAN) -DMV_$(CPU_ARCH) + +# Internal include path +HAL_PATH = -I$(HAL_DIR) -I$(HAL_SATA_CORE_DIR) +COMMON_PATH = -I$(COMMON_DIR) +OSSERVICES_PATH = -I$(OSSERVICES_DIR) +USP_PATH = -I$(USP_DIR) +SOC_PATH = -I$(ORION_FAM_DIR) -I$(SOC_DIR) -I$(SOC_ENV_DIR) -I$(SOC_SYS_DIR) -I$(SOC_CPU_DIR) -I$(SOC_DEVICE_DIR) +BOARD_PATH = -I$(BOARD_ENV_DIR) + +CFLAGS += $(MV_DEFINE) $(OSSERVICES_PATH) $(HAL_PATH) $(COMMON_PATH) \ + $(USP_PATH) $(SOC_PATH) $(BOARD_PATH) $(SYS_PATH) + +AFLAGS += $(MV_DEFINE) $(OSSERVICES_PATH) $(HAL_PATH) $(COMMON_PATH) \ + $(USP_PATH) $(SOC_PATH) $(BOARD_PATH) $(SYS_PATH) + diff --git a/board/mv_feroceon/config_dd/u-boot-nand.lds b/board/mv_feroceon/config_dd/u-boot-nand.lds new file mode 100644 index 0000000..bd515d5 --- /dev/null +++ b/board/mv_feroceon/config_dd/u-boot-nand.lds @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : { *(.text) } + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + __u_boot_cmd_end = .; + + . = ALIGN(4); + _bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_dd/u-boot-sec128k.lds b/board/mv_feroceon/config_dd/u-boot-sec128k.lds new file mode 100644 index 0000000..31ffdb7 --- /dev/null +++ b/board/mv_feroceon/config_dd/u-boot-sec128k.lds @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x20000; + .dummy : { board/disco/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x70000; + .reset_vector_sect : { board/disco/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_dd/u-boot.lds b/board/mv_feroceon/config_dd/u-boot.lds new file mode 100644 index 0000000..353b77d --- /dev/null +++ b/board/mv_feroceon/config_dd/u-boot.lds @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x10000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x60000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = _start + 0x6FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_dd/u-boot_def.lds b/board/mv_feroceon/config_dd/u-boot_def.lds new file mode 100644 index 0000000..353b77d --- /dev/null +++ b/board/mv_feroceon/config_dd/u-boot_def.lds @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x10000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x60000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = _start + 0x6FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/Makefile b/board/mv_feroceon/config_kw/Makefile new file mode 100644 index 0000000..4648704 --- /dev/null +++ b/board/mv_feroceon/config_kw/Makefile @@ -0,0 +1,77 @@ +include mvRules.mk + + +# Objects list + +COMMON_OBJS = $(COMMON_DIR)/mvCommon.o + +OSSERVICES_OBJS = $(OSSERVICES_DIR)/mvOs.o $(OSSERVICES_DIR)/mvOsSata.o + +BOARD_OBJS = $(BOARD_ENV_DIR)/mvBoardEnvLib.o $(BOARD_ENV_DIR)/mvBoardEnvSpec.o + +HAL_OBJS = $(HAL_FLASH_DIR)/mvFlash.o $(HAL_FLASH_DIR)/mvAmdFlash.o $(HAL_FLASH_DIR)/mvIntelFlash.o \ + $(HAL_FLASH_DIR)/mvFlashCom.o $(HAL_SPD_DIR)/mvSpd.o $(HAL_DRAM_DIR)/mvDramIf.o \ + $(HAL_SATA_CORE_DIR)/mvSata.o $(HAL_SATA_CORE_DIR)/mvStorageDev.o \ + $(HAL_SATA_CORE_DIR)/mvLog.o $(HAL_SFLASH_DIR)/mvSFlash.o \ + $(HAL_ETHPHY_DIR)/mvEthPhy.o $(HAL_RTC_DIR)/mvRtc.o \ + $(HAL_CNTMR_DIR)/mvCntmr.o $(HAL_TWSI_DIR)/mvTwsi.o \ + $(HAL_UART_DIR)/mvUart.o $(HAL_GPP_DIR)/mvGpp.o \ + $(HAL_SPI_DIR)/mvSpi.o $(HAL_SPI_DIR)/mvSpiCmnd.o $(HAL_USB_DIR)/mvUsb.o \ + $(HAL_XOR_DIR)/mvXor.o $(HAL_ETH_GBE_DIR)/mvEth.o $(HAL_PCIIF_DIR)/mvPciIf.o \ + $(HAL_ETH_GBE_DIR)/mvEthDebug.o $(HAL_PEX_DIR)/mvPex.o $(HAL_AUDIO_DIR)/mvAudio.o \ + $(HAL_TS_DIR)/mvTsu.o $(HAL_CESA_DIR)/mvMD5.o $(HAL_ETH_SWITCH_DIR)/mvSwitch.o + + +SOC_OBJS = $(SOC_DIR)/mv_cmd.o $(SOC_DIR)/mv_dram.o $(SOC_DIR)/mv_main.o \ + $(SOC_ENV_DIR)/mvCtrlEnvLib.o \ + $(SOC_ENV_DIR)/mvCtrlEnvAddrDec.o $(SOC_SYS_DIR)/mvAhbToMbus.o \ + $(SOC_SYS_DIR)/mvCpuIf.o $(SOC_SYS_DIR)/mvSysXor.o $(SOC_SYS_DIR)/mvSysDram.o \ + $(SOC_SYS_DIR)/mvSysGbe.o $(SOC_SYS_DIR)/mvSysAudio.o $(SOC_SYS_DIR)/mvSysTs.o\ + $(SOC_SYS_DIR)/mvSysPex.o $(SOC_SYS_DIR)/mvSysSata.o $(SOC_SYS_DIR)/mvSysUsb.o \ + $(SOC_CPU_DIR)/mvCpu.o $(SOC_DEVICE_DIR)/mvDevice.o + +ifneq ($(MV_TINY_IMAGE), y) +SOC_OBJS += $(HAL_PCIIF_DIR)/pci_util/mvPciUtils.o +endif + +USP_OBJS = $(USP_DIR)/mv_flash.o $(USP_DIR)/mv_serial.o \ + $(USP_DIR)/mv_pageTable.o $(USP_DIR)/mv_rtc.o $(USP_DIR)/mv_mon_init.o \ + $(USP_DIR)/mv_pci.o $(USP_DIR)/mv_nand.o \ + $(USP_DIR)/mv_ide.o $(USP_DIR)/mv_egiga.o \ + $(USP_DIR)/mv_fs.o $(USP_DIR)/mv_loadnet.o $(USP_DIR)/mv_protectionUnit.o \ + $(USP_DIR)/mv_i2c.o $(USP_DIR)/mv_ext2_boot.o + +ifeq ($(NAND_BOOT), y) +USP_OBJS += $(USP_DIR)/nBootloader.o +endif + +SOBJS = $(USP_DIR)/jump.o \ + $(SOC_DIR)/platform.o \ + $(HAL_DRAM_DIR)/mvDramIfBasicInit.o \ + $(HAL_DRAM_DIR)/mvDramIfConfig.o \ + $(HAL_TWSI_DIR)/mvTwsiEeprom.o \ + $(SOC_SYS_DIR)/mvCpuIfInit.o + +ifeq ($(NAND_BOOT), y) +SOBJS += ../mv_kw/nBootstrap.o +endif + + +OBJS = $(COMMON_OBJS) $(OSSERVICES_OBJS) $(HAL_OBJS) $(SOC_OBJS) $(BOARD_OBJS) $(USP_OBJS) + +LIB = lib$(BOARD).a + +all: $(LIB) + +$(LIB): .depend $(SOBJS) $(OBJS) + $(AR) crv $@ $(SOBJS) $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) $(USB_OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) $(USB_OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### + diff --git a/board/mv_feroceon/config_kw/config.mk b/board/mv_feroceon/config_kw/config.mk new file mode 100644 index 0000000..1af1815 --- /dev/null +++ b/board/mv_feroceon/config_kw/config.mk @@ -0,0 +1,13 @@ +# +# image should be loaded at 0x00600000 +# + +TEXT_BASE = 0x00600000 + +BOOT_TEXT_BASE = 0x00020000 + +NAND_LDSCRIPT = ./board/$(BOARDDIR)/u-boot-nand.lds + +NAND_LDFLAGS += -Bdynamic -T $(NAND_LDSCRIPT) -Ttext $(BOOT_TEXT_BASE) $(PLATFORM_LDFLAGS) +NAND_OBJS = ./board/mv_feroceon/mv_kw/nBootstrap.o +NAND_OBJS += ./board/mv_feroceon/USP/nBootloader.o diff --git a/board/mv_feroceon/config_kw/config_16mb.mk b/board/mv_feroceon/config_kw/config_16mb.mk new file mode 100644 index 0000000..9452ff9 --- /dev/null +++ b/board/mv_feroceon/config_kw/config_16mb.mk @@ -0,0 +1,4 @@ +# +# image should be loaded at 0x00c00000 +# +TEXT_BASE = 0x00c10000 diff --git a/board/mv_feroceon/config_kw/config_def.mk b/board/mv_feroceon/config_kw/config_def.mk new file mode 100644 index 0000000..cca0183 --- /dev/null +++ b/board/mv_feroceon/config_kw/config_def.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x00600000 +# + +TEXT_BASE = 0x00600000 diff --git a/board/mv_feroceon/config_kw/config_nand.mk b/board/mv_feroceon/config_kw/config_nand.mk new file mode 100644 index 0000000..93c4799 --- /dev/null +++ b/board/mv_feroceon/config_kw/config_nand.mk @@ -0,0 +1,8 @@ + +BOOT_TEXT_BASE = 0x00020000 + +NAND_LDSCRIPT = ./board/$(BOARDDIR)/u-boot-nand.lds + +NAND_LDFLAGS += -Bdynamic -T $(NAND_LDSCRIPT) -Ttext $(BOOT_TEXT_BASE) $(PLATFORM_LDFLAGS) +NAND_OBJS = ./board/mv_feroceon/mv_kw/nBootstrap.o +NAND_OBJS += ./board/mv_feroceon/USP/nBootloader.o diff --git a/board/mv_feroceon/config_kw/config_prpmc.mk b/board/mv_feroceon/config_kw/config_prpmc.mk new file mode 100644 index 0000000..ac0295c --- /dev/null +++ b/board/mv_feroceon/config_kw/config_prpmc.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x02f00000 +# + +TEXT_BASE = 0x02f10000 diff --git a/board/mv_feroceon/config_kw/mvRules.mk b/board/mv_feroceon/config_kw/mvRules.mk new file mode 100644 index 0000000..c053e50 --- /dev/null +++ b/board/mv_feroceon/config_kw/mvRules.mk @@ -0,0 +1,80 @@ +# This flags will be used only by the Marvell arch files compilation. +include $(TOPDIR)/config.mk +include $(TOPDIR)/include/config.mk + + +# General definitions +CPU_ARCH = ARM +CHIP = kw +VENDOR = Marvell +ENDIAN = LE +LD_ENDIAN = -EL + +ifeq ($(BIG_ENDIAN),y) +ENDIAN = BE +LD_ENDIAN = -EB +endif + + +# Main directory structure +SRC_PATH = $(TOPDIR)/board/mv_feroceon +HAL_DIR = $(SRC_PATH)/mv_hal +COMMON_DIR = $(SRC_PATH)/common +USP_DIR = $(SRC_PATH)/USP +SOC_DIR = $(SRC_PATH)/mv_$(CHIP) +ORION_FAM_DIR = $(SOC_DIR)/$(CHIP)_family +SOC_ENV_DIR = $(ORION_FAM_DIR)/ctrlEnv +SOC_SYS_DIR = $(ORION_FAM_DIR)/ctrlEnv/sys +SOC_CPU_DIR = $(ORION_FAM_DIR)/cpu +SOC_DEVICE_DIR = $(ORION_FAM_DIR)/device +BOARD_ENV_DIR = $(ORION_FAM_DIR)/boardEnv + +# HAL components +HAL_DRAM_DIR = $(HAL_DIR)/ddr2 +HAL_SPD_DIR = $(HAL_DRAM_DIR)/spd +HAL_ETHPHY_DIR = $(HAL_DIR)/eth-phy +HAL_ETH_SWITCH_DIR = $(HAL_DIR)/ethswitch +HAL_FLASH_DIR = $(HAL_DIR)/norflash +HAL_PCI_DIR = $(HAL_DIR)/pci +HAL_PCIIF_DIR = $(HAL_DIR)/pci-if +HAL_RTC_DIR = $(HAL_DIR)/rtc/integ_rtc +HAL_SFLASH_DIR = $(HAL_DIR)/sflash +HAL_SATA_CORE_DIR = $(HAL_DIR)/sata/CoreDriver/ +HAL_CNTMR_DIR = $(HAL_DIR)/cntmr +HAL_GPP_DIR = $(HAL_DIR)/gpp +HAL_IDMA_DIR = $(HAL_DIR)/idma +HAL_PEX_DIR = $(HAL_DIR)/pex +HAL_TWSI_DIR = $(HAL_DIR)/twsi +HAL_TWSI_ARCH_DIR = $(HAL_TWSI_DIR)/Arch$(CPU_ARCH) +HAL_ETH_DIR = $(HAL_DIR)/eth +HAL_ETH_GBE_DIR = $(HAL_ETH_DIR)/gbe +HAL_UART_DIR = $(HAL_DIR)/uart +HAL_XOR_DIR = $(HAL_DIR)/xor +HAL_USB_DIR = $(HAL_DIR)/usb +HAL_SATA_DIR = $(HAL_DIR)/sata +HAL_MFLASH_DIR = $(HAL_DIR)/mflash +HAL_SPI_DIR = $(HAL_DIR)/spi +HAL_TS_DIR = $(HAL_DIR)/ts +HAL_AUDIO_DIR = $(HAL_DIR)/audio +HAL_CESA_DIR = $(HAL_DIR)/cesa + +# OS services +OSSERVICES_DIR = $(SRC_PATH)/uboot_oss + +# Internal definitions +MV_DEFINE = -DMV_UBOOT -DMV_CPU_$(ENDIAN) -DMV_$(CPU_ARCH) + +# Internal include path +HAL_PATH = -I$(HAL_DIR) -I$(HAL_SATA_CORE_DIR) +COMMON_PATH = -I$(COMMON_DIR) +OSSERVICES_PATH = -I$(OSSERVICES_DIR) +USP_PATH = -I$(USP_DIR) +SOC_PATH = -I$(ORION_FAM_DIR) -I$(SOC_DIR) -I$(SOC_ENV_DIR) -I$(SOC_SYS_DIR) -I$(SOC_CPU_DIR) -I$(SOC_DEVICE_DIR) +BOARD_PATH = -I$(BOARD_ENV_DIR) + +CFLAGS += $(MV_DEFINE) $(OSSERVICES_PATH) $(HAL_PATH) $(COMMON_PATH) \ + $(USP_PATH) $(SOC_PATH) $(BOARD_PATH) $(SYS_PATH) + +AFLAGS += $(MV_DEFINE) $(OSSERVICES_PATH) $(HAL_PATH) $(COMMON_PATH) \ + $(USP_PATH) $(SOC_PATH) $(BOARD_PATH) $(SYS_PATH) + diff --git a/board/mv_feroceon/config_kw/u-boot-nand.lds b/board/mv_feroceon/config_kw/u-boot-nand.lds new file mode 100644 index 0000000..bd515d5 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-nand.lds @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : { *(.text) } + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + __u_boot_cmd_end = .; + + . = ALIGN(4); + _bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec128k-tiny.lds b/board/mv_feroceon/config_kw/u-boot-sec128k-tiny.lds new file mode 100644 index 0000000..9df76fa --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec128k-tiny.lds @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x20000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = _start + 0x30000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec128k.lds b/board/mv_feroceon/config_kw/u-boot-sec128k.lds new file mode 100644 index 0000000..548b2a4 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec128k.lds @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x70000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec256k.lds b/board/mv_feroceon/config_kw/u-boot-sec256k.lds new file mode 100644 index 0000000..548b2a4 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec256k.lds @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x70000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec4k-header-tiny.lds b/board/mv_feroceon/config_kw/u-boot-sec4k-header-tiny.lds new file mode 100644 index 0000000..fc85653 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec4k-header-tiny.lds @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x3ec00; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = _start + 0x3ee00; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec4k-tiny.lds b/board/mv_feroceon/config_kw/u-boot-sec4k-tiny.lds new file mode 100644 index 0000000..988fbd9 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec4k-tiny.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = _start + 0x30000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x3c000; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec4k.lds b/board/mv_feroceon/config_kw/u-boot-sec4k.lds new file mode 100644 index 0000000..47712f8 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec4k.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x70000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec64k-header-nand.lds b/board/mv_feroceon/config_kw/u-boot-sec64k-header-nand.lds new file mode 100644 index 0000000..f292c75 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec64k-header-nand.lds @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7DC00; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = _start + 0x7DE00; + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec64k-header.lds b/board/mv_feroceon/config_kw/u-boot-sec64k-header.lds new file mode 100644 index 0000000..3685db3 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec64k-header.lds @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = _start + 0x6FE00; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + + . = _start + 0x7DE00; + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec64k-tiny.lds b/board/mv_feroceon/config_kw/u-boot-sec64k-tiny.lds new file mode 100644 index 0000000..d3bece6 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec64k-tiny.lds @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start - 0x10000; + .dummy : { board/mv_feroceon/USP/jump.o (.dummy) } + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = _start + 0x30000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/mv_feroceon/config_kw/u-boot-sec64k.lds b/board/mv_feroceon/config_kw/u-boot-sec64k.lds new file mode 100644 index 0000000..f8ccfd0 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot-sec64k.lds @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x60000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = _start + 0x6FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot.lds b/board/mv_feroceon/config_kw/u-boot.lds new file mode 100644 index 0000000..548b2a4 --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot.lds @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = _start; + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + . = ALIGN(4); + .got : { *(.got) } + + + . = _start + 0x70000; + .reset_vector_sect : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = _start + 0x7FFF0; + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/config_kw/u-boot_16mb.lds b/board/mv_feroceon/config_kw/u-boot_16mb.lds new file mode 100644 index 0000000..5ce504e --- /dev/null +++ b/board/mv_feroceon/config_kw/u-boot_16mb.lds @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .dummy 0x00c00000 : { board/mv_feroceon/USP/jump.o (.dummy) } + . = 0x0c10000; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + .reset_vector_sect 0x00c70000 : { board/mv_feroceon/USP/jump.o (.reset_vector_sect) } + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; + +} diff --git a/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.c b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.c new file mode 100644 index 0000000..3cef3d7 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.c @@ -0,0 +1,1420 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "boardEnv/mvBoardEnvLib.h" +#include "boardEnv/mvBoardEnvSpec.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "cntmr/mvCntmr.h" +#include "device/mvDevice.h" +#include "gpp/mvGpp.h" +#include "twsi/mvTwsi.h" +#include "cpu/mvCpu.h" +#include "device/mvDeviceRegs.h" +#include "eth-phy/mvEthPhy.h" +/* defines */ +#ifdef DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* defines */ +#define REF_TIMER 0 /* reference timer number */ + +/* local */ +MV_BOOL mvBoardIsBootFromNand(MV_VOID); +static MV_DEV_CS_INFO* boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); + +/* Locals */ +MV_U32 refClkDevInit(MV_VOID); +MV_VOID refClkDevRelease(MV_U32 prevState); +MV_U32 refClkDevBitRateGet(MV_VOID); +MV_VOID refClkDevStart(MV_U32 refClkDevBits); +MV_U32 sysClkRate = -1; +MV_U32 tClkRate = -1; +MV_U32 gBoardId = 0; + + +MV_DEV_CS_INFO dbBoardCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ + { + {DEVICE_CS0, N_A, BOARD_DEV_NOR_FLASH, 32}, + {DEVICE_CS1, N_A, BOARD_DEV_SEVEN_SEG, 4}, + {DEVICE_CS2, N_A, BOARD_DEV_NAND_FLASH, 8}, + {DEV_BOOCS, N_A, BOARD_DEV_NOR_FLASH, 8}, +#if !defined (MV78XX0_Z0) + {SPI_CS, N_A, BOARD_DEV_SPI_FLASH, 8}, +#endif + {MAX_TARGETS, 0, 0, 0} + }; + +MV_DEV_CS_INFO dbBoardCsBootFromSpiInfo[] = + /*{deviceCS, params, devType, devWidth}*/ + { + {DEVICE_CS0, N_A, BOARD_DEV_NOR_FLASH, 32}, + {DEVICE_CS1, N_A, BOARD_DEV_SEVEN_SEG, 4}, + {DEVICE_CS2, N_A, BOARD_DEV_NAND_FLASH, 8}, +#if !defined (MV78XX0_Z0) + {SPI_CS, N_A, BOARD_DEV_SPI_FLASH, 8}, +#endif + {MAX_TARGETS, 0, 0, 0} + }; + +MV_DEV_CS_INFO dbBoardCsInfoBootFromNand[] = + /*{deviceCS, params, devType, devWidth}*/ + { + {DEVICE_CS0, N_A, BOARD_DEV_NAND_FLASH, 8}, + {MAX_TARGETS, 0, 0, 0} + }; + +static MV_DEV_CS_INFO* boardGetCsArray(MV_VOID) +{ + if (MV_TRUE == mvBoardIsBootFromNand()) + return dbBoardCsInfoBootFromNand; + else + if (MV_TRUE == mvBoardIsBootFromSpi()) + return dbBoardCsBootFromSpiInfo; + else + return dbBoardCsInfo; + +} + +/******************************************************************************* +* mvBoardEnvInit - Init board +* +* DESCRIPTION: +* In this function the board environment take care of device bank +* initialization. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardEnvInit(MV_VOID) +{ + MV_U32 devNum, gpioLedMask; + MV_U32 devBankParam = -1; + MV_U32 devBankParamWr = -1; + MV_U32 boardId = mvBoardIdGet(); + if (UNKNOWN_BOARD_ID == boardId) + { + mvOsPrintf("mvBoardEnvInit:Board unknown.\n"); + return; + } + for (devNum = DEV_CS0; devNum <= DEV_CS3; devNum++) + { + switch(devNum) + { + case (DEV_CS0): + devBankParam = DEVICE_CS0_PARAM; + devBankParamWr = DEVICE_CS0_PARAM_WR; + break; + case (DEV_CS1): + devBankParam = DEVICE_CS1_PARAM; + devBankParamWr = DEVICE_CS1_PARAM_WR; + break; + case (DEV_CS2): + devBankParam = DEVICE_CS2_PARAM; + devBankParamWr = DEVICE_CS2_PARAM_WR; + break; + case (DEV_CS3): + devBankParam = DEVICE_CS3_PARAM; + devBankParamWr = DEVICE_CS3_PARAM_WR; + break; + default: + devBankParam = -1; + devBankParamWr = -1; + } + + if(devBankParam != -1) + MV_REG_WRITE(DEV_BANK_PARAM_REG(devNum), devBankParam); + if(devBankParamWr != -1) + MV_REG_WRITE(DEV_BANK_PARAM_REG_WR(devNum), devBankParamWr); + devBankParam = -1; + devBankParamWr = -1; + } + + /* Check if boot from NAND - do nothing */ + if (!((MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & MSAR_BOOTDEV_MASK) == MSAR_BOOTDEV_DCE_NAND) || + ((MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & MSAR_BOOTDEV_MASK) == MSAR_BOOTDEV_CE_NAND)) + /* Assign NAND CS and care in control reg */ + mvDevNandDevCsSet(MV_NAND_CS, MV_NAND_CARE); + + /* Set GPP value before sett OE to prevent reset */ + switch (boardId) { + case DB_78XX0_ID: + MV_REG_WRITE(GPP_DATA_OUT_SET_REG, (1 << DB_78XX0_SW_RESET)); + break; + case RD_78XX0_AMC_ID: + MV_REG_WRITE(GPP_DATA_OUT_CLEAR_REG, (1 << RD_AMC_SW_RESET)); + break; + case RD_78XX0_MASA_ID: + MV_REG_WRITE(GPP_DATA_OUT_SET_REG, (1 << RD_MASA_DEBUG_LED_GPP_PIN(1))); + break; + case RD_78XX0_H3C_ID: + MV_REG_WRITE(GPP_DATA_OUT_SET_REG, (1 << RD_H3C_SW_RESET_SELECT)); + break; + default: + break; + } + /* Debug Led operates via GPP. Initialize GPP */ + gpioLedMask = mvBoardDbgLedGpioMaskGet(); + + switch(boardId) { + case DB_78XX0_ID: + gpioLedMask |= 1 << DB_78XX0_SW_RESET; +#ifdef MV_INCLUDE_MODEM_ON_TTYS1 + gpioLedMask |= 1 << DB_78XX0_SERIAL_DTR; /* set DTR as output*/ +#endif + break; + case RD_78XX0_AMC_ID: + gpioLedMask |= RD_AMC_GPIO_OUTPUT_EN; + break; + case RD_78XX0_MASA_ID: + gpioLedMask |= RD_MASA_GPIO_OUTPUT_EN; /* set DTR as output*/ + break; + case RD_78XX0_H3C_ID: + gpioLedMask |= RD_H3C_GPIO_OUTPUT_EN; /* set DTR as output*/ + break; + default: + break; + } + + /* Set the GPP interrupt pins to output. */ + mvGppTypeSet (0, gpioLedMask, (gpioLedMask & MV_GPP_OUT)); +} + +/******************************************************************************* +* mvBoardIsBootFromNand - +* +* DESCRIPTION: +* This routine returns MV_TRUE if the board is configure to boot from nand +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - boot from nand. +* MV_FALSE - other. +* +*******************************************************************************/ +MV_BOOL mvBoardIsBootFromNand(MV_VOID) +{ + /* Check if boot from NAND - do nothing */ + if (((MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & MSAR_BOOTDEV_MASK) == MSAR_BOOTDEV_DCE_NAND) || + ((MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & MSAR_BOOTDEV_MASK) == MSAR_BOOTDEV_CE_NAND)) + { + return MV_TRUE; + } + return MV_FALSE; +} +/******************************************************************************* +* mvBoardIsBootFromSpi - +* +* DESCRIPTION: +* This routine returns MV_TRUE if the board is configure to boot from SPI flash +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - boot from SPI. +* MV_FALSE - other. +* +*******************************************************************************/ +MV_BOOL mvBoardIsBootFromSpi(MV_VOID) +{ + /* Check if boot from NAND - do nothing */ + if ((MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & MSAR_BOOTDEV_MASK) == MSAR_BOOTDEV_SPI) + { + return MV_TRUE; + } + return MV_FALSE; +} +/******************************************************************************* +* mvBoardIsBootFromNor - +* +* DESCRIPTION: +* This routine returns MV_TRUE if the board is configure to boot from NOR flash +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - boot from Nor. +* MV_FALSE - other. +* +*******************************************************************************/ +MV_BOOL mvBoardIsBootFromNor(MV_VOID) +{ + /* Check if boot from NAND - do nothing */ + if ((MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & MSAR_BOOTDEV_MASK) == MSAR_BOOTDEV_FLASH) + { + return MV_TRUE; + } + return MV_FALSE; +} + +/******************************************************************************* +* mvBoardNameGet - Get Board name +* +* DESCRIPTION: +* This function returns a string describing the board model and revision. +* String is extracted from board I2C EEPROM. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain board name string. Minimum size 32 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ +MV_STATUS mvBoardNameGet(char *pNameBuff) +{ + char ctrlStr[132] = ""; + MV_U32 boardId = mvBoardIdGet(); + mvCtrlNameGet(ctrlStr); + + if (RD_78XX0_H3C_ID == boardId) + { + sprintf (pNameBuff, "RD-"); + strcat (pNameBuff, ctrlStr); + strcat (pNameBuff, "-H3C"); + } + else + if (DB_78XX0_ID == boardId) + { + sprintf (pNameBuff, "DB-"); + strcat (pNameBuff, ctrlStr); + strcat (pNameBuff, "-A-BP"); + } + else + if (DB_78200_ID == boardId) + { + sprintf (pNameBuff, "DB-"); + strcat (pNameBuff, ctrlStr); + strcat (pNameBuff, "-A-BP"); + } + else + if (RD_78XX0_AMC_ID == boardId) + { + sprintf (pNameBuff, "RD-"); + strcat (pNameBuff, ctrlStr); + strcat (pNameBuff, "-AMC"); + } + else + if (RD_78XX0_MASA_ID == boardId) + { + sprintf (pNameBuff, "RD-"); + strcat (pNameBuff, ctrlStr); + strcat (pNameBuff, "-MASA"); + } + else + { + sprintf (pNameBuff, "Board unknown.\n"); + return MV_ERROR; + } + + return MV_OK; +} + +/******************************************************************************* +* mvBoardIsPortInSgmii - +* +* DESCRIPTION: +* This routine returns MV_TRUE for port number works in SGMII or MV_FALSE +* For all other options. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - port in SGMII. +* MV_FALSE - other. +* +*******************************************************************************/ +MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum) +{ + MV_BOOL ethPortSgmiiSupport[BOARD_ETH_PORT_NUM] = MV_ETH_PORT_SGMII; + + if (ethPortNum > BOARD_ETH_END_PORT_NUM) + { + mvOsPrintf ("mvBoardIsPortInSgmii: Invalid portNo=%d.\n", ethPortNum); + return MV_FALSE; + } + return ethPortSgmiiSupport[ethPortNum - BOARD_ETH_START_PORT_NUM]; +} + +/******************************************************************************* +* mvBoardPhyAddrGet - Get the phy address +* +* DESCRIPTION: +* This routine returns the Phy address of a given ethernet port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing Phy address, '-1' if the port number is wrong. +* +*******************************************************************************/ +MV_U32 mvBoardPhyAddrGet(MV_U32 ethPortNum) +{ + MV_U32 ethPortPhyAddr[BOARD_ETH_PORT_NUM] = MV_ETH_PORT_PHY_ADDR; + + if(ethPortNum > BOARD_ETH_END_PORT_NUM) + { + mvOsPrintf ("mvBoardPhyAddrGet: Invalid portNo=%d.\n", ethPortNum); + return MV_ERROR; + } + + return ethPortPhyAddr[ethPortNum - BOARD_ETH_START_PORT_NUM]; +} + + +/******************************************************************************* +* mvBoardMacSpeedGet - Get the Mac speed +* +* DESCRIPTION: +* This routine returns the Mac speed if pre define of a given ethernet port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BOARD_MAC_SPEED, -1 the port number is wrong. +* +*******************************************************************************/ +MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum) +{ + MV_32 boardId = mvBoardIdGet(); + if (boardId == RD_78XX0_H3C_ID) + /* RD-H3C 1145 works in RGMII to SGMII mode which disable speed AN, + force speed to 1000*/ + return BOARD_MAC_SPEED_1000M; + else + return BOARD_MAC_SPEED_AUTO; +} +/******************************************************************************* +* mvBoardSpecInitGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: Return MV_TRUE and parameters in case board need specific phy init, +* otherwise return MV_FALSE. +* +* +*******************************************************************************/ + +MV_BOOL mvBoardSpecInitGet(MV_U32* regOff, MV_U32* data) +{ + return MV_FALSE; +} + +/******************************************************************************* +* mvBoardTclkGet - Get the board Tclk (Controller clock) +* +* DESCRIPTION: +* This routine extract the controller T clock. +* +* INPUT: +* None. +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +MV_32 mvBoardTclkGet(MV_VOID) +{ + MV_32 tmpTClkRate=0; + + if (-1 == tClkRate) + { + tmpTClkRate = MV_REG_READ(CPU_RESET_SAMPLE_H_REG); + switch(tmpTClkRate & MSAR_TCLCK_MASK) + { + case(MSAR_TCLCK_167): + tmpTClkRate = MV_BOARD_TCLK_166MHZ; + break; + case(MSAR_TCLCK_200): + tmpTClkRate = MV_BOARD_TCLK_200MHZ; + break; + default: + tmpTClkRate = MV_BOARD_TCLK_200MHZ; + break; + } + + tClkRate = tmpTClkRate ; + } + else + { + tmpTClkRate = tClkRate; + } + + + return tmpTClkRate; +} + +/******************************************************************************* +* mvBoardSysClkGet - Get the board SysClk (CPU bus clock) +* +* DESCRIPTION: +* This routine extract the CPU bus clock. +* Note: In the MPC745x, DEC is decremented and the time base +* increments at 1/4 of the system bus clock frequancy. +* Note: In order to avoid interference, make sure task context switch +* and interrupts will not occure during this function operation +* +* INPUT: +* countNum - Counter number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +MV_32 mvBoardSysClkGet(MV_VOID) +{ + MV_32 tmpSysClkRate=0; + + if (-1 == sysClkRate) + { + tmpSysClkRate = MV_REG_READ(CPU_RESET_SAMPLE_L_REG); + switch(tmpSysClkRate & MSAR_SYSCLCK_MASK) + { + case(MSAR_SYSCLCK_200): + tmpSysClkRate = MV_BOARD_SYSCLK_200MHZ; + break; + case(MSAR_SYSCLCK_267): + tmpSysClkRate = MV_BOARD_SYSCLK_267MHZ; + break; + case(MSAR_SYSCLCK_333): + tmpSysClkRate = MV_BOARD_SYSCLK_333MHZ; + break; + case(MSAR_SYSCLCK_400): + tmpSysClkRate = MV_BOARD_SYSCLK_400MHZ; + break; + case(MSAR_SYSCLCK_250): + tmpSysClkRate = MV_BOARD_SYSCLK_250MHZ; + break; + case(MSAR_SYSCLCK_300): + tmpSysClkRate = MV_BOARD_SYSCLK_300MHZ; + break; + default: + tmpSysClkRate = MV_BOARD_SYSCLK_267MHZ; + break; + } + + sysClkRate = tmpSysClkRate; + } + else + { + tmpSysClkRate = sysClkRate; + } + + return tmpSysClkRate; +} + +/******************************************************************************* +* mvBoardDebugLed - Set the board debug LEDs +* +* DESCRIPTION: +* This function sets the board debug LEDs as the input number in hex, +* e.g - if state == 3 -->> debug leds 0 and 1 are turned on +* +* INPUT: +* hexNum - Number to be displied in hex by LEDs. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardDebugLed(MV_U32 binNum) +{ + int ledNum; + MV_32 boardId = mvBoardIdGet(); + + /* Binary number limited by the number of LEDs */ + binNum %= (1 << MV_BOARD_LED_NUM); + + for(ledNum = 0 ; ledNum < MV_BOARD_LED_NUM ; ledNum++) + { + if(binNum & (1 << ledNum)) /* turn led on */ + { + if (DB_78XX0_ID == boardId) + mvGppValueSet( 0, + (1 << DB_78XX0_LED_GPP_PIN(ledNum)), /* mask */ + (1 << DB_78XX0_LED_GPP_PIN(ledNum))); /* value */ + else if (RD_78XX0_AMC_ID == boardId) + mvGppValueSet( 0, + (1 << RD_AMC_LED_GPP_PIN(ledNum)), /* mask */ + (1 << RD_AMC_LED_GPP_PIN(ledNum))); /* value */ + } + else /* turn led off */ + { + if (DB_78XX0_ID == boardId) + mvGppValueSet( 0, + (1 << DB_78XX0_LED_GPP_PIN(ledNum)), /* mask */ + ~(1 << DB_78XX0_LED_GPP_PIN(ledNum))); /* value */ + if (RD_78XX0_AMC_ID == boardId) + mvGppValueSet( 0, + (1 << RD_AMC_LED_GPP_PIN(ledNum)), /* mask */ + ~(1 << RD_AMC_LED_GPP_PIN(ledNum))); /* value */ + } + } +} + + +/******************************************************************************* +* mvBoardDebug7Seg - Set the board debug 7Seg +* +* DESCRIPTION: +* +* INPUT: +* hexNum - Number to be displied in hex by 7Seg. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardDebug7Seg(MV_U32 hexNum) +{ + MV_U32 dummy, address; + + MV_32 boardId = mvBoardIdGet(); + if ( (DB_78XX0_ID == boardId) || (DB_78200_ID == boardId) ) +#if !defined (MV78XX0_Z0) + MV_MEMIO8_WRITE(MV_BOARD_7SEG_BASE, hexNum); +#else + { + + address = MV_BOARD_7SEG_BASE + (hexNum << 4); + dummy = MV_MEMIO32_READ(CPU_MEMIO_UNCACHED_ADDR(address)); + } +#endif + else + { + /* The 7Seg on the device bus uses the address to set the sement */ + if (mvBoardIdGet() == RD_78XX0_H3C_ID) { + dummy = (hexNum % 4); + MV_MEMIO8_WRITE(CPU_MEMIO_UNCACHED_ADDR(MV_BOARD_7SEG_BASE), dummy); + } +#if !defined (MV78XX0_Z0) + else { + address = MV_BOARD_7SEG_BASE + (hexNum << 4); + dummy = MV_MEMIO32_READ(CPU_MEMIO_UNCACHED_ADDR(address)); + } +#endif + } +} +/******************************************************************************* +* mvBoardReset - mvBoardReset +* +* DESCRIPTION: +* Reset the board +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvBoardReset(MV_VOID) +{ + MV_32 boardId = mvBoardIdGet(); + if ((boardId == DB_78XX0_ID) || (DB_78200_ID == boardId) || + (boardId == RD_78XX0_MASA_ID) || (boardId == RD_78XX0_H3C_ID)) + { + MV_REG_WRITE(CPU_RESET_OUT_MASK_REG, (CPU_SOFT_RESET_OUT_MASK)); + MV_REG_WRITE(CPU_SOFT_RESET_OUT_REG, (CPU_SOFT_RESET_OUT)); + while(1); + } + + if (boardId == RD_78XX0_AMC_ID) + { + MV_REG_WRITE(GPP_DATA_OUT_REG(0), (1 << RD_AMC_SW_RESET)); + while(1); + } +} + +/******************************************************************************* +* mvBoardUSBVbusGpioPinGet - Get board GPP pin number connected to USB VBUS +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardUSBVbusGpioPinGet(int devId) +{ + MV_U32 boardID; + + boardID = mvBoardIdGet(); + + if(boardID == DB_78XX0_ID) + { + return DB_78XX0_USB_VBUS_PIN(devId); + } + + if (boardID == RD_78XX0_AMC_ID) + { + return RD_AMC_USB_VBUS_PIN(devId); + } + + if (boardID == RD_78XX0_H3C_ID) + { + return RD_H3C_USB_VBUS_PIN(devId); + } + + return MV_ERROR; +} + +/******************************************************************************* +* mvBoardUSBVbusEnGpioPinGet - return Vbus Enable output GPP +* +* DESCRIPTION: +* +* INPUT: +* int devNo. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardUSBVbusEnGpioPinGet(int devId) +{ + return N_A; +} +/******************************************************************************* +* mvBoardGpioIntMaskGet - Get GPIO mask for interrupt pins +* +* DESCRIPTION: +* This function returns a 32-bit mask of GPP pins that connected to +* interrupt generating sources on board. +* For example if UART channel A is hardwired to GPP pin 8 and +* UART channel B is hardwired to GPP pin 4 the fuinction will return +* the value 0x000000110 +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* See description. The function return -1 if board is not identified. +* +*******************************************************************************/ +MV_32 mvBoardGpioIntMaskGet(MV_VOID) +{ + MV_U32 boardID; + + boardID = mvBoardIdGet(); + + if ((boardID == DB_78XX0_ID) || (boardID == RD_78XX0_AMC_ID)) + { + return MV_ERROR; + } + else if (boardID == RD_78XX0_MASA_ID) + { + return RD_78XX0_MASA_INT_MASK; + } + + return MV_ERROR; /* Error */ +} +/******************************************************************************* +* mvBoardMppGet - Get board dependent MPP register value +* +* DESCRIPTION: +* MPP settings are derived from board design. +* MPP group consist of 8 MPPs. An MPP group represent MPP +* control register. +* This function retrieves board dependend MPP register value. +* +* INPUT: +* mppGroupNum - MPP group number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit value describing MPP control register value. +* +*******************************************************************************/ +MV_U32 mvBoardMppGet(MV_U32 mppGroupNum) +{ + MV_U32 boardID; + + boardID = mvBoardIdGet(); + + /* This id DB-MV78100-BP */ + if(DB_78XX0_ID == boardID) + { + switch(mppGroupNum) + { + case (0): + return DB_78XX0_MPP0_7; + case (1): + return DB_78XX0_MPP8_15; + case (2): + return DB_78XX0_MPP16_23; + case (3): + return DB_78XX0_MPP24_31; + default: + return 0; + } + } + /* This id DB-MV78200-BP */ + if(DB_78200_ID == boardID) + { + switch(mppGroupNum) + { + case (0): + return DB_78200_MPP0_7; + case (1): + return DB_78200_MPP8_15; + case (2): + return DB_78200_MPP16_23; + case (3): + return DB_78200_MPP24_31; + case (4): + return DB_78200_MPP32_39; + default: + return 0; + } + } + else if(RD_78XX0_AMC_ID == boardID) + { + switch(mppGroupNum) + { + case (0): + return RD_AMC_MPP0_7; + case (1): + return RD_AMC_MPP8_15; + case (2): + return RD_AMC_MPP16_23; + case (3): + return RD_AMC_MPP24_31; + default: + DB(mvOsPrintf("mvBoardMppGet: ERR. Unsupported MPP group %d\n", + mppGroupNum)); + } + } + else if(RD_78XX0_H3C_ID == boardID) + { + switch(mppGroupNum) + { + case (0): + return RD_H3C_MPP0_7; + case (1): + return RD_H3C_MPP8_15; + case (2): + return RD_H3C_MPP16_23; + case (3): + return RD_H3C_MPP24_31; + default: + DB(mvOsPrintf("mvBoardMppGet: ERR. Unsupported MPP group %d\n", + mppGroupNum)); + } + } + else if(RD_78XX0_MASA_ID == boardID) + { + switch(mppGroupNum) + { + case (0): + return RD_MASA_MPP0_7; + case (1): + return RD_MASA_MPP8_15; + case (2): + return RD_MASA_MPP16_23; + case (3): + return RD_MASA_MPP24_31; + default: + DB(mvOsPrintf("mvBoardMppGet: ERR. Unsupported MPP group %d\n", + mppGroupNum)); + } + } + else + { + DB(mvOsPrintf("mvBoardMppGet: ERR. Board not spported\n")); + } + + return 0; +} +/* Board devices API managments */ + +/******************************************************************************* +* mvBoardGetDeviceNumber - Get number of device of some type on the board +* +* DESCRIPTION: +* +* INPUT: +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* number of those devices else the function returns 0 +* +* +*******************************************************************************/ +MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass) +{ + MV_32 i, count = 0; + MV_DEV_CS_INFO* devEntry = boardGetCsArray(); + + for (i = 0; devEntry[i].deviceCS != MAX_TARGETS; i++) + { + if (devClass == devEntry[i].devClass) + count++; + } + return count; +} + +/******************************************************************************* +* mvBoardGetDeviceBaseAddr - Get base address of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* Base address else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_U32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return mvCpuIfTargetWinBaseLowGet(devEntry->deviceCS); + } + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* mvBoardGetDeviceBusWidth - Get Bus width of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* Bus width else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_U32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return devEntry->devWidth; + } + + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* mvBoardGetDeviceWinSize - Get the window size of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* window size else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_U32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return mvCpuIfTargetWinSizeGet(devEntry->deviceCS); + } + + return 0xFFFFFFFF; +} + + + +/******************************************************************************* +* mvBoardRtcTwsiAddrTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardRtcTwsiAddrTypeGet() +{ + return MV_BOARD_RTC_I2C_ADDR_TYPE; +} + +/******************************************************************************* +* mvBoardRtcTwsiAddrGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardRtcTwsiAddrGet() +{ + return MV_BOARD_RTC_I2C_ADDR; +} + + +/******************************************************************************* +* boardGetDevEntry - returns the entry pointer of a device on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* dev number else the function returns 0x0 +* +* +*******************************************************************************/ +static MV_DEV_CS_INFO* boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_U32 foundIndex = 0, i; + MV_DEV_CS_INFO* devEntry = boardGetCsArray(); + + for (i = 0; devEntry[i].deviceCS != MAX_TARGETS; i++) + { + if (devEntry[i].devClass == devClass) + { + if (foundIndex == devNum) + { + return &devEntry[i]; + } + foundIndex++; + } + } + + /* device not found */ + return NULL; +} + + +/******************************************************************************* +* mvBoardGetDevCS - +* +* DESCRIPTION: +* Return device CS target +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None +* +*******************************************************************************/ +MV_TARGET mvBoardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return devEntry->deviceCS; + } + return MAX_TARGETS; +} + + + +MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + return devEntry->devWidth; + + return 0xFFFFFFFF; + +} + + +MV_U32 mvBoardFlashParamGet(MV_VOID) +{ + MV_U32 boardId = mvBoardIdGet(); + if (RD_78XX0_AMC_ID == boardId || + RD_78XX0_MASA_ID == boardId || + RD_78XX0_H3C_ID == boardId) + return 0; + else + return MV_BOARD_FLASH_PARAM_VAL; +} + +MV_U32 mvBoardGetMaxUsbIf(MV_VOID) +{ + MV_U32 boardId = mvBoardIdGet(); + if (RD_78XX0_AMC_ID == boardId || + RD_78XX0_H3C_ID == boardId) + return 1; + else + return 3; +} + + +/******************************************************************************* +* mvEthPhyInit - Initialize Phy +* +* DESCRIPTION: +* This function initialize ethernet phy DFCDLs. +* +* INPUT: +* phyAddr - Phy address. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardEthPhyInit(MV_VOID) +{ + MV_U32 port; + MV_U32 boardID = mvBoardIdGet(); + for (port = BOARD_ETH_START_PORT_NUM; port < BOARD_ETH_END_PORT_NUM; port ++) { + /* First init the SGMII to copper on the test board */ + if (boardID == RD_78XX0_H3C_ID) { + mvEthSgmiiToCopperPhyBasicInit(port); + mvEth1145PhyBasicInit(port); + } + else if (boardID == RD_78XX0_AMC_ID) { + mvEth1145PhyBasicInit(port); + } + /* This id DB-78XX0-BP */ + else if ((boardID == DB_78XX0_ID) || + (boardID == RD_78XX0_MASA_ID)) + mvEth1121PhyBasicInit(port); + } +} + +/******************************************************************************* +* mvBoardIdGet - Get Board model +* +* DESCRIPTION: +* This function returns board ID. +* Board ID is 32bit word constructed of board model (16bit) and +* board revision (16bit) in the following way: 0xMMMMRRRR. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit board ID number, '-1' if board is undefined. +* +*******************************************************************************/ +MV_U32 mvBoardIdGet(MV_VOID) +{ + MV_U32 ctrlModel; + if (gBoardId != 0) + return gBoardId; +/*No detection mechanism*/ +#if defined(RD_MV78XX0_AMC) + return RD_78XX0_AMC_ID; +#elif defined(RD_MV78XX0_MASA) + return RD_78XX0_MASA_ID; +#elif defined(RD_MV78XX0_H3C) + return RD_78XX0_H3C_ID; +#endif + + ctrlModel = mvCtrlModelGet(); + + if (MV_78XX0_DEV_ID == ctrlModel || + MV_78100_DEV_ID == ctrlModel) + { + return DB_78XX0_ID; + } + else + if (MV_78200_DEV_ID == ctrlModel) + { + return DB_78200_ID; + } + else + return UNKNOWN_BOARD_ID; +} +/******************************************************************************* +* refClkDevInit - Initialize the reference clock device. +* +* DESCRIPTION: +* This function initialize the on board DUART device to be used as +* reference clock device which its baudrate is known. +* Note that the channel to be used is channel 'B' and baudrate is set +* to 115200. +* Note that the module extract the DUART channel B base using the CPU +* interface API. This is done in order to make this code independed +* of its location relative to CPU interface initialization where address +* decodes are updated. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_U32 refClkDevInit(MV_VOID) +{ + return 0; +} + +/******************************************************************************* +* refClkDevRelease - Release the reference clock device. +* +* DESCRIPTION: +* This function release the on board DUART device to its previous +* state before using it as a reference clocking device. +* Note that the module extract the DUART channel B base using the CPU +* interface API. This is done in order to make this code independed +* of its location relative to CPU interface initialization where address +* decodes are updated. +* +* INPUT: +* prevState - Previous state with the following encoding: +* byte0 - previous IER +* byte1 - previous DLL +* byte2 - previous DLM +* byte3 - previous divisior high +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID refClkDevRelease(MV_U32 prevState) +{ + return; +} + +/******************************************************************************* +* refClkDevBitRateGet - Get the reference clock device bit rate. +* +* DESCRIPTION: +* The UART device bauderate is theoretical. The UART protocol insert +* control bits along with data transport (start and stop bits). +* This means that for each 8 bit data (we use the UART with 8 bit data) +* two bits are for control, which gives us actual bauderate ~82.5% of +* the theoretical one. +* This function retrieve the on board DUART device bauderate. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_U32 refClkDevBitRateGet(MV_VOID) +{ + return (mvBoardTclkGet() * TCLK_TO_COUNTER_RATIO); +} + +/******************************************************************************* +* refClkDevStart - Start the reference clock device. +* +* DESCRIPTION: +* This enable counter REF_TIMER for an input number of tikcs. +* +* INPUT: +* refClkDevBits - Number of bits to transmit (must be a multiple of 8). +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID refClkDevStart(MV_U32 refClkDevBits) +{ + MV_CNTMR_CTRL cntmrCtrl; + + cntmrCtrl.enable = MV_TRUE; + + + if (MV_OK != mvCntmrStart(REF_TIMER, refClkDevBits, &cntmrCtrl)) + { + DB(mvOsPrintf("refClkDevStart - Can't start counter %d\n", REF_TIMER)); + } + else + { + while(mvCntmrRead(REF_TIMER)); + } +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.h b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.h new file mode 100644 index 0000000..8290a4e --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvLib.h @@ -0,0 +1,192 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvBoardEnvLibh +#define __INCmvBoardEnvLibh + +/* defines */ +/* The below constant macros defines the board I2C EEPROM data offsets */ + +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "boardEnv/mvBoardEnvSpec.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "mvSysHwConfig.h" + +#define BD_NAME_OFFS +#define BD_MODEL_MAJOR_OFFS +#define BD_MODEL_MINOR_OFFS +#define BD_REV_MAJOR_OFFS +#define BD_REV_MINOR_OFFS + + +/* Board specific */ +/* =============================== */ + +/* boards ID numbers */ + +/* New board ID numbers */ + +#define DB_78XX0_ID 0x00000050 +#define DB_78200_ID 0x00000090 +#define DB_78XX0_BP_MLL_ID 1683 +#define RD_78XX0_AMC_ID 0x00000060 +#define RD_78XX0_MASA_ID 0x00000070 +#define RD_78XX0_H3C_ID 0x00000080 + +#define MAX_BOARD_NAME_LEN 0x20 +#define UNKNOWN_BOARD_ID 0x0 + +/* DUART stuff for Tclk detection only */ +#define DUART_BAUD_RATE 115200 +#define MAX_CLOCK_MARGINE 5000000 /* Maximum detected clock margine */ + + +typedef enum _devBoardClass +{ + BOARD_DEV_NOR_FLASH, + BOARD_DEV_NAND_FLASH, + BOARD_DEV_SEVEN_SEG, + BOARD_DEV_FPGA, + BOARD_DEV_SRAM, + BOARD_DEV_RTC, + BOARD_DEV_PEX_TO_PCI_BRIDGE, + BOARD_DEV_MV_SWITCH, + BOARD_DEV_USB_VBUS, + BOARD_DEV_REF_CLCK, + BOARD_DEV_VOIP_SLIC, + BOARD_DEV_BUTTON, + BOARD_DEV_POWER_BUTTON, + BOARD_DEV_RESTOR_BUTTON, + BOARD_DEV_HDD0_POWER, + BOARD_DEV_HDD1_POWER, + BOARD_DEV_FAN_POWER, + BOARD_DEV_SPI_FLASH, + BOARD_DEV_RESET, + BOARD_DEV_POWER_ON_LED, + BOARD_DEV_HDD_POWER, + BOARD_DEV_OTHER, +} MV_BOARD_DEV_CLASS; + + +typedef struct _devCsInfo +{ + MV_U8 deviceCS; + MV_U32 params; + MV_U32 devClass; /* MV_BOARD_DEV_CLASS */ + MV_U8 devWidth; + +}MV_DEV_CS_INFO; + +typedef enum _boardMacSpeed +{ + BOARD_MAC_SPEED_10M, + BOARD_MAC_SPEED_100M, + BOARD_MAC_SPEED_1000M, + BOARD_MAC_SPEED_AUTO, + +}MV_BOARD_MAC_SPEED; + +/* Locals */ + + +MV_VOID mvBoardEnvInit(MV_VOID); +MV_U32 mvBoardIdGet(MV_VOID); +MV_STATUS mvBoardNameGet(char *pNameBuff); +MV_U32 mvBoardPhyAddrGet(MV_U32 ethPortNum); +MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum); +MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum); +MV_32 mvBoardTclkGet(MV_VOID); +MV_32 mvBoardSysClkGet(MV_VOID); +MV_VOID mvBoardDebugLed(MV_U32 hexNum); +MV_VOID mvBoardDebug7Seg(MV_U32 hexNum); + +MV_U32 mvBoardMppGet(MV_U32 mppGroupNum); + +MV_U8 mvBoardRtcTwsiAddrTypeGet(MV_VOID); +MV_U8 mvBoardRtcTwsiAddrGet(MV_VOID); + + +MV_32 mvBoardPciGpioPinGet(MV_U32 pciIf, MV_U32 idSel, MV_U32 intPin); +MV_32 mvBoardWDGpioPinGet(MV_VOID); +MV_32 mvBoardDbgLedGpioMaskGet(MV_VOID); + +MV_32 mvBoardGpioIntMaskGet(MV_VOID); +MV_32 mvBoardUSBVbusGpioPinGet(int devId); +MV_32 mvBoardUSBVbusEnGpioPinGet(int devId); + +MV_VOID mvBoardReset(MV_VOID); +MV_TARGET mvBoardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass); +MV_U32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_U32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_U32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); + +MV_BOOL mvBoardIsBootFromNand(MV_VOID); +MV_BOOL mvBoardIsBootFromSpi(MV_VOID); +MV_BOOL mvBoardIsBootFromNor(MV_VOID); +MV_VOID mvBoardEthPhyInit(MV_VOID); +MV_BOOL mvBoardSpecInitGet(MV_U32* regOff, MV_U32* data); +MV_U32 mvBoardFlashParamGet(MV_VOID); +MV_U32 mvBoardGetMaxUsbIf(MV_VOID); +#endif /* __INCmvBoardEnvLibh */ diff --git a/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.c b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.c new file mode 100644 index 0000000..5c565b9 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.c @@ -0,0 +1,180 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "cntmr/mvCntmr.h" +#include "device/mvDevice.h" + +/* defines */ +#ifdef DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + + +/******************************************************************************* +* mvBoardPciGpioPinGet - Get board PCI interrupt level. +* +* DESCRIPTION: +* This function returns the value of Gpp Pin that is connected +* to the specified IDSEL and interrupt pin (A,B,C,D). For example, If +* IDSEL 8 (device 8) interrupt A is connected to GPIO pin 4 the function +* will return the value 4. +* This function supports multiple PCI interfaces. +* +* INPUT: +* pciIf - PCI interface number. +* devNum - device number (IDSEL). +* intPin - Interrupt pin (A=1, B=2, C=3, D=4). +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardPciGpioPinGet(MV_U32 pciIf, MV_U32 devNum, MV_U32 intPin) +{ + /*No PCI*/ + return MV_ERROR; +} + +/******************************************************************************* +* mvBoardWDGpioPinGet - Get board Watchdog NMI GPP pin number. +* +* DESCRIPTION: +* This function returns the number of Gpp Pin that is connected +* to the watchdog NMI interrupt. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardWDGpioPinGet(MV_VOID) +{ + int intPin = -1; + MV_U32 boardID; + + boardID = mvBoardIdGet(); + + if ((boardID == DB_78XX0_ID) || (boardID == RD_78XX0_AMC_ID) || + (boardID == RD_78XX0_MASA_ID) || (boardID == RD_78XX0_H3C_ID)) + { + return MV_ERROR; + } + + return intPin; +} + +/******************************************************************************* +* mvBoardDbgLedGpioMaskGet - Get board debug LED GPP bit mask. +* +* DESCRIPTION: +* This function returns a bit-mask of Gpp Pin that is connected +* to the debug LED. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32-bit bit-mask. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardDbgLedGpioMaskGet(MV_VOID) +{ + MV_U32 boardID; + MV_U32 intPin = -1; + + boardID = mvBoardIdGet(); + switch(boardID){ + case DB_78XX0_ID: +#ifdef MV_INCLUDE_MODEM_ON_TTYS1 + intPin = 0; +#else + return MV_ERROR; +#endif + break; + case RD_78XX0_AMC_ID: + intPin = 0; + break; + case RD_78XX0_MASA_ID: + intPin = (BIT22 | BIT23); + break; + } + + return intPin; +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.h b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.h new file mode 100644 index 0000000..cfe0261 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/boardEnv/mvBoardEnvSpec.h @@ -0,0 +1,361 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvBoardEnvSpech +#define __INCmvBoardEnvSpech + +#include "mvSysHwConfig.h" + +#define DB_MODEL_BACKPLAIN 0x0100 + +/* Clocks stuff */ +#define MV_BOARD_DEFAULT_TCLK 166000000 /* Default Tclk 166MHz */ +#define MV_BOARD_DEFAULT_SYSCLK 200000000 /* Default SysClk 200MHz */ + +/* MPP[0] = GE_TXCLK MPP[1] = GE_TXCTL */ +/* MPP[2] = GE_RXCTL MPP[3] = GE_RXCLK */ +/* MPP[4] = GE_TXD0 MPP[5] = GE_TXD1 */ +/* MPP[6] = GE_TXD2 MPP[7] = GE_TXD3 */ +#define RD_MASA_MPP0_7 0x22222222 + +/* MPP[8] = GE_RXD0 MPP[9] = GE_RXD1 */ +/* MPP[10] = GE_RXD2 MPP[11] = GE_RXD3 */ +/* MPP[12] = DC MPP[13] = SysRst */ +/* MPP[14] = SATA_ACT MPP[15] = SATA_ACT */ +#define RD_MASA_MPP8_15 0x33302222 + +/* MPP[16] = DC MPP[17] = DC */ +/* MPP[18] = DC MPP[19] = DC */ +/* MPP[20] = DC MPP[21] = DC */ +/* MPP[22] = DC MPP[23] = DC */ +#define RD_MASA_MPP16_23 0x00000000 + +/* MPP[24] = DC MPP[25] = DC */ +/* MPP[26] = DC MPP[26] = DC */ +/* MPP[28] = DC MPP[27] = DC */ +/* MPP[30] = DC MPP[28] = DC */ +#define RD_MASA_MPP24_31 0x00000000 + +/* MPP[0] = GE_TXCLK MPP[1] = GE_TXCTL */ +/* MPP[2] = GE_RXCTL MPP[3] = GE_RXCLK */ +/* MPP[4] = GE_TXD0 MPP[5] = GE_TXD1 */ +/* MPP[6] = GE_TXD2 MPP[7] = GE_TXD3 */ +#define RD_AMC_MPP0_7 0x22222222 + +/* MPP[8] = GE_RXD0 MPP[9] = GE_RXD1 */ +/* MPP[10] = GE_RXD2 MPP[11] = GE_RXD3 */ +/* MPP[12] = DC MPP[13] = DC */ +/* MPP[14] = DC MPP[15] = DC */ +#define RD_AMC_MPP8_15 0x00002222 + +/* MPP[16] = DC MPP[17] = DC */ +/* MPP[18] = DC MPP[19] = DC */ +/* MPP[20] = DC MPP[21] = DC */ +/* MPP[22] = DC MPP[23] = DC */ +#define RD_AMC_MPP16_23 0x00000000 + +/* MPP[24] = DC MPP[25] = DC */ +/* MPP[26] = DC MPP[26] = DC */ +/* MPP[28] = DC MPP[27] = DC */ +/* MPP[30] = DC MPP[28] = DC */ +#define RD_AMC_MPP24_31 0x00000000 + +/* MPP[0] = GE_TXCLK MPP[1] = GE_TXCTL */ +/* MPP[2] = GE_RXCTL MPP[3] = GE_RXCLK */ +/* MPP[4] = GE_TXD0 MPP[5] = GE_TXD1 */ +/* MPP[6] = GE_TXD2 MPP[7] = GE_TXD3 */ +#define RD_H3C_MPP0_7 0x22222222 + +/* MPP[8] = GE_RXD0 MPP[9] = GE_RXD1 */ +/* MPP[10] = GE_RXD2 MPP[11] = GE_RXD3 */ +/* MPP[12] = DC MPP[13] = DC */ +/* MPP[14] = DC MPP[15] = DC */ +#define RD_H3C_MPP8_15 0x00302222 + +/* MPP[16] = DC MPP[17] = DC */ +/* MPP[18] = DC MPP[19] = DC */ +/* MPP[20] = DC MPP[21] = DC */ +/* MPP[22] = DC MPP[23] = DC */ +#define RD_H3C_MPP16_23 0x00000000 + +/* MPP[24] = DC MPP[25] = DC */ +/* MPP[26] = DC MPP[26] = DC */ +/* MPP[28] = DC MPP[27] = DC */ +/* MPP[30] = DC MPP[28] = DC */ +#define RD_H3C_MPP24_31 0x00000000 + +/* MPP[0] = GE_TXCLK MPP[1] = GE_TXCTL */ +/* MPP[2] = GE_RXCTL MPP[3] = GE_RXCLK */ +/* MPP[4] = GE_TXD0 MPP[5] = GE_TXD1 */ +/* MPP[6] = GE_TXD2 MPP[7] = GE_TXD3 */ +#define DB_78XX0_MPP0_7 0x22222222 + +/* MPP[8] = GE_RXD0 MPP[9] = GE_RXD1 */ +/* MPP[10] = GE_RXD2 MPP[11] = GE_RXD3 */ +/* MPP[12] = GPIO[12] - USB1_VBUS MPP[13] = MV_SYS_RST */ +/* MPP[14] = SATA1_ACT MPP[15] = SATA2_ACT */ +#define DB_78XX0_MPP8_15 0x33302222 + +/* MPP[16] = UART2_TXD MPP[17] = UART2_RXD */ +/* MPP[18] = UART0_CTS MPP[19] = UART0_RTS */ +/* MPP[20] = UART1_CTS MPP[21] = UART1_RTS */ +/* MPP[22] = UART3_TXD MPP[23] = UART3_RXD */ +#define DB_78XX0_MPP16_23 0x44444444 + +/* MPP[24] = DC MPP[25] = DC */ +/* MPP[26] = DC MPP[26] = DC */ +/* MPP[28] = DC MPP[27] = DC */ +/* MPP[30] = DC MPP[28] = DC */ +#define DB_78XX0_MPP24_31 0x00000000 + +/* MPP[0] = GE_TXCLK MPP[1] = GE_TXCTL */ +/* MPP[2] = GE_RXCTL MPP[3] = GE_RXCLK */ +/* MPP[4] = GE_TXD0 MPP[5] = GE_TXD1 */ +/* MPP[6] = GE_TXD2 MPP[7] = GE_TXD3 */ +#define DB_78200_MPP0_7 0x22222222 + +/* MPP[8] = GE_RXD0 MPP[9] = GE_RXD1 */ +/* MPP[10] = GE_RXD2 MPP[11] = GE_RXD3 */ +/* MPP[12] = GPIO[12] - USB1_VBUS MPP[13] = MV_SYS_RST */ +/* MPP[14] = SATA1_ACT MPP[15] = SATA2_ACT */ +#define DB_78200_MPP8_15 0x22222222 + +/* MPP[16] = UART2_TXD MPP[17] = UART2_RXD */ +/* MPP[18] = UART0_CTS MPP[19] = UART0_RTS */ +/* MPP[20] = UART1_CTS MPP[21] = UART1_RTS */ +/* MPP[22] = UART3_TXD MPP[23] = UART3_RXD */ +#define DB_78200_MPP16_23 0x22222222 + +/* MPP[24] = DC MPP[25] = DC */ +/* MPP[26] = DC MPP[26] = DC */ +/* MPP[28] = DC MPP[27] = DC */ +/* MPP[30] = DC MPP[28] = DC */ +#define DB_78200_MPP24_31 0x22222222 + +/* MPP[24] = DC MPP[25] = DC */ +/* MPP[26] = DC MPP[26] = DC */ +/* MPP[28] = DC MPP[27] = DC */ +/* MPP[30] = DC MPP[28] = DC */ +#define DB_78200_MPP32_39 0x51112222 + +#define DB_78XX0_HAS_PTP_BRIDGE 1 + +/* 7-Segment stuff */ +#define MV_BOARD_7SEG_BASE ((RD_78XX0_H3C_ID == mvBoardIdGet())? \ + DEVICE_CS2_BASE : DEVICE_CS1_BASE) +#define MV_BOARD_7SEG_PARAM 0x003E07CF /* 8 bit */ + +/* Board main flash */ +#define MV_BOARD_FLASH_BASE_ADRS DEVICE_CS0_BASE +#define MV_BOARD_FLASH_BUS_WIDTH 32 /* Two byte width bus */ +#define MV_BOARD_FLASH_DEVICE_WIDTH 16 /* 16-bit width Flash mode*/ +#define MV_BOARD_FLASH_PARAM (mvBoardFlashParamGet()) +#define MV_BOARD_FLASH_PARAM_VAL 0x803E07CF /* 32 bit */ + +/* NAND flash */ +#define MV_NAND_CS DEV_CS2 +#define MV_NAND_CARE 0 +#define MV_BOARD_NFLASH_DEVICE_WIDTH 8 /* 8-bit width Flash mode*/ +#define MV_BOARD_NFLASH_BASE_ADRS DEVICE_CS2_BASE /* empty */ +#define MV_BOARD_NFLASH_PARAM 0x003E07CF /* 8 bit */ + +/* Boot Flash definitions */ +#define MV_BOARD_BOOT_FLASH_BASE_ADRS BOOTDEV_CS_BASE +#define MV_BOARD_BOOT_FLASH_BUS_WIDTH 8 /* One byte width bus */ +#define MV_BOARD_BOOT_FLASH_DEVICE_WIDTH 8 /* 8-bit width Flash mode */ +#define MV_BOARD_BOOT_FLASH_PARAM 0x003E07CF /* 8 bit */ + + +#define DEVICE_CS0_PARAM MV_BOARD_FLASH_PARAM +#define DEVICE_CS1_PARAM MV_BOARD_7SEG_PARAM +#define DEVICE_CS2_PARAM MV_BOARD_NFLASH_PARAM + +#define DEVICE_CS3_PARAM 0 + +#define DEVICE_CS0_PARAM_WR 0xF0F0F +#define DEVICE_CS1_PARAM_WR 0xF0F0F +#define DEVICE_CS2_PARAM_WR 0xF0F0F +#define DEVICE_CS3_PARAM_WR 0xF0F0F + +#define BOOTDEV_CS_PARAM MV_BOARD_BOOT_FLASH_PARAM + +#define DRAM_SLOT_NUM 2 + +/* Debug Led stuff. GPP pin assigments. Board depended. */ +#define MV_BOARD_LED_NUM 0 + +/* Other GPIOs */ +/* DB-78100-A-BP */ +#define DB_78XX0_LED_GPP_PIN(ledNum) (0) +#define DB_78XX0_SW_RESET 13 +#define DB_78XX0_USB_VBUS_PIN(usb) 12 + +/* DB-78200-A-BP */ +#define DB_78200_SW_RESET 31 + +/* RD-AMC */ +#define RD_AMC_LED_GPP_PIN(ledNum) (0) +#define RD_AMC_SW_RESET 25 +#define RD_AMC_USB_VBUS_PIN(usb) ((usb == 0) ? 22 : ((usb == 1) ? 12 : 23)) +/* GPP 12, 13, 16-19 are output */ +#define RD_AMC_GPIO_OUTPUT_EN (BIT12 | BIT13 | BIT16 | BIT17 | BIT18 | BIT19 | BIT25) + +#define RD_H3C_SW_RESET 13 +#define RD_H3C_SW_RESET_SELECT 14 +#define RD_H3C_USB_VBUS_PIN(usb) 12 +/* GPP 14 is output */ +#define RD_H3C_GPIO_OUTPUT_EN (BIT14) + +#define RD_MASA_LED_GPP_PIN(ledNum) 23 +#define RD_MASA_DEBUG_LED_GPP_PIN(ledNum) 22 +#define RD_MASA_SW_RESET 13 +/* GPP 12, 13, 16-19 are output */ +#define RD_MASA_GPIO_OUTPUT_EN (BIT17 | BIT18 | BIT22 | BIT23) +#define RD_MASA_USB_OC BIT16 +#define RD_MASA_USB_PWR BIT17 +#define RD_MASA_HDD_PWR BIT18 +#define RD_MASA_SW_INT BIT19 +#define RD_MASA_RTC_INT BIT20 +#define RD_MASA_PHY_INT BIT21 +#define RD_78XX0_MASA_INT_MASK (RD_MASA_USB_OC | RD_MASA_SW_INT | \ + RD_MASA_RTC_INT | RD_MASA_PHY_INT) + +#ifdef MV_INCLUDE_MODEM_ON_TTYS1 +#define DB_78XX0_SERIAL_DTR 2 +#define DB_78XX0_SERIAL_DSR 3 +#define DB_78XX0_SERIAL_DCD 1 +#define DB_78XX0_SERIAL_RI 19 +#endif + +/* GPIO interrupt connectivity on the DB-MV78XX0 board */ + +/* I2C bus addresses */ +#define MV_BOARD_CTRL_I2C_ADDR 0x0 /* Controller slave addr */ +#define MV_BOARD_CTRL_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_DIMM_I2C_CHANNEL 0x0 +#ifdef RD_MV78XX0_MASA +/* SODIMM only two bit TWSI address */ +#define MV_BOARD_DIMM0_I2C_ADDR 0x50 +#define MV_BOARD_DIMM1_I2C_ADDR 0x51 +#else +#define MV_BOARD_DIMM0_I2C_ADDR 0x56 +#define MV_BOARD_DIMM1_I2C_ADDR 0x54 +#endif +#define MV_BOARD_DIMM0_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_DIMM1_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_CPU0_I2C_ADDR 0x51 +#define MV_BOARD_CPU0_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_CPU1_I2C_ADDR 0x51 /* Both CPU use the same I2C EEPROM */ +#define MV_BOARD_CPU1_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_SYS_I2C_ADDR 0x50 +#define MV_BOARD_SYS_I2C_ADDR_TYPE ADDR7_BIT +#if defined (MV78XX0_Z0) +#define MV_BOARD_RTC_I2C_CHANNEL 0x0 +#else +#define MV_BOARD_RTC_I2C_CHANNEL 0x1 +#endif +#define MV_BOARD_RTC_I2C_ADDR 0x68 +#define MV_BOARD_RTC_I2C_ADDR_TYPE ADDR7_BIT + +/* Ethernet stuff */ +#define MV78XX0_ETH_MAX_PORTS 2 +#define MV78200_ETH_MAX_PORTS 4 + +#define BOARD_ETH_START_PORT_NUM 0 +#define BOARD_ETH_END_PORT_NUM 3 +#define BOARD_ETH_PORT_NUM 4 +#define MV_ETH_PORT_SGMII {0, 0, 0, 0}; +#define MV_ETH_PORT_PHY_ADDR {0x8, 0x9, 0xA, 0xB}; + +#define MV_BOARD_MAX_USB_IF (mvBoardGetMaxUsbIf()) + +#define MV_BOARD_MAX_TWSI_DEV 8 +#define MV_BOARD_MAX_PCI_DEV 5 + +/* Supported clocks */ +#define MV_BOARD_TCLK_100MHZ 100000000 +#define MV_BOARD_TCLK_125MHZ 125000000 +#define MV_BOARD_TCLK_133MHZ 133333334 +#define MV_BOARD_TCLK_150MHZ 150000000 +#define MV_BOARD_TCLK_166MHZ 166666667 +#define MV_BOARD_TCLK_200MHZ 200000000 + +#define MV_BOARD_SYSCLK_100MHZ 100000000 +#define MV_BOARD_SYSCLK_125MHZ 125000000 +#define MV_BOARD_SYSCLK_133MHZ 133333334 +#define MV_BOARD_SYSCLK_150MHZ 150000000 +#define MV_BOARD_SYSCLK_166MHZ 166666667 +#define MV_BOARD_SYSCLK_200MHZ 200000000 +#define MV_BOARD_SYSCLK_160MHZ 160000000 +#define MV_BOARD_SYSCLK_233MHZ 233333334 +#define MV_BOARD_SYSCLK_250MHZ 250000000 +#define MV_BOARD_SYSCLK_267MHZ 266666667 +#define MV_BOARD_SYSCLK_300MHZ 300000000 +#define MV_BOARD_SYSCLK_333MHZ 333333334 +#define MV_BOARD_SYSCLK_400MHZ 400000000 + + +#define SGMII_OUTBAND_AN +#define PHY_UPDATE_TIMEOUT 10000 +#endif /* __INCmvBoardEnvSpech */ diff --git a/board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.c b/board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.c new file mode 100644 index 0000000..8a3e98d --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.c @@ -0,0 +1,281 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/*#include "mvCpu.h"*/ +#include "boardEnv/mvBoardEnvLib.h" +#include "cpu/mvCpu.h" +#include "twsi/mvTwsi.h" + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* locals */ +static int cpuCoreIdGet(MV_VOID); +/******************************************************************************* +* mvCpuSampleAtResetGet - Get the CPU sample at reset register value +* +* DESCRIPTION: +* Relevent for 1160 only. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit sample at reset register +* +*******************************************************************************/ +MV_U32 mvCpuSampleAtResetGet(MV_VOID) +{ + MV_U8 data[4]; + MV_U32 mvSampleAtReset = 0; + + /* Read 88F1160 S@R register */ + MV_TWSI_SLAVE twsiSlave; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.slaveAddr.address = CPU_TWSI_DEBUG_ADDR; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_TRUE; + + if( MV_OK != mvTwsiRead (0, &twsiSlave, data, 4)) + { + return 0xffffffff; + } + else + { + mvSampleAtReset = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + } + + return mvSampleAtReset; +} + +/******************************************************************************* +* mvCpuPclkGet - Get the CPU pClk (pipe clock) +* +* DESCRIPTION: +* This routine extract the CPU core clock. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ + +/* Mul constant */ +int sys2cpu_clk_ratio_m[] = {1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 6}; +/* Div constant */ +int sys2cpu_clk_ratio_n[] = {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1}; + +MV_U32 mvCpuPclkGet(MV_VOID) +{ + int p = 0; + MV_U32 tmpPClkRate = MV_REG_READ(CPU_RESET_SAMPLE_L_REG); + + p = ((tmpPClkRate & MSAR_SYSCLK2CPU_MASK) >> MSAR_SYSCLK2CPU_OFFS); + tmpPClkRate = sys2cpu_clk_ratio_m[p]; + tmpPClkRate *= mvBoardSysClkGet(); + + return (tmpPClkRate/sys2cpu_clk_ratio_n[p]); +} + +MV_U32 mvCpuL2ClkGet(MV_VOID) +{ + MV_U32 tmpL2ClkRate = MV_REG_READ(CPU_RESET_SAMPLE_L_REG); + + tmpL2ClkRate = ((tmpL2ClkRate & MSAR_CPUL2CLK_MASK) >> MSAR_CPUL2CLK_OFFS); + tmpL2ClkRate++; + + return (mvCpuPclkGet() / tmpL2ClkRate); +} +/******************************************************************************* +* mvAHBclkGet - Get the AHB Clk +* +* DESCRIPTION: +* This routine extract the AHB core clock. Relevent for 1160 only. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +MV_U32 mvAHBclkGet(MV_VOID) +{ + MV_U32 mvSampleAtReset = 0; + MV_U32 mvSysClkDiv = 0; + MV_U32 tmpPClkRate=0; + + /* Read 88F1160 S@R register */ + mvSampleAtReset = mvCpuSampleAtResetGet(); + if (mvSampleAtReset & BIT12) + { + mvSysClkDiv = 32 + (2 * ((mvSampleAtReset >> 7) & 0x1f)); + } + else + { + mvSysClkDiv = (mvSampleAtReset >> 7) & 0x1f; + } + + tmpPClkRate = mvCpuPclkGet() / mvSysClkDiv; + + return tmpPClkRate; +} + +/******************************************************************************* +* mvCpuNameGet - Get CPU name +* +* DESCRIPTION: +* This function returns a string describing the CPU model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain board name string. Minimum size 32 chars. +* +* RETURN: +* None. +*******************************************************************************/ +MV_VOID mvCpuNameGet(char *pNameBuff) +{ + MV_U32 cpuModel; + + cpuModel = mvOsCpuPartGet(); + + /* The CPU module is indicated in the Processor Version Register (PVR) */ + switch(cpuModel) + { + case CPU_PART_ARM926: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM926",mvOsCpuRevGet()); + break; + case CPU_PART_ARM946: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM946",mvOsCpuRevGet()); + break; + case CPU_PART_MRVL571: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "MRVL571",mvOsCpuRevGet()); + break; + case CPU_PART_MRVL521: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "MRVL521",mvOsCpuRevGet()); + break; + default: + mvOsSPrintf(pNameBuff,"??? (0x%04x) (Rev %d)",cpuModel,mvOsCpuRevGet()); + } /* switch */ +} + + +/******************************************************************************* +* whoAmI - Get CPU name +* +* DESCRIPTION: +* This function returns a string describing the CPU model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain board name string. Minimum size 32 chars. +* +* RETURN: +* None. +*******************************************************************************/ +unsigned int whoAmI(void) +{ +#if !defined(MV78XX0_Z0) + if (mvCtrlModelGet() != MV_78200_DEV_ID) + return (unsigned int)MASTER_CPU; + + return (cpuCoreIdGet() > 0) ? SLAVE_CPU: MASTER_CPU; +#else + return MASTER_CPU; +#endif + +} + +static int cpuCoreIdGet(MV_VOID) +{ + MV_U32 value; + + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0 @ read control reg\n" + : "=r" (value) :: "memory"); + return !!(value & (1 << 14)); +} + + diff --git a/board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.h b/board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.h new file mode 100644 index 0000000..524439e --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/cpu/mvCpu.h @@ -0,0 +1,101 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuArmh +#define __INCmvCpuArmh + +/* defines */ +#define MASTER_CPU 0 +#define SLAVE_CPU 1 + + +#define CPU_PART_MRVL131 0x131 +#define CPU_PART_ARM926 0x926 +#define CPU_PART_ARM946 0x946 +#define CPU_PART_MRVL571 0x571 +#define CPU_PART_MRVL521 0x521 +#define MV_CPU_ARM_CLK_ELM_SIZE 12 +#define MV_CPU_ARM_CLK_RATIO_OFF 8 +#define MV_CPU_ARM_CLK_DDR_OFF 4 + +#define CPU_TWSI_DEBUG_ADDR 0x2f + +#ifndef MV_ASMLANGUAGE +typedef struct _mvCpuArmClk +{ + MV_U32 cpuClk; /* CPU clock in MHz */ + MV_U32 ddrClk; /* DDR clock in MHz */ + MV_U32 clkRatio; /* CPU DDR clock ratio */ + +}MV_CPU_ARM_CLK; + +MV_U32 mvAHBclkGet(MV_VOID); +unsigned int whoAmI(MV_VOID); +MV_U32 mvCpuPclkGet(MV_VOID); +MV_U32 mvCpuL2ClkGet(MV_VOID); +MV_VOID mvCpuNameGet(char *pNameBuff); + +#endif /* MV_ASMLANGUAGE */ +#endif /* __INCmvCpuArmh */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.c new file mode 100644 index 0000000..e830ca8 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.c @@ -0,0 +1,427 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvCtrlEnvAddrDec.h - Marvell controller address decode library +* +* DESCRIPTION: +* The Marvell controller device has a fully programmable address map. +* There is a separate address map to each of the interfaces: +* - CPU address space +* - PCI_0 address space +* - PCI_1 address space +* - Gigabit Ethernet/FIFO interface address space +* - IDMA address space +* - XOR DMA address space (where XOR available) +* - Serial communication address space. +* Each interface includes programmable address windows that allows it +* to access any of the MV6456x resources. Each window can map up to +* 4 GB of address space. +* This file contains Marvell Controller address decode library API +* for Gigabit Ethernet, Serial communication, IDMA and XOR that shares +* the same address space decode implementation. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +/* includes */ +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* #define MV_DEBUG */ + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* Base Address Register (BAR) */ +#define BAR_TARGET_DRAM DRAM_TARGET_ID +#define BAR_TARGET_DEVICE DEV_TARGET_ID + + +#define BAR_TARGET_PCI0 PCI0_TARGET_ID +#define BAR_TARGET_PCI1 PCI0_TARGET_ID +#define BAR_TARGET_PCI2 PCI0_TARGET_ID +#define BAR_TARGET_PCI3 PCI1_TARGET_ID +#define BAR_TARGET_PCI4 PCI1_TARGET_ID +#define BAR_TARGET_PCI5 PCI1_TARGET_ID + +/* DRAM attributes */ +#define BAR_DRAM_BANK_MASK 0xF +#define BAR_DRAM_BANK(bankNo) (~(1 << (bankNo)) & BAR_DRAM_BANK_MASK) +#define BAR_DRAM_COHERENCY_OFFS 4 /* DRAM Cache coherency offset */ +#define BAR_DRAM_COHERENCY_MASK (0x3 << BAR_DRAM_COHERENCY_OFFS) +#define BAR_DRAM_NO_COHERENCY (NO_COHERENCY << BAR_DRAM_COHERENCY_OFFS) +#define BAR_DRAM_WT_COHERENCY (WT_COHERENCY << BAR_DRAM_COHERENCY_OFFS) +#define BAR_DRAM_WB_COHERENCY (WB_COHERENCY << BAR_DRAM_COHERENCY_OFFS) + + /* Device attributes */ +#define BAR_DEVICE_BANK_MASK 0x1F +#define BAR_DEVICE_BANK(bankNo) (~(1 << (bankNo)) & BAR_DEVICE_BANK_MASK) + + /* PCI0/1 attributes */ +#define BAR_PCI_BYTE_SWAP_OFFS 0 +#define BAR_PCI_BYTE_SWAP_MASK (0x3 << BAR_PCI_BYTE_SWAP_OFFS) +#define BAR_PCI_BYTE_SWAP MV_BYTE_SWAP +#define BAR_PCI_NO_SWAP MV_NO_SWAP +#define BAR_PCI_BYTE_WORD_SWAP MV_BYTE_WORD_SWAP +#define BAR_PCI_WORD_SWAP MV_WORD_SWAP +#define BAR_PCIX_NO_SNOOP_OFFS 2 +#define BAR_PCIX_NO_SNOOP_MASK (1 << BAR_PCIX_NO_SNOOP_OFFS) +#define BAR_PCI_BAR_TYPE_OFFS 3 /* PCI MEM/IO space */ +#define BAR_PCI_BAR_TYPE_MASK (1 << BAR_PCI_BAR_TYPE_OFFS) +#define BAR_PCI_IO_SPACE (0 << BAR_PCI_BAR_TYPE_OFFS) +#define BAR_PCI_MEMORY_SPACE (1 << BAR_PCI_BAR_TYPE_OFFS) +#define BAR_PCI_REQ64_MODE_OFFS 4 /* PCIx_REQ64n control */ +#define BAR_PCI_REQ64_MODE_MASK (1 << BAR_PCI_REQ64_MODE_OFFS) +#define BAR_PCI_REQ64_ALWAYS (0 << BAR_PCI_REQ64_MODE_OFFS) +#define BAR_PCI_REQ64_PER_REQU (1 << BAR_PCI_REQ64_MODE_OFFS) + +#define BAR_PCI_LANE_SELECT_OFF 4 +#define BAR_PCI_LANE_SELECT_MASK (0xf << BAR_PCI_LANE_SELECT_OFF) +#define BAR_PCI_LANE_0 (0xe << BAR_PCI_LANE_SELECT_OFF) +#define BAR_PCI_LANE_1 (0xd << BAR_PCI_LANE_SELECT_OFF) +#define BAR_PCI_LANE_2 (0xb << BAR_PCI_LANE_SELECT_OFF) +#define BAR_PCI_LANE_3 (0x7 << BAR_PCI_LANE_SELECT_OFF) + +/* Size register */ +#define BAR_SIZE_ALIGNMENT 0x10000 /* Minimum size 64K */ + +/* typedefs */ + +/* Locals */ + +MV_TARGET_ATTRIB mvTargetDefaultsArray[] = +{ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ + {0x3E,DEV_TARGET_ID}, /* DEVICE_CS0 */ + {0x3D,DEV_TARGET_ID}, /* DEVICE_CS1 */ + {0x3B,DEV_TARGET_ID}, /* DEVICE_CS2 */ + {0x37,DEV_TARGET_ID}, /* DEVICE_CS3 */ + {0x2F,DEV_TARGET_ID}, /* DEV_BOOCS*/ +#if !defined(MV78XX0_Z0) + {0x1F,DEV_TARGET_ID}, /* DEV_SPI*/ +#endif + {0xE0,PCI0_TARGET_ID}, /* PCI0_IO */ + {0xE8,PCI0_TARGET_ID}, /* PCI0_MEM */ + {0xD0,PCI0_TARGET_ID}, /* PCI1_IO */ + {0xD8,PCI0_TARGET_ID}, /* PCI1_MEM */ + {0xB0,PCI0_TARGET_ID}, /* PCI2_IO */ + {0xB8,PCI0_TARGET_ID}, /* PCI2_MEM */ + {0x70,PCI0_TARGET_ID}, /* PCI3_IO */ + {0x78,PCI0_TARGET_ID}, /* PCI3_MEM */ + {0xE0,PCI1_TARGET_ID}, /* PCI4_IO */ + {0xE8,PCI1_TARGET_ID}, /* PCI4_MEM */ + {0xD0,PCI1_TARGET_ID}, /* PCI5_IO */ + {0xD8,PCI1_TARGET_ID}, /* PCI5_MEM */ + {0xB0,PCI1_TARGET_ID}, /* PCI6_IO */ + {0xB8,PCI1_TARGET_ID}, /* PCI6_MEM */ + {0x70,PCI1_TARGET_ID}, /* PCI7_IO */ + {0x78,PCI1_TARGET_ID}, /* PCI7_MEM */ + {0x01,CRYPT_TARGET_ID}, /* CRYPT_ENG */ + {0xFF, 0xFF} /* INTER_REGS */ +}; + +#define CTRL_DEC_BASE_OFFS 16 +#define CTRL_DEC_BASE_MASK (0xffff << CTRL_DEC_BASE_OFFS) +#define CTRL_DEC_BASE_ALIGNMENT 0x10000 + +#define CTRL_DEC_SIZE_OFFS 16 +#define CTRL_DEC_SIZE_MASK (0xffff << CTRL_DEC_SIZE_OFFS) +#define CTRL_DEC_SIZE_ALIGNMENT 0x10000 + +#define CTRL_DEC_WIN_EN BIT0 + + +/******************************************************************************* +* mvCtrlAddrDecToReg - Get address decode register format values +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, MV_DEC_REGS *pAddrDecRegs) +{ + + MV_U32 baseToReg=0 , sizeToReg=0; + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->baseLow & CTRL_DEC_BASE_MASK; + + /* Write to address decode Base Address Register */ + pAddrDecRegs->baseReg &= ~CTRL_DEC_BASE_MASK; + pAddrDecRegs->baseReg |= baseToReg; + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->size, CTRL_DEC_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + return MV_BAD_PARAM; + } + + /* set size */ + pAddrDecRegs->sizeReg &= ~CTRL_DEC_SIZE_MASK; + pAddrDecRegs->sizeReg |= (sizeToReg << CTRL_DEC_SIZE_OFFS); + + + return MV_OK; + +} + + +/******************************************************************************* +* mvCtrlRegToAddrDec - Extract address decode struct from registers. +* +* DESCRIPTION: +* This function extract address decode struct from address decode +* registers given as parameters. +* +* INPUT: +* pAddrDecRegs - Address decode register struct. +* +* OUTPUT: +* pAddrDecWin - Target window data structure. +* +* RETURN: +* MV_BAD_PARAM if address decode registers data is invalid. +* +*******************************************************************************/ +MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 sizeRegVal; + + sizeRegVal = (pAddrDecRegs->sizeReg & CTRL_DEC_SIZE_MASK) >> + CTRL_DEC_SIZE_OFFS; + + pAddrDecWin->size = ctrlRegToSize(sizeRegVal, CTRL_DEC_SIZE_ALIGNMENT); + + + /* Extract base address */ + /* Base register [31:16] ==> baseLow[31:16] */ + pAddrDecWin->baseLow = pAddrDecRegs->baseReg & CTRL_DEC_BASE_MASK; + + pAddrDecWin->baseHigh = 0; + + return MV_OK; + +} + + +/******************************************************************************* +* mvCtrlAddrDecToParams - Get address decode register format values +* +* DESCRIPTION: +* This function returns the given address window information in the +* format of address decode base and size registers. +* +* INPUT: +* pAddrDecWin - Target window data structure. +* +* OUTPUT: +* pWinParam - Address decode window parameters. +* +* RETURN: +* MV_BAD_PARAM if base address is invalid parameter or target is +* unknown. +* +*******************************************************************************/ +MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, + MV_DEC_WIN_PARAMS *pWinParam) +{ + MV_TARGET_ATTRIB targetAttrib; + MV_U32 size; /* Holds BAR size */ + /* 2) Initialize Size register */ + /* 2.1 Get address decode size register value to given size */ + size = ctrlSizeToReg(pAddrDecWin->addrWin.size, BAR_SIZE_ALIGNMENT); + /* Size parameter validity check. */ + if (-1 == size) + { + DB(mvOsPrintf("mvCtrlAddrDecToParams: ERR. addrDecSizeToReg failed.\n")); + return MV_BAD_PARAM; + } + + /* Write the size register value */ + pWinParam->size = size; + /* Base address */ + pWinParam->baseAddr = pAddrDecWin->addrWin.baseLow; + /* attrib and targetId */ + mvCtrlAttribGet(pAddrDecWin->target, &targetAttrib); + pWinParam->attrib = targetAttrib.attrib; + pWinParam->targetId = targetAttrib.targetId; + return MV_OK; + +} + +/******************************************************************************* +* mvCtrlParamsToAddrDec - Extract address decode struct from registers. +* +* DESCRIPTION: +* This function extract address decode struct from address decode +* registers given as parameters. +* +* INPUT: +* pWinParam - Address decode register parameters +* +* OUTPUT: +* pAddrDecWin - Target window data structure. +* +* RETURN: +* MV_BAD_PARAM if address decode registers data is invalid. +* +*******************************************************************************/ +MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam, + MV_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttrib; + + pAddrDecWin->addrWin.baseLow = pWinParam->baseAddr; + + /* Upper 32bit address base is supported under PCI High Address remap */ + pAddrDecWin->addrWin.baseHigh = 0; + + /* Prepare sizeReg to ctrlRegToSize function */ + pAddrDecWin->addrWin.size = ctrlRegToSize(pWinParam->size, BAR_SIZE_ALIGNMENT); + + if (-1 == pAddrDecWin->addrWin.size) + { + DB(mvOsPrintf("mvCtrlParamsToAddrDec: ERR. ctrlRegToSize failed.\n")); + return MV_BAD_PARAM; + } + + /* attrib and targetId */ + targetAttrib.attrib = pWinParam->attrib; + targetAttrib.targetId = pWinParam->targetId; + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + if (MAX_TARGETS == pAddrDecWin->target) + { + DB(mvOsPrintf("mvCtrlParamsToAddrDec: ERR. 0x%x, 0x%x\n",targetAttrib.targetId, targetAttrib.attrib)); + return MV_ERROR; + } + return MV_OK; +} + + +/******************************************************************************* +* mvCtrlAttribGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ + +MV_STATUS mvCtrlAttribGet(MV_TARGET target, MV_TARGET_ATTRIB *targetAttrib) +{ + + targetAttrib->attrib = mvTargetDefaultsArray[target].attrib; + targetAttrib->targetId = mvTargetDefaultsArray[target].targetId; + + return MV_OK; + +} +/******************************************************************************* +* mvCtrlTargetGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib) +{ + MV_TARGET target; + for (target = SDRAM_CS0; target < MAX_TARGETS ; target ++) + { + if ((mvTargetDefaultsArray[target].attrib == targetAttrib->attrib) && + (mvTargetDefaultsArray[target].targetId == targetAttrib->targetId)) + { + /* found it */ + break; + } + } + + return target; +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.h new file mode 100644 index 0000000..6a5b5ac --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAddrDec.h @@ -0,0 +1,126 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCtrlEnvAddrDech +#define __INCmvCtrlEnvAddrDech + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ +#include "mvCtrlEnvLib.h" + +/* defines */ + +typedef struct _mvDecRegs +{ + MV_U32 baseReg; + MV_U32 baseRegHigh; + MV_U32 sizeReg; +} MV_DEC_REGS; + + +/* This structure describes address decode window */ +typedef struct _mvDecWin +{ + MV_TARGET target; /* Target for addr decode window */ + MV_ADDR_WIN addrWin; /* Address window of target */ + MV_BOOL enable; /* Window enable/disable */ +}MV_DEC_WIN; + +typedef struct _mvDecWinParams +{ + MV_TARGET_ID targetId; /* Target ID field */ + MV_U8 attrib; /* Attribute field */ + MV_U32 baseAddr; /* Base address in register format */ + MV_U32 size; /* Size in register format */ +}MV_DEC_WIN_PARAMS; + +typedef struct _mvTargetAttrib +{ + MV_U8 attrib; /* chip select attributes */ + MV_TARGET_ID targetId; /* Target Id of this MV_TARGET */ + +}MV_TARGET_ATTRIB; + +/* mvCtrlEnvAddrDec API list */ +MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, + MV_DEC_REGS *pAddrDecRegs); +MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs, + MV_ADDR_WIN *pAddrDecWin); + +MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, + MV_DEC_WIN_PARAMS *pWinParam); + +MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam, + MV_DEC_WIN *pAddrDecWin); +MV_STATUS mvCtrlAttribGet(MV_TARGET target, MV_TARGET_ATTRIB *targetAttrib); +MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvCtrlEnvAddrDech */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAsm.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAsm.h new file mode 100644 index 0000000..d5a7501 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvAsm.h @@ -0,0 +1,94 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCtrlEnvAsmh +#define __INCmvCtrlEnvAsmh + +#include "pex/mvPexRegs.h" + +/* Read device ID into toReg bits 15:0 from 0xd0000000 */ +/* defines */ +#define NPXDAVI_DEV_ID_OFFS #PXDAVI_DEV_ID_OFFS +#if defined(MV_INCLUDE_PEX) +#define MV_DV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + MV_DV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID));\ + mov toReg, toReg, LSR NPXDAVI_DEV_ID_OFFS /* toReg = toReg >> 16 */ +#else + #error "No Way to get Device ID" +#endif /* MV_INCLUDE_PEX */ + +/* Read Revision into toReg bits 7:0 0xd0000000*/ +#define NPXCCARI_REVID_MASK #PXCCARI_REVID_MASK + +#if defined(MV_INCLUDE_PEX) +#define MV_DV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + /* Read device revision */ \ + MV_DV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_CLASS_CODE_AND_REVISION_ID));\ + and toReg, toReg, NPXCCARI_REVID_MASK /* Mask for calss ID */ +#else + #error "No Way to get Revision ID" +#endif /* MV_INCLUDE_PEX */ + +#endif /* __INCmvCtrlEnvAsmh */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.c new file mode 100644 index 0000000..f5b3aa5 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.c @@ -0,0 +1,1202 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#ifdef MV_INCLUDE_PEX +#include "pex/mvPex.h" +#include "ctrlEnv/sys/mvSysPex.h" +#endif +#include "cpu/mvCpu.h" + +#include "ctrlEnv/sys/mvCpuIf.h" +#include "eth/mvEth.h" +#include "ctrlEnv/sys/mvSysGbe.h" +#ifdef MV_INCLUDE_IDMA +#include "idma/mvIdma.h" +#include "ctrlEnv/sys/mvSysIdma.h" +#endif +#ifdef MV_INCLUDE_XOR +#include "xor/mvXor.h" +#include "ctrlEnv/sys/mvSysXor.h" +#endif +#ifdef MV_INCLUDE_USB +#include "usb/mvUsb.h" +#include "ctrlEnv/sys/mvSysUsb.h" +#endif +#ifdef MV_INCLUDE_SATA +#include "ctrlEnv/sys/mvSysSata.h" +#endif + +#include "device/mvDevice.h" + +#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 + +#define PCCRIR_REVID_OFFS 0 /* Revision ID */ +#define PCCRIR_REVID_MASK (0xff << PCCRIR_REVID_OFFS) + + + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + + +/* Global paramters initial value '-1' to indicate they are uninitialized. */ +/* In case of data section is located in ROM, this value will not be able */ +/* to change. */ +MV_32 ctrlDevModel = -1; +MV_32 ctrlDevRev = -1; + +/******************************************************************************* +* mvCtrlEnvInit - Initialize Marvell controller environment. +* +* DESCRIPTION: +* This function get environment information and initialize controller +* internal/external environment. For example +* 1) MPP settings according to board MPP macros. +* NOTE: It is the user responsibility to shut down all DMA channels +* in device and disable controller sub units interrupts during +* boot process. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvCtrlEnvInit(MV_VOID) +{ + MV_U32 mppGroup; + + /* Read MPP group from board level and assign to MPP register */ + for (mppGroup = 0; mppGroup < MV_MPP_MAX_GROUP; mppGroup++) + { + MV_REG_WRITE(MPP_CONTROL_REG(mppGroup), mvBoardMppGet(mppGroup)); + } + /*Only CPU0 bridge influences the system*/ + MV_REG_BIT_SET(CPU_CTRL_STAT_REG(0), CCSR_PEX0_ENABLE); + MV_REG_BIT_SET(CPU_CTRL_STAT_REG(0), CCSR_PEX1_ENABLE); + return MV_OK; +} + +/******************************************************************************* +* mvCtrlSramSizeGet - Get Marvell controller integrated SRAM size +* +* DESCRIPTION: +* This function returns Marvell controller integrated SRAM size +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlSramSizeGet(MV_VOID) +{ + return 0; +} + +/******************************************************************************* +* mvCtrlPciMaxIfGet - Get Marvell controller number of PCI interfaces. +* +* DESCRIPTION: +* This function returns Marvell controller number of PCI interfaces. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of PCI interfaces. +* +*******************************************************************************/ +MV_U32 mvCtrlPciMaxIfGet(MV_VOID) +{ + return 0; +} + +/******************************************************************************* +* mvCtrlPexMaxIfGet - Get Marvell controller number of PEX interfaces. +* +* DESCRIPTION: +* This function returns Marvell controller number of PEX interfaces. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of PEX interfaces. +* +*******************************************************************************/ +MV_U32 mvCtrlPexMaxIfGet(MV_VOID) +{ + return MV_PEX_MAX_IF; +} + +/******************************************************************************* +* mvCtrlPciIfiMaxIfGet - Get Marvell controller number of PCI interfaces. +* +* DESCRIPTION: +* This function returns Marvell controller number of PCI interfaces. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of PCI interfaces. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlPciIfMaxIfGet(MV_VOID) +{ + return mvCtrlPexMaxIfGet(); +} +/******************************************************************************* +* mvCtrlEthMaxPortGet - Get Marvell controller number of etherent ports. +* +* DESCRIPTION: +* This function returns Marvell controller number of etherent port. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of etherent port. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlEthMaxPortGet(MV_VOID) +{ + if (MV_78200_DEV_ID == mvCtrlModelGet()) + return MV78200_ETH_MAX_PORTS; + + return MV78XX0_ETH_MAX_PORTS; +} + +/******************************************************************************* +* mvCtrlIdmaMaxChanGet - Get Marvell controller number of IDMA channels. +* +* DESCRIPTION: +* This function returns Marvell controller number of IDMA channels. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of IDMA channels. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlIdmaMaxChanGet(MV_VOID) +{ + return MV_IDMA_MAX_CHAN; +} + +/******************************************************************************* +* mvCtrlUsbHostMaxGet - Get number of Marvell Usb controllers +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* returns number of Marvell USB controllers. +* +*******************************************************************************/ +MV_U32 mvCtrlUsbMaxGet(void) +{ + return MV_USB_MAX_CHAN; +} + + +#if defined(MV_INCLUDE_PEX) + +/******************************************************************************* +* mvCtrlModelGet - Get Marvell controller device model (Id) +* +* DESCRIPTION: +* This function returns 16bit describing the device model (ID) as defined +* in PCI Device and Vendor ID configuration register offset 0x0. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit desscribing Marvell controller ID +* +*******************************************************************************/ +MV_U16 mvCtrlModelGet(MV_VOID) +{ + + MV_32 tmpCtrlDevModel; + + /* Check if global variable has already been intialized */ + if (-1 == ctrlDevModel) + { + /* Extract device number */ + tmpCtrlDevModel = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID)); + tmpCtrlDevModel &= PXDAVI_DEV_ID_MASK; + tmpCtrlDevModel = (tmpCtrlDevModel >> PXDAVI_DEV_ID_OFFS); +#ifndef MV_UBOOT + ctrlDevModel = tmpCtrlDevModel; +#endif + } + else + { + tmpCtrlDevModel = ctrlDevModel; + } + + if (MV_78XX0_ZY_DEV_ID == tmpCtrlDevModel) + { + tmpCtrlDevModel = MV_78XX0_DEV_ID; + } + + return (MV_U16)tmpCtrlDevModel; +} + +/******************************************************************************* +* mvCtrlRevGet - Get Marvell controller revision +* +* DESCRIPTION: +* This function returns 16bit describing the device revision as defined +* in PCI Class Code and Revision ID configuration register offset 0x8. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit desscribing Marvell controller revision +* +*******************************************************************************/ +MV_U8 mvCtrlRevGet(MV_VOID) +{ + + MV_32 tmpCtrlDevRev; + + /* Check if global variable has already been intialized */ + if (-1 == ctrlDevRev) + { + tmpCtrlDevRev = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0,PEX_CLASS_CODE_AND_REVISION_ID)); + tmpCtrlDevRev &= PXCCARI_REVID_MASK; + tmpCtrlDevRev = (tmpCtrlDevRev >> PXCCARI_REVID_OFFS); +#ifndef MV_UBOOT + ctrlDevRev = tmpCtrlDevRev; +#endif + } + else + { + tmpCtrlDevRev = ctrlDevRev; + } + + return (MV_U8)tmpCtrlDevRev; +} + + +#else +/******************************************************************************* +* mvCtrlModelGet - Get Marvell controller device model (Id) +* +* DESCRIPTION: +* This function returns 16bit describing the device model (ID) as defined +* in PCI Device and Vendor ID configuration register offset 0x0. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit desscribing Marvell controller ID +* +*******************************************************************************/ +MV_U16 mvCtrlModelGet(MV_VOID) +{ + MV_U32 localBusNum; + MV_U32 localDevNum; + MV_U32 pciData; + MV_32 tmpCtrlDevModel; + MV_BOOL ifPwrOn; + /* Check if global variable has already been intialized */ + /* In U-boot we are still in the flash so we skeep it */ +#ifndef MV_UBOOT + if (-1 == ctrlDevModel) + { +#endif + ifPwrOn = mvCtrlPwrClckGet(PEX_UNIT_ID, PEX_DEFAULT_IF); + if (MV_FALSE == ifPwrOn) + { + mvCtrlPwrClckSet(PEX_UNIT_ID, PEX_DEFAULT_IF, MV_TRUE); + } + /* Get PCI local bus number */ + localBusNum = mvPciLocalBusNumGet(PEX_DEFAULT_IF); + /* Get PCI local dev number */ + localDevNum = mvPciLocalDevNumGet(PEX_DEFAULT_IF); + + /* Read configuration register 0 */ + pciData=mvPciConfigRead(PEX_DEFAULT_IF, localBusNum, localDevNum, 0, 0); + + /* Extract device number */ + tmpCtrlDevModel = ((pciData & PDVIR_DEV_ID_MASK) >> PDVIR_DEV_ID_OFFS); + if (MV_FALSE == ifPwrOn) + { + mvCtrlPwrClckSet(PEX_UNIT_ID, PEX_DEFAULT_IF, MV_FALSE); + } +#ifndef MV_UBOOT + ctrlDevModel = tmpCtrlDevModel; + } + else + { + tmpCtrlDevModel = ctrlDevModel; + } +#endif + if (MV_78XX0_ZY_DEV_ID == tmpCtrlDevModel) + { + tmpCtrlDevModel = MV_78XX0_DEV_ID; + } + + return (MV_U16)tmpCtrlDevModel; +} + +/******************************************************************************* +* mvCtrlRevGet - Get Marvell controller revision +* +* DESCRIPTION: +* This function returns 16bit describing the device revision as defined +* in PCI Class Code and Revision ID configuration register offset 0x8. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit desscribing Marvell controller revision +* +*******************************************************************************/ +MV_U8 mvCtrlRevGet(MV_VOID) +{ + MV_U32 localBusNum; + MV_U32 localDevNum; + MV_U32 pciData; + MV_32 tmpCtrlDevRev; + + /* Check if global variable has already been intialized */ + if (-1 == ctrlDevRev) + { + //MV_BOOL ifPwrOn = mvCtrlPwrClckGet(PEX_UNIT_ID, pciIf); + //if (MV_FALSE == ifPwrOn) + { + // mvCtrlPwrClckSet(PEX_UNIT_ID, PEX_DEFAULT_IF, MV_TRUE); + } + /* Get PCI local bus number */ + localBusNum = mvPciLocalBusNumGet(PEX_DEFAULT_IF); + /* Get PCI local dev number */ + localDevNum = mvPciLocalDevNumGet(PEX_DEFAULT_IF); + + /* Read configuration register 8 */ + pciData=mvPciConfigRead(PEX_DEFAULT_IF, localBusNum, localDevNum, 0, 8); + + /* Extract revision number */ + tmpCtrlDevRev = ((pciData & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS); + + ctrlDevRev = tmpCtrlDevRev; + } + //if (MV_FALSE == ifPwrOn) + //{ + // mvCtrlPwrClckSet(PEX_UNIT_ID, pciIf, MV_FALSE); + //} + } + else + { + tmpCtrlDevRev = ctrlDevRev; + } + + return (MV_U8)tmpCtrlDevRev; +} + +#endif + +/******************************************************************************* +* mvCtrlModelRevGet - Get Controller Model (Device ID) and Revision +* +* DESCRIPTION: +* This function returns 32bit value describing both Device ID and Revision +* as defined in PCI Express Device and Vendor ID Register and device revision +* as defined in PCI Express Class Code and Revision ID Register. + +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing both controller device ID and revision number +* +*******************************************************************************/ +MV_U32 mvCtrlModelRevGet(MV_VOID) +{ +#ifndef MV_UBOOT + if (-1 == ctrlDevModel) + ctrlDevModel = mvCtrlModelGet(); + return ((ctrlDevModel << 16) | mvCtrlRevGet()); +#else + return ((mvCtrlModelGet() << 16) | mvCtrlRevGet()); +#endif +} + + +/******************************************************************************* +* mvCtrlNameGet - Get Marvell controller name +* +* DESCRIPTION: +* This function returns a string describing the device model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain device name string. Minimum size 30 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ +MV_STATUS mvCtrlNameGet(char *pNameBuff) +{ +#ifndef MV_UBOOT + if (-1 == ctrlDevModel) + ctrlDevModel = mvCtrlModelGet(); + switch(ctrlDevModel) { +#else + switch(mvCtrlModelGet()) { +#endif + case MV_78XX0_DEV_ID: + sprintf (pNameBuff, "%s", MV_78XX0_NAME); + break; + case MV_78100_DEV_ID: + sprintf (pNameBuff, "%s", MV_78100_NAME); + break; + case MV_78200_DEV_ID: + sprintf (pNameBuff, "%s", MV_78200_NAME); + break; + default: + sprintf (pNameBuff, "Controller device ID 0x%x unknown.\n", mvCtrlModelGet()); + return MV_ERROR; + } + + return MV_OK; +} + +/******************************************************************************* +* mvCtrlNameGet - Get Marvell controller name +* +* DESCRIPTION: +* This function returns a string describing the device model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain device name string. Minimum size 30 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ + +MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff) +{ + switch (mvCtrlModelRevGet()) + { + case MV_78XX0_Z0_ID: + mvOsSPrintf (pNameBuff, "%s", MV_78XX0_Z0_NAME); + break; + case MV_78XX0_Y0_ID: + mvOsSPrintf (pNameBuff, "%s", MV_78XX0_Y0_NAME); + break; + case MV_78100_A0_ID: + mvOsSPrintf (pNameBuff, "%s", MV_78100_A0_NAME); + break; + case MV_78200_A0_ID: + mvOsSPrintf (pNameBuff, "%s", MV_78200_A0_NAME); + break; + default: + mvCtrlNameGet(pNameBuff); + break; + } + + + return MV_OK; +} + +/******************************************************************************* +* mvCtrlMppRegGet - return reg address of mpp group +* +* DESCRIPTION: +* +* INPUT: +* mppGroup - MPP group. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_U32 - Register address. +* +*******************************************************************************/ +MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup) +{ + return MPP_CONTROL_REG(mppGroup); +} + +/******************************************************************************* +* ctrlWinOverlapTest - Test address windows for overlaping. +* +* DESCRIPTION: +* This function checks the given two address windows for overlaping. +* +* INPUT: +* pAddrWin1 - Address window 1. +* pAddrWin2 - Address window 2. +* +* OUTPUT: +* None. +* +* RETURN: +* +* MV_TRUE if address window overlaps, MV_FALSE otherwise. +*******************************************************************************/ +MV_STATUS ctrlWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2) +{ + MV_U32 winBase1, winBase2; + MV_U32 winTop1, winTop2; + + winBase1 = pAddrWin1->baseLow; + winBase2 = pAddrWin2->baseLow; + winTop1 = winBase1 + pAddrWin1->size; + winTop2 = winBase2 + pAddrWin2->size; + + if (((winBase1 < winTop2 ) && ( winTop2 < winTop1)) || + ((winBase1 < winBase2) && (winBase2 < winTop1))) + { + return MV_TRUE; + } + else + { + return MV_FALSE; + } +} + +/******************************************************************************* +* ctrlWinWithinWinTest - Test address windows for overlaping. +* +* DESCRIPTION: +* This function checks the given win1 boundries is within +* win2 boundries. +* +* INPUT: +* pAddrWin1 - Address window 1. +* pAddrWin2 - Address window 2. +* +* OUTPUT: +* None. +* +* RETURN: +* +* MV_TRUE if found win1 inside win2, MV_FALSE otherwise. +*******************************************************************************/ +MV_STATUS ctrlWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2) +{ + MV_U32 winBase1, winBase2; + MV_U32 winTop1, winTop2; + + winBase1 = pAddrWin1->baseLow; + winBase2 = pAddrWin2->baseLow; + winTop1 = winBase1 + pAddrWin1->size -1; + winTop2 = winBase2 + pAddrWin2->size -1; + + if (((winBase1 >= winBase2 ) && ( winBase1 <= winTop2)) || + ((winTop1 >= winBase2) && (winTop1 <= winTop2))) + { + return MV_TRUE; + } + else + { + return MV_FALSE; + } +} + +/******************************************************************************* +* mvCtrlTargetNameGet - Get Marvell controller target name +* +* DESCRIPTION: +* This function convert the trget enumeration to string. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Target name (const MV_8 *) +*******************************************************************************/ +const MV_8* mvCtrlTargetNameGet( MV_TARGET target ) +{ + switch( target ) + { + case SDRAM_CS0: + return "SDRAM_CS0...."; + case SDRAM_CS1: + return "SDRAM_CS1...."; + case SDRAM_CS2: + return "SDRAM_CS2...."; + case SDRAM_CS3: + return "SDRAM_CS3...."; + case DEVICE_CS0: + return "DEVICE_CS0..."; + case DEVICE_CS1: + return "DEVICE_CS1..."; + case DEVICE_CS2: + return "DEVICE_CS2..."; + case DEVICE_CS3: + return "DEVICE_CS3..."; +#if !defined (MV78XX0_Z0) + case SPI_CS: + return "DEVICE_SPI..."; +#endif + case DEV_BOOCS: + return "DEV_BOOCS...."; + case PCI0_IO: + return "PEX0_IO......"; + case PCI0_MEM0: + return "PEX0_MEM0...."; + case PCI1_IO: + return "PEX1_IO......"; + case PCI1_MEM0: + return "PEX1_MEM0...."; + case PCI2_IO: + return "PEX2_IO......"; + case PCI2_MEM0: + return "PEX2_MEM0...."; + case PCI3_IO: + return "PEX3_IO......"; + case PCI3_MEM0: + return "PEX3_MEM0...."; + case PCI4_IO: + return "PEX4_IO......"; + case PCI4_MEM0: + return "PEX4_MEM0...."; + case PCI5_IO: + return "PEX5_IO......"; + case PCI5_MEM0: + return "PEX5_MEM0...."; + case PCI6_IO: + return "PEX6_IO......"; + case PCI6_MEM0: + return "PEX6_MEM0...."; + case PCI7_IO: + return "PEX7_IO......"; + case PCI7_MEM0: + return "PEX7_MEM0...."; + case CRYPT_ENG: + return "CRYPT_ENG....."; + case INTER_REGS: + return "INTER_REGS..."; + case USB_IF: + return "USB_IF......."; + default: + return "target unknown"; + } +} + +/******************************************************************************* +* mvCtrlAddrDecShow - Print the Controller units address decode map. +* +* DESCRIPTION: +* This function the Controller units address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvCtrlAddrDecShow(MV_VOID) +{ + mvCpuIfAddrDecShow(whoAmI()); +#ifdef MV_INCLUDE_PEX + mvPexAddrDecShow(); +#endif +#ifdef MV_INCLUDE_IDMA + mvDmaAddrDecShow(); +#endif + mvEthAddrDecShow(); +#ifdef MV_INCLUDE_XOR + mvXorAddrDecShow(); +#endif +#ifdef MV_INCLUDE_SATA + mvSataAddrDecShow(); +#endif +#ifdef MV_INCLUDE_USB + mvUsbAddrDecShow(); +#endif +} + +/******************************************************************************* +* ctrlSizeToReg - Extract size value for register assignment. +* +* DESCRIPTION: +* Address decode size parameter must be programed from LSB to MSB as +* sequence of 1's followed by sequence of 0's. The number of 1's +* specifies the size of the window in 64 KB granularity (e.g. a +* value of 0x00ff specifies 256x64k = 16 MB). +* This function extract the size value from the size parameter according +* to given aligment paramter. For example for size 0x1000000 (16MB) and +* aligment 0x10000 (64KB) the function will return 0x00FF. +* +* INPUT: +* size - Size. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size register value correspond to size parameter. +* If value is '-1' size parameter or aligment are invalid. +*******************************************************************************/ +MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment) +{ + MV_U32 retVal; + + /* Check size parameter alignment */ + if ((0 == size) || (MV_IS_NOT_ALIGN(size, alignment))) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Size is zero or not aligned.\n")); + return -1; + } + + /* Take out the "alignment" portion out of the size parameter */ + alignment--; /* Now the alignmet is a sequance of '1' (e.g. 0xffff) */ + /* and size is 0x1000000 (16MB) for example */ + while(alignment & 1) /* Check that alignmet LSB is set */ + { + size = (size >> 1); /* If LSB is set, move 'size' one bit to right */ + alignment = (alignment >> 1); + } + + /* If after the alignment first '0' was met we still have '1' in */ + /* it then aligment is invalid (not power of 2) */ + if (alignment) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", + (MV_U32)alignment)); + return -1; + } + + /* Now the size is shifted right according to aligment: 0x0100 */ + size--; /* Now the size is a sequance of '1': 0x00ff */ + + retVal = size ; + + /* Check that LSB to MSB is sequence of 1's followed by sequence of 0's */ + while(size & 1) /* Check that LSB is set */ + { + size = (size >> 1); /* If LSB is set, move one bit to the right */ + } + + if (size) /* Sequance of 1's is over. Check that we have no other 1's */ + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Size parameter 0x%x invalid.\n", + size)); + return -1; + } + + return retVal; + +} + +/******************************************************************************* +* ctrlRegToSize - Extract size value from register value. +* +* DESCRIPTION: +* This function extract a size value from the register size parameter +* according to given aligment paramter. For example for register size +* value 0xff and aligment 0x10000 the function will return 0x01000000. +* +* INPUT: +* regSize - Size as in register format. See ctrlSizeToReg. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size. +* If value is '-1' size parameter or aligment are invalid. +*******************************************************************************/ +MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment) +{ + MV_U32 temp; + if (0 == regSize) + { + return 0; + } + /* Check that LSB to MSB is sequence of 1's followed by sequence of 0's */ + temp = regSize; /* Now the size is a sequence of '1': 0x00ff */ + + while(temp & 1) /* Check that LSB is set */ + { + temp = (temp >> 1); /* If LSB is set, move one bit to the right */ + } + + if (temp) /* Sequence of 1's is over. Check that we have no other 1's */ + { + DB(mvOsPrintf("ctrlRegToSize: ERR. Size parameter 0x%x invalid.\n", + regSize)); + return -1; + } + + + /* Check that aligment is a power of two */ + temp = alignment - 1;/* Now the alignmet is a sequance of '1' (0xffff) */ + + while(temp & 1) /* Check that alignmet LSB is set */ + { + temp = (temp >> 1); /* If LSB is set, move 'size' one bit to right */ + } + + /* If after the 'temp' first '0' was met we still have '1' in 'temp' */ + /* then 'temp' is invalid (not power of 2) */ + if (temp) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", + alignment)); + return -1; + } + + regSize++; /* Now the size is 0x0100 */ + + /* Add in the "alignment" portion to the register size parameter */ + alignment--; /* Now the alignmet is a sequance of '1' (e.g. 0xffff) */ + + while(alignment & 1) /* Check that alignmet LSB is set */ + { + regSize = (regSize << 1); /* LSB is set, move 'size' one bit left */ + alignment = (alignment >> 1); + } + + return regSize; +} + + +/******************************************************************************* +* ctrlSizeRegRoundUp - Round up given size +* +* DESCRIPTION: +* This function round up a given size to a size that is a power of 2. +* For example, for size parameter 0xa1000 and aligment 0x1000 the +* function will return 0x100000. For size parametr 0x200 and aligment +* 0x10000 the function will return 0x10000. +* +* INPUT: +* size - Size. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size value correspond to size in register. +*******************************************************************************/ +MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment) +{ + MV_U32 msbBit = 0; + MV_U32 retSize; + + /* Check if size parameter is already comply with restriction */ + if (!(-1 == ctrlSizeToReg(size, alignment))) + { + return size; + } + while(size) + { + size = (size >> 1); + msbBit++; + } + retSize = (1 << msbBit); + + if (retSize < alignment) + { + return alignment; + } + else + { + return retSize; + } +} + + +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +/******************************************************************************* +* mvCtrlPwrClckSet - Set Power State for specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +*******************************************************************************/ +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable) +{ + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_PEX_MASK(index)); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG,PMC_PEX_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_GE_MASK(index)); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_GE_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_INTEG_SATA) + case SATA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SATA_MASK(index)); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SATA_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SE_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SE_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_USB_MASK(index)); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_USB_MASK(index)); + } + break; +#endif + default: + break; + } +} + +/******************************************************************************* +* mvCtrlPwrClckGet - Get Power State of specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +******************************************************************************/ +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index) +{ + MV_U32 reg = MV_REG_READ(POWER_MNG_CTRL_REG); + MV_BOOL state = MV_TRUE; + + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if (0 == (reg & PMC_PEX_UP(index))) + { + state = MV_FALSE; + } + else state = MV_TRUE; + + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if (0 == (reg & PMC_GE_UP(index))) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_SATA) + case SATA_UNIT_ID: + if (0 == (reg & PMC_SATA_UP(index))) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if (0 == (reg & PMC_SE_UP)) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if (0 == (reg & PMC_USB_UP(index))) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif + default: + state = MV_TRUE; + break; + } + return state; +} +#else +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable) {return;} +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index) {return MV_TRUE;} +#endif /* #if defined(MV_INCLUDE_CLK_PWR_CNTRL) */ + + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.h new file mode 100644 index 0000000..f641ffe --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvLib.h @@ -0,0 +1,159 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCtrlEnvLibh +#define __INCmvCtrlEnvLibh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ +#include "mvSysHwConfig.h" +#include "mvCommon.h" +#include "mvTypes.h" +#include "mvOs.h" +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/sys/mvCpuIfRegs.h" + +/* defines */ + +#define PCI0_IS_QUAD_X1 (MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & 0x8) +#define PCI1_IS_QUAD_X1 (MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & 0x10) +#if defined(MV78200) + #define IS_CPU1_ENABLED (MV_REG_READ(CPU_RESET_SAMPLE_L_REG) & (0x100000)) +#endif + +/* typedefs */ + +/* This enumerator describes the possible HW cache coherency policies the */ +/* controllers supports. */ +typedef enum _mvCachePolicy +{ + NO_COHERENCY, /* No HW cache coherency support */ + WT_COHERENCY, /* HW cache coherency supported in Write Through policy */ + WB_COHERENCY /* HW cache coherency supported in Write Back policy */ +}MV_CACHE_POLICY; + +/* The swapping is referred to a 64-bit words (as this is the controller */ +/* internal data path width). This enumerator describes the possible */ +/* data swap types. Below is an example of the data 0x0011223344556677 */ +typedef enum _mvSwapType +{ + MV_BYTE_SWAP, /* Byte Swap 77 66 55 44 33 22 11 00 */ + MV_NO_SWAP, /* No swapping 00 11 22 33 44 55 66 77 */ + MV_BYTE_WORD_SWAP, /* Both byte and word swap 33 22 11 00 77 66 55 44 */ + MV_WORD_SWAP, /* Word swap 44 55 66 77 00 11 22 33 */ + SWAP_TYPE_MAX /* Delimiter for this enumerator */ +}MV_SWAP_TYPE; + +/* This structure describes access rights for Access protection windows */ +/* that can be found in IDMA, XOR, Ethernet etc. */ +/* Note that the permission enumerator coresponds to its register format. */ +/* For example, Read only premission is presented as "1" in register field. */ +typedef enum _mvAccessRights +{ + NO_ACCESS_ALLOWED = 0, /* No access allowed */ + READ_ONLY = 1, /* Read only permission */ + ACC_RESERVED = 2, /* Reserved access right */ + FULL_ACCESS = 3, /* Read and Write permission */ + MAX_ACC_RIGHTS +}MV_ACCESS_RIGHTS; + +/* mcspLib.h API list */ +MV_STATUS mvCtrlEnvInit(MV_VOID); +MV_U32 mvCtrlSramSizeGet(MV_VOID); +MV_U32 mvCtrlPciMaxIfGet(MV_VOID); +MV_U32 mvCtrlPexMaxIfGet(MV_VOID); +MV_U32 mvCtrlPciIfMaxIfGet(MV_VOID); +MV_U32 mvCtrlEthMaxPortGet(MV_VOID); +MV_U32 mvCtrlIdmaMaxChanGet(MV_VOID); +MV_U32 mvCtrlUsbMaxGet(MV_VOID); +MV_U32 mvCtrlNandSupport(MV_VOID); +MV_U16 mvCtrlModelGet(MV_VOID); +MV_U8 mvCtrlRevGet(MV_VOID); +MV_U32 mvCtrlModelRevGet(MV_VOID); +MV_STATUS mvCtrlNameGet(char *pNameBuff); +MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff); +MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup); + +MV_VOID mvCtrlAddrDecShow(MV_VOID); +const MV_8* mvCtrlTargetNameGet( MV_TARGET ); + +MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment); +MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment); +MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment); +MV_STATUS ctrlWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2); +MV_STATUS ctrlWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2); + +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable); +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index); +MV_U32 mvCtrlPexIfBaseGet(MV_U32 pexIf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvCtrlEnvLibh */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvSpec.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvSpec.h new file mode 100644 index 0000000..c7bc087 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/mvCtrlEnvSpec.h @@ -0,0 +1,462 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCtrlEnvSpech +#define __INCmvCtrlEnvSpech + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ +#include "mvDeviceId.h" + +#define SOC_NAME_PREFIX "MV" + +#define INTER_REGS_SIZE _1M + +#define MV78XX0_ETH_MAX_PORTS 2 +#define MV78200_ETH_MAX_PORTS 4 + +#define INTERNAL_REG_BASE_DEFAULT 0xD0000000 + + +/* Define Register base adress for each unit */ + +#if defined(MV78200) + #define MV_MAX_CPU 2 + #define CPU_IF_BASE(cpu) (0x20000 + ((cpu) << 14)) +#else + #define MV_MAX_CPU 1 + #define CPU_IF_BASE(cpu) 0x20000 +#endif + +#define AHB_TO_MBUS_BASE CPU_IF_BASE + +#define DRAM_BASE 0x00000 +#define DEVICE_BUS_BASE 0x10000 + +#if defined(MV_ASMLANGUAGE) + #define PEX_IF_BASE(pexIf) 0x40000 +#else + #define PEX_IF_BASE(pexIf) (((pexIf) < 4) ? \ + (0x40000 + (pexIf) * 0x4000) : \ + (0x80000 + ((pexIf) - 4) * 0x4000)) +#endif + +#define MV_ETH_VERSION 3 +#define MV_ETH_MAX_RXQ 8 +#define MV_ETH_MAX_TXQ 8 +#define MV_ETH_MAX_PORTS 4 + +#define MV_ETH_REG_BASE(port) ((((port) < 2)? 0x72000 : 0x32000) \ + + (0x4000*(port & 1))) +#define INT_CTRL_BASE 0x20200 +#define CNTMR_BASE 0x20300 +#define USB_REG_BASE(dev) (0x50000 + (0x1000*(dev))) + +#define IDMA_UNIT_BASE 0x60800 +#define XOR_UNIT_BASE(unit) 0x60900 + +#define WD_BASE 0x10000 +#define TWSI_SLAVE_BASE(chanNum) (0x11000 + (0x100 * (chanNum))) + +#define GPP_BASE 0x10000 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (0x100 * (chanNum))) +#define MPP_BASE 0x10000 +#define SATA_REG_BASE 0xA0000 + +/* MPP control registers offsets */ +#define MPP_CONTROL_REG(groupNum) (MPP_BASE + ((groupNum) * 4)) + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ +#define MV_MPP_MAX_GROUP 7 + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 4 + +#define MV_SATA_MAX_CHAN 2 +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + +/* This define describes the maximum number of available XOR channels. */ +#define MV_XOR_MAX_UNIT 1 +#define MV_XOR_MAX_CHAN_PER_UNIT 2 +#define MV_XOR_MAX_CHAN 2 + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_MAX_IF 0 +#define MV_PCI_START_IF 0 + +/* This define describes the maximum number of supported PEX Interfaces */ +#define MV_DISABLE_PEX_DEVICE_BAR +#define MV_PEX_START_IF MV_PCI_MAX_IF + +/* This define describes the maximum number of supported PEX & PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) +#define MV_PEX_MAX_IF 8 +#define PEX_DEFAULT_IF 0 +#define MV_INCLUDE_PEX1 +#define MV_INCLUDE_PEX2 +#define MV_INCLUDE_PEX3 +#define PEX0_MEM PCI0_MEM0 +#define PEX1_MEM PCI1_MEM0 +#define PEX2_MEM PCI2_MEM0 +#define PEX3_MEM PCI3_MEM0 +/* This define describes the maximum number of available USB channels. */ +#define MV_USB_MAX_CHAN 3 +#define MV_USB_VERSION 1 + +/* CESA version #2: One channel, 2KB SRAM, TDMA */ +#define MV_CESA_VERSION 2 +#define MV_CESA_REG_BASE 0x9D000 +#define MV_CESA_TDMA_REG_BASE 0x90000 +#define MV_CESA_SRAM_SIZE 2*1024 + +/* main interrupt */ +#define MV_TWSI_MAX_CHAN 2 +#define TWSI_CPU_MAIN_INT_CAUSE_REG CPU_INT_LOW_REG(whoAmI()) +#define TWSI0_CPU_MAIN_INT_BIT 0x4 +#define TWSI1_CPU_MAIN_INT_BIT 0x8 + + +/* These macros help units to identify a target Xbar group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEV_BOOCS)) + +#define MV_TARGET_IS_PCI0(target) \ + ((target >= PCI0_IO) && (target <= PCI0_MEM0)) + +#define MV_TARGET_IS_PCI1(target) \ + ((target >= PCI1_IO) && (target <= PCI1_MEM0)) + +#define MV_TARGET_IS_PCI2(target) \ + ((target >= PCI2_IO) && (target <= PCI2_MEM0)) + +#define MV_TARGET_IS_PCI3(target) \ + ((target >= PCI3_IO) && (target <= PCI3_MEM0)) + +#define MV_TARGET_IS_PCI4(target) \ + ((target >= PCI4_IO) && (target <= PCI4_MEM0)) + +#define MV_TARGET_IS_PCI5(target) \ + ((target >= PCI5_IO) && (target <= PCI5_MEM0)) +/*No conventional PCI*/ +#define MV_TARGET_IS_PEX(target) 1 +#define MV_TARGET_IS_PCI(target) 0 + +#define MV_TARGET_IS_PCI_IO(target) \ + ((target == PCI0_IO) || (target == PCI1_IO)|| (target == PCI2_IO) || \ + (target == PCI3_IO) || (target == PCI4_IO)|| (target == PCI5_IO)) + +#define MV_TARGET_IS_AS_BOOT(target) (0) + +#define MV_CHANGE_BOOT_CS(target) ((target) == DEV_BOOCS)?\ + sampleAtResetTargetArray[((MV_REG_READ(CPU_RESET_SAMPLE_L_REG)\ + & MSAR_BOOTDEV_MASK) >> MSAR_BOOTDEV_OFFS)]\ + :(target) +#if !defined(MV78XX0_Z0) +#define BOOT_TARGETS_NAME_ARRAY { \ + DEV_BOOCS, \ + SPI_CS, \ + TBL_TERM, \ +} +#else +#define BOOT_TARGETS_NAME_ARRAY { \ + DEV_BOOCS, \ + TBL_TERM, \ +} +#endif + +#if defined (MV_INCLUDE_PEX) + #define PCI_IF0_MEM0 PEX0_MEM + #define PCI_IF0_IO PEX0_IO +#endif + + + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ + +/* MV78XX0 sample @ reset registers offsets */ +/*******************************************/ +#define CPU_RESET_SAMPLE_L_REG (0x10030) +#define CPU_RESET_SAMPLE_H_REG (0x10034) +/* S@R Register low */ +#define MSAR_SYSCLCK_OFFS 5 +#define MSAR_SYSCLCK_MASK (0x7 << MSAR_SYSCLCK_OFFS) +#define MSAR_SYSCLCK_200 (0x1 << MSAR_SYSCLCK_OFFS) +#define MSAR_SYSCLCK_267 (0x2 << MSAR_SYSCLCK_OFFS) +#define MSAR_SYSCLCK_333 (0x3 << MSAR_SYSCLCK_OFFS) +#define MSAR_SYSCLCK_400 (0x4 << MSAR_SYSCLCK_OFFS) +#define MSAR_SYSCLCK_250 (0x5 << MSAR_SYSCLCK_OFFS) +#define MSAR_SYSCLCK_300 (0x6 << MSAR_SYSCLCK_OFFS) + +#define MSAR_SYSCLK2CPU_OFFS 8 +#define MSAR_SYSCLK2CPU_MASK (0xF << MSAR_SYSCLK2CPU_OFFS) +/* 1_5 == sysclk * 1.5 */ +#define MSAR_SYSCLK2CPU_1 (0x0 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_1_5 (0x1 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_2 (0x2 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_2_5 (0x3 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_3 (0x4 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_3_5 (0x5 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_4 (0x6 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_4_5 (0x7 << MSAR_SYSCLK2CPU_OFFS) +#define MSAR_SYSCLK2CPU_5 (0x8 << MSAR_SYSCLK2CPU_OFFS) + +#define MSAR_CPUL2CLK_OFFS 12 +#define MSAR_CPUL2CLK_MASK (0x3 << MSAR_CPUL2CLK_OFFS) +#define MSAR_CPUL2CLK_1 (0x0 << MSAR_CPUL2CLK_OFFS) +#define MSAR_CPUL2CLK_2 (0x1 << MSAR_CPUL2CLK_OFFS) + +#define MSAR_BOOTDEV_OFFS 23 +#define MSAR_BOOTDEV_MASK (0x3 << MSAR_BOOTDEV_OFFS) +#define MSAR_BOOTDEV_FLASH (0x0 << MSAR_BOOTDEV_OFFS) +#define MSAR_BOOTDEV_SPI (0x1 << MSAR_BOOTDEV_OFFS) +#define MSAR_BOOTDEV_DCE_NAND (0x2 << MSAR_BOOTDEV_OFFS) +#define MSAR_BOOTDEV_CE_NAND (0x3 << MSAR_BOOTDEV_OFFS) + +#define MSAR_CPU1_EN_OFFS 20 +#define MSAR_CPU1_EN_MASK (0x1 << MSAR_CPU1_EN_OFFS) +#define MSAR_CPU1_DIS (0x0 << MSAR_CPU1_EN_OFFS) +#define MSAR_CPU1_EN (0x1 << MSAR_CPU1_EN_OFFS) + +/* S@R Register high */ +#define MSAR_TCLCK_MODE_OFFS 6 +#define MSAR_TCLCK_MODE_MASK (0x1 << MSAR_TCLCK_MODE_OFFS) +#define MSAR_TCLCK_MODE_EXT (0x0 << MSAR_TCLCK_MODE_OFFS) +#define MSAR_TCLCK_MODE_PLL (0x1 << MSAR_TCLCK_MODE_OFFS) +#define MSAR_TCLCK_OFFS 7 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_167 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_200 (0x1 << MSAR_TCLCK_OFFS) + +/* CPU system reset mask register */ +#define CPU_RESET_OUT_MASK_REG (CPU_IF_BASE(whoAmI())+0x108) +#define CPU_PEX_RESET_OUT_MASK_OFF 0 +#define CPU_PEX_RESET_OUT_MASK (0x1 << CPU_PEX_RESET_OUT_MASK_OFF) +#define CPU_WD_RESET_OUT_MASK_OFF 1 +#define CPU_WD_RESET_OUT_MASK (0x1 << CPU_WD_RESET_OUT_MASK_OFF) +#define CPU_SOFT_RESET_OUT_MASK_OFF 2 +#define CPU_SOFT_RESET_OUT_MASK (0x1 << CPU_SOFT_RESET_OUT_MASK_OFF) + +/* CPU soft system reset register */ +#define CPU_SOFT_RESET_OUT_REG (CPU_IF_BASE(whoAmI())+0x10C) +#define CPU_SOFT_RESET_OUT_OFF 0 +#define CPU_SOFT_RESET_OUT (0x1 << CPU_SOFT_RESET_OUT_OFF) + + +#define POWER_MNG_CTRL_REG (CPU_IF_BASE(whoAmI())+0x11C) + +#define PMC_GE_OFFS(port) ((port)+1) +#define PMC_GE_MASK(port) (1 << PMC_GE_OFFS(port)) +#define PMC_GE_UP(port) (1 << PMC_GE_OFFS(port)) + +#define PMC_PEX_OFFS(port) ((port)+5) +#define PMC_PEX_MASK(port) (1 << PMC_PEX_OFFS(port)) +#define PMC_PEX_UP(port) (1 << PMC_PEX_OFFS(port)) + +#define PMC_SATA_OFFS(port) (((port)<<1)+14) +#define PMC_SATA_MASK(port) (1 << PMC_SATA_OFFS(port)) +#define PMC_SATA_UP(port) (1 << PMC_SATA_OFFS(port)) + +#define PMC_USB_OFFS(port) ((port)+17) +#define PMC_USB_MASK(port) (1 << PMC_USB_OFFS(port)) +#define PMC_USB_UP(port) (1 << PMC_USB_OFFS(port)) + +#define PMC_SE_OFFS 22 +#define PMC_SE_MASK (1 << PMC_SE_OFFS) +#define PMC_SE_UP (1 << PMC_SE_OFFS) + + + +/* typedefs */ + +#ifndef MV_ASMLANGUAGE + +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ + +typedef enum _mvTarget +{ + TBL_TERM=-1, /* Invalid Target*/ + SDRAM_CS0, /* 0 SDRAM chip select 0 */ + SDRAM_CS1, /* 1 SDRAM chip select 1 */ + SDRAM_CS2, /* 2 SDRAM chip select 2 */ + SDRAM_CS3, /* 3 SDRAM chip select 3 */ + DEVICE_CS0, /* 4 Device chip select 0 */ + DEVICE_CS1, /* 5 Device chip select 1 */ + DEVICE_CS2, /* 6 Device chip select 2 */ + DEVICE_CS3, /* 7 Device chip select 3 */ + DEV_BOOCS, /* 8 Boot device chip select */ +#if !defined(MV78XX0_Z0) + SPI_CS, /* x SPI device chip select */ +#endif + PCI0_IO, /* 9 PCI 0 IO */ + PCI0_MEM0, /* 10 PCI 0 memory 0 */ + PCI1_IO, /* 11 PCI 1 IO */ + PCI1_MEM0, /* 12 PCI 1 memory 0 */ + PCI2_IO, /* 13 PCI 2 IO */ + PCI2_MEM0, /* 14 PCI 2 memory 0 */ + PCI3_IO, /* 15 PCI 3 IO */ + PCI3_MEM0, /* 16 PCI 3 memory 0 */ + PCI4_IO, /* 17 PCI 4 IO */ + PCI4_MEM0, /* 18 PCI 4 memory 0 */ + PCI5_IO, /* 19 PCI 4 IO */ + PCI5_MEM0, /* 20 PCI 4 memory 0 */ + PCI6_IO, /* 21 PCI 4 IO */ + PCI6_MEM0, /* 22 PCI 4 memory 0 */ + PCI7_IO, /* 23 PCI 4 IO */ + PCI7_MEM0, /* 24 PCI 4 memory 0 */ + CRYPT_ENG, /* 25 Crypto Engine - map to bar 4 without remap */ + INTER_REGS, /* 26 Internal registers */ + MAX_TARGETS, + USB_IF, /* USB interface. Note: This is a logic target! */ +}MV_TARGET; + +#define SDRAM_CS(dramScNum) (SDRAM_CS0 + dramScNum) +#define DEVICE_CS(devNum) (DEVICE_CS0 + devNum) +#define PCI_IO(pciIf) (PCI0_IO + (2 * pciIf)) +#define PCI_MEM(pciIf, memNum) (PCI0_MEM0 + (2 * pciIf)) +/* convert device number to its target number */ +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0, + DEV_TARGET_ID = 1, + PCI0_TARGET_ID = 4, + PCI1_TARGET_ID = 8, + CRYPT_TARGET_ID =9, + MAX_TARGET_ID +}MV_TARGET_ID; + + +/* This enumerator describes the Marvell controller possible devices that */ +/* can be connected to its device interface. */ +typedef enum _mvDevice +{ + DEV_CS0, /* Device connected to dev CS[0] */ + DEV_CS1, /* Device connected to dev CS[1] */ + DEV_CS2, /* Device connected to dev CS[2] */ + DEV_CS3, /* Device connected to dev CS[3] */ + BOOT_CS, /* Device connected to boot CS */ + MV_DEV_MAX_CS +}MV_DEVICE; + +/* This enumerator defines the Marvell Units ID */ +typedef enum _mvUnitId +{ + DRAM_UNIT_ID, + PEX_UNIT_ID, + PCI_UNIT_ID, + ETH_GIG_UNIT_ID, + ETH_UNM_UNIT_ID, + USB_UNIT_ID, + IDMA_UNIT_ID, + XOR_UNIT_ID, + SATA_UNIT_ID, + TDM_UNIT_ID, + UART_UNIT_ID, + CESA_UNIT_ID, +#if !defined(MV78XX0_Z0) + SPI_UNIT_ID, +#endif + MAX_UNITS_ID, + +}MV_UNIT_ID; + +#endif /* MV_ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvCtrlEnvSpech */ + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.c new file mode 100644 index 0000000..9659a85 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.c @@ -0,0 +1,894 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "ctrlEnv/sys/mvAhbToMbus.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#undef MV_DEBUG +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* typedefs */ + + +/* CPU address remap registers offsets are inconsecutive. This struct */ +/* describes address remap register offsets */ +typedef struct _ahbToMbusRemapRegOffs +{ + MV_U32 lowRegOffs; /* Low 32-bit remap register offset */ + MV_U32 highRegOffs; /* High 32 bit remap register offset */ +}AHB_TO_MBUS_REMAP_REG_OFFS; + +/* locals */ +static MV_STATUS ahbToMbusRemapRegOffsGet (MV_U32 cpu, + MV_U32 winNum, + AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs); + +/******************************************************************************* +* mvAhbToMbusInit - Initialize AHB To Mbus Address Map ! +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK always. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusInit(MV_VOID) +{ + return MV_OK; + +} + +/******************************************************************************* +* mvAhbToMbusWinSet - Set CPU-to-peripheral winNum address window +* +* DESCRIPTION: +* This function sets +* address window, also known as address decode window. +* A new address decode window is set for specified winNum address window. +* If address decode window parameter structure enables the window, +* the routine will also enable the winNum window, allowing CPU to access +* the winNum window. +* +* INPUT: +* winNum - Windows number. +* pAddrDecWin - CPU winNum window data structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if CPU winNum window was set correctly, MV_ERROR in case of +* address window overlapps with other active CPU winNum window or +* trying to assign 36bit base address while CPU does not support that. +* The function returns MV_NOT_SUPPORTED, if the winNum is unsupported. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinSet(MV_U32 cpu, MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttribs; + MV_DEC_REGS decRegs; + + /* Parameter checking */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusWinSet: ERR. Invalid cpu %d\n", cpu); + return MV_NOT_SUPPORTED; + } + + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinSet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + + /* read base register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(cpu, winNum)); + } + else + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG(cpu)); + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvAhbToMbusWinSet:Error setting AHB to MBUS window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + /* read control register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(cpu, winNum)); + } + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvAhbToMbusWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + /* enable\Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + decRegs.sizeReg |= ATMWCR_WIN_ENABLE; + } + else + { + decRegs.sizeReg &= ~ATMWCR_WIN_ENABLE; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~ATMWCR_WIN_ATTR_MASK; + decRegs.sizeReg |= targetAttribs.attrib << ATMWCR_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.sizeReg &= ~ATMWCR_WIN_TARGET_MASK; + decRegs.sizeReg |= targetAttribs.targetId << ATMWCR_WIN_TARGET_OFFS; + + /* for the safe side we disable the window before writing the new + values */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + mvAhbToMbusWinEnable(cpu, winNum,MV_FALSE); + } + + /* 3) Write to address decode Base Address Register */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(cpu, winNum), decRegs.baseReg); + } + else + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_INTEREG_REG(cpu), decRegs.baseReg); + } + + + /* Internal register space have no size */ + /* register. Do not perform size register assigment for those targets */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + /* Write to address decode Size Register */ + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(cpu, winNum), decRegs.sizeReg); + } + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusWinGet - Get CPU-to-peripheral winNum address window +* +* DESCRIPTION: +* Get the CPU peripheral winNum address window. +* +* INPUT: +* cpu - CPU id +* winNum - Peripheral winNum enumerator +* +* OUTPUT: +* pAddrDecWin - CPU winNum window information data structure. +* +* RETURN: +* MV_OK if winNum exist, MV_ERROR otherwise. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinGet(MV_U32 cpu, MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusWinGet: ERR. Invalid cpu %d\n", cpu); + return MV_NOT_SUPPORTED; + } + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + /* Internal register space size have no size register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(cpu, winNum)); + } + else + { + decRegs.sizeReg = 0; + } + + /* Read base and size */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(cpu, winNum)); + } + else + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG(cpu)); + } + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + { + pAddrDecWin->addrWin.size = INTER_REGS_SIZE; + pAddrDecWin->target = INTER_REGS; + pAddrDecWin->enable = MV_TRUE; + + return MV_OK; + } + + if (decRegs.sizeReg & ATMWCR_WIN_ENABLE) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + if (-1 == pAddrDecWin->addrWin.size) + { + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & ATMWCR_WIN_ATTR_MASK) >> + ATMWCR_WIN_ATTR_OFFS; + targetAttrib.targetId = (decRegs.sizeReg & ATMWCR_WIN_TARGET_MASK) >> + ATMWCR_WIN_TARGET_OFFS; + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinTargetGet(MV_U32 cpu, MV_TARGET target) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 winNum; + + /* Parameter checking */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: ERR. Invalid cpu %d\n", cpu); + return MV_NOT_SUPPORTED; + } + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + if (INTER_REGS == target) + { + return MV_AHB_TO_MBUS_INTREG_WIN; + } + + for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS ; winNum++) + { + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + continue; + + if (mvAhbToMbusWinGet(cpu,winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail, win %d\n", winNum); + return 0xffffffff; + } + + if (decWin.enable == MV_TRUE) + { + if (decWin.target == target) + { + return winNum; + } + } + } + + return 0xFFFFFFFF; +} + +/******************************************************************************* +* mvAhbToMbusWinAvailGet - Get First Available window number. +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinAvailGet(MV_U32 cpu) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 winNum; + + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusWinAvailGet: ERR. Invalid cpu %d\n", cpu); + return MV_NOT_SUPPORTED; + } + + for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS ; winNum++) + { + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + continue; + + if (mvAhbToMbusWinGet(cpu, winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail\n"); + return 0xffffffff; + } + + if (decWin.enable == MV_FALSE) + { + return winNum; + } + } + + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* mvAhbToMbusWinEnable - Enable/disable a CPU address decode window +* +* DESCRIPTION: +* This function enable/disable a CPU address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling CPU accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* cpu - CPU id +* winNum - Peripheral winNum enumerator. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if protection window number was wrong, or the window +* overlapps other winNum window. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinEnable(MV_U32 cpu, MV_U32 winNum, MV_BOOL enable) +{ + + /* Parameter checking */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusWinEnable: ERR. Invalid cpu %d\n", cpu); + return MV_NOT_SUPPORTED; + } + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinEnable: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + /* Internal registers bar can't be disable or enabled */ + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + { + return (enable ? MV_OK : MV_ERROR); + } + + if (enable == MV_TRUE) + { + /* enable the window */ + MV_REG_BIT_SET(AHB_TO_MBUS_WIN_CTRL_REG(cpu, winNum), ATMWCR_WIN_ENABLE); + } + else + { /* Disable address decode winNum window */ + MV_REG_BIT_RESET(AHB_TO_MBUS_WIN_CTRL_REG(cpu, winNum), ATMWCR_WIN_ENABLE); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvAhbToMbusWinRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* After a CPU address hits one of PCI address decode windows there is an +* option to remap the address to a different one. For example, CPU +* executes a read from PCI winNum window address 0x1200.0000. This +* can be modified so the address on the PCI bus would be 0x1400.0000 +* Using the PCI address remap mechanism. +* +* INPUT: +* cpu - CPU id +* winNum - Peripheral winNum enumerator. Must be a PCI winNum. +* pAddrDecWin - CPU winNum window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if winNum is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinRemap(MV_U32 cpu, MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddr; + AHB_TO_MBUS_REMAP_REG_OFFS remapRegOffs; + + MV_U32 effectiveBaseAddress=0,baseAddrValue=0,windowSizeValue=0; + + + /* Parameter checking */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusWinEnable: ERR. Invalid cpu %d\n", cpu); + return MV_NOT_SUPPORTED; + } + + /* Get registers offsets of given winNum */ + if (MV_NO_SUCH == ahbToMbusRemapRegOffsGet(cpu, winNum, &remapRegOffs)) + { + return 0xffffffff; + } + + /* 1) Set address remap low */ + baseAddr = pAddrWin->baseLow; + + /* Check base address aligment */ + /* + if (MV_IS_NOT_ALIGN(baseAddr, ATMWRLR_REMAP_LOW_ALIGNMENT)) + { + mvOsPrintf("mvAhbToMbusPciRemap: Warning. Target base 0x%x unaligned\n", baseAddr); + return MV_ERROR; + } + */ + + /* BaseLow[31:16] => base register [31:16] */ + baseAddr = baseAddr & ATMWRLR_REMAP_LOW_MASK; + + MV_REG_WRITE(remapRegOffs.lowRegOffs, baseAddr); + + MV_REG_WRITE(remapRegOffs.highRegOffs, pAddrWin->baseHigh); + + + baseAddrValue = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(cpu, winNum)); + windowSizeValue = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(cpu, winNum)); + + baseAddrValue &= ATMWBR_BASE_MASK; + windowSizeValue &=ATMWCR_WIN_SIZE_MASK; + + /* Start calculating the effective Base Address */ + effectiveBaseAddress = baseAddrValue; + + /* The effective base address will be combined from the chopped (if any) + remap value (according to the size value and remap mechanism) and the + window's base address */ + effectiveBaseAddress |= (((windowSizeValue) | 0xffff) & pAddrWin->baseLow); + /* If the effectiveBaseAddress exceed the window boundaries return an + invalid value. */ + + if (effectiveBaseAddress > (baseAddrValue + (windowSizeValue | 0xffff))) + { + mvOsPrintf("mvAhbToMbusPciRemap: Error\n"); + return 0xffffffff; + } + + return effectiveBaseAddress; +} +/******************************************************************************* +* mvAhbToMbusWinTargetSwap - Swap AhbToMbus windows between targets +* +* DESCRIPTION: +* +* INPUT: +* cpu - CPU id +* target1 - CPU Interface target 1 +* target2 - CPU Interface target 2 +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if targets are illigal, or if one of the targets is not +* associated to a valid window . +* MV_OK otherwise. +* +*******************************************************************************/ + + +MV_STATUS mvAhbToMbusWinTargetSwap(MV_U32 cpu, MV_TARGET target1,MV_TARGET target2) +{ + MV_U32 winNum1,winNum2; + MV_AHB_TO_MBUS_DEC_WIN winDec1,winDec2,winDecTemp; + AHB_TO_MBUS_REMAP_REG_OFFS remapRegs1,remapRegs2; + MV_U32 remapBaseLow1=0,remapBaseLow2=0; + MV_U32 remapBaseHigh1=0,remapBaseHigh2=0; + + /* Check parameters */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: ERR. Invalid cpu %d\n", cpu); + return MV_NOT_SUPPORTED; + } + + if (target1 >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is Illigal\n", target1); + return MV_ERROR; + } + + if (target2 >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is Illigal\n", target1); + return MV_ERROR; + } + + /* get window associated with this target */ + winNum1 = mvAhbToMbusWinTargetGet(cpu, target1); + if (winNum1 == 0xffffffff) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", + target1,winNum1); + return MV_ERROR; + } + + /* get window associated with this target */ + winNum2 = mvAhbToMbusWinTargetGet(cpu, target2); + if (winNum2 == 0xffffffff) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", + target2,winNum2); + return MV_ERROR; + } + + /* now Get original values of both Windows */ + if (MV_OK != mvAhbToMbusWinGet(cpu, winNum1,&winDec1)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", + winNum1); + return MV_ERROR; + } + if (MV_OK != mvAhbToMbusWinGet(cpu, winNum2,&winDec2)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", + winNum2); + return MV_ERROR; + } + + + /* disable both windows */ + if (MV_OK != mvAhbToMbusWinEnable(cpu, winNum1,MV_FALSE)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable window %d\n", + winNum1); + return MV_ERROR; + } + + if (MV_OK != mvAhbToMbusWinEnable(cpu, winNum2,MV_FALSE)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable windo %d\n", + winNum2); + return MV_ERROR; + } + + /* now swap targets */ + /* first save winDec2 values */ + winDecTemp.addrWin.baseHigh = winDec2.addrWin.baseHigh; + winDecTemp.addrWin.baseLow = winDec2.addrWin.baseLow; + winDecTemp.addrWin.size = winDec2.addrWin.size; + winDecTemp.enable = winDec2.enable; + winDecTemp.target = winDec2.target; + + /* winDec2 = winDec1 */ + winDec2.addrWin.baseHigh = winDec1.addrWin.baseHigh; + winDec2.addrWin.baseLow = winDec1.addrWin.baseLow; + winDec2.addrWin.size = winDec1.addrWin.size; + winDec2.enable = winDec1.enable; + winDec2.target = winDec1.target; + + /* winDec1 = winDecTemp */ + winDec1.addrWin.baseHigh = winDecTemp.addrWin.baseHigh; + winDec1.addrWin.baseLow = winDecTemp.addrWin.baseLow; + winDec1.addrWin.size = winDecTemp.addrWin.size; + winDec1.enable = winDecTemp.enable; + winDec1.target = winDecTemp.target; + + /* now set the new values */ + mvAhbToMbusWinSet(cpu, winNum1,&winDec1); + mvAhbToMbusWinSet(cpu, winNum2,&winDec2); + + /* now we will treat the remap windows if exist */ + /* now check if one or both windows has a remap window + as well after the swap ! */ + /* if a window had a remap value differnt than the base value + before the swap , then after the swap the remap value will be + equal to the base value unless both windows has a remap windows*/ + + /* first get old values */ + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(cpu, winNum1,&remapRegs1)) + { + remapBaseLow1 = MV_REG_READ(remapRegs1.lowRegOffs); + remapBaseHigh1 = MV_REG_READ(remapRegs1.highRegOffs); + } + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(cpu, winNum2,&remapRegs2)) + { + remapBaseLow2 = MV_REG_READ(remapRegs2.lowRegOffs); + remapBaseHigh2 = MV_REG_READ(remapRegs2.highRegOffs); + } + + /* now do the swap */ + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(cpu, winNum1,&remapRegs1)) + { + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(cpu, winNum2,&remapRegs2)) + { + /* Two windows has a remap !!! so swap */ + + MV_REG_WRITE(remapRegs2.highRegOffs,remapBaseHigh1); + MV_REG_WRITE(remapRegs2.lowRegOffs,remapBaseLow1); + + MV_REG_WRITE(remapRegs1.highRegOffs,remapBaseHigh2); + MV_REG_WRITE(remapRegs1.lowRegOffs,remapBaseLow2); + } + else + { + /* remap == base */ + MV_REG_WRITE(remapRegs1.highRegOffs,winDec1.addrWin.baseHigh); + MV_REG_WRITE(remapRegs1.lowRegOffs,winDec1.addrWin.baseLow); + } + } + else if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(cpu,winNum2,&remapRegs2)) + { + /* remap == base */ + MV_REG_WRITE(remapRegs2.highRegOffs,winDec2.addrWin.baseHigh); + MV_REG_WRITE(remapRegs2.lowRegOffs,winDec2.addrWin.baseLow); + } + + return MV_OK; +} + + + + +/******************************************************************************* +* ahbToMbusRemapRegOffsGet - Get CPU address remap register offsets +* +* DESCRIPTION: +* CPU to PCI address remap registers offsets are inconsecutive. +* This function returns PCI address remap registers offsets. +* +* INPUT: +* cpu - CPU id +* winNum - Address decode window number. See MV_U32 enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if winNum is not a PCI one. +* +*******************************************************************************/ +static MV_STATUS ahbToMbusRemapRegOffsGet(MV_U32 cpu, MV_U32 winNum, + AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs) +{ + pRemapRegs->lowRegOffs = AHB_TO_MBUS_WIN_REMAP_LOW_REG(cpu, winNum); + pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(cpu, winNum); + + if ((pRemapRegs->lowRegOffs == 0) || (pRemapRegs->highRegOffs == 0)) + { + DB(mvOsPrintf("ahbToMbusRemapRegOffsGet: ERR. Invalid winNum %d\n", + winNum)); + return MV_NO_SUCH; + } + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusCpuWinCopy - Copy the Ahb2MBus registers value of CPU 0 to CPU 1. +* +* DESCRIPTION: +* This function copy CPU 0 address decode map to CPU 1. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +#if defined(MV78XX0) && defined(MV78200) +MV_VOID mvAhbToMbusCpuWinCopy(MV_VOID) +{ + MV_U32 winNum; + + for( winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++ ) + { + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(1, winNum), + MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(0, winNum))); + MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(1, winNum), + MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(0, winNum))); + /* We have remap register only for win [7..0] */ + if (winNum != MAX_AHB_TO_MBUS_REMAP_WINS) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_LOW_REG(1, winNum), + MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_LOW_REG(0, winNum))); + MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(1, winNum), + MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(0, winNum))); + } + } + else + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_INTEREG_REG(1), + MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG(0))); + } + } +} +#endif +/******************************************************************************* +* mvAhbToMbusAddDecShow - Print the Ahb to MBus bridge address decode map. +* +* DESCRIPTION: +* This function print the CPU address decode map. +* +* INPUT: +* cpu - CPU id +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvAhbToMbusAddDecShow(MV_U32 cpu) +{ + MV_AHB_TO_MBUS_DEC_WIN win; + MV_U32 winNum; + /* Check parameters */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvAhbToMbusAddDecShow: ERR. Invalid cpu %d\n", cpu); + return; + } + + mvOsOutput( "\n" ); + mvOsOutput( "CPU %d, AHB To MBUS Bridge:\n", cpu); + mvOsOutput( "-------------------\n" ); + + for( winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++ ) + { + memset( &win, 0, sizeof(MV_AHB_TO_MBUS_DEC_WIN) ); + + mvOsOutput( "win%d - ", winNum ); + + if( mvAhbToMbusWinGet(cpu, winNum, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.h new file mode 100644 index 0000000..79bb21d --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbus.h @@ -0,0 +1,99 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbush +#define __INCmvAhbToMbush + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* defines */ + + +typedef struct _mvAhbtoMbusDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_AHB_TO_MBUS_DEC_WIN; + +/* mvAhbToMbus.h API list */ + +MV_STATUS mvAhbToMbusInit(MV_VOID); +MV_STATUS mvAhbToMbusWinSet(MV_U32 cpu, MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin); +MV_STATUS mvAhbToMbusWinGet(MV_U32 cpu, MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin); +MV_STATUS mvAhbToMbusWinEnable(MV_U32 cpu, MV_U32 winNum,MV_BOOL enable); +MV_U32 mvAhbToMbusWinRemap(MV_U32 cpu, MV_U32 winNum, MV_ADDR_WIN *pAddrDecWin); +MV_U32 mvAhbToMbusWinTargetGet(MV_U32 cpu, MV_TARGET target); +MV_U32 mvAhbToMbusWinAvailGet(MV_U32 cpu); +MV_STATUS mvAhbToMbusWinTargetSwap(MV_U32 cpu, MV_TARGET target1,MV_TARGET target2); +MV_VOID mvAhbToMbusAddDecShow(MV_U32 cpu); +#if defined(MV78XX0) && defined(MV78200) +MV_VOID mvAhbToMbusCpuWinCopy(MV_VOID); +#endif +#endif /* __INCmvAhbToMbush */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusConfig.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusConfig.h new file mode 100644 index 0000000..c54906a --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusConfig.h @@ -0,0 +1,74 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbusConfigh +#define __INCmvAhbToMbusConfigh + +#include "mvSysHwConfig.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" + + + +#endif /* __INCmvAhbToMbusConfigh */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusRegs.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusRegs.h new file mode 100644 index 0000000..f046929 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvAhbToMbusRegs.h @@ -0,0 +1,156 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbusRegsh +#define __INCmvAhbToMbusRegsh + +/******************************/ +/* ARM Address Map Registers */ +/******************************/ + +#define MAX_AHB_TO_MBUS_WINS 15 +#define MAX_AHB_TO_MBUS_REMAP_WINS 8 +#define MV_AHB_TO_MBUS_INTREG_WIN 14 + + +#define AHB_TO_MBUS_WIN_CTRL_REG(cpu, winNum) (((winNum) < 8)? \ + (AHB_TO_MBUS_BASE(cpu) + (winNum)*0x10): \ + (AHB_TO_MBUS_BASE(cpu) + 0x900 + ((winNum)-8)*0x10)) + +#define AHB_TO_MBUS_WIN_BASE_REG(cpu, winNum) (((winNum) < 8)? \ + (AHB_TO_MBUS_BASE(cpu) + 0x4 + (winNum)*0x10): \ + (AHB_TO_MBUS_BASE(cpu) + 0x904 + ((winNum)-8)*0x10)) + +#define AHB_TO_MBUS_WIN_REMAP_LOW_REG(cpu, winNum) (((winNum) < 8)? \ + (AHB_TO_MBUS_BASE(cpu) + 0x8 + (winNum)*0x10): \ + (0)) + +#define AHB_TO_MBUS_WIN_REMAP_HIGH_REG(cpu, winNum) (((winNum) < 8)? \ + (AHB_TO_MBUS_BASE(cpu) + 0xC + (winNum)*0x10): \ + (0)) + +#define AHB_TO_MBUS_WIN_INTEREG_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x80) + +/* Window Control Register */ +/* AHB_TO_MBUS_WIN_CTRL_REG (ATMWCR)*/ +#define ATMWCR_WIN_ENABLE BIT0 /* Window Enable */ + +#define ATMWCR_WIN_TARGET_OFFS 4 /* The target interface associated + with this window*/ +#define ATMWCR_WIN_TARGET_MASK (0xf << ATMWCR_WIN_TARGET_OFFS) + +#define ATMWCR_WIN_ATTR_OFFS 8 /* The target interface attributes + Associated with this window */ +#define ATMWCR_WIN_ATTR_MASK (0xff << ATMWCR_WIN_ATTR_OFFS) + + +/* +Used with the Base register to set the address window size and location +Must be programed from LSB to MSB as sequence of 1’s followed +by sequence of 0’s. The number of 1’s specifies the size of the window +in 64 KB granularity (e.g. a value of 0x00FF specifies 256 = 16 MB). + +NOTE: A value of 0x0 specifies 64KB size. +*/ +#define ATMWCR_WIN_SIZE_OFFS 16 /* Window Size */ +#define ATMWCR_WIN_SIZE_MASK (0xffff << ATMWCR_WIN_SIZE_OFFS) +#define ATMWCR_WIN_SIZE_ALIGNMENT 0x10000 + +/* Window Base Register */ +/* AHB_TO_MBUS_WIN_BASE_REG (ATMWBR) */ + +/* +Used with the size field to set the address window size and location. +Corresponds to transaction address[31:16] +*/ +#define ATMWBR_BASE_OFFS 16 /* Base Address */ +#define ATMWBR_BASE_MASK (0xffff << ATMWBR_BASE_OFFS) +#define ATMWBR_BASE_ALIGNMENT 0x10000 + +/* Window Remap Low Register */ +/* AHB_TO_MBUS_WIN_REMAP_LOW_REG (ATMWRLR) */ + +/* +Used with the size field to specifies address bits[31:0] to be driven to +the target interface.: +target_addr[31:16] = (addr[31:16] & size[15:0]) | (remap[31:16] & ~size[15:0]) +*/ +#define ATMWRLR_REMAP_LOW_OFFS 16 /* Remap Address */ +#define ATMWRLR_REMAP_LOW_MASK (0xffff << ATMWRLR_REMAP_LOW_OFFS) +#define ATMWRLR_REMAP_LOW_ALIGNMENT 0x10000 + +/* Window Remap High Register */ +/* AHB_TO_MBUS_WIN_REMAP_HIGH_REG (ATMWRHR) */ + +/* +Specifies address bits[63:32] to be driven to the target interface. +target_addr[63:32] = (RemapHigh[31:0] +*/ +#define ATMWRHR_REMAP_HIGH_OFFS 0 /* Remap Address */ +#define ATMWRHR_REMAP_HIGH_MASK (0xffffffff << ATMWRHR_REMAP_HIGH_OFFS) + + +#endif /* __INCmvAhbToMbusRegsh */ + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.c new file mode 100644 index 0000000..1eb2ac3 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.c @@ -0,0 +1,1110 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" +#include "cpu/mvCpu.h" +#include "ctrlEnv/sys/mvSysDram.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "mvSysHwConfig.h" + + +/*#define MV_DEBUG*/ +/* defines */ + +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* typedefs */ +/* CPU address decode registers offsets are inconsecutive. This struct */ +/* describes address decode register offsets */ +typedef struct _cpuDecRegOffs +{ + MV_U32 baseRegOffs; /* Base address register offset. */ + MV_U32 sizeRegOffs; /* Size address register offset. */ + /* Used as size itself for windows with no size */ + /* registers (e.g. internal registers) */ +}CPU_DEC_REG_OFFS; + +/* CPU address remap registers offsets are inconsecutive. This struct */ +/* describes address remap register offsets */ +typedef struct _cpuRemapRegOffs +{ + MV_U32 lowRegOffs; /* Low 32-bit remap register offset */ + MV_U32 highRegOffs; /* High 32 bit remap register offset */ +}CPU_REMAP_REG_OFFS; + +#if defined (MV_BRIDGE_SYNC_REORDER) +MV_U32 *mvUncachedParam = NULL; +#endif + +/* locals */ + +/* CPU address decode table. Note that table entry number must match its */ +/* target enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* target which is represent by DEVICE_CS0 enumerator (4). */ + + +/* locals */ +/* static functions */ +static MV_BOOL cpuTargetWinOverlap(MV_U32 cpu, MV_TARGET target, MV_ADDR_WIN *pAddrWin); +#ifdef MV_INCLUDE_MONT_EXT +MV_STATUS mvBoardSpecWinMapOverride(MV_VOID); +#endif +MV_TARGET sampleAtResetTargetArray[] = BOOT_TARGETS_NAME_ARRAY; +/******************************************************************************* +* mvCpuIfInit - Initialize Controller CPU interface +* +* DESCRIPTION: +* This function initialize Controller CPU interface: +* 1. Set CPU interface configuration registers. +* 2. Set CPU master Pizza arbiter control according to static +* configuration described in configuration file. +* 3. Opens CPU address decode windows. DRAM windows are assumed to be +* already set (auto detection). +* +* INPUT: +* cpu - CPU id +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvCpuIfInitForCpu(MV_U32 cpu, MV_CPU_DEC_WIN *cpuAddrWinMap) +{ + MV_U32 regVal; + MV_TARGET target; + MV_ADDR_WIN addrWin; + MV_CPU_DEC_WIN *winMap = cpuAddrWinMap; + + if (cpuAddrWinMap == NULL) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. cpuAddrWinMap == NULL\n")); + return MV_ERROR; + } + + /* Set ARM Configuration register */ + regVal = MV_REG_READ(CPU_CONFIG_REG(cpu)); + regVal &= ~CPU_CONFIG_DEFAULT_MASK; + regVal |= CPU_CONFIG_DEFAULT; + + + MV_REG_WRITE(CPU_CONFIG_REG(cpu),regVal); + + /* Set ARM Control and Status register */ + regVal = MV_REG_READ(CPU_CTRL_STAT_REG(cpu)); + regVal &= ~CPU_CTRL_STAT_DEFAULT_MASK; + regVal |= CPU_CTRL_STAT_DEFAULT; + MV_REG_WRITE(CPU_CTRL_STAT_REG(cpu),regVal); + + + /* First disable all CPU target windows */ + for (target = 0; winMap[target].enable != TBL_TERM; target++) + { + if ((MV_TARGET_IS_DRAM(target))||(target == INTER_REGS)) + { + continue; + } + +#ifdef MV_MEM_OVER_PEX_WA + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PEX(target)) + { + continue; + } +#endif + mvCpuIfTargetWinEnableForCpu(cpu, MV_CHANGE_BOOT_CS(target),MV_FALSE); + } + + /* Go through all targets in user table until table terminator */ + for (target = 0; winMap[target].enable != TBL_TERM; target++) + { + /* if DRAM auto sizing is used do not initialized DRAM target windows, */ + /* assuming this already has been done earlier. */ +#ifdef MV_DRAM_AUTO_SIZE + if (MV_TARGET_IS_DRAM(target)) + { + continue; + } +#endif + +#ifdef MV_MEM_OVER_PEX_WA + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PEX(target)) + { + continue; + } +#endif + /* If the target attribute is the same as the boot device attribute */ + /* then it's stays disable */ +#if !defined(MV78XX0_Z0) + if (mvBoardIsBootFromSpi() && (target == SPI_CS)) + continue; +#endif + if (MV_TARGET_IS_AS_BOOT(target)) + { + continue; + } + + if((0 == winMap[target].addrWin.size) || + (DIS == winMap[target].enable)) + + { + + if (MV_OK != mvCpuIfTargetWinEnableForCpu(cpu, target, MV_FALSE)) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinEnable fail\n")); + return MV_ERROR; + } + + } + else + { + if (MV_OK != mvCpuIfTargetWinSetForCpu(cpu, + target, + &winMap[target])) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); + + + return MV_ERROR; + } + + addrWin.baseLow = winMap[target].addrWin.baseLow; + addrWin.baseHigh = winMap[target].addrWin.baseHigh; + if (0xffffffff == mvAhbToMbusWinRemap(cpu, winMap[target].winNum ,&addrWin)) + { + DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", + winMap[target].winNum)); + } + } + } + return MV_OK; +} + +MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap) +{ + return mvCpuIfInitForCpu(whoAmI(), cpuAddrWinMap); +} + + +#if defined (MV_BRIDGE_SYNC_REORDER) +MV_STATUS mvCpuIfBridgeReorderWAInit(void) +{ + MV_ULONG tmpPhysAddress; + mvUncachedParam = mvOsIoUncachedMalloc(NULL, 4, &tmpPhysAddress, NULL); + if (mvUncachedParam == NULL) { + mvOsPrintf("Uncached memory allocation failed\n"); + return MV_ERROR; + } + return MV_OK; +} +#endif + +/******************************************************************************* +* mvCpuIfTargetWinSet - Set CPU-to-peripheral target address window +* +* DESCRIPTION: +* This function sets a peripheral target (e.g. SDRAM bank0, PCI0_MEM0) +* address window, also known as address decode window. +* A new address decode window is set for specified target address window. +* If address decode window parameter structure enables the window, +* the routine will also enable the target window, allowing CPU to access +* the target window. +* +* INPUT: +* cpu - cpu id +* target - Peripheral target enumerator. +* pAddrDecWin - CPU target window data structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if CPU target window was set correctly, MV_ERROR in case of +* address window overlapps with other active CPU target window or +* trying to assign 36bit base address while CPU does not support that. +* The function returns MV_NOT_SUPPORTED, if the target is unsupported. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinSetForCpu(MV_U32 cpu, MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 existingWinNum; + MV_DRAM_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfTargetWinSet: ERR. Invalid cpu %d\n", cpu); + return MV_ERROR; + } + + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinSet: target %d is Illegal\n", target); + return MV_ERROR; + } + + /* 2) Check if the requested window overlaps with current windows */ + if (MV_TRUE == cpuTargetWinOverlap(cpu, target, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvCpuIfTargetWinSet: ERR. Target %d overlap\n", target); + return MV_BAD_PARAM; + } + + if (MV_TARGET_IS_DRAM(target)) + { + /* copy relevant data to MV_DRAM_DEC_WIN structure */ + addrDecWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; + addrDecWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; + addrDecWin.addrWin.size = pAddrDecWin->addrWin.size; + addrDecWin.enable = pAddrDecWin->enable; + + if (MV_OK != mvDramIfWinSet(cpu,target,&addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinSet: mvDramIfWinSet Failed\n"); + return MV_ERROR; + } + + } + else + { + /* copy relevant data to MV_AHB_TO_MBUS_DEC_WIN structure */ + decWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; + decWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; + decWin.addrWin.size = pAddrDecWin->addrWin.size; + decWin.enable = pAddrDecWin->enable; + decWin.target = target; + + existingWinNum = mvAhbToMbusWinTargetGet(cpu, target); + + /* check if there is already another Window configured + for this target */ + if ((existingWinNum < MAX_AHB_TO_MBUS_WINS )&& + (existingWinNum != pAddrDecWin->winNum)) + { + /* if we want to enable the new winow number + passed by the user , then the old one should + be disabled */ + if (MV_TRUE == pAddrDecWin->enable) + { + /* be sure it is disabled */ + mvAhbToMbusWinEnable(cpu, existingWinNum , MV_FALSE); + } + } + + if (mvAhbToMbusWinSet(cpu, pAddrDecWin->winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinSet: mvAhbToMbusWinSet Failed\n"); + return MV_ERROR; + } + } + + return MV_OK; +} + +MV_STATUS mvCpuIfTargetWinSet( MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + return mvCpuIfTargetWinSetForCpu(whoAmI(), target, pAddrDecWin); +} + +/******************************************************************************* +* mvCpuIfTargetWinGetForCpu - Get CPU-to-peripheral target address window +* +* DESCRIPTION: +* Get the CPU peripheral target address window. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* pAddrDecWin - CPU target window information data structure. +* +* RETURN: +* MV_OK if target exist, MV_ERROR otherwise. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinGetForCpu(MV_U32 cpu, MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + + MV_U32 winNum=0xffffffff; + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_DRAM_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfTargetWinGet: ERR. Invalid cpu %d\n", cpu); + return MV_ERROR; + } + + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinGet: target %d is Illigal\n", target); + return MV_ERROR; + } + + if (MV_TARGET_IS_DRAM(target)) + { + if (mvDramIfWinGet(cpu,target,&addrDecWin) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", + target); + return MV_ERROR; + } + + /* copy relevant data to MV_CPU_DEC_WIN structure */ + pAddrDecWin->addrWin.baseLow = addrDecWin.addrWin.baseLow; + pAddrDecWin->addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pAddrDecWin->addrWin.size = addrDecWin.addrWin.size; + pAddrDecWin->enable = addrDecWin.enable; + pAddrDecWin->winNum = 0xffffffff; + + } + else + { + /* get the Window number associated with this target */ + + winNum = mvAhbToMbusWinTargetGet(cpu, target); + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + return MV_NO_SUCH; + + } + + if (mvAhbToMbusWinGet(cpu, winNum , &decWin) != MV_OK) + { + mvOsPrintf("%s: mvAhbToMbusWinGet Failed at winNum = %d\n", + __FUNCTION__, winNum); + return MV_ERROR; + + } + + /* copy relevant data to MV_CPU_DEC_WIN structure */ + pAddrDecWin->addrWin.baseLow = decWin.addrWin.baseLow; + pAddrDecWin->addrWin.baseHigh = decWin.addrWin.baseHigh; + pAddrDecWin->addrWin.size = decWin.addrWin.size; + pAddrDecWin->enable = decWin.enable; + pAddrDecWin->winNum = winNum; + + } + + return MV_OK; +} + + +/******************************************************************************* +* mvCpuIfTargetWinGet - Get CPU-to-peripheral target address window +* +* DESCRIPTION: +* Get the CPU peripheral target address window. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* pAddrDecWin - CPU target window information data structure. +* +* RETURN: +* MV_OK if target exist, MV_ERROR otherwise. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + return mvCpuIfTargetWinGetForCpu(whoAmI(), target, pAddrDecWin); +} + +/******************************************************************************* +* mvCpuIfTargetWinEnable - Enable/disable a CPU address decode window +* +* DESCRIPTION: +* This function enable/disable a CPU address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling CPU accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* cpu - CPU id +* target - Peripheral target enumerator. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if protection window number was wrong, or the window +* overlapps other target window. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinEnableForCpu(MV_U32 cpu, MV_TARGET target,MV_BOOL enable) +{ + MV_U32 winNum, temp; + MV_CPU_DEC_WIN addrDecWin; + + /* Check parameters */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfTargetWinEnable: ERR. Invalid cpu %d\n", cpu); + return MV_ERROR; + } + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinEnable: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* get the window and check if it exist */ + temp = mvCpuIfTargetWinGetForCpu(cpu, target, &addrDecWin); + if (MV_NO_SUCH == temp) + { + return (enable? MV_ERROR: MV_OK); + } + else if( MV_OK != temp) + { + mvOsPrintf("%s: ERR. Getting target %d failed.\n",__FUNCTION__, target); + return MV_ERROR; + } + + + /* check overlap */ + + if (MV_TRUE == enable) + { + if (MV_TRUE == cpuTargetWinOverlap(cpu, target, &addrDecWin.addrWin)) + { + DB(mvOsPrintf("%s: ERR. Target %d overlap\n",__FUNCTION__, target)); + return MV_ERROR; + } + + } + + + if (MV_TARGET_IS_DRAM(target)) + { + if (mvDramIfWinEnable(cpu, target, enable) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: mvDramIfWinEnable Failed at \n"); + return MV_ERROR; + + } + + } + else + { + /* get the Window number associated with this target */ + + winNum = mvAhbToMbusWinTargetGet(cpu, target); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + return (enable? MV_ERROR: MV_OK); + } + + if (mvAhbToMbusWinEnable(cpu, winNum, enable) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: Failed to enable window = %d\n", + winNum); + return MV_ERROR; + + } + + } + + return MV_OK; +} + +MV_STATUS mvCpuIfTargetWinEnable( MV_TARGET target,MV_BOOL enable) +{ + return mvCpuIfTargetWinEnableForCpu(whoAmI(), target, enable); +} + +/******************************************************************************* +* mvCpuIfTargetWinSizeGet - Get CPU target address window size +* +* DESCRIPTION: +* Get the size of CPU-to-peripheral target window. +* +* INPUT: +* cpu - CPU id +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit size. Function also returns '0' if window is closed. +* Function returns 0xFFFFFFFF in case of an error. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinSizeGetForCpu(MV_U32 cpu, MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfTargetWinSizeGet: ERR. Invalid cpu %d\n", cpu); + return 0; + } + + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinSizeGet: target %d is Illigal\n", target); + return 0; + } + + /* Get the winNum window */ + if (MV_OK != mvCpuIfTargetWinGetForCpu(cpu, target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinSizeGet:ERR. Getting target %d failed.\n", + target); + return 0; + } + + /* Check if window is enabled */ + if (addrDecWin.enable == MV_TRUE) + { + return (addrDecWin.addrWin.size); + } + else + { + return 0; /* Window disabled. return 0 */ + } +} + +MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target) +{ + return mvCpuIfTargetWinSizeGetForCpu(whoAmI(), target); +} + +/******************************************************************************* +* mvCpuIfTargetWinBaseLowGet - Get CPU target address window base low +* +* DESCRIPTION: +* CPU-to-peripheral target address window base is constructed of +* two parts: Low and high. +* This function gets the CPU peripheral target low base address. +* +* INPUT: +* cpu - CPU id +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit low base address. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinBaseLowGetForCpu(MV_U32 cpu, MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet: ERR. Invalid cpu %d\n", cpu); + return 0xffffffff; + } + + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + /* Get the target window */ + if (MV_OK != mvCpuIfTargetWinGetForCpu(cpu, target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet:ERR. Getting target %d failed.\n", + target); + return 0xffffffff; + } + + if (MV_FALSE == addrDecWin.enable) + { + return 0xffffffff; + } + return (addrDecWin.addrWin.baseLow); +} + +MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target) +{ + return mvCpuIfTargetWinBaseLowGetForCpu(whoAmI(), target); +} + +/******************************************************************************* +* mvCpuIfTargetWinBaseHighGet - Get CPU target address window base high +* +* DESCRIPTION: +* CPU-to-peripheral target address window base is constructed of +* two parts: Low and high. +* This function gets the CPU peripheral target high base address. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* cpu - CPU id +* None. +* +* RETURN: +* 32bit high base address. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinBaseHighGetForCpu(MV_U32 cpu, MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfTargetWinBaseHighGet: ERR. Invalid cpu %d\n", cpu); + return 0xffffffff; + } + + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + /* Get the target window */ + if (MV_OK != mvCpuIfTargetWinGetForCpu(cpu, target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinBaseHighGet:ERR. Getting target %d failed.\n", + target); + return 0xffffffff; + } + + if (MV_FALSE == addrDecWin.enable) + { + return 0; + } + + return (addrDecWin.addrWin.baseHigh); +} + +MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target) +{ + return mvCpuIfTargetWinBaseHighGetForCpu(whoAmI(), target); +} + +#if defined(MV_INCLUDE_PEX) +/******************************************************************************* +* mvCpuIfPciIfRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* pciTarget - Peripheral target enumerator. Must be a PCI target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciIfTarget, MV_ADDR_WIN *pAddrDecWin) +{ + if (MV_TARGET_IS_PEX(pciIfTarget)) + { + return mvCpuIfPexRemap(pciIfTarget,pAddrDecWin); + } + return 0; +} + +/******************************************************************************* +* mvCpuIfPexRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* cpu - CPU id +* pexTarget - Peripheral target enumerator. Must be a PEX target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PEX one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPexRemapForCpu(MV_U32 cpu, MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 winNum; + + /* Check parameters */ + + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfPexRemap: ERR. Invalid cpu %d\n", cpu); + return 0xffffffff; + } + + if (!MV_TARGET_IS_PEX(pexTarget)) + { + mvOsPrintf("mvCpuIfPexRemap: target %d is Illigal\n",pexTarget); + return 0xffffffff; + } + + /* get the Window number associated with this target */ + winNum = mvAhbToMbusWinTargetGet(cpu, pexTarget); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvCpuIfPexRemap: mvAhbToMbusWinTargetGet Failed\n"); + return 0xffffffff; + + } + + return mvAhbToMbusWinRemap(cpu, winNum, pAddrDecWin); +} + +MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin) +{ + return mvCpuIfPexRemapForCpu(whoAmI(), pexTarget, pAddrDecWin); +} + +#endif + + +/******************************************************************************* +* cpuTargetWinOverlap - Detect CPU address decode windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case CPU address decode +* windows overlapps. +* This function detects CPU address decode windows overlapping of a +* specified target. The function does not check the target itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* cpu - cpu Id +* target - Peripheral target enumerator. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlaps current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL cpuTargetWinOverlap(MV_U32 cpu, MV_TARGET target, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 targetNum; + MV_CPU_DEC_WIN addrDecWin; + MV_STATUS status; + + + for(targetNum = 0; targetNum < MAX_TARGETS; targetNum++) + { + + /* don't check our target or illegal targets */ + if (targetNum == target) + { + continue; + } + + /* Get window parameters */ + status = mvCpuIfTargetWinGetForCpu(cpu, targetNum, &addrDecWin); + if(MV_NO_SUCH == status) + { + continue; + } + if(MV_OK != status) + { + DB(mvOsPrintf("cpuTargetWinOverlap: ERR. TargetWinGet failed\n")); + return MV_TRUE; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + DB(mvOsPrintf("cpuTargetWinOverlap: Required target %d overlap current %d\n", + target, targetNum)); + return MV_TRUE; + } + } + return MV_FALSE; +} + + + +/******************************************************************************* +* mvCpuIfAddDecShow - Print the CPU address decode map. +* +* DESCRIPTION: +* This function print the CPU address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ + +MV_VOID mvCpuIfAddrDecShow(MV_U32 cpu) +{ + MV_CPU_DEC_WIN win; + MV_U32 target; + + if (cpu >= MV_MAX_CPU) + { + mvOsPrintf("mvCpuIfAddrDecShow: ERR. Invalid cpu %d\n", cpu); + return; + } + + mvOsOutput( "\n" ); + mvOsOutput( "CPU %d, CPU Interface\n", cpu); + mvOsOutput( "-------------\n" ); + + for( target = 0; target < MAX_TARGETS; target++ ) + { + + memset( &win, 0, sizeof(MV_CPU_DEC_WIN) ); + + mvOsOutput( "%s ",mvCtrlTargetNameGet(target)); + mvOsOutput( "...." ); + + if( mvCpuIfTargetWinGetForCpu(cpu, target, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "base %08x, ", win.addrWin.baseLow ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + + } + else + mvOsOutput( "disable\n" ); + } + else if( mvCpuIfTargetWinGetForCpu(cpu, target, &win ) == MV_NO_SUCH ) + { + mvOsOutput( "no such\n" ); + } + + } + +} + + +/*******************************************************************************/ + +#if defined(MV78XX0) + +#define MV_PROC_STR_SIZE 50 + +void mvCpuIfGetL2EccMode(MV_8 *buf) +{ + MV_U32 regVal = MV_REG_READ(CPU_CONFIG_REG(0)); + if (regVal & BIT22) + mvOsSPrintf(buf, "L2 ECC Enabled"); + else + mvOsSPrintf(buf, "L2 ECC Disabled"); +} + +void mvCpuIfGetL2Mode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT22) + mvOsSPrintf(buf, "L2 Enabled in %s mode", + (MV_REG_READ(CPU_CTRL_STAT_REG(whoAmI())) & CCSR_L2WT) ? + "Write-Trough" : "Write-Back"); + else + mvOsSPrintf(buf, "L2 Disabled"); +} + +void mvCpuIfGetL2PrefetchMode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT24) + mvOsSPrintf(buf, "L2 Prefetch Disabled"); + else + mvOsSPrintf(buf, "L2 Prefetch Enabled"); +} + +void mvCpuIfGetVfpMode(MV_8 *buf) +{ + +} + +void mvCpuIfGetWriteAllocMode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT28) + mvOsSPrintf(buf, "Write Allocate Enabled"); + else + mvOsSPrintf(buf, "Write Allocate Disabled"); +} + +void mvCpuIfGetCpuStreamMode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT29) + mvOsSPrintf(buf, "CPU Streaming Enabled"); + else + mvOsSPrintf(buf, "CPU Streaming Disabled"); +} + +void mvCpuIfGetDramEccMode(MV_8 *buf) +{ + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_ECC_EN) + { + mvOsSPrintf(buf, "DRAM ECC enabled"); + } + else + { + mvOsSPrintf(buf, "DRAM ECC Disabled"); + } +} + +void mvCpuIfGetCasLatency(MV_8 *buf) +{ + MV_U32 sdramCasLat = mvDramIfCalGet(); + + mvOsSPrintf(buf, "CAS Latency %d.%d\n", sdramCasLat/10, sdramCasLat%10); +} + +MV_U32 mvCpuIfPrintSystemConfig(MV_8 *buffer, MV_U32 index) +{ + MV_U32 count = 0; + + MV_8 L2_ECC_str[MV_PROC_STR_SIZE]; + MV_8 L2_En_str[MV_PROC_STR_SIZE]; + MV_8 L2_Prefetch_str[MV_PROC_STR_SIZE]; + /*MV_8 VFP_mode_str[MV_PROC_STR_SIZE];*/ + MV_8 Write_Alloc_str[MV_PROC_STR_SIZE]; + MV_8 Cpu_Stream_str[MV_PROC_STR_SIZE]; + MV_8 Dram_ECC_str[MV_PROC_STR_SIZE]; + MV_8 Cas_Latency_str[MV_PROC_STR_SIZE]; + + mvCpuIfGetL2Mode(L2_En_str); + mvCpuIfGetL2EccMode(L2_ECC_str); + mvCpuIfGetL2PrefetchMode(L2_Prefetch_str); + /*mvCpuIfGetVfpMode(VFP_mode_str);*/ + mvCpuIfGetWriteAllocMode(Write_Alloc_str); + mvCpuIfGetCpuStreamMode(Cpu_Stream_str); + mvCpuIfGetDramEccMode(Dram_ECC_str); + mvCpuIfGetCasLatency(Cas_Latency_str); + + count += mvOsSPrintf(buffer + count + index, "%s\n", L2_En_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", L2_ECC_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", L2_Prefetch_str); + /*count += mvOsSPrintf(buffer + count + index, "%s\n", VFP_mode_str);*/ + count += mvOsSPrintf(buffer + count + index, "%s\n", Write_Alloc_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", Cpu_Stream_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", Dram_ECC_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", Cas_Latency_str); + return count; +} + +#endif + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.h new file mode 100644 index 0000000..fb5c945 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIf.h @@ -0,0 +1,119 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfh +#define __INCmvCpuIfh + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIfRegs.h" +#include "ctrlEnv/sys/mvAhbToMbus.h" +#include "ctrlEnv/sys/mvCpuIfConfig.h" +#include "ddr2/mvDramIf.h" + +/* defines */ + +/* typedefs */ +/* This structure describes CPU interface address decode window */ +typedef struct _mvCpuIfDecWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_U32 winNum; /* Window Number in the AHB To Mbus bridge */ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_CPU_DEC_WIN; + + + +/* mvCpuIfLib.h API list */ + +MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *winMap); +MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target,MV_BOOL enable); +MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target); + + + +#if defined(MV_INCLUDE_PEX) +MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciIfTarget, MV_ADDR_WIN *pAddrDecWin); +MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin); +MV_U32 mvCpuIfPexRemapForCpu(MV_U32 cpu, MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin); +#endif +MV_STATUS mvCpuIfInitForCpu(MV_U32 cpu, MV_CPU_DEC_WIN *winMap); +MV_STATUS mvCpuIfTargetWinSetForCpu(MV_U32 cpu, MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinGetForCpu(MV_U32 cpu, MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinEnableForCpu(MV_U32 cpu, MV_TARGET target,MV_BOOL enable); +MV_U32 mvCpuIfTargetWinSizeGetForCpu(MV_U32 cpu, MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseLowGetForCpu(MV_U32 cpu, MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseHighGetForCpu(MV_U32 cpu, MV_TARGET target); + +MV_VOID mvCpuIfAddrDecShow(MV_U32 cpu); +MV_STATUS mvCpuIfBridgeReorderWAInit(void); +MV_U32 mvCpuIfPrintSystemConfig(MV_8 *buffer, MV_U32 index); + +#endif /* __INCmvCpuIfh */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfConfig.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfConfig.h new file mode 100644 index 0000000..95c814c --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfConfig.h @@ -0,0 +1,123 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfconfigh +#define __INCmvCpuIfConfigh + +#include "mvSysHwConfig.h" +#include "ctrlEnv/sys/mvCpuIfRegs.h" + + +/* CPU control register map */ +/* Set bits means value is about to change according to new value */ +#define CPU_CONFIG_DEFAULT_MASK (CCR_VEC_INIT_LOC_MASK | \ + CCR_AHB_ERROR_PROP_MASK) + + +#define CPU_CONFIG_DEFAULT (CCR_VEC_INIT_LOC_FF00) + +/* CPU Control and status defaults */ +#define CPU_CTRL_STAT_DEFAULT_MASK (CCSR_PEX0_ENABLE | \ + CCSR_PEX1_ENABLE) + + +#define CPU_CTRL_STAT_DEFAULT (CCSR_PEX0_ENABLE | \ + CCSR_PEX1_ENABLE | \ + CCSR_L2_PARITY_PROTECTION) + +/* Ratio options for CPU to DDR */ +#define CPU_2_DDR_CLK_1x1 1 +#define CPU_2_DDR_CLK_1x2 2 +#define CPU_2_DDR_CLK_1x3 3 +#define CPU_2_DDR_CLK_1x4 4 +#define CPU_2_DDR_CLK_1x5 5 +#define CPU_2_DDR_CLK_1x6 6 +#define CPU_2_DDR_CLK_1x7 7 + +/* Default values for CPU to Mbus-L DDR Interface Tick Driver and */ +/* CPU to Mbus-L Tick Sample fields in CPU config register */ +#define TICK_DRV_1x2 0 +#define TICK_SMPL_1x2 0 +#define TICK_DRV_1x3 1 +#define TICK_SMPL_1x3 2 +#define TICK_DRV_1x4 2 +#define TICK_SMPL_1x4 2 + +#define CPU_2_AHB_DDR_CLK_1x2 \ + ((TICK_DRV_1x2 << CCR_CPU_2_AHB_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x2 << CCR_CPU_2_AHB_TICK_SMPL_OFFS)) +#define CPU_2_AHB_DDR_CLK_1x3 \ + ((TICK_DRV_1x3 << CCR_CPU_2_AHB_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x3 << CCR_CPU_2_AHB_TICK_SMPL_OFFS)) +#define CPU_2_AHB_DDR_CLK_1x4 \ + ((TICK_DRV_1x4 << CCR_CPU_2_AHB_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x4 << CCR_CPU_2_AHB_TICK_SMPL_OFFS)) + + +#define CPU_FTDLL_IC_CONFIG_DEFAULT 0x1b +#define CPU_FTDLL_DC_CONFIG_DEFAULT 0x2 + + +#endif /* __INCmvCpuIfConfigh */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfRegs.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfRegs.h new file mode 100644 index 0000000..d29855b --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvCpuIfRegs.h @@ -0,0 +1,245 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfRegsh +#define __INCmvCpuIfRegsh + +/****************************************/ +/* ARM Control and Status Registers Map */ +/****************************************/ +#define CPU_CONFIG_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x100) +#define CPU_CTRL_STAT_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x104) +#define CPU_AHB_MBUS_CAUSE_INT_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x110) +#define CPU_AHB_MBUS_MASK_INT_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x114) +#define CPU_PM_CTRL_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x11C) +#define CPU_TIMING_ADJUST_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x120) +#define CPU_L1_RAM_TIMING0_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x128) +#define CPU_L1_RAM_TIMING1_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x12C) +#define CPU_MBUS_TIMEOUT_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x130) +#define CPU_L2_RAM_TIMING0_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x134) +#define CPU_L2_RAM_TIMING1_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x138) +#define CPU_MEMORY_PM_CTRL_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x140) +#define CPU_L2_RAM_PM_CTRL_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x144) + +/* ARM Configuration register */ +/* CPU_CONFIG_REG (CCR) */ + +/* Reset vector location */ +#define CCR_VEC_INIT_LOC_OFFS 1 +#define CCR_VEC_INIT_LOC_MASK BIT1 +/* reset at 0x00000000 */ +#define CCR_VEC_INIT_LOC_0000 (0 << CCR_VEC_INIT_LOC_OFFS) +/* reset at 0xFFFF0000 */ +#define CCR_VEC_INIT_LOC_FF00 (1 << CCR_VEC_INIT_LOC_OFFS) + +#define CCR_AHB_ERROR_PROP_OFFS 2 +#define CCR_AHB_ERROR_PROP_MASK BIT2 +/* Erros are not propogated to AHB */ +#define CCR_AHB_ERROR_PROP_NO_INDICATE (0 << CCR_AHB_ERROR_PROP_OFFS) +/* Erros are propogated to AHB */ +#define CCR_AHB_ERROR_PROP_INDICATE (1 << CCR_AHB_ERROR_PROP_OFFS) + + +#define CCR_ENDIAN_INIT_OFFS 3 +#define CCR_ENDIAN_INIT_MASK BIT3 +#define CCR_ENDIAN_INIT_LITTLE (0 << CCR_ENDIAN_INIT_OFFS) +#define CCR_ENDIAN_INIT_BIG (1 << CCR_ENDIAN_INIT_OFFS) + +#define CCR_CPU_ID_OFFS 4 +#define CCR_CPU_ID_MASK BIT4 +#define CCR_ARM_CPU_ID (0 << CCR_CPU_ID_OFFS) +#define CCR_MRVL_CPU_ID (1 << CCR_CPU_ID_OFFS) + + +#define CCR_MMU_DISABLED_OFFS 5 +#define CCR_MMU_DISABLED_MASK (1 << CCR_MMU_DISABLED_OFFS) +#define CCR_MMU_ENABLED (0 << CCR_MMU_DISABLED_OFFS) +#define CCR_MMU_DISABLED (1 << CCR_MMU_DISABLED_OFFS) + +#define CCR_CPU_2_AHB_TICK_DRV_OFFS 8 +#define CCR_CPU_2_AHB_TICK_DRV_MASK (0xF << CCR_CPU_2_AHB_TICK_DRV_OFFS) +#define CCR_CPU_2_AHB_TICK_SMPL_OFFS 12 +#define CCR_CPU_2_AHB_TICK_SMPL_MASK (0xF << CCR_CPU_2_AHB_TICK_SMPL_OFFS) +#define CCR_ICACH_PREF_BUF_ENABLE BIT16 +#define CCR_DCACH_PREF_BUF_ENABLE BIT17 + +#define CCR_AHB_ERROR_PROP_OFFS 2 +#define CCR_AHB_ERROR_PROP_MASK BIT2 +/* Erros are not propogated to AHB */ +#define CCR_AHB_ERROR_PROP_NO_INDICATE (0 << CCR_AHB_ERROR_PROP_OFFS) +/* Erros are propogated to AHB */ +#define CCR_AHB_ERROR_PROP_INDICATE (1 << CCR_AHB_ERROR_PROP_OFFS) + +/* ARM Control and Status register */ +/* CPU_CTRL_STAT_REG (CCSR) */ + + +/* +This is used to block PCI express\PCI from access Socrates/Feroceon GP +while ARM boot is still in progress +*/ + +#define CCSR_PEX0_ENABLE BIT0 +#define CCSR_PEX1_ENABLE BIT1 +#define CCSR_ARM_RESET BIT3 +#define CCSR_SELF_INT BIT2 +#define CCSR_BIG_ENDIAN BIT15 +#define CCSR_L2WT BIT17 +#define CCSR_DDR_RD_WIDTH BIT18 +#define CCSR_DDR_WR_WIDTH BIT19 +#define CCSR_L2_PARITY_PROTECTION BIT24 + +/* Mbus-L to Mbus Bridge Interrupt Cause Register*/ +/* CPU_AHB_MBUS_CAUSE_INT_REG (CAMCIR) */ + +#define CMMCIR_ARM_SELF_INT BIT0 +#define CMMCIR_ARM_TIMER0_INT_REQ BIT1 +#define CMMCIR_ARM_TIMER1_INT_REQ BIT2 +#define CMMCIR_ARM_WD_TIMER_INT_REQ BIT3 +#define CMMCIR_ARM_TIMER2_INT_REQ BIT6 +#define CMMCIR_ARM_TIMER3_INT_REQ BIT7 + + +/* Mbus-L to Mbus Bridge Interrupt Mask Register*/ +/* CPU_AHB_MBUS_MASK_INT_REG (CAMMIR) */ + +#define CMMCIR_ARM_SELF_INT_OFFS 0 +#define CMMCIR_ARM_SELF_INT_MASK BIT0 +#define CMMCIR_ARM_SELF_INT_EN (1 << CMMCIR_ARM_SELF_INT_OFFS) +#define CMMCIR_ARM_SELF_INT_DIS (0 << CMMCIR_ARM_SELF_INT_OFFS) + + +#define CMMCIR_ARM_TIMER0_INT_REQ_OFFS 1 +#define CMMCIR_ARM_TIMER0_INT_REQ_MASK BIT1 +#define CMMCIR_ARM_TIMER0_INT_REQ_EN (1 << CMMCIR_ARM_TIMER0_INT_REQ_OFFS) +#define CMMCIR_ARM_TIMER0_INT_REQ_DIS (0 << CMMCIR_ARM_TIMER0_INT_REQ_OFFS) + +#define CMMCIR_ARM_TIMER1_INT_REQ_OFFS 2 +#define CMMCIR_ARM_TIMER1_INT_REQ_MASK BIT2 +#define CMMCIR_ARM_TIMER1_INT_REQ_EN (1 << CMMCIR_ARM_TIMER1_INT_REQ_OFFS) +#define CMMCIR_ARM_TIMER1_INT_REQ_DIS (0 << CMMCIR_ARM_TIMER1_INT_REQ_OFFS) + +#define CMMCIR_ARM_TIMER2_INT_REQ_OFFS 6 +#define CMMCIR_ARM_TIMER2_INT_REQ_MASK BIT6 +#define CMMCIR_ARM_TIMER2_INT_REQ_EN (1 << CMMCIR_ARM_TIMER0_INT_REQ_OFFS) +#define CMMCIR_ARM_TIMER2_INT_REQ_DIS (0 << CMMCIR_ARM_TIMER0_INT_REQ_OFFS) + +#define CMMCIR_ARM_TIMER3_INT_REQ_OFFS 7 +#define CMMCIR_ARM_TIMER3_INT_REQ_MASK BIT7 +#define CMMCIR_ARM_TIMER3_INT_REQ_EN (1 << CMMCIR_ARM_TIMER1_INT_REQ_OFFS) +#define CMMCIR_ARM_TIMER3_INT_REQ_DIS (0 << CMMCIR_ARM_TIMER1_INT_REQ_OFFS) + + +#define CMMCIR_ARM_WD_TIMER_INT_REQ_OFFS 3 +#define CMMCIR_ARM_WD_TIMER_INT_REQ_MASK BIT3 +#define CMMCIR_ARM_WD_TIMER_INT_REQ_EN (1 << CMMCIR_ARM_WD_TIMER_INT_REQ_OFFS) +#define CMMCIR_ARM_WD_TIMER_INT_REQ_DIS (0 << CMMCIR_ARM_WD_TIMER_INT_REQ_OFFS) + + +/*******************************************/ +/* Main Interrupt Controller Registers Map */ +/*******************************************/ + +#define CPU_INT_ERROR_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x200) +#define CPU_INT_LOW_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x204) +#define CPU_INT_HIGH_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x208) +#define CPU_INT_MASK_ERROR_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x20C) +#define CPU_INT_MASK_LOW_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x210) +#define CPU_INT_MASK_HIGH_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x214) +#define CPU_INT_SELECT_CAUSE_REG(cpu) (AHB_TO_MBUS_BASE(cpu) + 0x218) + + +/*******************************************/ +/* Power Management control */ +/*******************************************/ + +#define CPMCR_CLOCK_REALIGN BIT0 +#define CPMCR_GBE_POWER_UP(num) (BIT1 << (num)) +#define CPMCR_PEX_POWER_UP(num, bar) ((BIT5 << (bar)) << ((num)*4)) +#define CPMCR_SATA_PHY_POWER_UP(num) (BIT13 << (num*2)) +#define CPMCR_SATA_HC_POWER_UP(num) (BIT14 << (num*2)) +#define CPMCR_USB_POWER_UP(num) (BIT17 << (num)) +#define CPMCR_IDMA_POWER_UP BIT20 +#define CPMCR_XOR_POWER_UP BIT21 +#define CPMCR_CRYPTO_POWER_UP BIT22 +#define CPMCR_DEVICE_POWER_UP BIT23 + + + + +/*******************************************/ +/* ARM Doorbell Registers Map */ +/*******************************************/ + +#define CPU_HOST_TO_ARM_DRBL_REG (AHB_TO_MBUS_BASE(cpu) + 0x400) +#define CPU_HOST_TO_ARM_MASK_REG (AHB_TO_MBUS_BASE(cpu) + 0x404) +#define CPU_ARM_TO_HOST_DRBL_REG (AHB_TO_MBUS_BASE(cpu) + 0x408) +#define CPU_ARM_TO_HOST_MASK_REG (AHB_TO_MBUS_BASE(cpu) + 0x40C) + + + + +#endif /* __INCmvCpuIfRegsh */ + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.c new file mode 100644 index 0000000..71270f0 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.c @@ -0,0 +1,379 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvSysCesa.h" +#include "cpu/mvCpu.h" + +#if (MV_CESA_VERSION >= 2) +MV_TARGET tdmaAddrDecPrioTable[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif + + TBL_TERM +}; + +/******************************************************************************* +* mvCesaWinGet - Get TDMA target address window. +* +* DESCRIPTION: +* Get TDMA target address window. +* +* INPUT: +* winNum - TDMA target address decode window number. +* +* OUTPUT: +* pDecWin - TDMA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvCesaWinGet(MV_U32 winNum, MV_DEC_WIN *pDecWin) +{ + MV_DEC_WIN_PARAMS winParam; + MV_U32 sizeReg, baseReg; + + /* Parameter checking */ + if (winNum >= MV_CESA_TDMA_ADDR_DEC_WIN) + { + mvOsPrintf("%s : ERR. Invalid winNum %d\n", + __FUNCTION__, winNum); + return MV_NOT_SUPPORTED; + } + + baseReg = MV_REG_READ( MV_CESA_TDMA_BASE_ADDR_REG(winNum) ); + sizeReg = MV_REG_READ( MV_CESA_TDMA_WIN_CTRL_REG(winNum) ); + + /* Check if window is enabled */ + if(sizeReg & MV_CESA_TDMA_WIN_ENABLE_MASK) + { + pDecWin->enable = MV_TRUE; + + /* Extract window parameters from registers */ + winParam.targetId = (sizeReg & MV_CESA_TDMA_WIN_TARGET_MASK) >> MV_CESA_TDMA_WIN_TARGET_OFFSET; + winParam.attrib = (sizeReg & MV_CESA_TDMA_WIN_ATTR_MASK) >> MV_CESA_TDMA_WIN_ATTR_OFFSET; + winParam.size = (sizeReg & MV_CESA_TDMA_WIN_SIZE_MASK) >> MV_CESA_TDMA_WIN_SIZE_OFFSET; + winParam.baseAddr = (baseReg & MV_CESA_TDMA_WIN_BASE_MASK); + + /* Translate the decode window parameters to address decode struct */ + if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin)) + { + mvOsPrintf("Failed to translate register parameters to CESA address" \ + " decode window structure\n"); + return MV_ERROR; + } + } + else + { + pDecWin->enable = MV_FALSE; + } + return MV_OK; +} + +/******************************************************************************* +* cesaWinOverlapDetect - Detect CESA TDMA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case TDMA address decode +* windows overlapps. +* This function detects TDMA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - if the given address window overlap current address +* decode map, +* MV_FALSE - otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS cesaWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_CESA_TDMA_ADDR_DEC_WIN) + { + mvOsPrintf("mvCesaTdmaWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == cesaWinOverlapDetect(winNum, &pDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) + { + mvOsPrintf("mvCesaTdmaWinSet: Error setting CESA TDMA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pDecWin->target), + pDecWin->addrWin.baseLow, + pDecWin->addrWin.size); + return MV_ERROR; + } + + if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams)) + { + mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* set Size, Attributes and TargetID */ + sizeReg = (((winParams.targetId << MV_CESA_TDMA_WIN_TARGET_OFFSET) & MV_CESA_TDMA_WIN_TARGET_MASK) | + ((winParams.attrib << MV_CESA_TDMA_WIN_ATTR_OFFSET) & MV_CESA_TDMA_WIN_ATTR_MASK) | + ((winParams.size << MV_CESA_TDMA_WIN_SIZE_OFFSET) & MV_CESA_TDMA_WIN_SIZE_MASK)); + + if (pDecWin->enable == MV_TRUE) + { + sizeReg |= MV_CESA_TDMA_WIN_ENABLE_MASK; + } + else + { + sizeReg &= ~MV_CESA_TDMA_WIN_ENABLE_MASK; + } + + /* Update Base value */ + baseReg = (winParams.baseAddr & MV_CESA_TDMA_WIN_BASE_MASK); + + MV_REG_WRITE( MV_CESA_TDMA_WIN_CTRL_REG(winNum), sizeReg); + MV_REG_WRITE( MV_CESA_TDMA_BASE_ADDR_REG(winNum), baseReg); + + return MV_OK; +} + + +MV_STATUS mvCesaTdmaAddrDecInit (void) +{ + MV_U32 winNum; + MV_STATUS status; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_DEC_WIN cesaWin; + MV_U32 winPrioIndex = 0; + + /* First disable all address decode windows */ + for(winNum=0; winNum= 2 */ + + + + +MV_STATUS mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle) +{ + MV_U32 cesaCryptEngBase; + MV_CPU_DEC_WIN addrDecWin; + + if(sizeof(MV_CESA_SRAM_MAP) > MV_CESA_SRAM_SIZE) + { + mvOsPrintf("mvCesaInit: Wrong SRAM map - %d > %d\n", + sizeof(MV_CESA_SRAM_MAP), MV_CESA_SRAM_SIZE); + return MV_FAIL; + } + + if (mvCpuIfTargetWinGet(CRYPT_ENG, &addrDecWin) == MV_OK) + cesaCryptEngBase = addrDecWin.addrWin.baseLow; + else + { + mvOsPrintf("mvCesaInit: ERR. mvCpuIfTargetWinGet failed\n"); + return MV_ERROR; + } + +#if (MV_CESA_VERSION >= 2) + mvCesaTdmaAddrDecInit(); +#endif /* MV_CESA_VERSION >= 2 */ + + return mvCesaHalInit(numOfSession, queueDepth, pSramBase, cesaCryptEngBase, + osHandle); + +} diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.h new file mode 100644 index 0000000..73bcdc5 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysCesa.h @@ -0,0 +1,100 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __mvSysCesa_h__ +#define __mvSysCesa_h__ + + +#include "mvCommon.h" +#include "cesa/mvCesa.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/sys/mvCpuIf.h" + +/***************************** TDMA Registers *************************************/ + +#define MV_CESA_TDMA_ADDR_DEC_WIN 4 + +#define MV_CESA_TDMA_BASE_ADDR_REG(win) (MV_CESA_TDMA_REG_BASE + 0xa00 + (win<<3)) + +#define MV_CESA_TDMA_WIN_CTRL_REG(win) (MV_CESA_TDMA_REG_BASE + 0xa04 + (win<<3)) + +#define MV_CESA_TDMA_WIN_ENABLE_BIT 0 +#define MV_CESA_TDMA_WIN_ENABLE_MASK (1 << MV_CESA_TDMA_WIN_ENABLE_BIT) + +#define MV_CESA_TDMA_WIN_TARGET_OFFSET 4 +#define MV_CESA_TDMA_WIN_TARGET_MASK (0xf << MV_CESA_TDMA_WIN_TARGET_OFFSET) + +#define MV_CESA_TDMA_WIN_ATTR_OFFSET 8 +#define MV_CESA_TDMA_WIN_ATTR_MASK (0xff << MV_CESA_TDMA_WIN_ATTR_OFFSET) + +#define MV_CESA_TDMA_WIN_SIZE_OFFSET 16 +#define MV_CESA_TDMA_WIN_SIZE_MASK (0xFFFF << MV_CESA_TDMA_WIN_SIZE_OFFSET) + +#define MV_CESA_TDMA_WIN_BASE_OFFSET 16 +#define MV_CESA_TDMA_WIN_BASE_MASK (0xFFFF << MV_CESA_TDMA_WIN_BASE_OFFSET) + + +MV_STATUS mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle); + +#endif diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.c new file mode 100644 index 0000000..5da1478 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.c @@ -0,0 +1,363 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ + +#include "ddr2/mvDramIf.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/sys/mvSysDram.h" + +/* #define MV_DEBUG */ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +static MV_BOOL sdramIfWinOverlap(MV_U32 cpu, MV_TARGET target, MV_ADDR_WIN *pAddrWin); + +/******************************************************************************* +* mvDramIfWinSet - Set DRAM interface address decode window +* +* DESCRIPTION: +* This function sets DRAM interface address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* pAddrDecWin - SDRAM address window structure. +* +* OUTPUT: +* None +* +* RETURN: +* MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK +* otherwise. +*******************************************************************************/ +MV_STATUS mvDramIfWinSet(MV_U32 cpu, MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) +{ + MV_U32 baseReg=0,sizeReg=0; + MV_U32 baseToReg=0 , sizeToReg=0; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinSet: target %d is not SDRAM\n", target); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlaps with current enabled windows */ + if (MV_TRUE == sdramIfWinOverlap(cpu, target, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvDramIfWinSet: ERR. Target %d overlaps\n", target); + return MV_BAD_PARAM; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvDramIfWinSet:Error setting DRAM interface window %d."\ + "\nAddress 0x%08x is unaligned to size 0x%x.\n", + target, + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + /* read base register*/ + baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(cpu,target)); + + /* read size register */ + sizeReg = MV_REG_READ(SDRAM_SIZE_REG(cpu,target)); + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->addrWin.baseLow & SCBAR_BASE_MASK; + + /* Write to address decode Base Address Register */ + baseReg &= ~SCBAR_BASE_MASK; + baseReg |= baseToReg; + + /* Translate the given window size to register format */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, SCSR_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n",target); + return MV_BAD_PARAM; + } + + /* set size */ + sizeReg &= ~SCSR_SIZE_MASK; + /* Size is located at upper 16 bits */ + sizeReg |= (sizeToReg << SCSR_SIZE_OFFS); + + /* enable/Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + sizeReg |= SCSR_WIN_EN; + } + else + { + sizeReg &= ~SCSR_WIN_EN; + } + + /* 3) Write to address decode Base Address Register */ + MV_REG_WRITE(SDRAM_BASE_ADDR_REG(cpu,target), baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(SDRAM_SIZE_REG(cpu,target), sizeReg); + + return MV_OK; +} +/******************************************************************************* +* mvDramIfWinGet - Get DRAM interface address decode window +* +* DESCRIPTION: +* This function gets DRAM interface address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* +* OUTPUT: +* pAddrDecWin - SDRAM address window structure. +* +* RETURN: +* MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK +* otherwise. +*******************************************************************************/ +MV_STATUS mvDramIfWinGet(MV_U32 cpu, MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) +{ + MV_U32 baseReg,sizeReg; + MV_U32 sizeRegVal; + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinGet: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* Read base and size registers */ + sizeReg = MV_REG_READ(SDRAM_SIZE_REG(cpu,target)); + baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(cpu,target)); + + sizeRegVal = (sizeReg & SCSR_SIZE_MASK) >> SCSR_SIZE_OFFS; + + pAddrDecWin->addrWin.size = ctrlRegToSize(sizeRegVal, + SCSR_SIZE_ALIGNMENT); + + /* Check if ctrlRegToSize returned OK */ + if (-1 == pAddrDecWin->addrWin.size) + { + mvOsPrintf("mvDramIfWinGet: size of target %d is Illigal\n", target); + return MV_ERROR; + } + + /* Extract base address */ + /* Base register [31:16] ==> baseLow[31:16] */ + pAddrDecWin->addrWin.baseLow = baseReg & SCBAR_BASE_MASK; + + pAddrDecWin->addrWin.baseHigh = 0; + + + if (sizeReg & SCSR_WIN_EN) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} +/******************************************************************************* +* mvDramIfWinEnable - Enable/Disable SDRAM address decode window +* +* DESCRIPTION: +* This function enable/Disable SDRAM address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR in case function parameter are invalid, MV_OK otherewise. +* +*******************************************************************************/ +MV_STATUS mvDramIfWinEnable(MV_U32 cpu, MV_TARGET target, MV_BOOL enable) +{ + MV_DRAM_DEC_WIN addrDecWin; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinEnable: target %d is Illigal\n", target); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + if (MV_OK != mvDramIfWinGet(cpu, target, &addrDecWin)) + { + mvOsPrintf("mvDramIfWinEnable:ERR. Getting target %d failed.\n", + target); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == sdramIfWinOverlap(cpu, target, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode winNum window */ + MV_REG_BIT_SET(SDRAM_SIZE_REG(cpu,target), SCSR_WIN_EN); + } + else + { /* Overlap detected */ + mvOsPrintf("mvDramIfWinEnable: ERR. Target %d overlap detect\n", + target); + return MV_ERROR; + } + } + else + { /* Disable address decode winNum window */ + MV_REG_BIT_RESET(SDRAM_SIZE_REG(cpu, target), SCSR_WIN_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* sdramIfWinOverlap - Check if an address window overlap an SDRAM address window +* +* DESCRIPTION: +* This function scan each SDRAM address decode window to test if it +* overlapps the given address windoow +* +* INPUT: +* target - SDRAM target where the function skips checking. +* pAddrDecWin - The tested address window for overlapping with +* SDRAM windows. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlaps any enabled address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL sdramIfWinOverlap(MV_U32 cpu, MV_TARGET target, MV_ADDR_WIN *pAddrWin) +{ + MV_TARGET targetNum; + MV_DRAM_DEC_WIN addrDecWin; + + for(targetNum = SDRAM_CS0; targetNum < MV_DRAM_MAX_CS ; targetNum++) + { + /* don't check our winNum or illegal targets */ + if (targetNum == target) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvDramIfWinGet(cpu, targetNum, &addrDecWin)) + { + mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n"); + return MV_ERROR; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + mvOsPrintf( + "sdramIfWinOverlap: Required target %d overlap winNum %d\n", + target, targetNum); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +#if defined(MV78200) +MV_VOID mvDramIfCpuWinCopy(MV_VOID) +{ + MV_U32 i; + + for(i = 0; i < MV_DRAM_MAX_CS; i++) + { + MV_REG_WRITE(SDRAM_SIZE_REG(1, i), + MV_REG_READ(SDRAM_SIZE_REG(0, i))); + MV_REG_WRITE(SDRAM_BASE_ADDR_REG(1, i), + MV_REG_READ(SDRAM_BASE_ADDR_REG(0, i))); + } +} +#endif + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.h new file mode 100644 index 0000000..7c59e73 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysDram.h @@ -0,0 +1,82 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __sysDram +#define __sysDram + +/* This structure describes CPU interface address decode window */ +typedef struct _mvDramIfDecWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ +}MV_DRAM_DEC_WIN; + +MV_STATUS mvDramIfWinSet(MV_U32 cpu, MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin); +MV_STATUS mvDramIfWinGet(MV_U32 cpu, MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin); +MV_STATUS mvDramIfWinEnable(MV_U32 cpu, MV_TARGET target, MV_BOOL enable); +#if defined(MV78200) +MV_VOID mvDramIfCpuWinCopy(MV_VOID); +#endif +#endif diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysGbe.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysGbe.c new file mode 100644 index 0000000..b1f0a34 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysGbe.c @@ -0,0 +1,656 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "ctrlEnv/sys/mvSysGbe.h" +#include "cpu/mvCpu.h" + + +typedef struct _mvEthDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_ETH_DEC_WIN; + +MV_TARGET ethAddrDecPrioTap[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_DEVICE_CS0) + DEVICE_CS0, +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + DEVICE_CS1, +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + DEVICE_CS2, +#endif +#if defined(MV_INCLUDE_DEVICE_CS3) + DEVICE_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PCI0_IO, +#endif + TBL_TERM +}; + +static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin); +static MV_STATUS mvEthWinSet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); +static MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); + + +/******************************************************************************* +* mvEthWinInit - Initialize ETH address decode windows +* +* DESCRIPTION: +* This function initialize ETH window decode unit. It set the +* default address decode windows of the unit. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if setting fail. +*******************************************************************************/ +/* Configure EthDrv memory map registes. */ +MV_STATUS mvEthWinInit (int port) +{ + MV_U32 winNum, status, winPrioIndex=0, i, regVal=0; + MV_ETH_DEC_WIN ethWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + static MV_U32 accessProtReg = 0; + +#if (MV_ETH_VERSION <= 1) + static MV_BOOL isFirst = MV_TRUE; + + if(isFirst == MV_FALSE) + { + MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg); + return MV_OK; + } + isFirst = MV_FALSE; +#endif /* MV_GIGA_ETH_VERSION */ + + /* Initiate Ethernet address decode */ + + /* First disable all address decode windows */ + for(winNum=0; winNum= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == ethWinOverlapDetect(port, winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvEthWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvEthWinSet: Error setting Ethernet window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + + decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); + decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvEthWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.baseReg &= ~ETH_WIN_ATTR_MASK; + decRegs.baseReg |= targetAttribs.attrib << ETH_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.baseReg &= ~ETH_WIN_TARGET_MASK; + decRegs.baseReg |= targetAttribs.targetId << ETH_WIN_TARGET_OFFS; + + /* for the safe side we disable the window before writing the new + values */ + mvEthWinEnable(port, winNum, MV_FALSE); + MV_REG_WRITE(ETH_WIN_BASE_REG(port, winNum), decRegs.baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(ETH_WIN_SIZE_REG(port, winNum), decRegs.sizeReg); + + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvEthWinEnable(port, winNum, MV_TRUE); + } + + return MV_OK; +} + +/******************************************************************************* +* mvETHWinGet - Get dma peripheral target address window. +* +* DESCRIPTION: +* Get ETH peripheral target address window. +* +* INPUT: +* winNum - ETH to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - ETH target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); + decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (decRegs.baseReg & ETH_WIN_ATTR_MASK) >> ETH_WIN_ATTR_OFFS; + targetAttrib.targetId = + (decRegs.baseReg & ETH_WIN_TARGET_MASK) >> ETH_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (~(MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port))) & (1 << winNum) ) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvEthWinEnable - Enable/disable a ETH to target address window +* +* DESCRIPTION: +* This function enable/disable a ETH to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling ETH accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - ETH to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvEthWinEnable(int port, MV_U32 winNum,MV_BOOL enable) +{ + MV_ETH_DEC_WIN addrDecWin; + + /* Parameter checking */ + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthTargetWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvEthWinGet(port, winNum, &addrDecWin)) + { + mvOsPrintf("mvEthTargetWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == ethWinOverlapDetect(port, winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_RESET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); + } + else + { /* Overlap detected */ + mvOsPrintf("mvEthTargetWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { /* Disable address decode target window */ + MV_REG_BIT_SET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); + } + return MV_OK; +} + +/******************************************************************************* +* mvEthWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* window number +* +*******************************************************************************/ +MV_U32 mvEthWinTargetGet(int port, MV_TARGET target) +{ + MV_ETH_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + for (winNum=0; winNum= mvCtrlEthMaxPortGet()) + { + mvOsPrintf("mvEthProtWinSet:ERR. Invalid port number %d\n", portNo); + return MV_ERROR; + } + + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthProtWinSet:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) + { + mvOsPrintf("mvEthProtWinSet:ERR. Inv access param %d\n", access); + return MV_ERROR; + } + /* Read current protection register */ + protReg = MV_REG_READ(ETH_ACCESS_PROTECT_REG(portNo)); + + /* Clear protection window field */ + protReg &= ~(ETH_PROT_WIN_MASK(winNum)); + + /* Set new protection field value */ + protReg |= (access << (ETH_PROT_WIN_OFFS(winNum))); + + /* Write protection register back */ + MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(portNo), protReg); + + return MV_OK; +} + +/******************************************************************************* +* ethWinOverlapDetect - Detect ETH address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case ETH address decode +* windows overlapps. +* This function detects ETH address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex; + MV_ETH_DEC_WIN addrDecWin; + + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port)); + + for (winNumIndex=0; winNumIndex= IDMA_MAX_ADDR_DEC_WIN) + { + mvOsPrintf("mvDmaWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == dmaWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvDmaWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvDmaWinSet: Error setting IDMA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + + decRegs.baseReg = MV_REG_READ(IDMA_BASE_ADDR_REG(winNum)); + decRegs.sizeReg = MV_REG_READ(IDMA_SIZE_REG(winNum)); + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvDmaWinSet: mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + +#if defined(MV_INCLUDE_CESA) + /* See BTS Nastore #19.*/ + /* To access Tunit SRAM from IDMA use targetId = 0x5 */ + /* To access Tunit SRAM from the CPU use targetId = 0x9 */ + if(pAddrDecWin->target == CRYPT_ENG) + targetAttribs.targetId = 5; +#endif /* defined(MV_INCLUDE_CESA) */ + + /* set attributes */ + decRegs.baseReg &= ~IDMA_WIN_ATTR_MASK; + decRegs.baseReg |= targetAttribs.attrib << IDMA_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.baseReg &= ~IDMA_WIN_TARGET_MASK; + decRegs.baseReg |= targetAttribs.targetId << IDMA_WIN_TARGET_OFFS; + + /* for the safe side we disable the window before writing the new + values */ + mvDmaWinEnable(winNum,MV_FALSE); + + MV_REG_WRITE(IDMA_BASE_ADDR_REG(winNum), decRegs.baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(IDMA_SIZE_REG(winNum), decRegs.sizeReg); + + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvDmaWinEnable(winNum, MV_TRUE); + } + + return MV_OK; +} + +/******************************************************************************* +* mvDmaWinGet - Get dma peripheral target address window. +* +* DESCRIPTION: +* Get IDMA peripheral target address window. +* +* INPUT: +* winNum - IDMA to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - IDMA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvDmaWinGet(MV_U32 winNum, MV_DMA_DEC_WIN *pAddrDecWin) +{ + + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= IDMA_MAX_ADDR_DEC_WIN) + { + mvOsPrintf("mvDmaWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(IDMA_BASE_ADDR_REG(winNum)); + decRegs.sizeReg = MV_REG_READ(IDMA_SIZE_REG(winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvDmaWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (decRegs.baseReg & IDMA_WIN_ATTR_MASK) >> IDMA_WIN_ATTR_OFFS; + targetAttrib.targetId = + (decRegs.baseReg & IDMA_WIN_TARGET_MASK) >> IDMA_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (~(MV_REG_READ(IDMA_BASE_ADDR_ENABLE_REG)) & (IBAER_ENABLE(winNum))) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvDmaWinEnable - Enable/disable a DMA to target address window +* +* DESCRIPTION: +* This function enable/disable a DMA to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling DMA accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - IDMA to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvDmaWinEnable(MV_U32 winNum,MV_BOOL enable) +{ + MV_DMA_DEC_WIN addrDecWin; + + /* Parameter checking */ + if (winNum >= IDMA_MAX_ADDR_DEC_WIN) + { + mvOsPrintf("mvDmaWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvDmaWinGet(winNum, &addrDecWin)) + { + mvOsPrintf("mvDmaWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == dmaWinOverlapDetect(winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_RESET(IDMA_BASE_ADDR_ENABLE_REG, IBAER_ENABLE(winNum)); + } + else + { /* Overlap detected */ + mvOsPrintf("mvDmaWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { /* Disable address decode target window */ + MV_REG_BIT_SET(IDMA_BASE_ADDR_ENABLE_REG, IBAER_ENABLE(winNum)); + } + return MV_OK; +} + +/******************************************************************************* +* mvDmaWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* window number +* +*******************************************************************************/ +MV_U32 mvDmaWinTargetGet(MV_TARGET target) +{ + MV_DMA_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvDmaWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + for (winNum = 0; winNum < IDMA_MAX_ADDR_DEC_WIN ; winNum++) + { + if (mvDmaWinGet(winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvDmaWinTargetGet: mvDmaWinGet returned error\n"); + return 0xffffffff; + } + if (decWin.enable == MV_TRUE) + { + if (decWin.target == target) + { + return winNum; + } + } + } + return 0xFFFFFFFF; +} + +/******************************************************************************* +* mvDmaProtWinSet - Set access protection of IDMA to target window. +* +* DESCRIPTION: +* Each IDMA channel can be configured with access attributes for each +* of the IDMA to target windows (address decode windows). This +* function sets access attributes to a given window for the given channel. +* +* INPUTS: +* chan - IDMA channel number. See MV_DMA_CHANNEL enumerator. +* winNum - IDMA to target address decode window number. +* access - IDMA access rights. See MV_ACCESS_RIGHTS enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR in case window number is invalid or access right reserved. +* +*******************************************************************************/ +MV_STATUS mvDmaProtWinSet (MV_U32 chan, MV_U32 winNum, MV_ACCESS_RIGHTS access) +{ + MV_U32 protReg; + + /* Parameter checking */ + if ((chan >= MV_IDMA_MAX_CHAN) || (winNum >= IDMA_MAX_ADDR_DEC_WIN)) + { + mvOsPrintf("mvDmaProtWinSet:ERR. Invalid chan number %d\n", chan); + return MV_ERROR; + } + if((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) + { + mvOsPrintf("mvDmaProtWinSet:ERR. Inv access param %d\n", access); + return MV_ERROR; + } + /* Read current protection register */ + protReg = MV_REG_READ(IDMA_ACCESS_PROTECT_REG(chan)); + + /* Clear protection window field */ + protReg &= ~(ICAPR_PROT_WIN_MASK(winNum)); + + /* Set new protection field value */ + protReg |= (access << (ICAPR_PROT_WIN_OFFS(winNum))); + + /* Write protection register back */ + MV_REG_WRITE(IDMA_ACCESS_PROTECT_REG(chan), protReg); + + return MV_OK; +} + +/******************************************************************************* +* mvDmaOverrideSet - Set DMA target window override +* +* DESCRIPTION: +* The address override feature enables additional address decoupling. +* For example, it allows the use of the same source and destination +* addresses while the source is targeted to one interface and +* destination to a second interface. +* DMA source/destination/next descriptor addresses can be override per +* address decode windows 1, 2 and 3 only. +* This function set override parameters per DMA channel. It access +* DMA control register low. +* +* INPUT: +* chan - IDMA channel number. See MV_DMA_CHANNEL enumerator. +* winNum - Override window numver. +* Note: 1) Not all windows can override. +* 2) Window '0' means disable override. +* override - Type of override. See MV_DMA_OVERRIDE enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM in case window can not perform override. +* +*******************************************************************************/ +MV_STATUS mvDmaOverrideSet(MV_U32 chan, MV_U32 winNum, MV_DMA_OVERRIDE override) +{ + MV_U32 ctrlLowReg; + + /* Parameter checking */ + if ((chan >= MV_IDMA_MAX_CHAN) || (winNum >= IDMA_MAX_OVERRIDE_WIN)) + { + mvOsPrintf("mvDmaOverrideSet:ERR. Invalid chan num %d\n", chan); + return MV_ERROR; + } + /* Read control register */ + ctrlLowReg = MV_REG_READ(IDMA_CTRL_LOW_REG(chan)); + + switch (override) + { + case (DMA_SRC_ADDR): + ctrlLowReg &= ~ICCLR_OVRRD_SRC_MASK; /* Clear SRC field */ + ctrlLowReg |= ICCLR_OVRRD_SRC_BAR(winNum); /* Set reg field */ + break; + case (DMA_DST_ADDR): + ctrlLowReg &= ~ICCLR_OVRRD_DST_MASK; /* Clear DST field */ + ctrlLowReg |= ICCLR_OVRRD_DST_BAR(winNum); /* Set reg field */ + break; + case (DMA_NEXT_DESC): + ctrlLowReg &= ~ICCLR_OVRRD_NDSC_MASK; /* Clear N_Desc field*/ + ctrlLowReg |= ICCLR_OVRRD_NDSC_BAR(winNum); /* Set reg field */ + break; + default: + { + mvOsPrintf("mvDmaOverrideSet:ERR. Inv override param%d\n",override); + return MV_BAD_PARAM; + } + } + /* Write control word back */ + MV_REG_WRITE(IDMA_CTRL_LOW_REG(chan), ctrlLowReg); + + return MV_OK; +} + +/******************************************************************************* +* mvDmaPciRemap - Set DMA remap register for PCI address windows. +* +* DESCRIPTION: +* The PCI interface supports 64-bit addressing. Four of the eight +* address windows have an upper 32-bit address register. To access the +* PCI bus with 64-bit addressing cycles (DAC cycles), this function +* assigns one (or more) of these four windows to target the PCI bus. +* The address generated on the PCI bus is composed of the window base +* address and the High Remap register. +* +* INPUT: +* winNum - IDMA to target address decode window number. Only 0 - 3. +* addrHigh - upper 32-bit address. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if window number is not between 0 and 3. +* +*******************************************************************************/ +MV_STATUS mvDmaPciRemap(MV_U32 winNum, MV_U32 addrHigh) +{ + /* Parameter checking */ + if (winNum >= IDMA_MAX_OVERRIDE_WIN) + { + mvOsPrintf("mvDmaPciRemap:ERR. Invalid window num %d\n", winNum); + return MV_BAD_PARAM; + } + + MV_REG_WRITE(IDMA_HIGH_ADDR_REMAP_REG(winNum), addrHigh); + + return MV_OK; +} + +/******************************************************************************* +* dmaWinOverlapDetect - Detect DMA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case DMA address decode +* windows overlapps. +* This function detects DMA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS dmaWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex; + MV_DMA_DEC_WIN addrDecWin; + + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(IDMA_BASE_ADDR_ENABLE_REG); + + for (winNumIndex = 0; winNumIndex < IDMA_MAX_ADDR_DEC_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + + /* Do not check disabled windows */ + if (baseAddrEnableReg & (IBAER_ENABLE(winNumIndex))) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvDmaWinGet(winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("dmaWinOverlapDetect: ERR. TargetWinGet failed\n")); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + return MV_FALSE; +} + +/******************************************************************************* +* mvDmaAddrDecShow - Print the DMA address decode map. +* +* DESCRIPTION: +* This function print the DMA address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvDmaAddrDecShow(MV_VOID) +{ + + MV_DMA_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "DMA:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < IDMA_MAX_ADDR_DEC_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_DMA_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvDmaWinGet( i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} +/******************************************************************************* +* mvDmaAllStop - Stop any IDMA activity. +* +* DESCRIPTION: +* This function stops any DMA activity. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvDmaAllStop(MV_VOID) +{ + MV_U32 dmaChanNum; + + for(dmaChanNum = 0; dmaChanNum < MV_IDMA_MAX_CHAN; dmaChanNum++) + { + mvDmaCommandSet(dmaChanNum, MV_STOP); + } + + return; +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysIdma.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysIdma.h new file mode 100644 index 0000000..e16ca6d --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysIdma.h @@ -0,0 +1,143 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvSysIdmah +#define __INCmvSysIdmah + +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* General IDMA */ +#define IDMA_MAX_ADDR_DEC_WIN 8 /* Maximum address decode windows */ +#define IDMA_MAX_OVERRIDE_WIN 4 /* Maximum address override windows */ + +/* IDMA Address Decoding Base and size Registers */ +#define IDMA_BASE_ADDR_REG(winNum) (0x60a00 + ((winNum) * 8)) +#define IDMA_SIZE_REG(winNum) (0x60a04 + ((winNum) * 8)) + +/* IDMA Address Decoding High Address Remap,. Note that only window 0 - 3 */ +/* has remap capabilities */ +#define IDMA_HIGH_ADDR_REMAP_REG(winNum) (0x60a60 + ((winNum) * 4)) + +/* IDMA Base Addres enable register*/ +#define IDMA_BASE_ADDR_ENABLE_REG 0x60a80 + +/* IDMA Access Protection Registers */ +#define IDMA_ACCESS_PROTECT_REG(chan) (0x60a70 + ((chan) * 4)) + /* IDMA Headers Retarget Registers */ +#define IDMA_HEADERS_RETARGET_CTRL_REG 0x60a84 +#define IDMA_HEADERS_RETARGET_BASE_REG 0x60a88 + + +/* Base Addr reg */ +#define IDMA_WIN_TARGET_OFFS 0 /* The target interface associated with window*/ +#define IDMA_WIN_TARGET_MASK (0xf << IDMA_WIN_TARGET_OFFS) +#define IDMA_WIN_ATTR_OFFS 8 /* The target attributes Associated with window*/ +#define IDMA_WIN_ATTR_MASK (0xff << IDMA_WIN_ATTR_OFFS) + +/* IDMA Base Address Enable Register (IBAER) */ +#define IBAER_ENABLE_OFFS 0 +#define IBAER_ENABLE_MASK (0xFF << IBAER_ENABLE_OFFS) +#define IBAER_ENABLE(winNum) (1 << (winNum)) + +/* IDMA Channel Access Protect Register (ICAPR)*/ +#define ICAPR_PROT_NO_ACCESS NO_ACCESS_ALLOWED +#define ICAPR_PROT_READ_ONLY READ_ONLY +#define ICAPR_PROT_FULL_ACCESS FULL_ACCESS +#define ICAPR_PROT_WIN_OFFS(winNum) (2 * (winNum)) +#define ICAPR_PROT_WIN_MASK(winNum) (0x3 << ICAPR_PROT_WIN_OFFS(winNum)) + +/* This struct describes address decode override types */ +typedef enum _mvDmaOverride +{ + DMA_SRC_ADDR, /* Override source address */ + DMA_DST_ADDR, /* Override destination address */ + DMA_NEXT_DESC /* Override next descriptor address */ +}MV_DMA_OVERRIDE; + + +typedef struct _mvDmaDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_DMA_DEC_WIN; + +MV_STATUS mvDmaInit (MV_VOID); + +MV_STATUS mvDmaWinSet(MV_U32 winNum, MV_DMA_DEC_WIN *pAddrDecWin); +MV_STATUS mvDmaWinGet(MV_U32 winNum, MV_DMA_DEC_WIN *pAddrDecWin); +MV_STATUS mvDmaWinEnable(MV_U32 winNum,MV_BOOL enable); +MV_U32 mvDmaWinTargetGet(MV_TARGET target); + +MV_STATUS mvDmaProtWinSet (MV_U32 chan, MV_U32 winNum, MV_ACCESS_RIGHTS access); +MV_STATUS mvDmaOverrideSet(MV_U32 chan, MV_U32 winNum, MV_DMA_OVERRIDE override); +MV_STATUS mvDmaPciRemap(MV_U32 winNum, MV_U32 addrHigh); + +MV_VOID mvDmaAddrDecShow(MV_VOID); +MV_VOID mvDmaAllStop(MV_VOID); + +#endif /* __INCmvSysIdmaBarh */ + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.c new file mode 100644 index 0000000..4ade10f --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.c @@ -0,0 +1,1620 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "ctrlEnv/sys/mvSysPex.h" +#include "cpu/mvCpu.h" +#include "pex/mvPex.h" + +#ifdef MV_DEBUG +#define mvOsPrintf printf +#define DB(x) x +#else +#define DB(x) +#endif + +/* locals */ +/* this structure describes the mapping between a Pex Window and a CPU target*/ +typedef struct _pexWinToTarget +{ + MV_TARGET target; + MV_BOOL enable; +}PEX_WIN_TO_TARGET; + +/* this array is a priority array that define How Pex windows should be +configured , We have only 6 Pex Windows that can be configured , but we +have morethat that CPU target windows ! the following array is a priority +array where the lowest index has the highest priotiy and the highest +index has the lowest priority of being cnfigured */ +MV_U32 pexDevBarPrioTable[] = +{ + DEVICE_CS0, + DEVICE_CS1, + DEVICE_CS2, + DEV_BOOCS, + TBL_TERM +}; + +/* PEX Wins registers offsets are inconsecutive. This struct describes WIN */ +/* register offsets and its function where its is located. */ +/* Also, PEX address remap registers offsets are inconsecutive. This struct */ +/* describes address remap register offsets */ +typedef struct _pexWinRegInfo +{ + MV_U32 winCtrlRegOffs; + MV_U32 winBaseRegOffs; + MV_U32 winRemapLowRegOffs; + MV_U32 winRemapHighRegOffs; + +}PEX_WIN_REG_INFO; + +static MV_STATUS pexWinOverlapDetect(MV_U32 pexIf, MV_U32 winNum, + MV_ADDR_WIN *pAddrWin); +static MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, MV_U32 winNum, + PEX_WIN_REG_INFO *pWinRegInfo); +static MV_STATUS pexBarIsValid(MV_U32 baseLow, MV_U32 size); +static MV_BOOL pexIsWinWithinBar(MV_U32 pexIf,MV_ADDR_WIN *pAddrWin); +static MV_BOOL pexBarOverlapDetect(MV_U32 pexIf,MV_U32 barNum, + MV_ADDR_WIN *pAddrWin); +static MV_VOID mvPexDecWinShow(MV_U32 pexIf); + +/******************************************************************************* +* mvPexInit - Initialize PEX interfaces +* +* DESCRIPTION: +* +* This function is responsible of intialization of the Pex Interface , It +* configure the Pex Bars and Windows in the following manner: +* +* Assumptions : +* Bar0 is always internal registers bar +* Bar1 is always the DRAM bar +* Bar2 is always the Device bar +* +* 1) Sets the Internal registers bar base by obtaining the base from +* the CPU Interface +* 2) Sets the DRAM bar base and size by getting the base and size from +* the CPU Interface when the size is the sum of all enabled DRAM +* chip selects and the base is the base of CS0 . +* 3) Sets the Device bar base and size by getting these values from the +* CPU Interface when the base is the base of the lowest base of the +* Device chip selects, and the +* +* +* INPUT: +* +* pexIf - PEX interface number. +* +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM +* +*******************************************************************************/ +MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType) +{ + MV_U32 bar; + MV_U32 winNum,winIndex; + MV_PEX_BAR pexBar; + MV_PEX_DEC_WIN pexWin; + MV_CPU_DEC_WIN addrDecWin; + MV_TARGET target; + MV_U32 pexStartWindow; + MV_U32 pexCurrWin=0; + MV_U32 status; + /* default and expansion ROM are always configured */ + MV_U32 maxBase=0,sizeOfMaxBase=0; + MV_U32 dramSize = mvDramIfSizeGet(); + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexInit: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + /* Start with bars */ + /* First disable all PEX bars*/ + for (bar = 0; bar < PEX_MAX_BARS; bar++) + { + if (PEX_INTER_REGS_BAR != bar) + { + if (MV_OK != mvPexBarEnable(pexIf, bar, MV_FALSE)) + { + mvOsPrintf("mvPexInit: Closing all BARs failed at bar %d\n",bar); + return MV_ERROR; + } + } + } + + /* and disable all PEX target windows */ + for (winNum = 0; winNum < PEX_GRNERAL_WIN_NUM; winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_FALSE)) + { + mvOsPrintf("mvPexInit: Disable all windows failed at win %d\n",winNum); + return MV_ERROR; + } + } + + /* Now, go through all bars*/ + +/******************************************************************************/ +/* Internal registers bar */ +/******************************************************************************/ + + /* first get the CS attribute from the CPU Interface */ + if (MV_OK !=mvCpuIfTargetWinGet(INTER_REGS,&addrDecWin)) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",INTER_REGS); + return MV_ERROR; + } + + /* mvOsPrintf("mvPexInit: dramSize =%dGBYTE\n",dramSize/_1M); */ + if (dramSize > _2G) + { + pexBar.addrWin.baseHigh = 1; + } + else + { + pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + } + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexBar.addrWin.size = addrDecWin.addrWin.size; + pexBar.enable = MV_TRUE; + + if (MV_OK != mvPexBarSet(pexIf, PEX_INTER_REGS_BAR, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", PEX_INTER_REGS_BAR); + return MV_ERROR; + } + +/******************************************************************************/ +/* DRAM bar */ +/******************************************************************************/ + + bar = PEX_DRAM_BAR; + + pexBar.addrWin.size = 0; + + for (target = SDRAM_CS0;target <= SDRAM_CS3; target++ ) + { + status = mvCpuIfTargetWinGet(target, &addrDecWin); + if((MV_NO_SUCH == status) && (target != SDRAM_CS0)) + { + continue; + } + /* first get attributes from CPU If */ + if (MV_OK != status) + { + mvOsPrintf("mvPexInit: ERR. Getting DRAM address decode window "\ + "%d from CPU interface failed\n",target - SDRAM_CS0); + return MV_ERROR; + } + + DB(mvOsPrintf("mvPexInit: target %d, size =%d MBYTE \n",target,addrDecWin.addrWin.size/_1M)); + if (addrDecWin.enable == MV_TRUE) + { + /* the base is the First DIMM on address 0 */ + if (mvDramIfGetFirstCS() == target ) + { + pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + } + + /* Accumulate bar size */ + pexBar.addrWin.size += addrDecWin.addrWin.size; + + + /* set a Pex window for this target ! + DRAM CS always will have a Pex Window , and is not a + part of the priority table */ + pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexWin.addrWin.size = addrDecWin.addrWin.size; + + /* we disable the windows at first because we are not + sure that it is witihin bar boundries */ + pexWin.enable =MV_FALSE; + pexWin.target = target; + pexWin.targetBar = bar; + + if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++,&pexWin)) + { + mvOsPrintf("mvPexInit: ERR. mvPexTargetWinSet failed\n"); + return MV_ERROR; + } + } + if (pexBar.addrWin.size >= (_2G + _1G)) + { + break; + } + } + + /* check if the size of the bar is illeggal */ + pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); + + /* check if the size and base are valid */ + if (MV_TRUE == pexBarOverlapDetect(pexIf, bar, &pexBar.addrWin)) + { + mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n",bar); + mvOsPrintf("it will be disabled\n"); + mvOsPrintf("please check Pex and CPU windows configuration\n"); + } + else + { + pexBar.enable = MV_TRUE; + + /* configure the bar */ + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + + /* after the bar was configured then we enable the Pex windows*/ + for (winNum = 0;winNum < pexCurrWin ;winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) + { + mvOsPrintf("mvPexInit: Can't enable window =%d\n",winNum); + return MV_ERROR; + } + + } + } + + +/******************************************************************************/ +/* DEVICE bar */ +/******************************************************************************/ + + /* then device bar*/ + bar = PEX_DEVICE_BAR; + + /* save the starting window */ + pexStartWindow = pexCurrWin; + maxBase = 0; + if (dramSize <= _2G) + { + pexBar.addrWin.size = 0; + pexBar.addrWin.baseLow = 0xffffffff; + pexBar.addrWin.baseHigh = 0; + } + else + { + /********************************************/ + /* DEVICE bar config windows over 2G */ + /********************************************/ + target++; + /* the base is the base of DRAM CS0 always */ + pexBar.addrWin.baseHigh = 0; + pexBar.addrWin.baseLow = _2G; + pexBar.addrWin.size = _2G; + for ( ;target <= SDRAM_CS3; target++ ) + { + status = mvCpuIfTargetWinGet(target, &addrDecWin); + if (MV_NO_SUCH == status) + { + continue; + } + + /* first get attributes from CPU If */ + if (MV_OK != status) + { + mvOsPrintf("mvPexInit: ERR. Getting DRAM address decode window "\ + "%d from CPU interface failed\n",target - SDRAM_CS0); + return MV_ERROR; + } + + if (addrDecWin.enable == MV_TRUE) + { + + /* set a Pex window for this target ! + DRAM CS always will have a Pex Window , and is not a + part of the priority table */ + pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexWin.addrWin.size = addrDecWin.addrWin.size; + DB(mvOsPrintf("mvPexInit: target %d, size =%d MBYTE \n",target,addrDecWin.addrWin.size/_1M)); + + /* we disable the windows at first because we are not + sure that it is witihin bar boundries */ + pexWin.enable =MV_FALSE; + pexWin.target = target; + pexWin.targetBar = bar; + if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++,&pexWin)) + { + mvOsPrintf("mvPexInit: ERR. mvPexTargetWinSet failed\n"); + return MV_ERROR; + } + } + } + } + + for (target = DEV_TO_TARGET(DEV_CS0); + target < DEV_TO_TARGET(MV_DEV_MAX_CS); + target++ ) + { + status = mvCpuIfTargetWinGet(target, &addrDecWin); + if (MV_NO_SUCH == status) + { + continue; + } + + if (MV_OK != status) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target); + return MV_ERROR; + } + + if (addrDecWin.enable == MV_TRUE) + { + /* get the minimum base */ + if (addrDecWin.addrWin.baseLow < pexBar.addrWin.baseLow) + { + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + } + + /* get the maximum base */ + if (addrDecWin.addrWin.baseLow > maxBase) + { + maxBase = addrDecWin.addrWin.baseLow; + sizeOfMaxBase = addrDecWin.addrWin.size; + } + + /* search in the priority table for this target */ + for (winIndex = 0; pexDevBarPrioTable[winIndex] != TBL_TERM; + winIndex++) + { + if (pexDevBarPrioTable[winIndex] != target) + { + continue; + } + else if (pexDevBarPrioTable[winIndex] == target) + { + /*found it */ + + /* if the index of this target in the prio table is valid + then we set the Pex window for this target, a valid index is + an index that is lower than the number of the windows that + was not configured yet */ + if ( pexCurrWin < PEX_GRNERAL_WIN_NUM) + { + /* set a Pex window for this target ! */ + pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexWin.addrWin.size = addrDecWin.addrWin.size; + + /* we disable the windows at first because we are not + sure that it is witihin bar boundries */ + pexWin.enable = MV_FALSE; + pexWin.target = target; + pexWin.targetBar = bar; + if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++, &pexWin)) + { + mvOsPrintf("mvPexInit: ERR. Window Set failed\n"); + return MV_ERROR; + } + } + } + } + } + } + + if (dramSize <= _2G) + { + pexBar.addrWin.size = maxBase - pexBar.addrWin.baseLow + sizeOfMaxBase; + } + pexBar.enable = MV_TRUE; + + pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); + + /* check if the size and base are valid */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,bar,&pexBar.addrWin)) + { + mvOsPrintf("mvPexInit:Warning :Bar %d size is illegal\n",bar); + mvOsPrintf("it will be disabled\n"); + mvOsPrintf("please check Pex and CPU windows configuration\n"); + } + else + { + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + + /* now enable the windows */ + for (winNum = pexStartWindow; winNum < pexCurrWin ; winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) + { + mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", + winNum); + return MV_ERROR; + } + } + } + /* WA - to set default value for default window */ + MV_REG_WRITE(PEX_WIN_DEFAULT_CTRL_REG(pexIf),0xf10); + + return mvPexHalInit(pexIf, pexType); +} + +/******************************************************************************* +* mvPexTargetWinSet - Set PEX to peripheral target address window BAR +* +* DESCRIPTION: +* +* INPUT: +* pexIf - PEX interface number. +* winNum - Address window number. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if PEX BAR target window was set correctly, +* MV_BAD_PARAM on bad params +* MV_ERROR otherwise +* (e.g. address window overlapps with other active PEX target window). +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pPexAddrDecWin) +{ + + MV_DEC_WIN_PARAMS winParams; + PEX_WIN_REG_INFO winRegOffs; + MV_U32 winCtrlReg = 0; + MV_U32 winBaseReg = 0; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + if (MV_TRUE == pPexAddrDecWin->enable) + { + /* Check if the requested window overlaps with current windows */ + if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &pPexAddrDecWin->addrWin)) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Target %d overlap\n", winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window is within its BAR */ + if (MV_FALSE == pexIsWinWithinBar(pexIf,&pPexAddrDecWin->addrWin)) + { + mvOsPrintf("mvPexTargetWinSet: Win %d should be in bar boundries\n", + winNum); + return MV_BAD_PARAM; + } + } + + /* Translate the PEX address decode structure to register fields format */ + if (MV_OK != mvCtrlAddrDecToParams((MV_DEC_WIN*)pPexAddrDecWin, &winParams)) + { + mvOsPrintf("Failed to translate the PEX address decode structure to "\ + "register fields format\n"); + return MV_ERROR; + } + + /* set bar Mapping */ + winCtrlReg |= PXWCR_WIN_BAR_MAP_BAR(pPexAddrDecWin->targetBar); + + /* set attributes */ + winCtrlReg |= (winParams.attrib << PXWCR_ATTRIB_OFFS); + + /* If window is DRAM with HW cache coherency, make sure bit2 is set */ + winCtrlReg &= ~PXWCR_SLV_WR_SPLT_MASK; + winCtrlReg |= PXWCR_SLV_WR_SPLT_128B; + + /* set target ID */ + winCtrlReg |= (winParams.targetId << PXWCR_TARGET_OFFS); + + /* set window size */ + winCtrlReg |= (winParams.size << PXWCR_SIZE_OFFS); + + /* enable\Disable */ + if (MV_TRUE == pPexAddrDecWin->enable) + { + winCtrlReg |= PXWCR_WIN_EN; + } + + /* PCI Express Default Window Control Register reserve some fields */ + if (MV_PEX_WIN_DEFAULT == winNum) + { + winCtrlReg &= (PXWCR_TARGET_MASK | PXWCR_ATTRIB_MASK | PXWCR_SLV_WR_SPLT_MASK); + } + + /* PCI Express Expansion ROM Window Control Register reserve some fields */ + if (MV_PEX_WIN_EXP_ROM == winNum) + { + winCtrlReg &= (PXWCR_TARGET_MASK | PXWCR_ATTRIB_MASK); + } + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf, winNum, &winRegOffs); + + /* Write to window control register */ + MV_REG_WRITE(winRegOffs.winCtrlRegOffs, winCtrlReg); + + /* PCI Express Default Window and Expansion ROM Window does not have */ + /* base register */ + if (0 != winRegOffs.winBaseRegOffs) + { + /* Base parameter */ + winBaseReg = (winParams.baseAddr & PXWBR_BASE_MASK); + + /* Write to window base register */ + MV_REG_WRITE(winRegOffs.winBaseRegOffs, winBaseReg); + } + + return MV_OK; + +} + +/******************************************************************************* +* mvPexTargetWinGet - Get PEX to peripheral target address window +* +* DESCRIPTION: +* Get the PEX to peripheral target address window BAR. +* +* INPUT: +* pexIf - PEX interface number. +* winNum - Address window number. +* +* OUTPUT: +* pAddrBarWin - PEX target window information data structure. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, MV_PEX_DEC_WIN *pPexAddrDecWin) +{ + MV_DEC_WIN_PARAMS winParams; + PEX_WIN_REG_INFO winRegOffs; + MV_U32 winCtrlReg = 0; + MV_U32 winBaseReg = 0; + + /* Parameter checking */ + if(pexIf > mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf,winNum, &winRegOffs); + + /* Read Control register */ + winCtrlReg = MV_REG_READ(winRegOffs.winCtrlRegOffs); + + /* Read size reg if there is valid base information */ + if (winRegOffs.winBaseRegOffs) + { + winBaseReg = MV_REG_READ(winRegOffs.winBaseRegOffs); + } + + /* Extract window parameters from registers */ + winParams.attrib = (winCtrlReg & PXWCR_ATTRIB_MASK) >> PXWCR_ATTRIB_OFFS; + winParams.targetId = (winCtrlReg & PXWCR_TARGET_MASK) >> PXWCR_TARGET_OFFS; + winParams.size = (winCtrlReg & PXWCR_SIZE_MASK) >> PXWCR_SIZE_OFFS; + winParams.baseAddr = winBaseReg & PXWBR_BASE_MASK; + + /* Translate the decode window parameters to address decode struct */ + if (MV_OK != mvCtrlParamsToAddrDec(&winParams, (MV_DEC_WIN*)pPexAddrDecWin)) + { + mvOsPrintf("Failed to translate register parameters to PEX address" \ + " decode window structure\n"); + return MV_ERROR; + } + + /* get target bar */ + pPexAddrDecWin->targetBar = ((winCtrlReg & PXWCR_WIN_BAR_MAP_MASK) >> + PXWCR_WIN_BAR_MAP_OFFS) + 1; + + pPexAddrDecWin->slvWrSpltCnt = ((winCtrlReg & PXWCR_SLV_WR_SPLT_MASK) >> + PXWCR_SLV_WR_SPLT_OFFS); + + pPexAddrDecWin->enable = (winCtrlReg & PXWCR_WIN_EN) >> PXWCR_WIN_EN_OFFS; + + return MV_OK; + +} + +/******************************************************************************* +* mvPexTargetWinEnable - Enable/disable a PEX BAR window +* +* DESCRIPTION: +* This function enable/disable a PEX BAR window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling PEX accesses for that BAR (before enabling the +* window it is tested for overlapping). Otherwise, the window will +* be disabled. +* +* INPUT: +* pexIf - PEX interface number. +* winNum - Address window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf,MV_U32 winNum, MV_BOOL enable) +{ + PEX_WIN_REG_INFO winRegOffs; + MV_PEX_DEC_WIN addrDecWin; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinEnable: ERR. Invalid PEX If %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinEnable ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + /* Enable/Disable not relevant to default and expantion rom windows */ + if ((MV_PEX_WIN_DEFAULT == winNum) || (MV_PEX_WIN_EXP_ROM == winNum)) + { + return MV_BAD_PARAM; + } + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf, winNum, &winRegOffs); + + /* if the address windows is disabled , we only disable the appropriare + pex window and ignore other settings */ + if (MV_FALSE == enable) + { + MV_REG_BIT_RESET(winRegOffs.winCtrlRegOffs, PXWCR_WIN_EN); + } + else + { + if (MV_OK != mvPexTargetWinGet(pexIf,winNum, &addrDecWin)) + { + mvOsPrintf("mvPexTargetWinEnable: mvPexTargetWinGet Failed\n"); + return MV_ERROR; + } + + /* Check if the requested window overlaps with current windows */ + if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &addrDecWin.addrWin)) + { + mvOsPrintf("mvPexTargetWinEnable: ERR. Target %d overlap\n", winNum); + return MV_BAD_PARAM; + } + + if (MV_FALSE == pexIsWinWithinBar(pexIf, &addrDecWin.addrWin)) + { + mvOsPrintf("mvPexTargetWinEnable: Win %d should be in bar boundries\n", + winNum); + return MV_BAD_PARAM; + } + + MV_REG_BIT_SET(winRegOffs.winCtrlRegOffs, PXWCR_WIN_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* mvPexTargetWinRemap - Set PEX to target address window remap. +* +* DESCRIPTION: +* The PEX interface supports remap of the BAR original address window. +* For each BAR it is possible to define a remap address. For example +* an address 0x12345678 that hits BAR 0x10 (SDRAM CS[0]) will be modified +* according to remap register but will also be targeted to the +* SDRAM CS[0]. +* +* INPUT: +* pexIf - PEX interface number. +* winNum - Address window number. +* pAddrWin - Address window to be checked. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_REMAP_WIN *pAddrWin) +{ + + PEX_WIN_REG_INFO winRegOffs; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", + pexIf); + return MV_BAD_PARAM; + } + + if ((MV_PEX_WIN_DEFAULT == winNum) || (winNum >= PEX_MAX_TARGET_WIN)) + { + mvOsPrintf("mvPexTargetWinEnable ERR. Invalid PEX winNum %d\n", winNum); + + return MV_BAD_PARAM; + } + + if (MV_IS_NOT_ALIGN(pAddrWin->addrWin.baseLow, PXWRR_REMAP_ALIGNMENT)) + { + mvOsPrintf("mvPexTargetWinRemap: Error remap PEX interface %d win %d."\ + "\nAddress 0x%08x is unaligned to size 0x%x.\n", + pexIf, + winNum, + pAddrWin->addrWin.baseLow, + pAddrWin->addrWin.size); + + return MV_ERROR; + } + + pexWinRegInfoGet(pexIf, winNum, &winRegOffs); + + /* Set remap low register value */ + MV_REG_WRITE(winRegOffs.winRemapLowRegOffs, pAddrWin->addrWin.baseLow); + + /* Skip base high settings if the BAR has only base low (32-bit) */ + if (0 != winRegOffs.winRemapHighRegOffs) + { + MV_REG_WRITE(winRegOffs.winRemapHighRegOffs, pAddrWin->addrWin.baseHigh); + } + + + if (pAddrWin->enable == MV_TRUE) + { + MV_REG_BIT_SET(winRegOffs.winRemapLowRegOffs,PXWRR_REMAP_EN); + } + else + { + MV_REG_BIT_RESET(winRegOffs.winRemapLowRegOffs,PXWRR_REMAP_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* mvPexTargetWinRemapEnable - +* +* DESCRIPTION: +* +* INPUT: +* pexIf - PEX interface number. +* winNum - Address window number. +* +* OUTPUT: +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, + MV_BOOL enable) +{ + PEX_WIN_REG_INFO winRegOffs; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", + pexIf); + return MV_BAD_PARAM; + } + + if ((MV_PEX_WIN_DEFAULT == winNum) || (winNum >= PEX_MAX_TARGET_WIN)) + { + mvOsPrintf("mvPexTargetWinEnable ERR. Invalid PEX winNum %d\n", winNum); + + return MV_BAD_PARAM; + } + + pexWinRegInfoGet(pexIf, winNum, &winRegOffs); + + if (enable == MV_TRUE) + { + MV_REG_BIT_SET(winRegOffs.winRemapLowRegOffs,PXWRR_REMAP_EN); + } + else + { + MV_REG_BIT_RESET(winRegOffs.winRemapLowRegOffs,PXWRR_REMAP_EN); + } + + return MV_OK; + +} + +/******************************************************************************* +* mvPexBarSet - Set PEX bar address and size +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexBarSet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin) +{ + MV_U32 regBaseLow; + MV_U32 regSize,sizeToReg; + + + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarSet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarSet: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + + if (pAddrWin->addrWin.size == 0) + { + mvOsPrintf("mvPexBarSet: Size zero is Illigal\n" ); + return MV_BAD_PARAM; + } + + + /* Check if the window complies with PEX spec */ + if (MV_TRUE != pexBarIsValid(pAddrWin->addrWin.baseLow, + pAddrWin->addrWin.size)) + { + mvOsPrintf("mvPexBarSet: ERR. Target %d window invalid\n", barNum); + return MV_BAD_PARAM; + } + + /* 2) Check if the requested bar overlaps with current bars */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,barNum, &pAddrWin->addrWin)) + { + mvOsPrintf("mvPexBarSet: ERR. Target %d overlap\n", barNum); + return MV_BAD_PARAM; + } + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrWin->addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); + + /* Read bar size */ + if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ + { + regSize = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvPexBarSet: ERR. Target BAR %d size invalid.\n",barNum); + return MV_BAD_PARAM; + } + + regSize &= ~PXBCR_BAR_SIZE_MASK; + regSize |= (sizeToReg << PXBCR_BAR_SIZE_OFFS) ; + + MV_REG_WRITE(PEX_BAR_CTRL_REG(pexIf,barNum),regSize); + + } + + /* set size */ + + + + /* Read base address low */ + regBaseLow = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_MV_BAR_BASE(barNum))); + + /* clear current base */ + if (PEX_INTER_REGS_BAR == barNum) + { + regBaseLow &= ~PXBIR_BASE_MASK; + regBaseLow |= (pAddrWin->addrWin.baseLow & PXBIR_BASE_MASK); + } + else + { + regBaseLow &= ~PXBR_BASE_MASK; + regBaseLow |= (pAddrWin->addrWin.baseLow & PXBR_BASE_MASK); + } + + /* if we had a previous value that contain the bar type (MeM\IO), we want to + restore it */ + regBaseLow |= PEX_BAR_DEFAULT_ATTRIB; + + /* write base low */ + MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum)), + regBaseLow); + + if (pAddrWin->addrWin.baseHigh != 0) + { + /* Read base address high */ + MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum)), + pAddrWin->addrWin.baseHigh); + + } + + /* lastly enable the Bar */ + if (pAddrWin->enable == MV_TRUE) + { + if (PEX_INTER_REGS_BAR != barNum) /* internal registers + are enabled always */ + { + MV_REG_BIT_SET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + } + } + else if (MV_FALSE == pAddrWin->enable) + { + if (PEX_INTER_REGS_BAR != barNum) /* internal registers + are enabled always */ + { + MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + } + + } + + + + return MV_OK; +} + + +/******************************************************************************* +* mvPexBarGet - Get PEX bar address and size +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexBarGet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin) +{ + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarGet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarGet: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + /* read base low */ + pAddrWin->addrWin.baseLow = + MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum))); + + + if (PEX_INTER_REGS_BAR == barNum) + { + pAddrWin->addrWin.baseLow &= PXBIR_BASE_MASK; + } + else + { + pAddrWin->addrWin.baseLow &= PXBR_BASE_MASK; + } + + + /* read base high */ + pAddrWin->addrWin.baseHigh = + MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum))); + + + /* Read bar size */ + if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ + { + pAddrWin->addrWin.size = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); + + /* check if enable or not */ + if (pAddrWin->addrWin.size & PXBCR_BAR_EN) + { + pAddrWin->enable = MV_TRUE; + } + else + { + pAddrWin->enable = MV_FALSE; + } + + /* now get the size */ + pAddrWin->addrWin.size &= PXBCR_BAR_SIZE_MASK; + pAddrWin->addrWin.size >>= PXBCR_BAR_SIZE_OFFS; + + pAddrWin->addrWin.size = ctrlRegToSize(pAddrWin->addrWin.size, + PXBCR_BAR_SIZE_ALIGNMENT); + + } + else /* PEX_INTER_REGS_BAR */ + { + pAddrWin->addrWin.size = INTER_REGS_SIZE; + pAddrWin->enable = MV_TRUE; + } + + + return MV_OK; +} + +/******************************************************************************* +* mvPexBarEnable - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable) +{ + + MV_PEX_BAR pexBar; + + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarEnable: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarEnable: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + if (PEX_INTER_REGS_BAR == barNum) + { + if (MV_TRUE == enable) + { + return MV_OK; + } + else + { + return MV_ERROR; + } + } + + + if (MV_FALSE == enable) + { + /* disable bar and quit */ + MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + return MV_OK; + } + + /* else */ + + if (mvPexBarGet(pexIf,barNum,&pexBar) != MV_OK) + { + mvOsPrintf("mvPexBarEnable: mvPexBarGet Failed\n"); + return MV_ERROR; + + } + + if (MV_TRUE == pexBar.enable) + { + /* it is already enabled !!! */ + return MV_OK; + } + + /* else enable the bar*/ + + pexBar.enable = MV_TRUE; + + if (mvPexBarSet(pexIf,barNum,&pexBar) != MV_OK) + { + mvOsPrintf("mvPexBarEnable: mvPexBarSet Failed\n"); + return MV_ERROR; + + } + + return MV_OK; +} + + +/******************************************************************************* +* pexWinOverlapDetect - Detect address windows overlapping +* +* DESCRIPTION: +* This function detects address window overlapping of a given address +* window in PEX BARs. +* +* INPUT: +* pAddrWin - Address window to be checked. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexWinOverlapDetect(MV_U32 pexIf, + MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 win; + MV_PEX_DEC_WIN addrDecWin; + + for(win = 0; win < PEX_GRNERAL_WIN_NUM ; win++) + { + /* don't check our target or illegal targets */ + if (winNum == win) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvPexTargetWinGet(pexIf, win, &addrDecWin)) + { + mvOsPrintf("pexWinOverlapDetect: ERR. TargetWinGet failed win=%x\n", + win); + return MV_ERROR; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + mvOsPrintf("pexWinOverlapDetect: winNum %d overlap current %d\n", winNum, win); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* pexIsWinWithinBar - Detect if address is within PEX bar boundries +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexIsWinWithinBar(MV_U32 pexIf, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 bar; + MV_PEX_BAR addrDecWin; + + for(bar = 0; bar < PEX_MAX_BARS; bar++) + { + /* Get window parameters */ + if (MV_OK != mvPexBarGet(pexIf, bar, &addrDecWin)) + { + mvOsPrintf("pexIsWinWithinBar: ERR. mvPexBarGet failed\n"); + return MV_ERROR; + } + + /* Do not check disabled bars */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinWithinWinTest(pAddrWin, &addrDecWin.addrWin)) + { + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* pexBarOverlapDetect - Detect address windows overlapping +* +* DESCRIPTION: +* This function detects address window overlapping of a given address +* window in PEX BARs. +* +* INPUT: +* pAddrWin - Address window to be checked. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexBarOverlapDetect(MV_U32 pexIf, + MV_U32 barNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 bar; + MV_PEX_BAR barDecWin; + + + for(bar = 0; bar < PEX_MAX_BARS; bar++) + { + /* don't check our target or illegal targets */ + if (barNum == bar) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvPexBarGet(pexIf, bar, &barDecWin)) + { + mvOsPrintf("pexBarOverlapDetect: ERR. TargetWinGet failed\n"); + return MV_ERROR; + } + + /* don'nt check disabled bars */ + if (barDecWin.enable == MV_FALSE) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &barDecWin.addrWin)) + { + mvOsPrintf("pexBarOverlapDetect: winNum %d overlap current %d\n", barNum, bar); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* pexBarIsValid - Check if the given address window is valid +* +* DESCRIPTION: +* PEX spec restrict BAR base to be aligned to BAR size. +* This function checks if the given address window is valid. +* +* INPUT: +* baseLow - 32bit low base address. +* size - Window size. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the address window is valid, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_STATUS pexBarIsValid(MV_U32 baseLow, MV_U32 size) +{ + + /* PCI spec restrict BAR base to be aligned to BAR size */ + if(MV_IS_NOT_ALIGN(baseLow, size)) + { + return MV_ERROR; + } + else + { + return MV_TRUE; + } + + return MV_TRUE; +} + +/******************************************************************************* +* pexBarRegInfoGet - Get BAR register information +* +* DESCRIPTION: +* PEX BARs registers offsets are inconsecutive. +* This function gets a PEX BAR register information like register offsets +* and function location of the BAR. +* +* INPUT: +* pexIf - PEX interface number. +* winNum - The PEX address decode window in question. +* +* OUTPUT: +* pBarRegInfo - BAR register info struct. +* +* RETURN: +* MV_BAD_PARAM when bad parameters ,MV_ERROR on error ,othewise MV_OK +* +*******************************************************************************/ +static MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, + MV_U32 winNum, + PEX_WIN_REG_INFO *pWinRegInfo) +{ + + if (MV_PEX_WIN_DEFAULT == winNum) + { + pWinRegInfo->winCtrlRegOffs = PEX_WIN_DEFAULT_CTRL_REG(pexIf); + pWinRegInfo->winBaseRegOffs = 0; + pWinRegInfo->winRemapLowRegOffs = 0; + pWinRegInfo->winRemapHighRegOffs = 0; + } + else if (MV_PEX_WIN_EXP_ROM == winNum) + { + pWinRegInfo->winCtrlRegOffs = PEX_WIN_EXP_ROM_CTRL_REG(pexIf); + pWinRegInfo->winBaseRegOffs = 0; + pWinRegInfo->winRemapLowRegOffs = PEX_WIN_EXP_ROM_REMAP_REG(pexIf); + pWinRegInfo->winRemapHighRegOffs = 0; + + } + else + { + pWinRegInfo->winCtrlRegOffs = PEX_WIN_CTRL_REG(pexIf,winNum); + pWinRegInfo->winBaseRegOffs = PEX_WIN_BASE_REG(pexIf,winNum); + pWinRegInfo->winRemapLowRegOffs = PEX_WIN_REMAP_REG(pexIf,winNum); + pWinRegInfo->winRemapHighRegOffs = PEX_WIN_REMAP_HIGH_REG(pexIf,winNum); + } + + + return MV_OK; +} + +/******************************************************************************* +* pexBarNameGet - Get the string name of PEX BAR. +* +* DESCRIPTION: +* This function get the string name of PEX BAR. +* +* INPUT: +* bar - PEX bar number. +* +* OUTPUT: +* None. +* +* RETURN: +* pointer to the string name of PEX BAR. +* +*******************************************************************************/ +const MV_8* pexBarNameGet( MV_U32 bar ) +{ + switch( bar ) + { + case PEX_INTER_REGS_BAR: + return "Internal Regs Bar0...."; + case PEX_DRAM_BAR: + return "DRAM Bar1............."; + case PEX_DEVICE_BAR: + return "Devices Bar2.........."; + default: + return "Bar unknown"; + } +} +/******************************************************************************* +* mvPexAddrDecShow - Print the PEX address decode map (BARs and windows). +* +* DESCRIPTION: +* This function print the PEX address decode map (BARs and windows). +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvPexAddrDecShow(MV_VOID) +{ + MV_PEX_BAR pexBar; + MV_U32 pexIf; + MV_U32 pexIfMax = mvCtrlPexMaxIfGet(); + MV_U32 bar; + + for( pexIf = 0; pexIf < pexIfMax; pexIf++ ) + { + mvOsOutput( "\n" ); + mvOsOutput( "PEX%d:\n", pexIf ); + mvOsOutput( "-----" ); + + mvOsOutput( "\nPex Bars \n\n"); + + for( bar = 0; bar < PEX_MAX_BARS; bar++ ) + { + memset( &pexBar, 0, sizeof(MV_PEX_BAR) ); + + mvOsOutput( "%s ", pexBarNameGet(bar) ); + + if( mvPexBarGet( pexIf, bar, &pexBar ) == MV_OK ) + { + if( pexBar.enable ) + { + mvOsOutput( "base %08x:%08x, ", pexBar.addrWin.baseHigh, pexBar.addrWin.baseLow ); + mvSizePrint( pexBar.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } + + mvPexDecWinShow(pexIf); + } +} + + +/******************************************************************************* +* mvPexDecWinShow - Print the PEX address decode windows. +* +* DESCRIPTION: +* This function print the PEX address decode windows. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID mvPexDecWinShow(MV_U32 pexIf) +{ + MV_PEX_DEC_WIN win; + int winNum; + + mvOsOutput( "\nPex Decode Windows\n\n"); + + for( winNum = 0; winNum < PEX_GRNERAL_WIN_NUM; winNum++ ) + { + memset( &win, 0, sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "win%d - ", winNum ); + + if ( mvPexTargetWinGet(pexIf,winNum,&win) == MV_OK) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x:%08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseHigh, win.addrWin.baseLow ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } + + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "default win - " ); + + if ( mvPexTargetWinGet(pexIf, MV_PEX_WIN_DEFAULT, &win) == MV_OK) + { + mvOsOutput( "%s ", + mvCtrlTargetNameGet(win.target) ); + mvOsOutput( "\n" ); + } + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "Expansion ROM - " ); + + if ( mvPexTargetWinGet(pexIf, MV_PEX_WIN_EXP_ROM, &win) == MV_OK) + { + mvOsOutput( "%s ", + mvCtrlTargetNameGet(win.target) ); + mvOsOutput( "\n" ); + } +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.h new file mode 100644 index 0000000..37cb4e9 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysPex.h @@ -0,0 +1,286 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCSysPEXH +#define __INCSysPEXH + +#include "mvCommon.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" +#include "pex/mvPex.h" + + +#define MV_PEX_WIN_DEFAULT 6 +#define MV_PEX_WIN_EXP_ROM 7 +#define PEX_GRNERAL_WIN_NUM 6 +#define PEX_MAX_TARGET_WIN 8 + + +#define PEX_MAX_BARS 3 +#define PEX_INTER_REGS_BAR 0 +#define PEX_DRAM_BAR 1 +#define PEX_DEVICE_BAR 2 + +/*************************************/ +/* PCI Express BAR Control Registers */ +/*************************************/ +#define PEX_BAR_CTRL_REG(pexIf, bar) ((PEX_IF_BASE(pexIf)) + 0x1800 + (bar * 4)) +#define PEX_EXP_ROM_BAR_CTRL_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x180C) +/************************************************/ +/* PCI Express Address Window Control Registers */ +/************************************************/ +#define PEX_WIN_REG_OFFS(winNum) ((winNum >= 5) ? 0x60 : (winNum * 0x10)) + +#define PEX_WIN_CTRL_REG(pexIf,winNum) \ + ((PEX_IF_BASE(pexIf)) + 0x1820 + PEX_WIN_REG_OFFS(winNum)) + +#define PEX_WIN_BASE_REG(pexIf,winNum) \ + ((PEX_IF_BASE(pexIf)) + 0x1824 + PEX_WIN_REG_OFFS(winNum)) + +#define PEX_WIN_REMAP_REG(pexIf,winNum) \ + ((PEX_IF_BASE(pexIf)) + 0x182C + PEX_WIN_REG_OFFS(winNum)) + +#define PEX_WIN_REMAP_HIGH_REG(pexIf,winNum) \ + ((winNum >= 4) ? ((PEX_IF_BASE(pexIf)) + 0x1870 + ((winNum - 4) * 0x20)) : 0) + +#define PEX_WIN_DEFAULT_CTRL_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x18B0) +#define PEX_WIN_EXP_ROM_CTRL_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x18C0) +#define PEX_WIN_EXP_ROM_REMAP_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x18C4) + +/* PCI Express Window Control Register */ +/* PEX_WIN_CTRL_REG (PXWCR) */ +#define PXWCR_WIN_EN_OFFS 0 +#define PXWCR_WIN_EN BIT0 /* Window Enable.*/ +#define PXWCR_WIN_BAR_MAP_OFFS 1 /* Mapping to BAR.*/ +#define PXWCR_WIN_BAR_MAP_MASK (1 << PXWCR_WIN_BAR_MAP_OFFS) +#define PXWCR_WIN_BAR_MAP_BAR(barNum) ((barNum-1) << PXWCR_WIN_BAR_MAP_OFFS) +#define PXWCR_SLV_WR_SPLT_OFFS 2 +#define PXWCR_SLV_WR_SPLT_MASK (1 << PXWCR_SLV_WR_SPLT_OFFS) +#define PXWCR_SLV_WR_SPLT_128B (0 << PXWCR_SLV_WR_SPLT_OFFS) +#define PXWCR_SLV_WR_SPLT_32B (1 << PXWCR_SLV_WR_SPLT_OFFS) +#define PXWCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWCR_TARGET_MASK (0xf << PXWCR_TARGET_OFFS) +#define PXWCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWCR_ATTRIB_MASK (0xff << PXWCR_ATTRIB_OFFS) +#define PXWCR_SIZE_OFFS 16 /* size */ +#define PXWCR_SIZE_MASK (0xffff << PXWCR_SIZE_OFFS) +#define PXWCR_SIZE_ALIGNMENT 0x10000 + +/* PCI Express Window Base Register */ +/* PEX_WIN_BASE_REG (PXWBR)*/ +#define PXWBR_BASE_OFFS 16 /* address[31:16] */ +#define PXWBR_BASE_MASK (0xffff << PXWBR_BASE_OFFS) +#define PXWBR_BASE_ALIGNMENT 0x10000 + +/* PCI Express Window Remap Register */ +/* PEX_WIN_REMAP_REG (PXWRR)*/ +#define PXWRR_REMAP_EN BIT0 +#define PXWRR_REMAP_OFFS 16 +#define PXWRR_REMAP_MASK (0xffff << PXWRR_REMAP_OFFS) +#define PXWRR_REMAP_ALIGNMENT 0x10000 + +/* PCI Express Window Remap (High) Register */ +/* PEX_WIN_REMAP_HIGH_REG (PXWRHR)*/ +#define PXWRHR_REMAP_HIGH_OFFS 0 +#define PXWRHR_REMAP_HIGH_MASK (0xffffffff << PXWRHR_REMAP_HIGH_OFFS) + +/* PCI Express Default Window Control Register */ +/* PEX_WIN_DEFAULT_CTRL_REG (PXWDCR) */ +#define PXWDCR_SLV_WR_SPLT_CNT_OFFS 2 +#define PXWDCR_SLV_WR_SPLT_CNT_MASK (1 << PXWDCR_SLV_WR_SPLT_CNT_OFFS) +#define PXWDCR_SLV_WR_SPLT_CNT_128B (0 << PXWDCR_SLV_WR_SPLT_CNT_OFFS) +#define PXWDCR_SLV_WR_SPLT_CNT_32B (1 << PXWDCR_SLV_WR_SPLT_CNT_OFFS) +#define PXWDCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWDCR_TARGET_MASK (0xf << PXWDCR_TARGET_OFFS) +#define PXWDCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWDCR_ATTRIB_MASK (0xff << PXWDCR_ATTRIB_OFFS) + +/* PCI Express Expansion ROM Window Control Register */ +/* PEX_WIN_EXP_ROM_CTRL_REG (PXWERCR)*/ +#define PXWERCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWERCR_TARGET_MASK (0xf << PXWERCR_TARGET_OFFS) +#define PXWERCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWERCR_ATTRIB_MASK (0xff << PXWERCR_ATTRIB_OFFS) + +/* PCI Express Expansion ROM Window Remap Register */ +/* PEX_WIN_EXP_ROM_REMAP_REG (PXWERRR)*/ +#define PXWERRR_REMAP_EN BIT0 +#define PXWERRR_REMAP_OFFS 16 +#define PXWERRR_REMAP_MASK (0xffff << PXWERRR_REMAP_OFFS) +#define PXWERRR_REMAP_ALIGNMENT 0x10000 + + +/* PCI Express BAR Control Register */ +/* PEX_BAR_CTRL_REG (PXBCR) */ +#define PXBCR_BAR_EN BIT0 +#define PXBCR_BAR_SIZE_OFFS 16 +#define PXBCR_BAR_SIZE_MASK (0xffff << PXBCR_BAR_SIZE_OFFS) +#define PXBCR_BAR_SIZE_ALIGNMENT 0x10000 + +/* PCI Express Expansion ROM BAR Control Register */ +/* PEX_EXP_ROM_BAR_CTRL_REG (PXERBCR) */ +#define PXERBCR_EXPROM_EN BIT0 +#define PXERBCR_EXPROMSZ_OFFS 19 +#define PXERBCR_EXPROMSZ_MASK (0x7 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_512KB (0x0 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_1024KB (0x1 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_2048KB (0x3 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_4096KB (0x7 << PXERBCR_EXPROMSZ_OFFS) + + +/* PCI Express BAR0 Internal Register*/ +/* PEX BAR0_INTER_REG (PXBIR)*/ +#define PXBIR_IOSPACE BIT0 /* Memory Space Indicator */ +#define PXBIR_TYPE_OFFS 1 /* BAR Type/Init Val. */ +#define PXBIR_TYPE_MASK (0x3 << PXBIR_TYPE_OFFS) +#define PXBIR_TYPE_32BIT_ADDR (0x0 << PXBIR_TYPE_OFFS) +#define PXBIR_TYPE_64BIT_ADDR (0x2 << PXBIR_TYPE_OFFS) +#define PXBIR_PREFETCH_EN BIT3 /* Prefetch Enable */ +#define PXBIR_BASE_OFFS 20 /* Base address. Address bits [31:20] */ +#define PXBIR_BASE_MASK (0xfff << PXBIR_BASE_OFFS) +#define PXBIR_BASE_ALIGNMET (1 << PXBIR_BASE_OFFS) + +/* PCI Express BAR1 Register and PCI Express BAR2 Register*/ +/* PEX BAR1_REG (PXBR) and PEX BAR2_REG (PXBR) */ +#define PXBR_IOSPACE PXBIR_IOSPACE +#define PXBR_TYPE_OFFS PXBIR_TYPE_OFFS +#define PXBR_TYPE_MASK PXBIR_TYPE_MASK +#define PXBR_TYPE_32BIT_ADDR PXBIR_TYPE_32BIT_ADDR +#define PXBR_TYPE_64BIT_ADDR PXBIR_TYPE_64BIT_ADDR +#define PXBR_PREFETCH_EN PXBIR_PREFETCH_EN +#define PXBR_BASE_OFFS 16 /* Base address. Address bits [31:16] */ +#define PXBR_BASE_MASK (0xffff << PXBR_BASE_OFFS) +#define PXBR_BASE_ALIGNMET (1 << PXBR_BASE_OFFS) + +/* This macro defines default BAR attributes */ +#define PEX_BAR_DEFAULT_ATTRIB 0xc /* Memory - Prefetch - 64 bit address */ + +/* PEX Bar attributes */ +typedef struct _mvPexBar +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ +}MV_PEX_BAR; + +/* PEX Remap Window attributes */ +typedef struct _mvPexRemapWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_PEX_REMAP_WIN; + +/* PEX Window attributes */ +typedef struct _mvPexDecWin +{ + MV_TARGET target; /* Target for addr decode window */ + MV_ADDR_WIN addrWin; /* Address window of target */ + MV_BOOL enable; /* Window enable/disable */ + MV_U32 targetBar; + MV_BOOL slvWrSpltCnt; +} MV_PEX_DEC_WIN; + + +/* Global Functions prototypes */ +/* mvPexHalInit - Initialize PEX interfaces*/ +MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType); + + +/* mvPexTargetWinSet - Set PEX to peripheral target address window BAR*/ +MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, + MV_U32 winNum, MV_PEX_DEC_WIN *pPexAddrDecWin); + +/* mvPexTargetWinGet - Get PEX to peripheral target address window*/ +MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pPexAddrDecWin); +/* mvPexTargetWinEnable - Enable/disable a PEX BAR window*/ +MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf, + MV_U32 winNum, MV_BOOL enable); + +/* mvPexTargetWinRemap - Set PEX to target address window remap.*/ +MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_REMAP_WIN *pAddrWin); + +/* mvPexTargetWinRemapEnable -enable\disable a PEX Window remap.*/ +MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, + MV_BOOL enable); + +/* mvPexBarSet - Set PEX bar address and size */ +MV_STATUS mvPexBarSet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin); + +/* mvPexBarGet - Get PEX bar address and size */ +MV_STATUS mvPexBarGet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin); + +/* mvPexBarEnable - enable\disable a PEX bar*/ +MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable); + +/* mvPexAddrDecShow - Display address decode windows attributes */ +MV_VOID mvPexAddrDecShow(MV_VOID); + +#endif diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.c new file mode 100644 index 0000000..1036db4 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.c @@ -0,0 +1,431 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "mvTypes.h" +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "cpu/mvCpu.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "mvRegs.h" +#include "ctrlEnv/sys/mvSysSata.h" +#include "cpu/mvCpu.h" + +MV_TARGET sataAddrDecPrioTab[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif + TBL_TERM +}; + + +/******************************************************************************* +* sataWinOverlapDetect - Detect SATA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case SATA address decode +* windows overlapps. +* This function detects SATA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS sataWinOverlapDetect(int dev, MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_SATA_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_SATA_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == sataWinOverlapDetect(dev, winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvSataWinSet:Error setting SATA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = 0; + decRegs.sizeReg = 0; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~MV_SATA_WIN_ATTR_MASK; + decRegs.sizeReg |= (targetAttribs.attrib << MV_SATA_WIN_ATTR_OFFSET); + + /* set target ID */ + decRegs.sizeReg &= ~MV_SATA_WIN_TARGET_MASK; + decRegs.sizeReg |= (targetAttribs.targetId << MV_SATA_WIN_TARGET_OFFSET); + + if (pAddrDecWin->enable == MV_TRUE) + { + decRegs.sizeReg |= MV_SATA_WIN_ENABLE_MASK; + } + else + { + decRegs.sizeReg &= ~MV_SATA_WIN_ENABLE_MASK; + } + + MV_REG_WRITE( MV_SATA_WIN_CTRL_REG(dev, winNum), decRegs.sizeReg); + MV_REG_WRITE( MV_SATA_WIN_BASE_REG(dev, winNum), decRegs.baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvSataWinGet - Get SATA peripheral target address window. +* +* DESCRIPTION: +* Get SATA peripheral target address window. +* +* INPUT: +* winNum - SATA target address decode window number. +* +* OUTPUT: +* pAddrDecWin - SATA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSataWinGet(int dev, MV_U32 winNum, MV_SATA_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= MV_SATA_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", + __FUNCTION__, dev, winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ( MV_SATA_WIN_BASE_REG(dev, winNum) ); + decRegs.sizeReg = MV_REG_READ( MV_SATA_WIN_CTRL_REG(dev, winNum) ); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) ) + { + mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & MV_SATA_WIN_ATTR_MASK) >> + MV_SATA_WIN_ATTR_OFFSET; + targetAttrib.targetId = (decRegs.sizeReg & MV_SATA_WIN_TARGET_MASK) >> + MV_SATA_WIN_TARGET_OFFSET; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if(decRegs.sizeReg & MV_SATA_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + return MV_OK; +} +/******************************************************************************* +* mvSataAddrDecShow - Print the SATA address decode map. +* +* DESCRIPTION: +* This function print the SATA address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvSataAddrDecShow(MV_VOID) +{ + + MV_SATA_DEC_WIN win; + int i,j; + + + + for( j = 0; j < MV_SATA_MAX_CHAN; j++ ) + { + if (MV_FALSE == mvCtrlPwrClckGet(SATA_UNIT_ID, j)) + return; + + mvOsOutput( "\n" ); + mvOsOutput( "SATA %d:\n", j ); + mvOsOutput( "----\n" ); + + for( i = 0; i < MV_SATA_MAX_ADDR_DECODE_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_SATA_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvSataWinGet(j, i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } + } +} + + +/******************************************************************************* +* mvSataWinInit - Initialize the integrated SATA target address window. +* +* DESCRIPTION: +* Initialize the SATA peripheral target address window. +* +* INPUT: +* +* +* OUTPUT: +* +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSataWinInit(MV_VOID) +{ + int winNum; + MV_SATA_DEC_WIN sataWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_U32 status, winPrioIndex = 0; + + /* Initiate Sata address decode */ + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_SATA_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_U32 regVal = MV_REG_READ(MV_SATA_WIN_CTRL_REG(0, winNum)); + regVal &= ~MV_SATA_WIN_ENABLE_MASK; + MV_REG_WRITE(MV_SATA_WIN_CTRL_REG(0, winNum), regVal); + } + + winNum = 0; + while( (sataAddrDecPrioTab[winPrioIndex] != TBL_TERM) && + (winNum < MV_SATA_MAX_ADDR_DECODE_WIN) ) + { + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(sataAddrDecPrioTab[winPrioIndex], + &cpuAddrDecWin); + + if(MV_NO_SUCH == status) + { + winPrioIndex++; + continue; + } + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + sataWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + sataWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + sataWin.addrWin.size = cpuAddrDecWin.addrWin.size; + sataWin.enable = MV_TRUE; + sataWin.target = sataAddrDecPrioTab[winPrioIndex]; + + if(MV_OK != mvSataWinSet(0/*dev*/, winNum, &sataWin)) + { + return MV_ERROR; + } + winNum++; + } + winPrioIndex++; + } + return MV_OK; +} + + + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.h new file mode 100644 index 0000000..325fb8d --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysSata.h @@ -0,0 +1,128 @@ + +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVSysSataAddrDech +#define __INCMVSysSataAddrDech + +#include "mvCommon.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _mvSataDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +} MV_SATA_DEC_WIN; + + +#define MV_SATA_MAX_ADDR_DECODE_WIN 4 + +#define MV_SATA_WIN_CTRL_REG(dev, win) (SATA_REG_BASE + 0x30 + ((win)<<4)) +#define MV_SATA_WIN_BASE_REG(dev, win) (SATA_REG_BASE + 0x34 + ((win)<<4)) + +/* BITs in Bridge Interrupt Cause and Mask registers */ +#define MV_SATA_ADDR_DECODE_ERROR_BIT 0 +#define MV_SATA_ADDR_DECODE_ERROR_MASK (1<= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == tdmWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvTdmWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvTdmWinSet: Error setting TDM window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum)); + decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvTdmWinSet: mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* for the safe side we disable the window before writing the new + values */ + mvTdmWinEnable(winNum, MV_FALSE); + + ctrlReg |= (targetAttribs.attrib << TDM_WIN_ATTRIB_OFFS); + ctrlReg |= (targetAttribs.targetId << TDM_WIN_TARGET_OFFS); + ctrlReg |= (decRegs.sizeReg << TDM_WIN_SIZE_OFFS); + + /* Write to address base and control registers */ + MV_REG_WRITE(TDM_WIN_BASE_REG(winNum), decRegs.baseReg); + MV_REG_WRITE(TDM_WIN_CTRL_REG(winNum), ctrlReg); + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvTdmWinEnable(winNum, MV_TRUE); + } + return MV_OK; +} + +/******************************************************************************* +* mvTdmWinGet - Get peripheral target address window. +* +* DESCRIPTION: +* Get TDM peripheral target address window. +* +* INPUT: +* winNum - TDM to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - TDM target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ + +MV_STATUS mvTdmWinGet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin) +{ + + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum)); + decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS; + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvTdmWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ATTRIB_MASK) >> TDM_WIN_ATTRIB_OFFS; + targetAttrib.targetId = + (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_TARGET_MASK) >> TDM_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvTdmWinEnable - Enable/disable a TDM to target address window +* +* DESCRIPTION: +* This function enable/disable a TDM to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling TDM accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - TDM to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvTdmWinEnable(int winNum, MV_BOOL enable) +{ + MV_TDM_DEC_WIN addrDecWin; + + if (MV_TRUE == enable) + { + if (winNum >= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvTdmWinGet(winNum, &addrDecWin)) + { + mvOsPrintf("mvTdmWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == tdmWinOverlapDetect(winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_SET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK); + } + else + { /* Overlap detected */ + mvOsPrintf("mvTdmWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { + MV_REG_BIT_RESET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK); + } + return MV_OK; +} + + +/******************************************************************************* +* tdmWinOverlapDetect - Detect TDM address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviour is expected in case TDM address decode +* windows overlapps. +* This function detects TDM address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS tdmWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_TDM_DEC_WIN addrDecWin; + + for (winNumIndex = 0; winNumIndex < TDM_MBUS_MAX_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + /* Do not check disabled windows */ + if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK) + { + /* Get window parameters */ + if (MV_OK != mvTdmWinGet(winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("dmaWinOverlapDetect: ERR. TargetWinGet failed\n")); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + } + return MV_FALSE; +} + +/******************************************************************************* +* mvTdmAddrDecShow - Print the TDM address decode map. +* +* DESCRIPTION: +* This function print the TDM address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvTdmAddrDecShow(MV_VOID) +{ + MV_TDM_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "TDM:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < TDM_MBUS_MAX_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_TDM_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if (mvTdmWinGet(i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysTdm.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysTdm.h new file mode 100644 index 0000000..00de28c --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysTdm.h @@ -0,0 +1,92 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSysTdmh +#define __INCmvSysTdmh + +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define TDM_MBUS_MAX_WIN 4 +#define TDM_WIN_CTRL_REG(win) ((TDM_REG_BASE + 0x4030) + (win<<4)) +#define TDM_WIN_BASE_REG(win) ((TDM_REG_BASE +0x4034) + (win<<4)) + +/* TDM_WIN_CTRL_REG bits */ +#define TDM_WIN_ENABLE_OFFS 0 +#define TDM_WIN_ENABLE_MASK (1<mcr = MCR_AFCE; /* Enable Auto flow control */ +#endif + + /*set the UART channel to use the IDMA*/ + MV_REG_BIT_SET(UART_EXTERNAL_CONTROL_REG, BIT0 | (BIT8 << port)); + + /* Set IDMA BAR target to UART*/ + MV_REG_BIT_RESET(IDMA_BASE_ADDR_REG(idmaWinNum), 0xffff0000); + /*Set BAR to UART*/ + MV_REG_BIT_SET(IDMA_BASE_ADDR_REG(idmaWinNum), 0x0101); + + /* Set IDMA0 channel to UART mode*/ + switch (srcBurstSize) + { + case 8: + srcBurstLim = ICCLR_SRC_BURST_LIM_8BYTE; + break; + case 16: + srcBurstLim = ICCLR_SRC_BURST_LIM_16BYTE; + break; + case 32: + srcBurstLim = ICCLR_SRC_BURST_LIM_32BYTE; + break; + case 64: + srcBurstLim = ICCLR_SRC_BURST_LIM_64BYTE; + break; + case 128: + srcBurstLim = ICCLR_SRC_BURST_LIM_128BYTE; + break; + default: + mvOsPrintf("mvUartDmaInit:ERR. Illegal source burst limit, setting to 128B default\n"); + srcBurstLim = ICCLR_SRC_BURST_LIM_128BYTE; + break; + } + mvDmaCtrlLowSet(0, 0x18220 | srcBurstLim); /*channel control low according FS*/ + mvDmaOverrideSet(0, idmaWinNum, DMA_DST_ADDR); + return; +} + + +/******************************************************************************* +* mvUartDmaTransmit - Transmit a buffer over the UART using the IDMA. +* +* DESCRIPTION: +* This routine transmits a buffer over the UART port using IDMA0. +* +* INPUT: +* port - uart port number. +* byteCount - The total number of bytes to be transferred to the UART. +* srcAddr - The source address of the buffer to be transferred. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK. +* +*******************************************************************************/ +MV_STATUS mvUartDmaTransmit(MV_U32 port, MV_U32 byteCount, MV_U32 srcAddr) +{ + MV_U32 dstAddr, tmp; + + /* Verify IDMA 0 is not busy */ + if(mvDmaStateGet(port) != MV_IDLE) + { + mvOsPrintf("mvUartDmaTransmit: ERR. IDMA 0 busy.\n"); + return MV_ERROR; + } + + /* Verify byte count is legal, and choose either 64K mode or 16M mode */ + if(byteCount >= 0x1000000) + { + mvOsPrintf("mvUartDmaTransmit: ERR. Illegal Byte count.\n"); + return MV_ERROR; + } + else if (byteCount >= 0x10000) + { + byteCount |= BIT31; + } + + /* Calculate UART destination address from assigned BAR*/ + tmp = MV_REG_READ(IDMA_CTRL_LOW_REG(0)); + tmp = (tmp >> 23) & 0x3; /* Extract the destination override window number*/ + + /* Check that destination BAR is configured and calculate destination address*/ + if((MV_REG_READ(IDMA_BASE_ADDR_REG(tmp)) & 0xffff) != 0x0101) + { + mvOsPrintf("mvUartDmaTransmit: ERR. IDMA UART BAR isn't configured.\n"); + return MV_ERROR; + } + else + dstAddr = (MV_REG_READ(IDMA_BASE_ADDR_REG(tmp)) & 0xffff0000 ) | (port << 8); + + /* Start transfer */ + if(mvDmaTransfer(0, srcAddr, dstAddr, byteCount, 0x0) == MV_OK) + return MV_OK; + else + return MV_ERROR; +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUart.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUart.h new file mode 100644 index 0000000..1969e80 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUart.h @@ -0,0 +1,75 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __MVSYSUART_H__ +#define __MVSYSUART_H__ + + + +/* APIs */ +MV_VOID mvUartDmaInit(MV_U32 port, MV_U32 baudDivisor, MV_UART_PORT* base, + MV_U32 idmaWinNum, MV_U32 srcBurstSize); +MV_STATUS mvUartDmaTransmit(MV_U32 port, MV_U32 byteCount, MV_U32 srcAddr); + +#endif /* __MVSYSUART_H__ */ diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUsb.c b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUsb.c new file mode 100644 index 0000000..c5ebaca --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysUsb.c @@ -0,0 +1,498 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "ctrlEnv/sys/mvSysUsb.h" +#include "cpu/mvCpu.h" + +MV_TARGET usbAddrDecPrioTab[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_CESA) && defined(USB_UNDERRUN_WA) + CRYPT_ENG, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif + TBL_TERM +}; + + + +MV_STATUS mvUsbInit(int dev, MV_BOOL isHost) +{ + MV_STATUS status; + + status = mvUsbWinInit(dev); + if(status != MV_OK) + return status; + + return mvUsbHalInit(dev, isHost); +} + + +/******************************************************************************* +* usbWinOverlapDetect - Detect USB address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case USB address decode +* windows overlapps. +* This function detects USB address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS usbWinOverlapDetect(int dev, MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_USB_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == usbWinOverlapDetect(dev, winNum, &pDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) + { + mvOsPrintf("mvUsbWinSet:Error setting USB window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pDecWin->target), + pDecWin->addrWin.baseLow, + pDecWin->addrWin.size); + return MV_ERROR; + } + + if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams)) + { + mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* set Size, Attributes and TargetID */ + sizeReg = (((winParams.targetId << MV_USB_WIN_TARGET_OFFSET) & MV_USB_WIN_TARGET_MASK) | + ((winParams.attrib << MV_USB_WIN_ATTR_OFFSET) & MV_USB_WIN_ATTR_MASK) | + ((winParams.size << MV_USB_WIN_SIZE_OFFSET) & MV_USB_WIN_SIZE_MASK)); + +#if defined(MV645xx) || defined(MV646xx) + /* If window is DRAM with HW cache coherency, make sure bit2 is set */ + sizeReg &= ~MV_USB_WIN_BURST_WR_LIMIT_MASK; + + if((MV_TARGET_IS_DRAM(pDecWin->target)) && + (pDecWin->addrWinAttr.cachePolicy != NO_COHERENCY)) + { + sizeReg |= MV_USB_WIN_BURST_WR_32BIT_LIMIT; + } + else + { + sizeReg |= MV_USB_WIN_BURST_WR_NO_LIMIT; + } +#endif /* MV645xx || MV646xx */ + + if (pDecWin->enable == MV_TRUE) + { + sizeReg |= MV_USB_WIN_ENABLE_MASK; + } + else + { + sizeReg &= ~MV_USB_WIN_ENABLE_MASK; + } + + /* Update Base value */ + baseReg = (winParams.baseAddr & MV_USB_WIN_BASE_MASK); + + MV_REG_WRITE( MV_USB_WIN_CTRL_REG(dev, winNum), sizeReg); + MV_REG_WRITE( MV_USB_WIN_BASE_REG(dev, winNum), baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvUsbWinGet - Get USB peripheral target address window. +* +* DESCRIPTION: +* Get USB peripheral target address window. +* +* INPUT: +* winNum - USB target address decode window number. +* +* OUTPUT: +* pDecWin - USB target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvUsbWinGet(int dev, MV_U32 winNum, MV_DEC_WIN *pDecWin) +{ + MV_DEC_WIN_PARAMS winParam; + MV_U32 sizeReg, baseReg; + + /* Parameter checking */ + if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", + __FUNCTION__, dev, winNum); + return MV_NOT_SUPPORTED; + } + + baseReg = MV_REG_READ( MV_USB_WIN_BASE_REG(dev, winNum) ); + sizeReg = MV_REG_READ( MV_USB_WIN_CTRL_REG(dev, winNum) ); + + /* Check if window is enabled */ + if(sizeReg & MV_USB_WIN_ENABLE_MASK) + { + pDecWin->enable = MV_TRUE; + + /* Extract window parameters from registers */ + winParam.targetId = (sizeReg & MV_USB_WIN_TARGET_MASK) >> MV_USB_WIN_TARGET_OFFSET; + winParam.attrib = (sizeReg & MV_USB_WIN_ATTR_MASK) >> MV_USB_WIN_ATTR_OFFSET; + winParam.size = (sizeReg & MV_USB_WIN_SIZE_MASK) >> MV_USB_WIN_SIZE_OFFSET; + winParam.baseAddr = (baseReg & MV_USB_WIN_BASE_MASK); + + /* Translate the decode window parameters to address decode struct */ + if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin)) + { + mvOsPrintf("Failed to translate register parameters to USB address" \ + " decode window structure\n"); + return MV_ERROR; + } + } + else + { + pDecWin->enable = MV_FALSE; + } + return MV_OK; +} + +/******************************************************************************* +* mvUsbWinInit - +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvUsbWinInit(int dev) +{ + MV_STATUS status; + MV_DEC_WIN usbWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + int winNum; + MV_U32 winPrioIndex = 0; + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_USB_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_REG_BIT_RESET(MV_USB_WIN_CTRL_REG(dev, winNum), MV_USB_WIN_ENABLE_MASK); + } + + /* Go through all windows in user table until table terminator */ + winNum = 0; + while( (usbAddrDecPrioTab[winPrioIndex] != TBL_TERM) && + (winNum < MV_USB_MAX_ADDR_DECODE_WIN) ) + { + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(usbAddrDecPrioTab[winPrioIndex], + &cpuAddrDecWin); + + if(MV_NO_SUCH == status) + { + winPrioIndex++; + continue; + } + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + usbWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + usbWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + usbWin.addrWin.size = cpuAddrDecWin.addrWin.size; + usbWin.enable = MV_TRUE; + usbWin.target = usbAddrDecPrioTab[winPrioIndex]; + +#if defined(MV645xx) || defined(MV646xx) + /* Get the default attributes for that target window */ + mvCtrlDefAttribGet(usbWin.target, &usbWin.addrWinAttr); +#endif /* MV645xx || MV646xx */ + + if(MV_OK != mvUsbWinSet(dev, winNum, &usbWin)) + { + return MV_ERROR; + } + winNum++; + } + winPrioIndex++; + } + return MV_OK; +} + +/******************************************************************************* +* mvUsbAddrDecShow - Print the USB address decode map. +* +* DESCRIPTION: +* This function print the USB address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvUsbAddrDecShow(MV_VOID) +{ + MV_DEC_WIN addrDecWin; + int i, winNum; + + mvOsOutput( "\n" ); + mvOsOutput( "USB:\n" ); + mvOsOutput( "----\n" ); + + for(i=0; i= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + if (pAddrDecWin == NULL) + { + DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + /* Check if the requested window overlaps with current windows */ + if (MV_TRUE == xorWinOverlapDetect(unit, winNum, &pAddrDecWin->addrWin)) + { + DB(mvOsPrintf("%s: ERR. Window %d overlap\n",__FUNCTION__,winNum)); + return MV_ERROR; + } + + xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum)); + xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum)); + + /* Get Base Address and size registers values */ + if(MV_OK != mvCtrlAddrDecToReg(&pAddrDecWin->addrWin, &xorDecRegs)) + { + DB(mvOsPrintf("%s: ERR. Invalid addr dec window\n",__FUNCTION__)); + return MV_BAD_PARAM; + } + + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + xorDecRegs.baseReg &= ~XEBARX_ATTR_MASK; + xorDecRegs.baseReg |= targetAttribs.attrib << XEBARX_ATTR_OFFS; + /* set target ID */ + xorDecRegs.baseReg &= ~XEBARX_TARGET_MASK; + xorDecRegs.baseReg |= targetAttribs.targetId << XEBARX_TARGET_OFFS; + + + /* Write to address decode Base Address Register */ + MV_REG_WRITE(XOR_BASE_ADDR_REG(unit,winNum), xorDecRegs.baseReg); + + /* Write to Size Register */ + MV_REG_WRITE(XOR_SIZE_MASK_REG(unit,winNum), xorDecRegs.sizeReg); + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + if (pAddrDecWin->enable) + { + MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit,chan), + (XEXWCR_WIN_EN_MASK(winNum)) | + (XEXWCR_WIN_ACC_MASK(winNum))); + } + else + { + MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit,chan), + (XEXWCR_WIN_EN_MASK(winNum)) | + (XEXWCR_WIN_ACC_MASK(winNum))); + } + } + return MV_OK; +} + +/******************************************************************************* +* mvXorTargetWinGet - Get xor peripheral target address window. +* +* DESCRIPTION: +* Get xor peripheral target address window. +* +* INPUT: +* winNum - One of the possible XOR memory decode windows. +* +* OUTPUT: +* base - Window base address. +* size - Window size. +* enable - window enable/disable. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorTargetWinGet(MV_U32 unit,MV_U32 winNum, MV_XOR_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS xorDecRegs; + MV_TARGET_ATTRIB targetAttrib; + MV_U32 chan=0,chanWinEn; + + /* Parameter checking */ + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__ , winNum)); + return MV_ERROR; + } + + if (NULL == pAddrDecWin) + { + DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + + chanWinEn = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,0)) & XEXWCR_WIN_EN_MASK(winNum); + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) /* we should scan here all channels per unit */ + { + /* Check if enable bit is equal for all channels */ + if ((MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)) & + XEXWCR_WIN_EN_MASK(winNum)) != chanWinEn) + { + mvOsPrintf("%s: ERR. Window enable field must be equal in " + "all channels(chan=%d)\n",__FUNCTION__, chan); + return MV_ERROR; + } + } + + + + xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum)); + xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&xorDecRegs, &pAddrDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. mvCtrlRegToAddrDec failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (xorDecRegs.baseReg & XEBARX_ATTR_MASK) >> XEBARX_ATTR_OFFS; + targetAttrib.targetId = + (xorDecRegs.baseReg & XEBARX_TARGET_MASK) >> XEBARX_TARGET_OFFS; + + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + if(chanWinEn) + { + pAddrDecWin->enable = MV_TRUE; + } + else pAddrDecWin->enable = MV_FALSE; + + return MV_OK; +} + +/******************************************************************************* +* mvXorTargetWinEnable - Enable/disable a Xor address decode window +* +* DESCRIPTION: +* This function enable/disable a XOR address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling XOR accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - Decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorTargetWinEnable(MV_U32 unit,MV_U32 winNum, MV_BOOL enable) +{ + MV_XOR_DEC_WIN addrDecWin; + MV_U32 chan; + + /* Parameter checking */ + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid winNum%d\n", __FUNCTION__, winNum)); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { + /* Get current window */ + if (MV_OK != mvXorTargetWinGet(unit,winNum, &addrDecWin)) + { + DB(mvOsPrintf("%s: ERR. targetWinGet fail\n", __FUNCTION__)); + return MV_ERROR; + } + + /* Check for overlapping */ + if (MV_TRUE == xorWinOverlapDetect(unit,winNum, &(addrDecWin.addrWin))) + { + /* Overlap detected */ + DB(mvOsPrintf("%s: ERR. Overlap detected\n", __FUNCTION__)); + return MV_ERROR; + } + + /* No Overlap. Enable address decode target window */ + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + + } + else + { + /* Disable address decode target window */ + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + + } + + return MV_OK; +} + +/******************************************************************************* +* mvXorSetProtWinSet - Configure access attributes of a XOR engine +* to one of the XOR memory windows. +* +* DESCRIPTION: +* Each engine can be configured with access attributes for each of the +* memory spaces. This function sets access attributes +* to a given window for the given engine +* +* INPUTS: +* chan - One of the possible engines. +* winNum - One of the possible XOR memory spaces. +* access - Protection access rights. +* write - Write rights. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorProtWinSet (MV_U32 unit,MV_U32 chan, MV_U32 winNum, MV_BOOL access, + MV_BOOL write) +{ + MV_U32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN_PER_UNIT) + { + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __FUNCTION__ , chan)); + return MV_BAD_PARAM; + } + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + + temp = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)) & + (~XEXWCR_WIN_ACC_MASK(winNum)); + + /* if access is disable */ + if (!access) + { + /* disable access */ + temp |= XEXWCR_WIN_ACC_NO_ACC(winNum); + } + /* if access is enable */ + else + { + /* if write is enable */ + if (write) + { + /* enable write */ + temp |= XEXWCR_WIN_ACC_RW(winNum); + } + /* if write is disable */ + else + { + /* disable write */ + temp |= XEXWCR_WIN_ACC_RO(winNum); + } + } + MV_REG_WRITE(XOR_WINDOW_CTRL_REG(unit,chan),temp); + return MV_OK; +} + +/******************************************************************************* +* mvXorPciRemap - Set XOR remap register for PCI address windows. +* +* DESCRIPTION: +* only Windows 0-3 can be remapped. +* +* INPUT: +* winNum - window number +* pAddrDecWin - pointer to address space window structure +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorPciRemap(MV_U32 unit,MV_U32 winNum, MV_U32 addrHigh) +{ + /* Parameter checking */ + if (winNum >= XOR_MAX_REMAP_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + + MV_REG_WRITE(XOR_HIGH_ADDR_REMAP_REG(unit,winNum), addrHigh); + + return MV_OK; +} + +/******************************************************************************* +* xorWinOverlapDetect - Detect XOR address windows overlaping +* +* DESCRIPTION: +* An unpredicted behaviour is expected in case XOR address decode +* windows overlaps. +* This function detects XOR address decode windows overlaping of a +* specified window. The function does not check the window itself for +* overlaping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS xorWinOverlapDetect(MV_U32 unit,MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex,chan; + MV_XOR_DEC_WIN addrDecWin; + + if (pAddrWin == NULL) + { + DB(mvOsPrintf("%s: ERR. pAddrWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)); + + for (winNumIndex = 0; winNumIndex < XOR_MAX_ADDR_DEC_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + + /* Do not check disabled windows */ + if ((baseAddrEnableReg & XEXWCR_WIN_EN_MASK(winNumIndex)) == 0) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvXorTargetWinGet(unit,winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__ )); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + } + + return MV_FALSE; +} + +static MV_VOID mvXorAddrDecShowUnit(MV_U32 unit) +{ + MV_XOR_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "XOR %d:\n", unit ); + mvOsOutput( "----\n" ); + + for( i = 0; i < XOR_MAX_ADDR_DEC_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_XOR_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvXorTargetWinGet(unit, i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + +/******************************************************************************* +* mvXorAddrDecShow - Print the XOR address decode map. +* +* DESCRIPTION: +* This function print the XOR address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvXorAddrDecShow(MV_VOID) +{ + int i; + + for( i = 0; i < MV_XOR_MAX_UNIT; i++ ) + mvXorAddrDecShowUnit(i); + +} + +/******************************************************************************* +* mvXorAllStop - Stop any XOR activity. +* +* DESCRIPTION: +* This function stops any XOR activity. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvXorAllStop(MV_VOID) +{ + MV_U32 xorChanNum; + + /* Abort any XOR activity */ + for(xorChanNum = 0; xorChanNum < MV_XOR_MAX_CHAN; xorChanNum++) + { + mvXorCommandSet(xorChanNum, MV_STOP); + } + + return; +} + + diff --git a/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysXor.h b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysXor.h new file mode 100644 index 0000000..c7b7075 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/ctrlEnv/sys/mvSysXor.h @@ -0,0 +1,141 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCMVSysXorh +#define __INCMVSysXorh + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ctrlEnv/sys/mvCpuIf.h" + +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define XOR_MAX_ADDR_DEC_WIN 8 /* Maximum address decode windows */ +#define XOR_MAX_REMAP_WIN 4 /* Maximum address arbiter windows */ + +/* XOR Engine Address Decoding Register Map */ +#define XOR_WINDOW_CTRL_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x240 + ((chan) * 4))) +#define XOR_BASE_ADDR_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x250 + ((winNum) * 4))) +#define XOR_SIZE_MASK_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x270 + ((winNum) * 4))) +#define XOR_HIGH_ADDR_REMAP_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x290 + ((winNum) * 4))) + +/* XOR Engine [0..1] Window Control Registers (XExWCR) */ +#define XEXWCR_WIN_EN_OFFS(winNum) (winNum) +#define XEXWCR_WIN_EN_MASK(winNum) (1 << (XEXWCR_WIN_EN_OFFS(winNum))) +#define XEXWCR_WIN_EN_ENABLE(winNum) (1 << (XEXWCR_WIN_EN_OFFS(winNum))) +#define XEXWCR_WIN_EN_DISABLE(winNum) (0 << (XEXWCR_WIN_EN_OFFS(winNum))) + +#define XEXWCR_WIN_ACC_OFFS(winNum) ((2 * winNum) + 16) +#define XEXWCR_WIN_ACC_MASK(winNum) (3 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_NO_ACC(winNum) (0 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_RO(winNum) (1 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_RW(winNum) (3 << (XEXWCR_WIN_ACC_OFFS(winNum))) + +/* XOR Engine Base Address Registers (XEBARx) */ +#define XEBARX_TARGET_OFFS (0) +#define XEBARX_TARGET_MASK (0xF << XEBARX_TARGET_OFFS) +#define XEBARX_ATTR_OFFS (8) +#define XEBARX_ATTR_MASK (0xFF << XEBARX_ATTR_OFFS) +#define XEBARX_BASE_OFFS (16) +#define XEBARX_BASE_MASK (0xFFFF << XEBARX_BASE_OFFS) + +/* XOR Engine Size Mask Registers (XESMRx) */ +#define XESMRX_SIZE_MASK_OFFS (16) +#define XESMRX_SIZE_MASK_MASK (0xFFFF << XESMRX_SIZE_MASK_OFFS) + +/* XOR Engine High Address Remap Register (XEHARRx1) */ +#define XEHARRX_REMAP_OFFS (0) +#define XEHARRX_REMAP_MASK (0xFFFFFFFF << XEHARRX_REMAP_OFFS) + +typedef struct _mvXorDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_XOR_DEC_WIN; + +MV_STATUS mvXorInit (MV_VOID); +MV_STATUS mvXorTargetWinSet(MV_U32 unit, MV_U32 winNum, + MV_XOR_DEC_WIN *pAddrDecWin); +MV_STATUS mvXorTargetWinGet(MV_U32 unit, MV_U32 winNum, + MV_XOR_DEC_WIN *pAddrDecWin); +MV_STATUS mvXorTargetWinEnable(MV_U32 unit, + MV_U32 winNum, MV_BOOL enable); +MV_STATUS mvXorProtWinSet (MV_U32 unit,MV_U32 chan, MV_U32 winNum, MV_BOOL access, + MV_BOOL write); +MV_STATUS mvXorPciRemap(MV_U32 unit, MV_U32 winNum, MV_U32 addrHigh); + +MV_VOID mvXorAddrDecShow(MV_VOID); +MV_VOID mvXorAllStop(MV_VOID); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/mv_feroceon/mv_dd/dd_family/device/mvDevice.c b/board/mv_feroceon/mv_dd/dd_family/device/mvDevice.c new file mode 100644 index 0000000..8babb5f --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/device/mvDevice.c @@ -0,0 +1,375 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#include "mvTypes.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "device/mvDevice.h" + +/* defines */ +#ifdef DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + + + +/******************************************************************************* +* mvDevPramSet - Set device interface bank parameters +* +* DESCRIPTION: +* This function sets a device bank parameters to a given device. +* +* INPUT: +* device - Device number. See MV_DEVICE enumerator. +* *pDevParams - Device bank parameter struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvDevIfPramSet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams) +{ + MV_U32 devParam = 0; + /* check parameters */ + if (device >= MV_DEV_MAX_CS) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device)); + return MV_BAD_PARAM; + + } + if (pDevParams->turnOff > MAX_DBP_TURNOFF) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->turnOff out of range\n")); + return MV_ERROR; + } + if (pDevParams->acc2First > MAX_DBP_ACC2FIRST) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->acc2First out of range\n")); + return MV_ERROR; + } + if (pDevParams->acc2Next > MAX_DBP_ACC2NEXT) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->acc2Next out of range\n")); + return MV_ERROR; + } + if (pDevParams->ale2Wr > MAX_DBP_ALE2WR) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->ale2Wr out of range\n")); + return MV_ERROR; + } + if (pDevParams->wrLow > MAX_DBP_WRLOW) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->ale2Wr out of range\n")); + return MV_ERROR; + } + if (pDevParams->wrHigh > MAX_DBP_WRHIGH) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->ale2Wr out of range\n")); + return MV_ERROR; + } + if ((pDevParams->badrSkew << DBP_BADRSKEW_OFFS) > DBP_BADRSKEW_2CYCLE ) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->badrSkew out of range\n")); + return MV_ERROR; + } + if ((pDevParams->deviceWidth != 8 )&& + (pDevParams->deviceWidth != 16 )) + { +#if defined(MV78XX0) + if (pDevParams->deviceWidth != 32) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth out of range\n")); + return MV_ERROR; + } +#endif + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth out of range\n")); + return MV_ERROR; + } + + /* devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device)); */ + /* Bit 31 must be 1 */ +#if !defined(MV78XX0) + devParam = DEV_BANK_PARAM_REG_DV; +#endif + /* setting values */ + devParam |= DBP_TURNOFF_SET(pDevParams->turnOff); + devParam |= DBP_ACC2FIRST_SET(pDevParams->acc2First); + devParam |= DBP_ACC2NEXT_SET(pDevParams->acc2Next); +#if !defined(MV78XX0) + devParam |= DBP_ALE2WR_SET(pDevParams->ale2Wr); + devParam |= DBP_WRLOW_SET(pDevParams->wrLow); + devParam |= DBP_WRHIGH_SET(pDevParams->wrHigh); +#endif + devParam |= ((pDevParams->badrSkew & DBP_BADRSKEW_MASK) << DBP_BADRSKEW_OFFS); + + switch (pDevParams->deviceWidth) + { + case 8: + devParam |= DBP_DEVWIDTH_8BIT; + break; + case 16: + devParam |= DBP_DEVWIDTH_16BIT; + break; +#if defined(MV78XX0) + case 32: + devParam |= DBP_DEVWIDTH_32BIT; + break; +#endif + default: + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth non valid value\n")); + return MV_ERROR; + break; + } + + MV_REG_WRITE(DEV_BANK_PARAM_REG(device),devParam); + +#if defined(MV78XX0) + devParam = 0; + devParam |= DBP_ALE2WR_SET(pDevParams->ale2Wr); + devParam |= DBP_WRLOW_SET(pDevParams->wrLow); + devParam |= DBP_WRHIGH_SET(pDevParams->wrHigh); + MV_REG_WRITE(DEV_BANK_PARAM_REG_WR(device),devParam); +#endif + + return MV_OK; +} + +/******************************************************************************* +* mvDevPramget - Get device interface bank parameters +* +* DESCRIPTION: +* This function retrieves a device bank parameter settings. +* +* INPUT: +* device - Device number. See MV_DEVICE enumerator. +* +* OUTPUT: +* *pDevParams - Device bank parameter struct. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvDevPramGet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams) +{ + MV_U32 devParam = 0; + + /* check parameters */ + if (device >= MV_DEV_MAX_CS) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device)); + return MV_BAD_PARAM; + + } + + devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device)); + + pDevParams->turnOff = DBP_TURNOFF_GET(devParam); + pDevParams->acc2First = DBP_ACC2FIRST_GET(devParam); + pDevParams->acc2Next = DBP_ACC2NEXT_GET(devParam); +#if !defined(MV78XX0) + pDevParams->ale2Wr = DBP_ALE2WR_GET(devParam); + pDevParams->wrLow = DBP_WRLOW_GET(devParam); + pDevParams->wrHigh = DBP_WRHIGH_GET(devParam); +#endif + pDevParams->badrSkew = (devParam & DBP_BADRSKEW_MASK) >> DBP_BADRSKEW_OFFS; + + switch (devParam & DBP_DEVWIDTH_MASK) + { + case DBP_DEVWIDTH_8BIT: + pDevParams->deviceWidth=8; + break; + case DBP_DEVWIDTH_16BIT: + pDevParams->deviceWidth=16; + break; +#if defined(MV78XX0) + case DBP_DEVWIDTH_32BIT: + pDevParams->deviceWidth=32; + break; +#endif + default: + DB(mvOsPrintf("mvDevIfPramSet: ERR. pDevParams->deviceWidth non valid value\n")); + return MV_ERROR; + break; + } + +#if defined(MV78XX0) + devParam = MV_REG_READ(DEV_BANK_PARAM_REG_WR(device)); + pDevParams->ale2Wr = DBP_ALE2WR_GET(devParam); + pDevParams->wrLow = DBP_WRLOW_GET(devParam); + pDevParams->wrHigh = DBP_WRHIGH_GET(devParam); +#endif + + return MV_OK; +} + +/******************************************************************************* +* mvDevWidthGet - Get device width parameter +* +* DESCRIPTION: +* This function gets width parameter of a given device. +* +* INPUT: +* device - Device number. See MV_DEVICE enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* Device width in bytes. +* +*******************************************************************************/ +MV_U32 mvDevWidthGet(MV_DEVICE device) +{ + + MV_U32 devParam; + + /* check parameters */ + if (device >= MV_DEV_MAX_CS) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device)); + return MV_BAD_PARAM; + + } + + devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device)); + + devParam = (devParam & DBP_DEVWIDTH_MASK) >> DBP_DEVWIDTH_OFFS; + + return (MV_U32)(0x8 << devParam); + +} + +/******************************************************************************* +* mvDevNandDevCsSet - Set NAND chip-select, care mode and init sequence +* +* DESCRIPTION: +* This function set the NAND flash controller registers with NAND +* device chip-select. +* +* INPUT: +* devNum - Device number. See MV_DEVICE enumerator. +* careMode - NAND device care mode (0 = Don't care, '1' = care). +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvDevNandDevCsSet(MV_DEVICE device, MV_BOOL careMode) +{ + MV_U32 nfCtrlReg; /* NAND Flash Control Register */ + + /* Set chip select */ + nfCtrlReg = MV_REG_READ(DEV_NAND_CTRL_REG); + + nfCtrlReg |= (DINFCR_NF_CS_MASK(device)); + + if (careMode) + nfCtrlReg |= (DINFCR_NF_ACT_CE_MASK(device)); + else + nfCtrlReg &= ~(DINFCR_NF_ACT_CE_MASK(device)); + + + MV_REG_WRITE(DEV_NAND_CTRL_REG, nfCtrlReg); +} + +/******************************************************************************* +* mvDevNandDevCsGet - Get NAND chip-select. +* +* DESCRIPTION: +* This function get the NAND flash chip-select. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Nand device chip-select. +* +*******************************************************************************/ +MV_32 mvDevNandDevCsGet(MV_VOID) +{ + MV_U32 nfCtrlReg; /* NAND Flash Control Register */ + + + nfCtrlReg = MV_REG_READ(DEV_NAND_CTRL_REG); + + nfCtrlReg &= (DINFCR_NF_CS_MASK(MV_NAND_CS)); + + if (nfCtrlReg) + return MV_NAND_CS; + else + return 0xffffffff; + +} + diff --git a/board/mv_feroceon/mv_dd/dd_family/device/mvDevice.h b/board/mv_feroceon/mv_dd/dd_family/device/mvDevice.h new file mode 100644 index 0000000..d8a9d75 --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/device/mvDevice.h @@ -0,0 +1,102 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvDeviceH +#define __INCmvDeviceH + +#include "device/mvDeviceRegs.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* This structure describes device interface parameters to be assigned to */ +/* device bank parameter */ +typedef struct _mvDeviceParam +{ /* boundary values */ + MV_U32 turnOff; /* 0x0 - 0xf */ + MV_U32 acc2First; /* 0x0 - 0x1f */ + MV_U32 acc2Next; /* 0x0 - 0x1f */ + MV_U32 ale2Wr; /* 0x0 - 0xf */ + MV_U32 wrLow; /* 0x0 - 0xf */ + MV_U32 wrHigh; /* 0x0 - 0xf */ + MV_U32 badrSkew; /* 0x0 - 0x2 */ + MV_U32 deviceWidth; /* in Bytes */ +} MV_DEVICE_PARAM; + + +/* mvDevPramSet - Set device interface bank parameters */ +MV_STATUS mvDevIfPramSet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams); + +/* mvDevPramget - Get device interface bank parameters */ +MV_STATUS mvDevPramGet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams); + +/* mvDevWidthGet - Get device width parameter*/ +MV_U32 mvDevWidthGet(MV_DEVICE device); + +/* mvDevNandDevCsSet - Set the NAND flash control registers with NAND device- */ +/* select and care mode */ +MV_VOID mvDevNandDevCsSet(MV_DEVICE device, MV_BOOL careMode); + +/* mvDevNandDevCsGet - Get the NAND flash chip-select */ +MV_32 mvDevNandDevCsGet(MV_VOID); + +#endif /* #ifndef __INCmvDeviceH */ diff --git a/board/mv_feroceon/mv_dd/dd_family/device/mvDeviceRegs.h b/board/mv_feroceon/mv_dd/dd_family/device/mvDeviceRegs.h new file mode 100644 index 0000000..b86e80b --- /dev/null +++ b/board/mv_feroceon/mv_dd/dd_family/device/mvDeviceRegs.h @@ -0,0 +1,481 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvDeviceRegsH +#define __INCmvDeviceRegsH + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MV_DEVICE_MAX_XBAR_TIMEOUT 0x0FFF +#define DEV_BANK_PARAM_REG_DV 0x80000000 +/* registers offsets */ + +#if defined(MV78XX0) + +static INLINE MV_U32 DEV_BANK_PARAM_REG(int num) +{ + switch(num) + { + case (BOOT_CS): + return DEVICE_BUS_BASE + 0x400; + case (DEV_CS0): + return DEVICE_BUS_BASE + 0x408; + case (DEV_CS1): + return DEVICE_BUS_BASE + 0x410; + case (DEV_CS2): + return DEVICE_BUS_BASE + 0x418; + case (DEV_CS3): + return DEVICE_BUS_BASE + 0x420; + default: + return 0xFFFFFFFF; + + } +} + +#define DEV_BANK_PARAM_REG_WR(num) (DEV_BANK_PARAM_REG(num)+0x4) +#define DEV_NAND_CTRL_REG (DEVICE_BUS_BASE + 0x0470) + +/* Device Bank Parameters register fields (DBP_REG)*/ +/* Boot Device Bank Parameters (DBP) register fields (DEV_BOOT_BANK_PARAM_REG)*/ +/* DBP_XXX_MASK_HIGH is the offset of the extend bit from the msb of the input value */ + +#define DBP_TURNOFF_OFFS_LOW 0 +#define DBP_TURNOFF_MASK_LOW 0x3F +#define MAX_DBP_TURNOFF 0xf + + +#define DBP_TURNOFF_SET(value) \ +((value & DBP_TURNOFF_MASK_LOW) << DBP_TURNOFF_OFFS_LOW) + +#define DBP_TURNOFF_GET(value) \ +((value >> DBP_TURNOFF_OFFS_LOW) & DBP_TURNOFF_MASK_LOW) + +#define DBP_ACC2FIRST_OFFS_LOW 6 +#define DBP_ACC2FIRST_MASK_LOW 0x3f +#define MAX_DBP_ACC2FIRST 0x3f + +#define DBP_ACC2FIRST_SET(value) \ +((value & DBP_ACC2FIRST_MASK_LOW) << DBP_ACC2FIRST_OFFS_LOW) + +#define DBP_ACC2FIRST_GET(value) \ +((value >> DBP_ACC2FIRST_OFFS_LOW) & DBP_ACC2FIRST_MASK_LOW) + +#define DBP_ACC2NEXT_OFFS_LOW 17 +#define DBP_ACC2NEXT_MASK_LOW 0x3f +#define MAX_DBP_ACC2NEXT 0x3f + +#define DBP_ACC2NEXT_SET(value) \ +((value & DBP_ACC2FIRST_MASK_LOW) << DBP_ACC2FIRST_OFFS_LOW) + +#define DBP_ACC2NEXT_GET(value) \ +((value >> DBP_ACC2NEXT_OFFS_LOW) & DBP_ACC2NEXT_MASK_LOW) + +#define DBP_DEVWIDTH_OFFS 30 /* Device Width */ +#define DBP_DEVWIDTH_MASK (0x3 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_8BIT (0x0 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_16BIT (0x1 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_32BIT (0x2 << DBP_DEVWIDTH_OFFS) + +#define DBP_BADRSKEW_OFFS 28 +#define DBP_BADRSKEW_MASK (0x3 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_NOGAP (0x0 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_1CYCLE (0x1 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_2CYCLE (0x2 << DBP_BADRSKEW_OFFS) + +#define DBP_ALE2WR_OFFS_LOW 0 +#define DBP_ALE2WR_MASK_LOW 0x3f +#define MAX_DBP_ALE2WR 0x3F + + +#define DBP_ALE2WR_SET(value) \ +((value & DBP_ALE2WR_MASK_LOW) << DBP_ALE2WR_OFFS_LOW) + +#define DBP_ALE2WR_GET(value) \ +((value >> DBP_ALE2WR_OFFS_LOW) & DBP_ALE2WR_MASK_LOW) + +#define DBP_WRLOW_OFFS_LOW 8 +#define DBP_WRLOW_MASK_LOW 0x3F +#define MAX_DBP_WRLOW 0x3F + +#define DBP_WRLOW_SET(value) \ +((value & DBP_WRLOW_MASK_LOW) << DBP_WRLOW_OFFS_LOW) + +#define DBP_WRLOW_GET(value) \ +((value >> DBP_WRLOW_OFFS_LOW) & DBP_WRLOW_MASK_LOW) + +#define DBP_WRHIGH_OFFS_LOW 16 +#define DBP_WRHIGH_MASK_LOW 0x3F +#define MAX_DBP_WRHIGH 0x3F + +#define DBP_WRHIGH_SET(value) \ +((value & DBP_WRHIGH_MASK_LOW) << DBP_WRHIGH_OFFS_LOW) + +#define DBP_WRHIGH_GET(value) \ +((value >> DBP_WRHIGH_OFFS_LOW) & DBP_WRHIGH_MASK_LOW) + + +/* Device Interface Control register fields (DIC) (DIC_REG)*/ +#define DIC_TIMEOUT_OFFS 0 /* Timeout Timer Preset Value. */ +#define DIC_TIMEOUT_MASK (0xffff << DIC_TIMEOUT_OFFS) +#define MAX_DIC_TIMEOUT 0xffff + +/* NAND Flash Control register fields (NF) (NF_REG)*/ +#define NF_BOOTCS_OFFS 0 /* Define if BOOTCS is connected to NAND Flash */ +#define NF_BOOT_MASK (1 << NF_BOOTCS_OFFS) +#define NF_BOOT_NC (0 << NF_BOOTCS_OFFS) +#define NF_BOOT_C (1 << NF_BOOTCS_OFFS) + +#define NF_BOOTCS_CE_ACT_OFFS 1 /* Define if NAND Flash on BOOTCS is CE care or CE don't care */ +#define NF_BOOTCS_CE_ACT_MASK (1 << NF_BOOTCS_CE_ACT_OFFS) +#define NF_BOOTCS_CE_ACT_NCARE (0 << NF_BOOTCS_CE_ACT_OFFS) +#define NF_BOOTCS_CE_ACT_CARE (1 << NF_BOOTCS_CE_ACT_OFFS) + +#define NF_CS0_OFFS 2 /* Define if CS0 is connected to NAND Flash */ +#define NF_CS0_MASK (1 << NF_CS0_OFFS) +#define NF_CS0_NC (0 << NF_CS0_OFFS) +#define NF_CS0_C (1 << NF_CS0_OFFS) + +#define NF_CS0_CE_ACT_OFFS 3 /* Define if NAND Flash on CS0 is CE care or CE don't care */ +#define NF_CS0_CE_ACT_MASK (1 << NF_CS0_CE_ACT_OFFS) +#define NF_CS0_CE_ACT_NCARE (0 << NF_CS0_CE_ACT_OFFS) +#define NF_CS0_CE_ACT_CARE (1 << NF_CS0_CE_ACT_OFFS) + +#define NF_CS1_OFFS 4 /* Define if CS1 is connected to NAND Flash */ +#define NF_CS1_MASK (1 << NF_CS1_OFFS) +#define NF_CS1_NC (0 << NF_CS1_OFFS) +#define NF_CS1_C (1 << NF_CS1_OFFS) + +#define NF_CS1_CE_ACT_OFFS 5 /* Define if NAND Flash on CS1 is CE care or CE don't care */ +#define NF_CS1_CE_ACT_MASK (1 << NF_CS1_CE_ACT_OFFS) +#define NF_CS1_CE_ACT_NCARE (0 << NF_CS1_CE_ACT_OFFS) +#define NF_CS1_CE_ACT_CARE (1 << NF_CS1_CE_ACT_OFFS) + +#define NF_CS2_OFFS 6 /* Define if CS2 is connected to NAND Flash */ +#define NF_CS2_MASK (1 << NF_CS2_OFFS) +#define NF_CS2_NC (0 << NF_CS2_OFFS) +#define NF_CS2_C (1 << NF_CS2_OFFS) + +#define NF_CS2_CE_ACT_OFFS 7 /* Define if NAND Flash on CS2 is CE care or CE don't care */ +#define NF_CS2_CE_ACT_MASK (1 << NF_CS2_CE_ACT_OFFS) +#define NF_CS2_CE_ACT_NCARE (0 << NF_CS2_CE_ACT_OFFS) +#define NF_CS2_CE_ACT_CARE (1 << NF_CS2_CE_ACT_OFFS) + +#define NF_INIT_SEQ_OFFS 8 /* NAND Flash initialization sequence */ +#define NF_INIT_SEQ_MASK (1 << NF_INIT_SEQ_OFFS) +#define NF_INIT_SEQ_EN (0 << NF_INIT_SEQ_OFFS) +#define NF_INIT_SEQ_DIS (1 << NF_INIT_SEQ_OFFS) + +#define NF_OE_HIGHW_OFFS 9 /* NAND Flash OE high width in core clocks units (value + 1) */ +#define NF_OE_HIGHW_MASK (0x1f << NF_OE_HIGHW_OFFS) +#define MAX_OE_HIGHW (0x1f << NF_OE_HIGHW_OFFS) + +#define NF_TREADY_OFFS 14 /* NAND Flash time ready in core clocks units (value + 1) */ +#define NF_TREADY_MASK (0x1f << NF_TREADY_OFFS) +#define MAX_TREADY (0x1f << NF_TREADY_OFFS) + +#define NF_OE_TCTRL_OFFS 19 /* NAND Flash OE toggle control */ +#define NF_OE_TCTRL_MASK (1 << NF_OE_TCTRL_OFFS) +#define NF_OE_TCTRL_1_CYC_AFT (0 << NF_OE_TCTRL_OFFS) +#define NF_OE_TCTRL_SAME_CYC (1 << NF_OE_TCTRL_OFFS) + +#define NF_CS3_OFFS 20 /* Define if CS3 is connected to NAND Flash */ +#define NF_CS3_MASK (1 << NF_CS3_OFFS) +#define NF_CS3_NC (0 << NF_CS3_OFFS) +#define NF_CS3_C (1 << NF_CS3_OFFS) + +#define NF_CS3_CE_ACT_OFFS 21 /* Define if NAND Flash on CS3 is CE care or CE don't care */ +#define NF_CS3_CE_ACT_MASK (1 << NF_CS3_CE_ACT_OFFS) +#define NF_CS3_CE_ACT_NCARE (0 << NF_CS3_CE_ACT_OFFS) +#define NF_CS3_CE_ACT_CARE (1 << NF_CS3_CE_ACT_OFFS) + + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) \ +(csNum == BOOT_CS) ? 0x1 : ((csNum == DEV_CS3) ? (0x1 << 20) : (0x1 << (((csNum+1) % MV_DEV_MAX_CS) * 2))) + + +#define DINFCR_NF_ACT_CE_MASK(csNum) \ +(csNum == DEV_CS3) ? (0x2 << 20) : (0x2 << (((csNum+1) % MV_DEV_MAX_CS) * 2)) + + +#else + +#define DEV_BANK_PARAM_REG(num) (DEVICE_BUS_BASE + 0x045C + (num)*4) +#define DEV_BOOT_BANK_PARAM_REG (DEVICE_BUS_BASE + 0x046C) +#define DEV_NAND_CTRL_REG (DEVICE_BUS_BASE + 0x04CC) +#define DEV_BUS_CTRL_REG (DEVICE_BUS_BASE + 0x04C0) +#define DEV_INTR_CAUSE_REG (DEVICE_BUS_BASE + 0x04D0) +#define DEV_INTR_MASK_REG (DEVICE_BUS_BASE + 0x04D4) +#define DEV_ERR_ADDR_REG (DEVICE_BUS_BASE + 0x0208) +#define DEV_PWR_SAVE_CTRL_REG (DEVICE_BUS_BASE + 0x0058) +#define DEV_PWR_SAVE_CTRL_MASK 0xFFFF + +/* Device Bank Parameters register fields (DBP_REG)*/ +/* Boot Device Bank Parameters (DBP) register fields (DEV_BOOT_BANK_PARAM_REG)*/ +/* DBP_XXX_MASK_HIGH is the offset of the extend bit from the msb of the input value */ + +#define DBP_TURNOFF_OFFS_LOW 0 +#define DBP_TURNOFF_MASK_LOW 0x7 +#define DBP_TURNOFF_OFFS_HIGH 18 +#define DBP_TURNOFF_MASK_HIGH 0x8 +#define MAX_DBP_TURNOFF 0xf + +#define DBP_TURNOFF_SET(value) \ +((value & DBP_TURNOFF_MASK_LOW) << DBP_TURNOFF_OFFS_LOW) | \ +((value & DBP_TURNOFF_MASK_HIGH) << DBP_TURNOFF_OFFS_HIGH) + +#define DBP_TURNOFF_GET(value) \ +((value >> DBP_TURNOFF_OFFS_LOW) & DBP_TURNOFF_MASK_LOW) | \ +((value >> DBP_TURNOFF_OFFS_HIGH) & DBP_TURNOFF_MASK_HIGH) + +#define DBP_ACC2FIRST_OFFS_LOW 3 +#define DBP_ACC2FIRST_MASK_LOW 0xf +#define DBP_ACC2FIRST_OFFS_HIGH 17 +#define DBP_ACC2FIRST_MASK_HIGH 0x10 +#define MAX_DBP_ACC2FIRST 0x1f + +#define DBP_ACC2FIRST_SET(value) \ +((value & DBP_ACC2FIRST_MASK_LOW) << DBP_ACC2FIRST_OFFS_LOW) | \ +((value & DBP_ACC2FIRST_MASK_HIGH) << DBP_ACC2FIRST_OFFS_HIGH) + +#define DBP_ACC2FIRST_GET(value) \ +((value >> DBP_ACC2FIRST_OFFS_LOW) & DBP_ACC2FIRST_MASK_LOW) | \ +((value >> DBP_ACC2FIRST_OFFS_HIGH) & DBP_ACC2FIRST_MASK_HIGH) + + +#define DBP_ACC2NEXT_OFFS_LOW 7 +#define DBP_ACC2NEXT_MASK_LOW 0xf +#define DBP_ACC2NEXT_OFFS_HIGH 18 +#define DBP_ACC2NEXT_MASK_HIGH 0x10 +#define MAX_DBP_ACC2NEXT 0x1f + +#define DBP_ACC2NEXT_SET(value) \ +((value & DBP_ACC2FIRST_MASK_LOW) << DBP_ACC2FIRST_OFFS_LOW) | \ +((value & DBP_ACC2FIRST_MASK_HIGH) << DBP_ACC2FIRST_OFFS_HIGH) + +#define DBP_ACC2NEXT_GET(value) \ +((value >> DBP_ACC2NEXT_OFFS_LOW) & DBP_ACC2NEXT_MASK_LOW) | \ +((value >> DBP_ACC2NEXT_OFFS_HIGH) & DBP_ACC2NEXT_MASK_HIGH) + + +#define DBP_ALE2WR_OFFS_LOW 11 +#define DBP_ALE2WR_MASK_LOW 0x7 +#define DBP_ALE2WR_OFFS_HIGH 21 +#define DBP_ALE2WR_MASK_HIGH 0x8 +#define MAX_DBP_ALE2WR 0xf + +#define DBP_ALE2WR_SET(value) \ +((value & DBP_ALE2WR_MASK_LOW) << DBP_ALE2WR_OFFS_LOW) | \ +((value & DBP_ALE2WR_MASK_HIGH) << DBP_ALE2WR_OFFS_HIGH) + +#define DBP_ALE2WR_GET(value) \ +((value >> DBP_ALE2WR_OFFS_LOW) & DBP_ALE2WR_MASK_LOW) | \ +((value >> DBP_ALE2WR_OFFS_HIGH) & DBP_ALE2WR_MASK_HIGH) + + +#define DBP_WRLOW_OFFS_LOW 14 +#define DBP_WRLOW_MASK_LOW 0x7 +#define DBP_WRLOW_OFFS_HIGH 23 +#define DBP_WRLOW_MASK_HIGH 0x4 +#define MAX_DBP_WRLOW 0xf + +#define DBP_WRLOW_SET(value) \ +((value & DBP_WRLOW_MASK_LOW) << DBP_WRLOW_OFFS_LOW) | \ +((value & DBP_WRLOW_MASK_HIGH) << DBP_WRLOW_OFFS_HIGH) + +#define DBP_WRLOW_GET(value) \ +((value >> DBP_WRLOW_OFFS_LOW) & DBP_WRLOW_MASK_LOW) | \ +((value >> DBP_WRLOW_OFFS_HIGH) & DBP_WRLOW_MASK_HIGH) + +#define DBP_WRHIGH_OFFS_LOW 14 +#define DBP_WRHIGH_MASK_LOW 0x7 +#define DBP_WRHIGH_OFFS_HIGH 24 +#define DBP_WRHIGH_MASK_HIGH 0x4 +#define MAX_DBP_WRHIGH 0xf + +#define DBP_WRHIGH_SET(value) \ +((value & DBP_WRHIGH_MASK_LOW) << DBP_WRHIGH_OFFS_LOW) | \ +((value & DBP_WRHIGH_MASK_HIGH) << DBP_WRHIGH_OFFS_HIGH) + +#define DBP_WRHIGH_GET(value) \ +((value >> DBP_WRHIGH_OFFS_LOW) & DBP_WRHIGH_MASK_LOW) | \ +((value >> DBP_WRHIGH_OFFS_HIGH) & DBP_WRHIGH_MASK_HIGH) + +#define DBP_DEVWIDTH_OFFS 20 /* Device Width */ +#define DBP_DEVWIDTH_MASK (0x3 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_8BIT (0x0 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_16BIT (0x1 << DBP_DEVWIDTH_OFFS) + +#define DBP_BADRSKEW_OFFS 28 +#define DBP_BADRSKEW_MASK (0x3 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_NOGAP (0x0 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_1CYCLE (0x1 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_2CYCLE (0x2 << DBP_BADRSKEW_OFFS) + +/* Device Interface Control register fields (DIC) (DIC_REG)*/ + +#define DIC_TIMEOUT_OFFS 0 /* Timeout Timer Preset Value. */ +#define DIC_TIMEOUT_MASK (0xffff << DIC_TIMEOUT_OFFS) +#define MAX_DIC_TIMEOUT 0xffff + +#define DIC_PARSEL BIT17 /* Even or Odd parity select */ +#define DIC_RDDPPAR_OFFS 17 /* Read data path parity select */ +#define DIC_RDDPPAR_MASK (1 << DIC_RDDPPAR_OFFS) +#define DIC_RDDPPAR_EVEN (0 << DIC_RDDPPAR_OFFS) +#define DIC_RDDPPAR_ODD (1 << DIC_RDDPPAR_OFFS) + +/* NAND Flash Control register fields (NF) (NF_REG)*/ + +#define NF_BOOTCS_OFFS 0 /* Define if BOOTCS is connected to NAND Flash */ +#define NF_BOOT_MASK (1 << NF_BOOTCS_OFFS) +#define NF_BOOT_NC (0 << NF_BOOTCS_OFFS) +#define NF_BOOT_C (1 << NF_BOOTCS_OFFS) + +#define NF_BOOTCS_CE_ACT_OFFS 1 /* Define if NAND Flash on BOOTCS is CE care or CE don't care */ +#define NF_BOOTCS_CE_ACT_MASK (1 << NF_BOOTCS_CE_ACT_OFFS) +#define NF_BOOTCS_CE_ACT_NCARE (0 << NF_BOOTCS_CE_ACT_OFFS) +#define NF_BOOTCS_CE_ACT_CARE (1 << NF_BOOTCS_CE_ACT_OFFS) + +#define NF_CS0_OFFS 2 /* Define if CS0 is connected to NAND Flash */ +#define NF_CS0_MASK (1 << NF_CS0_OFFS) +#define NF_CS0_NC (0 << NF_CS0_OFFS) +#define NF_CS0_C (1 << NF_CS0_OFFS) + +#define NF_CS0_CE_ACT_OFFS 3 /* Define if NAND Flash on CS0 is CE care or CE don't care */ +#define NF_CS0_CE_ACT_MASK (1 << NF_CS0_CE_ACT_OFFS) +#define NF_CS0_CE_ACT_NCARE (0 << NF_CS0_CE_ACT_OFFS) +#define NF_CS0_CE_ACT_CARE (1 << NF_CS0_CE_ACT_OFFS) + +#define NF_CS1_OFFS 4 /* Define if CS1 is connected to NAND Flash */ +#define NF_CS1_MASK (1 << NF_CS1_OFFS) +#define NF_CS1_NC (0 << NF_CS1_OFFS) +#define NF_CS1_C (1 << NF_CS1_OFFS) + +#define NF_CS1_CE_ACT_OFFS 5 /* Define if NAND Flash on CS1 is CE care or CE don't care */ +#define NF_CS1_CE_ACT_MASK (1 << NF_CS1_CE_ACT_OFFS) +#define NF_CS1_CE_ACT_NCARE (0 << NF_CS1_CE_ACT_OFFS) +#define NF_CS1_CE_ACT_CARE (1 << NF_CS1_CE_ACT_OFFS) + +#define NF_CS2_OFFS 6 /* Define if CS2 is connected to NAND Flash */ +#define NF_CS2_MASK (1 << NF_CS2_OFFS) +#define NF_CS2_NC (0 << NF_CS2_OFFS) +#define NF_CS2_C (1 << NF_CS2_OFFS) + +#define NF_CS2_CE_ACT_OFFS 7 /* Define if NAND Flash on CS2 is CE care or CE don't care */ +#define NF_CS2_CE_ACT_MASK (1 << NF_CS2_CE_ACT_OFFS) +#define NF_CS2_CE_ACT_NCARE (0 << NF_CS2_CE_ACT_OFFS) +#define NF_CS2_CE_ACT_CARE (1 << NF_CS2_CE_ACT_OFFS) + +#define NF_INIT_SEQ_OFFS 8 /* NAND Flash initialization sequence */ +#define NF_INIT_SEQ_MASK (1 << NF_INIT_SEQ_OFFS) +#define NF_INIT_SEQ_EN (0 << NF_INIT_SEQ_OFFS) +#define NF_INIT_SEQ_DIS (1 << NF_INIT_SEQ_OFFS) + +#define NF_OE_HIGHW_OFFS 9 /* NAND Flash OE high width in core clocks units (value + 1) */ +#define NF_OE_HIGHW_MASK (0x1f << NF_OE_HIGHW_OFFS) +#define MAX_OE_HIGHW (0x1f << NF_OE_HIGHW_OFFS) + +#define NF_TREADY_OFFS 14 /* NAND Flash time ready in core clocks units (value + 1) */ +#define NF_TREADY_MASK (0x1f << NF_TREADY_OFFS) +#define MAX_TREADY (0x1f << NF_TREADY_OFFS) + +#define NF_OE_TCTRL_OFFS 19 /* NAND Flash OE toggle control */ +#define NF_OE_TCTRL_MASK (1 << NF_OE_TCTRL_OFFS) +#define NF_OE_TCTRL_1_CYC_AFT (0 << NF_OE_TCTRL_OFFS) +#define NF_OE_TCTRL_SAME_CYC (1 << NF_OE_TCTRL_OFFS) + +#define NF_CS3_OFFS 6 /* Define if CS3 is connected to NAND Flash */ +#define NF_CS3_MASK (1 << NF_CS3_OFFS) +#define NF_CS3_NC (0 << NF_CS3_OFFS) +#define NF_CS3_C (1 << NF_CS3_OFFS) + +#define NF_CS3_CE_ACT_OFFS 7 /* Define if NAND Flash on CS3 is CE care or CE don't care */ +#define NF_CS3_CE_ACT_MASK (1 << NF_CS3_CE_ACT_OFFS) +#define NF_CS3_CE_ACT_NCARE (0 << NF_CS3_CE_ACT_OFFS) +#define NF_CS3_CE_ACT_CARE (1 << NF_CS3_CE_ACT_OFFS) + + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) \ +(csNum == BOOT_CS) ? 0x1 : ((csNum == DEV_CS3) ? (0x1 << 20) : (0x1 << (((csNum+1) % MV_DEV_MAX_CS) * 2))) + + +#define DINFCR_NF_ACT_CE_MASK(csNum) \ +(csNum == DEV_CS3) ? (0x2 << 20) : (0x2 << (((csNum+1) % MV_DEV_MAX_CS) * 2)) + +/* Power Save Control Register (PSCR) */ +#define PSCR_PCI_PD BIT7 +#define PSCR_PEX0_PD BIT8 +#define PSCR_PEX10_PD BIT12 +#define PSCR_PEX11_PD BIT13 +#define PSCR_PEX12_PD BIT14 +#define PSCR_PEX13_PD BIT15 +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* #ifndef __INCmvDeviceRegsH */ diff --git a/board/mv_feroceon/mv_dd/mvSysHwConfig.h b/board/mv_feroceon/mv_dd/mvSysHwConfig.h new file mode 100644 index 0000000..6889b1b --- /dev/null +++ b/board/mv_feroceon/mv_dd/mvSysHwConfig.h @@ -0,0 +1,455 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmvSysHwConfigh +#define __INCmvSysHwConfigh +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PEX +#define MV_INCLUDE_IDMA +#define MV_INCLUDE_XOR +#define MV_INCLUDE_SPI +#define MV_INCLUDE_SATA +#define MV_INCLUDE_USB +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_CLK_PWR_CNTRL +#define MV_INCLUDE_INTEG_SATA + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board SPI Flash support */ +#define MV_INC_BOARD_SPI_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA driver*/ +#define MV_INC_BOARD_PCI_SATA + +#if defined(DB_MV78XX0) +#define CFG_DRAM_BANKS 4 +#elif defined(RD_MV78XX0_AMC) +#define MV_STATIC_DRAM_ON_BOARD +#define CFG_DRAM_BANKS 1 +#define CFG_NO_FLASH +#elif defined(RD_MV78XX0_MASA) +#define CFG_DRAM_BANKS 2 +#define CFG_NO_FLASH +#elif defined(RD_MV78XX0_H3C) +#define MV_STATIC_DRAM_ON_BOARD +#define CFG_DRAM_BANKS 1 +#define AMD_FLASH_16BIT_IN_8BIT_MODE +#endif + +/************************************************/ +/* U-Boot Specific */ +/************************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#endif + + +#define MV_CACHEABLE(address) ((address) | 0x80000000) + +/* includes */ +#define _1K 0x00000400 +#define _4K 0x00001000 +#define _8K 0x00002000 +#define _16K 0x00004000 +#define _32K 0x00008000 +#define _64K 0x00010000 +#define _128K 0x00020000 +#define _256K 0x00040000 +#define _512K 0x00080000 + +#define _1M 0x00100000 +#define _2M 0x00200000 +#define _4M 0x00400000 +#define _8M 0x00800000 +#define _16M 0x01000000 +#define _32M 0x02000000 +#define _64M 0x04000000 +#define _128M 0x08000000 +#define _256M 0x10000000 +#define _512M 0x20000000 + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _8M + +#define SDRAM_CS1_BASE 0x00800000 +#define SDRAM_CS1_SIZE _8M + +#define SDRAM_CS2_BASE 0x01000000 +#define SDRAM_CS2_SIZE _8M + +#define SDRAM_CS3_BASE 0x01800000 +#define SDRAM_CS3_SIZE _8M + +/* PCI/PEX: IO and memory size */ +#define PCIx_IO_SIZE _1M +#define PCIx_MEM0_SIZE _32M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ + +/* PCI0: IO and memory space */ +#define PCI0_IO_BASE 0xf0000000 +#define PCI0_IO_SIZE _1M +#define PCI0_MEM0_BASE 0xc0000000 +#define PCI0_MEM0_ME_BASE 0x90000000 +#define PCI0_MEM0_SIZE _64M + +/* PCI1: IO and memory space */ +#define PCI1_IO_BASE 0xf0100000 +#define PCI1_IO_SIZE _1M +#define PCI1_MEM0_BASE 0xc4000000 +#define PCI1_MEM0_ME_BASE 0x94000000 +#define PCI1_MEM0_SIZE _64M + +/* PCI2: IO and memory space */ +#define PCI2_IO_BASE 0xf0200000 +#define PCI2_IO_SIZE _1M +#define PCI2_MEM0_BASE 0xd0000000 +#define PCI2_MEM0_SIZE _64M + +/* PCI3: IO and memory space */ +#define PCI3_IO_BASE 0xf0300000 +#define PCI3_IO_SIZE _1M +#define PCI3_MEM0_BASE 0xcc000000 +#define PCI3_MEM0_ME_BASE 0x98000000 +#define PCI3_MEM0_SIZE _64M + +/* PCI4: IO and memory space */ +#define PCI4_IO_BASE 0xf0400000 +#define PCI4_IO_SIZE _1M +#define PCI4_MEM0_BASE 0xc8000000 +#define PCI4_MEM0_ME_BASE 0x9c000000 +#define PCI4_MEM0_SIZE _64M + +/* PCI5: IO and memory space */ +#define PCI5_IO_BASE 0 +#define PCI5_IO_SIZE 0 +#define PCI5_MEM0_BASE 0xd4000000 +#define PCI5_MEM0_SIZE _64M + +/* PCI6: IO and memory space */ +#define PCI6_IO_BASE 0 +#define PCI6_IO_SIZE 0 +#define PCI6_MEM0_BASE 0xd8000000 +#define PCI6_MEM0_SIZE _64M + +/* PCI7: IO and memory space */ +#define PCI7_IO_BASE 0 +#define PCI7_IO_SIZE 0 +#define PCI7_MEM0_BASE 0xdc000000 +#define PCI7_MEM0_SIZE _64M + +/* Crypto memory space */ +#define CRYPTO_BASE 0xd8000000 +#define CRYPTO_SIZE _1M + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xf1000000 /*0x14000000*/ +/* #define IDMA_INTER_REGS_BASE 0xf1060000 0x14000000 */ + +/* Device: CS0 - 32MB 32bit FLASH, CS1 - 7seg, CS2 - NAND, CS3 - SPI */ +#define DEVICE_CS0_BASE 0xf8000000 +#define DEVICE_CS0_SIZE _32M + +#define DEVICE_CS1_BASE 0xfe000000 +#define DEVICE_CS1_SIZE _1M + +#define DEVICE_CS2_BASE 0xfc000000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE 0xfd000000 +#define DEVICE_CS3_SIZE _8M + +#define DEVICE_SPI_BASE DEVICE_CS3_BASE +#define DEVICE_SPI_SIZE DEVICE_CS3_SIZE + +#if defined(MV_BOOTSIZE_256K) + +#define BOOTDEV_CS_SIZE _256K + +#elif defined(MV_BOOTSIZE_512K) + +#define BOOTDEV_CS_SIZE _512K + +#elif defined(MV_BOOTSIZE_4M) + +#define BOOTDEV_CS_SIZE _4M + +#elif defined(MV_BOOTSIZE_8M) + +#define BOOTDEV_CS_SIZE _8M + +#elif defined(MV_BOOTSIZE_16M) + +#define BOOTDEV_CS_SIZE _16M + +#elif defined(MV_BOOTSIZE_32M) + +#define BOOTDEV_CS_SIZE _32M + +#elif defined(MV_BOOTSIZE_64M) + +#define BOOTDEV_CS_SIZE _64M + +#elif defined(MV_NAND_BOOT) + +#define BOOTDEV_CS_SIZE _512K + +#else + +#define Error MV_BOOTSIZE undefined + +#endif + +#define BOOTDEV_CS_BASE ((0xFFFFFFFF - BOOTDEV_CS_SIZE) + 1) + +#if !defined(MV_NAND_BOOT) +#define CFG_NAND_BASE DEVICE_CS2_BASE +#else +#define CFG_NAND_BASE BOOTDEV_CS_BASE +#endif + +#define BOOT_FLASH_INDEX 1 +#define MAIN_FLASH_INDEX 0 + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +/* These addresses defines the place where global parameters will be placed */ +/* in case running from ROM. We Use SYS_MEM_TOP. See bootInit.c file */ +#define DRAM_DETECT_FLAG_ADDR 0x03000000 +#define DRAM_CONFIG_ROM_ADDR 0x03000004 + +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable/disable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE }, 0xFFFFFFFF, EN },/* 0 */ \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE }, 0xFFFFFFFF, EN },/* 1 */ \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE }, 0xFFFFFFFF, EN },/* 2 */ \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE }, 0xFFFFFFFF, EN },/* 3 */ \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE}, 10, EN },/* 4 */ \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE}, 11, EN },/* 5 */ \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE}, 12, EN },/* 6 */ \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE}, 9, DIS },/* 7 */ \ + {{BOOTDEV_CS_BASE, 0, BOOTDEV_CS_SIZE}, 13, EN },/* 8 */ \ + {{DEVICE_SPI_BASE, 0, DEVICE_SPI_SIZE}, 9, EN },/* 7 */ \ + {{PCI0_IO_BASE , 0, PCI0_IO_SIZE }, 0, EN },/* 9 */ \ + {{PCI0_MEM0_BASE , 0, PCI0_MEM0_SIZE }, 1, EN },/* 10 */ \ + {{PCI1_IO_BASE , 0, PCI1_IO_SIZE }, 2, EN },/* 11 */ \ + {{PCI1_MEM0_BASE , 0, PCI1_MEM0_SIZE }, 3, EN },/* 12 */ \ + {{PCI2_IO_BASE , 0, PCI2_IO_SIZE }, 4, DIS},/* 13 */ \ + {{PCI2_MEM0_BASE , 0, PCI2_MEM0_SIZE }, 5, DIS},/* 14 */ \ + {{PCI3_IO_BASE , 0, PCI3_IO_SIZE }, 4, EN },/* 15 */ \ + {{PCI3_MEM0_BASE , 0, PCI3_MEM0_SIZE }, 5, EN },/* 16 */ \ + {{PCI4_IO_BASE , 0, PCI4_IO_SIZE }, 6, EN },/* 17 */ \ + {{PCI4_MEM0_BASE , 0, PCI4_MEM0_SIZE }, 7, EN },/* 18 */ \ + {{PCI5_IO_BASE , 0, PCI5_IO_SIZE }, 5, DIS},/* 19 */ \ + {{PCI5_MEM0_BASE , 0, PCI5_MEM0_SIZE }, 5, DIS},/* 20 */ \ + {{PCI6_IO_BASE , 0, PCI6_IO_SIZE }, 6, DIS},/* 21 */ \ + {{PCI6_MEM0_BASE , 0, PCI6_MEM0_SIZE }, 6, DIS},/* 22 */ \ + {{PCI7_IO_BASE , 0, PCI7_IO_SIZE }, 7, DIS},/* 23 */ \ + {{PCI7_MEM0_BASE , 0, PCI7_MEM0_SIZE }, 7, DIS},/* 24 */ \ + {{CRYPTO_BASE , 0, CRYPTO_SIZE }, 8, EN },/* 25 */ \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE}, 14, EN },/* 26 */ \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM, TBL_TERM} \ +}; + +#define MV_CPU_IF_ADDR_WIN_MON_EXT_MAP_TBL { \ +/* base low base high size WinNum enable/disable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE }, 0xFFFFFFFF, EN },/* 0 */ \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE }, 0xFFFFFFFF, EN },/* 1 */ \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE }, 0xFFFFFFFF, EN },/* 2 */ \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE }, 0xFFFFFFFF, EN },/* 3 */ \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE}, 10, EN },/* 4 */ \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE}, 11, EN },/* 5 */ \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE}, 12, EN },/* 6 */ \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE}, 9, DIS },/* 7 */ \ + {{BOOTDEV_CS_BASE, 0, BOOTDEV_CS_SIZE}, 13, EN },/* 8 */ \ + {{DEVICE_SPI_BASE, 0, DEVICE_SPI_SIZE}, 9, EN },/* 7 */ \ + {{PCI0_IO_BASE , 0, PCI0_IO_SIZE }, 0, EN },/* 9 */ \ + {{PCI0_MEM0_ME_BASE, 0, PCI0_MEM0_SIZE }, 1, EN },/* 10 */ \ + {{PCI1_IO_BASE , 0, PCI1_IO_SIZE }, 2, EN },/* 11 */ \ + {{PCI1_MEM0_ME_BASE, 0, PCI1_MEM0_SIZE }, 3, EN },/* 12 */ \ + {{PCI2_IO_BASE , 0, PCI2_IO_SIZE }, 4, DIS},/* 13 */ \ + {{PCI2_MEM0_BASE , 0, PCI2_MEM0_SIZE }, 5, DIS},/* 14 */ \ + {{PCI3_IO_BASE , 0, PCI3_IO_SIZE }, 4, EN },/* 15 */ \ + {{PCI3_MEM0_ME_BASE, 0, PCI3_MEM0_SIZE }, 5, EN },/* 16 */ \ + {{PCI4_IO_BASE , 0, PCI4_IO_SIZE }, 6, EN },/* 17 */ \ + {{PCI4_MEM0_ME_BASE, 0, PCI4_MEM0_SIZE }, 7, EN },/* 18 */ \ + {{PCI5_IO_BASE , 0, PCI5_IO_SIZE }, 5, DIS},/* 19 */ \ + {{PCI5_MEM0_BASE , 0, PCI5_MEM0_SIZE }, 5, DIS},/* 20 */ \ + {{PCI6_IO_BASE , 0, PCI6_IO_SIZE }, 6, DIS},/* 21 */ \ + {{PCI6_MEM0_BASE , 0, PCI6_MEM0_SIZE }, 6, DIS},/* 22 */ \ + {{PCI7_IO_BASE , 0, PCI7_IO_SIZE }, 7, DIS},/* 23 */ \ + {{PCI7_MEM0_BASE , 0, PCI7_MEM0_SIZE }, 7, DIS},/* 24 */ \ + {{CRYPTO_BASE , 0, CRYPTO_SIZE }, 8, EN },/* 25 */ \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE}, 14, EN },/* 26 */ \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM, TBL_TERM} \ +}; + +/* We use the following registers to store DRAM interface pre configuration */ +/* auto-detection results */ +#define DRAM_BUF_REG0 0x60810 /* sdram bank 0 size */ +#define DRAM_BUF_REG1 0x60814 /* sdram config */ +#define DRAM_BUF_REG2 0x60818 /* sdram mode */ +#define DRAM_BUF_REG3 0x6081c /* dunit control low */ +#define DRAM_BUF_REG4 0x60820 /* sdram address control */ +#define DRAM_BUF_REG5 0x60824 /* sdram timing control low */ +#define DRAM_BUF_REG6 0x60828 /* sdram timing control high */ +#define DRAM_BUF_REG7 0x6082c /* sdram ODT control low */ +#define DRAM_BUF_REG8 0x60830 /* sdram ODT control high */ +#define DRAM_BUF_REG9 0x60834 /* sdram Dunit ODT control */ +#define DRAM_BUF_REG10 0x60838 /* sdram Extended Mode */ +#define DRAM_BUF_REG11 0x6083c /* sdram Ddr2 Timing Low */ +#define DRAM_BUF_REG12 0x60870 /* sdram Ddr2 Timing High */ +#define DRAM_BUF_REG13 0x60874 /* dunit control high */ +#define DRAM_BUF_REG14 0x60878 /* if == '1' second dimm exist */ + +/* HW cache coherency configuration */ +#define DRAM_COHERENCY NO_COHERENCY + +/* PCI stuff */ +/* Local bus and device number of PCI0/1*/ +#define PCI_HOST_BUS_NUM(pciIf) 0 +#define PCI_HOST_DEV_NUM(pciIf) 0 +#define PEX_HOST_BUS_NUM(pexIf) (1 * pexIf) +#define PEX_HOST_DEV_NUM(pexIf) 0 + + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + +/* Board clock detection */ +#undef TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#undef SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ + +/* Memory uncached, HW or SW cache coherency is not needed */ +#define MV_UNCACHED 0 +/* Memory cached, HW cache coherency supported in WriteThrough mode */ +#define MV_CACHE_COHER_HW_WT 1 +/* Memory cached, HW cache coherency supported in WriteBack mode */ +#define MV_CACHE_COHER_HW_WB 2 +/* Memory cached, No HW cache coherency, Cache coherency must be in SW */ +#define MV_CACHE_COHER_SW 3 + + +#if INTEG_SRAM_COHER == MV_CACHE_COHER_HW_WB +# define INTEG_SRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif INTEG_SRAM_COHER == MV_CACHE_COHER_HW_WT +# define INTEG_SRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif INTEG_SRAM_COHER == MV_CACHE_COHER_SW +# define INTEG_SRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif INTEG_SRAM_COHER == MV_UNCACHED +# define INTEG_SRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected INTEG_SRAM_COHER value" +#endif /* INTEG_SRAM_COHER */ + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +#define ETH_DEF_TXQ 0 +#define ETH_DEF_RXQ 0 +#define MV_ETH_TX_Q_NUM 1 +#define MV_ETH_RX_Q_NUM 1 +#define ETH_NUM_OF_RX_DESCR 64 +#define ETH_NUM_OF_TX_DESCR ETH_NUM_OF_RX_DESCR*2 + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if defined(ETH_DESCR_IN_SRAM) +# define ETH_DESCR_CONFIG_STR "ETH_DESCR_IN_SRAM" +#elif defined(ETH_DESCR_IN_SDRAM) +# define ETH_DESCR_CONFIG_STR "ETH_DESCR_IN_SDRAM" +#else +# error "ETH_DESCR_IN_SRAM or ETH_DESCR_IN_SDRAM must be defined" +#endif /* ETH_DESCR_IN_SRAM or ETH_DESCR_IN_SDRAM*/ + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + +#define MV_BRIDGE_REORDER_WA(param) \ +{ \ + volatile MV_U8 dummy = (MV_U8)param;\ +} + + +#endif /* __INCmvSysHwConfigh */ diff --git a/board/mv_feroceon/mv_dd/mv_cmd.c b/board/mv_feroceon/mv_dd/mv_cmd.c new file mode 100644 index 0000000..25cee13 --- /dev/null +++ b/board/mv_feroceon/mv_dd/mv_cmd.c @@ -0,0 +1,1171 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include +#include + +#include "mvTypes.h" +#include "mvCtrlEnvLib.h" + +#if defined(MV_INC_BOARD_DDIM) +#include "ddr2/spd/mvSpd.h" +#endif + +#if defined(MV_INC_BOARD_NOR_FLASH) +#include "norflash/mvFlash.h" +#endif + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +#include "eth-phy/mvEthPhy.h" +#endif + +#if defined(MV_INCLUDE_PEX) +#include "pex/mvPex.h" +#endif + +#if defined(MV_INCLUDE_IDMA) +#include "idma/mvIdma.h" +#include "sys/mvSysIdma.h" +#endif + +#if defined(CFG_NAND_BOOT) || defined(CFG_CMD_NAND) +#include + +/* references to names in cmd_nand.c */ +#define NANDRW_READ 0x01 +#define NANDRW_WRITE 0x00 +#define NANDRW_JFFS2 0x02 +//extern struct nand_chip nand_dev_desc[]; +extern nand_info_t nand_info[]; /* info for NAND chips */ +/* int nand_rw (struct nand_chip* nand, int cmd, + size_t start, size_t len, + size_t * retlen, u_char * buf); + int nand_erase(struct nand_chip* nand, size_t ofs, + size_t len, int clean); +*/ +extern int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); +extern int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts); + + +#endif /* CFG_NAND_BOOT */ + +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) +#if !defined(CFG_NAND_BOOT) +static unsigned int flash_in_which_sec(flash_info_t *fl,unsigned int offset) +{ + unsigned int sec_num; + if(NULL == fl) + return 0xFFFFFFFF; + + for( sec_num = 0; sec_num < fl->sector_count ; sec_num++){ + /* If last sector*/ + if (sec_num == fl->sector_count -1) + { + if((offset >= fl->start[sec_num]) && + (offset <= (fl->size + fl->start[0] - 1)) ) + { + return sec_num; + } + + } + else + { + if((offset >= fl->start[sec_num]) && + (offset < fl->start[sec_num + 1]) ) + { + return sec_num; + } + + } + } + /* return illegal sector Number */ + return 0xFFFFFFFF; + +} + +#endif /* !defined(CFG_NAND_BOOT) */ + + +/******************************************************************************* +burn a u-boot.bin on the Boot Flash +********************************************************************************/ +extern flash_info_t flash_info[]; /* info for FLASH chips */ +#include +#if (CONFIG_COMMANDS & CFG_CMD_NET) +#if defined(CFG_NAND_BOOT) +/* Boot from NAND flash */ +/* Write u-boot image into the nand flash */ +int nand_burn_uboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 ret = 0; + extern char console_buffer[]; + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + nand_write_options_t wr_opts; + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "u-boot.bin", sizeof(BootFile)); + printf("using default file \"u-boot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + printf("\n**Warning**\n"); + printf("If U-Boot Endiannes is going to change (LE->BE or BE->LE), Then Env parameters should be overriden..\n"); + printf("Override Env parameters? (y/n)"); + readline(" "); + if( strcmp(console_buffer,"Y") == 0 || + strcmp(console_buffer,"yes") == 0 || + strcmp(console_buffer,"y") == 0 ) { + + printf("Erase Env parameters sector %d... ",CFG_ENV_OFFSET); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_ENV_OFFSET; + er_opts.length = CFG_ENV_SECT_SIZE; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0); + printf("\n"); + } + + printf("Erase %d - %d ... ",CFG_MONITOR_BASE, CFG_MONITOR_LEN); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_MONITOR_BASE; + er_opts.length = CFG_MONITOR_LEN; + er_opts.quiet = 1; + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_MONITOR_BASE, CFG_MONITOR_LEN, 0); + + printf("\nCopy to Nand Flash... "); + memset(&wr_opts, 0, sizeof(wr_opts)); + wr_opts.buffer = (u_char*) load_addr; + wr_opts.length = CFG_MONITOR_LEN; + wr_opts.offset = CFG_MONITOR_BASE; + /* opts.forcejffs2 = 1; */ + wr_opts.pad = 1; + wr_opts.blockalign = 1; + wr_opts.quiet = 1; + ret = nand_write_opts(nand, &wr_opts); + /* ret = nand_rw(nand_dev_desc + 0, + NANDRW_WRITE | NANDRW_JFFS2, CFG_MONITOR_BASE, CFG_MONITOR_LEN, + &total, (u_char*)0x100000 + CFG_MONITOR_IMAGE_OFFSET); + */ + if (ret) + printf("Error - NAND burn faild!\n"); + else + printf("\ndone\n"); + + return 1; +} + +U_BOOT_CMD( + bubt, 2, 1, nand_burn_uboot_cmd, + "bubt - Burn an image on the Boot Nand Flash.\n", + " file-name \n" + "\tBurn a binary image on the Boot Nand Flash, default file-name is u-boot.bin .\n" +); + +/* Write nboot loader image into the nand flash */ +int nand_burn_nboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 ret = 0; + extern char console_buffer[]; + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + nand_write_options_t wr_opts; + + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "nboot.bin", sizeof(BootFile)); + printf("using default file \"nboot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + printf("Erase %d - %d ... ",CFG_NBOOT_BASE, CFG_NBOOT_LEN); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_NBOOT_BASE; + er_opts.length = CFG_NBOOT_LEN; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_NBOOT_BASE, CFG_NBOOT_LEN , 0); + + printf("\nCopy to Nand Flash... "); + memset(&wr_opts, 0, sizeof(wr_opts)); + wr_opts.buffer = (u_char*) load_addr; + wr_opts.length = CFG_NBOOT_LEN; + wr_opts.offset = CFG_NBOOT_BASE; + /* opts.forcejffs2 = 1; */ + wr_opts.pad = 1; + wr_opts.blockalign = 1; + wr_opts.quiet = 1; + ret = nand_write_opts(nand, &wr_opts); + /* ret = nand_rw(nand_dev_desc + 0, + NANDRW_WRITE | NANDRW_JFFS2, CFG_NBOOT_BASE, CFG_NBOOT_LEN, + &total, (u_char*)0x100000); + */ + if (ret) + printf("Error - NAND burn faild!\n"); + else + printf("\ndone\n"); + + return 1; +} + +U_BOOT_CMD( + nbubt, 2, 1, nand_burn_nboot_cmd, + "nbubt - Burn a boot loader image on the Boot Nand Flash.\n", + " file-name \n" + "\tBurn a binary boot loader image on the Boot Nand Flash, default file-name is nboot.bin .\n" +); + +#else +/* Boot from Nor flash */ +int nor_burn_uboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 s_first,s_end,env_sec; + extern char console_buffer[]; + + + s_first = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_MONITOR_BASE); + s_end = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_MONITOR_BASE + CFG_MONITOR_LEN -1); + + env_sec = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_ENV_ADDR); + + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "u-boot.bin", sizeof(BootFile)); + printf("using default file \"u-boot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + printf("Un-Protect Flash Monitor space\n"); + flash_protect (FLAG_PROTECT_CLEAR, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[BOOT_FLASH_INDEX]); + + printf("\n**Warning**\n"); + printf("If U-Boot Endiannes is going to change (LE->BE or BE->LE), Then Env parameters should be overriden..\n"); + printf("Override Env parameters? (y/n)"); + readline(" "); + if( strcmp(console_buffer,"Y") == 0 || + strcmp(console_buffer,"yes") == 0 || + strcmp(console_buffer,"y") == 0 ) { + + flash_protect (FLAG_PROTECT_CLEAR, + flash_info[BOOT_FLASH_INDEX].start[env_sec], + flash_info[BOOT_FLASH_INDEX].start[env_sec] + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + + printf("Erase Env parameters sector %d... ",env_sec); + flash_erase(&flash_info[BOOT_FLASH_INDEX], env_sec, env_sec); + + if (MV_FALSE == mvBoardIsBootFromSpi()) + flash_protect (FLAG_PROTECT_SET, + flash_info[BOOT_FLASH_INDEX].start[env_sec], + flash_info[BOOT_FLASH_INDEX].start[env_sec] + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + + } + + printf("Erase %d - %d sectors... ",s_first,s_end); + flash_erase(&flash_info[BOOT_FLASH_INDEX], s_first, s_end); + + printf("Copy to Flash... "); + + flash_write ( (uchar *)(CFG_LOAD_ADDR + CFG_MONITOR_IMAGE_OFFSET), + (ulong)CFG_MONITOR_BASE, + (ulong)(filesize - CFG_MONITOR_IMAGE_OFFSET)); + + printf("done\nProtect Flash Monitor space\n"); + flash_protect (FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[BOOT_FLASH_INDEX]); + + return 1; +} + +U_BOOT_CMD( + bubt, 2, 1, nor_burn_uboot_cmd, + "bubt - Burn an image on the Boot Flash.\n", + " file-name \n" + "\tBurn a binary image on the Boot Flash, default file-name is u-boot.bin .\n" +); +#endif /* defined(CFG_NAND_BOOT) */ +#endif /* (CONFIG_COMMANDS & CFG_CMD_NET) */ + + + +/******************************************************************************* +Reset environment variables. +********************************************************************************/ +extern flash_info_t flash_info[]; /* info for FLASH chips */ +int resetenv_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(CFG_NAND_BOOT) + printf("Erase Env parameters offset 0x%x... ",CFG_ENV_OFFSET); + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_ENV_OFFSET; + er_opts.length = CFG_ENV_SECT_SIZE; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0); + printf("done"); +#else + MV_U32 env_sec = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_ENV_ADDR); + + if (env_sec == -1) + { + printf("Could not find ENV Sector\n"); + return 0; + } + + printf("Un-Protect ENV Sector\n"); + + flash_protect(FLAG_PROTECT_CLEAR, + CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + + + printf("Erase sector %d ... ",env_sec); + flash_erase(&flash_info[BOOT_FLASH_INDEX], env_sec, env_sec); + printf("done\nProtect ENV Sector\n"); + + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + +#endif /* defined(CFG_NAND_BOOT) */ + printf("\nWarning: Default Environment Variables will take effect Only after RESET \n\n"); + return 1; +} + +U_BOOT_CMD( + resetenv, 1, 1, resetenv_cmd, + "resetenv - Return all environment variable to default.\n", + " \n" + "\t Erase the environemnt variable sector.\n" +); + +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FLASH) */ +#if CONFIG_COMMANDS & CFG_CMD_BSP + +/****************************************************************************** +* Category - General +* Functionality- The commands allows the user to view the contents of the MV +* internal registers and modify them. +* Need modifications (Yes/No) - no +*****************************************************************************/ +int ir_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +{ + MV_U32 regNum = 0x0, regVal, regValTmp, res; + MV_8 regValBin[40]; + MV_8 cmd[40]; + int i,j = 0, flagm = 0; + extern MV_8 console_buffer[]; + + if( argc == 2 ) { + regNum = simple_strtoul( argv[1], NULL, 16 ); + } + else { + printf( "Usage:\n%s\n", cmdtp->usage ); + return 0; + } + + regVal = MV_REG_READ( regNum ); + regValTmp = regVal; + printf( "Internal register 0x%x value : 0x%x\n ",regNum, regVal ); + printf( "\n 31 24 16 8 0" ); + printf( "\n | | | | |\nOLD: " ); + + for( i = 31 ; i >= 0 ; i-- ) { + if( regValTmp > 0 ) { + res = regValTmp % 2; + regValTmp = (regValTmp - res) / 2; + if( res == 0 ) + regValBin[i] = '0'; + else + regValBin[i] = '1'; + } + else + regValBin[i] = '0'; + } + + for( i = 0 ; i < 32 ; i++ ) { + printf( "%c", regValBin[i] ); + if( (((i+1) % 4) == 0) && (i > 1) && (i < 31) ) + printf( "-" ); + } + + readline( "\nNEW: " ); + strcpy(cmd, console_buffer); + if( (cmd[0] == '0') && (cmd[1] == 'x') ) { + regVal = simple_strtoul( cmd, NULL, 16 ); + flagm=1; + } + else { + for( i = 0 ; i < 40 ; i++ ) { + if(cmd[i] == '\0') + break; + if( i == 4 || i == 9 || i == 14 || i == 19 || i == 24 || i == 29 || i == 34 ) + continue; + if( cmd[i] == '1' ) { + regVal = regVal | (0x80000000 >> j); + flagm = 1; + } + else if( cmd[i] == '0' ) { + regVal = regVal & (~(0x80000000 >> j)); + flagm = 1; + } + j++; + } + } + + if( flagm == 1 ) { + MV_REG_WRITE( regNum, regVal ); + printf( "\nNew value = 0x%x\n\n", MV_REG_READ(regNum) ); + } + return 1; +} + +U_BOOT_CMD( + ir, 2, 1, ir_cmd, + "ir - reading and changing MV internal register values.\n", + " address\n" + "\tDisplays the contents of the internal register in 2 forms, hex and binary.\n" + "\tIt's possible to change the value by writing a hex value beginning with \n" + "\t0x or by writing 0 or 1 in the required place. \n" + "\tPressing enter without any value keeps the value unchanged.\n" +); + +/****************************************************************************** +* Category - General +* Functionality- Display the auto detect values of the TCLK and SYSCLK. +* Need modifications (Yes/No) - no +*****************************************************************************/ +int clk_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + printf( "TCLK %dMhz, SYSCLK %dMhz (UART baudrate %d)\n", + mvTclkGet()/1000000, mvSysClkGet()/1000000, CONFIG_BAUDRATE); + return 1; +} + +U_BOOT_CMD( + dclk, 1, 1, clk_cmd, + "dclk - Display the MV device CLKs.\n", + " \n" + "\tDisplay the auto detect values of the TCLK and SYSCLK.\n" +); + +/****************************************************************************** +* Functional only when using Lauterbach to load image into DRAM +* Category - DEBUG +* Functionality- Display the array of registers the u-boot write to. +* +*****************************************************************************/ +#if defined(REG_DEBUG) +int reg_arry[REG_ARRAY_SIZE][2]; +int reg_arry_index = 0; +int print_registers( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int i; + printf("Register display\n"); + + for (i=0; i < reg_arry_index; i++) + printf("Index %d 0x%x=0x%08x\n", i, (reg_arry[i][0] & 0x000fffff), reg_arry[i][1]); + + /* Print DRAM registers */ + printf("Index %d 0x%x=0x%08x\n", i++, 0x1500, MV_REG_READ(0x1500)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1504, MV_REG_READ(0x1504)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1508, MV_REG_READ(0x1508)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x150c, MV_REG_READ(0x150c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1510, MV_REG_READ(0x1510)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1514, MV_REG_READ(0x1514)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1518, MV_REG_READ(0x1518)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x151c, MV_REG_READ(0x151c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1400, MV_REG_READ(0x1400)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1404, MV_REG_READ(0x1404)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1408, MV_REG_READ(0x1408)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x140c, MV_REG_READ(0x140c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1410, MV_REG_READ(0x1410)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x141c, MV_REG_READ(0x141c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1420, MV_REG_READ(0x1420)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1424, MV_REG_READ(0x1424)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1428, MV_REG_READ(0x1428)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x147c, MV_REG_READ(0x147c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1494, MV_REG_READ(0x1494)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1498, MV_REG_READ(0x1498)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x149c, MV_REG_READ(0x149c)); + + printf("Number of Reg %d \n", i); + + return 1; +} + +U_BOOT_CMD( + printreg, 1, 1, print_registers, + "printreg - Display the register array the u-boot write to.\n", + " \n" + "\tDisplay the register array the u-boot write to.\n" +); +#endif + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +/****************************************************************************** +* Category - Etherent +* Functionality- Display PHY ports status (using SMI access). +* Need modifications (Yes/No) - No +*****************************************************************************/ +int sg_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(MV_INC_BOARD_QD_SWITCH) + printf( "Switch status not supported\n"); +#else + MV_U32 port; + for( port = 0 ; port < mvCtrlEthMaxPortGet(); port++ ) { + + printf( "PHY %d :\n", port ); + printf( "---------\n" ); + + mvEthPhyPrintStatus( mvBoardPhyAddrGet(port) ); + + printf("\n"); + } +#endif + return 1; +} + +U_BOOT_CMD( + sg, 1, 1, sg_cmd, + "sg - scanning the PHYs status\n", + " \n" + "\tScan all the Gig port PHYs and display their Duplex, Link, Speed and AN status.\n" +); +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + +#if defined(MV_INCLUDE_IDMA) + +/****************************************************************************** +* Category - DMA +* Functionality- Perform a DMA transaction +* Need modifications (Yes/No) - No +*****************************************************************************/ +int mvDma_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +{ + MV_8 cmd[20], c; + extern MV_8 console_buffer[]; + MV_U32 chan, src, dst, byteCount, ctrlLo; + MV_DMA_DEC_WIN win; + MV_BOOL err; + + /* IDMA channel */ + if( argc == 2 ) + chan = simple_strtoul( argv[1], NULL, 16 ); + else + chan = 0; + + /* source address */ + while(1) { + readline( "Source Address: " ); + strcpy( cmd, console_buffer ); + src = simple_strtoul( cmd, NULL, 16 ); + if( src == 0xffffffff ) printf( "Bad address !!!\n" ); + else break; + } + + /* desctination address */ + while(1) { + readline( "Destination Address: " ); + strcpy(cmd, console_buffer); + dst = simple_strtoul( cmd, NULL, 16 ); + if( dst == 0xffffffff ) printf("Bad address !!!\n"); + else break; + } + + /* byte count */ + while(1) { + readline( "Byte Count (up to 16M (0xffffff-1)): " ); + strcpy( cmd, console_buffer ); + byteCount = simple_strtoul( cmd, NULL, 16 ); + if( (byteCount > 0xffffff) || (byteCount == 0) ) printf("Bad value !!!\n"); + else break; + } + + /* compose the command */ + ctrlLo = ICCLR_BLOCK_MODE | ICCLR_NON_CHAIN_MODE | ICCLR_SRC_INC | ICCLR_DST_INC; + + + if (byteCount > _64K) + { + ctrlLo |= ICCLR_DESC_MODE_16M; + } + + /* set data transfer limit */ + while(1) { + printf( "Data transfer limit:\n" ); + printf( "(1) 8 bytes at a time.\n" ); + printf( "(2) 16 bytes at a time.\n" ); + printf( "(3) 32 bytes at a time.\n" ); + printf( "(4) 64 bytes at a time.\n" ); + printf( "(5) 128 bytes at a time.\n" ); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + ctrlLo |= (ICCLR_DST_BURST_LIM_32BYTE | ICCLR_SRC_BURST_LIM_32BYTE); + printf( "32 bytes at a time.\n" ); + break; + case '1': + ctrlLo |= (ICCLR_DST_BURST_LIM_8BYTE | ICCLR_SRC_BURST_LIM_8BYTE); + break; + case '2': + ctrlLo |= (ICCLR_DST_BURST_LIM_16BYTE | ICCLR_SRC_BURST_LIM_16BYTE); + break; + case '3': + ctrlLo |= (ICCLR_DST_BURST_LIM_32BYTE | ICCLR_SRC_BURST_LIM_32BYTE); + break; + case '4': + ctrlLo |= (ICCLR_DST_BURST_LIM_64BYTE | ICCLR_SRC_BURST_LIM_64BYTE); + break; + case '5': + ctrlLo |= (ICCLR_DST_BURST_LIM_128BYTE | ICCLR_SRC_BURST_LIM_128BYTE); + break; + default: + printf( "Bad value !!!\n" ); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* set ovveride source option */ + while(1) { + printf( "Override Source:\n" ); + printf( "(0) - no override\n" ); + mvDmaWinGet( 1, &win ); + printf( "(1) - use Win1 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 2, &win ); + printf( "(2) - use Win2 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 3, &win ); + printf( "(3) - use Win3 (%s)\n",mvCtrlTargetNameGet(win.target)); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + case '0': + printf( "No override\n" ); + break; + case '1': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(1); + break; + case '2': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(2); + break; + case '3': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(3); + break; + default: + printf("Bad value !!!\n"); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* set override destination option */ + while(1) { + printf( "Override Destination:\n" ); + printf( "(0) - no override\n" ); + mvDmaWinGet( 1, &win ); + printf( "(1) - use Win1 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 2, &win ); + printf( "(2) - use Win2 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 3, &win ); + printf( "(3) - use Win3 (%s)\n",mvCtrlTargetNameGet(win.target)); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + case '0': + printf( "No override\n" ); + break; + case '1': + ctrlLo |= ICCLR_OVRRD_DST_BAR(1); + break; + case '2': + ctrlLo |= ICCLR_OVRRD_DST_BAR(2); + break; + case '3': + ctrlLo |= ICCLR_OVRRD_DST_BAR(3); + break; + default: + printf("Bad value !!!\n"); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* wait for previous transfer completion */ + while( mvDmaStateGet(chan) != MV_IDLE ); + + /* issue the transfer */ + mvDmaCtrlLowSet( chan, ctrlLo ); + mvDmaTransfer( chan, src, dst, byteCount, 0 ); + + /* wait for completion */ + while( mvDmaStateGet(chan) != MV_IDLE ); + + printf( "Done...\n" ); + return 1; +} + +U_BOOT_CMD( + dma, 2, 1, mvDma_cmd, + "dma - Perform DMA\n", + " \n" + "\tPerform DMA transaction with the parameters given by the user.\n" +); + +#endif /* #if defined(MV_INCLUDE_IDMA) */ + +/****************************************************************************** +* Category - Memory +* Functionality- Displays the MV's Memory map +* Need modifications (Yes/No) - Yes +*****************************************************************************/ +int displayMemoryMap_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvCtrlAddrDecShow(); + return 1; +} + +U_BOOT_CMD( + map, 1, 1, displayMemoryMap_cmd, + "map - Diasplay address decode windows\n", + " \n" + "\tDisplay controller address decode windows: CPU, PCI, Gig, DMA, XOR and COMM\n" +); + + + +#include "ddr2/spd/mvSpd.h" +#if defined(MV_INC_BOARD_DDIM) + +/****************************************************************************** +* Category - Memory +* Functionality- Displays the SPD information for a givven dimm +* Need modifications (Yes/No) - +*****************************************************************************/ + +int dimminfo_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int num = 0; + + if (argc > 1) { + num = simple_strtoul (argv[1], NULL, 10); + } + + printf("*********************** DIMM%d *****************************\n",num); + + dimmSpdPrint(num); + + printf("************************************************************\n"); + + return 1; +} + +U_BOOT_CMD( + ddimm, 2, 1, dimminfo_cmd, + "ddimm - Display SPD Dimm Info\n", + " [0/1]\n" + "\tDisplay Dimm 0/1 SPD information.\n" +); + +/****************************************************************************** +* Category - Memory +* Functionality- Copy the SPD information of dimm 0 to dimm 1 +* Need modifications (Yes/No) - +*****************************************************************************/ + +int spdcpy_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + printf("Copy DIMM 0 SPD data into DIMM 1 SPD..."); + + if (MV_OK != dimmSpdCpy()) + printf("\nDIMM SPD copy fail!\n"); + else + printf("Done\n"); + + return 1; +} + +U_BOOT_CMD( + spdcpy, 2, 1, spdcpy_cmd, + "spdcpy - Copy Dimm 0 SPD to Dimm 1 SPD \n", + "" + "" +); +#endif /* #if defined(MV_INC_BOARD_DDIM) */ + +/****************************************************************************** +* Functionality- Go to an address and execute the code there and return, +* defualt address is 0x40004 +*****************************************************************************/ +extern void cpu_dcache_flush_all(void); +extern void cpu_icache_flush_invalidate_all(void); + +void mv_go(unsigned long addr,int argc, char *argv[]) +{ + int rc; + addr = MV_CACHEABLE(addr); + char* envCacheMode = getenv("cacheMode"); + + /* + * pass address parameter as argv[0] (aka command name), + * and all remaining args + */ + + if(envCacheMode && (strcmp(envCacheMode,"write-through") == 0)) + { + int i=0; + + /* Flush Invalidate I-Cache */ + cpu_icache_flush_invalidate_all(); + + /* Drain write buffer */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); + + + } + else /*"write-back"*/ + { + int i=0; + + /* Flush Invalidate I-Cache */ + cpu_icache_flush_invalidate_all(); + + /* Drain write buffer */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); + + + /* Flush invalidate D-cache */ + cpu_dcache_flush_all(); + + + } + + + rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]); + + return; +} + +int g_cmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0; + } + + addr = 0x40000; + + if (argc > 1) { + addr = simple_strtoul(argv[1], NULL, 16); + } + mv_go(addr,argc,&argv[0]); + return 1; +} + +U_BOOT_CMD( + g, CFG_MAXARGS, 1, g_cmd, + "g - start application at cached address 'addr'(default addr 0x40000)\n", + " addr [arg ...] \n" + "\tStart application at address 'addr'cachable!!!(default addr 0x40004/0x240004)\n" + "\tpassing 'arg' as arguments\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/****************************************************************************** +* Functionality- Searches for a value +*****************************************************************************/ +int fi_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 s_address,e_address,value,i,tempData; + MV_BOOL error = MV_FALSE; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 4){ + value = simple_strtoul(argv[1], NULL, 16); + s_address = simple_strtoul(argv[2], NULL, 16); + e_address = simple_strtoul(argv[3], NULL, 16); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + if(s_address == 0xffffffff || e_address == 0xffffffff) error = MV_TRUE; + if(s_address%4 != 0 || e_address%4 != 0) error = MV_TRUE; + if(s_address > e_address) error = MV_TRUE; + if(error) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + for(i = s_address; i < e_address ; i+=4) + { + tempData = (*((volatile unsigned int *)i)); + if(tempData == value) + { + printf("Value: %x found at ",value); + printf("address: %x\n",i); + return 1; + } + } + printf("Value not found!!\n"); + return 1; +} + +U_BOOT_CMD( + fi, 4, 1, fi_cmd, + "fi - Find value in the memory.\n", + " value start_address end_address\n" + "\tSearch for a value 'value' in the memory from address 'start_address to\n" + "\taddress 'end_address'.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/****************************************************************************** +* Functionality- Compare the memory with Value. +*****************************************************************************/ +int cmpm_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 s_address,e_address,value,i,tempData; + MV_BOOL error = MV_FALSE; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 4){ + value = simple_strtoul(argv[1], NULL, 16); + s_address = simple_strtoul(argv[2], NULL, 16); + e_address = simple_strtoul(argv[3], NULL, 16); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + if(s_address == 0xffffffff || e_address == 0xffffffff) error = MV_TRUE; + if(s_address%4 != 0 || e_address%4 != 0) error = MV_TRUE; + if(s_address > e_address) error = MV_TRUE; + if(error) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + for(i = s_address; i < e_address ; i+=4) + { + tempData = (*((volatile unsigned int *)i)); + if(tempData != value) + { + printf("Value: %x found at address: %x\n",tempData,i); + } + } + return 1; +} + +U_BOOT_CMD( + cmpm, 4, 1, cmpm_cmd, + "cmpm - Compare Memory\n", + " value start_address end_address.\n" + "\tCompare the memory from address 'start_address to address 'end_address'.\n" + "\twith value 'value'\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + + + +#if 0 +/****************************************************************************** +* Category - Etherent +* Functionality- Display PHY ports status (using SMI access). +* Need modifications (Yes/No) - No +*****************************************************************************/ +int eth_show_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ethRegs(argv[1]); + ethPortRegs(argv[1]); + ethPortStatus(argv[1]); + ethPortQueues(argv[1],0,0,1); + return 1; +} + +U_BOOT_CMD( + ethShow, 2, 2, eth_show_cmd, + "ethShow - scanning the PHYs status\n", + " \n" + "\tScan all the Gig port PHYs and display their Duplex, Link, Speed and AN status.\n" +); +#endif + +#if defined(MV_INCLUDE_PEX) + +#include "pci/mvPci.h" + +int pcie_phy_read_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U16 phyReg; + + mvPexPhyRegRead(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16), &phyReg); + + printf ("0x%x\n", phyReg); + + return 1; +} + +U_BOOT_CMD( + pciePhyRead, 3, 3, pcie_phy_read_cmd, + "phyRead - Read PCI-E Phy register\n", + " PCI-E_interface Phy_offset. \n" + "\tRead the PCI-E Phy register. \n" +); + + +int pcie_phy_write_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvPexPhyRegWrite(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16 ), + simple_strtoul( argv[3], NULL, 16 )); + + return 1; +} + +U_BOOT_CMD( + pciePhyWrite, 4, 4, pcie_phy_write_cmd, + "pciePhyWrite - Write PCI-E Phy register\n", + " PCI-E_interface Phy_offset value.\n" + "\tWrite to the PCI-E Phy register.\n" +); + +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) + +#include "eth-phy/mvEthPhy.h" + +int phy_read_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U16 phyReg; + + mvEthPhyRegRead(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16), &phyReg); + + printf ("0x%x\n", phyReg); + + return 1; +} + +U_BOOT_CMD( + phyRead, 3, 3, phy_read_cmd, + "phyRead - Read Phy register\n", + " Phy_address Phy_offset. \n" + "\tRead the Phy register. \n" +); + + +int phy_write_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvEthPhyRegWrite(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16 ), + simple_strtoul( argv[3], NULL, 16 )); + + return 1; +} + +U_BOOT_CMD( + phyWrite, 4, 4, phy_write_cmd, + "phyWrite - Write Phy register\n", + " Phy_address Phy_offset value.\n" + "\tWrite to the Phy register.\n" +); + +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + +#endif /* MV_TINY */ + +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) +extern void recoveryHandle(void); +int do_rcvr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + recoveryHandle(); + return 1; +} + +U_BOOT_CMD( + rcvr, 3, 1, do_rcvr, + "rcvr\t- Satrt recovery process (Distress Beacon with TFTP server)\n", + "\n" +); +#endif /* CFG_CMD_RCVR */ diff --git a/board/mv_feroceon/mv_dd/mv_dram.c b/board/mv_feroceon/mv_dd/mv_dram.c new file mode 100644 index 0000000..48078f2 --- /dev/null +++ b/board/mv_feroceon/mv_dd/mv_dram.c @@ -0,0 +1,316 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include "ddr2/mvDramIf.h" +#include "mvOs.h" +#include "mvBoardEnvLib.h" +#include "ddr2/mvDramIfRegs.h" +#include "mvCpuIfRegs.h" +#include "cpu/mvCpu.h" + +#ifdef DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +extern void i2c_init(int speed, int slaveaddr); +extern void _start(void); +extern unsigned int mvCpuPclkGet(void); +extern void reset_cpu(void); +extern int dramBoot; + + +#ifdef MV_INC_DRAM_MFG_TEST +static MV_VOID mvDramMfgTrst(void); +static MV_STATUS mv_mem_test(MV_U32* pMem, MV_U32 pattern, MV_U32 count); +static MV_STATUS mv_mem_cmp(MV_U32* pMem, MV_U32 pattern, MV_U32 count); +#endif + +MV_VOID mvIntrfaceWidthPrint(MV_VOID) +{ + MV_U32 deviceW, temp; + temp = MV_REG_READ(SDRAM_CONFIG_REG); + deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_32BIT )? 32 : 64; + printf(" %dbit width",deviceW); +} + +MV_VOID mvIntrfaceParamPrint(MV_VOID) +{ + MV_U32 temp; + + printf("DRAM"); + switch((MV_REG_READ(SDRAM_MODE_REG) >> 4) & 0x7) + { + case 0x3: printf(" CAS Latency = 3"); + break; + case 0x4: printf(" CAS Latency = 4"); + break; + case 0x5: printf(" CAS Latency = 5"); + break; + case 0x6: printf(" CAS Latency = 6"); + break; + default: printf(" unknown CAL "); + break; + } + + temp = MV_REG_READ(SDRAM_TIMING_CTRL_LOW_REG); + printf(" tRP = %d tRAS = %d tRCD=%d\n", + ((temp >> 8) & 0xf) + 1, ((temp >> 16) & 0x10) + (temp & 0xf) + 1, ((temp >> 4) & 0xf) + 1); +} + +int dram_init (void) +{ + + DECLARE_GLOBAL_DATA_PTR; + unsigned int i, dramTotalSize=0; + char name[15]; + MV_32 memBase; + + mvCtrlModelRevNameGet(name); + printf("\nSoc: %s", name); + printf(" (DDR2)\n", name); + + printf("CPU running @ %dMhz L2 running @ %dMhz\n", mvCpuPclkGet()/1000000, mvCpuL2ClkGet()/1000000); +#ifdef MV_TCLK_CALC + printf("SysClock = %dMhz , Calc TClock = %dMhz \n\n", CFG_BUS_CLK/1000000, CFG_TCLK/1000000); +#else + printf("SysClock = %dMhz , TClock = %dMhz \n\n", CFG_BUS_CLK/1000000, CFG_TCLK/1000000); +#endif +#if defined(MV_INC_BOARD_DDIM) + /* Call dramInit */ + if (0 == initdram(0)) + { + printf("DRAM Initialization Failed\n"); + reset_cpu(); + return (1); + } +#endif + + mvIntrfaceParamPrint(); + + for(i = 0; i< MV_DRAM_MAX_CS; i++) + { + memBase = mvDramIfBankBaseGet(i); + if (MV_ERROR == memBase) + gd->bd->bi_dram[i].start = 0; + else + gd->bd->bi_dram[i].start = memBase; + + gd->bd->bi_dram[i].size = mvDramIfBankSizeGet(i); + dramTotalSize += gd->bd->bi_dram[i].size; + if (gd->bd->bi_dram[i].size) + { + printf("DRAM CS[%d] base 0x%08x ",i, gd->bd->bi_dram[i].start); + mvSizePrint(gd->bd->bi_dram[i].size); + printf("\n"); + } + } + + printf("DRAM Total "); + mvSizePrint(dramTotalSize); + mvIntrfaceWidthPrint(); + printf("\n"); +#ifdef MV_INC_DRAM_MFG_TEST + mvDramMfgTrst(); +#endif + return 0; +} + +#if defined(MV_INC_BOARD_DDIM) + +/* u-boot interface function to SDRAM init - this is where all the + * controlling logic happens */ +long int initdram(int board_type) +{ + MV_VOIDFUNCPTR pRom; + MV_U32 forcedCl; /* Forced CAS Latency */ + MV_U32 disEcc; /* disable ECC */ + MV_U32 totalSize; + char * env; + MV_TWSI_ADDR slave; + + /* r0 <- current position of code */ + /* test if we run from flash or RAM */ + if(dramBoot != 1) + { + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(MV_BOARD_DIMM_I2C_CHANNEL, CFG_I2C_SPEED, CFG_TCLK, &slave, 0); + + /* Calculating MIN/MAX CAS latency according to user settings */ + env = getenv("CASset"); + + if(env && (strcmp(env,"1.5") == 0)) + { + forcedCl = 15; + } + else if(env && (strcmp(env,"2") == 0)) + { + forcedCl = 20; + } + else if(env && (strcmp(env,"2.5") == 0)) + { + forcedCl = 25; + } + else if(env && (strcmp(env,"3") == 0)) + { + forcedCl = 30; + } + else if(env && (strcmp(env,"4") == 0)) + { + forcedCl = 40; + } + else if(env && (strcmp(env,"5") == 0)) + { + forcedCl = 50; + } + else if(env && (strcmp(env,"6") == 0)) + { + forcedCl = 60; + } + else + { + forcedCl = 0; + } + + disEcc = 1; +#ifdef CONFIG_MV_ECC + /* update the enaECC env parameter */ + env = getenv("enaECC"); + if(env && ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + disEcc = 0; +#endif + /* detect the dram configuartion parameters */ + if (MV_OK != mvDramIfDetect(forcedCl,disEcc)) + { + printf("DRAM Auto Detection Failed! System Halt!\n"); + return 0; + } + + /* set the dram configuration */ + /* Calculate jump address of _mvDramIfConfig() */ + +#if defined(MV_BOOTROM) + pRom = (MV_VOIDFUNCPTR)(((MV_VOIDFUNCPTR)_mvDramIfConfig - (MV_VOIDFUNCPTR)_start) + + (MV_VOIDFUNCPTR)CFG_MONITOR_BASE + (MV_VOIDFUNCPTR)MONITOR_HEADER_LEN); +#else + pRom = (MV_VOIDFUNCPTR)(((MV_VOIDFUNCPTR)_mvDramIfConfig - (MV_VOIDFUNCPTR)_start) + + (MV_VOIDFUNCPTR)CFG_MONITOR_BASE); +#endif + + + (*pRom) (); /* Jump to _mvDramIfConfig*/ + } + + totalSize = mvDramIfSizeGet(); + + + return(totalSize); +} + +#endif /* #if defined(MV_INC_BOARD_DDIM) */ + +#ifdef MV_INC_DRAM_MFG_TEST +static MV_VOID mvDramMfgTrst(void) +{ + + /* Memory test */ + DECLARE_GLOBAL_DATA_PTR; + unsigned int mem_len,i,j, pattern; + unsigned int *mem_start; + char *env; + + env = getenv("enaPost"); + if(!env || ( (strcmp(env,"Yes") == 0) || (strcmp(env,"yes") == 0) ) ) + { + printf("Memory test pattern: "); + + for (j = 0 ; j<2 ; j++) + { + + switch(j){ + case 0: + pattern=0x55555555; + printf("0x%X, ",pattern); + break; + case 1: + pattern=0xAAAAAAAA; + printf("0x%X, ",pattern); + break; + default: + pattern=0x0; + printf("0x%X, ",pattern); + break; + } + + for(i = 0; i< MV_DRAM_MAX_CS; i++) + { + mem_start = (unsigned int *)gd->bd->bi_dram[i].start; + mem_len = gd->bd->bi_dram[i].size; + if (i == 0) + { + mem_start+= _4M; + mem_len-= _4M; + } + mem_len/=4; + if (MV_OK != mv_mem_test(mem_start, pattern, mem_len)) + { + printf(" Fail!\n"); + while(1); + } + } + } + printf(" Pass\n"); + } +} + + +static MV_STATUS mv_mem_test(MV_U32* pMem, MV_U32 pattern, MV_U32 count) +{ + int i; + for (i=0 ; i< count ; i+=1) + *(pMem + i) = pattern; + + if (MV_OK != mv_mem_cmp(pMem, pattern, count)) + { + return MV_ERROR; + } + return MV_OK; +} + +static MV_STATUS mv_mem_cmp(MV_U32* pMem, MV_U32 pattern, MV_U32 count) +{ + int i; + for (i=0 ; i< count ; i+=1) + { + if (*(pMem + i) != pattern) + { + printf("Fail\n"); + printf("Test failed at 0x%x\n",(pMem + i)); + return MV_ERROR; + } + } + + return MV_OK; +} +#endif /* MV_INC_DRAM_MFG_TEST */ diff --git a/board/mv_feroceon/mv_dd/mv_main.c b/board/mv_feroceon/mv_dd/mv_main.c new file mode 100644 index 0000000..edbc1c1 --- /dev/null +++ b/board/mv_feroceon/mv_dd/mv_main.c @@ -0,0 +1,1414 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +#include "mvCtrlEnvLib.h" +#include +#include "mvTypes.h" +#include "mvBoardEnvLib.h" +#include "mvCpuIf.h" +#include "mvCtrlEnvLib.h" +#include "mv_mon_init.h" +#include "mvDebug.h" +#include "device/mvDevice.h" +#include "twsi/mvTwsi.h" +#include "ethfp/mvEth.h" +#include "pex/mvPex.h" +#include "eth-phy/mvEthPhy.h" +#include "ethSwitch/mv_switch.h" +#include "gpp/mvGpp.h" +#include "sys/mvSysUsb.h" + +#ifdef MV_INCLUDE_RTC +#include "rtc/integ_rtc/mvRtc.h" +#elif defined CONFIG_RTC_DS1338_DS1339 +#include "rtc/ext_rtc/mvDS133x.h" +#endif + +#if defined(MV_INCLUDE_XOR) +#include "xor/mvXor.h" +extern MV_STATUS mvXorInit (MV_VOID); +#endif +#if defined(MV_INCLUDE_IDMA) +#include "sys/mvSysIdma.h" +#include "idma/mvIdma.h" +extern MV_STATUS mvDmaInit (MV_VOID); +#endif +#if defined(MV_INCLUDE_USB) +#include "usb/mvUsb.h" +#endif + +#include "cpu/mvCpu.h" + +#ifdef CONFIG_PCI +# include +#endif +#include "pci/mvPciRegs.h" + +#include +#include + +#include "net.h" +#include + +/* #define MV_DEBUG */ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +/* CPU address decode table. */ +MV_CPU_DEC_WIN mvCpuAddrWinMap[] = MV_CPU_IF_ADDR_WIN_MAP_TBL; +#if defined(MV78XX0) && defined(MV_INCLUDE_MONT_EXT) +MV_CPU_DEC_WIN mvCpuAddrWinMonExtMap[] = MV_CPU_IF_ADDR_WIN_MON_EXT_MAP_TBL; +#endif + +#if defined(RD_88F6281) || defined(RD_88F6192) +static void mvHddPowerCtrl(void); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) +static void recoveryDetection(void); +void recoveryHandle(void); +static u32 rcvrflag = 0; +#endif +void mv_cpu_init(void); +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +int mv_set_power_scheme(void); +#endif + +#ifdef CFG_FLASH_CFI_DRIVER +MV_VOID mvUpdateNorFlashBaseAddrBank(MV_VOID); +int mv_board_num_flash_banks; +extern flash_info_t flash_info[]; /* info for FLASH chips */ +extern unsigned long flash_add_base_addr (uint flash_index, ulong flash_base_addr); +#endif /* CFG_FLASH_CFI_DRIVER */ + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +extern MV_VOID mvEgigaPhySwitchInit(void); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +/* Define for SDK 2.0 */ +int __aeabi_unwind_cpp_pr0(int a,int b,int c) {return 0;} +int __aeabi_unwind_cpp_pr1(int a,int b,int c) {return 0;} +#endif + +#if 0 +MV_VOID mvMppModuleTypePrint(MV_VOID); +#endif + +/* Define for SDK 2.0 */ +int raise(void) {return 0;} + +void print_mvBanner(void) +{ +#ifdef CONFIG_SILENT_CONSOLE + DECLARE_GLOBAL_DATA_PTR; + gd->flags |= GD_FLG_SILENT; +#endif + printf("\n"); + printf(" __ __ _ _\n"); + printf(" | \\/ | __ _ _ ____ _____| | |\n"); + printf(" | |\\/| |/ _` | '__\\ \\ / / _ \\ | |\n"); + printf(" | | | | (_| | | \\ V / __/ | |\n"); + printf(" |_| |_|\\__,_|_| \\_/ \\___|_|_|\n"); + printf(" _ _ ____ _\n"); + printf("| | | | | __ ) ___ ___ | |_ \n"); + printf("| | | |___| _ \\ / _ \\ / _ \\| __| \n"); + printf("| |_| |___| |_) | (_) | (_) | |_ \n"); + printf(" \\___/ |____/ \\___/ \\___/ \\__| "); +#if !defined(MV_NAND_BOOT) +#if defined(MV_INCLUDE_MONT_EXT) + if(!enaMonExt()) + printf(" ** LOADER **"); + else + printf(" ** MONITOR **"); +#else + + printf(" ** Forcing LOADER mode only **"); +#endif /* MV_INCLUDE_MONT_EXT */ +#endif + return; +} + +void print_dev_id(void){ + static char boardName[30]; + + mvBoardNameGet(boardName); + +#if defined(MV_CPU_BE) + printf("\n ** MARVELL BOARD: %s BE ",boardName); +#else + printf("\n ** MARVELL BOARD: %s LE ",boardName); +#endif + + return; +} + + +void maskAllInt(void) +{ + /* mask all external interrupt sources */ + MV_REG_WRITE(CPU_AHB_MBUS_MASK_INT_REG(0), 0); + MV_REG_WRITE(CPU_INT_MASK_ERROR_REG(0), 0); + MV_REG_WRITE(CPU_INT_MASK_LOW_REG(0), 0); + MV_REG_WRITE(CPU_INT_MASK_HIGH_REG(0), 0); +} + +/* init for the Master*/ +void misc_init_r_dec_win(void) +{ +#if defined(MV_INCLUDE_USB) + { + char *env; + + env = getenv("usb0Mode"); + if((!env) || (strcmp(env,"host") == 0) || (strcmp(env,"Host") == 0) ) + { + setenv("usb0Mode","host"); + printf("USB 0: host mode\n"); + mvUsbInit(0, MV_TRUE); + } + else + { + printf("USB 0: device mode\n"); + mvUsbInit(0, MV_FALSE); + } + + env = getenv("usb1Mode"); + if((!env) || (strcmp(env,"host") == 0) || (strcmp(env,"Host") == 0) ) + { + setenv("usb1Mode","host"); + printf("USB 1: host mode\n"); + mvUsbInit(1, MV_TRUE); + } + else + { + printf("USB 1: device mode\n"); + mvUsbInit(1, MV_FALSE); + } + + env = getenv("usb2Mode"); + if((!env) || (strcmp(env,"device") == 0) || (strcmp(env,"Device") == 0) ) + { + setenv("usb2Mode","device"); + printf("USB 2: device mode\n"); + mvUsbInit(2, MV_FALSE); + } + else + { + printf("USB 2: host mode\n"); + mvUsbInit(2, MV_TRUE); + } + + + } +#endif/* #if defined(MV_INCLUDE_USB) */ + +#if defined(MV_INCLUDE_XOR) + mvXorInit(); +#endif +#if defined(MV_INCLUDE_IDMA) + mvDmaInit(); +#endif +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + mv_set_power_scheme(); +#endif + + return; +} + + +/* + * Miscellaneous platform dependent initialisations + */ + +extern MV_STATUS mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data); +extern MV_STATUS mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data); + +/* golabal mac address for yukon EC */ +unsigned char yuk_enetaddr[6]; +extern int interrupt_init (void); +extern void i2c_init(int speed, int slaveaddr); + +int cpuMapInit (void) +{ + /* For Mon ext mode only we reset the PEX mem base from 0xc0000000 to + 0x90000000 in order to enable working with CIV page table */ +#if defined(MV78XX0) + if (enaMonExt()) + mvCpuIfInit(mvCpuAddrWinMonExtMap); +#endif + return 0; +} + + +int board_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; +#if defined(MV_INCLUDE_TWSI) + MV_TWSI_ADDR slave; +#endif + unsigned int i; + + maskAllInt(); + + /* must initialize the int in order for udelay to work */ + interrupt_init(); + +#if defined(MV_INCLUDE_TWSI) + slave.type = ADDR7_BIT; + slave.address = 0; + for (i = 0; i < MV_TWSI_MAX_CHAN; i++) + mvTwsiInit(i, CFG_I2C_SPEED, CFG_TCLK, &slave, 0); +#endif + + /* Init the Board environment module (device bank params init) */ + mvBoardEnvInit(); + + /* Init the Controlloer environment module (MPP init) */ + mvCtrlEnvInit(); + + mvBoardDebug7Seg(3); + + /* Init the Controller CPU interface */ + mvCpuIfInit(mvCpuAddrWinMap); + + /* arch number of Integrator Board */ + gd->bd->bi_arch_number = 528; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + /* relocate the exception vectors */ + /* U-Boot is running from DRAM at this stage */ + for(i = 0; i < 0x100; i+=4) + { + *(unsigned int *)(0x0 + i) = *(unsigned int*)(TEXT_BASE + i); + } + + /* Update NOR flash base address bank for CFI driver */ +#ifdef CFG_FLASH_CFI_DRIVER + mvUpdateNorFlashBaseAddrBank(); +#endif /* CFG_FLASH_CFI_DRIVER */ + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) + /* Init the PHY or Switch of the board */ + mvEgigaPhySwitchInit(); +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + + mvBoardDebug7Seg(4); + + return 0; +} + +void misc_init_r_env(void){ + char *env; + char tmp_buf[10]; + unsigned int malloc_len; + DECLARE_GLOBAL_DATA_PTR; + + unsigned int flashSize =0 , secSize =0, ubootSize =0; + char buff[256]; + +#if defined(MV_BOOTSIZE_4M) + flashSize = _4M; +#elif defined(MV_BOOTSIZE_8M) + flashSize = _8M; +#elif defined(MV_BOOTSIZE_16M) + flashSize = _16M; +#elif defined(MV_BOOTSIZE_32M) + flashSize = _32M; +#elif defined(MV_BOOTSIZE_64M) + flashSize = _64M; +#endif + +#if defined(MV_SEC_64K) + secSize = _64K; +#if defined(MV_TINY_IMAGE) + ubootSize = _256K; +#else + ubootSize = _512K; +#endif +#elif defined(MV_SEC_128K) + secSize = _128K; +#if defined(MV_TINY_IMAGE) + ubootSize = _128K * 3; +#else + ubootSize = _128K * 5; +#endif +#elif defined(MV_SEC_256K) + secSize = _256K; +#if defined(MV_TINY_IMAGE) + ubootSize = _256K * 3; +#else + ubootSize = _256K * 3; +#endif +#endif + /* Dual CPU Firmware load address */ + env = getenv("fw_image_base"); + if(!env) + setenv("fw_image_base", "0x0"); + + /* Dual CPU Firmware size */ + env = getenv("fw_image_size"); + if(!env) + setenv("fw_image_size", "0x0"); + +#ifndef MV_STATIC_DRAM_ON_BOARD +#ifdef CONFIG_MV_ECC + /* update the enaECC env parameter */ + env = getenv("enaECC"); + if(env && ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + setenv("enaECC","yes"); + else +#endif + setenv("enaECC","no"); +#endif + + if ((0 == flashSize) || (0 == secSize) || (0 == ubootSize)) + { + env = getenv("console"); + if(!env) + setenv("console","console=ttyS0,115200"); + } + else + { + sprintf(buff,"console=ttyS0,115200 mtdparts=cfi_flash:0x%x(root),0x%x(uboot)ro", + flashSize - ubootSize, ubootSize); + env = getenv("console"); + if(!env) + setenv("console",buff); + } + + + /* Linux open port support */ + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + setenv("mainlineLinux","yes"); + else + setenv("mainlineLinux","no"); + + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + /* arch number for open port Linux */ + env = getenv("arcNumber"); + if(!env ) + { + /* arch number according to board ID */ + int board_id = mvBoardIdGet(); + switch(board_id){ + case(DB_78XX0_ID): + sprintf(tmp_buf,"%d", DB_78XX0_BP_MLL_ID); + board_id = DB_78XX0_BP_MLL_ID; + /* Set CPU ID to MRVL */ + MV_REG_BIT_SET(CPU_CONFIG_REG(whoAmI()),CCR_MRVL_CPU_ID); + + break; + default: + sprintf(tmp_buf,"%d", board_id); + board_id = board_id; + break; + } + gd->bd->bi_arch_number = board_id; + setenv("arcNumber", tmp_buf); + } + else + { + gd->bd->bi_arch_number = simple_strtoul(env, NULL, 10); + } + } + + /* update the CASset env parameter */ + env = getenv("CASset"); + if(!env ) + { +#ifdef MV_MIN_CAL + setenv("CASset","min"); +#else + setenv("CASset","max"); +#endif + } + /* Monitor extension */ +#ifdef MV_INCLUDE_MONT_EXT + env = getenv("enaMonExt"); + if(/* !env || */ ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + setenv("enaMonExt","yes"); + else +#endif + setenv("enaMonExt","no"); + +#if defined (MV_INC_BOARD_NOR_FLASH) + env = getenv("enaFlashBuf"); + if( ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("enaFlashBuf","no"); + else + setenv("enaFlashBuf","yes"); +#endif + + /* CPU streaming */ + env = getenv("enaCpuStream"); + if(!env || ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + setenv("enaCpuStream","yes"); + else + setenv("enaCpuStream","no"); + + /* Write allocation */ + env = getenv("enaWrAllo"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaWrAllo","no"); + else + setenv("enaWrAllo","yes"); + + /* FPU */ + env = getenv("enaFPU"); + if( !env || ( ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ))) + setenv("enaFPU","yes"); + else + setenv("enaFPU","no"); + + /* Pex mode */ + env = getenv("pexMode"); + if( env && ( ((strcmp(env,"EP") == 0) || (strcmp(env,"ep") == 0) ))) + setenv("pexMode","EP"); + else + setenv("pexMode","RC"); + + env = getenv("disL2Cache"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("disL2Cache","no"); + else + setenv("disL2Cache","yes"); + + env = getenv("setL2CacheWT"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("setL2CacheWT","no"); + else + setenv("setL2CacheWT","yes"); + + env = getenv("disL2Prefetch"); + if(!env || ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + setenv("disL2Prefetch","yes"); + else + setenv("disL2Prefetch","no"); + + env = getenv("setL2Size256K"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("setL2Size256K","no"); + else + setenv("setL2Size256K","yes"); + + env = getenv("disL2Ecc"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("disL2Ecc","no"); + else + setenv("disL2Ecc","yes"); + + + env = getenv("sata_dma_mode"); + if( env && ((strcmp(env,"No") == 0) || (strcmp(env,"no") == 0) ) ) + setenv("sata_dma_mode","no"); + else + setenv("sata_dma_mode","yes"); + + + /* Malloc length */ + env = getenv("MALLOC_len"); + malloc_len = simple_strtoul(env, NULL, 10) << 20; + if(malloc_len == 0){ + sprintf(tmp_buf,"%d",CFG_MALLOC_LEN>>20); + setenv("MALLOC_len",tmp_buf); + } + + /* primary network interface */ + env = getenv("ethprime"); + if(!env) + setenv("ethprime",ENV_ETH_PRIME); + + /* netbsd boot arguments */ + env = getenv("netbsd_en"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("netbsd_en","no"); + else + { + setenv("netbsd_en","yes"); + env = getenv("netbsd_gw"); + if(!env) + setenv("netbsd_gw","192.168.0.254"); + + env = getenv("netbsd_mask"); + if(!env) + setenv("netbsd_mask","255.255.255.0"); + + env = getenv("netbsd_fs"); + if(!env) + setenv("netbsd_fs","nfs"); + + env = getenv("netbsd_server"); + if(!env) + setenv("netbsd_server","192.168.0.1"); + + env = getenv("netbsd_ip"); + if(!env) + { + env = getenv("ipaddr"); + setenv("netbsd_ip",env); + } + + env = getenv("netbsd_rootdev"); + if(!env) + setenv("netbsd_rootdev","mgi0"); + + env = getenv("netbsd_add"); + if(!env) + setenv("netbsd_add","0x800000"); + + env = getenv("netbsd_get"); + if(!env) + setenv("netbsd_get","tftpboot $(netbsd_add) $(image_name)"); + +#if defined(MV_INC_BOARD_QD_SWITCH) + env = getenv("netbsd_netconfig"); + if(!env) + setenv("netbsd_netconfig","mv_net_config=<((mgi0,00:00:11:22:33:44,0)(mgi1,00:00:11:22:33:55,1:2:3:4)),mtu=1500>"); +#endif + env = getenv("netbsd_set_args"); + if(!env) + setenv("netbsd_set_args","setenv bootargs nfsroot=$(netbsd_server):$(rootpath) fs=$(netbsd_fs) \ +ip=$(netbsd_ip) serverip=$(netbsd_server) mask=$(netbsd_mask) gw=$(netbsd_gw) rootdev=$(netbsd_rootdev) \ +ethaddr=$(ethaddr) $(netbsd_netconfig)"); + + env = getenv("netbsd_boot"); + if(!env) + setenv("netbsd_boot","bootm $(netbsd_add) $(bootargs)"); + + env = getenv("netbsd_bootcmd"); + if(!env) + setenv("netbsd_bootcmd","run netbsd_get ; run netbsd_set_args ; run netbsd_boot"); + } + + /* vxWorks boot arguments */ + env = getenv("vxworks_en"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("vxworks_en","no"); + else + { + char* buff = (char *)0x1100; + setenv("vxworks_en","yes"); + + sprintf(buff,"mgi(0,0) host:vxWorks.st"); + env = getenv("serverip"); + strcat(buff, " h="); + strcat(buff,env); + env = getenv("ipaddr"); + strcat(buff, " e="); + strcat(buff,env); + strcat(buff, ":ffff0000 u=anonymous pw=target "); + + setenv("vxWorks_bootargs",buff); + } + + /* linux boot arguments */ + env = getenv("bootargs_root"); + if(!env) + setenv("bootargs_root","root=/dev/nfs rw"); + + /* For open Linux we set boot args differently */ + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + env = getenv("bootargs_end"); + if(!env) + setenv("bootargs_end",":::orion:eth0:none"); + } + else + { + env = getenv("bootargs_end"); + if(!env) +#if defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootargs_end",CFG_BOOTARGS_END_SWITCH); +#else + setenv("bootargs_end",CFG_BOOTARGS_END); +#endif + } + + env = getenv("image_name"); + if(!env) + setenv("image_name","uImage"); + + +#if (CONFIG_BOOTDELAY >= 0) + env = getenv("bootcmd"); + if(!env) +#if defined(MV_INCLUDE_TDM) && defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig) $(mvPhoneConfig); bootm 0x400000; "); +#elif defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig); bootm 0x400000; "); +#elif defined(MV_INCLUDE_TDM) + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvPhoneConfig); bootm 0x400000; "); +#else + + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x400000; "); +#endif +#endif /* (CONFIG_BOOTDELAY >= 0) */ + + env = getenv("standalone"); + if(!env) +#if defined(MV_INCLUDE_TDM) && defined(MV_INC_BOARD_QD_SWITCH) + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig) $(mvPhoneConfig); bootm 0x400000;"); +#elif defined(MV_INC_BOARD_QD_SWITCH) + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig); bootm 0x400000;"); +#elif defined(MV_INCLUDE_TDM) + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvPhoneConfig); bootm 0x400000;"); +#else + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x400000;"); +#endif + + /* Set boodelay to 3 sec, if Monitor extension are disabled */ + if(!enaMonExt()){ + setenv("bootdelay","3"); + setenv("disaMvPnp","no"); + } + + /* Disable PNP config of Marvel memory controller devices. */ + env = getenv("disaMvPnp"); + if(!env) + setenv("disaMvPnp","no"); + +#if (defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH)) +#include "cesa/mvMD5.h" + /* Generate random ip and mac address */ + /* Read DRAM FTDLL register to create random data for enc */ + unsigned int xi, xj, xk, xl, i; + char ethaddr[4][30]; + + char temp[20]; + MV_U32 random[16]; + unsigned char digest[16]; + + MV_REG_BIT_SET(0x1478, BIT7); + for(i=0; i < 16;i++) + random[i] = MV_REG_READ(0x1470); + + /* Run MD5 over the ftdll buffer */ + mvMD5((unsigned char*)random, 64, digest); + + xi = (digest[0]%254); + /* No valid ip with one of the fileds has the value 0 */ + if (xi == 0) + xi+=2; + + xj = (digest[1]%254); + /* No valid ip with one of the fileds has the value 0 */ + if (xj == 0) + xj+=2; + + /* Check if the ip address is the same as the server ip */ + if ((xj == 1) && (xi == 11)) + xi+=2; + + xk = digest[2]; + xl = digest[3]; + + sprintf(ethaddr[0],"00:50:43:%02x:%02x:%02x",xk,xi,xj); + sprintf(ethaddr[1],"00:50:43:%02x:%02x:%02x",xl,xi,xj); + sprintf(ethaddr[2],"00:50:43:%02x:%02x:%02x",xk,xj,xi); + sprintf(ethaddr[3],"00:50:43:%02x:%02x:%02x",xl,xj,xi); + + /* MAC addresses */ + for (i = 0 ;i < mvCtrlEthMaxPortGet();i++) + { + sprintf( temp,(i ? "eth%daddr" : "ethaddr"), i); + env = getenv(temp); + if(!env) + setenv(temp,ethaddr[i]); + + sprintf( temp,(i ? "eth%dmtu" : "ethmtu"), i); + env = getenv(temp); + if(!env) + setenv(temp,"1500"); + } +#if defined(MV_INCLUDE_TDM) + /* Set mvPhoneConfig env parameter */ + env = getenv("mvPhoneConfig"); + if(!env ) + setenv("mvPhoneConfig","mv_phone_config=dev0:fxs,dev1:fxo"); +#endif +#if defined(MV_INC_BOARD_QD_SWITCH) + /* Set mvNetConfig env parameter */ + env = getenv("mvNetConfig"); + if(!env ) + setenv("mvNetConfig","mv_net_config=(00:aa:bb:cc:dd:ee,0)(00:11:22:33:44:55,1:2:3:4),mtu=1500"); +#endif +#endif /* (MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) */ + +#if defined(MV_INCLUDE_USB) + /* USB Host */ + env = getenv("usb0Mode"); + if(!env) + setenv("usb0Mode",ENV_USB0_MODE); + + env = getenv("usb1Mode"); + if(!env) + setenv("usb1Mode",ENV_USB1_MODE); + + env = getenv("usb2Mode"); + if(!env) + setenv("usb2Mode",ENV_USB2_MODE); +#endif /* (MV_INCLUDE_USB) */ + +#if defined(YUK_ETHADDR) + env = getenv("yuk_ethaddr"); + if(!env) + setenv("yuk_ethaddr",YUK_ETHADDR); + + { + int i; + char *tmp = getenv ("yuk_ethaddr"); + char *end; + + for (i=0; i<6; i++) { + yuk_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end+1 : end; + } + } +#endif /* defined(YUK_ETHADDR) */ + +#if defined(RD_88F6281) || defined(RD_88F6192) + mvHddPowerCtrl(); +#endif +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + env = getenv("netretry"); + if (!env) + setenv("netretry","no"); + + env = getenv("rcvrip"); + if (!env) + setenv("rcvrip",RCVR_IP_ADDR); + + env = getenv("loadaddr"); + if (!env) + setenv("loadaddr",RCVR_LOAD_ADDR); + + env = getenv("autoload"); + if (!env) + setenv("autoload","no"); + +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + /* Check the recovery trigger */ + recoveryDetection(); +#endif +#endif + return; +} + +#ifdef BOARD_LATE_INIT +int board_late_init (void) +{ + /* Check if to use the LED's for debug or to use single led for init and Linux heartbeat */ + mvBoardDebug7Seg(0); + return 0; +} +#endif + +int misc_init_r (void) +{ + char name[128]; + + mvBoardDebug7Seg(5); + + /* init special env variables */ + misc_init_r_env(); + + mvCpuNameGet(name); + printf("\nCPU : %s\n", name); + + mv_cpu_init(); + +#if defined(MV_INCLUDE_MONT_EXT) + if(enaMonExt()){ + printf("\n Marvell monitor extension:\n"); + mon_extension_after_relloc(); + } + printf("\n"); +#endif /* MV_INCLUDE_MONT_EXT */ + + printf("\n"); + /* init the units decode windows */ + misc_init_r_dec_win(); + + mvBoardDebug7Seg(6); + +#ifdef CONFIG_PCI +#if !defined(MV_MEM_OVER_PCI_WA) && !defined(MV_MEM_OVER_PEX_WA) + pci_init(); +#endif +#endif + + mvBoardDebug7Seg(7); + + return 0; +} + +MV_U32 mvTclkGet(void) +{ + DECLARE_GLOBAL_DATA_PTR; + /* get it only on first time */ + if(gd->tclk == 0) + gd->tclk = mvBoardTclkGet(); + + return gd->tclk; +} + +MV_U32 mvSysClkGet(void) +{ + DECLARE_GLOBAL_DATA_PTR; + /* get it only on first time */ + if(gd->bus_clk == 0) + gd->bus_clk = mvBoardSysClkGet(); + + return gd->bus_clk; +} + +/* exported for EEMBC */ +MV_U32 mvGetRtcSec(void) +{ + MV_RTC_TIME time; +#ifdef MV_INCLUDE_RTC + mvRtcTimeGet(&time); +#elif defined CONFIG_RTC_DS1338_DS1339 + mvRtcDS133xTimeGet(&time); +#endif + return (time.minutes * 60) + time.seconds; +} + +void reset_cpu(void) +{ + mvBoardReset(); +} + +void mv_cpu_init(void) +{ + char *env; + volatile unsigned int temp; + + /*CPU streaming & write allocate */ + env = getenv("enaWrAllo"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp |= BIT28; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + + } + else + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp &= ~BIT28; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + } + + env = getenv("enaCpuStream"); + if(!env || (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp &= ~BIT29; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + } + else + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp |= BIT29; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + } + + /* Verifay write allocate and streaming */ + printf("\n"); + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + if (temp & BIT29) + printf("Streaming enabled \n"); + else + printf("Streaming disabled \n"); + if (temp & BIT28) + printf("Write allocate enabled\n"); + else + printf("Write allocate disabled\n"); + + env = getenv("enaFPU"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + /* init and Enable FPU to Run Fast Mode */ + printf("FPU initialized to Run Fast Mode.\n"); + /* Enable */ + temp = FPEXC_ENABLE; + fmxr(FPEXC, temp); + /* Run Fast Mode */ + temp = fmrx(FPSCR); + temp |= (FPSCR_DEFAULT_NAN | FPSCR_FLUSHTOZERO); + fmxr(FPSCR, temp); + } + else + { + printf("FPU not initialized\n"); + /* Disable */ + temp = fmrx(FPEXC); + temp &= ~FPEXC_ENABLE; + fmxr(FPEXC, temp); + } + + /* DCache Pref */ + env = getenv("enaDCPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + MV_REG_BIT_SET( CPU_CONFIG_REG(whoAmI()) , CCR_DCACH_PREF_BUF_ENABLE); + + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + MV_REG_BIT_RESET( CPU_CONFIG_REG(whoAmI()) , CCR_DCACH_PREF_BUF_ENABLE); + + /* ICache Pref */ + env = getenv("enaICPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + MV_REG_BIT_SET( CPU_CONFIG_REG(whoAmI()) , CCR_ICACH_PREF_BUF_ENABLE); + + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + MV_REG_BIT_RESET( CPU_CONFIG_REG(whoAmI()) , CCR_ICACH_PREF_BUF_ENABLE); + + /* Set L2C WT mode - Set bit 17 */ + temp = MV_REG_READ(CPU_CTRL_STAT_REG(whoAmI())); + env = getenv("setL2CacheWT"); + if(!env || ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + temp |= BIT17; + else + temp &= ~BIT17; + + /* Set L2C size */ + env = getenv("setL2Size256K"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + temp &= ~BIT21; + else + temp |= BIT21; + MV_REG_WRITE(CPU_CTRL_STAT_REG(whoAmI()),temp); + + /* Set L2 ECC en/dis - Set bit 22 */ + temp = MV_REG_READ(CPU_CONFIG_REG(whoAmI())); + env = getenv("disL2Ecc"); + if(env && ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + temp |= BIT22; + else + temp &= ~BIT22; + MV_REG_WRITE(CPU_CONFIG_REG(whoAmI()),temp); + + /* L2Cache settings */ + asm ("mrc p15, 1, %0, c15, c1, 0":"=r" (temp)); + + /* Disable L2C pre fetch - Set bit 24 */ + env = getenv("disL2Prefetch"); + if(env && ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + temp &= ~BIT24; + else + temp |= BIT24; + + /* enable L2C - Set bit 22 */ + env = getenv("disL2Cache"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + temp |= BIT22; + else + temp &= ~BIT22; + + asm ("mcr p15, 1, %0, c15, c1, 0": :"r" (temp)); + + + /* Enable i cache */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (temp)); + temp |= BIT12; + /* Change reset vector to address 0x0 */ + temp &= ~BIT13; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (temp)); +} +#if 0 +/******************************************************************************* +* mvBoardMppModuleTypePrint - print module detect +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvMppModuleTypePrint(MV_VOID) +{ + + MV_BOARD_MPP_GROUP_CLASS devClass; + MV_BOARD_MPP_TYPE_CLASS mppGroupType; + MV_U32 devId; + MV_U32 maxMppGrp = 1; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + maxMppGrp = MV_6281_MPP_MAX_MODULE; + break; + case MV_6192_DEV_ID: + maxMppGrp = MV_6192_MPP_MAX_MODULE; + break; + case MV_6180_DEV_ID: + maxMppGrp = MV_6180_MPP_MAX_MODULE; + break; + } + + for (devClass = 0; devClass < maxMppGrp; devClass++) + { + mppGroupType = mvBoardMppGroupTypeGet(devClass); + + switch(mppGroupType) + { + case MV_BOARD_TDM: + printf("Module %d is TDM\n", devClass); + break; + case MV_BOARD_AUDIO: + printf("Module %d is AUDIO\n", devClass); + break; + case MV_BOARD_RGMII: + printf("Module %d is RGMII\n", devClass); + break; + case MV_BOARD_GMII: + printf("Module %d is GMII\n", devClass); + break; + case MV_BOARD_TS: + printf("Module %d is TS\n", devClass); + break; + default: + break; + } + } +} +#endif +/* Set unit in power off mode acording to the detection of MPP */ +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +int mv_set_power_scheme(void) +{ +#if 0 + int mppGroupType1 = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_1); + int mppGroupType2 = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_2); + MV_U32 devId = mvCtrlModelGet(); + + if (devId == MV_6180_DEV_ID) + { + /* Sata power down */ + mvCtrlPwrMemSet(SATA_UNIT_ID, 1, MV_FALSE); + mvCtrlPwrMemSet(SATA_UNIT_ID, 0, MV_FALSE); + mvCtrlPwrClckSet(SATA_UNIT_ID, 1, MV_FALSE); + mvCtrlPwrClckSet(SATA_UNIT_ID, 0, MV_FALSE); + /* Sdio power down */ + mvCtrlPwrMemSet(SDIO_UNIT_ID, 0, MV_FALSE); + mvCtrlPwrClckSet(SDIO_UNIT_ID, 0, MV_FALSE); + } + + /* Close egiga 1 */ + if ((mppGroupType1 != MV_BOARD_RGMII) && (mppGroupType2 != MV_BOARD_RGMII)) + { + DB(printf("Warning: Giga1 is Powered Off\n")); + mvCtrlPwrMemSet(ETH_GIG_UNIT_ID, 1, MV_FALSE); + mvCtrlPwrClckSet(ETH_GIG_UNIT_ID, 1, MV_FALSE); + } + + /* Close TDM */ + if ((mppGroupType1 != MV_BOARD_TDM) && (mppGroupType2 != MV_BOARD_TDM)) + { + DB(printf("Warning: TDM is Powered Off\n")); + mvCtrlPwrClckSet(TDM_UNIT_ID, 0, MV_FALSE); + } + + /* Close AUDIO */ + if ((mppGroupType1 != MV_BOARD_AUDIO) && (mppGroupType2 != MV_BOARD_AUDIO)) + { + DB(printf("Warning: AUDIO is Powered Off\n")); + mvCtrlPwrMemSet(AUDIO_UNIT_ID, 0, MV_FALSE); + mvCtrlPwrClckSet(AUDIO_UNIT_ID, 0, MV_FALSE); + } + + /* Close TS */ + if ((mppGroupType1 != MV_BOARD_TS) && (mppGroupType2 != MV_BOARD_TS)) + { + DB(printf("Warning: TS is Powered Off\n")); + mvCtrlPwrClckSet(TS_UNIT_ID, 0, MV_FALSE); + } +#endif + return MV_OK; +} + +#endif /* defined(MV_INCLUDE_CLK_PWR_CNTRL) */ + +/******************************************************************************* +* mvUpdateNorFlashBaseAddrBank - +* +* DESCRIPTION: +* This function update the CFI driver base address bank with on board NOR +* devices base address. +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* None +* +*******************************************************************************/ +#ifdef CFG_FLASH_CFI_DRIVER +MV_VOID mvUpdateNorFlashBaseAddrBank(MV_VOID) +{ + + MV_U32 devBaseAddr; + MV_U32 devNum = 0; + int i; + + /* Update NOR flash base address bank for CFI flash init driver */ + for (i = 0 ; i < CFG_MAX_FLASH_BANKS_DETECT; i++) + { + devBaseAddr = mvBoardGetDeviceBaseAddr(i,BOARD_DEV_NOR_FLASH); + if (devBaseAddr != 0xFFFFFFFF) + { + flash_add_base_addr (devNum, devBaseAddr); + devNum++; + } + } + mv_board_num_flash_banks = devNum; + + /* Update SPI flash count for CFI flash init driver */ + /* Assumption only 1 SPI flash on board */ + for (i = 0 ; i < CFG_MAX_FLASH_BANKS_DETECT; i++) + { + devBaseAddr = mvBoardGetDeviceBaseAddr(i,BOARD_DEV_SPI_FLASH); + if (devBaseAddr != 0xFFFFFFFF) + mv_board_num_flash_banks += 1; + } + + if (mvCtrlModelGet() == MV_6082_DEV_ID) + /* Add internal MFlash to NOR devices */ + mv_board_num_flash_banks += 1; + +} +#endif /* CFG_FLASH_CFI_DRIVER */ + + +/******************************************************************************* +* mvHddPowerCtrl - +* +* DESCRIPTION: +* This function set HDD power on/off acording to env or wait for button push +* INPUT: +* None +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +#if defined(RD_88F6281) || defined(RD_88F6192) +static void mvHddPowerCtrl(void) +{ + + MV_32 hddPowerBit = mvBoarGpioPinNumGet(BOARD_GPP_HDD_POWER, 0); + MV_32 fanPowerBit = mvBoarGpioPinNumGet(BOARD_GPP_FAN_POWER, 0); + MV_32 hddHigh = 0; + MV_32 fanHigh = 0; + char* env; + + if (hddPowerBit > 31) + { + hddPowerBit = hddPowerBit % 32; + hddHigh = 1; + } + + if (fanPowerBit > 31) + { + fanPowerBit = fanPowerBit % 32; + fanHigh = 1; + } + + if ((RD_88F6281_ID == mvBoardIdGet()) || (RD_88F6192_ID == mvBoardIdGet())) + { + env = getenv("hddPowerCtrl"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("hddPowerCtrl","no"); + else + setenv("hddPowerCtrl","yes"); + + /* FAN power on */ + MV_REG_BIT_SET(GPP_DATA_OUT_REG(fanHigh),(1< 31) + { + stateButtonBit = stateButtonBit % 32; + buttonHigh = 1; + } + + /* Set state input indication pin as input */ + MV_REG_BIT_SET(GPP_DATA_OUT_EN_REG(buttonHigh),(1<> 4)) +#define NAND_ADDR_PORT (0x2 << (NFLASH_DEV_WIDTH >> 4)) + +/* NAND Flash Chip Capability */ +#ifdef MV_LARGE_PAGE +#define NUM_BLOCKS 2048 +#define PAGES_PER_BLOCK 64 +#define PAGE_SIZE 2048 /* Bytes */ +#define SPARE_SIZE 64 +#define CFG_NAND_PAGE_SIZE (2048) /* NAND chip page size */ +#define CFG_NAND_BLOCK_SIZE (128 << 10) /* NAND chip block size */ +#define CFG_NAND_PAGE_COUNT (64) /* NAND chip page count */ +#define CFG_NAND_BAD_BLOCK_POS (0) /* Location of bad block marker */ + +#define CFG_NAND_U_BOOT_OFFS CFG_MONITOR_BASE /* Offset to U-Boot image */ +#define CFG_NAND_U_BOOT_SIZE CFG_MONITOR_LEN /* Size of RAM U-Boot image */ +#define CFG_NAND_U_BOOT_DST CFG_MONITOR_IMAGE_DST /* Load NUB to this addr */ +#define CFG_NAND_U_BOOT_START CFG_NAND_U_BOOT_DST /* Start NUB from this addr */ + +#else /* ! LARGE PAGE NAND */ +/* NAND Flash Chip Capability */ +#define NUM_BLOCKS 2048 +#define PAGES_PER_BLOCK 32 +#define PAGE_SIZE 512 /* Bytes */ +#define SPARE_SIZE 16 +#define CFG_NAND_PAGE_SIZE (512) /* NAND chip page size */ +#define CFG_NAND_BLOCK_SIZE (16 << 10) /* NAND chip block size */ +#define CFG_NAND_PAGE_COUNT (32) /* NAND chip page count */ +#define CFG_NAND_BAD_BLOCK_POS (5) /* Location of bad block marker */ + +#define CFG_NAND_U_BOOT_OFFS CFG_MONITOR_BASE /* Offset to U-Boot image */ +#define CFG_NAND_U_BOOT_SIZE CFG_MONITOR_LEN /* Size of RAM U-Boot image */ +#define CFG_NAND_U_BOOT_DST CFG_MONITOR_IMAGE_DST /* Load NUB to this addr */ +#define CFG_NAND_U_BOOT_START CFG_NAND_U_BOOT_DST /* Start NUB from this addr */ + +#endif + +/* NAND Flash Command. This appears to be generic across all NAND flash chips */ +#define CMD_READ 0x00 /* Read */ +#define CMD_READ1 0x01 /* Read1 */ +#define CMD_READ2 0x50 /* Read2 */ +#define CMD_START_READ 0x30 /* Read command after write addr */ +#define CMD_READID 0x90 /* ReadID */ +#define CMD_READID2 0x91 /* Read extended ID */ +#define CMD_WRITE 0x80 /* Write phase 1 */ +#define CMD_WRITE2 0x10 /* Write phase 2 */ +#define CMD_ERASE 0x60 /* Erase phase 1 */ +#define CMD_ERASE2 0xd0 /* Erase phase 2 */ +#define CMD_STATUS 0x70 /* Status read */ +#define CMD_RESET 0xff /* Reset */ + +/* Status bit pattern */ +#define STATUS_READY 0x40 /* Ready */ +#define STATUS_ERROR 0x01 /* Error */ + + +#define NFLASH_DEV_WIDTH 8 +#ifdef MV_LARGE_PAGE +#define BOOTER_PAGE_NUM 2 +#define BOOTER_BASE 0x00020000 + PAGE_SIZE +#else +#define BOOTER_PAGE_NUM 5 +#define BOOTER_BASE 0x00020000 + (3 * PAGE_SIZE) +#endif /* MV_LARGE_PAGE */ +#define BOOTER_END (BOOTER_BASE + (BOOTER_PAGE_NUM * PAGE_SIZE)) + +#undef INTER_REGS_BASE +#define INTER_REGS_BASE 0xd0000000 + + +#if defined(MV_BOOTROM) +#if defined(MV_88F6082) +#define NAND_FLASH_BASE 0xD8000000 +#endif +#if defined(MV_88F5182) +#define NAND_FLASH_BASE 0xf0000000 +#endif +#else +#define NAND_FLASH_BASE 0xffff0000 +#endif /* defined(MV_BOOTROM) */ + +#if 0 +#define NBOOT_UART_CHAN 0 +#define NBOOT_BAUDRATE 115200 +#define NBOOT_TIMER_NUM 0 + + +/* CPU config register (0x20100) bit[15:8] value for CPU to DDR clock ratio */ +#define CPU_2_MBUSL_DDR_CLK 0x0000 /* clock ratio 1x2 */ +/* #define CPU_2_MBUSL_DDR_CLK 0x2100 *//* clock ratio 1x3 */ +/* #define CPU_2_MBUSL_DDR_CLK 0x2200 *//* clock ratio 1x4 */ + +/* Load General Purpose Register (GPR) with 32-bit constant value */ +#define GPR_LOAD(reg, val) \ + mov reg, $(val & 0xFF) ;\ + orr reg, reg, $(val & 0xFF00) ;\ + orr reg, reg, $(val & 0xFF0000) ;\ + orr reg, reg, $(val & 0xFF000000) + +/* Register Read/Write */ +#define MV_REG_READ_ASM(toReg, baseReg, regOffs) \ + ldr toReg, [baseReg, $(regOffs & 0xFFF)] + +#define MV_REG_WRITE_ASM(fromReg, baseReg, regOffs) \ + str fromReg, [baseReg, $(regOffs & 0xFFF)] + + +/* 32bit byte swap. For example 0x11223344 -> 0x44332211 */ +#define MV_BYTE_SWAP_32BIT(X) ((((X)&0xff)<<24) | \ + (((X)&0xff00)<<8) | \ + (((X)&0xff0000)>>8) | \ + (((X)&0xff000000)>>24)) +/* Endianess macros. */ +#if defined(MV_CPU_LE) + #define MV_32BIT_LE(X) (X) + #define MV_32BIT_BE(X) MV_BYTE_SWAP_32BIT(X) +#elif defined(MV_CPU_BE) + #define MV_32BIT_LE(X) MV_BYTE_SWAP_32BIT(X) + #define MV_32BIT_BE(X) (X) +#else + #error "CPU endianess isn't defined!\n" +#endif +#endif + +#endif /* __INCnBootstraph */ diff --git a/board/mv_feroceon/mv_dd/nBootstrap_LP.S b/board/mv_feroceon/mv_dd/nBootstrap_LP.S new file mode 100644 index 0000000..1769e95 --- /dev/null +++ b/board/mv_feroceon/mv_dd/nBootstrap_LP.S @@ -0,0 +1,335 @@ +#define MV_ASMLANGUAGE +#include "mvDramIfRegs.h" +#include "mvDramIfConfig.h" +#include "nBootstrap.h" + + +/* #define NAND_DEBUG */ +#if !defined(MV_BOOTROM) +.globl nbootStart +nbootStart: + /* + * set the cpu to SVC32 mode, I and F disabled. + */ + mov r1, #0xd3 + msr cpsr,r1 + + /* + * flush v4 I/D caches + */ + mcr p15, 0, r1, c7, c7, 0 /* invalidate v3/v4 cache */ + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r1, c1, c0, 0 + bic r1, r1, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r1, r1, #0x00000007 /* clear bits 2:0 (-CAM) */ + orr r1, r1, #0x00001000 /* set bit 12 (I) I-Cache */ + /* MUST BE PLACED AT END OF CACHE LINE!!!!!!!!!!!!!!! */ + mcr p15, 0, r1, c1, c0, 0 + + /* Add nop commands for cache flush operations */ + nop + nop + nop + nop + nop + /* here. MUST BE IN THE SAME CACHE LINE */ + + mov r0, #0 /* We use r0 as always '0' */ + +#ifdef NAND_CTRL_88F528x + + /* Load CPU controller base address 0xD0020000 */ + mov r2, #0xd0000000 + orr r2, r2, #0x20000 + + MV_REG_READ_ASM (r1, r2, 0x20120) + bic r1, r1, #MV_32BIT_LE(0x7F00) + orr r1, r1, #MV_32BIT_LE(0x8200) + bic r1, r1, #MV_32BIT_LE(0x007F) + orr r1, r1, #MV_32BIT_LE(0x001b) + MV_REG_WRITE_ASM(r1, r2, 0x20120) + + /* Set CPU to Mbus-L DDR Interface Tick Driver and Tick Sample */ + MV_REG_READ_ASM (r1, r2, 0x20100) + bic r1, r1, #MV_32BIT_LE(0xFF00) + orr r1, r1, #MV_32BIT_LE(CPU_2_MBUSL_DDR_CLK) + MV_REG_WRITE_ASM(r1, r2, 0x20100) + +#endif /* NAND_CTRL_88F528x */ + + /* lock I-Cache */ + mrc p15, 0, r8, c9, c0, 1 + orr r8, r8, #0xf + mcr p15, 0, r8, c9, c0, 1 + + /* Start load code into I-Cache */ + mov r2, #0x500 + mov r8, pc +.align 5 + bic r8, #0x1f + add r8, r8, #32 +load_loop: + mcr p15, 0, r8, c7, c13, 1 + add r8, r8, #32 /* 8 dwords * 4 bytes */ + sub r2, r2, #32 /* 8 dwords * 4 bytes */ + cmp r2, #0 /* check if we have read a full Page */ + bne load_loop + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0xf0ffffff + MV_REG_WRITE_ASM(r1, r2, 0x104) + mov r1, #0x1000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + + /* DRAM memory initialization */ + /* Load SDRAM controller base address 0xd0001000 */ + mov r2, #0xd0000000 + orr r2, r2, #0x1000 + + /* Write to SDRAM coniguration register */ +#ifndef MV_88W8660 + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_CONFIG_REG_DV)) +#else + GPR_LOAD(r1, MV_32BIT_LE((SDRAM_CONFIG_REG_DV & ~(0x40)))) +#endif /* MV_88W8660 */ + MV_REG_WRITE_ASM(r1, r2, SDRAM_CONFIG_REG) + + /* Write Dunit control low register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_DUNIT_CTRL_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_DUNIT_CTRL_REG) + + /* Write SDRAM address control register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_ADDR_CTRL_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_ADDR_CTRL_REG) + + /* Write SDRAM timing Low register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_TIMING_CTRL_LOW_REG_DVAL)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_TIMING_CTRL_LOW_REG) + + /* Write SDRAM timing High register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_TIMING_CTRL_HIGH_REG_DVAL)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_TIMING_CTRL_HIGH_REG) + + /* Write SDRAM mode register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_MODE_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_MODE_REG) + + /* Write SDRAM Extended mode register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_EXTENDED_MODE_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_EXTENDED_MODE_REG) + + /* Config DDR2 registers pad calibration */ + MV_REG_READ_ASM (r1, r2, SDRAM_CONFIG_REG) + tst r1, #SDRAM_DTYPE_DDR2 + beq ddr1PadCal + + /* Config DDR2 On Die Termination (ODT) registers */ + GPR_LOAD(r1, MV_32BIT_LE(DDR2_SDRAM_ODT_CTRL_LOW_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, DDR2_SDRAM_ODT_CTRL_LOW_REG) + + /* Write SDRAM DDR2 ODT control high register */ + GPR_LOAD(r1, MV_32BIT_LE(DDR2_SDRAM_ODT_CTRL_HIGH_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, DDR2_SDRAM_ODT_CTRL_HIGH_REG) + + /* Write SDRAM DDR2 Dunit ODT control register */ + GPR_LOAD(r1, MV_32BIT_LE(DDR2_DUNIT_ODT_CTRL_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, DDR2_DUNIT_ODT_CONTROL_REG) + + mov r3, #MV_32BIT_LE(DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV) + mov r4, #MV_32BIT_LE(DDR2_DATA_PAD_STRENGTH_TYPICAL_DV) + b next + +ddr1PadCal: + mov r3, #MV_32BIT_LE(DDR1_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV) + mov r4, #MV_32BIT_LE(DDR1_DATA_PAD_STRENGTH_TYPICAL_DV) + +next: + /* Implement Guideline (GL# MEM-3) Drive Strength Value */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + /* DDR SDRAM Address/Control Pads Calibration */ + MV_REG_READ_ASM (r1, r2, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + orr r5, r1, #MV_32BIT_LE(SDRAM_WR_EN) /* Make register writeable */ + + MV_REG_WRITE_ASM (r5, r2, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + orr r1, r3, r1 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r1, r2, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + + /* DDR SDRAM Data Pads Calibration */ + MV_REG_READ_ASM (r1, r2, SDRAM_DATA_PADS_CAL_REG) + + orr r5, r1, #MV_32BIT_LE(SDRAM_WR_EN) /* Make register writeable */ + + MV_REG_WRITE_ASM (r5, r2, SDRAM_DATA_PADS_CAL_REG) + + orr r1, r4, r1 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r1, r2, SDRAM_DATA_PADS_CAL_REG) + +#ifndef MV_88W8660 + /* Write Dunit FTDLL Configuration Register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_FTDLL_CONFIG_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_FTDLL_CONFIG_REG) +#endif /* MV_88W8660 */ + + /* DDR SDRAM Initialization Control Register. Init enable */ + mov r1, #MV_32BIT_LE(DSICR_INIT_EN) + MV_REG_WRITE_ASM (r1, r2, DDR_SDRAM_INIT_CTRL_REG) + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0x2000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + +ddrInitLoop: + MV_REG_READ_ASM (r1, r2, DDR_SDRAM_INIT_CTRL_REG) + cmp r1, #0 + bne ddrInitLoop + + /* Load back SDRAM controller base address 0xd0001000 */ + mov r2, #0xd0000000 + orr r2, r2, #0x1000 + + /* Open SDRAM bank 0 size register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_SIZE_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_SIZE_REG(0)) + + /* Close SDRAM bank 1,2,3 */ + MV_REG_WRITE_ASM(r0, r2, SDRAM_SIZE_REG(1)) + MV_REG_WRITE_ASM(r0, r2, SDRAM_SIZE_REG(2)) + MV_REG_WRITE_ASM(r0, r2, SDRAM_SIZE_REG(3)) + + /* Prepare the address where to find the nandBoot function pointer */ + mov lr, #BOOTER_BASE + +#ifdef DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0x2000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + + /* init */ + mov r2, #0x1 /* start with page 1 */ + mov r3, #BOOTER_BASE /* start of DRAM buffer */ + GPR_LOAD(r5, NAND_FLASH_BASE) + +cp_page_loop: + mov r0, #0 + mov r6, #CMD_READ + mov r7, #CMD_START_READ + mov r9, #CMD_RESET + mov r4, #PAGE_SIZE /* Byte counter */ + + +startRead: + /* issue reset command */ + strb r9, [r5, #NAND_CMD_PORT] + + mov r9, #0x1000000 +loop_delay1: + sub r9, r9, #1 + cmp r9, #0 + bne loop_delay1 + + /* issue read command */ + strb r6, [r5, #NAND_CMD_PORT] + + /* issue address */ + strb r0, [r5, #NAND_ADDR_PORT] + strb r0, [r5, #NAND_ADDR_PORT] + strb r2, [r5, #NAND_ADDR_PORT] /* page address */ + strb r0, [r5, #NAND_ADDR_PORT] + strb r0, [r5, #NAND_ADDR_PORT] + strb r7, [r5, #NAND_CMD_PORT] + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r6, #0xd0000000 + orr r6, r6, #0x10000 + mov r1, #0x3000000 + MV_REG_WRITE_ASM(r1, r6, 0x100) +#endif + /* Delay of at least 25uSec (NAND flash tR) */ + mov r9, #0x1000000 +loop_delay3: + sub r9, r9, #1 + cmp r9, #0 + bne loop_delay3 + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r6, #0xd0000000 + orr r6, r6, #0x10000 + mov r1, #0x4000000 + MV_REG_WRITE_ASM(r1, r6, 0x100) +#endif + + /* now perform reading */ + mov r0, r5 + +copy_loop1: + sub r4, r4, #16 /* 4 dwords * 4 bytes */ + ldmia r0!, {r6-r9} + stmia r3!, {r6-r9} + + cmp r4, #0 /* check if we have read a full Page */ + bne copy_loop1 + +nextPage: + add r2, r2, #1 /* increment page number */ + cmp r2, #BOOTER_PAGE_NUM + bne cp_page_loop + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0x5000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + + /* Set up the stack */ +stack_setup: + mov r0, #BOOTER_BASE + sub sp, r0, #12 /* leave 3 words for abort-stack */ + /* jump to new code */ + mov pc, lr + +.align 10 +/* This is known to be address (BOOTER_BASE + 2 * PAGE_SIZE) */ +_nandBootPtr: + .word nand_boot + +#else /* MV_BOOTROM */ + +.globl nbootStart +nbootStart: + /* Enable I-Cache */ + mrc p15, 0, r1, c1, c0, 0 + orr r1, r1, #0x00001000 /* set bit 12 (I) I-Cache */ + /* MUST BE PLACED AT END OF CACHE LINE!!!!!!!!!!!!!!! */ + mcr p15, 0, r1, c1, c0, 0 + + /* Set up the stack */ + mov r0, #BOOTER_BASE + sub sp, r0, #12 /* leave 3 words for abort-stack */ + + /* jump to new code */ + + ldr lr, =nandBoot + mov pc, lr +#endif /* !defined(MV_BOOTROM) */ diff --git a/board/mv_feroceon/mv_dd/platform.S b/board/mv_feroceon/mv_dd/platform.S new file mode 100644 index 0000000..47795c8 --- /dev/null +++ b/board/mv_feroceon/mv_dd/platform.S @@ -0,0 +1,153 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#define MV_ASMLANGUAGE +#include "mvOsAsm.h" +#include +#include +#include "mvBoardEnvSpec.h" +#include "mvCtrlEnvSpec.h" +#include "mvCpuIfConfig.h" +#include "pci/mvPciRegs.h" +#include "pex/mvPexRegs.h" +#include "ddr2/mvDramIfRegs.h" +#include "mvCtrlEnvAsm.h" +#include "mvAhbToMbusRegs.h" +#if defined(MV_INC_BOARD_SPI_FLASH) +#include "spi/mvSpiSpec.h" +#endif + +.globl lowlevel_init + +/************************************************/ +/* lowlevel_init * +/************************************************/ + +lowlevel_init: + +#if defined(MV78200) + mov r0, #0 + mrc p15, 1, r0, c15, c1, 0 + /* Check if we are CPU0 or CPU1 */ + and r0, r0, #0x4000 + cmp r0, #0x4000 + bne cpu0_reg_offset + b done_cpu1 +#endif + + /* change CPU0 reg base to 0xf1000000 */ +cpu0_reg_offset: + ldr r4, =CFG_MV_REGS + MV_DV_REG_WRITE_ASM(r4, r1, (AHB_TO_MBUS_WIN_INTEREG_REG(0))) + MV_REG_WRITE_ASM (r4, r1, (AHB_TO_MBUS_WIN_INTEREG_REG(1))) + +#if defined(MV_INC_BOARD_SPI_FLASH) + /* configure the Prescale of SPI clk Tclk = 200MHz */ + MV_REG_READ_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) + and r6, r6, #~MV_SPI_CLK_PRESCALE_MASK + orr r6, r6, #0x15 + MV_REG_WRITE_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) +#endif + + /* Set CPU_2_AHB_TICK_DRV and CCR_CPU_2_AHB_TICK_SMPL tiks */ + MV_REG_READ_ASM (r6, r1, CPU_RESET_SAMPLE_L_REG) + and r6, r6 , #MSAR_SYSCLK2CPU_MASK + mov r6, r6, LSR #MSAR_SYSCLK2CPU_OFFS + ldr r4, = ((1 << CCR_CPU_2_AHB_TICK_SMPL_OFFS) | (0 << CCR_CPU_2_AHB_TICK_DRV_OFFS)) + cmp r6, #0x2 + beq set_cpu_config + ldr r4, = ((1 << CCR_CPU_2_AHB_TICK_SMPL_OFFS) | (1 << CCR_CPU_2_AHB_TICK_DRV_OFFS)) + cmp r6, #0x4 + beq set_cpu_config + ldr r4, = ((1 << CCR_CPU_2_AHB_TICK_SMPL_OFFS) | (2 << CCR_CPU_2_AHB_TICK_DRV_OFFS)) + cmp r6, #0x6 + beq set_cpu_config + ldr r4, =0 +set_cpu_config: + /* Don't change R4 !!! use for Second CPU as well */ + MV_REG_READ_ASM (r6, r1, CPU_CONFIG_REG(MASTER_CPU)) + //orr r6, r6, r4 + MV_REG_WRITE_ASM (r6, r1, CPU_CONFIG_REG(MASTER_CPU)) + MV_REG_READ_ASM (r6, r1, CPU_CONFIG_REG(SLAVE_CPU)) + //orr r6, r6, r4 + MV_REG_WRITE_ASM (r6, r1, CPU_CONFIG_REG(SLAVE_CPU)) + + mov r2, lr + + /* init MPP */ + ldr r6, =DB_78XX0_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_78XX0_MPP8_15 + /* Clear SATA_ACT for load indication */ + and r6, r6 ,#0xffffff + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_78XX0_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10008) + /* init GPP , Out enable */ + MV_REG_READ_ASM(r6, r1, 0x10104); + bic r6, #(0x3 << 14) + MV_REG_WRITE_ASM(r6, r1, 0x10104); + ldr r6, =(0x1 << 15) + MV_REG_WRITE_ASM(r6, r1, 0x10120); + ldr r6, =(0x1 << 14) + MV_REG_WRITE_ASM(r6, r1, 0x10124); + +#if defined(RD_MV78XX0_AMC) + /* init MPP */ + ldr r6, =RD_AMC_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_AMC_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_AMC_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10008) + /* init GPP , Out enable */ +#endif + +#if defined(RD_MV78XX0_MASA) + /* init MPP */ + ldr r6, =RD_MASA_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_MASA_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_MASA_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10008) + /* init GPP , Out enable, blink */ + ldr r6, = (1 << RD_MASA_LED_GPP_PIN(0)); + MV_REG_WRITE_ASM(r6, r1, 0x10108); + MV_REG_WRITE_ASM(r6, r1, 0x10128); + MV_REG_WRITE_ASM(r6, r1, 0x10124); +#endif + +#if defined(MV_STATIC_DRAM_ON_BOARD) + + bl _mvDramIfStaticInit +#else + bl _mvDramIfBasicInit + /* SATA LEDs */ + ldr r6, =(0x1 << 14) + MV_REG_WRITE_ASM(r6, r1, 0x10120); + ldr r6, =(0x1 << 15) + MV_REG_WRITE_ASM(r6, r1, 0x10124); +#endif +done: + mov lr, r2 +done_cpu1: + mov pc, lr + diff --git a/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.c b/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.c new file mode 100644 index 0000000..fad52d7 --- /dev/null +++ b/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.c @@ -0,0 +1,500 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvCLAudioCodec.h" +#include "mvCLAudioCodecRegs.h" + +/******************************************************************************* +* mvCLAudioCodecInit - Initizlize the Cirrus Logic device +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* OUTPUT: +* None +* RETURN: +* MV_TRUE or MV_FALSE. +* +*******************************************************************************/ +MV_BOOL mvCLAudioCodecInit(MV_AUDIO_CODEC_DEV *pCodecDev) +{ + MV_U8 nData; + + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return MV_FALSE; + } + + /* Verify chip ID and revision */ + nData = mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_ID_REG); + if((MV_CL_AUDIO_CODEC_CHIP_ID != (nData >> 3)) || + (MV_CL_AUDIO_CODEC_REV_ID != (nData & 0x7))) + { + mvOsPrintf("%s: Error - Invalid Cirrus Logic chip/rev ID!\n",__FUNCTION__); + return MV_FALSE; + } + + /* Set the digital Interface format */ + nData = mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_IF_CTRL_REG); + nData &= ~(0x7<<3); + nData |= (pCodecDev->DACDigitalIFFormat << 3); + mvCLAudioCodecRegSet(pCodecDev,CL_AUDIO_CODEC_IF_CTRL_REG,nData); + + /* Set the ADC Mode */ + if(MV_LEFT_JUSTIFIED_MODE == pCodecDev->ADCMode) + mvCLAudioCodecRegBitsReset(pCodecDev,CL_AUDIO_CODEC_IF_CTRL_REG,BIT2); + else + mvCLAudioCodecRegBitsSet(pCodecDev,CL_AUDIO_CODEC_IF_CTRL_REG,BIT2); + + + return MV_TRUE; +} + +/******************************************************************************* +* mvCLAudioCodecOutputVolumeSet - Set the Cirrus Logic output volume of OUTA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nVolume : Volume level. +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecOutputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + mvCLAudioCodecRegSet(pCodecDev,CL_AUDIO_CODEC_VOL_OUTA_CTRL_REG,nVolume); +} + +/******************************************************************************* +* mvCLAudioCodecOutputVolumeGet - Get the Cirrus Logic output volume of OUTA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* OUTPUT: +* None +* RETURN: +* Volume level. +* +*******************************************************************************/ +MV_U8 mvCLAudioCodecOutputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return 0; + } + return mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_VOL_OUTA_CTRL_REG); +} + +/******************************************************************************* +* mvCLAudioCodecOutputVolumeMute - Mute the Cirrus Logic output volume of OUTA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* bMute : MV_TRUE for mute, MV_FALSE to un-mute +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecOutputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, MV_BOOL bMute) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + if(MV_TRUE == bMute) + mvCLAudioCodecRegBitsSet(pCodecDev,CL_AUDIO_CODEC_DAC_OUTPUT_CTRL_REG,BIT0); + else + mvCLAudioCodecRegBitsReset(pCodecDev,CL_AUDIO_CODEC_DAC_OUTPUT_CTRL_REG,BIT0); +} + +/******************************************************************************* +* mvCLAudioCodecInputVolumeSet - Set the Cirrus Logic input volume of INA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nVolume : Volume level. +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecInputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume) +{ + MV_U8 nData; + + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + nData = mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG); + nData &= ~0x1f; + nData |= (0x1f & nVolume); + mvCLAudioCodecRegSet(pCodecDev,CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG,nData); +} + +/******************************************************************************* +* mvCLAudioCodecInputVolumeGet - Get the Cirrus Logic input volume of INA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* OUTPUT: +* None +* RETURN: +* Volume level. +* +*******************************************************************************/ +MV_U8 mvCLAudioCodecInputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return 0; + } + return mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG) & 0x1f; +} + +/******************************************************************************* +* mvCLAudioCodecInputVolumeMute - Mute the Cirrus Logic input volume of INA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* bMute : MV_TRUE for mute, MV_FALSE to un-mute +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecInputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, + MV_BOOL bMute) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + if(MV_TRUE == bMute) + mvCLAudioCodecRegBitsSet(pCodecDev,CL_AUDIO_CODEC_ADC_INPUT_INV_MUTE_REG, + BIT0); + else + mvCLAudioCodecRegBitsReset(pCodecDev,CL_AUDIO_CODEC_ADC_INPUT_INV_MUTE_REG, + BIT0); +} + +/******************************************************************************* +* mvCLAudioCodecTrebleSet - Set the Cirrus Logic output treble of INA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nTreble : treble value. +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecTrebleSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nTreble) +{ + MV_U8 nData; + + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + nData = mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_TONE_CTRL_REG); + nData &= 0xF; + nData |= (nTreble<<4); + mvCLAudioCodecRegSet(pCodecDev,CL_AUDIO_CODEC_TONE_CTRL_REG,nData); +} + +/******************************************************************************* +* mvCLAudioCodecTrebleGet - Get the Cirrus Logic output treble of INA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* OUTPUT: +* None +* RETURN: +* treble value +* +*******************************************************************************/ +MV_U8 mvCLAudioCodecTrebleGet(MV_AUDIO_CODEC_DEV *pCodecDev) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return 0; + } + return mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_TONE_CTRL_REG)>>4; +} +/******************************************************************************* +* mvCLAudioCodecBassSet - Set the Cirrus Logic output bass of INA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nBass : Bass level. +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecBassSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nBass) +{ + MV_U8 nData; + + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + nData = mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_TONE_CTRL_REG); + nData &= 0xf0; + nData |= nBass; + mvCLAudioCodecRegSet(pCodecDev,CL_AUDIO_CODEC_TONE_CTRL_REG,nData); +} + +/******************************************************************************* +* mvCLAudioCodecBassGet - Get the Cirrus Logic output bass of INA +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* OUTPUT: +* None +* RETURN: +* Bass level +* +*******************************************************************************/ +MV_U8 mvCLAudioCodecBassGet(MV_AUDIO_CODEC_DEV *pCodecDev) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return 0; + } + return mvCLAudioCodecRegGet(pCodecDev,CL_AUDIO_CODEC_TONE_CTRL_REG)& 0xF; +} + +/******************************************************************************* +* mvCLAudioCodecRegSet - Set Cirrus Logic register value +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nOffset : register offset +* nData : register data +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecRegSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, + MV_U8 nData) +{ + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + pCodecDev->twsiSlave.offset = nOffset; + if(mvTwsiWrite(MV_BOARD_DIMM_I2C_CHANNEL,&pCodecDev->twsiSlave,&nData,1) != MV_OK) + { + mvOsPrintf("%s: Error while writing register!\n",__FUNCTION__); + return; + } +} + +/******************************************************************************* +* mvCLAudioCodecRegGet - Set Cirrus Logic register value +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nOffset : register offset +* OUTPUT: +* None +* RETURN: +* register data +* +*******************************************************************************/ +MV_U8 mvCLAudioCodecRegGet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset) +{ + MV_U8 nData; + + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return 0; + } + pCodecDev->twsiSlave.offset = nOffset; + if(mvTwsiRead(MV_BOARD_DIMM_I2C_CHANNEL,&pCodecDev->twsiSlave,&nData,1) != MV_OK) + { + mvOsPrintf("%s: Error while reading register!\n",__FUNCTION__); + return 0; + } + return nData; +} + +/******************************************************************************* +* mvCLAudioCodecRegBitsSet - Set Cirrus Logic register bits value +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nOffset : register offset +* nBits : register bits +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecRegBitsSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, + MV_U8 nBits) +{ + MV_U8 nData; + + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + + pCodecDev->twsiSlave.offset = nOffset; + nData = mvCLAudioCodecRegGet(pCodecDev,nOffset); + nData |= nBits; + mvCLAudioCodecRegSet(pCodecDev,nOffset,nData); + +} + +/******************************************************************************* +* mvCLAudioCodecRegGet - Reset Cirrus Logic register bits value +* +* DESCRIPTION: +* +* INPUT: +* pCodecDev: pointer to MV_AUDIO_CODEC_DEV structure. +* nOffset : register offset +* nBits : register bits +* OUTPUT: +* None +* RETURN: +* register data +* +*******************************************************************************/ +MV_VOID mvCLAudioCodecRegBitsReset(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nBits) +{ + MV_U8 nData; + + if(NULL == pCodecDev) + { + mvOsPrintf("%s: Error - pCodecDev = NULL!\n",__FUNCTION__); + return; + } + + pCodecDev->twsiSlave.offset = nOffset; + nData = mvCLAudioCodecRegGet(pCodecDev,nOffset); + nData &= ~nBits; + mvCLAudioCodecRegSet(pCodecDev,nOffset,nData); +} diff --git a/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.h b/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.h new file mode 100644 index 0000000..74b3c72 --- /dev/null +++ b/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodec.h @@ -0,0 +1,139 @@ + +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCLAudioCodech +#define __INCmvCLAudioCodech + +#include "mvTypes.h" +#include "twsi/mvTwsi.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "boardEnv/mvBoardEnvSpec.h" + +#define MV_CL_AUDIO_CODEC_CHIP_ID 0x1B +#define MV_CL_AUDIO_CODEC_REV_ID 0x1 + +/* Selects the digital interface format used for the data in on SDIN. */ +typedef enum _mvDACDigitalIFFormat +{ + MV_L_JUSTIFIED_UP_TO_24_BIT, + MV_I2S_UP_TO_24_BIT, + MV_R_JUSTIFIED_UP_TO_24_BIT, + MV_R_JUSTIFIED_20_BIT, + MV_R_JUSTIFIED_18_BIT, + MV_R_JUSTIFIED_16_BIT + +} MV_DAC_DIGITAL_IF_FORMAT; + +/* Selects either the I2S or Left-Justified digital interface format for the + data on SDOUT. */ +typedef enum _mvADCMode +{ + MV_LEFT_JUSTIFIED_MODE, + MV_I2S_MODE +} MV_ADC_MODE; + + +/* Cirrus Logic device structure */ +typedef struct _mvAudioCodecDev +{ + /* MUST be set by user!!! */ + MV_TWSI_SLAVE twsiSlave; + MV_DAC_DIGITAL_IF_FORMAT DACDigitalIFFormat; + MV_ADC_MODE ADCMode; + + /* Set by driver */ + MV_U8 nChipID; + MV_U8 nRevID; + +} MV_AUDIO_CODEC_DEV; + +/* Initialize the Cirrus Logic device */ +MV_BOOL mvCLAudioCodecInit(MV_AUDIO_CODEC_DEV *pCodecDev); + +/* Function to control output volume (playback) */ +MV_VOID mvCLAudioCodecOutputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume); +MV_U8 mvCLAudioCodecOutputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev); +MV_VOID mvCLAudioCodecOutputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, MV_BOOL bMute); + +/* Function to control input volume (record) */ +MV_VOID mvCLAudioCodecInputVolumeSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nVolume); +MV_U8 mvCLAudioCodecInputVolumeGet(MV_AUDIO_CODEC_DEV *pCodecDev); +MV_VOID mvCLAudioCodecInputVolumeMute(MV_AUDIO_CODEC_DEV *pCodecDev, MV_BOOL bMute); + +/* Function to control output tone */ +MV_VOID mvCLAudioCodecTrebleSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nTreble); +MV_U8 mvCLAudioCodecTrebleGet(MV_AUDIO_CODEC_DEV *pCodecDev); +MV_VOID mvCLAudioCodecBassSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_8 nBass); +MV_U8 mvCLAudioCodecBassGet(MV_AUDIO_CODEC_DEV *pCodecDev); + +/* Function to access the Cirrus Logic CODEC registers */ +MV_VOID mvCLAudioCodecRegSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nData); +MV_U8 mvCLAudioCodecRegGet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset); +MV_VOID mvCLAudioCodecRegBitsSet(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nBits); +MV_VOID mvCLAudioCodecRegBitsReset(MV_AUDIO_CODEC_DEV *pCodecDev, MV_U8 nOffset, MV_U8 nBits); + + +#endif /* __INCmvCLAudioCodech */ + diff --git a/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodecRegs.h b/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodecRegs.h new file mode 100644 index 0000000..aef84a7 --- /dev/null +++ b/board/mv_feroceon/mv_hal/audio/dac/mvCLAudioCodecRegs.h @@ -0,0 +1,83 @@ + +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCLAudioCodecRegsh +#define __INCmvCLAudioCodecRegsh + +#include "mvTypes.h" +//#include "mvRegs.h" + +#define CL_AUDIO_CODEC_ID_REG 0x1 +#define CL_AUDIO_CODEC_IF_CTRL_REG 0x4 +#define CL_AUDIO_CODEC_ADC_INPUT_INV_MUTE_REG 0x7 +#define CL_AUDIO_CODEC_DAC_OUTPUT_CTRL_REG 0x8 +#define CL_AUDIO_CODEC_DAC_CTRL_REG 0x9 +#define CL_AUDIO_CODEC_PGAA_VOL_CTRL_REG 0xa +#define CL_AUDIO_CODEC_TONE_CTRL_REG 0x15 +#define CL_AUDIO_CODEC_VOL_OUTA_CTRL_REG 0x16 + + +#endif /* __INCmvCLAudioCodecRegsh */ + diff --git a/board/mv_feroceon/mv_hal/audio/mvAudio.c b/board/mv_feroceon/mv_hal/audio/mvAudio.c new file mode 100644 index 0000000..e9077c5 --- /dev/null +++ b/board/mv_feroceon/mv_hal/audio/mvAudio.c @@ -0,0 +1,1057 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#include "mvAudio.h" +#include "ctrlEnv/sys/mvSysAudio.h" + +static MV_U32 audioBurstBytesNumGet(MV_AUDIO_BURST_SIZE burst); + +/******************************************************************************* +* mvAudioHalInit - Initialize the Audio subsystem +* +* DESCRIPTION: +* +* INPUT: +* None +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvAudioHalInit(void) +{ + int timeout; + + MV_REG_BIT_RESET(AUDIO_REG_BASE + 0x1200,0x333FF8); + MV_REG_BIT_SET(AUDIO_REG_BASE + 0x1200,0x111D18); + + /*MV_REG_BIT_RESET(0x10074,0xC018000); + MV_REG_BIT_SET(0x10074,0x4008000);*/ + + timeout = 10000000; + while(timeout--); + + MV_REG_BIT_RESET(AUDIO_REG_BASE + 0x1200,0x333FF8); + MV_REG_BIT_SET(AUDIO_REG_BASE + 0x1200,0x111D18); + + /*MV_REG_BIT_RESET(0x10074,0xC018000); + MV_REG_BIT_SET(0x10074,0x4008000);*/ + +} + + + +/* Clocks Control and Status related*/ +/******************************************************************************* +* mvAudioDCOCtrlSet - Set DCO control register +* +* DESCRIPTION: +* +* INPUT: +* dcoCtrl: pointer to MV_AUDIO_FREQ_DATA structure +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ + +MV_STATUS mvAudioDCOCtrlSet(MV_AUDIO_FREQ_DATA *dcoCtrl) +{ + MV_U32 reg; + /* Check parameters*/ + if (dcoCtrl->baseFreq > AUDIO_FREQ_96KH) + { + mvOsPrintf("mvAudioDCOCtrlSet: dcoCtrl->baseFreq value (0x%x) invalid\n", + dcoCtrl->baseFreq); + return MV_BAD_PARAM; + + } + if ((dcoCtrl->offset > 0xFD0)||(dcoCtrl->offset < 0x20)) + { + mvOsPrintf("mvAudioDCOCtrlSet: dcoCtrl->offset value (0x%x) invalid\n", + dcoCtrl->baseFreq); + return MV_BAD_PARAM; + } + reg = MV_REG_READ(MV_AUDIO_DCO_CTRL_REG); + + reg &= ~(ADCR_DCO_CTRL_FS_MASK|ADCR_DCO_CTRL_OFFSET_MASK); + reg |= ((dcoCtrl->baseFreq << ADCR_DCO_CTRL_FS_OFFS) | + (dcoCtrl->offset << ADCR_DCO_CTRL_OFFSET_OFFS)); + MV_REG_WRITE(MV_AUDIO_DCO_CTRL_REG, reg); + + return MV_OK; +} + +/******************************************************************************* +* mvAudioDCOCtrlGet - Set DCO control register +* +* DESCRIPTION: +* +* INPUT: +* dcoCtrl: pointer to MV_AUDIO_FREQ_DATA structure +* OUTPUT: +* dcoCtrl: pointer to MV_AUDIO_FREQ_DATA structure +* RETURN: +* None +* +*******************************************************************************/ + +MV_VOID mvAudioDCOCtrlGet(MV_AUDIO_FREQ_DATA *dcoCtrl) +{ + MV_U32 reg = MV_REG_READ(MV_AUDIO_DCO_CTRL_REG); + + dcoCtrl->baseFreq = (reg & ADCR_DCO_CTRL_FS_MASK) >> ADCR_DCO_CTRL_FS_OFFS ; + dcoCtrl->offset = (reg & ADCR_DCO_CTRL_OFFSET_MASK) >> ADCR_DCO_CTRL_OFFSET_OFFS ; +} +/******************************************************************************* +* mvAudioSpcrCtrlGet - Set SPCR control register +* +* DESCRIPTION: +* +* INPUT: +* spcrCtrl: pointer to MV_AUDIO_FREQ_DATA structure +* OUTPUT: +* spcrCtrl: pointer to MV_AUDIO_FREQ_DATA structure +* RETURN: +* None +* +*******************************************************************************/ + +MV_VOID mvAudioSpcrCtrlGet(MV_AUDIO_FREQ_DATA *spcrCtrl) +{ + MV_U32 reg = MV_REG_READ(MV_AUDIO_SPCR_DCO_STATUS_REG); + + spcrCtrl->baseFreq = (reg & ASDSR_SPCR_CTRLFS_MASK) >> ASDSR_SPCR_CTRLFS_OFFS ; + spcrCtrl->offset = (reg & ASDSR_SPCR_CTRLOFFSET_MASK) >> ASDSR_SPCR_CTRLOFFSET_OFFS; +} + + +/* Audio PlayBack related*/ +/******************************************************************************* +* mvAudioPlaybackControlSet - Set Playback general parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_AUDIO_PLAYBACK_CTRL structure +* OUTPUT: +* None +* RETURN: +* MV_OK on success , MV_FAIL on fail +* +*******************************************************************************/ +MV_STATUS mvAudioPlaybackControlSet(MV_AUDIO_PLAYBACK_CTRL *ctrl) +{ + MV_AUDIO_DEC_WIN audioWin; + MV_CPU_DEC_WIN cpuWin; + MV_ADDR_WIN bufAddrWin; + MV_U32 target; + MV_U32 reg; + + if (ctrl->monoMode >= AUDIO_PLAY_OTHER_MONO) + { + mvOsPrintf("mvAudioPlaybackControlSet: Error ,illegal monoMode %x\n", + ctrl->monoMode ); + + return MV_FAIL; + + } + + if ((ctrl->burst != AUDIO_32BYTE_BURST) && + (ctrl->burst != AUDIO_128BYTE_BURST)) + { + mvOsPrintf("mvAudioPlaybackControlSet: Error ,illegal burst %x\n", + ctrl->burst ); + + return MV_FAIL; + + } + + if (ctrl->bufferPhyBase & (MV_AUDIO_BUFFER_MIN_ALIGN - 1)) + { + mvOsPrintf("mvAudioPlaybackControlSet: Error ,bufferPhyBase is not"\ + "\n aligned to 0x%x bytes\n",MV_AUDIO_BUFFER_MIN_ALIGN ); + + return MV_FAIL; + } + + if ((ctrl->bufferSize <= audioBurstBytesNumGet(ctrl->burst))|| + (ctrl->bufferSize & (audioBurstBytesNumGet(ctrl->burst) - 1))|| + (ctrl->bufferSize > AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX)) + ) + { + mvOsPrintf("mvAudioPlaybackControlSet: Error, bufferSize smaller"\ + "\nthan or not multiple of 0x%x bytes or larger than"\ + "\n 0x%x", + audioBurstBytesNumGet(ctrl->burst), + AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX)); + + return MV_FAIL; + } + + + reg = MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG); + reg &= ~(APCR_PLAY_BURST_SIZE_MASK|APCR_LOOPBACK_MASK|APCR_PLAY_MONO_MASK | + APCR_PLAY_SAMPLE_SIZE_MASK); + reg |= ctrl->burst << APCR_PLAY_BURST_SIZE_OFFS; + reg |= ctrl->loopBack << APCR_LOOPBACK_OFFS; + reg |= ctrl->monoMode << APCR_PLAY_MONO_OFFS; + reg |= ctrl->sampleSize << APCR_PLAY_SAMPLE_SIZE_OFFS; + MV_REG_WRITE(MV_AUDIO_PLAYBACK_CTRL_REG, reg); + + /* Get the details of the Playback address window*/ + if( mvAudioWinGet( MV_AUDIO_PLAYBACK_WIN_NUM, &audioWin ) != MV_OK ) + { + mvOsPrintf("mvAudioPlaybackControlSet: Error calling mvAudioWinGet on win %d\n", + MV_AUDIO_PLAYBACK_WIN_NUM); + return MV_FAIL; + } + + bufAddrWin.baseHigh = 0; + bufAddrWin.baseLow = ctrl->bufferPhyBase; + bufAddrWin.size = ctrl->bufferSize; + + /* If Playback window is not enabled or buffer address is not within window boundries + then try to set a new value to the Playback window by + Geting the target of where the buffer exist, if the buffer is within the window + of the new target then set the Playback window to that target + else return Fail + */ + + if((audioWin.enable != MV_TRUE) || + (MV_TRUE != ctrlWinWithinWinTest(&bufAddrWin, &audioWin.addrWin))) + { + /* Get the target of the buffer that user require*/ + target = mvCpuIfTargetOfBaseAddressGet(ctrl->bufferPhyBase); + if (MAX_TARGETS == target) + { + mvOsPrintf("mvCpuIfTargetOfBaseAddressGet: Error calling mvAudioWinGet on address 0x%x\n", + ctrl->bufferPhyBase); + return MV_FAIL; + } + + /* Get the window details of this target*/ + if (MV_OK != mvCpuIfTargetWinGet(target, &cpuWin)) + { + mvOsPrintf("mvAudioPlaybackControlSet: Error calling mvCpuIfTargetWinGet on target %d\n", + target); + return MV_FAIL; + + } + + /* if the address window of the target is enabled and te user buffer is within + that target address window then set the palyback\recording window to the + target window + + */ + if((cpuWin.enable == MV_TRUE) && + (MV_TRUE == ctrlWinWithinWinTest(&bufAddrWin, &cpuWin.addrWin))) + { + audioWin.addrWin.baseHigh = cpuWin.addrWin.baseHigh; + audioWin.addrWin.baseLow = cpuWin.addrWin.baseLow; + audioWin.addrWin.size = cpuWin.addrWin.size; + audioWin.enable = cpuWin.enable; + audioWin.target = target; + + + if( mvAudioWinSet( MV_AUDIO_PLAYBACK_WIN_NUM, &audioWin ) != MV_OK ) + { + mvOsPrintf("mvAudioPlaybackControlSet: Error calling mvAudioWinGet on win %d\n", + MV_AUDIO_PLAYBACK_WIN_NUM); + return MV_FAIL; + } + + } + else + { + mvOsPrintf("mvAudioPlaybackControlSet: Error buffer is not within a valid target\n"); + return MV_FAIL; + + } + } + + /* Set the interrupt byte count. */ + reg = ctrl->intByteCount & APBCI_BYTE_COUNT_MASK; + MV_REG_WRITE(MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG, reg); + + + MV_REG_WRITE(MV_AUDIO_PLAYBACK_BUFF_START_REG, ctrl->bufferPhyBase); + MV_REG_WRITE(MV_AUDIO_PLAYBACK_BUFF_SIZE_REG, + AUDIO_SIZE_TO_REG(ctrl->bufferSize)); + + return MV_OK; +} + +/******************************************************************************* +* mvAudioPlaybackControlGet - Get Playback general parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_AUDIO_PLAYBACK_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_AUDIO_PLAYBACK_CTRL structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvAudioPlaybackControlGet(MV_AUDIO_PLAYBACK_CTRL *ctrl) +{ + + MV_U32 reg = MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG); + + ctrl->burst = (reg & APCR_PLAY_BURST_SIZE_MASK) >> APCR_PLAY_BURST_SIZE_OFFS; + ctrl->loopBack = (reg & APCR_LOOPBACK_MASK) >> APCR_LOOPBACK_OFFS; + ctrl->monoMode = (reg & APCR_PLAY_MONO_MASK) >> APCR_PLAY_MONO_OFFS; + + ctrl->bufferPhyBase = MV_REG_READ(MV_AUDIO_PLAYBACK_BUFF_START_REG); + reg = MV_REG_READ(MV_AUDIO_PLAYBACK_BUFF_SIZE_REG); + ctrl->bufferSize = AUDIO_REG_TO_SIZE(reg); + + ctrl->intByteCount = MV_REG_READ(MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG); + +} +/******************************************************************************* +* mvAudioPlaybackStatusGet - Get Playback status parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_AUDIO_PLAYBACK_STATUS structure +* OUTPUT: +* ctrl: pointer to MV_AUDIO_PLAYBACK_STATUS structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvAudioPlaybackStatusGet(MV_AUDIO_PLAYBACK_STATUS *status) +{ + + status->muteI2S = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG)&APCR_PLAY_I2S_MUTE_MASK)? + MV_TRUE:MV_FALSE); + status->enableI2S = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG)&APCR_PLAY_I2S_ENABLE_MASK)? + MV_TRUE:MV_FALSE); + status->muteSPDIF = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG)&APCR_PLAY_SPDIF_MUTE_MASK)? + MV_TRUE:MV_FALSE); + status->enableSPDIF = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG)&APCR_PLAY_SPDIF_ENABLE_MASK)? + MV_TRUE:MV_FALSE); + status->pause = ((MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG)&APCR_PLAY_PAUSE_MASK)? + MV_TRUE:MV_FALSE); + +} + +/******************************************************************************* +* mvSPDIFPlaybackCtrlGet - Set SPDIF Playback control parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure +* RETURN: +* None +* +*******************************************************************************/ +/* Audio SPDIF PlayBack related*/ +MV_VOID mvSPDIFPlaybackCtrlSet(MV_SPDIF_PLAYBACK_CTRL *ctrl) +{ + if (ctrl->blockStartInternally) + { + MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_BLOCK_START_MASK); + } + else + { + MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_BLOCK_START_MASK); + } + + if (ctrl->validityFromMemory) + { + MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK); + } + else + { + MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK); + } + + if (ctrl->userBitsFromMemory) + { + MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_MEM_USR_EN_MASK); + } + else + { + MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_MEM_USR_EN_MASK); + } + + if (ctrl->underrunData) + { + MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_UNDERRUN_DATA_MASK); + } + else + { + MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_UNDERRUN_DATA_MASK); + } + + if (ctrl->validity) + { + MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_REG_VALIDITY_MASK); + } + else + { + MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_REG_VALIDITY_MASK); + } + + if (ctrl->nonPcm) + { + MV_REG_BIT_SET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_NONPCM_MASK); + } + else + { + MV_REG_BIT_RESET(MV_AUDIO_SPDIF_PLAY_CTRL_REG,ASPCR_SPDIF_PB_NONPCM_MASK); + } +} +/******************************************************************************* +* mvSPDIFPlaybackCtrlGet - Get SPDIF Playback control parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_SPDIF_PLAYBACK_CTRL structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvSPDIFPlaybackCtrlGet(MV_SPDIF_PLAYBACK_CTRL *ctrl) +{ + ctrl->blockStartInternally = + ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG)&ASPCR_SPDIF_BLOCK_START_MASK)? + MV_TRUE:MV_FALSE); + ctrl->nonPcm = + ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG)&ASPCR_SPDIF_PB_NONPCM_MASK)? + MV_TRUE:MV_FALSE); + ctrl->underrunData = + ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG)&ASPCR_SPDIF_UNDERRUN_DATA_MASK)? + MV_TRUE:MV_FALSE); + ctrl->userBitsFromMemory = + ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG)&ASPCR_SPDIF_PB_MEM_USR_EN_MASK)? + MV_TRUE:MV_FALSE); + ctrl->validity = + ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG)&ASPCR_SPDIF_PB_REG_VALIDITY_MASK)? + MV_TRUE:MV_FALSE); + ctrl->validityFromMemory = + ((MV_REG_READ(MV_AUDIO_SPDIF_PLAY_CTRL_REG)&ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK)? + MV_TRUE:MV_FALSE); + + + +} + +/******************************************************************************* +* mvI2SPlaybackCtrlSet - Set I2S Playback control parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure +* RETURN: +* MV_OK on success, and MV_FAIL on fail. +* +*******************************************************************************/ + +/* Audio I2S PlayBack related*/ +MV_STATUS mvI2SPlaybackCtrlSet(MV_I2S_PLAYBACK_CTRL *ctrl) +{ + MV_U32 reg = MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG) & + ~(AIPCR_I2S_PB_JUSTF_MASK|AIPCR_I2S_PB_SAMPLE_SIZE_MASK); + + if (ctrl->sampleSize > SAMPLE_16BIT) + { + mvOsPrintf("mvI2SPlaybackCtrlSet: illigal sample size\n"); + return MV_FAIL; + } + + reg |= ctrl->sampleSize << AIPCR_I2S_PB_SAMPLE_SIZE_OFFS; + + if (ctrl->sendLastFrame) + { + MV_REG_BIT_SET(MV_AUDIO_I2S_PLAY_CTRL_REG,AIPCR_I2S_SEND_LAST_FRM_MASK); + } + else + { + MV_REG_BIT_RESET(MV_AUDIO_I2S_PLAY_CTRL_REG,AIPCR_I2S_SEND_LAST_FRM_MASK); + } + + + switch (ctrl->justification) + { + case I2S_JUSTIFIED: + case LEFT_JUSTIFIED: + case RIGHT_JUSTIFIED: + reg |= ctrl->justification << AIPCR_I2S_PB_JUSTF_OFFS; + break; + default: + mvOsPrintf("mvI2SPlaybackCtrlSet: illigal Justification value\n"); + return MV_FAIL; + + } + + MV_REG_WRITE(MV_AUDIO_I2S_PLAY_CTRL_REG, reg); + return MV_OK; + +} + +/******************************************************************************* +* mvI2SPlaybackCtrlGet - Get I2S Playback control parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_I2S_PLAYBACK_CTRL structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvI2SPlaybackCtrlGet(MV_I2S_PLAYBACK_CTRL *ctrl) +{ + ctrl->sendLastFrame = + ((MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG)&AIPCR_I2S_SEND_LAST_FRM_MASK)? + MV_TRUE:MV_FALSE); + + ctrl->justification = + ((MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG)&AIPCR_I2S_PB_JUSTF_MASK) >> + AIPCR_I2S_PB_JUSTF_OFFS); + + ctrl->sampleSize = + ((MV_REG_READ(MV_AUDIO_I2S_PLAY_CTRL_REG)&AIPCR_I2S_PB_SAMPLE_SIZE_MASK ) >> + AIPCR_I2S_PB_SAMPLE_SIZE_OFFS); + +} +/******************************************************************************* +* mvAudioRecordControlGet - Get Recording control parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_AUDIO_RECORD_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_AUDIO_RECORD_CTRL structure +* RETURN: +* MV_OK on success , MV_FAIL on fail. +* +*******************************************************************************/ +/* Audio Recording*/ +MV_STATUS mvAudioRecordControlSet(MV_AUDIO_RECORD_CTRL *ctrl) +{ + MV_AUDIO_DEC_WIN audioWin; + MV_CPU_DEC_WIN cpuWin; + MV_ADDR_WIN bufAddrWin; + MV_U32 target; + MV_U32 reg; + + if (ctrl->monoChannel > AUDIO_REC_RIGHT_MONO) + { + mvOsPrintf("mvAudioRecordControlSet: Error ,illegal monoChannel %x\n", + ctrl->monoChannel ); + + return MV_FAIL; + } + + if ((ctrl->burst != AUDIO_32BYTE_BURST) && + (ctrl->burst != AUDIO_128BYTE_BURST)) + { + mvOsPrintf("mvAudioRecordControlSet: Error ,illegal burst %x\n", + ctrl->burst ); + + return MV_FAIL; + + } + + if (ctrl->bufferPhyBase & (MV_AUDIO_BUFFER_MIN_ALIGN - 1)) + { + mvOsPrintf("mvAudioRecordControlSet: Error ,bufferPhyBase is not"\ + "\n aligned to 0x%x bytes\n",MV_AUDIO_BUFFER_MIN_ALIGN ); + + return MV_FAIL; + } + + if ((ctrl->bufferSize <= audioBurstBytesNumGet(ctrl->burst))|| + (ctrl->bufferSize & (audioBurstBytesNumGet(ctrl->burst) - 1))|| + (ctrl->bufferSize > AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX)) + ) + { + mvOsPrintf("mvAudioRecordControlSet: Error, bufferSize smaller"\ + "\nthan or not multiple of 0x%x bytes or larger than"\ + "\n 0x%x", + audioBurstBytesNumGet(ctrl->burst), + AUDIO_REG_TO_SIZE(APBBCR_SIZE_MAX)); + + return MV_FAIL; + } + + + reg = MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG); + reg &= ~(ARCR_RECORD_BURST_SIZE_MASK|ARCR_RECORDED_MONO_CHNL_MASK| + ARCR_RECORD_SAMPLE_SIZE_MASK); + switch (ctrl->sampleSize) + { + case SAMPLE_16BIT: + case SAMPLE_16BIT_NON_COMPACT: + case SAMPLE_20BIT: + case SAMPLE_24BIT: + case SAMPLE_32BIT: + reg |= ctrl->sampleSize << ARCR_RECORD_SAMPLE_SIZE_OFFS; + break; + default: + mvOsPrintf("mvAudioRecordControlSet: Error ,illegal sampleSize %x\n", + ctrl->sampleSize ); + + return MV_FAIL; + } + + reg |= ctrl->burst << ARCR_RECORD_BURST_SIZE_OFFS; + reg |= ctrl->monoChannel << ARCR_RECORDED_MONO_CHNL_OFFS; + MV_REG_WRITE(MV_AUDIO_RECORD_CTRL_REG, reg); + + if (ctrl->mono) + { + MV_REG_BIT_SET (MV_AUDIO_RECORD_CTRL_REG, + ARCR_RECORD_MONO_MASK); + } + else + { + MV_REG_BIT_RESET (MV_AUDIO_RECORD_CTRL_REG, + ARCR_RECORD_MONO_MASK); + } + + /* Get the details of the Record address window*/ + if( mvAudioWinGet( MV_AUDIO_RECORD_WIN_NUM, &audioWin ) != MV_OK ) + { + mvOsPrintf("mvAudioRecordControlSet: Error calling mvAudioWinGet on win %d\n", + MV_AUDIO_RECORD_WIN_NUM); + return MV_FAIL; + } + + bufAddrWin.baseHigh = 0; + bufAddrWin.baseLow = ctrl->bufferPhyBase; + bufAddrWin.size = ctrl->bufferSize; + + /* If Record window is not enabled or buffer address is not within window boundries + then try to set a new value to the Record window by + Geting the target of where the buffer exist, if the buffer is within the window + of the new target then set the Record window to that target + else return Fail + */ + + if((audioWin.enable != MV_TRUE) || + (MV_TRUE != ctrlWinWithinWinTest(&bufAddrWin, &audioWin.addrWin))) + { + /* Get the target of the buffer that user require*/ + target = mvCpuIfTargetOfBaseAddressGet(ctrl->bufferPhyBase); + if (MAX_TARGETS == target) + { + mvOsPrintf("mvAudioRecordControlSet: Error calling mvAudioWinGet on address 0x%x\n", + ctrl->bufferPhyBase); + return MV_FAIL; + } + + /* Get the window details of this target*/ + if (MV_OK != mvCpuIfTargetWinGet(target, &cpuWin)) + { + mvOsPrintf("mvAudioRecordControlSet: Error calling mvCpuIfTargetWinGet on target %d\n", + target); + return MV_FAIL; + + } + + /* if the address window of the target is enabled and te user buffer is within + that target address window then set the palyback\recording window to the + target window + + */ + if((cpuWin.enable == MV_TRUE) && + (MV_TRUE == ctrlWinWithinWinTest(&bufAddrWin, &cpuWin.addrWin))) + { + + audioWin.addrWin.baseHigh = cpuWin.addrWin.baseHigh; + audioWin.addrWin.baseLow = cpuWin.addrWin.baseLow; + audioWin.addrWin.size = cpuWin.addrWin.size; + audioWin.enable = cpuWin.enable; + audioWin.target = target; + + if( mvAudioWinSet( MV_AUDIO_RECORD_WIN_NUM, &audioWin ) != MV_OK ) + { + mvOsPrintf("mvAudioRecordControlSet: Error calling mvAudioWinGet on win %d\n", + MV_AUDIO_RECORD_WIN_NUM); + return MV_FAIL; + } + + } + else + { + mvOsPrintf("mvAudioRecordControlSet: Error buffer is not within a valid target\n"); + return MV_FAIL; + + } + } + + /* Set the interrupt byte count. */ + reg = ctrl->intByteCount & ARBCI_BYTE_COUNT_MASK; + MV_REG_WRITE(MV_AUDIO_RECORD_BYTE_CNTR_INT_REG, reg); + + + MV_REG_WRITE(MV_AUDIO_RECORD_START_ADDR_REG, ctrl->bufferPhyBase); + MV_REG_WRITE(MV_AUDIO_RECORD_BUFF_SIZE_REG, + AUDIO_SIZE_TO_REG(ctrl->bufferSize)); + + return MV_OK; +} + +/******************************************************************************* +* mvAudioRecordControlGet - Get Recording control parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_AUDIO_RECORD_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_AUDIO_RECORD_CTRL structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvAudioRecordControlGet(MV_AUDIO_RECORD_CTRL *ctrl) +{ + MV_U32 reg; + + ctrl->mono = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORD_MONO_MASK)? + MV_TRUE:MV_FALSE); + + ctrl->burst = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORD_BURST_SIZE_MASK) >> + ARCR_RECORD_BURST_SIZE_OFFS); + + ctrl->monoChannel = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORDED_MONO_CHNL_MASK) >> + ARCR_RECORDED_MONO_CHNL_OFFS); + + ctrl->sampleSize = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORD_SAMPLE_SIZE_MASK) >> + ARCR_RECORD_SAMPLE_SIZE_OFFS); + + ctrl->bufferPhyBase = MV_REG_READ(MV_AUDIO_RECORD_START_ADDR_REG); + reg = MV_REG_READ(MV_AUDIO_RECORD_BUFF_SIZE_REG); + ctrl->bufferSize = AUDIO_REG_TO_SIZE(reg); + + ctrl->intByteCount = MV_REG_READ(MV_AUDIO_RECORD_BYTE_CNTR_INT_REG); + +} + +/******************************************************************************* +* mvAudioRecordControlGet - Get Recording status parameters +* +* DESCRIPTION: +* +* INPUT: +* status: pointer to MV_AUDIO_RECORD_STATUS structure +* OUTPUT: +* status: pointer to MV_AUDIO_RECORD_STATUS structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvAudioRecordStatusGet(MV_AUDIO_RECORD_STATUS *status) +{ + status->I2SEnable = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORD_I2S_EN_MASK)? + MV_TRUE:MV_FALSE); + + status->mute = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORD_MUTE_MASK)? + MV_TRUE:MV_FALSE); + + status->pause = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORD_PAUSE_MASK)? + MV_TRUE:MV_FALSE); + + status->spdifEnable = + ((MV_REG_READ(MV_AUDIO_RECORD_CTRL_REG)&ARCR_RECORD_SPDIF_EN_MASK)? + MV_TRUE:MV_FALSE); + +} +/******************************************************************************* +* mvSPDIFRecordTclockSet - Set T-clock for SPDIF +* +* DESCRIPTION: +* +* INPUT: +* none +* OUTPUT: +* none +* RETURN: +* MV_OK on success , MV_NOT_SUPPORTED on non supported T-clock +* +*******************************************************************************/ + +/* SPDIF Recording Related*/ +MV_STATUS mvSPDIFRecordTclockSet() +{ + MV_U32 tclock = mvBoardTclkGet(); + MV_U32 reg = MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG); + + reg &= ~ASRGR_CORE_CLK_FREQ_MASK; + + switch (tclock) + { + case MV_BOARD_TCLK_133MHZ: + reg |= ASRGR_CORE_CLK_FREQ_133MHZ; + break; + case MV_BOARD_TCLK_150MHZ: + reg |= ASRGR_CORE_CLK_FREQ_150MHZ; + break; + case MV_BOARD_TCLK_166MHZ: + reg |= ASRGR_CORE_CLK_FREQ_166MHZ; + break; + case MV_BOARD_TCLK_200MHZ: + reg |= ASRGR_CORE_CLK_FREQ_200MHZ; + break; + default: + mvOsPrintf("mvSPDIFRecordTclockSet: Not supported core clock %d\n",tclock); + return MV_NOT_SUPPORTED; + } + + MV_REG_WRITE(MV_AUDIO_SPDIF_REC_GEN_REG, reg); + + return MV_OK; + +} +/******************************************************************************* +* mvSPDIFRecordTclockGet - Get T-clock for SPDIF +* +* DESCRIPTION: +* +* INPUT: +* none +* OUTPUT: +* none +* RETURN: +* T-clock configured in the SPDIF. +* +*******************************************************************************/ +MV_U32 mvSPDIFRecordTclockGet(MV_VOID) +{ + MV_U32 reg = (MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG) & ASRGR_CORE_CLK_FREQ_MASK); + + switch (reg) + { + case ASRGR_CORE_CLK_FREQ_133MHZ: + return MV_BOARD_TCLK_133MHZ; + case ASRGR_CORE_CLK_FREQ_150MHZ: + return MV_BOARD_TCLK_150MHZ; + case ASRGR_CORE_CLK_FREQ_166MHZ: + return MV_BOARD_TCLK_166MHZ; + case ASRGR_CORE_CLK_FREQ_200MHZ: + return MV_BOARD_TCLK_200MHZ; + } + + return 0; +} + +/******************************************************************************* +* mvAudioRecordControlGet - Get SPDIF Recording status parameters +* +* DESCRIPTION: +* +* INPUT: +* status: pointer to MV_SPDIF_RECORD_STATUS structure +* OUTPUT: +* status: pointer to MV_SPDIF_RECORD_STATUS structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvSPDIFRecordStatusGet(MV_SPDIF_RECORD_STATUS *status) +{ + status->freq = + ((MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG)&ASRGR_CORE_CLK_FREQ_MASK) >> + ASRGR_CORE_CLK_FREQ_OFFS); + + status->nonLinearPcm = + ((MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG)&ASRGR_NON_PCM_MASK)? + MV_TRUE:MV_FALSE); + + status->validPcm = + ((MV_REG_READ(MV_AUDIO_SPDIF_REC_GEN_REG)&ASRGR_VALID_PCM_INFO_MASK)? + MV_TRUE:MV_FALSE); + +} + +/* I2S Recording Related*/ +/******************************************************************************* +* mvI2SRecordCntrlSet - Get I2S Recording status parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_I2S_RECORD_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_I2S_RECORD_CTRL structure +* RETURN: +* MV_OK on success , MV_FAIL on fail. +* +*******************************************************************************/ +MV_STATUS mvI2SRecordCntrlSet(MV_I2S_RECORD_CTRL *ctrl) +{ + MV_U32 reg; + +#if 0 + if (ctrl->sample > SAMPLE_16BIT) + { + mvOsPrintf("mvI2SRecordCntrlSet: Error , Illigal sample size %d\n", + ctrl->sample); + return MV_FAIL; + } +#endif + + reg = MV_REG_READ(MV_AUDIO_I2S_REC_CTRL_REG); + reg &= ~(AIRCR_I2S_RECORD_JUSTF_MASK|AIRCR_I2S_SAMPLE_SIZE_MASK); + + switch (ctrl->justf) + { + case I2S_JUSTIFIED: + case LEFT_JUSTIFIED: + case RIGHT_JUSTIFIED: + case RISE_BIT_CLCK_JUSTIFIED: + reg |= ctrl->justf << AIRCR_I2S_RECORD_JUSTF_OFFS; + break; + default: + return MV_FAIL; + } + + reg |= ctrl->sample << AIRCR_I2S_SAMPLE_SIZE_OFFS; + + MV_REG_WRITE(MV_AUDIO_I2S_REC_CTRL_REG, reg); + return MV_OK; +} + +/******************************************************************************* +* mvAudioRecordControlGet - Get I2S Recording status parameters +* +* DESCRIPTION: +* +* INPUT: +* ctrl: pointer to MV_I2S_RECORD_CTRL structure +* OUTPUT: +* ctrl: pointer to MV_I2S_RECORD_CTRL structure +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvI2SRecordCntrlGet(MV_I2S_RECORD_CTRL *ctrl) +{ + ctrl->sample = + ((MV_REG_READ(MV_AUDIO_I2S_REC_CTRL_REG)&AIRCR_I2S_SAMPLE_SIZE_MASK) >> + AIRCR_I2S_SAMPLE_SIZE_OFFS); + + ctrl->justf = + ((MV_REG_READ(MV_AUDIO_I2S_REC_CTRL_REG)&AIRCR_I2S_RECORD_JUSTF_MASK) >> + AIRCR_I2S_RECORD_JUSTF_OFFS); + + +} + + +/******************************************************************************* +* audioBurstBytesNumGet - Convert Burst enum to bytes number +* +* DESCRIPTION: +* +* INPUT: +* burst: MV_AUDIO_BURST_SIZE enum +* OUTPUT: +* none +* RETURN: +* number of burst bytes +* +*******************************************************************************/ +static MV_U32 audioBurstBytesNumGet(MV_AUDIO_BURST_SIZE burst) +{ + switch (burst) + { + case AUDIO_32BYTE_BURST: + return 32; + case AUDIO_128BYTE_BURST: + return 128; + default: + return 0xffffffff; + } +} + diff --git a/board/mv_feroceon/mv_hal/audio/mvAudio.h b/board/mv_feroceon/mv_hal/audio/mvAudio.h new file mode 100644 index 0000000..dd9f3f2 --- /dev/null +++ b/board/mv_feroceon/mv_hal/audio/mvAudio.h @@ -0,0 +1,342 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVAudioH +#define __INCMVAudioH + +#include "mvCommon.h" +#include "audio/mvAudioRegs.h" + + +/*********************************/ +/* General enums and structures */ +/*********************************/ +/* Type of Audio operations*/ +typedef enum _mvAudioOperation +{ + AUDIO_PLAYBACK = 0, + AUDIO_RECORD = 1 + +}MV_AUDIO_OP; + +typedef struct _mvAudioFreqData +{ + MV_AUDIO_FREQ baseFreq; /* Control FS, selects the base frequency of the DCO */ + MV_U32 offset; /* Offset control in which each step equals to 0.9536 ppm */ + +} MV_AUDIO_FREQ_DATA; + + +/*********************************/ +/* Play Back related structures */ +/*********************************/ + + +typedef struct _mvAudioPlaybackCtrl +{ + MV_AUDIO_BURST_SIZE burst; /* Specifies the Burst Size of the DMA */ + MV_BOOL loopBack; /* When Loopback is enabled, playback + data is looped back to be recorded */ + MV_AUDIO_PLAYBACK_MONO monoMode; /* Mono Mode is used */ + MV_U32 bufferPhyBase; /* Physical Address of DMA buffer */ + MV_U32 bufferSize; /* Size of DMA buffer */ + MV_U32 intByteCount; /* Number of bytes after which an + interrupt will be issued.*/ + MV_AUDIO_SAMPLE_SIZE sampleSize; /* Playback Sample Size*/ +}MV_AUDIO_PLAYBACK_CTRL; + +typedef struct _mvAudioPlaypackStatus +{ + MV_BOOL muteI2S; + MV_BOOL enableI2S; + MV_BOOL muteSPDIF; + MV_BOOL enableSPDIF; + MV_BOOL pause; + +}MV_AUDIO_PLAYBACK_STATUS; + + +typedef struct _mvSpdifPlaybackCtrl +{ + MV_BOOL nonPcm; /* PCM or non-PCM mode*/ + MV_BOOL validity; /* Validity bit value when using + registers (userBitsFromMemory=0)*/ + MV_BOOL underrunData; /* If true send last frame on mute/pause/underrun + otherwise send 24 binary*/ + MV_BOOL userBitsFromMemory; /* otherwise from intenal registers*/ + MV_BOOL validityFromMemory; /* otherwise from internal registers*/ + MV_BOOL blockStartInternally; /* When user and valid bits are form registers + then this bit should be zero */ +}MV_SPDIF_PLAYBACK_CTRL; + +typedef struct _mvI2SPlaybackCtrl +{ + MV_AUDIO_SAMPLE_SIZE sampleSize; + MV_AUDIO_I2S_JUSTIFICATION justification; + MV_BOOL sendLastFrame; /* If true send last frame on mute/pause/underrun + otherwise send 64 binary*/ +}MV_I2S_PLAYBACK_CTRL; + + +/*********************************/ +/* Recording related structures */ +/*********************************/ + +typedef struct _mvAudioRecordCtrl +{ + MV_AUDIO_BURST_SIZE burst; /* Recording DMA Burst Size */ + MV_AUDIO_SAMPLE_SIZE sampleSize; /*Recording Sample Size */ + MV_BOOL mono; /* If true then recording mono else recording stereo*/ + MV_AUDIO_RECORD_MONO monoChannel; /* Left or right moono*/ + MV_U32 bufferPhyBase; /* Physical Address of DMA buffer */ + MV_U32 bufferSize; /* Size of DMA buffer */ + + MV_U32 intByteCount; /* Number of bytes after which an + interrupt will be issued.*/ + + +}MV_AUDIO_RECORD_CTRL; + +typedef struct _mvAudioRecordStatus +{ + MV_BOOL mute; + MV_BOOL pause; + MV_BOOL spdifEnable; + MV_BOOL I2SEnable; + +}MV_AUDIO_RECORD_STATUS; + + +typedef struct _mvSPDIFRecordStatus +{ + MV_BOOL nonLinearPcm; /* pcm non-pcm*/ + MV_BOOL validPcm; /* valid non-valid pcm*/ + MV_AUDIO_SAMPLE_FREQ freq; /* sampled frequency*/ + +}MV_SPDIF_RECORD_STATUS; + +typedef struct _mvI2SRecordCntrl +{ + MV_AUDIO_SAMPLE_SIZE sample; /* I2S Recording Sample Size*/ + MV_AUDIO_I2S_JUSTIFICATION justf; +}MV_I2S_RECORD_CTRL; + + + +/*********************************/ +/* Usefull Macros */ +/* + -- Clocks Control and Status related -- +mvAudioIsDcoLocked() +mvAudioIsSpcrLocked() +mvAudioIsPllLocked() +mvAudioAllCountersClear() +mvAudioPlayCounterClear() +mvAudioRecCounterClear() +mvAudioAllCountersStart() +mvAudioPlayCounterStart() +mvAudioRecCounterStart() +mvAudioAllCountersStop() +mvAudioPlayCounterStop() +mvAudioRecCounterStop() + + -- PlayBack related -- +mvAudioIsPlaybackBusy() +mvAudioI2SPlaybackMute(mute) +mvAudioI2SPlaybackEnable(enable) +mvAudioSPDIFPlaybackMute(mute) +mvAudioSPDIFPlaybackEnable(enable) +mvAudioPlaybackPause(pause) + +---- Recording --- +mvAudioSPDIFRecordingEnable(enable) +mvAudioI2SRecordingEnable(enable) +mvAudioRecordMute(mute) +mvAudioRecordPause(pause) + +********************************/ + + + + +/* Clocks Control and Status related*/ +#define mvAudioIsDcoLocked() \ + (ASDSR_DCO_LOCK_MASK & MV_REG_READ(MV_AUDIO_SPCR_DCO_STATUS_REG)) +#define mvAudioIsSpcrLocked() \ + (ASDSR_SPCR_LOCK_MASK & MV_REG_READ(AUDIO_SPCR_DCO_STATUS_REG)) +#define mvAudioIsPllLocked() \ + (ASDSR_PLL_LOCK_MASK & MV_REG_READ(AUDIO_SPCR_DCO_STATUS_REG)) + +#define mvAudioAllCountersClear() \ + (MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_CLR_REC_CNTR_MASK|ASCCR_CLR_PLAY_CNTR_MASK))) +#define mvAudioPlayCounterClear() \ + (MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_CLR_PLAY_CNTR_MASK))) +#define mvAudioRecCounterClear() \ + (MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_CLR_REC_CNTR_MASK))) + +#define mvAudioAllCountersStart() \ + (MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_ACTIVE_PLAY_CNTR_MASK|ASCCR_ACTIVE_REC_CNTR_MASK))) +#define mvAudioPlayCounterStart() \ + (MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_ACTIVE_PLAY_CNTR_MASK))) +#define mvAudioRecCounterStart() \ + (MV_REG_BIT_SET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_ACTIVE_REC_CNTR_MASK))) + +#define mvAudioAllCountersStop() \ + (MV_REG_BIT_RESET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_ACTIVE_PLAY_CNTR_MASK|ASCCR_ACTIVE_REC_CNTR_MASK))) +#define mvAudioPlayCounterStop() \ + (MV_REG_BIT_RESET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_ACTIVE_PLAY_CNTR_MASK))) +#define mvAudioRecCounterStop() \ + (MV_REG_BIT_RESET(MV_AUDIO_SAMPLE_CNTR_CTRL_REG,(ASCCR_ACTIVE_REC_CNTR_MASK))) + +/* Audio PlayBack related*/ +#define mvAudioIsPlaybackBusy() \ + (APCR_PLAY_BUSY_MASK & MV_REG_READ(MV_AUDIO_PLAYBACK_CTRL_REG)) + +#define mvAudioI2SPlaybackMute(mute) \ + (void)((mute)?(MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_I2S_MUTE_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_I2S_MUTE_MASK)) +#define mvAudioI2SPlaybackEnable(enable) \ + (void)((enable)?(MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_I2S_ENABLE_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_I2S_ENABLE_MASK)) + +#define mvAudioSPDIFPlaybackMute(mute) \ + (void)((mute)?(MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_SPDIF_MUTE_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_SPDIF_MUTE_MASK)) +#define mvAudioSPDIFPlaybackEnable(enable) \ + (void)((enable)?(MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_SPDIF_ENABLE_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_SPDIF_ENABLE_MASK)) + +#define mvAudioAllIfPlaybackEnable(enable) \ + (void)((enable)? \ + (MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG, \ + (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))): \ + MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG, \ + (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) + +#define mvAudioPlaybackPause(pause) \ + (void)((pause)?(MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_PAUSE_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_PLAY_PAUSE_MASK)) + +#define mvAudioPlaybackLoopbackEnable(enable) \ + (void)((enable)?(MV_REG_BIT_SET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_LOOPBACK_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_PLAYBACK_CTRL_REG,APCR_LOOPBACK_MASK)) + + +/* Audio Recording*/ +#define mvAudioSPDIFRecordingEnable(enable) \ + (void)((enable)?(MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_SPDIF_EN_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_SPDIF_EN_MASK)) + +#define mvAudioI2SRecordingEnable(enable) \ + (void)((enable)?(MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_I2S_EN_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_I2S_EN_MASK)) + +#define mvAudioRecordMute(mute) \ + (void)((mute)?(MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_MUTE_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_MUTE_MASK)) + +#define mvAudioRecordPause(pause) \ + (void)((pause)?(MV_REG_BIT_SET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_PAUSE_MASK)): \ + MV_REG_BIT_RESET(MV_AUDIO_RECORD_CTRL_REG,ARCR_RECORD_PAUSE_MASK)) + + + +/*********************************/ +/* Functions API */ +/*********************************/ + +MV_VOID mvAudioHalInit(void); + +/* Clocks Control and Status related*/ +MV_STATUS mvAudioDCOCtrlSet(MV_AUDIO_FREQ_DATA *dcoCtrl); +MV_VOID mvAudioDCOCtrlGet(MV_AUDIO_FREQ_DATA *dcoCtrl); +MV_VOID mvAudioSpcrCtrlGet(MV_AUDIO_FREQ_DATA *spcrCtrl); + +/* Audio PlayBack related*/ +MV_STATUS mvAudioPlaybackControlSet(MV_AUDIO_PLAYBACK_CTRL *ctrl); +MV_VOID mvAudioPlaybackControlGet(MV_AUDIO_PLAYBACK_CTRL *ctrl); +MV_VOID mvAudioPlaybackStatusGet(MV_AUDIO_PLAYBACK_STATUS *status); + +/* Audio SPDIF PlayBack related*/ +MV_VOID mvSPDIFPlaybackCtrlSet(MV_SPDIF_PLAYBACK_CTRL *ctrl); +MV_VOID mvSPDIFPlaybackCtrlGet(MV_SPDIF_PLAYBACK_CTRL *ctrl); + +/* Audio I2S PlayBack related*/ +MV_STATUS mvI2SPlaybackCtrlSet(MV_I2S_PLAYBACK_CTRL *ctrl); +MV_VOID mvI2SPlaybackCtrlGet(MV_I2S_PLAYBACK_CTRL *ctrl); + +/* Audio Recording*/ +MV_STATUS mvAudioRecordControlSet(MV_AUDIO_RECORD_CTRL *ctrl); +MV_VOID mvAudioRecordControlGet(MV_AUDIO_RECORD_CTRL *ctrl); +MV_VOID mvAudioRecordStatusGet(MV_AUDIO_RECORD_STATUS *status); + +/* SPDIF Recording Related*/ +MV_STATUS mvSPDIFRecordTclockSet(MV_VOID); +MV_U32 mvSPDIFRecordTclockGet(MV_VOID); +MV_VOID mvSPDIFRecordStatusGet(MV_SPDIF_RECORD_STATUS *status); + +/* I2S Recording Related*/ +MV_STATUS mvI2SRecordCntrlSet(MV_I2S_RECORD_CTRL *ctrl); +MV_VOID mvI2SRecordCntrlGet(MV_I2S_RECORD_CTRL *ctrl); + +#endif diff --git a/board/mv_feroceon/mv_hal/audio/mvAudioRegs.h b/board/mv_feroceon/mv_hal/audio/mvAudioRegs.h new file mode 100644 index 0000000..9b6579d --- /dev/null +++ b/board/mv_feroceon/mv_hal/audio/mvAudioRegs.h @@ -0,0 +1,411 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVAudioRegsH +#define __INCMVAudioRegsH + +#include "ctrlEnv/mvCtrlEnvSpec.h" + +/* Audio source Clocks enum*/ +typedef enum _mvAudioClock +{ + AUDIO_DCO_CLK = 0, + AUDIO_SPCR_CLK = 2, + AUDIO_EXT_CLK = 3 + +}MV_AUDIO_CLOCK; + +typedef enum _mvAudioFreq +{ + AUDIO_FREQ_44_1KH = 0, /* 11.2896Mhz */ + AUDIO_FREQ_48KH = 1, /* 12.288Mhz */ + AUDIO_FREQ_96KH =2, /* 24.576Mhz */ + AUDIO_FREQ_LOWER_44_1KH = 3 ,/*Lower than 11.2896MHz*/ + AUDIO_FREQ_HIGHER_96KH = 4, /*Higher than 24.576MHz*/ + AUDIO_FREQ_OTHER = 7, /*Other frequency*/ +}MV_AUDIO_FREQ; + + +typedef enum _mvAudioSampleFreq +{ + SMAPLE_8KHZ = 0, + SMAPLE_16KHZ, + SMAPLE_22_05KHZ, + SMAPLE_24KHZ, + SMAPLE_32KHZ, + SMAPLE_44_1KHZ, + SMAPLE_48KHZ, + SMAPLE_64KHZ, + SMAPLE_88KHZ, + SMAPLE_96KHZ, + SMAPLE_176KHZ, + SMAPLE_192KHZ +}MV_AUDIO_SAMPLE_FREQ; + +typedef enum _mvAudioBurstSize +{ + AUDIO_32BYTE_BURST = 1, + AUDIO_128BYTE_BURST = 2, + +}MV_AUDIO_BURST_SIZE; + +typedef enum _mvAudioPlaybackMono +{ + AUDIO_PLAY_MONO_OFF = 0, + AUDIO_PLAY_LEFT_MONO = 1, + AUDIO_PLAY_RIGHT_MONO = 2, + AUDIO_PLAY_BOTH_MONO = 3, + AUDIO_PLAY_OTHER_MONO = 4 + +}MV_AUDIO_PLAYBACK_MONO; + +typedef enum _mvAudioRecordMono +{ + AUDIO_REC_LEFT_MONO = 0, + AUDIO_REC_RIGHT_MONO = 1, + +}MV_AUDIO_RECORD_MONO; + +typedef enum _mvAudioSampleSize +{ + SAMPLE_32BIT = 0, + SAMPLE_24BIT = 1, + SAMPLE_20BIT = 2, + SAMPLE_16BIT = 3, + SAMPLE_16BIT_NON_COMPACT = 7 + +}MV_AUDIO_SAMPLE_SIZE; + +typedef enum _mvAudioI2SJustification +{ + LEFT_JUSTIFIED = 0, + I2S_JUSTIFIED = 5, + RISE_BIT_CLCK_JUSTIFIED =7, + RIGHT_JUSTIFIED = 8, + +}MV_AUDIO_I2S_JUSTIFICATION; + + +#define APBBCR_SIZE_MAX 0x3FFFFF +#define APBBCR_SIZE_SHIFT 0x2 + +#define AUDIO_REG_TO_SIZE(reg) (((reg) + 1) << APBBCR_SIZE_SHIFT) +#define AUDIO_SIZE_TO_REG(size) (((size) >> APBBCR_SIZE_SHIFT) - 1) + +#define MV_AUDIO_BUFFER_MIN_ALIGN 0x8 + +/********************/ +/* Clocking Control*/ +/*******************/ + + + +#define MV_AUDIO_DCO_CTRL_REG (AUDIO_REG_BASE + 0x1204) +#define MV_AUDIO_SPCR_DCO_STATUS_REG (AUDIO_REG_BASE + 0x120c) +#define MV_AUDIO_SAMPLE_CNTR_CTRL_REG (AUDIO_REG_BASE + 0x1220) +#define MV_AUDIO_PLAYBACK_SAMPLE_CNTR_REG (AUDIO_REG_BASE + 0x1224) +#define MV_AUDIO_RECORD_SAMPLE_CNTR_REG (AUDIO_REG_BASE + 0x1228) +#define MV_AUDIO_CLOCK_CTRL_REG (AUDIO_REG_BASE + 0x1230) + + +/* MV_AUDIO_DCO_CTRL_REG */ +#define ADCR_DCO_CTRL_FS_OFFS 0 +#define ADCR_DCO_CTRL_FS_MASK (0x3 << ADCR_DCO_CTRL_FS_OFFS) +#define ADCR_DCO_CTRL_FS_44_1KHZ (0x0 << ADCR_DCO_CTRL_FS_OFFS) +#define ADCR_DCO_CTRL_FS_48KHZ (0x1 << ADCR_DCO_CTRL_FS_OFFS) +#define ADCR_DCO_CTRL_FS_96KHZ (0x2 << ADCR_DCO_CTRL_FS_OFFS) + + +#define ADCR_DCO_CTRL_OFFSET_OFFS 2 +#define ADCR_DCO_CTRL_OFFSET_MASK (0xfff << ADCR_DCO_CTRL_OFFSET_OFFS) + +/* MV_AUDIO_SPCR_DCO_STATUS_REG */ +#define ASDSR_SPCR_CTRLFS_OFFS 0 +#define ASDSR_SPCR_CTRLFS_MASK (0x7 << ASDSR_SPCR_CTRLFS_OFFS) +#define ASDSR_SPCR_CTRLFS_44_1KHZ (0x0 << ASDSR_SPCR_CTRLFS_OFFS) +#define ASDSR_SPCR_CTRLFS_48KHZ (0x1 << ASDSR_SPCR_CTRLFS_OFFS) +#define ASDSR_SPCR_CTRLFS_96KHZ (0x2 << ASDSR_SPCR_CTRLFS_OFFS) +#define ASDSR_SPCR_CTRLFS_44_1KHZ_LESS (0x3 << ASDSR_SPCR_CTRLFS_OFFS) +#define ASDSR_SPCR_CTRLFS_96KHZ_MORE (0x4 << ASDSR_SPCR_CTRLFS_OFFS) +#define ASDSR_SPCR_CTRLFS_OTHER (0x7 << ASDSR_SPCR_CTRLFS_OFFS) + + +#define ASDSR_SPCR_CTRLOFFSET_OFFS 3 +#define ASDSR_SPCR_CTRLOFFSET_MASK (0xfff << ASDSR_SPCR_CTRLOFFSET_OFFS) + +#define ASDSR_SPCR_LOCK_OFFS 15 +#define ASDSR_SPCR_LOCK_MASK (0x1 << ASDSR_SPCR_LOCK_OFFS) + +#define ASDSR_DCO_LOCK_OFFS 16 +#define ASDSR_DCO_LOCK_MASK (0x1 << ASDSR_DCO_LOCK_OFFS) + +#define ASDSR_PLL_LOCK_OFFS 17 +#define ASDSR_PLL_LOCK_MASK (0x1 << ASDSR_PLL_LOCK_OFFS) + +/*MV_AUDIO_SAMPLE_CNTR_CTRL_REG */ + +#define ASCCR_CLR_PLAY_CNTR_OFFS 9 +#define ASCCR_CLR_PLAY_CNTR_MASK (0x1 << ASCCR_CLR_PLAY_CNTR_OFFS) + +#define ASCCR_CLR_REC_CNTR_OFFS 8 +#define ASCCR_CLR_REC_CNTR_MASK (0x1 << ASCCR_CLR_REC_CNTR_OFFS) + +#define ASCCR_ACTIVE_PLAY_CNTR_OFFS 1 +#define ASCCR_ACTIVE_PLAY_CNTR_MASK (0x1 << ASCCR_ACTIVE_PLAY_CNTR_OFFS) + +#define ASCCR_ACTIVE_REC_CNTR_OFFS 0 +#define ASCCR_ACTIVE_REC_CNTR_MASK (0x1 << ASCCR_ACTIVE_REC_CNTR_OFFS) + +/* MV_AUDIO_CLOCK_CTRL_REG */ +#define ACCR_MCLK_SOURCE_OFFS 0 +#define ACCR_MCLK_SOURCE_MASK (0x3 << ACCR_MCLK_SOURCE_OFFS) +#define ACCR_MCLK_SOURCE_DCO (0x0 << ACCR_MCLK_SOURCE_OFFS) +#define ACCR_MCLK_SOURCE_SPCR (0x2 << ACCR_MCLK_SOURCE_OFFS) +#define ACCR_MCLK_SOURCE_EXT (0x3 << ACCR_MCLK_SOURCE_OFFS) + + + +/********************/ +/* Interrupts */ +/*******************/ +#define MV_AUDIO_ERROR_CAUSE_REG (AUDIO_REG_BASE + 0x1300) +#define MV_AUDIO_ERROR_MASK_REG (AUDIO_REG_BASE + 0x1304) +#define MV_AUDIO_INT_CAUSE_REG (AUDIO_REG_BASE + 0x1308) +#define MV_AUDIO_INT_MASK_REG (AUDIO_REG_BASE + 0x130C) +#define MV_AUDIO_RECORD_BYTE_CNTR_INT_REG (AUDIO_REG_BASE + 0x1310) +#define MV_AUDIO_PLAYBACK_BYTE_CNTR_INT_REG (AUDIO_REG_BASE + 0x1314) + +/* MV_AUDIO_INT_CAUSE_REG*/ +#define AICR_RECORD_BYTES_INT (0x1 << 13) +#define AICR_PLAY_BYTES_INT (0x1 << 14) + +#define ARBCI_BYTE_COUNT_MASK 0xFFFFFF +#define APBCI_BYTE_COUNT_MASK 0xFFFFFF + +/********************/ +/* Audio Playback */ +/*******************/ +/* General */ +#define MV_AUDIO_PLAYBACK_CTRL_REG (AUDIO_REG_BASE + 0x1100) +#define MV_AUDIO_PLAYBACK_BUFF_START_REG (AUDIO_REG_BASE + 0x1104) +#define MV_AUDIO_PLAYBACK_BUFF_SIZE_REG (AUDIO_REG_BASE + 0x1108) +#define MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG (AUDIO_REG_BASE + 0x110c) + +/*SPDIF */ +#define MV_AUDIO_SPDIF_PLAY_CTRL_REG (AUDIO_REG_BASE + 0x2204) +#define MV_AUDIO_SPDIF_PLAY_CH_STATUS_LEFT_REG(ind) \ + (AUDIO_REG_BASE + 0x2280 + (ind << 2)) +#define MV_AUDIO_SPDIF_PLAY_CH_STATUS_RIGHT_REG(ind) \ + (AUDIO_REG_BASE + 0x22a0 + (ind << 2)) +#define MV_AUDIO_SPDIF_PLAY_USR_BITS_LEFT_REG(ind) \ + (AUDIO_REG_BASE + 0x22c0 + (ind << 2)) +#define MV_AUDIO_SPDIF_PLAY_USR_BITS_RIGHT_REG(ind) \ + (AUDIO_REG_BASE + 0x22e0 + (ind << 2)) +/*I2S*/ +#define MV_AUDIO_I2S_PLAY_CTRL_REG (AUDIO_REG_BASE + 0x2508) + + +/* MV_AUDIO_PLAYBACK_CTRL_REG */ +#define APCR_PLAY_SAMPLE_SIZE_OFFS 0 +#define APCR_PLAY_SAMPLE_SIZE_MASK (0x7 << APCR_PLAY_SAMPLE_SIZE_OFFS) + +#define APCR_PLAY_I2S_ENABLE_OFFS 3 +#define APCR_PLAY_I2S_ENABLE_MASK (0x1 << APCR_PLAY_I2S_ENABLE_OFFS) + +#define APCR_PLAY_SPDIF_ENABLE_OFFS 4 +#define APCR_PLAY_SPDIF_ENABLE_MASK (0x1 << APCR_PLAY_SPDIF_ENABLE_OFFS) + +#define APCR_PLAY_MONO_OFFS 5 +#define APCR_PLAY_MONO_MASK (0x3 << APCR_PLAY_MONO_OFFS) + +#define APCR_PLAY_I2S_MUTE_OFFS 7 +#define APCR_PLAY_I2S_MUTE_MASK (0x1 << APCR_PLAY_I2S_MUTE_OFFS) + +#define APCR_PLAY_SPDIF_MUTE_OFFS 8 +#define APCR_PLAY_SPDIF_MUTE_MASK (0x1 << APCR_PLAY_SPDIF_MUTE_OFFS) + +#define APCR_PLAY_PAUSE_OFFS 9 +#define APCR_PLAY_PAUSE_MASK (0x1 << APCR_PLAY_PAUSE_OFFS) + +#define APCR_LOOPBACK_OFFS 10 +#define APCR_LOOPBACK_MASK (0x1 << APCR_LOOPBACK_OFFS) + +#define APCR_PLAY_BURST_SIZE_OFFS 11 +#define APCR_PLAY_BURST_SIZE_MASK (0x3 << APCR_PLAY_BURST_SIZE_OFFS) + +#define APCR_PLAY_BUSY_OFFS 16 +#define APCR_PLAY_BUSY_MASK (0x1 << APCR_PLAY_BUSY_OFFS) + +/* MV_AUDIO_PLAYBACK_BUFF_BYTE_CNTR_REG */ +#define APBBCR_SIZE_MAX 0x3FFFFF +#define APBBCR_SIZE_SHIFT 0x2 + + +/* MV_AUDIO_SPDIF_PLAY_CTRL_REG */ +#define ASPCR_SPDIF_BLOCK_START_OFFS 0x0 +#define ASPCR_SPDIF_BLOCK_START_MASK (0x1 << ASPCR_SPDIF_BLOCK_START_OFFS) + +#define ASPCR_SPDIF_PB_EN_MEM_VALIDITY_OFFS 0x1 +#define ASPCR_SPDIF_PB_EN_MEM_VALIDITY_MASK (0x1 << ASPCR_SPDIF_PB_EN_MEM_VALIDITY_OFFS) + +#define ASPCR_SPDIF_PB_MEM_USR_EN_OFFS 0x2 +#define ASPCR_SPDIF_PB_MEM_USR_EN_MASK (0x1 << ASPCR_SPDIF_PB_MEM_USR_EN_OFFS) + +#define ASPCR_SPDIF_UNDERRUN_DATA_OFFS 0x5 +#define ASPCR_SPDIF_UNDERRUN_DATA_MASK (0x1 << ASPCR_SPDIF_UNDERRUN_DATA_OFFS) + +#define ASPCR_SPDIF_PB_REG_VALIDITY_OFFS 16 +#define ASPCR_SPDIF_PB_REG_VALIDITY_MASK (0x1 << ASPCR_SPDIF_PB_REG_VALIDITY_OFFS) + +#define ASPCR_SPDIF_PB_NONPCM_OFFS 17 +#define ASPCR_SPDIF_PB_NONPCM_MASK (0x1 << ASPCR_SPDIF_PB_NONPCM_OFFS) + + + +/* MV_AUDIO_I2S_PLAY_CTRL_REG */ +#define AIPCR_I2S_SEND_LAST_FRM_OFFS 23 +#define AIPCR_I2S_SEND_LAST_FRM_MASK (1 << AIPCR_I2S_SEND_LAST_FRM_OFFS) + +#define AIPCR_I2S_PB_JUSTF_OFFS 26 +#define AIPCR_I2S_PB_JUSTF_MASK (0xf << AIPCR_I2S_PB_JUSTF_OFFS) + +#define AIPCR_I2S_PB_SAMPLE_SIZE_OFFS 30 +#define AIPCR_I2S_PB_SAMPLE_SIZE_MASK (0x3 << AIPCR_I2S_PB_SAMPLE_SIZE_OFFS) + +/********************/ +/* Audio Recordnig */ +/*******************/ +/* General */ +#define MV_AUDIO_RECORD_CTRL_REG (AUDIO_REG_BASE + 0x1000) +#define MV_AUDIO_RECORD_START_ADDR_REG (AUDIO_REG_BASE + 0x1004) +#define MV_AUDIO_RECORD_BUFF_SIZE_REG (AUDIO_REG_BASE + 0x1008) +#define MV_AUDIO_RECORD_BUF_BYTE_CNTR_REG (AUDIO_REG_BASE + 0x100C) + +/*SPDIF */ +#define MV_AUDIO_SPDIF_REC_GEN_REG (AUDIO_REG_BASE + 0x2004) +#define MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG (AUDIO_REG_BASE + 0x2008) +#define MV_AUDIO_SPDIF_REC_CH_STATUS_LEFT_REG(ind) \ + (AUDIO_REG_BASE + 0x2180 + ((ind) << 2)) +#define MV_AUDIO_SPDIF_REC_CH_STATUS_RIGHT_REG(ind) \ + (AUDIO_REG_BASE + 0x21a0 + ((ind) << 2)) +#define MV_AUDIO_SPDIF_REC_USR_BITS_LEFT_REG(ind) \ + (AUDIO_REG_BASE + 0x21c0 + ((ind) << 2)) +#define MV_AUDIO_SPDIF_REC_USR_BITS_RIGHT_REG(ind) \ + (AUDIO_REG_BASE + 0x21e0 + ((ind) << 2)) + +/*I2S*/ +#define MV_AUDIO_I2S_REC_CTRL_REG (AUDIO_REG_BASE + 0x2408) + + +/* MV_AUDIO_RECORD_CTRL_REG*/ +#define ARCR_RECORD_SAMPLE_SIZE_OFFS 0 +#define ARCR_RECORD_SAMPLE_SIZE_MASK (0x7 << ARCR_RECORD_SAMPLE_SIZE_OFFS) + +#define ARCR_RECORDED_MONO_CHNL_OFFS 3 +#define ARCR_RECORDED_MONO_CHNL_MASK (0x1 << ARCR_RECORDED_MONO_CHNL_OFFS) + +#define ARCR_RECORD_MONO_OFFS 4 +#define ARCR_RECORD_MONO_MASK (0x1 << ARCR_RECORD_MONO_OFFS) + +#define ARCR_RECORD_BURST_SIZE_OFFS 5 +#define ARCR_RECORD_BURST_SIZE_MASK (0x3 << ARCR_RECORD_BURST_SIZE_OFFS) + +#define ARCR_RECORD_MUTE_OFFS 8 +#define ARCR_RECORD_MUTE_MASK (0x1 << ARCR_RECORD_MUTE_OFFS) + +#define ARCR_RECORD_PAUSE_OFFS 9 +#define ARCR_RECORD_PAUSE_MASK (0x1 << ARCR_RECORD_PAUSE_OFFS) + +#define ARCR_RECORD_I2S_EN_OFFS 10 +#define ARCR_RECORD_I2S_EN_MASK (0x1 << ARCR_RECORD_I2S_EN_OFFS) + +#define ARCR_RECORD_SPDIF_EN_OFFS 11 +#define ARCR_RECORD_SPDIF_EN_MASK (0x1 << ARCR_RECORD_SPDIF_EN_OFFS) + + +/* MV_AUDIO_SPDIF_REC_GEN_REG*/ +#define ASRGR_CORE_CLK_FREQ_OFFS 1 +#define ASRGR_CORE_CLK_FREQ_MASK (0x3 << ASRGR_CORE_CLK_FREQ_OFFS) +#define ASRGR_CORE_CLK_FREQ_133MHZ (0x0 << ASRGR_CORE_CLK_FREQ_OFFS) +#define ASRGR_CORE_CLK_FREQ_150MHZ (0x1 << ASRGR_CORE_CLK_FREQ_OFFS) +#define ASRGR_CORE_CLK_FREQ_166MHZ (0x2 << ASRGR_CORE_CLK_FREQ_OFFS) +#define ASRGR_CORE_CLK_FREQ_200MHZ (0x3 << ASRGR_CORE_CLK_FREQ_OFFS) + +#define ASRGR_VALID_PCM_INFO_OFFS 7 +#define ASRGR_VALID_PCM_INFO_MASK (0x1 << ASRGR_VALID_PCM_INFO_OFFS) + +#define ASRGR_SAMPLE_FREQ_OFFS 8 +#define ASRGR_SAMPLE_FREQ_MASK (0xf << ASRGR_SAMPLE_FREQ_OFFS) + +#define ASRGR_NON_PCM_OFFS 14 +#define ASRGR_NON_PCM_MASK (1 << ASRGR_NON_PCM_OFFS) + +/* MV_AUDIO_I2S_REC_CTRL_REG*/ +#define AIRCR_I2S_RECORD_JUSTF_OFFS 26 +#define AIRCR_I2S_RECORD_JUSTF_MASK (0xf << AIRCR_I2S_RECORD_JUSTF_OFFS) + +#define AIRCR_I2S_SAMPLE_SIZE_OFFS 30 +#define AIRCR_I2S_SAMPLE_SIZE_MASK (0x3 << AIRCR_I2S_SAMPLE_SIZE_OFFS) + +#endif /* __INCMVAudioRegsH */ + diff --git a/board/mv_feroceon/mv_hal/cesa/AES/mvAes.h b/board/mv_feroceon/mv_hal/cesa/AES/mvAes.h new file mode 100644 index 0000000..07a8601 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/AES/mvAes.h @@ -0,0 +1,62 @@ +/* mvAes.h v2.0 August '99 + * Reference ANSI C code + */ + +/* AES Cipher header file for ANSI C Submissions + Lawrence E. Bassham III + Computer Security Division + National Institute of Standards and Technology + + April 15, 1998 + + This sample is to assist implementers developing to the Cryptographic +API Profile for AES Candidate Algorithm Submissions. Please consult this +document as a cross-reference. + + ANY CHANGES, WHERE APPROPRIATE, TO INFORMATION PROVIDED IN THIS FILE +MUST BE DOCUMENTED. CHANGES ARE ONLY APPROPRIATE WHERE SPECIFIED WITH +THE STRING "CHANGE POSSIBLE". FUNCTION CALLS AND THEIR PARAMETERS CANNOT +BE CHANGED. STRUCTURES CAN BE ALTERED TO ALLOW IMPLEMENTERS TO INCLUDE +IMPLEMENTATION SPECIFIC INFORMATION. +*/ + +/* Includes: + Standard include files +*/ + +#include "mvOs.h" + + +/* Error Codes - CHANGE POSSIBLE: inclusion of additional error codes */ + +/* Key direction is invalid, e.g., unknown value */ +#define AES_BAD_KEY_DIR -1 + +/* Key material not of correct length */ +#define AES_BAD_KEY_MAT -2 + +/* Key passed is not valid */ +#define AES_BAD_KEY_INSTANCE -3 + +/* Params struct passed to cipherInit invalid */ +#define AES_BAD_CIPHER_MODE -4 + +/* Cipher in wrong state (e.g., not initialized) */ +#define AES_BAD_CIPHER_STATE -5 + +#define AES_BAD_CIPHER_INSTANCE -7 + + +/* Function protoypes */ +/* CHANGED: makeKey(): parameter blockLen added + this parameter is absolutely necessary if you want to + setup the round keys in a variable block length setting + cipherInit(): parameter blockLen added (for obvious reasons) + */ +int aesMakeKey(MV_U8 *expandedKey, MV_U8 *keyMaterial, int keyLen, int blockLen); +int aesBlockEncrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen, + MV_U32 *plain, int numBlocks, MV_U32 *cipher); +int aesBlockDecrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen, + MV_U32 *plain, int numBlocks, MV_U32 *cipher); + + diff --git a/board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.c b/board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.c new file mode 100644 index 0000000..a65dc28 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.c @@ -0,0 +1,317 @@ +/* rijndael-alg-ref.c v2.0 August '99 + * Reference ANSI C code + * authors: Paulo Barreto + * Vincent Rijmen, K.U.Leuven + * + * This code is placed in the public domain. + */ + +#include "mvOs.h" + +#include "mvAesAlg.h" + +#include "mvAesBoxes.dat" + + +MV_U8 mul1(MV_U8 aa, MV_U8 bb); +void KeyAddition(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC], MV_U8 BC); +void ShiftRow128Enc(MV_U8 a[4][MAXBC]); +void ShiftRow128Dec(MV_U8 a[4][MAXBC]); +void Substitution(MV_U8 a[4][MAXBC], MV_U8 box[256]); +void MixColumn(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC]); +void InvMixColumn(MV_U8 a[4][MAXBC]); + + +#define mul(aa, bb) (mask[bb] & Alogtable[aa + Logtable[bb]]) + +MV_U8 mul1(MV_U8 aa, MV_U8 bb) +{ + return mask[bb] & Alogtable[aa + Logtable[bb]]; +} + + +void KeyAddition(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC], MV_U8 BC) +{ + /* Exor corresponding text input and round key input bytes + */ + ((MV_U32*)(&(a[0][0])))[0] ^= ((MV_U32*)(&(rk[0][0])))[0]; + ((MV_U32*)(&(a[1][0])))[0] ^= ((MV_U32*)(&(rk[1][0])))[0]; + ((MV_U32*)(&(a[2][0])))[0] ^= ((MV_U32*)(&(rk[2][0])))[0]; + ((MV_U32*)(&(a[3][0])))[0] ^= ((MV_U32*)(&(rk[3][0])))[0]; + +} + +void ShiftRow128Enc(MV_U8 a[4][MAXBC]) { + /* Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + MV_U8 tmp[MAXBC]; + + tmp[0] = a[1][1]; + tmp[1] = a[1][2]; + tmp[2] = a[1][3]; + tmp[3] = a[1][0]; + + ((MV_U32*)(&(a[1][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; + /* + a[1][0] = tmp[0]; + a[1][1] = tmp[1]; + a[1][2] = tmp[2]; + a[1][3] = tmp[3]; + */ + tmp[0] = a[2][2]; + tmp[1] = a[2][3]; + tmp[2] = a[2][0]; + tmp[3] = a[2][1]; + + ((MV_U32*)(&(a[2][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; + /* + a[2][0] = tmp[0]; + a[2][1] = tmp[1]; + a[2][2] = tmp[2]; + a[2][3] = tmp[3]; + */ + tmp[0] = a[3][3]; + tmp[1] = a[3][0]; + tmp[2] = a[3][1]; + tmp[3] = a[3][2]; + + ((MV_U32*)(&(a[3][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; + /* + a[3][0] = tmp[0]; + a[3][1] = tmp[1]; + a[3][2] = tmp[2]; + a[3][3] = tmp[3]; + */ +} + +void ShiftRow128Dec(MV_U8 a[4][MAXBC]) { + /* Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + MV_U8 tmp[MAXBC]; + + tmp[0] = a[1][3]; + tmp[1] = a[1][0]; + tmp[2] = a[1][1]; + tmp[3] = a[1][2]; + + ((MV_U32*)(&(a[1][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; + /* + a[1][0] = tmp[0]; + a[1][1] = tmp[1]; + a[1][2] = tmp[2]; + a[1][3] = tmp[3]; + */ + + tmp[0] = a[2][2]; + tmp[1] = a[2][3]; + tmp[2] = a[2][0]; + tmp[3] = a[2][1]; + + ((MV_U32*)(&(a[2][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; + /* + a[2][0] = tmp[0]; + a[2][1] = tmp[1]; + a[2][2] = tmp[2]; + a[2][3] = tmp[3]; + */ + + tmp[0] = a[3][1]; + tmp[1] = a[3][2]; + tmp[2] = a[3][3]; + tmp[3] = a[3][0]; + + ((MV_U32*)(&(a[3][0])))[0] = ((MV_U32*)(&(tmp[0])))[0]; + /* + a[3][0] = tmp[0]; + a[3][1] = tmp[1]; + a[3][2] = tmp[2]; + a[3][3] = tmp[3]; + */ +} + +void Substitution(MV_U8 a[4][MAXBC], MV_U8 box[256]) { + /* Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + int i, j; + + for(i = 0; i < 4; i++) + for(j = 0; j < 4; j++) a[i][j] = box[a[i][j]] ; +} + +void MixColumn(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC]) { + /* Mix the four bytes of every column in a linear way + */ + MV_U8 b[4][MAXBC]; + int i, j; + + for(j = 0; j < 4; j++){ + b[0][j] = mul(25,a[0][j]) ^ mul(1,a[1][j]) ^ a[2][j] ^ a[3][j]; + b[1][j] = mul(25,a[1][j]) ^ mul(1,a[2][j]) ^ a[3][j] ^ a[0][j]; + b[2][j] = mul(25,a[2][j]) ^ mul(1,a[3][j]) ^ a[0][j] ^ a[1][j]; + b[3][j] = mul(25,a[3][j]) ^ mul(1,a[0][j]) ^ a[1][j] ^ a[2][j]; + } + for(i = 0; i < 4; i++) + /*for(j = 0; j < BC; j++) a[i][j] = b[i][j];*/ + ((MV_U32*)(&(a[i][0])))[0] = ((MV_U32*)(&(b[i][0])))[0] ^ ((MV_U32*)(&(rk[i][0])))[0];; +} + +void InvMixColumn(MV_U8 a[4][MAXBC]) { + /* Mix the four bytes of every column in a linear way + * This is the opposite operation of Mixcolumn + */ + MV_U8 b[4][MAXBC]; + int i, j; + + for(j = 0; j < 4; j++){ + b[0][j] = mul(223,a[0][j]) ^ mul(104,a[1][j]) ^ mul(238,a[2][j]) ^ mul(199,a[3][j]); + b[1][j] = mul(223,a[1][j]) ^ mul(104,a[2][j]) ^ mul(238,a[3][j]) ^ mul(199,a[0][j]); + b[2][j] = mul(223,a[2][j]) ^ mul(104,a[3][j]) ^ mul(238,a[0][j]) ^ mul(199,a[1][j]); + b[3][j] = mul(223,a[3][j]) ^ mul(104,a[0][j]) ^ mul(238,a[1][j]) ^ mul(199,a[2][j]); + } + for(i = 0; i < 4; i++) + /*for(j = 0; j < BC; j++) a[i][j] = b[i][j];*/ + ((MV_U32*)(&(a[i][0])))[0] = ((MV_U32*)(&(b[i][0])))[0]; +} + +int rijndaelKeySched (MV_U8 k[4][MAXKC], int keyBits, int blockBits, MV_U8 W[MAXROUNDS+1][4][MAXBC]) +{ + /* Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits + */ + int KC, BC, ROUNDS; + int i, j, t, rconpointer = 0; + MV_U8 tk[4][MAXKC]; + + switch (keyBits) { + case 128: KC = 4; break; + case 192: KC = 6; break; + case 256: KC = 8; break; + default : return (-1); + } + + switch (blockBits) { + case 128: BC = 4; break; + case 192: BC = 6; break; + case 256: BC = 8; break; + default : return (-2); + } + + switch (keyBits >= blockBits ? keyBits : blockBits) { + case 128: ROUNDS = 10; break; + case 192: ROUNDS = 12; break; + case 256: ROUNDS = 14; break; + default : return (-3); /* this cannot happen */ + } + + + for(j = 0; j < KC; j++) + for(i = 0; i < 4; i++) + tk[i][j] = k[i][j]; + t = 0; + /* copy values into round key array */ + for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) + for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; + + while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */ + /* calculate new values */ + for(i = 0; i < 4; i++) + tk[i][0] ^= S[tk[(i+1)%4][KC-1]]; + tk[0][0] ^= rcon[rconpointer++]; + + if (KC != 8) + for(j = 1; j < KC; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + else { + for(j = 1; j < KC/2; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]]; + for(j = KC/2 + 1; j < KC; j++) + for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1]; + } + /* copy values into round key array */ + for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) + for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j]; + } + + return 0; +} + + + +int rijndaelEncrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS+1][4][MAXBC], int rounds) +{ + /* Encryption of one block. + */ + int r, BC, ROUNDS; + + BC = 4; + ROUNDS = rounds; + + /* begin with a key addition + */ + + KeyAddition(a,rk[0],BC); + + /* ROUNDS-1 ordinary rounds + */ + for(r = 1; r < ROUNDS; r++) { + Substitution(a,S); + ShiftRow128Enc(a); + MixColumn(a, rk[r]); + /*KeyAddition(a,rk[r],BC);*/ + } + + /* Last round is special: there is no MixColumn + */ + Substitution(a,S); + ShiftRow128Enc(a); + KeyAddition(a,rk[ROUNDS],BC); + + return 0; +} + + +int rijndaelDecrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS+1][4][MAXBC], int rounds) +{ + int r, BC, ROUNDS; + + BC = 4; + ROUNDS = rounds; + + /* To decrypt: apply the inverse operations of the encrypt routine, + * in opposite order + * + * (KeyAddition is an involution: it 's equal to its inverse) + * (the inverse of Substitution with table S is Substitution with the inverse table of S) + * (the inverse of Shiftrow is Shiftrow over a suitable distance) + */ + + /* First the special round: + * without InvMixColumn + * with extra KeyAddition + */ + KeyAddition(a,rk[ROUNDS],BC); + ShiftRow128Dec(a); + Substitution(a,Si); + + /* ROUNDS-1 ordinary rounds + */ + for(r = ROUNDS-1; r > 0; r--) { + KeyAddition(a,rk[r],BC); + InvMixColumn(a); + ShiftRow128Dec(a); + Substitution(a,Si); + + } + + /* End with the extra key addition + */ + + KeyAddition(a,rk[0],BC); + + return 0; +} + diff --git a/board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.h b/board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.h new file mode 100644 index 0000000..ec81e40 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/AES/mvAesAlg.h @@ -0,0 +1,19 @@ +/* rijndael-alg-ref.h v2.0 August '99 + * Reference ANSI C code + * authors: Paulo Barreto + * Vincent Rijmen, K.U.Leuven + */ +#ifndef __RIJNDAEL_ALG_H +#define __RIJNDAEL_ALG_H + +#define MAXBC (128/32) +#define MAXKC (256/32) +#define MAXROUNDS 14 + + +int rijndaelKeySched (MV_U8 k[4][MAXKC], int keyBits, int blockBits, MV_U8 rk[MAXROUNDS+1][4][MAXBC]); + +int rijndaelEncrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS+1][4][MAXBC], int rounds); +int rijndaelDecrypt128(MV_U8 a[4][MAXBC], MV_U8 rk[MAXROUNDS+1][4][MAXBC], int rounds); + +#endif /* __RIJNDAEL_ALG_H */ diff --git a/board/mv_feroceon/mv_hal/cesa/AES/mvAesApi.c b/board/mv_feroceon/mv_hal/cesa/AES/mvAesApi.c new file mode 100644 index 0000000..b432dc6 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/AES/mvAesApi.c @@ -0,0 +1,312 @@ +/* rijndael-api-ref.c v2.1 April 2000 + * Reference ANSI C code + * authors: v2.0 Paulo Barreto + * Vincent Rijmen, K.U.Leuven + * v2.1 Vincent Rijmen, K.U.Leuven + * + * This code is placed in the public domain. + */ +#include "mvOs.h" + +#include "mvAes.h" +#include "mvAesAlg.h" + + +/* Defines: + Add any additional defines you need +*/ + +#define MODE_ECB 1 /* Are we ciphering in ECB mode? */ +#define MODE_CBC 2 /* Are we ciphering in CBC mode? */ +#define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */ + + +int aesMakeKey(MV_U8 *expandedKey, MV_U8 *keyMaterial, int keyLen, int blockLen) +{ + MV_U8 W[MAXROUNDS+1][4][MAXBC]; + MV_U8 k[4][MAXKC]; + MV_U8 j; + int i, rounds, KC; + + if (expandedKey == NULL) + { + return AES_BAD_KEY_INSTANCE; + } + + if (!((keyLen == 128) || (keyLen == 192) || (keyLen == 256))) + { + return AES_BAD_KEY_MAT; + } + + if (keyMaterial == NULL) + { + return AES_BAD_KEY_MAT; + } + + /* initialize key schedule: */ + for(i=0; istate = MV_CESA_PROCESS; + cesaStats.startCount++; + + if(pReq->fragMode == MV_CESA_FRAG_NONE) + { + frag = 0; + } + else + { + frag = pReq->frags.nextFrag; + pReq->frags.nextFrag++; + } +#if (MV_CESA_VERSION >= 2) + /* Enable TDMA engine */ + MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0); + MV_REG_WRITE(MV_CESA_TDMA_NEXT_DESC_PTR_REG, + (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst)); +#else + /* Enable IDMA engine */ + MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0); + MV_REG_WRITE(IDMA_NEXT_DESC_PTR_REG(0), + (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst)); +#endif /* MV_CESA_VERSION >= 2 */ + +#if defined(MV_BRIDGE_SYNC_REORDER) + mvOsBridgeReorderWA(); +#endif + + /* Start Accelerator */ + MV_REG_WRITE(MV_CESA_CMD_REG, MV_CESA_CMD_CHAN_ENABLE_MASK); +} + + +/******************************************************************************* +* mvCesaHalInit - Initialize the CESA driver +* +* DESCRIPTION: +* This function initialize the CESA driver. +* 1) Session database +* 2) Request queue +* 4) DMA descriptor lists - one list per request. Each list +* has MV_CESA_MAX_DMA_DESC descriptors. +* +* INPUT: +* numOfSession - maximum number of supported sessions +* queueDepth - number of elements in the request queue. +* pSramBase - virtual address of Sram +* osHandle - A handle used by the OS to allocate memory for the +* module (Passed to the OS Services layer) +* +* RETURN: +* MV_OK - Success +* MV_NO_RESOURCE - Fail, can't allocate resources: +* Session database, request queue, +* DMA descriptors list, LRU cache database. +* MV_NOT_ALIGNED - Sram base address is not 8 byte aligned. +* +*******************************************************************************/ +MV_STATUS mvCesaHalInit (int numOfSession, int queueDepth, char* pSramBase, MV_U32 cryptEngBase, + void *osHandle) +{ + int i, req; + MV_U32 descOffsetReg, configReg; + MV_CESA_SRAM_SA *pSramSA; + + + mvOsPrintf("mvCesaInit: sessions=%d, queue=%d, pSram=%p\n", + numOfSession, queueDepth, pSramBase); + + cesaOsHandle = osHandle; + /* Create Session database */ + pCesaSAD = mvOsMalloc(sizeof(MV_CESA_SA)*numOfSession); + if(pCesaSAD == NULL) + { + mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d SAs\n", + sizeof(MV_CESA_SA)*numOfSession, numOfSession); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(pCesaSAD, 0, sizeof(MV_CESA_SA)*numOfSession); + cesaMaxSA = numOfSession; + + /* Allocate imag of sramSA in the DRAM */ + cesaSramSaBuf.bufSize = sizeof(MV_CESA_SRAM_SA)*numOfSession + + CPU_D_CACHE_LINE_SIZE; + + cesaSramSaBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle,cesaSramSaBuf.bufSize, + &cesaSramSaBuf.bufPhysAddr, + &cesaSramSaBuf.memHandle); + + if(cesaSramSaBuf.bufVirtPtr == NULL) + { + mvOsPrintf("mvCesaInit: Can't allocate %d bytes for sramSA structures\n", + cesaSramSaBuf.bufSize); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(cesaSramSaBuf.bufVirtPtr, 0, cesaSramSaBuf.bufSize); + pSramSA = (MV_CESA_SRAM_SA*)MV_ALIGN_UP((MV_ULONG)cesaSramSaBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + for(i=0; icesaDescBuf.bufSize = sizeof(MV_CESA_DESC)*MV_CESA_MAX_REQ_FRAGS + + CPU_D_CACHE_LINE_SIZE; + + pReq->cesaDescBuf.bufVirtPtr = + mvOsIoCachedMalloc(osHandle,pReq->cesaDescBuf.bufSize, + &pReq->cesaDescBuf.bufPhysAddr, + &pReq->cesaDescBuf.memHandle); + + if(pReq->cesaDescBuf.bufVirtPtr == NULL) + { + mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for CESA descriptors\n", + req, pReq->cesaDescBuf.bufSize); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(pReq->cesaDescBuf.bufVirtPtr, 0, pReq->cesaDescBuf.bufSize); + pReq->pCesaDesc = (MV_CESA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->cesaDescBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + pReq->dmaDescBuf.bufSize = sizeof(MV_DMA_DESC)*MV_CESA_MAX_DMA_DESC*MV_CESA_MAX_REQ_FRAGS + + CPU_D_CACHE_LINE_SIZE; + + pReq->dmaDescBuf.bufVirtPtr = + mvOsIoCachedMalloc(osHandle,pReq->dmaDescBuf.bufSize, + &pReq->dmaDescBuf.bufPhysAddr, + &pReq->dmaDescBuf.memHandle); + + if(pReq->dmaDescBuf.bufVirtPtr == NULL) + { + mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for DMA descriptor list\n", + req, pReq->dmaDescBuf.bufSize); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(pReq->dmaDescBuf.bufVirtPtr, 0, pReq->dmaDescBuf.bufSize); + pDmaDesc = (MV_DMA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->dmaDescBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + for(frag=0; fragdma[frag]; + + pDma->pDmaFirst = pDmaDesc; + pDma->pDmaLast = NULL; + + for(i=0; ipDmaFirst[i].phyNextDescPtr = + MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pDmaDesc[i+1])); + } + pDma->pDmaFirst[i].phyNextDescPtr = 0; + mvOsCacheFlush(NULL, &pDma->pDmaFirst[0], MV_CESA_MAX_DMA_DESC*sizeof(MV_DMA_DESC)); + + pDmaDesc += MV_CESA_MAX_DMA_DESC; + } + } + /*mvCesaCryptoIvSet(NULL, MV_CESA_MAX_IV_LENGTH);*/ + descOffsetReg = (MV_U16)((MV_U8*)&cesaSramVirtPtr->desc - mvCesaSramAddrGet()); + MV_REG_WRITE(MV_CESA_CHAN_DESC_OFFSET_REG, descOffsetReg); + + configReg |= (MV_CESA_CFG_WAIT_DMA_MASK | MV_CESA_CFG_ACT_DMA_MASK); + +#if (MV_CESA_VERSION >= 2) + /* Initialize TDMA engine */ + MV_REG_WRITE(MV_CESA_TDMA_CTRL_REG, MV_CESA_TDMA_CTRL_VALUE); + MV_REG_WRITE(MV_CESA_TDMA_BYTE_COUNT_REG, 0); + MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0); +#else + /* Initialize IDMA #0 engine */ + MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0); + MV_REG_WRITE(IDMA_BYTE_COUNT_REG(0), 0); + MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0); + MV_REG_WRITE(IDMA_CTRL_HIGH_REG(0), ICCHR_ENDIAN_LITTLE +#ifdef MV_CPU_LE + | ICCHR_DESC_BYTE_SWAP_EN +#endif + ); + /* Clear Cause Byte of IDMA channel to be used */ + MV_REG_WRITE( IDMA_CAUSE_REG, ~ICICR_CAUSE_MASK_ALL(0)); + MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), MV_CESA_IDMA_CTRL_LOW_VALUE); +#endif /* (MV_CESA_VERSION >= 2) */ + + /* Set CESA configuration registers */ + MV_REG_WRITE( MV_CESA_CFG_REG, configReg); + mvCesaDebugStatsClear(); + + return MV_OK; +} + +/******************************************************************************* +* mvCesaFinish - Shutdown the CESA driver +* +* DESCRIPTION: +* This function shutdown the CESA driver and free all allocted resources. +* +* INPUT: None +* +* RETURN: +* MV_OK - Success +* Other - Fail +* +*******************************************************************************/ +MV_STATUS mvCesaFinish (void) +{ + int req; + MV_CESA_REQ* pReq; + + mvOsPrintf("mvCesaFinish: \n"); + + cesaSramVirtPtr = NULL; + + /* Free all resources: DMA list, etc. */ + for(req=0; reqdmaDescBuf.bufVirtPtr != NULL) + { + mvOsIoCachedFree(cesaOsHandle,pReq->dmaDescBuf.bufSize, + pReq->dmaDescBuf.bufPhysAddr, + pReq->dmaDescBuf.bufVirtPtr, + pReq->dmaDescBuf.memHandle); + } + if(pReq->cesaDescBuf.bufVirtPtr != NULL) + { + mvOsIoCachedFree(cesaOsHandle,pReq->cesaDescBuf.bufSize, + pReq->cesaDescBuf.bufPhysAddr, + pReq->cesaDescBuf.bufVirtPtr, + pReq->cesaDescBuf.memHandle); + } + } +#if (MV_CESA_VERSION < 2) + MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0); +#endif /* (MV_CESA_VERSION < 2) */ + + /* Free request queue */ + if(pCesaReqFirst != NULL) + { + mvOsFree(pCesaReqFirst); + pCesaReqFirst = pCesaReqLast = NULL; + pCesaReqEmpty = pCesaReqProcess = NULL; + cesaQueueDepth = cesaReqResources = 0; + } + /* Free SA database */ + if(pCesaSAD != NULL) + { + mvOsFree(pCesaSAD); + pCesaSAD = NULL; + cesaMaxSA = 0; + } + MV_REG_WRITE( MV_CESA_CFG_REG, 0); + MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0); + MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0); + + return MV_OK; +} + +/******************************************************************************* +* mvCesaCryptoIvSet - Set IV value for Crypto algorithm working in CBC mode +* +* DESCRIPTION: +* This function set IV value using by Crypto algorithms in CBC mode. +* Each channel has its own IV value. +* This function gets IV value from the caller. If no IV value passed from +* the caller or only part of IV passed, the function will init the rest part +* of IV value (or the whole IV) by random value. +* +* INPUT: +* MV_U8* pIV - Pointer to IV value supplied by user. If pIV==NULL +* the function will generate random IV value. +* int ivSize - size (in bytes) of IV provided by user. If ivSize is +* smaller than maximum IV size, the function will complete +* IV by random value. +* +* RETURN: +* MV_OK - Success +* Other - Fail +* +*******************************************************************************/ +MV_STATUS mvCesaCryptoIvSet(MV_U8* pIV, int ivSize) +{ + MV_U8* pSramIV; +#if defined(MV646xx) + mvOsPrintf("mvCesaCryptoIvSet: ERR. shouldn't use this call on MV64660\n"); +#endif + pSramIV = cesaSramVirtPtr->cryptoIV; + if(ivSize > MV_CESA_MAX_IV_LENGTH) + { + mvOsPrintf("mvCesaCryptoIvSet: ivSize (%d) is too large\n", ivSize); + ivSize = MV_CESA_MAX_IV_LENGTH; + } + if(pIV != NULL) + { + memcpy(pSramIV, pIV, ivSize); + ivSize = MV_CESA_MAX_IV_LENGTH - ivSize; + pSramIV += ivSize; + } + + while(ivSize > 0) + { + int size, mv_random = mvOsRand(); + + size = MV_MIN(ivSize, sizeof(mv_random)); + memcpy(pSramIV, (void*)&mv_random, size); + + pSramIV += size; + ivSize -= size; + } +/* + mvOsCacheFlush(NULL, cesaSramVirtPtr->cryptoIV, + MV_CESA_MAX_IV_LENGTH); + mvOsCacheInvalidate(NULL, cesaSramVirtPtr->cryptoIV, + MV_CESA_MAX_IV_LENGTH); +*/ + return MV_OK; +} + +/******************************************************************************* +* mvCesaSessionOpen - Open new uni-directional crypto session +* +* DESCRIPTION: +* This function open new session. +* +* INPUT: +* MV_CESA_OPEN_SESSION *pSession - pointer to new session input parameters +* +* OUTPUT: +* short *pSid - session ID, should be used for all future +* requests over this session. +* +* RETURN: +* MV_OK - Session opend successfully. +* MV_FULL - All sessions are in use, no free place in +* SA database. +* MV_BAD_PARAM - One of session input parameters is invalid. +* +*******************************************************************************/ +MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short* pSid) +{ + short sid; + MV_U32 config = 0; + int digestSize; + + cesaStats.openedCount++; + + /* Find free entry in SAD */ + for(sid=0; sidoperation >= MV_CESA_MAX_OPERATION) + { + mvOsPrintf("mvCesaSessionOpen: Unexpected operation %d\n", + pSession->operation); + return MV_BAD_PARAM; + } + config |= (pSession->operation << MV_CESA_OPERATION_OFFSET); + + if( (pSession->direction != MV_CESA_DIR_ENCODE) && + (pSession->direction != MV_CESA_DIR_DECODE) ) + { + mvOsPrintf("mvCesaSessionOpen: Unexpected direction %d\n", + pSession->direction); + return MV_BAD_PARAM; + } + config |= (pSession->direction << MV_CESA_DIRECTION_BIT); + /* Clear SA entry */ + /* memset(&pCesaSAD[sid], 0, sizeof(pCesaSAD[sid])); */ + + /* Check AUTH parameters and update SA entry */ + if(pSession->operation != MV_CESA_CRYPTO_ONLY) + { + /* For HMAC (MD5 and SHA1) - Maximum Key size is 64 bytes */ + if( (pSession->macMode == MV_CESA_MAC_HMAC_MD5) || + (pSession->macMode == MV_CESA_MAC_HMAC_SHA1) ) + { + if(pSession->macKeyLength > MV_CESA_MAX_MAC_KEY_LENGTH) + { + mvOsPrintf("mvCesaSessionOpen: macKeyLength %d is too large\n", + pSession->macKeyLength); + return MV_BAD_PARAM; + } + mvCesaHmacIvGet(pSession->macMode, pSession->macKey, pSession->macKeyLength, + pCesaSAD[sid].pSramSA->macInnerIV, + pCesaSAD[sid].pSramSA->macOuterIV); + pCesaSAD[sid].macKeyLength = pSession->macKeyLength; + } + switch(pSession->macMode) + { + case MV_CESA_MAC_MD5: + case MV_CESA_MAC_HMAC_MD5: + digestSize = MV_CESA_MD5_DIGEST_SIZE; + break; + + case MV_CESA_MAC_SHA1: + case MV_CESA_MAC_HMAC_SHA1: + digestSize = MV_CESA_SHA1_DIGEST_SIZE; + break; + + default: + mvOsPrintf("mvCesaSessionOpen: Unexpected macMode %d\n", + pSession->macMode); + return MV_BAD_PARAM; + } + config |= (pSession->macMode << MV_CESA_MAC_MODE_OFFSET); + + /* Supported digest sizes: MD5 - 16 bytes (128 bits), */ + /* SHA1 - 20 bytes (160 bits) or 12 bytes (96 bits) for both */ + if( (pSession->digestSize != digestSize) && (pSession->digestSize != 12)) + { + mvOsPrintf("mvCesaSessionOpen: Unexpected digest size %d\n", + pSession->digestSize); + mvOsPrintf("\t Valid values [bytes]: MD5-16, SHA1-20, Both-12\n"); + return MV_BAD_PARAM; + } + pCesaSAD[sid].digestSize = pSession->digestSize; + + if(pCesaSAD[sid].digestSize == 12) + { + /* Set MV_CESA_MAC_DIGEST_SIZE_BIT if digest size is 96 bits */ + config |= (MV_CESA_MAC_DIGEST_96B << MV_CESA_MAC_DIGEST_SIZE_BIT); + } + } + + /* Check CRYPTO parameters and update SA entry */ + if(pSession->operation != MV_CESA_MAC_ONLY) + { + switch(pSession->cryptoAlgorithm) + { + case MV_CESA_CRYPTO_DES: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_DES_KEY_LENGTH; + pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE; + break; + + case MV_CESA_CRYPTO_3DES: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_3DES_KEY_LENGTH; + pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE; + /* Only EDE mode is supported */ + config |= (MV_CESA_CRYPTO_3DES_EDE << + MV_CESA_CRYPTO_3DES_MODE_BIT); + break; + + case MV_CESA_CRYPTO_AES: + switch(pSession->cryptoKeyLength) + { + case 16: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_128_KEY_LENGTH; + config |= (MV_CESA_CRYPTO_AES_KEY_128 << + MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET); + break; + + case 24: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_192_KEY_LENGTH; + config |= (MV_CESA_CRYPTO_AES_KEY_192 << + MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET); + break; + + case 32: + default: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_256_KEY_LENGTH; + config |= (MV_CESA_CRYPTO_AES_KEY_256 << + MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET); + break; + } + pCesaSAD[sid].cryptoBlockSize = MV_CESA_AES_BLOCK_SIZE; + break; + + default: + mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoAlgorithm %d\n", + pSession->cryptoAlgorithm); + return MV_BAD_PARAM; + } + config |= (pSession->cryptoAlgorithm << MV_CESA_CRYPTO_ALG_OFFSET); + + if(pSession->cryptoKeyLength != pCesaSAD[sid].cryptoKeyLength) + { + mvOsPrintf("cesaSessionOpen: Wrong CryptoKeySize %d != %d\n", + pSession->cryptoKeyLength, pCesaSAD[sid].cryptoKeyLength); + return MV_BAD_PARAM; + } + + /* Copy Crypto key */ + if( (pSession->cryptoAlgorithm == MV_CESA_CRYPTO_AES) && + (pSession->direction == MV_CESA_DIR_DECODE)) + { + /* Crypto Key for AES decode is computed from original key material */ + /* and depend on cryptoKeyLength (128/192/256 bits) */ + aesMakeKey(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey, + pSession->cryptoKeyLength*8, MV_CESA_AES_BLOCK_SIZE*8); + } + else + { + /*panic("mvCesaSessionOpen2");*/ + memcpy(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey, + pCesaSAD[sid].cryptoKeyLength); + + } + + switch(pSession->cryptoMode) + { + case MV_CESA_CRYPTO_ECB: + pCesaSAD[sid].cryptoIvSize = 0; + break; + + case MV_CESA_CRYPTO_CBC: + pCesaSAD[sid].cryptoIvSize = pCesaSAD[sid].cryptoBlockSize; + break; + + case MV_CESA_CRYPTO_CTR: + /* Supported only for AES algorithm */ + if(pSession->cryptoAlgorithm != MV_CESA_CRYPTO_AES) + { + mvOsPrintf("mvCesaSessionOpen: CRYPTO CTR mode supported for AES only\n"); + return MV_BAD_PARAM; + } + pCesaSAD[sid].cryptoIvSize = 0; + pCesaSAD[sid].ctrMode = 1; + /* Replace to ECB mode for HW */ + pSession->cryptoMode = MV_CESA_CRYPTO_ECB; + break; + + default: + mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoMode %d\n", + pSession->cryptoMode); + return MV_BAD_PARAM; + } + + config |= (pSession->cryptoMode << MV_CESA_CRYPTO_MODE_BIT); + } + pCesaSAD[sid].config = config; + + mvOsCacheFlush(NULL, pCesaSAD[sid].pSramSA, sizeof(MV_CESA_SRAM_SA)); + if(pSid != NULL) + *pSid = sid; + + pCesaSAD[sid].valid = 1; + return MV_OK; +} + +/******************************************************************************* +* mvCesaSessionClose - Close active crypto session +* +* DESCRIPTION: +* This function closes existing session +* +* INPUT: +* short sid - Unique identifier of the session to be closed +* +* RETURN: +* MV_OK - Session closed successfully. +* MV_BAD_PARAM - Session identifier is out of valid range. +* MV_NOT_FOUND - There is no active session with such ID. +* +*******************************************************************************/ +MV_STATUS mvCesaSessionClose(short sid) +{ + cesaStats.closedCount++; + + if(sid >= cesaMaxSA) + { + mvOsPrintf("CESA Error: sid (%d) is too big\n", sid); + return MV_BAD_PARAM; + } + if(pCesaSAD[sid].valid == 0) + { + mvOsPrintf("CESA Warning: Session (sid=%d) is invalid\n", sid); + return MV_NOT_FOUND; + } + if(cesaLastSid == sid) + cesaLastSid = -1; + + pCesaSAD[sid].valid = 0; + return MV_OK; +} + +/******************************************************************************* +* mvCesaAction - Perform crypto operation +* +* DESCRIPTION: +* This function set new CESA request FIFO queue for further HW processing. +* The function checks request parameters before set new request to the queue. +* If one of the CESA channels is ready for processing the request will be +* passed to HW. When request processing is finished the CESA interrupt will +* be generated by HW. The caller should call mvCesaReadyGet() function to +* complete request processing and get result. +* +* INPUT: +* MV_CESA_COMMAND *pCmd - pointer to new CESA request. +* It includes pointers to Source and Destination +* buffers, session identifier get from +* mvCesaSessionOpen() function, pointer to caller +* private data and all needed crypto parameters. +* +* RETURN: +* MV_OK - request successfully added to request queue +* and will be processed. +* MV_NO_MORE - request successfully added to request queue and will +* be processed, but request queue became Full and next +* request will not be accepted. +* MV_NO_RESOURCE - request queue is FULL and the request can not +* be processed. +* MV_OUT_OF_CPU_MEM - memory allocation needed for request processing is +* failed. Request can not be processed. +* MV_NOT_ALLOWED - This mixed request (CRYPTO+MAC) can not be processed +* as one request and should be splitted for two requests: +* CRYPTO_ONLY and MAC_ONLY. +* MV_BAD_PARAM - One of the request parameters is out of valid range. +* The request can not be processed. +* +*******************************************************************************/ +MV_STATUS mvCesaAction (MV_CESA_COMMAND *pCmd) +{ + MV_STATUS status; + MV_CESA_REQ* pReq = pCesaReqEmpty; + int sid = pCmd->sessionId; + MV_CESA_SA* pSA = &pCesaSAD[sid]; + + cesaStats.reqCount++; + + /* Check that the request queue is not FULL */ + if(cesaReqResources == 0) + return MV_NO_RESOURCE; + + if( (sid >= cesaMaxSA) || (!pSA->valid) ) + { + mvOsPrintf("CESA Action Error: Session sid=%d is INVALID\n", sid); + return MV_BAD_PARAM; + } + pSA->count++; + + if(pSA->ctrMode) + { + /* AES in CTR mode can't be mixed with Authentication */ + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + mvOsPrintf("mvCesaAction : CRYPTO CTR mode can't be mixed with AUTH\n"); + return MV_NOT_ALLOWED; + } + /* All other request parameters should not be checked because key stream */ + /* (not user data) processed by AES HW engine */ + pReq->pOrgCmd = pCmd; + /* Allocate temporary pCmd structure for Key stream */ + pCmd = mvCesaCtrModeInit(); + if(pCmd == NULL) + return MV_OUT_OF_CPU_MEM; + + /* Prepare Key stream */ + mvCesaCtrModePrepare(pCmd, pReq->pOrgCmd); + pReq->fixOffset = 0; + } + else + { + /* Check request parameters and calculae fixOffset */ + status = mvCesaParamCheck(pSA, pCmd, &pReq->fixOffset); + if(status != MV_OK) + { + return status; + } + } + pReq->pCmd = pCmd; + + /* Check if the packet need fragmentation */ + if(pCmd->pSrc->mbufSize <= sizeof(cesaSramVirtPtr->buf) ) + { + /* request size is smaller than single buffer size */ + pReq->fragMode = MV_CESA_FRAG_NONE; + + /* Prepare NOT fragmented packets */ + status = mvCesaReqProcess(pReq); + if(status != MV_OK) + { + mvOsPrintf("CesaReady: ReqProcess error: pReq=%p, status=0x%x\n", + pReq, status); + } + } + else + { + MV_U8 frag = 0; + + /* request size is larger than buffer size - needs fragmentation */ + + /* Check restrictions for processing fragmented packets */ + status = mvCesaFragParamCheck(pSA, pCmd); + if(status != MV_OK) + return status; + + pReq->fragMode = MV_CESA_FRAG_FIRST; + pReq->frags.nextFrag = 0; + + /* Prepare Process Fragmented packets */ + while(pReq->fragMode != MV_CESA_FRAG_LAST) + { + if(frag >= MV_CESA_MAX_REQ_FRAGS) + { + mvOsPrintf("mvCesaAction Error: Too large request frag=%d\n", frag); + return MV_OUT_OF_CPU_MEM; + } + status = mvCesaFragReqProcess(pReq, frag); + if(status == MV_OK) + frag++; + } + pReq->frags.numFrag = frag; + } + + pReq->state = MV_CESA_PENDING; + + pCesaReqEmpty = MV_CESA_REQ_NEXT_PTR(pReq); + cesaReqResources -= 1; + +/* #ifdef CESA_DEBUG */ + if( (cesaQueueDepth - cesaReqResources) > cesaStats.maxReqCount) + cesaStats.maxReqCount = (cesaQueueDepth - cesaReqResources); +/* #endif CESA_DEBUG */ + + cesaLastSid = sid; + + /* Check status of CESA channels and process requests if possible */ + pReq = pCesaReqProcess; + if(pReq->state == MV_CESA_PENDING) + { + /* Start Process new request */ + mvCesaReqProcessStart(pReq); + } + /* If request queue became FULL - return MV_NO_MORE */ + if(cesaReqResources == 0) + return MV_NO_MORE; + + return MV_OK; +} + +/******************************************************************************* +* mvCesaReadyGet - Get crypto request that processing is finished +* +* DESCRIPTION: +* This function complete request processing and return ready request to +* caller. To don't miss interrupts the caller must call this function +* while MV_OK or MV_TERMINATE values returned. +* +* INPUT: +* MV_U32 chanMap - map of CESA channels finished thier job +* accordingly with CESA Cause register. +* MV_CESA_RESULT* pResult - pointer to structure contains information +* about ready request. It includes pointer to +* user private structure "pReqPrv", session identifier +* for this request "sessionId" and return code. +* Return code set to MV_FAIL if calculated digest value +* on decode direction is different than digest value +* in the packet. +* +* RETURN: +* MV_OK - Success, ready request is returned. +* MV_NOT_READY - Next request is not ready yet. New interrupt will +* be generated for futher request processing. +* MV_EMPTY - There is no more request for processing. +* MV_BUSY - Fragmented request is not ready yet. +* MV_TERMINATE - Call this function once more to complete processing +* of fragmented request. +* +*******************************************************************************/ +MV_STATUS mvCesaReadyGet(MV_CESA_RESULT* pResult) +{ + MV_STATUS status, readyStatus = MV_NOT_READY; + MV_U32 statusReg; + MV_CESA_REQ* pReq; + MV_CESA_SA* pSA; + + /* Check if there are request in process */ + if(pCesaReqProcess->state != MV_CESA_PROCESS) + { + return MV_EMPTY; + } + +#ifdef CESA_DEBUG + statusReg = MV_REG_READ(MV_CESA_STATUS_REG); + if( statusReg & MV_CESA_STATUS_ACTIVE_MASK ) + { + mvOsPrintf("mvCesaReadyGet: Not Ready, Status = 0x%x\n", statusReg); + cesaStats.notReadyCount++; + return MV_NOT_READY; + } +#endif /* CESA_DEBUG */ + + cesaStats.readyCount++; + + pReq = pCesaReqProcess; + pSA = &pCesaSAD[pReq->pCmd->sessionId]; + + pResult->retCode = MV_OK; + if(pReq->fragMode != MV_CESA_FRAG_NONE) + { + MV_U8* pNewDigest; + int frag = (pReq->frags.nextFrag - 1); + + /* Restore DMA descriptor list */ + pReq->dma[frag].pDmaLast->phyNextDescPtr = + MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[frag].pDmaLast[1])); + pReq->dma[frag].pDmaLast = NULL; + + /* Special processing for finished fragmented request */ + if(pReq->frags.nextFrag >= pReq->frags.numFrag) + { + /* Fragmented packet is ready */ + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + int macDataSize = pReq->pCmd->macLength - pReq->frags.macSize; + + if(macDataSize != 0) + { + /* Calculate all other blocks by SW */ + mvCesaFragAuthComplete(pReq, pSA, macDataSize); + } + + /* Copy new digest from SRAM to the Destination buffer */ + pNewDigest = cesaSramVirtPtr->buf + pReq->frags.newDigestOffset; + status = mvCesaCopyToMbuf(pNewDigest, pReq->pCmd->pDst, + pReq->pCmd->digestOffset, pSA->digestSize); + + /* For decryption: Compare new digest value with original one */ + if((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) + { + if( memcmp(pNewDigest, pReq->frags.orgDigest, pSA->digestSize) != 0) + { +/* + mvOsPrintf("Digest error: chan=%d, newDigest=%p, orgDigest=%p, status = 0x%x\n", + chan, pNewDigest, pReq->frags.orgDigest, MV_REG_READ(MV_CESA_STATUS_REG)); +*/ + /* Signiture verification is failed */ + pResult->retCode = MV_FAIL; + } + } + } + readyStatus = MV_OK; + } + } + else + { + /* Restore DMA descriptor list */ + pReq->dma[0].pDmaLast->phyNextDescPtr = + MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[0].pDmaLast[1])); + pReq->dma[0].pDmaLast = NULL; + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) && + ((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) ) + { + /* For AUTH on decode : Check Digest result in Status register */ + statusReg = MV_REG_READ(MV_CESA_STATUS_REG); + if(statusReg & MV_CESA_STATUS_DIGEST_ERR_MASK) + { +/* + mvOsPrintf("Digest error: chan=%d, status = 0x%x\n", + chan, statusReg); +*/ + /* Signiture verification is failed */ + pResult->retCode = MV_FAIL; + } + } + readyStatus = MV_OK; + } + + if(readyStatus == MV_OK) + { + /* If Request is ready - Prepare pResult structure */ + pResult->pReqPrv = pReq->pCmd->pReqPrv; + pResult->sessionId = pReq->pCmd->sessionId; + + pReq->state = MV_CESA_IDLE; + pCesaReqProcess = MV_CESA_REQ_NEXT_PTR(pReq); + cesaReqResources++; + + if(pSA->ctrMode) + { + /* For AES CTR mode - complete processing and free allocated resources */ + mvCesaCtrModeComplete(pReq->pOrgCmd, pReq->pCmd); + mvCesaCtrModeFinish(pReq->pCmd); + pReq->pOrgCmd = NULL; + } + } + + if(pCesaReqProcess->state == MV_CESA_PROCESS) + { + /* Start request Process */ + mvCesaReqProcessStart(pCesaReqProcess); + if(readyStatus == MV_NOT_READY) + readyStatus = MV_BUSY; + } + else if(pCesaReqProcess != pCesaReqEmpty) + { + /* Start process new request from the queue */ + mvCesaReqProcessStart(pCesaReqProcess); + } + return readyStatus; +} + +/***************** Functions to work with CESA_MBUF structure ******************/ + +/******************************************************************************* +* mvCesaMbufOffset - Locate offset in the Mbuf structure +* +* DESCRIPTION: +* This function locates offset inside Multi-Bufeer structure. +* It get fragment number and place in the fragment where the offset +* is located. +* +* +* INPUT: +* MV_CESA_MBUF* pMbuf - Pointer to multi-buffer structure +* int offset - Offset from the beginning of the data presented by +* the Mbuf structure. +* +* OUTPUT: +* int* pBufOffset - Offset from the beginning of the fragment where +* the offset is located. +* +* RETURN: +* int - Number of fragment, where the offset is located\ +* +*******************************************************************************/ +int mvCesaMbufOffset(MV_CESA_MBUF* pMbuf, int offset, int* pBufOffset) +{ + int frag = 0; + + while(offset > 0) + { + if(frag >= pMbuf->numFrags) + { + mvOsPrintf("mvCesaMbufOffset: Error: frag (%d) > numFrags (%d)\n", + frag, pMbuf->numFrags); + return MV_INVALID; + } + if(offset < pMbuf->pFrags[frag].bufSize) + { + break; + } + offset -= pMbuf->pFrags[frag].bufSize; + frag++; + } + if(pBufOffset != NULL) + *pBufOffset = offset; + + return frag; +} + +/******************************************************************************* +* mvCesaCopyFromMbuf - Copy data from the Mbuf structure to continuous buffer +* +* DESCRIPTION: +* +* +* INPUT: +* MV_U8* pDstBuf - Pointer to continuous buffer, where data is +* copied to. +* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is +* copied from. +* int offset - Offset in the Mbuf structure where located first +* byte of data should be copied. +* int size - Size of data should be copied +* +* RETURN: +* MV_OK - Success, all data is copied successfully. +* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range. +* No data is copied. +* MV_EMPTY - Multi-buffer structure has not enough data to copy +* Data from the offset to end of Mbuf data is copied. +* +*******************************************************************************/ +MV_STATUS mvCesaCopyFromMbuf(MV_U8* pDstBuf, MV_CESA_MBUF* pSrcMbuf, + int offset, int size) +{ + int frag, fragOffset, bufSize; + MV_U8* pBuf; + + if(size == 0) + return MV_OK; + + frag = mvCesaMbufOffset(pSrcMbuf, offset, &fragOffset); + if(frag == MV_INVALID) + { + mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset); + return MV_OUT_OF_RANGE; + } + + bufSize = pSrcMbuf->pFrags[frag].bufSize - fragOffset; + pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr + fragOffset; + while(MV_TRUE) + { + if(size <= bufSize) + { + memcpy(pDstBuf, pBuf, size); + return MV_OK; + } + memcpy(pDstBuf, pBuf, bufSize); + size -= bufSize; + frag++; + pDstBuf += bufSize; + if(frag >= pSrcMbuf->numFrags) + break; + + bufSize = pSrcMbuf->pFrags[frag].bufSize; + pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr; + } + mvOsPrintf("mvCesaCopyFromMbuf: Mbuf is EMPTY - %d bytes isn't copied\n", + size); + return MV_EMPTY; +} + +/******************************************************************************* +* mvCesaCopyToMbuf - Copy data from continuous buffer to the Mbuf structure +* +* DESCRIPTION: +* +* +* INPUT: +* MV_U8* pSrcBuf - Pointer to continuous buffer, where data is +* copied from. +* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is +* copied to. +* int offset - Offset in the Mbuf structure where located first +* byte of data should be copied. +* int size - Size of data should be copied +* +* RETURN: +* MV_OK - Success, all data is copied successfully. +* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range. +* No data is copied. +* MV_FULL - Multi-buffer structure has not enough place to copy +* all data. Data from the offset to end of Mbuf data +* is copied. +* +*******************************************************************************/ +MV_STATUS mvCesaCopyToMbuf(MV_U8* pSrcBuf, MV_CESA_MBUF* pDstMbuf, + int offset, int size) +{ + int frag, fragOffset, bufSize; + MV_U8* pBuf; + + if(size == 0) + return MV_OK; + + frag = mvCesaMbufOffset(pDstMbuf, offset, &fragOffset); + if(frag == MV_INVALID) + { + mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset); + return MV_OUT_OF_RANGE; + } + + bufSize = pDstMbuf->pFrags[frag].bufSize - fragOffset; + pBuf = pDstMbuf->pFrags[frag].bufVirtPtr + fragOffset; + while(MV_TRUE) + { + if(size <= bufSize) + { + memcpy(pBuf, pSrcBuf, size); + return MV_OK; + } + memcpy(pBuf, pSrcBuf, bufSize); + size -= bufSize; + frag++; + pSrcBuf += bufSize; + if(frag >= pDstMbuf->numFrags) + break; + + bufSize = pDstMbuf->pFrags[frag].bufSize; + pBuf = pDstMbuf->pFrags[frag].bufVirtPtr; + } + mvOsPrintf("mvCesaCopyToMbuf: Mbuf is FULL - %d bytes isn't copied\n", + size); + return MV_FULL; +} + +/******************************************************************************* +* mvCesaMbufCopy - Copy data from one Mbuf structure to the other Mbuf structure +* +* DESCRIPTION: +* +* +* INPUT: +* +* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is +* copied to. +* int dstMbufOffset - Offset in the dstMbuf structure where first byte +* of data should be copied to. +* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is +* copied from. +* int srcMbufOffset - Offset in the srcMbuf structure where first byte +* of data should be copied from. +* int size - Size of data should be copied +* +* RETURN: +* MV_OK - Success, all data is copied successfully. +* MV_OUT_OF_RANGE - Failed, srcMbufOffset or dstMbufOffset is out of +* srcMbuf or dstMbuf structure correspondently. +* No data is copied. +* MV_BAD_SIZE - srcMbuf or dstMbuf structure is too small to copy +* all data. Partial data is copied +* +*******************************************************************************/ +MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF* pMbufDst, int dstMbufOffset, + MV_CESA_MBUF* pMbufSrc, int srcMbufOffset, int size) +{ + int srcFrag, dstFrag, srcSize, dstSize, srcOffset, dstOffset; + int copySize; + MV_U8 *pSrc, *pDst; + + if(size == 0) + return MV_OK; + + srcFrag = mvCesaMbufOffset(pMbufSrc, srcMbufOffset, &srcOffset); + if(srcFrag == MV_INVALID) + { + mvOsPrintf("CESA srcMbuf Error: offset (%d) out of range\n", srcMbufOffset); + return MV_OUT_OF_RANGE; + } + pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr + srcOffset; + srcSize = pMbufSrc->pFrags[srcFrag].bufSize - srcOffset; + + dstFrag = mvCesaMbufOffset(pMbufDst, dstMbufOffset, &dstOffset); + if(dstFrag == MV_INVALID) + { + mvOsPrintf("CESA dstMbuf Error: offset (%d) out of range\n", dstMbufOffset); + return MV_OUT_OF_RANGE; + } + pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr + dstOffset; + dstSize = pMbufDst->pFrags[dstFrag].bufSize - dstOffset; + + while(size > 0) + { + copySize = MV_MIN(srcSize, dstSize); + if(size <= copySize) + { + memcpy(pDst, pSrc, size); + return MV_OK; + } + memcpy(pDst, pSrc, copySize); + size -= copySize; + srcSize -= copySize; + dstSize -= copySize; + + if(srcSize == 0) + { + srcFrag++; + if(srcFrag >= pMbufSrc->numFrags) + break; + + pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr; + srcSize = pMbufSrc->pFrags[srcFrag].bufSize; + } + + if(dstSize == 0) + { + dstFrag++; + if(dstFrag >= pMbufDst->numFrags) + break; + + pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr; + dstSize = pMbufDst->pFrags[dstFrag].bufSize; + } + } + mvOsPrintf("mvCesaMbufCopy: BAD size - %d bytes isn't copied\n", + size); + + return MV_BAD_SIZE; +} + +/*************************************** Local Functions ******************************/ + +/******************************************************************************* +* mvCesaFragReqProcess - Process fragmented request +* +* DESCRIPTION: +* This function processes a fragment of fragmented request (First, Middle or Last) +* +* +* INPUT: +* MV_CESA_REQ* pReq - Pointer to the request in the request queue. +* +* RETURN: +* MV_OK - The fragment is successfully passed to HW for processing. +* MV_TERMINATE - Means, that HW finished its work on this packet and no more +* interrupts will be generated for this request. +* Function mvCesaReadyGet() must be called to complete request +* processing and get request result. +* +*******************************************************************************/ +static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag) +{ + int i, copySize, cryptoDataSize, macDataSize, sid; + int cryptoIvOffset, digestOffset; + MV_U32 config; + MV_CESA_COMMAND* pCmd = pReq->pCmd; + MV_CESA_SA* pSA; + MV_CESA_MBUF* pMbuf; + MV_DMA_DESC* pDmaDesc = pReq->dma[frag].pDmaFirst; + MV_U8* pSramBuf = cesaSramVirtPtr->buf; + int macTotalLen = 0; + int fixOffset, cryptoOffset, macOffset; + + cesaStats.fragCount++; + + sid = pReq->pCmd->sessionId; + + pSA = &pCesaSAD[sid]; + + cryptoIvOffset = digestOffset = 0; + i = macDataSize = 0; + cryptoDataSize = 0; + + /* First fragment processing */ + if(pReq->fragMode == MV_CESA_FRAG_FIRST) + { + /* pReq->frags monitors processing of fragmented request between fragments */ + pReq->frags.bufOffset = 0; + pReq->frags.cryptoSize = 0; + pReq->frags.macSize = 0; + + config = pSA->config | (MV_CESA_FRAG_FIRST << MV_CESA_FRAG_MODE_OFFSET); + + /* fixOffset can be not equal to zero only for FIRST fragment */ + fixOffset = pReq->fixOffset; + /* For FIRST fragment crypto and mac offsets are taken from pCmd */ + cryptoOffset = pCmd->cryptoOffset; + macOffset = pCmd->macOffset; + + copySize = sizeof(cesaSramVirtPtr->buf) - pReq->fixOffset; + + /* Find fragment size: Must meet all requirements for CRYPTO and MAC + * cryptoDataSize - size of data will be encrypted/decrypted in this fragment + * macDataSize - size of data will be signed/verified in this fragment + * copySize - size of data will be copied from srcMbuf to SRAM and + * back to dstMbuf for this fragment + */ + mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset, + ©Size, &cryptoDataSize, &macDataSize); + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) + { + /* CryptoIV special processing */ + if( (pSA->config & MV_CESA_CRYPTO_MODE_MASK) == + (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT) ) + { + /* In CBC mode for encode direction when IV from user */ + if( (pCmd->ivFromUser) && + ((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) ) + { + + /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer, + * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place + * in the buffer to SRAM IVPointer + */ + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i], + MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize); + } + + /* Special processing when IV is not located in the first fragment */ + if(pCmd->ivOffset > (copySize - pSA->cryptoIvSize)) + { + /* Prepare dummy place for cryptoIV in SRAM */ + cryptoIvOffset = cesaSramVirtPtr->tempCryptoIV - mvCesaSramAddrGet(); + + /* For Decryption: Copy IV value from pCmd->ivOffset to Special SRAM place */ + if((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) + { + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->tempCryptoIV, &pDmaDesc[i], + MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize); + } + else + { + /* For Encryption when IV is NOT from User: */ + /* Copy IV from SRAM to buffer (pCmd->ivOffset) */ + if(pCmd->ivFromUser == 0) + { + /* copy IV value from cryptoIV to Buffer (pCmd->ivOffset) */ + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i], + MV_TRUE, pCmd->ivOffset, pSA->cryptoIvSize); + } + } + } + else + { + cryptoIvOffset = pCmd->ivOffset; + } + } + } + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + /* MAC digest special processing on Decode direction */ + if((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) + { + /* Save digest from pCmd->digestOffset */ + mvCesaCopyFromMbuf(pReq->frags.orgDigest, + pCmd->pSrc, pCmd->digestOffset, pSA->digestSize); + + /* If pCmd->digestOffset is not located on the first */ + if(pCmd->digestOffset > (copySize - pSA->digestSize)) + { + MV_U8 digestZero[MV_CESA_MAX_DIGEST_SIZE]; + + /* Set zeros to pCmd->digestOffset (DRAM) */ + memset(digestZero, 0, MV_CESA_MAX_DIGEST_SIZE); + mvCesaCopyToMbuf(digestZero, pCmd->pSrc, pCmd->digestOffset, pSA->digestSize); + + /* Prepare dummy place for digest in SRAM */ + digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet(); + } + else + { + digestOffset = pCmd->digestOffset; + } + } + } + /* Update SA in SRAM */ + if(cesaLastSid != sid) + { + mvCesaSramSaUpdate(sid, &pDmaDesc[i]); + i++; + } + + pReq->fragMode = MV_CESA_FRAG_MIDDLE; + } + else + { + /* Continue fragment */ + fixOffset = 0; + cryptoOffset = 0; + macOffset = 0; + if( (pCmd->pSrc->mbufSize - pReq->frags.bufOffset) <= sizeof(cesaSramVirtPtr->buf)) + { + /* Last fragment */ + config = pSA->config | (MV_CESA_FRAG_LAST << MV_CESA_FRAG_MODE_OFFSET); + pReq->fragMode = MV_CESA_FRAG_LAST; + copySize = pCmd->pSrc->mbufSize - pReq->frags.bufOffset; + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + macDataSize = pCmd->macLength - pReq->frags.macSize; + + /* If pCmd->digestOffset is not located on last fragment */ + if(pCmd->digestOffset < pReq->frags.bufOffset) + { + /* Prepare dummy place for digest in SRAM */ + digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet(); + } + else + { + digestOffset = pCmd->digestOffset - pReq->frags.bufOffset; + } + pReq->frags.newDigestOffset = digestOffset; + macTotalLen = pCmd->macLength; + + /* HW can't calculate the Digest correctly for fragmented packets + * in the following cases: + * - MV88F5182 || + * - MV88F5181L when total macLength more that 16 Kbytes || + * - total macLength more that 64 Kbytes + */ + if( (mvCtrlModelGet() == MV_5182_DEV_ID) || + ( (mvCtrlModelGet() == MV_5181_DEV_ID) && + (mvCtrlRevGet() >= MV_5181L_A0_REV) && + (pCmd->macLength >= (1 << 14)) ) ) + { + return MV_TERMINATE; + } + } + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + cryptoDataSize = pCmd->cryptoLength - pReq->frags.cryptoSize; + } + + /* cryptoIvOffset - don't care */ + } + else + { + /* WA for MV88F5182 SHA1 and MD5 fragmentation mode */ + if( (mvCtrlModelGet() == MV_5182_DEV_ID) && + (((pSA->config & MV_CESA_MAC_MODE_MASK) == + (MV_CESA_MAC_MD5 << MV_CESA_MAC_MODE_OFFSET)) || + ((pSA->config & MV_CESA_MAC_MODE_MASK) == + (MV_CESA_MAC_SHA1 << MV_CESA_MAC_MODE_OFFSET))) ) + { + pReq->frags.newDigestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet(); + pReq->fragMode = MV_CESA_FRAG_LAST; + + return MV_TERMINATE; + } + /* Middle fragment */ + config = pSA->config | (MV_CESA_FRAG_MIDDLE << MV_CESA_FRAG_MODE_OFFSET); + copySize = sizeof(cesaSramVirtPtr->buf); + /* digestOffset and cryptoIvOffset - don't care */ + + /* Find fragment size */ + mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset, + ©Size, &cryptoDataSize, &macDataSize); + } + } + /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/ + pMbuf = pCmd->pSrc; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_FALSE, pReq->frags.bufOffset, copySize); + + /* Prepare CESA descriptor to copy from DRAM to SRAM by DMA */ + mvCesaSramDescrBuild(config, frag, + cryptoOffset + fixOffset, cryptoIvOffset + fixOffset, + cryptoDataSize, macOffset + fixOffset, + digestOffset + fixOffset, macDataSize, macTotalLen, + pReq, &pDmaDesc[i]); + i++; + + /* Add special descriptor Ownership for CPU */ + pDmaDesc[i].byteCnt = 0; + pDmaDesc[i].phySrcAdd = 0; + pDmaDesc[i].phyDestAdd = 0; + i++; + + /********* Prepare DMA descriptors to copy from SRAM to pDst *********/ + pMbuf = pCmd->pDst; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_TRUE, pReq->frags.bufOffset, copySize); + + /* Next field of Last DMA descriptor must be NULL */ + pDmaDesc[i-1].phyNextDescPtr = 0; + pReq->dma[frag].pDmaLast = &pDmaDesc[i-1]; + mvOsCacheFlush(NULL, pReq->dma[frag].pDmaFirst, + i*sizeof(MV_DMA_DESC)); + + /*mvCesaDebugDescriptor(&cesaSramVirtPtr->desc[frag]);*/ + + pReq->frags.bufOffset += copySize; + pReq->frags.cryptoSize += cryptoDataSize; + pReq->frags.macSize += macDataSize; + + return MV_OK; +} + + +/******************************************************************************* +* mvCesaReqProcess - Process regular (Non-fragmented) request +* +* DESCRIPTION: +* This function processes the whole (not fragmented) request +* +* INPUT: +* MV_CESA_REQ* pReq - Pointer to the request in the request queue. +* +* RETURN: +* MV_OK - The request is successfully passed to HW for processing. +* Other - Failure. The request will not be processed +* +*******************************************************************************/ +static MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq) +{ + MV_CESA_MBUF *pMbuf; + MV_DMA_DESC *pDmaDesc; + MV_U8 *pSramBuf; + int sid, i, fixOffset; + MV_CESA_SA *pSA; + MV_CESA_COMMAND *pCmd = pReq->pCmd; + + cesaStats.procCount++; + + sid = pCmd->sessionId; + pSA = &pCesaSAD[sid]; + pDmaDesc = pReq->dma[0].pDmaFirst; + pSramBuf = cesaSramVirtPtr->buf; + fixOffset = pReq->fixOffset; + +/* + mvOsPrintf("mvCesaReqProcess: sid=%d, pSA=%p, pDmaDesc=%p, pSramBuf=%p\n", + sid, pSA, pDmaDesc, pSramBuf); +*/ + i = 0; + + /* Crypto IV Special processing in CBC mode for Encryption direction */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) && + ((pSA->config & MV_CESA_CRYPTO_MODE_MASK) == (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT)) && + ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) && + (pCmd->ivFromUser) ) + { + /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer, + * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place + * in the buffer to SRAM IVPointer + */ + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i], + MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize); + } + + /* Update SA in SRAM */ + if(cesaLastSid != sid) + { + mvCesaSramSaUpdate(sid, &pDmaDesc[i]); + i++; + } + + /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/ + pMbuf = pCmd->pSrc; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_FALSE, 0, pMbuf->mbufSize); + + /* Prepare Security Accelerator descriptor to SRAM words 0 - 7 */ + mvCesaSramDescrBuild(pSA->config, 0, pCmd->cryptoOffset + fixOffset, + pCmd->ivOffset + fixOffset, pCmd->cryptoLength, + pCmd->macOffset + fixOffset, pCmd->digestOffset + fixOffset, + pCmd->macLength, pCmd->macLength, pReq, &pDmaDesc[i]); + i++; + + /* Add special descriptor Ownership for CPU */ + pDmaDesc[i].byteCnt = 0; + pDmaDesc[i].phySrcAdd = 0; + pDmaDesc[i].phyDestAdd = 0; + i++; + + /********* Prepare DMA descriptors to copy from SRAM to pDst *********/ + pMbuf = pCmd->pDst; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_TRUE, 0, pMbuf->mbufSize); + + /* Next field of Last DMA descriptor must be NULL */ + pDmaDesc[i-1].phyNextDescPtr = 0; + pReq->dma[0].pDmaLast = &pDmaDesc[i-1]; + mvOsCacheFlush(NULL, pReq->dma[0].pDmaFirst, i*sizeof(MV_DMA_DESC)); + + return MV_OK; +} + + +/******************************************************************************* +* mvCesaSramDescrBuild - Set CESA descriptor in SRAM +* +* DESCRIPTION: +* This function builds CESA descriptor in SRAM from all Command parameters +* +* +* INPUT: +* int chan - CESA channel uses the descriptor +* MV_U32 config - 32 bits of WORD_0 in CESA descriptor structure +* int cryptoOffset - Offset from the beginning of SRAM buffer where +* data for encryption/decription is started. +* int ivOffset - Offset of crypto IV from the SRAM base. Valid only +* for first fragment. +* int cryptoLength - Size (in bytes) of data for encryption/descryption +* operation on this fragment. +* int macOffset - Offset from the beginning of SRAM buffer where +* data for Authentication is started +* int digestOffset - Offset from the beginning of SRAM buffer where +* digest is located. Valid for first and last fragments. +* int macLength - Size (in bytes) of data for Authentication +* operation on this fragment. +* int macTotalLen - Toatl size (in bytes) of data for Authentication +* operation on the whole request (packet). Valid for +* last fragment only. +* +* RETURN: None +* +*******************************************************************************/ +static void mvCesaSramDescrBuild(MV_U32 config, int frag, + int cryptoOffset, int ivOffset, int cryptoLength, + int macOffset, int digestOffset, int macLength, + int macTotalLen, MV_CESA_REQ* pReq, MV_DMA_DESC* pDmaDesc) +{ + MV_CESA_DESC* pCesaDesc = &pReq->pCesaDesc[frag]; + MV_CESA_DESC* pSramDesc = pSramDesc = &cesaSramVirtPtr->desc; + MV_U16 sramBufOffset = (MV_U16)((MV_U8*)cesaSramVirtPtr->buf - mvCesaSramAddrGet()); + + pCesaDesc->config = MV_32BIT_LE(config); + + if( (config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + /* word 1 */ + pCesaDesc->cryptoSrcOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset); + pCesaDesc->cryptoDstOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset); + /* word 2 */ + pCesaDesc->cryptoDataLen = MV_16BIT_LE(cryptoLength); + /* word 3 */ + pCesaDesc->cryptoKeyOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.cryptoKey - + mvCesaSramAddrGet())); + /* word 4 */ + pCesaDesc->cryptoIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->cryptoIV - + mvCesaSramAddrGet())); + pCesaDesc->cryptoIvBufOffset = MV_16BIT_LE(sramBufOffset + ivOffset); + } + + if( (config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + /* word 5 */ + pCesaDesc->macSrcOffset = MV_16BIT_LE(sramBufOffset + macOffset); + pCesaDesc->macTotalLen = MV_16BIT_LE(macTotalLen); + + /* word 6 */ + pCesaDesc->macDigestOffset = MV_16BIT_LE(sramBufOffset + digestOffset); + pCesaDesc->macDataLen = MV_16BIT_LE(macLength); + + /* word 7 */ + pCesaDesc->macInnerIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macInnerIV - + mvCesaSramAddrGet())); + pCesaDesc->macOuterIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macOuterIV - + mvCesaSramAddrGet())); + } + /* Prepare DMA descriptor to CESA descriptor from DRAM to SRAM */ + pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&pReq->cesaDescBuf, pCesaDesc)); + pDmaDesc->phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)pSramDesc)); + pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_DESC) | BIT31); + + /* flush Source buffer */ + mvOsCacheFlush(NULL, pCesaDesc, sizeof(MV_CESA_DESC)); +} + +/******************************************************************************* +* mvCesaSramSaUpdate - Move required SA information to SRAM if needed. +* +* DESCRIPTION: +* Copy to SRAM values of the required SA. +* +* +* INPUT: +* short sid - Session ID needs SRAM Cache update +* MV_DMA_DESC *pDmaDesc - Pointer to DMA descriptor used to +* copy SA values from DRAM to SRAM. +* +* RETURN: +* MV_OK - Cache entry for this SA copied to SRAM. +* MV_NO_CHANGE - Cache entry for this SA already exist in SRAM +* +*******************************************************************************/ +static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc) +{ + MV_CESA_SA *pSA = &pCesaSAD[sid]; + + /* Prepare DMA descriptor to Copy CACHE_SA from SA database in DRAM to SRAM */ + pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_SRAM_SA) | BIT31); + pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&cesaSramSaBuf, pSA->pSramSA)); + pDmaDesc->phyDestAdd = + MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)&cesaSramVirtPtr->sramSA)); + + /* Source buffer is already flushed during OpenSession*/ + /*mvOsCacheFlush(NULL, &pSA->sramSA, sizeof(MV_CESA_SRAM_SA));*/ +} + +/******************************************************************************* +* mvCesaDmaCopyPrepare - prepare DMA descriptor list to copy data presented by +* Mbuf structure from DRAM to SRAM +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_MBUF* pMbuf - pointer to Mbuf structure contains request +* data in DRAM +* MV_U8* pSramBuf - pointer to buffer in SRAM where data should +* be copied to. +* MV_DMA_DESC* pDmaDesc - pointer to first DMA descriptor for this copy. +* The function set number of DMA descriptors needed +* to copy the copySize bytes from Mbuf. +* MV_BOOL isToMbuf - Copy direction. +* MV_TRUE means copy from SRAM buffer to Mbuf in DRAM. +* MV_FALSE means copy from Mbuf in DRAM to SRAM buffer. +* int offset - Offset in the Mbuf structure that copy should be +* started from. +* int copySize - Size of data should be copied. +* +* RETURN: +* int - number of DMA descriptors used for the copy. +* +*******************************************************************************/ +#ifndef MV_NETBSD +static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf, + MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf, + int offset, int copySize) +{ + int bufOffset, bufSize, size, frag, i; + MV_U8* pBuf; + + i = 0; + + /* Calculate start place for copy: fragment number and offset in the fragment */ + frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset); + bufSize = pMbuf->pFrags[frag].bufSize - bufOffset; + pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset; + + /* Size accumulate total copy size */ + size = 0; + + /* Create DMA lists to copy mBuf from pSrc to SRAM */ + while(size < copySize) + { + /* Find copy size for each DMA descriptor */ + bufSize = MV_MIN(bufSize, (copySize - size)); + pDmaDesc[i].byteCnt = MV_32BIT_LE(bufSize | BIT31); + if(isToMbuf) + { + pDmaDesc[i].phyDestAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf)); + pDmaDesc[i].phySrcAdd = + MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size))); + /* invalidate the buffer */ + mvOsCacheInvalidate(NULL, pBuf, bufSize); + } + else + { + pDmaDesc[i].phySrcAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf)); + pDmaDesc[i].phyDestAdd = + MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size))); + /* flush the buffer */ + mvOsCacheFlush(NULL, pBuf, bufSize); + } + + /* Count number of used DMA descriptors */ + i++; + size += bufSize; + + /* go to next fragment in the Mbuf */ + frag++; + pBuf = pMbuf->pFrags[frag].bufVirtPtr; + bufSize = pMbuf->pFrags[frag].bufSize; + } + return i; +} +#else /* MV_NETBSD */ +static int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf, + MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf, + int offset, int copySize) +{ + int bufOffset, bufSize, thisSize, size, frag, i; + MV_ULONG bufPhys, sramPhys; + MV_U8* pBuf; + + /* + * Calculate start place for copy: fragment number and offset in + * the fragment + */ + frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset); + + /* + * Get SRAM physical address only once. We can update it in-place + * as we build the descriptor chain. + */ + sramPhys = mvCesaSramVirtToPhys(NULL, pSramBuf); + + /* + * 'size' accumulates total copy size, 'i' counts desccriptors. + */ + size = i = 0; + + /* Create DMA lists to copy mBuf from pSrc to SRAM */ + while (size < copySize) { + /* + * Calculate # of bytes to copy from the current fragment, + * and the pointer to the start of data + */ + bufSize = pMbuf->pFrags[frag].bufSize - bufOffset; + pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset; + bufOffset = 0; /* First frag may be non-zero */ + frag++; + + /* + * As long as there is data in the current fragment... + */ + while (bufSize > 0) { + /* + * Ensure we don't cross an MMU page boundary. + * XXX: This is NetBSD-specific, but it is a + * quick and dirty way to fix the problem. + * A true HAL would rely on the OS-specific + * driver to do this... + */ + thisSize = PAGE_SIZE - + (((MV_ULONG)pBuf) & (PAGE_SIZE - 1)); + thisSize = MV_MIN(bufSize, thisSize); + /* + * Make sure we don't copy more than requested + */ + if (thisSize > (copySize - size)) { + thisSize = copySize - size; + bufSize = 0; + } + + /* + * Physicall address of this fragment + */ + bufPhys = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf)); + + /* + * Set up the descriptor + */ + pDmaDesc[i].byteCnt = MV_32BIT_LE(thisSize | BIT31); + if(isToMbuf) { + pDmaDesc[i].phyDestAdd = bufPhys; + pDmaDesc[i].phySrcAdd = MV_32BIT_LE(sramPhys); + /* invalidate the buffer */ + mvOsCacheInvalidate(NULL, pBuf, thisSize); + } else { + pDmaDesc[i].phySrcAdd = bufPhys; + pDmaDesc[i].phyDestAdd = MV_32BIT_LE(sramPhys); + /* flush the buffer */ + mvOsCacheFlush(NULL, pBuf, thisSize); + } + + pDmaDesc[i].phyNextDescPtr = + MV_32BIT_LE(mvOsIoVirtToPhy(NULL,(&pDmaDesc[i+1]))); + + /* flush the DMA desc */ + mvOsCacheFlush(NULL, &pDmaDesc[i], sizeof(MV_DMA_DESC)); + + /* Update state */ + bufSize -= thisSize; + sramPhys += thisSize; + pBuf += thisSize; + size += thisSize; + i++; + } + } + + return i; +} +#endif /* MV_NETBSD */ +/******************************************************************************* +* mvCesaHmacIvGet - Calculate Inner and Outter values from HMAC key +* +* DESCRIPTION: +* This function calculate Inner and Outer values used for HMAC algorithm. +* This operation allows improve performance fro the whole HMAC processing. +* +* INPUT: +* MV_CESA_MAC_MODE macMode - Authentication mode: HMAC_MD5 or HMAC_SHA1. +* unsigned char key[] - Pointer to HMAC key. +* int keyLength - Size of HMAC key (maximum 64 bytes) +* +* OUTPUT: +* unsigned char innerIV[] - HASH(key^inner) +* unsigned char outerIV[] - HASH(key^outter) +* +* RETURN: None +* +*******************************************************************************/ +static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength, + unsigned char innerIV[], unsigned char outerIV[]) +{ + unsigned char inner[MV_CESA_MAX_MAC_KEY_LENGTH]; + unsigned char outer[MV_CESA_MAX_MAC_KEY_LENGTH]; + int i, digestSize = 0; +#if defined(MV_CPU_LE) || defined(MV_PPC) + MV_U32 swapped32, val32, *pVal32; +#endif + for(i=0; ipFrags[frag].bufVirtPtr + fragOffset; + size = pMbuf->pFrags[frag].bufSize - fragOffset; + + /* Complete Inner part */ + while(macLeftSize > 0) + { + if(macLeftSize <= size) + { + mvSHA1Update(&ctx, pData, macLeftSize); + break; + } + mvSHA1Update(&ctx, pData, size); + macLeftSize -= size; + frag++; + pData = pMbuf->pFrags[frag].bufVirtPtr; + size = pMbuf->pFrags[frag].bufSize; + } + mvSHA1Final(pDigest, &ctx); +/* + mvOsPrintf("mvCesaFragSha1Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n", + pOuterIV, macLeftSize, macTotalSize); + mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1); +*/ + + if(pOuterIV != NULL) + { + /* If HMAC - Complete Outer part */ + for(i=0; ipFrags[frag].bufVirtPtr + fragOffset; + size = pMbuf->pFrags[frag].bufSize - fragOffset; + + /* Complete Inner part */ + while(macLeftSize > 0) + { + if(macLeftSize <= size) + { + mvMD5Update(&ctx, pData, macLeftSize); + break; + } + mvMD5Update(&ctx, pData, size); + macLeftSize -= size; + frag++; + pData = pMbuf->pFrags[frag].bufVirtPtr; + size = pMbuf->pFrags[frag].bufSize; + } + mvMD5Final(pDigest, &ctx); + +/* + mvOsPrintf("mvCesaFragMd5Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n", + pOuterIV, macLeftSize, macTotalSize); + mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1); +*/ + if(pOuterIV != NULL) + { + /* Complete Outer part */ + for(i=0; ipCmd; + MV_U8* pDigest; + MV_CESA_MAC_MODE macMode; + MV_U8* pOuterIV = NULL; + + /* Copy data from Source fragment to Destination */ + if(pCmd->pSrc != pCmd->pDst) + { + mvCesaMbufCopy(pCmd->pDst, pReq->frags.bufOffset, + pCmd->pSrc, pReq->frags.bufOffset, macDataSize); + } + +/* + mvCesaCopyFromMbuf(cesaSramVirtPtr->buf[0], pCmd->pSrc, pReq->frags.bufOffset, macDataSize); + mvCesaCopyToMbuf(cesaSramVirtPtr->buf[0], pCmd->pDst, pReq->frags.bufOffset, macDataSize); +*/ + pDigest = (mvCesaSramAddrGet() + pReq->frags.newDigestOffset); + + macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET; +/* + mvOsPrintf("macDataSize=%d, macLength=%d, digestOffset=%d, macMode=%d\n", + macDataSize, pCmd->macLength, pCmd->digestOffset, macMode); +*/ + switch(macMode) + { + case MV_CESA_MAC_HMAC_MD5: + pOuterIV = pSA->pSramSA->macOuterIV; + + case MV_CESA_MAC_MD5: + mvCesaFragMd5Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV, + macDataSize, pCmd->macLength, pDigest); + break; + + case MV_CESA_MAC_HMAC_SHA1: + pOuterIV = pSA->pSramSA->macOuterIV; + + case MV_CESA_MAC_SHA1: + mvCesaFragSha1Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV, + macDataSize, pCmd->macLength, pDigest); + break; + + default: + mvOsPrintf("mvCesaFragAuthComplete: Unexpected macMode %d\n", macMode); + return MV_BAD_PARAM; + } + return MV_OK; +} + +/******************************************************************************* +* mvCesaCtrModeInit - +* +* DESCRIPTION: +* +* +* INPUT: NONE +* +* +* RETURN: +* MV_CESA_COMMAND* +* +*******************************************************************************/ +static MV_CESA_COMMAND* mvCesaCtrModeInit(void) +{ + MV_CESA_MBUF *pMbuf; + MV_U8 *pBuf; + MV_CESA_COMMAND *pCmd; + + pBuf = mvOsMalloc(sizeof(MV_CESA_COMMAND) + + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) + 100); + if(pBuf == NULL) + { + mvOsPrintf("mvCesaSessionOpen: Can't allocate %u bytes for CTR Mode\n", + sizeof(MV_CESA_COMMAND) + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) ); + return NULL; + } + pCmd = (MV_CESA_COMMAND*)pBuf; + pBuf += sizeof(MV_CESA_COMMAND); + + pMbuf = (MV_CESA_MBUF*)pBuf; + pBuf += sizeof(MV_CESA_MBUF); + + pMbuf->pFrags = (MV_BUF_INFO*)pBuf; + + pMbuf->numFrags = 1; + pCmd->pSrc = pMbuf; + pCmd->pDst = pMbuf; +/* + mvOsPrintf("CtrModeInit: pCmd=%p, pSrc=%p, pDst=%p, pFrags=%p\n", + pCmd, pCmd->pSrc, pCmd->pDst, + pMbuf->pFrags); +*/ + return pCmd; +} + +/******************************************************************************* +* mvCesaCtrModePrepare - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd) +{ + MV_CESA_MBUF *pMbuf; + MV_U8 *pBuf, *pIV; + MV_U32 counter, *pCounter; + int cryptoSize = MV_ALIGN_UP(pCmd->cryptoLength, MV_CESA_AES_BLOCK_SIZE); +/* + mvOsPrintf("CtrModePrepare: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n", + pCmd, pCmd->pSrc, pCmd->pDst, + pCtrModeCmd, pCtrModeCmd->pSrc, pCtrModeCmd->pDst); +*/ + pMbuf = pCtrModeCmd->pSrc; + + /* Allocate buffer for Key stream */ + pBuf = mvOsIoCachedMalloc(cesaOsHandle,cryptoSize, + &pMbuf->pFrags[0].bufPhysAddr, + &pMbuf->pFrags[0].memHandle); + if(pBuf == NULL) + { + mvOsPrintf("mvCesaCtrModePrepare: Can't allocate %d bytes\n", cryptoSize); + return MV_OUT_OF_CPU_MEM; + } + memset(pBuf, 0, cryptoSize); + mvOsCacheFlush(NULL, pBuf, cryptoSize); + + pMbuf->pFrags[0].bufVirtPtr = pBuf; + pMbuf->mbufSize = cryptoSize; + pMbuf->pFrags[0].bufSize = cryptoSize; + + pCtrModeCmd->pReqPrv = pCmd->pReqPrv; + pCtrModeCmd->sessionId = pCmd->sessionId; + + /* ivFromUser and ivOffset are don't care */ + pCtrModeCmd->cryptoOffset = 0; + pCtrModeCmd->cryptoLength = cryptoSize; + + /* digestOffset, macOffset and macLength are don't care */ + + mvCesaCopyFromMbuf(pBuf, pCmd->pSrc, pCmd->ivOffset, MV_CESA_AES_BLOCK_SIZE); + pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter))); + counter = *pCounter; + counter = MV_32BIT_BE(counter); + pIV = pBuf; + cryptoSize -= MV_CESA_AES_BLOCK_SIZE; + + /* fill key stream */ + while(cryptoSize > 0) + { + pBuf += MV_CESA_AES_BLOCK_SIZE; + memcpy(pBuf, pIV, MV_CESA_AES_BLOCK_SIZE - sizeof(counter)); + pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter))); + counter++; + *pCounter = MV_32BIT_BE(counter); + cryptoSize -= MV_CESA_AES_BLOCK_SIZE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvCesaCtrModeComplete - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd) +{ + int srcFrag, dstFrag, srcOffset, dstOffset, keyOffset, srcSize, dstSize; + int cryptoSize = pCmd->cryptoLength; + MV_U8 *pSrc, *pDst, *pKey; + MV_STATUS status = MV_OK; +/* + mvOsPrintf("CtrModeComplete: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n", + pCmd, pCmd->pSrc, pCmd->pDst, + pOrgCmd, pOrgCmd->pSrc, pOrgCmd->pDst); +*/ + /* XOR source data with key stream to destination data */ + pKey = pCmd->pDst->pFrags[0].bufVirtPtr; + keyOffset = 0; + + if( (pOrgCmd->pSrc != pOrgCmd->pDst) && + (pOrgCmd->cryptoOffset > 0) ) + { + /* Copy Prefix from source buffer to destination buffer */ + + status = mvCesaMbufCopy(pOrgCmd->pDst, 0, + pOrgCmd->pSrc, 0, pOrgCmd->cryptoOffset); +/* + status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc, + 0, pOrgCmd->cryptoOffset); + status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst, + 0, pOrgCmd->cryptoOffset); +*/ + } + + srcFrag = mvCesaMbufOffset(pOrgCmd->pSrc, pOrgCmd->cryptoOffset, &srcOffset); + pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr; + srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize; + + dstFrag = mvCesaMbufOffset(pOrgCmd->pDst, pOrgCmd->cryptoOffset, &dstOffset); + pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr; + dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize; + + while(cryptoSize > 0) + { + pDst[dstOffset] = (pSrc[srcOffset] ^ pKey[keyOffset]); + + cryptoSize--; + dstOffset++; + srcOffset++; + keyOffset++; + + if(srcOffset >= srcSize) + { + srcFrag++; + srcOffset = 0; + pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr; + srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize; + } + + if(dstOffset >= dstSize) + { + dstFrag++; + dstOffset = 0; + pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr; + dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize; + } + } + + if(pOrgCmd->pSrc != pOrgCmd->pDst) + { + /* Copy Suffix from source buffer to destination buffer */ + srcOffset = pOrgCmd->cryptoOffset + pOrgCmd->cryptoLength; + + if( (pOrgCmd->pDst->mbufSize - srcOffset) > 0) + { + status = mvCesaMbufCopy(pOrgCmd->pDst, srcOffset, + pOrgCmd->pSrc, srcOffset, + pOrgCmd->pDst->mbufSize - srcOffset); + } + +/* + status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc, + srcOffset, pOrgCmd->pSrc->mbufSize - srcOffset); + status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst, + srcOffset, pOrgCmd->pDst->mbufSize - srcOffset); +*/ + } + + /* Free buffer used for Key stream */ + mvOsIoCachedFree(cesaOsHandle,pCmd->pDst->pFrags[0].bufSize, + pCmd->pDst->pFrags[0].bufPhysAddr, + pCmd->pDst->pFrags[0].bufVirtPtr, + pCmd->pDst->pFrags[0].memHandle); + + return MV_OK; +} + +/******************************************************************************* +* mvCesaCtrModeFinish - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_COMMAND* pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static void mvCesaCtrModeFinish(MV_CESA_COMMAND* pCmd) +{ + mvOsFree(pCmd); +} + +/******************************************************************************* +* mvCesaParamCheck - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, + MV_U8* pFixOffset) +{ + MV_U8 fixOffset = 0xFF; + + /* Check AUTH operation parameters */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* MAC offset should be at least 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->macOffset, 4) ) + { + mvOsPrintf("mvCesaAction: macOffset %d must be 4 byte aligned\n", + pCmd->macOffset); + return MV_BAD_PARAM; + } + /* Digest offset must be 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->digestOffset, 4) ) + { + mvOsPrintf("mvCesaAction: digestOffset %d must be 4 byte aligned\n", + pCmd->digestOffset); + return MV_BAD_PARAM; + } + /* In addition all offsets should be the same alignment: 8 or 4 */ + if(fixOffset == 0xFF) + { + fixOffset = (pCmd->macOffset % 8); + } + else + { + if( (pCmd->macOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: macOffset %d mod 8 must be equal %d\n", + pCmd->macOffset, fixOffset); + return MV_BAD_PARAM; + } + } + if( (pCmd->digestOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: digestOffset %d mod 8 must be equal %d\n", + pCmd->digestOffset, fixOffset); + return MV_BAD_PARAM; + } + } + /* Check CRYPTO operation parameters */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* CryptoOffset should be at least 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->cryptoOffset, 4) ) + { + mvOsPrintf("CesaAction: cryptoOffset=%d must be 4 byte aligned\n", + pCmd->cryptoOffset); + return MV_BAD_PARAM; + } + /* cryptoLength should be the whole number of blocks */ + if( MV_IS_NOT_ALIGN(pCmd->cryptoLength, pSA->cryptoBlockSize) ) + { + mvOsPrintf("mvCesaAction: cryptoLength=%d must be %d byte aligned\n", + pCmd->cryptoLength, pSA->cryptoBlockSize); + return MV_BAD_PARAM; + } + if(fixOffset == 0xFF) + { + fixOffset = (pCmd->cryptoOffset % 8); + } + else + { + /* In addition all offsets should be the same alignment: 8 or 4 */ + if( (pCmd->cryptoOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: cryptoOffset %d mod 8 must be equal %d \n", + pCmd->cryptoOffset, fixOffset); + return MV_BAD_PARAM; + } + } + + /* check for CBC mode */ + if(pSA->cryptoIvSize > 0) + { + /* cryptoIV must not be part of CryptoLength */ + if( ((pCmd->ivOffset + pSA->cryptoIvSize) > pCmd->cryptoOffset) && + (pCmd->ivOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) ) + { + mvOsPrintf("mvCesaFragParamCheck: cryptoIvOffset (%d) is part of cryptoLength (%d+%d)\n", + pCmd->ivOffset, pCmd->macOffset, pCmd->macLength); + return MV_BAD_PARAM; + } + + /* ivOffset must be 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->ivOffset, 4) ) + { + mvOsPrintf("CesaAction: ivOffset=%d must be 4 byte aligned\n", + pCmd->ivOffset); + return MV_BAD_PARAM; + } + /* In addition all offsets should be the same alignment: 8 or 4 */ + if( (pCmd->ivOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: ivOffset %d mod 8 must be %d\n", + pCmd->ivOffset, fixOffset); + return MV_BAD_PARAM; + } + } + } + return MV_OK; +} + +/******************************************************************************* +* mvCesaFragParamCheck - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd) +{ + int offset; + + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* macOffset must be less that SRAM buffer size */ + if(pCmd->macOffset > (sizeof(cesaSramVirtPtr->buf) - MV_CESA_AUTH_BLOCK_SIZE)) + { + mvOsPrintf("mvCesaFragParamCheck: macOffset is too large (%d)\n", + pCmd->macOffset); + return MV_BAD_PARAM; + } + /* macOffset+macSize must be more than mbufSize - SRAM buffer size */ + if( ((pCmd->macOffset + pCmd->macLength) > pCmd->pSrc->mbufSize) || + ((pCmd->pSrc->mbufSize - (pCmd->macOffset + pCmd->macLength)) >= + sizeof(cesaSramVirtPtr->buf)) ) + { + mvOsPrintf("mvCesaFragParamCheck: macLength is too large (%d), mbufSize=%d\n", + pCmd->macLength, pCmd->pSrc->mbufSize); + return MV_BAD_PARAM; + } + } + + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* cryptoOffset must be less that SRAM buffer size */ + /* 4 for possible fixOffset */ + if( (pCmd->cryptoOffset + 4) > (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize)) + { + mvOsPrintf("mvCesaFragParamCheck: cryptoOffset is too large (%d)\n", + pCmd->cryptoOffset); + return MV_BAD_PARAM; + } + + /* cryptoOffset+cryptoSize must be more than mbufSize - SRAM buffer size */ + if( ((pCmd->cryptoOffset + pCmd->cryptoLength) > pCmd->pSrc->mbufSize) || + ((pCmd->pSrc->mbufSize - (pCmd->cryptoOffset + pCmd->cryptoLength)) >= + (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize)) ) + { + mvOsPrintf("mvCesaFragParamCheck: cryptoLength is too large (%d), mbufSize=%d\n", + pCmd->cryptoLength, pCmd->pSrc->mbufSize); + return MV_BAD_PARAM; + } + } + + /* When MAC_THEN_CRYPTO or CRYPTO_THEN_MAC */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) == + (MV_CESA_MAC_THEN_CRYPTO << MV_CESA_OPERATION_OFFSET)) || + ((pSA->config & MV_CESA_OPERATION_MASK) == + (MV_CESA_CRYPTO_THEN_MAC << MV_CESA_OPERATION_OFFSET)) ) + { + if( (mvCtrlModelGet() == MV_5182_DEV_ID) || + ( (mvCtrlModelGet() == MV_5181_DEV_ID) && + (mvCtrlRevGet() >= MV_5181L_A0_REV) && + (pCmd->macLength >= (1 << 14)) ) ) + { + return MV_NOT_ALLOWED; + } + + /* abs(cryptoOffset-macOffset) must be aligned cryptoBlockSize */ + if(pCmd->cryptoOffset > pCmd->macOffset) + { + offset = pCmd->cryptoOffset - pCmd->macOffset; + } + else + { + offset = pCmd->macOffset - pCmd->cryptoOffset; + } + + if( MV_IS_NOT_ALIGN(offset, pSA->cryptoBlockSize) ) + { +/* + mvOsPrintf("mvCesaFragParamCheck: (cryptoOffset - macOffset) must be %d byte aligned\n", + pSA->cryptoBlockSize); +*/ + return MV_NOT_ALLOWED; + } + /* Digest must not be part of CryptoLength */ + if( ((pCmd->digestOffset + pSA->digestSize) > pCmd->cryptoOffset) && + (pCmd->digestOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) ) + { +/* + mvOsPrintf("mvCesaFragParamCheck: digestOffset (%d) is part of cryptoLength (%d+%d)\n", + pCmd->digestOffset, pCmd->cryptoOffset, pCmd->cryptoLength); +*/ + return MV_NOT_ALLOWED; + } + } + return MV_OK; +} + +/******************************************************************************* +* mvCesaFragSizeFind - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, +* int cryptoOffset, int macOffset, +* +* OUTPUT: +* int* pCopySize, int* pCryptoDataSize, int* pMacDataSize +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq, + int cryptoOffset, int macOffset, + int* pCopySize, int* pCryptoDataSize, int* pMacDataSize) +{ + MV_CESA_COMMAND *pCmd = pReq->pCmd; + int cryptoDataSize, macDataSize, copySize; + + cryptoDataSize = macDataSize = 0; + copySize = *pCopySize; + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + cryptoDataSize = MV_MIN( (copySize - cryptoOffset), + (pCmd->cryptoLength - (pReq->frags.cryptoSize + 1)) ); + + /* cryptoSize for each fragment must be the whole number of blocksSize */ + if( MV_IS_NOT_ALIGN(cryptoDataSize, pSA->cryptoBlockSize) ) + { + cryptoDataSize = MV_ALIGN_DOWN(cryptoDataSize, pSA->cryptoBlockSize); + copySize = cryptoOffset + cryptoDataSize; + } + } + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + macDataSize = MV_MIN( (copySize - macOffset), + (pCmd->macLength - (pReq->frags.macSize + 1))); + + /* macSize for each fragment (except last) must be the whole number of blocksSize */ + if( MV_IS_NOT_ALIGN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE) ) + { + macDataSize = MV_ALIGN_DOWN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE); + copySize = macOffset + macDataSize; + } + cryptoDataSize = copySize - cryptoOffset; + } + *pCopySize = copySize; + + if(pCryptoDataSize != NULL) + *pCryptoDataSize = cryptoDataSize; + + if(pMacDataSize != NULL) + *pMacDataSize = macDataSize; +} diff --git a/board/mv_feroceon/mv_hal/cesa/mvCesa.c.keep b/board/mv_feroceon/mv_hal/cesa/mvCesa.c.keep new file mode 100644 index 0000000..6faedfb --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvCesa.c.keep @@ -0,0 +1,2942 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "cesa/mvCesa.h" + +#include "ctrlEnv/mvCtrlEnvLib.h" +#undef CESA_DEBUG + + +/********** Global variables **********/ + +/* If request size is more than MV_CESA_MAX_BUF_SIZE the + * request is processed as fragmented request. + */ + +MV_CESA_STATS cesaStats; + +MV_BUF_INFO cesaSramSaBuf; +short cesaLastSid = -1; +MV_CESA_SA* pCesaSAD = NULL; +MV_U16 cesaMaxSA = 0; + +MV_CESA_REQ* pCesaReqFirst = NULL; +MV_CESA_REQ* pCesaReqLast = NULL; +MV_CESA_REQ* pCesaReqEmpty = NULL; +MV_CESA_REQ* pCesaReqProcess = NULL; +int cesaQueueDepth = 0; +int cesaReqResources = 0; + +MV_CESA_SRAM_MAP* cesaSramVirtPtr = NULL; +MV_U32 cesaCryptEngBase = 0; +void *cesaOsHandle = NULL; + + +static INLINE MV_U8* mvCesaSramAddrGet(void) +{ +#ifdef MV_CESA_NO_SRAM + return (MV_U8*)cesaSramVirtPtr; +#else + return (MV_U8*)cesaCryptEngBase; +#endif /* MV_CESA_NO_SRAM */ +} + +static INLINE MV_ULONG mvCesaSramVirtToPhys(void* pDev, MV_U8* pSramVirt) +{ +#ifdef MV_CESA_NO_SRAM + return (MV_ULONG)mvOsIoVirtToPhy(NULL, pSramVirt); +#else + return (MV_ULONG)pSramVirt; +#endif /* MV_CESA_NO_SRAM */ +} + +/* Internal Function prototypes */ + +static INLINE void mvCesaSramDescrBuild(MV_U32 config, int frag, + int cryptoOffset, int ivOffset, int cryptoLength, + int macOffset, int digestOffset, int macLength, int macTotalLen, + MV_CESA_REQ *pCesaReq, MV_DMA_DESC* pDmaDesc); + +static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc); + +static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf, + MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf, + int offset, int copySize); + +static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength, + unsigned char innerIV[], unsigned char outerIV[]); + +static MV_STATUS mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA, + int macDataSize); + +static MV_CESA_COMMAND* mvCesaCtrModeInit(void); + +static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd); +static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd); +static void mvCesaCtrModeFinish(MV_CESA_COMMAND *pCmd); + +static INLINE MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq); +static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag); + +static INLINE MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset); +static INLINE MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd); + +static INLINE void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq, + int cryptoOffset, int macOffset, + int* pCopySize, int* pCryptoDataSize, int* pMacDataSize); + + +/* Go to the next request in the request queue */ +static INLINE MV_CESA_REQ* MV_CESA_REQ_NEXT_PTR(MV_CESA_REQ* pReq) +{ + if(pReq == pCesaReqLast) + return pCesaReqFirst; + + return pReq+1; +} + +static INLINE void mvCesaReqProcessStart(MV_CESA_REQ* pReq) +{ + int frag; + + pReq->state = MV_CESA_PROCESS; + cesaStats.startCount++; + + if(pReq->fragMode == MV_CESA_FRAG_NONE) + { + frag = 0; + } + else + { + frag = pReq->frags.nextFrag; + pReq->frags.nextFrag++; + } +#if (MV_CESA_VERSION >= 2) + /* Enable TDMA engine */ + MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0); + MV_REG_WRITE(MV_CESA_TDMA_NEXT_DESC_PTR_REG, + (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst)); +#else + /* Enable IDMA engine */ + MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0); + MV_REG_WRITE(IDMA_NEXT_DESC_PTR_REG(0), + (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst)); +#endif /* MV_CESA_VERSION >= 2 */ + +#if defined(MV_BRIDGE_SYNC_REORDER) + mvOsBridgeReorderWA(); +#endif + + /* Start Accelerator */ + MV_REG_WRITE(MV_CESA_CMD_REG, MV_CESA_CMD_CHAN_ENABLE_MASK); +} + + +/******************************************************************************* +* mvCesaHalInit - Initialize the CESA driver +* +* DESCRIPTION: +* This function initialize the CESA driver. +* 1) Session database +* 2) Request queue +* 4) DMA descriptor lists - one list per request. Each list +* has MV_CESA_MAX_DMA_DESC descriptors. +* +* INPUT: +* numOfSession - maximum number of supported sessions +* queueDepth - number of elements in the request queue. +* pSramBase - virtual address of Sram +* osHandle - A handle used by the OS to allocate memory for the +* module (Passed to the OS Services layer) +* +* RETURN: +* MV_OK - Success +* MV_NO_RESOURCE - Fail, can't allocate resources: +* Session database, request queue, +* DMA descriptors list, LRU cache database. +* MV_NOT_ALIGNED - Sram base address is not 8 byte aligned. +* +*******************************************************************************/ +MV_STATUS mvCesaHalInit (int numOfSession, int queueDepth, char* pSramBase, MV_U32 cryptEngBase, + void *osHandle) +{ + int i, req; + MV_U32 descOffsetReg, configReg; + MV_CESA_SRAM_SA *pSramSA; + + + mvOsPrintf("mvCesaInit: sessions=%d, queue=%d, pSram=%p\n", + numOfSession, queueDepth, pSramBase); + + cesaOsHandle = osHandle; + /* Create Session database */ + pCesaSAD = mvOsMalloc(sizeof(MV_CESA_SA)*numOfSession); + if(pCesaSAD == NULL) + { + mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d SAs\n", + sizeof(MV_CESA_SA)*numOfSession, numOfSession); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(pCesaSAD, 0, sizeof(MV_CESA_SA)*numOfSession); + cesaMaxSA = numOfSession; + + /* Allocate imag of sramSA in the DRAM */ + cesaSramSaBuf.bufSize = sizeof(MV_CESA_SRAM_SA)*numOfSession + + CPU_D_CACHE_LINE_SIZE; + + cesaSramSaBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle,cesaSramSaBuf.bufSize, + &cesaSramSaBuf.bufPhysAddr, + &cesaSramSaBuf.memHandle); + + if(cesaSramSaBuf.bufVirtPtr == NULL) + { + mvOsPrintf("mvCesaInit: Can't allocate %d bytes for sramSA structures\n", + cesaSramSaBuf.bufSize); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(cesaSramSaBuf.bufVirtPtr, 0, cesaSramSaBuf.bufSize); + pSramSA = (MV_CESA_SRAM_SA*)MV_ALIGN_UP((MV_ULONG)cesaSramSaBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + for(i=0; icesaDescBuf.bufSize = sizeof(MV_CESA_DESC)*MV_CESA_MAX_REQ_FRAGS + + CPU_D_CACHE_LINE_SIZE; + + pReq->cesaDescBuf.bufVirtPtr = + mvOsIoCachedMalloc(osHandle,pReq->cesaDescBuf.bufSize, + &pReq->cesaDescBuf.bufPhysAddr, + &pReq->cesaDescBuf.memHandle); + + if(pReq->cesaDescBuf.bufVirtPtr == NULL) + { + mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for CESA descriptors\n", + req, pReq->cesaDescBuf.bufSize); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(pReq->cesaDescBuf.bufVirtPtr, 0, pReq->cesaDescBuf.bufSize); + pReq->pCesaDesc = (MV_CESA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->cesaDescBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + pReq->dmaDescBuf.bufSize = sizeof(MV_DMA_DESC)*MV_CESA_MAX_DMA_DESC*MV_CESA_MAX_REQ_FRAGS + + CPU_D_CACHE_LINE_SIZE; + + pReq->dmaDescBuf.bufVirtPtr = + mvOsIoCachedMalloc(osHandle,pReq->dmaDescBuf.bufSize, + &pReq->dmaDescBuf.bufPhysAddr, + &pReq->dmaDescBuf.memHandle); + + if(pReq->dmaDescBuf.bufVirtPtr == NULL) + { + mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for DMA descriptor list\n", + req, pReq->dmaDescBuf.bufSize); + mvCesaFinish(); + return MV_NO_RESOURCE; + } + memset(pReq->dmaDescBuf.bufVirtPtr, 0, pReq->dmaDescBuf.bufSize); + pDmaDesc = (MV_DMA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->dmaDescBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + for(frag=0; fragdma[frag]; + + pDma->pDmaFirst = pDmaDesc; + pDma->pDmaLast = NULL; + + for(i=0; ipDmaFirst[i].phyNextDescPtr = + MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pDmaDesc[i+1])); + } + pDma->pDmaFirst[i].phyNextDescPtr = 0; + mvOsCacheFlush(NULL, &pDma->pDmaFirst[0], MV_CESA_MAX_DMA_DESC*sizeof(MV_DMA_DESC)); + + pDmaDesc += MV_CESA_MAX_DMA_DESC; + } + } + /*mvCesaCryptoIvSet(NULL, MV_CESA_MAX_IV_LENGTH);*/ + descOffsetReg = (MV_U16)((MV_U8*)&cesaSramVirtPtr->desc - mvCesaSramAddrGet()); + MV_REG_WRITE(MV_CESA_CHAN_DESC_OFFSET_REG, descOffsetReg); + + configReg |= (MV_CESA_CFG_WAIT_DMA_MASK | MV_CESA_CFG_ACT_DMA_MASK); + +#if (MV_CESA_VERSION >= 2) + /* Initialize TDMA engine */ + MV_REG_WRITE(MV_CESA_TDMA_CTRL_REG, MV_CESA_TDMA_CTRL_VALUE); + MV_REG_WRITE(MV_CESA_TDMA_BYTE_COUNT_REG, 0); + MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0); +#else + /* Initialize IDMA #0 engine */ + MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0); + MV_REG_WRITE(IDMA_BYTE_COUNT_REG(0), 0); + MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0); + MV_REG_WRITE(IDMA_CTRL_HIGH_REG(0), ICCHR_ENDIAN_LITTLE +#ifdef MV_CPU_LE + | ICCHR_DESC_BYTE_SWAP_EN +#endif + ); + /* Clear Cause Byte of IDMA channel to be used */ + MV_REG_WRITE( IDMA_CAUSE_REG, ~ICICR_CAUSE_MASK_ALL(0)); + MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), MV_CESA_IDMA_CTRL_LOW_VALUE); +#endif /* (MV_CESA_VERSION >= 2) */ + + /* Set CESA configuration registers */ + MV_REG_WRITE( MV_CESA_CFG_REG, configReg); + mvCesaDebugStatsClear(); + + return MV_OK; +} + +/******************************************************************************* +* mvCesaFinish - Shutdown the CESA driver +* +* DESCRIPTION: +* This function shutdown the CESA driver and free all allocted resources. +* +* INPUT: None +* +* RETURN: +* MV_OK - Success +* Other - Fail +* +*******************************************************************************/ +MV_STATUS mvCesaFinish (void) +{ + int req; + MV_CESA_REQ* pReq; + + mvOsPrintf("mvCesaFinish: \n"); + + cesaSramVirtPtr = NULL; + + /* Free all resources: DMA list, etc. */ + for(req=0; reqdmaDescBuf.bufVirtPtr != NULL) + { + mvOsIoCachedFree(cesaOsHandle,pReq->dmaDescBuf.bufSize, + pReq->dmaDescBuf.bufPhysAddr, + pReq->dmaDescBuf.bufVirtPtr, + pReq->dmaDescBuf.memHandle); + } + if(pReq->cesaDescBuf.bufVirtPtr != NULL) + { + mvOsIoCachedFree(cesaOsHandle,pReq->cesaDescBuf.bufSize, + pReq->cesaDescBuf.bufPhysAddr, + pReq->cesaDescBuf.bufVirtPtr, + pReq->cesaDescBuf.memHandle); + } + } +#if (MV_CESA_VERSION < 2) + MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0); +#endif /* (MV_CESA_VERSION < 2) */ + + /* Free request queue */ + if(pCesaReqFirst != NULL) + { + mvOsFree(pCesaReqFirst); + pCesaReqFirst = pCesaReqLast = NULL; + pCesaReqEmpty = pCesaReqProcess = NULL; + cesaQueueDepth = cesaReqResources = 0; + } + /* Free SA database */ + if(pCesaSAD != NULL) + { + mvOsFree(pCesaSAD); + pCesaSAD = NULL; + cesaMaxSA = 0; + } + MV_REG_WRITE( MV_CESA_CFG_REG, 0); + MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0); + MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0); + + return MV_OK; +} + +/******************************************************************************* +* mvCesaCryptoIvSet - Set IV value for Crypto algorithm working in CBC mode +* +* DESCRIPTION: +* This function set IV value using by Crypto algorithms in CBC mode. +* Each channel has its own IV value. +* This function gets IV value from the caller. If no IV value passed from +* the caller or only part of IV passed, the function will init the rest part +* of IV value (or the whole IV) by random value. +* +* INPUT: +* MV_U8* pIV - Pointer to IV value supplied by user. If pIV==NULL +* the function will generate random IV value. +* int ivSize - size (in bytes) of IV provided by user. If ivSize is +* smaller than maximum IV size, the function will complete +* IV by random value. +* +* RETURN: +* MV_OK - Success +* Other - Fail +* +*******************************************************************************/ +MV_STATUS mvCesaCryptoIvSet(MV_U8* pIV, int ivSize) +{ + MV_U8* pSramIV; +#if defined(MV646xx) + mvOsPrintf("mvCesaCryptoIvSet: ERR. shouldn't use this call on MV64660\n"); +#endif + pSramIV = cesaSramVirtPtr->cryptoIV; + if(ivSize > MV_CESA_MAX_IV_LENGTH) + { + mvOsPrintf("mvCesaCryptoIvSet: ivSize (%d) is too large\n", ivSize); + ivSize = MV_CESA_MAX_IV_LENGTH; + } + if(pIV != NULL) + { + memcpy(pSramIV, pIV, ivSize); + ivSize = MV_CESA_MAX_IV_LENGTH - ivSize; + pSramIV += ivSize; + } + + while(ivSize > 0) + { + int size, mv_random = mvOsRand(); + + size = MV_MIN(ivSize, sizeof(mv_random)); + memcpy(pSramIV, (void*)&mv_random, size); + + pSramIV += size; + ivSize -= size; + } +/* + mvOsCacheFlush(NULL, cesaSramVirtPtr->cryptoIV, + MV_CESA_MAX_IV_LENGTH); + mvOsCacheInvalidate(NULL, cesaSramVirtPtr->cryptoIV, + MV_CESA_MAX_IV_LENGTH); +*/ + return MV_OK; +} + +/******************************************************************************* +* mvCesaSessionOpen - Open new uni-directional crypto session +* +* DESCRIPTION: +* This function open new session. +* +* INPUT: +* MV_CESA_OPEN_SESSION *pSession - pointer to new session input parameters +* +* OUTPUT: +* short *pSid - session ID, should be used for all future +* requests over this session. +* +* RETURN: +* MV_OK - Session opend successfully. +* MV_FULL - All sessions are in use, no free place in +* SA database. +* MV_BAD_PARAM - One of session input parameters is invalid. +* +*******************************************************************************/ +MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short* pSid) +{ + short sid; + MV_U32 config = 0; + int digestSize; + + cesaStats.openedCount++; + + /* Find free entry in SAD */ + for(sid=0; sidoperation >= MV_CESA_MAX_OPERATION) + { + mvOsPrintf("mvCesaSessionOpen: Unexpected operation %d\n", + pSession->operation); + return MV_BAD_PARAM; + } + config |= (pSession->operation << MV_CESA_OPERATION_OFFSET); + + if( (pSession->direction != MV_CESA_DIR_ENCODE) && + (pSession->direction != MV_CESA_DIR_DECODE) ) + { + mvOsPrintf("mvCesaSessionOpen: Unexpected direction %d\n", + pSession->direction); + return MV_BAD_PARAM; + } + config |= (pSession->direction << MV_CESA_DIRECTION_BIT); + /* Clear SA entry */ + /* memset(&pCesaSAD[sid], 0, sizeof(pCesaSAD[sid])); */ + + /* Check AUTH parameters and update SA entry */ + if(pSession->operation != MV_CESA_CRYPTO_ONLY) + { + /* For HMAC (MD5 and SHA1) - Maximum Key size is 64 bytes */ + if( (pSession->macMode == MV_CESA_MAC_HMAC_MD5) || + (pSession->macMode == MV_CESA_MAC_HMAC_SHA1) ) + { + if(pSession->macKeyLength > MV_CESA_MAX_MAC_KEY_LENGTH) + { + mvOsPrintf("mvCesaSessionOpen: macKeyLength %d is too large\n", + pSession->macKeyLength); + return MV_BAD_PARAM; + } + mvCesaHmacIvGet(pSession->macMode, pSession->macKey, pSession->macKeyLength, + pCesaSAD[sid].pSramSA->macInnerIV, + pCesaSAD[sid].pSramSA->macOuterIV); + pCesaSAD[sid].macKeyLength = pSession->macKeyLength; + } + switch(pSession->macMode) + { + case MV_CESA_MAC_MD5: + case MV_CESA_MAC_HMAC_MD5: + digestSize = MV_CESA_MD5_DIGEST_SIZE; + break; + + case MV_CESA_MAC_SHA1: + case MV_CESA_MAC_HMAC_SHA1: + digestSize = MV_CESA_SHA1_DIGEST_SIZE; + break; + + default: + mvOsPrintf("mvCesaSessionOpen: Unexpected macMode %d\n", + pSession->macMode); + return MV_BAD_PARAM; + } + config |= (pSession->macMode << MV_CESA_MAC_MODE_OFFSET); + + /* Supported digest sizes: MD5 - 16 bytes (128 bits), */ + /* SHA1 - 20 bytes (160 bits) or 12 bytes (96 bits) for both */ + if( (pSession->digestSize != digestSize) && (pSession->digestSize != 12)) + { + mvOsPrintf("mvCesaSessionOpen: Unexpected digest size %d\n", + pSession->digestSize); + mvOsPrintf("\t Valid values [bytes]: MD5-16, SHA1-20, Both-12\n"); + return MV_BAD_PARAM; + } + pCesaSAD[sid].digestSize = pSession->digestSize; + + if(pCesaSAD[sid].digestSize == 12) + { + /* Set MV_CESA_MAC_DIGEST_SIZE_BIT if digest size is 96 bits */ + config |= (MV_CESA_MAC_DIGEST_96B << MV_CESA_MAC_DIGEST_SIZE_BIT); + } + } + + /* Check CRYPTO parameters and update SA entry */ + if(pSession->operation != MV_CESA_MAC_ONLY) + { + switch(pSession->cryptoAlgorithm) + { + case MV_CESA_CRYPTO_DES: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_DES_KEY_LENGTH; + pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE; + break; + + case MV_CESA_CRYPTO_3DES: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_3DES_KEY_LENGTH; + pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE; + /* Only EDE mode is supported */ + config |= (MV_CESA_CRYPTO_3DES_EDE << + MV_CESA_CRYPTO_3DES_MODE_BIT); + break; + + case MV_CESA_CRYPTO_AES: + switch(pSession->cryptoKeyLength) + { + case 16: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_128_KEY_LENGTH; + config |= (MV_CESA_CRYPTO_AES_KEY_128 << + MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET); + break; + + case 24: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_192_KEY_LENGTH; + config |= (MV_CESA_CRYPTO_AES_KEY_192 << + MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET); + break; + + case 32: + default: + pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_256_KEY_LENGTH; + config |= (MV_CESA_CRYPTO_AES_KEY_256 << + MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET); + break; + } + pCesaSAD[sid].cryptoBlockSize = MV_CESA_AES_BLOCK_SIZE; + break; + + default: + mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoAlgorithm %d\n", + pSession->cryptoAlgorithm); + return MV_BAD_PARAM; + } + config |= (pSession->cryptoAlgorithm << MV_CESA_CRYPTO_ALG_OFFSET); + + if(pSession->cryptoKeyLength != pCesaSAD[sid].cryptoKeyLength) + { + mvOsPrintf("cesaSessionOpen: Wrong CryptoKeySize %d != %d\n", + pSession->cryptoKeyLength, pCesaSAD[sid].cryptoKeyLength); + return MV_BAD_PARAM; + } + + /* Copy Crypto key */ + if( (pSession->cryptoAlgorithm == MV_CESA_CRYPTO_AES) && + (pSession->direction == MV_CESA_DIR_DECODE)) + { + /* Crypto Key for AES decode is computed from original key material */ + /* and depend on cryptoKeyLength (128/192/256 bits) */ + aesMakeKey(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey, + pSession->cryptoKeyLength*8, MV_CESA_AES_BLOCK_SIZE*8); + } + else + { + /*panic("mvCesaSessionOpen2");*/ + memcpy(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey, + pCesaSAD[sid].cryptoKeyLength); + + } + + switch(pSession->cryptoMode) + { + case MV_CESA_CRYPTO_ECB: + pCesaSAD[sid].cryptoIvSize = 0; + break; + + case MV_CESA_CRYPTO_CBC: + pCesaSAD[sid].cryptoIvSize = pCesaSAD[sid].cryptoBlockSize; + break; + + case MV_CESA_CRYPTO_CTR: + /* Supported only for AES algorithm */ + if(pSession->cryptoAlgorithm != MV_CESA_CRYPTO_AES) + { + mvOsPrintf("mvCesaSessionOpen: CRYPTO CTR mode supported for AES only\n"); + return MV_BAD_PARAM; + } + pCesaSAD[sid].cryptoIvSize = 0; + pCesaSAD[sid].ctrMode = 1; + /* Replace to ECB mode for HW */ + pSession->cryptoMode = MV_CESA_CRYPTO_ECB; + break; + + default: + mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoMode %d\n", + pSession->cryptoMode); + return MV_BAD_PARAM; + } + + config |= (pSession->cryptoMode << MV_CESA_CRYPTO_MODE_BIT); + } + pCesaSAD[sid].config = config; + + mvOsCacheFlush(NULL, pCesaSAD[sid].pSramSA, sizeof(MV_CESA_SRAM_SA)); + if(pSid != NULL) + *pSid = sid; + + pCesaSAD[sid].valid = 1; + return MV_OK; +} + +/******************************************************************************* +* mvCesaSessionClose - Close active crypto session +* +* DESCRIPTION: +* This function closes existing session +* +* INPUT: +* short sid - Unique identifier of the session to be closed +* +* RETURN: +* MV_OK - Session closed successfully. +* MV_BAD_PARAM - Session identifier is out of valid range. +* MV_NOT_FOUND - There is no active session with such ID. +* +*******************************************************************************/ +MV_STATUS mvCesaSessionClose(short sid) +{ + cesaStats.closedCount++; + + if(sid >= cesaMaxSA) + { + mvOsPrintf("CESA Error: sid (%d) is too big\n", sid); + return MV_BAD_PARAM; + } + if(pCesaSAD[sid].valid == 0) + { + mvOsPrintf("CESA Warning: Session (sid=%d) is invalid\n", sid); + return MV_NOT_FOUND; + } + if(cesaLastSid == sid) + cesaLastSid = -1; + + pCesaSAD[sid].valid = 0; + return MV_OK; +} + +/******************************************************************************* +* mvCesaAction - Perform crypto operation +* +* DESCRIPTION: +* This function set new CESA request FIFO queue for further HW processing. +* The function checks request parameters before set new request to the queue. +* If one of the CESA channels is ready for processing the request will be +* passed to HW. When request processing is finished the CESA interrupt will +* be generated by HW. The caller should call mvCesaReadyGet() function to +* complete request processing and get result. +* +* INPUT: +* MV_CESA_COMMAND *pCmd - pointer to new CESA request. +* It includes pointers to Source and Destination +* buffers, session identifier get from +* mvCesaSessionOpen() function, pointer to caller +* private data and all needed crypto parameters. +* +* RETURN: +* MV_OK - request successfully added to request queue +* and will be processed. +* MV_NO_MORE - request successfully added to request queue and will +* be processed, but request queue became Full and next +* request will not be accepted. +* MV_NO_RESOURCE - request queue is FULL and the request can not +* be processed. +* MV_OUT_OF_CPU_MEM - memory allocation needed for request processing is +* failed. Request can not be processed. +* MV_NOT_ALLOWED - This mixed request (CRYPTO+MAC) can not be processed +* as one request and should be splitted for two requests: +* CRYPTO_ONLY and MAC_ONLY. +* MV_BAD_PARAM - One of the request parameters is out of valid range. +* The request can not be processed. +* +*******************************************************************************/ +MV_STATUS mvCesaAction (MV_CESA_COMMAND *pCmd) +{ + MV_STATUS status; + MV_CESA_REQ* pReq = pCesaReqEmpty; + int sid = pCmd->sessionId; + MV_CESA_SA* pSA = &pCesaSAD[sid]; + + cesaStats.reqCount++; + + /* Check that the request queue is not FULL */ + if(cesaReqResources == 0) + return MV_NO_RESOURCE; + + if( (sid >= cesaMaxSA) || (!pSA->valid) ) + { + mvOsPrintf("CESA Action Error: Session sid=%d is INVALID\n", sid); + return MV_BAD_PARAM; + } + pSA->count++; + + if(pSA->ctrMode) + { + /* AES in CTR mode can't be mixed with Authentication */ + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + mvOsPrintf("mvCesaAction : CRYPTO CTR mode can't be mixed with AUTH\n"); + return MV_NOT_ALLOWED; + } + /* All other request parameters should not be checked because key stream */ + /* (not user data) processed by AES HW engine */ + pReq->pOrgCmd = pCmd; + /* Allocate temporary pCmd structure for Key stream */ + pCmd = mvCesaCtrModeInit(); + if(pCmd == NULL) + return MV_OUT_OF_CPU_MEM; + + /* Prepare Key stream */ + mvCesaCtrModePrepare(pCmd, pReq->pOrgCmd); + pReq->fixOffset = 0; + } + else + { + /* Check request parameters and calculae fixOffset */ + status = mvCesaParamCheck(pSA, pCmd, &pReq->fixOffset); + if(status != MV_OK) + { + return status; + } + } + pReq->pCmd = pCmd; + + /* Check if the packet need fragmentation */ + if(pCmd->pSrc->mbufSize <= sizeof(cesaSramVirtPtr->buf) ) + { + /* request size is smaller than single buffer size */ + pReq->fragMode = MV_CESA_FRAG_NONE; + + /* Prepare NOT fragmented packets */ + status = mvCesaReqProcess(pReq); + if(status != MV_OK) + { + mvOsPrintf("CesaReady: ReqProcess error: pReq=%p, status=0x%x\n", + pReq, status); + } + } + else + { + MV_U8 frag = 0; + + /* request size is larger than buffer size - needs fragmentation */ + + /* Check restrictions for processing fragmented packets */ + status = mvCesaFragParamCheck(pSA, pCmd); + if(status != MV_OK) + return status; + + pReq->fragMode = MV_CESA_FRAG_FIRST; + pReq->frags.nextFrag = 0; + + /* Prepare Process Fragmented packets */ + while(pReq->fragMode != MV_CESA_FRAG_LAST) + { + if(frag >= MV_CESA_MAX_REQ_FRAGS) + { + mvOsPrintf("mvCesaAction Error: Too large request frag=%d\n", frag); + return MV_OUT_OF_CPU_MEM; + } + status = mvCesaFragReqProcess(pReq, frag); + if(status == MV_OK) + frag++; + } + pReq->frags.numFrag = frag; + } + + pReq->state = MV_CESA_PENDING; + + pCesaReqEmpty = MV_CESA_REQ_NEXT_PTR(pReq); + cesaReqResources -= 1; + +/* #ifdef CESA_DEBUG */ + if( (cesaQueueDepth - cesaReqResources) > cesaStats.maxReqCount) + cesaStats.maxReqCount = (cesaQueueDepth - cesaReqResources); +/* #endif CESA_DEBUG */ + + cesaLastSid = sid; + + /* Check status of CESA channels and process requests if possible */ + pReq = pCesaReqProcess; + if(pReq->state == MV_CESA_PENDING) + { + /* Start Process new request */ + mvCesaReqProcessStart(pReq); + } + /* If request queue became FULL - return MV_NO_MORE */ + if(cesaReqResources == 0) + return MV_NO_MORE; + + return MV_OK; +} + +/******************************************************************************* +* mvCesaReadyGet - Get crypto request that processing is finished +* +* DESCRIPTION: +* This function complete request processing and return ready request to +* caller. To don't miss interrupts the caller must call this function +* while MV_OK or MV_TERMINATE values returned. +* +* INPUT: +* MV_U32 chanMap - map of CESA channels finished thier job +* accordingly with CESA Cause register. +* MV_CESA_RESULT* pResult - pointer to structure contains information +* about ready request. It includes pointer to +* user private structure "pReqPrv", session identifier +* for this request "sessionId" and return code. +* Return code set to MV_FAIL if calculated digest value +* on decode direction is different than digest value +* in the packet. +* +* RETURN: +* MV_OK - Success, ready request is returned. +* MV_NOT_READY - Next request is not ready yet. New interrupt will +* be generated for futher request processing. +* MV_EMPTY - There is no more request for processing. +* MV_BUSY - Fragmented request is not ready yet. +* MV_TERMINATE - Call this function once more to complete processing +* of fragmented request. +* +*******************************************************************************/ +MV_STATUS mvCesaReadyGet(MV_CESA_RESULT* pResult) +{ + MV_STATUS status, readyStatus = MV_NOT_READY; + MV_U32 statusReg; + MV_CESA_REQ* pReq; + MV_CESA_SA* pSA; + + /* Check if there are request in process */ + if(pCesaReqProcess->state != MV_CESA_PROCESS) + { + return MV_EMPTY; + } + +#ifdef CESA_DEBUG + statusReg = MV_REG_READ(MV_CESA_STATUS_REG); + if( statusReg & MV_CESA_STATUS_ACTIVE_MASK ) + { + mvOsPrintf("mvCesaReadyGet: Not Ready, Status = 0x%x\n", statusReg); + cesaStats.notReadyCount++; + return MV_NOT_READY; + } +#endif /* CESA_DEBUG */ + + cesaStats.readyCount++; + + pReq = pCesaReqProcess; + pSA = &pCesaSAD[pReq->pCmd->sessionId]; + + pResult->retCode = MV_OK; + if(pReq->fragMode != MV_CESA_FRAG_NONE) + { + MV_U8* pNewDigest; + int frag = (pReq->frags.nextFrag - 1); + + /* Restore DMA descriptor list */ + pReq->dma[frag].pDmaLast->phyNextDescPtr = + MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[frag].pDmaLast[1])); + pReq->dma[frag].pDmaLast = NULL; + + /* Special processing for finished fragmented request */ + if(pReq->frags.nextFrag >= pReq->frags.numFrag) + { + /* Fragmented packet is ready */ + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + int macDataSize = pReq->pCmd->macLength - pReq->frags.macSize; + + if(macDataSize != 0) + { + /* Calculate all other blocks by SW */ + mvCesaFragAuthComplete(pReq, pSA, macDataSize); + } + + /* Copy new digest from SRAM to the Destination buffer */ + pNewDigest = cesaSramVirtPtr->buf + pReq->frags.newDigestOffset; + status = mvCesaCopyToMbuf(pNewDigest, pReq->pCmd->pDst, + pReq->pCmd->digestOffset, pSA->digestSize); + + /* For decryption: Compare new digest value with original one */ + if((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) + { + if( memcmp(pNewDigest, pReq->frags.orgDigest, pSA->digestSize) != 0) + { +/* + mvOsPrintf("Digest error: chan=%d, newDigest=%p, orgDigest=%p, status = 0x%x\n", + chan, pNewDigest, pReq->frags.orgDigest, MV_REG_READ(MV_CESA_STATUS_REG)); +*/ + /* Signiture verification is failed */ + pResult->retCode = MV_FAIL; + } + } + } + readyStatus = MV_OK; + } + } + else + { + /* Restore DMA descriptor list */ + pReq->dma[0].pDmaLast->phyNextDescPtr = + MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[0].pDmaLast[1])); + pReq->dma[0].pDmaLast = NULL; + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) && + ((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) ) + { + /* For AUTH on decode : Check Digest result in Status register */ + statusReg = MV_REG_READ(MV_CESA_STATUS_REG); + if(statusReg & MV_CESA_STATUS_DIGEST_ERR_MASK) + { +/* + mvOsPrintf("Digest error: chan=%d, status = 0x%x\n", + chan, statusReg); +*/ + /* Signiture verification is failed */ + pResult->retCode = MV_FAIL; + } + } + readyStatus = MV_OK; + } + + if(readyStatus == MV_OK) + { + /* If Request is ready - Prepare pResult structure */ + pResult->pReqPrv = pReq->pCmd->pReqPrv; + pResult->sessionId = pReq->pCmd->sessionId; + + pReq->state = MV_CESA_IDLE; + pCesaReqProcess = MV_CESA_REQ_NEXT_PTR(pReq); + cesaReqResources++; + + if(pSA->ctrMode) + { + /* For AES CTR mode - complete processing and free allocated resources */ + mvCesaCtrModeComplete(pReq->pOrgCmd, pReq->pCmd); + mvCesaCtrModeFinish(pReq->pCmd); + pReq->pOrgCmd = NULL; + } + } + + if(pCesaReqProcess->state == MV_CESA_PROCESS) + { + /* Start request Process */ + mvCesaReqProcessStart(pCesaReqProcess); + if(readyStatus == MV_NOT_READY) + readyStatus = MV_BUSY; + } + else if(pCesaReqProcess != pCesaReqEmpty) + { + /* Start process new request from the queue */ + mvCesaReqProcessStart(pCesaReqProcess); + } + return readyStatus; +} + +/***************** Functions to work with CESA_MBUF structure ******************/ + +/******************************************************************************* +* mvCesaMbufOffset - Locate offset in the Mbuf structure +* +* DESCRIPTION: +* This function locates offset inside Multi-Bufeer structure. +* It get fragment number and place in the fragment where the offset +* is located. +* +* +* INPUT: +* MV_CESA_MBUF* pMbuf - Pointer to multi-buffer structure +* int offset - Offset from the beginning of the data presented by +* the Mbuf structure. +* +* OUTPUT: +* int* pBufOffset - Offset from the beginning of the fragment where +* the offset is located. +* +* RETURN: +* int - Number of fragment, where the offset is located\ +* +*******************************************************************************/ +int mvCesaMbufOffset(MV_CESA_MBUF* pMbuf, int offset, int* pBufOffset) +{ + int frag = 0; + + while(offset > 0) + { + if(frag >= pMbuf->numFrags) + { + mvOsPrintf("mvCesaMbufOffset: Error: frag (%d) > numFrags (%d)\n", + frag, pMbuf->numFrags); + return MV_INVALID; + } + if(offset < pMbuf->pFrags[frag].bufSize) + { + break; + } + offset -= pMbuf->pFrags[frag].bufSize; + frag++; + } + if(pBufOffset != NULL) + *pBufOffset = offset; + + return frag; +} + +/******************************************************************************* +* mvCesaCopyFromMbuf - Copy data from the Mbuf structure to continuous buffer +* +* DESCRIPTION: +* +* +* INPUT: +* MV_U8* pDstBuf - Pointer to continuous buffer, where data is +* copied to. +* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is +* copied from. +* int offset - Offset in the Mbuf structure where located first +* byte of data should be copied. +* int size - Size of data should be copied +* +* RETURN: +* MV_OK - Success, all data is copied successfully. +* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range. +* No data is copied. +* MV_EMPTY - Multi-buffer structure has not enough data to copy +* Data from the offset to end of Mbuf data is copied. +* +*******************************************************************************/ +MV_STATUS mvCesaCopyFromMbuf(MV_U8* pDstBuf, MV_CESA_MBUF* pSrcMbuf, + int offset, int size) +{ + int frag, fragOffset, bufSize; + MV_U8* pBuf; + + if(size == 0) + return MV_OK; + + frag = mvCesaMbufOffset(pSrcMbuf, offset, &fragOffset); + if(frag == MV_INVALID) + { + mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset); + return MV_OUT_OF_RANGE; + } + + bufSize = pSrcMbuf->pFrags[frag].bufSize - fragOffset; + pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr + fragOffset; + while(MV_TRUE) + { + if(size <= bufSize) + { + memcpy(pDstBuf, pBuf, size); + return MV_OK; + } + memcpy(pDstBuf, pBuf, bufSize); + size -= bufSize; + frag++; + pDstBuf += bufSize; + if(frag >= pSrcMbuf->numFrags) + break; + + bufSize = pSrcMbuf->pFrags[frag].bufSize; + pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr; + } + mvOsPrintf("mvCesaCopyFromMbuf: Mbuf is EMPTY - %d bytes isn't copied\n", + size); + return MV_EMPTY; +} + +/******************************************************************************* +* mvCesaCopyToMbuf - Copy data from continuous buffer to the Mbuf structure +* +* DESCRIPTION: +* +* +* INPUT: +* MV_U8* pSrcBuf - Pointer to continuous buffer, where data is +* copied from. +* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is +* copied to. +* int offset - Offset in the Mbuf structure where located first +* byte of data should be copied. +* int size - Size of data should be copied +* +* RETURN: +* MV_OK - Success, all data is copied successfully. +* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range. +* No data is copied. +* MV_FULL - Multi-buffer structure has not enough place to copy +* all data. Data from the offset to end of Mbuf data +* is copied. +* +*******************************************************************************/ +MV_STATUS mvCesaCopyToMbuf(MV_U8* pSrcBuf, MV_CESA_MBUF* pDstMbuf, + int offset, int size) +{ + int frag, fragOffset, bufSize; + MV_U8* pBuf; + + if(size == 0) + return MV_OK; + + frag = mvCesaMbufOffset(pDstMbuf, offset, &fragOffset); + if(frag == MV_INVALID) + { + mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset); + return MV_OUT_OF_RANGE; + } + + bufSize = pDstMbuf->pFrags[frag].bufSize - fragOffset; + pBuf = pDstMbuf->pFrags[frag].bufVirtPtr + fragOffset; + while(MV_TRUE) + { + if(size <= bufSize) + { + memcpy(pBuf, pSrcBuf, size); + return MV_OK; + } + memcpy(pBuf, pSrcBuf, bufSize); + size -= bufSize; + frag++; + pSrcBuf += bufSize; + if(frag >= pDstMbuf->numFrags) + break; + + bufSize = pDstMbuf->pFrags[frag].bufSize; + pBuf = pDstMbuf->pFrags[frag].bufVirtPtr; + } + mvOsPrintf("mvCesaCopyToMbuf: Mbuf is FULL - %d bytes isn't copied\n", + size); + return MV_FULL; +} + +/******************************************************************************* +* mvCesaMbufCopy - Copy data from one Mbuf structure to the other Mbuf structure +* +* DESCRIPTION: +* +* +* INPUT: +* +* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is +* copied to. +* int dstMbufOffset - Offset in the dstMbuf structure where first byte +* of data should be copied to. +* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is +* copied from. +* int srcMbufOffset - Offset in the srcMbuf structure where first byte +* of data should be copied from. +* int size - Size of data should be copied +* +* RETURN: +* MV_OK - Success, all data is copied successfully. +* MV_OUT_OF_RANGE - Failed, srcMbufOffset or dstMbufOffset is out of +* srcMbuf or dstMbuf structure correspondently. +* No data is copied. +* MV_BAD_SIZE - srcMbuf or dstMbuf structure is too small to copy +* all data. Partial data is copied +* +*******************************************************************************/ +MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF* pMbufDst, int dstMbufOffset, + MV_CESA_MBUF* pMbufSrc, int srcMbufOffset, int size) +{ + int srcFrag, dstFrag, srcSize, dstSize, srcOffset, dstOffset; + int copySize; + MV_U8 *pSrc, *pDst; + + if(size == 0) + return MV_OK; + + srcFrag = mvCesaMbufOffset(pMbufSrc, srcMbufOffset, &srcOffset); + if(srcFrag == MV_INVALID) + { + mvOsPrintf("CESA srcMbuf Error: offset (%d) out of range\n", srcMbufOffset); + return MV_OUT_OF_RANGE; + } + pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr + srcOffset; + srcSize = pMbufSrc->pFrags[srcFrag].bufSize - srcOffset; + + dstFrag = mvCesaMbufOffset(pMbufDst, dstMbufOffset, &dstOffset); + if(dstFrag == MV_INVALID) + { + mvOsPrintf("CESA dstMbuf Error: offset (%d) out of range\n", dstMbufOffset); + return MV_OUT_OF_RANGE; + } + pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr + dstOffset; + dstSize = pMbufDst->pFrags[dstFrag].bufSize - dstOffset; + + while(size > 0) + { + copySize = MV_MIN(srcSize, dstSize); + if(size <= copySize) + { + memcpy(pDst, pSrc, size); + return MV_OK; + } + memcpy(pDst, pSrc, copySize); + size -= copySize; + srcSize -= copySize; + dstSize -= copySize; + + if(srcSize == 0) + { + srcFrag++; + if(srcFrag >= pMbufSrc->numFrags) + break; + + pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr; + srcSize = pMbufSrc->pFrags[srcFrag].bufSize; + } + + if(dstSize == 0) + { + dstFrag++; + if(dstFrag >= pMbufDst->numFrags) + break; + + pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr; + dstSize = pMbufDst->pFrags[dstFrag].bufSize; + } + } + mvOsPrintf("mvCesaMbufCopy: BAD size - %d bytes isn't copied\n", + size); + + return MV_BAD_SIZE; +} + +/*************************************** Local Functions ******************************/ + +/******************************************************************************* +* mvCesaFragReqProcess - Process fragmented request +* +* DESCRIPTION: +* This function processes a fragment of fragmented request (First, Middle or Last) +* +* +* INPUT: +* MV_CESA_REQ* pReq - Pointer to the request in the request queue. +* +* RETURN: +* MV_OK - The fragment is successfully passed to HW for processing. +* MV_TERMINATE - Means, that HW finished its work on this packet and no more +* interrupts will be generated for this request. +* Function mvCesaReadyGet() must be called to complete request +* processing and get request result. +* +*******************************************************************************/ +static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag) +{ + int i, copySize, cryptoDataSize, macDataSize, sid; + int cryptoIvOffset, digestOffset; + MV_U32 config; + MV_CESA_COMMAND* pCmd = pReq->pCmd; + MV_CESA_SA* pSA; + MV_CESA_MBUF* pMbuf; + MV_DMA_DESC* pDmaDesc = pReq->dma[frag].pDmaFirst; + MV_U8* pSramBuf = cesaSramVirtPtr->buf; + int macTotalLen = 0; + int fixOffset, cryptoOffset, macOffset; + + cesaStats.fragCount++; + + sid = pReq->pCmd->sessionId; + + pSA = &pCesaSAD[sid]; + + cryptoIvOffset = digestOffset = 0; + i = macDataSize = 0; + cryptoDataSize = 0; + + /* First fragment processing */ + if(pReq->fragMode == MV_CESA_FRAG_FIRST) + { + /* pReq->frags monitors processing of fragmented request between fragments */ + pReq->frags.bufOffset = 0; + pReq->frags.cryptoSize = 0; + pReq->frags.macSize = 0; + + config = pSA->config | (MV_CESA_FRAG_FIRST << MV_CESA_FRAG_MODE_OFFSET); + + /* fixOffset can be not equal to zero only for FIRST fragment */ + fixOffset = pReq->fixOffset; + /* For FIRST fragment crypto and mac offsets are taken from pCmd */ + cryptoOffset = pCmd->cryptoOffset; + macOffset = pCmd->macOffset; + + copySize = sizeof(cesaSramVirtPtr->buf) - pReq->fixOffset; + + /* Find fragment size: Must meet all requirements for CRYPTO and MAC + * cryptoDataSize - size of data will be encrypted/decrypted in this fragment + * macDataSize - size of data will be signed/verified in this fragment + * copySize - size of data will be copied from srcMbuf to SRAM and + * back to dstMbuf for this fragment + */ + mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset, + ©Size, &cryptoDataSize, &macDataSize); + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) + { + /* CryptoIV special processing */ + if( (pSA->config & MV_CESA_CRYPTO_MODE_MASK) == + (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT) ) + { + /* In CBC mode for encode direction when IV from user */ + if( (pCmd->ivFromUser) && + ((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) ) + { + + /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer, + * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place + * in the buffer to SRAM IVPointer + */ + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i], + MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize); + } + + /* Special processing when IV is not located in the first fragment */ + if(pCmd->ivOffset > (copySize - pSA->cryptoIvSize)) + { + /* Prepare dummy place for cryptoIV in SRAM */ + cryptoIvOffset = cesaSramVirtPtr->tempCryptoIV - mvCesaSramAddrGet(); + + /* For Decryption: Copy IV value from pCmd->ivOffset to Special SRAM place */ + if((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) + { + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->tempCryptoIV, &pDmaDesc[i], + MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize); + } + else + { + /* For Encryption when IV is NOT from User: */ + /* Copy IV from SRAM to buffer (pCmd->ivOffset) */ + if(pCmd->ivFromUser == 0) + { + /* copy IV value from cryptoIV to Buffer (pCmd->ivOffset) */ + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i], + MV_TRUE, pCmd->ivOffset, pSA->cryptoIvSize); + } + } + } + else + { + cryptoIvOffset = pCmd->ivOffset; + } + } + } + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + /* MAC digest special processing on Decode direction */ + if((pSA->config & MV_CESA_DIRECTION_MASK) == + (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) + { + /* Save digest from pCmd->digestOffset */ + mvCesaCopyFromMbuf(pReq->frags.orgDigest, + pCmd->pSrc, pCmd->digestOffset, pSA->digestSize); + + /* If pCmd->digestOffset is not located on the first */ + if(pCmd->digestOffset > (copySize - pSA->digestSize)) + { + MV_U8 digestZero[MV_CESA_MAX_DIGEST_SIZE]; + + /* Set zeros to pCmd->digestOffset (DRAM) */ + memset(digestZero, 0, MV_CESA_MAX_DIGEST_SIZE); + mvCesaCopyToMbuf(digestZero, pCmd->pSrc, pCmd->digestOffset, pSA->digestSize); + + /* Prepare dummy place for digest in SRAM */ + digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet(); + } + else + { + digestOffset = pCmd->digestOffset; + } + } + } + /* Update SA in SRAM */ + if(cesaLastSid != sid) + { + mvCesaSramSaUpdate(sid, &pDmaDesc[i]); + i++; + } + + pReq->fragMode = MV_CESA_FRAG_MIDDLE; + } + else + { + /* Continue fragment */ + fixOffset = 0; + cryptoOffset = 0; + macOffset = 0; + if( (pCmd->pSrc->mbufSize - pReq->frags.bufOffset) <= sizeof(cesaSramVirtPtr->buf)) + { + /* Last fragment */ + config = pSA->config | (MV_CESA_FRAG_LAST << MV_CESA_FRAG_MODE_OFFSET); + pReq->fragMode = MV_CESA_FRAG_LAST; + copySize = pCmd->pSrc->mbufSize - pReq->frags.bufOffset; + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + macDataSize = pCmd->macLength - pReq->frags.macSize; + + /* If pCmd->digestOffset is not located on last fragment */ + if(pCmd->digestOffset < pReq->frags.bufOffset) + { + /* Prepare dummy place for digest in SRAM */ + digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet(); + } + else + { + digestOffset = pCmd->digestOffset - pReq->frags.bufOffset; + } + pReq->frags.newDigestOffset = digestOffset; + macTotalLen = pCmd->macLength; + + /* HW can't calculate the Digest correctly for fragmented packets + * in the following cases: + * - MV88F5182 || + * - MV88F5181L when total macLength more that 16 Kbytes || + * - total macLength more that 64 Kbytes + */ + if( (mvCtrlModelGet() == MV_5182_DEV_ID) || + ( (mvCtrlModelGet() == MV_5181_DEV_ID) && + (mvCtrlRevGet() >= MV_5181L_A0_REV) && + (pCmd->macLength >= (1 << 14)) ) ) + { + return MV_TERMINATE; + } + } + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + cryptoDataSize = pCmd->cryptoLength - pReq->frags.cryptoSize; + } + + /* cryptoIvOffset - don't care */ + } + else + { + /* WA for MV88F5182 SHA1 and MD5 fragmentation mode */ + if( (mvCtrlModelGet() == MV_5182_DEV_ID) && + (((pSA->config & MV_CESA_MAC_MODE_MASK) == + (MV_CESA_MAC_MD5 << MV_CESA_MAC_MODE_OFFSET)) || + ((pSA->config & MV_CESA_MAC_MODE_MASK) == + (MV_CESA_MAC_SHA1 << MV_CESA_MAC_MODE_OFFSET))) ) + { + pReq->frags.newDigestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet(); + pReq->fragMode = MV_CESA_FRAG_LAST; + + return MV_TERMINATE; + } + /* Middle fragment */ + config = pSA->config | (MV_CESA_FRAG_MIDDLE << MV_CESA_FRAG_MODE_OFFSET); + copySize = sizeof(cesaSramVirtPtr->buf); + /* digestOffset and cryptoIvOffset - don't care */ + + /* Find fragment size */ + mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset, + ©Size, &cryptoDataSize, &macDataSize); + } + } + /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/ + pMbuf = pCmd->pSrc; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_FALSE, pReq->frags.bufOffset, copySize); + + /* Prepare CESA descriptor to copy from DRAM to SRAM by DMA */ + mvCesaSramDescrBuild(config, frag, + cryptoOffset + fixOffset, cryptoIvOffset + fixOffset, + cryptoDataSize, macOffset + fixOffset, + digestOffset + fixOffset, macDataSize, macTotalLen, + pReq, &pDmaDesc[i]); + i++; + + /* Add special descriptor Ownership for CPU */ + pDmaDesc[i].byteCnt = 0; + pDmaDesc[i].phySrcAdd = 0; + pDmaDesc[i].phyDestAdd = 0; + i++; + + /********* Prepare DMA descriptors to copy from SRAM to pDst *********/ + pMbuf = pCmd->pDst; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_TRUE, pReq->frags.bufOffset, copySize); + + /* Next field of Last DMA descriptor must be NULL */ + pDmaDesc[i-1].phyNextDescPtr = 0; + pReq->dma[frag].pDmaLast = &pDmaDesc[i-1]; + mvOsCacheFlush(NULL, pReq->dma[frag].pDmaFirst, + i*sizeof(MV_DMA_DESC)); + + /*mvCesaDebugDescriptor(&cesaSramVirtPtr->desc[frag]);*/ + + pReq->frags.bufOffset += copySize; + pReq->frags.cryptoSize += cryptoDataSize; + pReq->frags.macSize += macDataSize; + + return MV_OK; +} + + +/******************************************************************************* +* mvCesaReqProcess - Process regular (Non-fragmented) request +* +* DESCRIPTION: +* This function processes the whole (not fragmented) request +* +* INPUT: +* MV_CESA_REQ* pReq - Pointer to the request in the request queue. +* +* RETURN: +* MV_OK - The request is successfully passed to HW for processing. +* Other - Failure. The request will not be processed +* +*******************************************************************************/ +static MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq) +{ + MV_CESA_MBUF *pMbuf; + MV_DMA_DESC *pDmaDesc; + MV_U8 *pSramBuf; + int sid, i, fixOffset; + MV_CESA_SA *pSA; + MV_CESA_COMMAND *pCmd = pReq->pCmd; + + cesaStats.procCount++; + + sid = pCmd->sessionId; + pSA = &pCesaSAD[sid]; + pDmaDesc = pReq->dma[0].pDmaFirst; + pSramBuf = cesaSramVirtPtr->buf; + fixOffset = pReq->fixOffset; + +/* + mvOsPrintf("mvCesaReqProcess: sid=%d, pSA=%p, pDmaDesc=%p, pSramBuf=%p\n", + sid, pSA, pDmaDesc, pSramBuf); +*/ + i = 0; + + /* Crypto IV Special processing in CBC mode for Encryption direction */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) && + ((pSA->config & MV_CESA_CRYPTO_MODE_MASK) == (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT)) && + ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) && + (pCmd->ivFromUser) ) + { + /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer, + * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place + * in the buffer to SRAM IVPointer + */ + i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i], + MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize); + } + + /* Update SA in SRAM */ + if(cesaLastSid != sid) + { + mvCesaSramSaUpdate(sid, &pDmaDesc[i]); + i++; + } + + /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/ + pMbuf = pCmd->pSrc; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_FALSE, 0, pMbuf->mbufSize); + + /* Prepare Security Accelerator descriptor to SRAM words 0 - 7 */ + mvCesaSramDescrBuild(pSA->config, 0, pCmd->cryptoOffset + fixOffset, + pCmd->ivOffset + fixOffset, pCmd->cryptoLength, + pCmd->macOffset + fixOffset, pCmd->digestOffset + fixOffset, + pCmd->macLength, pCmd->macLength, pReq, &pDmaDesc[i]); + i++; + + /* Add special descriptor Ownership for CPU */ + pDmaDesc[i].byteCnt = 0; + pDmaDesc[i].phySrcAdd = 0; + pDmaDesc[i].phyDestAdd = 0; + i++; + + /********* Prepare DMA descriptors to copy from SRAM to pDst *********/ + pMbuf = pCmd->pDst; + i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i], + MV_TRUE, 0, pMbuf->mbufSize); + + /* Next field of Last DMA descriptor must be NULL */ + pDmaDesc[i-1].phyNextDescPtr = 0; + pReq->dma[0].pDmaLast = &pDmaDesc[i-1]; + mvOsCacheFlush(NULL, pReq->dma[0].pDmaFirst, i*sizeof(MV_DMA_DESC)); + + return MV_OK; +} + + +/******************************************************************************* +* mvCesaSramDescrBuild - Set CESA descriptor in SRAM +* +* DESCRIPTION: +* This function builds CESA descriptor in SRAM from all Command parameters +* +* +* INPUT: +* int chan - CESA channel uses the descriptor +* MV_U32 config - 32 bits of WORD_0 in CESA descriptor structure +* int cryptoOffset - Offset from the beginning of SRAM buffer where +* data for encryption/decription is started. +* int ivOffset - Offset of crypto IV from the SRAM base. Valid only +* for first fragment. +* int cryptoLength - Size (in bytes) of data for encryption/descryption +* operation on this fragment. +* int macOffset - Offset from the beginning of SRAM buffer where +* data for Authentication is started +* int digestOffset - Offset from the beginning of SRAM buffer where +* digest is located. Valid for first and last fragments. +* int macLength - Size (in bytes) of data for Authentication +* operation on this fragment. +* int macTotalLen - Toatl size (in bytes) of data for Authentication +* operation on the whole request (packet). Valid for +* last fragment only. +* +* RETURN: None +* +*******************************************************************************/ +static void mvCesaSramDescrBuild(MV_U32 config, int frag, + int cryptoOffset, int ivOffset, int cryptoLength, + int macOffset, int digestOffset, int macLength, + int macTotalLen, MV_CESA_REQ* pReq, MV_DMA_DESC* pDmaDesc) +{ + MV_CESA_DESC* pCesaDesc = &pReq->pCesaDesc[frag]; + MV_CESA_DESC* pSramDesc = pSramDesc = &cesaSramVirtPtr->desc; + MV_U16 sramBufOffset = (MV_U16)((MV_U8*)cesaSramVirtPtr->buf - mvCesaSramAddrGet()); + + pCesaDesc->config = MV_32BIT_LE(config); + + if( (config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + /* word 1 */ + pCesaDesc->cryptoSrcOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset); + pCesaDesc->cryptoDstOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset); + /* word 2 */ + pCesaDesc->cryptoDataLen = MV_16BIT_LE(cryptoLength); + /* word 3 */ + pCesaDesc->cryptoKeyOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.cryptoKey - + mvCesaSramAddrGet())); + /* word 4 */ + pCesaDesc->cryptoIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->cryptoIV - + mvCesaSramAddrGet())); + pCesaDesc->cryptoIvBufOffset = MV_16BIT_LE(sramBufOffset + ivOffset); + } + + if( (config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + /* word 5 */ + pCesaDesc->macSrcOffset = MV_16BIT_LE(sramBufOffset + macOffset); + pCesaDesc->macTotalLen = MV_16BIT_LE(macTotalLen); + + /* word 6 */ + pCesaDesc->macDigestOffset = MV_16BIT_LE(sramBufOffset + digestOffset); + pCesaDesc->macDataLen = MV_16BIT_LE(macLength); + + /* word 7 */ + pCesaDesc->macInnerIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macInnerIV - + mvCesaSramAddrGet())); + pCesaDesc->macOuterIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macOuterIV - + mvCesaSramAddrGet())); + } + /* Prepare DMA descriptor to CESA descriptor from DRAM to SRAM */ + pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&pReq->cesaDescBuf, pCesaDesc)); + pDmaDesc->phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)pSramDesc)); + pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_DESC) | BIT31); + + /* flush Source buffer */ + mvOsCacheFlush(NULL, pCesaDesc, sizeof(MV_CESA_DESC)); +} + +/******************************************************************************* +* mvCesaSramSaUpdate - Move required SA information to SRAM if needed. +* +* DESCRIPTION: +* Copy to SRAM values of the required SA. +* +* +* INPUT: +* short sid - Session ID needs SRAM Cache update +* MV_DMA_DESC *pDmaDesc - Pointer to DMA descriptor used to +* copy SA values from DRAM to SRAM. +* +* RETURN: +* MV_OK - Cache entry for this SA copied to SRAM. +* MV_NO_CHANGE - Cache entry for this SA already exist in SRAM +* +*******************************************************************************/ +static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc) +{ + MV_CESA_SA *pSA = &pCesaSAD[sid]; + + /* Prepare DMA descriptor to Copy CACHE_SA from SA database in DRAM to SRAM */ + pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_SRAM_SA) | BIT31); + pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&cesaSramSaBuf, pSA->pSramSA)); + pDmaDesc->phyDestAdd = + MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)&cesaSramVirtPtr->sramSA)); + + /* Source buffer is already flushed during OpenSession*/ + /*mvOsCacheFlush(NULL, &pSA->sramSA, sizeof(MV_CESA_SRAM_SA));*/ +} + +/******************************************************************************* +* mvCesaDmaCopyPrepare - prepare DMA descriptor list to copy data presented by +* Mbuf structure from DRAM to SRAM +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_MBUF* pMbuf - pointer to Mbuf structure contains request +* data in DRAM +* MV_U8* pSramBuf - pointer to buffer in SRAM where data should +* be copied to. +* MV_DMA_DESC* pDmaDesc - pointer to first DMA descriptor for this copy. +* The function set number of DMA descriptors needed +* to copy the copySize bytes from Mbuf. +* MV_BOOL isToMbuf - Copy direction. +* MV_TRUE means copy from SRAM buffer to Mbuf in DRAM. +* MV_FALSE means copy from Mbuf in DRAM to SRAM buffer. +* int offset - Offset in the Mbuf structure that copy should be +* started from. +* int copySize - Size of data should be copied. +* +* RETURN: +* int - number of DMA descriptors used for the copy. +* +*******************************************************************************/ +#ifndef MV_NETBSD +static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf, + MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf, + int offset, int copySize) +{ + int bufOffset, bufSize, size, frag, i; + MV_U8* pBuf; + + i = 0; + + /* Calculate start place for copy: fragment number and offset in the fragment */ + frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset); + bufSize = pMbuf->pFrags[frag].bufSize - bufOffset; + pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset; + + /* Size accumulate total copy size */ + size = 0; + + /* Create DMA lists to copy mBuf from pSrc to SRAM */ + while(size < copySize) + { + /* Find copy size for each DMA descriptor */ + bufSize = MV_MIN(bufSize, (copySize - size)); + pDmaDesc[i].byteCnt = MV_32BIT_LE(bufSize | BIT31); + if(isToMbuf) + { + pDmaDesc[i].phyDestAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf)); + pDmaDesc[i].phySrcAdd = + MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size))); + /* invalidate the buffer */ + mvOsCacheInvalidate(NULL, pBuf, bufSize); + } + else + { + pDmaDesc[i].phySrcAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf)); + pDmaDesc[i].phyDestAdd = + MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size))); + /* flush the buffer */ + mvOsCacheFlush(NULL, pBuf, bufSize); + } + + /* Count number of used DMA descriptors */ + i++; + size += bufSize; + + /* go to next fragment in the Mbuf */ + frag++; + pBuf = pMbuf->pFrags[frag].bufVirtPtr; + bufSize = pMbuf->pFrags[frag].bufSize; + } + return i; +} +#else /* MV_NETBSD */ +static int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf, + MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf, + int offset, int copySize) +{ + int bufOffset, bufSize, thisSize, size, frag, i; + MV_ULONG bufPhys, sramPhys; + MV_U8* pBuf; + + /* + * Calculate start place for copy: fragment number and offset in + * the fragment + */ + frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset); + + /* + * Get SRAM physical address only once. We can update it in-place + * as we build the descriptor chain. + */ + sramPhys = mvCesaSramVirtToPhys(NULL, pSramBuf); + + /* + * 'size' accumulates total copy size, 'i' counts desccriptors. + */ + size = i = 0; + + /* Create DMA lists to copy mBuf from pSrc to SRAM */ + while (size < copySize) { + /* + * Calculate # of bytes to copy from the current fragment, + * and the pointer to the start of data + */ + bufSize = pMbuf->pFrags[frag].bufSize - bufOffset; + pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset; + bufOffset = 0; /* First frag may be non-zero */ + frag++; + + /* + * As long as there is data in the current fragment... + */ + while (bufSize > 0) { + /* + * Ensure we don't cross an MMU page boundary. + * XXX: This is NetBSD-specific, but it is a + * quick and dirty way to fix the problem. + * A true HAL would rely on the OS-specific + * driver to do this... + */ + thisSize = PAGE_SIZE - + (((MV_ULONG)pBuf) & (PAGE_SIZE - 1)); + thisSize = MV_MIN(bufSize, thisSize); + /* + * Make sure we don't copy more than requested + */ + if (thisSize > (copySize - size)) { + thisSize = copySize - size; + bufSize = 0; + } + + /* + * Physicall address of this fragment + */ + bufPhys = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf)); + + /* + * Set up the descriptor + */ + pDmaDesc[i].byteCnt = MV_32BIT_LE(thisSize | BIT31); + if(isToMbuf) { + pDmaDesc[i].phyDestAdd = bufPhys; + pDmaDesc[i].phySrcAdd = MV_32BIT_LE(sramPhys); + /* invalidate the buffer */ + mvOsCacheInvalidate(NULL, pBuf, thisSize); + } else { + pDmaDesc[i].phySrcAdd = bufPhys; + pDmaDesc[i].phyDestAdd = MV_32BIT_LE(sramPhys); + /* flush the buffer */ + mvOsCacheFlush(NULL, pBuf, thisSize); + } + + pDmaDesc[i].phyNextDescPtr = + MV_32BIT_LE(mvOsIoVirtToPhy(NULL,(&pDmaDesc[i+1]))); + + /* flush the DMA desc */ + mvOsCacheFlush(NULL, &pDmaDesc[i], sizeof(MV_DMA_DESC)); + + /* Update state */ + bufSize -= thisSize; + sramPhys += thisSize; + pBuf += thisSize; + size += thisSize; + i++; + } + } + + return i; +} +#endif /* MV_NETBSD */ +/******************************************************************************* +* mvCesaHmacIvGet - Calculate Inner and Outter values from HMAC key +* +* DESCRIPTION: +* This function calculate Inner and Outer values used for HMAC algorithm. +* This operation allows improve performance fro the whole HMAC processing. +* +* INPUT: +* MV_CESA_MAC_MODE macMode - Authentication mode: HMAC_MD5 or HMAC_SHA1. +* unsigned char key[] - Pointer to HMAC key. +* int keyLength - Size of HMAC key (maximum 64 bytes) +* +* OUTPUT: +* unsigned char innerIV[] - HASH(key^inner) +* unsigned char outerIV[] - HASH(key^outter) +* +* RETURN: None +* +*******************************************************************************/ +static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength, + unsigned char innerIV[], unsigned char outerIV[]) +{ + unsigned char inner[MV_CESA_MAX_MAC_KEY_LENGTH]; + unsigned char outer[MV_CESA_MAX_MAC_KEY_LENGTH]; + int i, digestSize = 0; +#if defined(MV_CPU_LE) || defined(MV_PPC) + MV_U32 swapped32, val32, *pVal32; +#endif + for(i=0; ipFrags[frag].bufVirtPtr + fragOffset; + size = pMbuf->pFrags[frag].bufSize - fragOffset; + + /* Complete Inner part */ + while(macLeftSize > 0) + { + if(macLeftSize <= size) + { + mvSHA1Update(&ctx, pData, macLeftSize); + break; + } + mvSHA1Update(&ctx, pData, size); + macLeftSize -= size; + frag++; + pData = pMbuf->pFrags[frag].bufVirtPtr; + size = pMbuf->pFrags[frag].bufSize; + } + mvSHA1Final(pDigest, &ctx); +/* + mvOsPrintf("mvCesaFragSha1Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n", + pOuterIV, macLeftSize, macTotalSize); + mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1); +*/ + + if(pOuterIV != NULL) + { + /* If HMAC - Complete Outer part */ + for(i=0; ipFrags[frag].bufVirtPtr + fragOffset; + size = pMbuf->pFrags[frag].bufSize - fragOffset; + + /* Complete Inner part */ + while(macLeftSize > 0) + { + if(macLeftSize <= size) + { + mvMD5Update(&ctx, pData, macLeftSize); + break; + } + mvMD5Update(&ctx, pData, size); + macLeftSize -= size; + frag++; + pData = pMbuf->pFrags[frag].bufVirtPtr; + size = pMbuf->pFrags[frag].bufSize; + } + mvMD5Final(pDigest, &ctx); + +/* + mvOsPrintf("mvCesaFragMd5Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n", + pOuterIV, macLeftSize, macTotalSize); + mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1); +*/ + if(pOuterIV != NULL) + { + /* Complete Outer part */ + for(i=0; ipCmd; + MV_U8* pDigest; + MV_CESA_MAC_MODE macMode; + MV_U8* pOuterIV = NULL; + + /* Copy data from Source fragment to Destination */ + if(pCmd->pSrc != pCmd->pDst) + { + mvCesaMbufCopy(pCmd->pDst, pReq->frags.bufOffset, + pCmd->pSrc, pReq->frags.bufOffset, macDataSize); + } + +/* + mvCesaCopyFromMbuf(cesaSramVirtPtr->buf[0], pCmd->pSrc, pReq->frags.bufOffset, macDataSize); + mvCesaCopyToMbuf(cesaSramVirtPtr->buf[0], pCmd->pDst, pReq->frags.bufOffset, macDataSize); +*/ + pDigest = (mvCesaSramAddrGet() + pReq->frags.newDigestOffset); + + macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET; +/* + mvOsPrintf("macDataSize=%d, macLength=%d, digestOffset=%d, macMode=%d\n", + macDataSize, pCmd->macLength, pCmd->digestOffset, macMode); +*/ + switch(macMode) + { + case MV_CESA_MAC_HMAC_MD5: + pOuterIV = pSA->pSramSA->macOuterIV; + + case MV_CESA_MAC_MD5: + mvCesaFragMd5Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV, + macDataSize, pCmd->macLength, pDigest); + break; + + case MV_CESA_MAC_HMAC_SHA1: + pOuterIV = pSA->pSramSA->macOuterIV; + + case MV_CESA_MAC_SHA1: + mvCesaFragSha1Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV, + macDataSize, pCmd->macLength, pDigest); + break; + + default: + mvOsPrintf("mvCesaFragAuthComplete: Unexpected macMode %d\n", macMode); + return MV_BAD_PARAM; + } + return MV_OK; +} + +/******************************************************************************* +* mvCesaCtrModeInit - +* +* DESCRIPTION: +* +* +* INPUT: NONE +* +* +* RETURN: +* MV_CESA_COMMAND* +* +*******************************************************************************/ +static MV_CESA_COMMAND* mvCesaCtrModeInit(void) +{ + MV_CESA_MBUF *pMbuf; + MV_U8 *pBuf; + MV_CESA_COMMAND *pCmd; + + pBuf = mvOsMalloc(sizeof(MV_CESA_COMMAND) + + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) + 100); + if(pBuf == NULL) + { + mvOsPrintf("mvCesaSessionOpen: Can't allocate %u bytes for CTR Mode\n", + sizeof(MV_CESA_COMMAND) + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) ); + return NULL; + } + pCmd = (MV_CESA_COMMAND*)pBuf; + pBuf += sizeof(MV_CESA_COMMAND); + + pMbuf = (MV_CESA_MBUF*)pBuf; + pBuf += sizeof(MV_CESA_MBUF); + + pMbuf->pFrags = (MV_BUF_INFO*)pBuf; + + pMbuf->numFrags = 1; + pCmd->pSrc = pMbuf; + pCmd->pDst = pMbuf; +/* + mvOsPrintf("CtrModeInit: pCmd=%p, pSrc=%p, pDst=%p, pFrags=%p\n", + pCmd, pCmd->pSrc, pCmd->pDst, + pMbuf->pFrags); +*/ + return pCmd; +} + +/******************************************************************************* +* mvCesaCtrModePrepare - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd) +{ + MV_CESA_MBUF *pMbuf; + MV_U8 *pBuf, *pIV; + MV_U32 counter, *pCounter; + int cryptoSize = MV_ALIGN_UP(pCmd->cryptoLength, MV_CESA_AES_BLOCK_SIZE); +/* + mvOsPrintf("CtrModePrepare: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n", + pCmd, pCmd->pSrc, pCmd->pDst, + pCtrModeCmd, pCtrModeCmd->pSrc, pCtrModeCmd->pDst); +*/ + pMbuf = pCtrModeCmd->pSrc; + + /* Allocate buffer for Key stream */ + pBuf = mvOsIoCachedMalloc(cesaOsHandle,cryptoSize, + &pMbuf->pFrags[0].bufPhysAddr, + &pMbuf->pFrags[0].memHandle); + if(pBuf == NULL) + { + mvOsPrintf("mvCesaCtrModePrepare: Can't allocate %d bytes\n", cryptoSize); + return MV_OUT_OF_CPU_MEM; + } + memset(pBuf, 0, cryptoSize); + mvOsCacheFlush(NULL, pBuf, cryptoSize); + + pMbuf->pFrags[0].bufVirtPtr = pBuf; + pMbuf->mbufSize = cryptoSize; + pMbuf->pFrags[0].bufSize = cryptoSize; + + pCtrModeCmd->pReqPrv = pCmd->pReqPrv; + pCtrModeCmd->sessionId = pCmd->sessionId; + + /* ivFromUser and ivOffset are don't care */ + pCtrModeCmd->cryptoOffset = 0; + pCtrModeCmd->cryptoLength = cryptoSize; + + /* digestOffset, macOffset and macLength are don't care */ + + mvCesaCopyFromMbuf(pBuf, pCmd->pSrc, pCmd->ivOffset, MV_CESA_AES_BLOCK_SIZE); + pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter))); + counter = *pCounter; + counter = MV_32BIT_BE(counter); + pIV = pBuf; + cryptoSize -= MV_CESA_AES_BLOCK_SIZE; + + /* fill key stream */ + while(cryptoSize > 0) + { + pBuf += MV_CESA_AES_BLOCK_SIZE; + memcpy(pBuf, pIV, MV_CESA_AES_BLOCK_SIZE - sizeof(counter)); + pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter))); + counter++; + *pCounter = MV_32BIT_BE(counter); + cryptoSize -= MV_CESA_AES_BLOCK_SIZE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvCesaCtrModeComplete - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd) +{ + int srcFrag, dstFrag, srcOffset, dstOffset, keyOffset, srcSize, dstSize; + int cryptoSize = pCmd->cryptoLength; + MV_U8 *pSrc, *pDst, *pKey; + MV_STATUS status = MV_OK; +/* + mvOsPrintf("CtrModeComplete: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n", + pCmd, pCmd->pSrc, pCmd->pDst, + pOrgCmd, pOrgCmd->pSrc, pOrgCmd->pDst); +*/ + /* XOR source data with key stream to destination data */ + pKey = pCmd->pDst->pFrags[0].bufVirtPtr; + keyOffset = 0; + + if( (pOrgCmd->pSrc != pOrgCmd->pDst) && + (pOrgCmd->cryptoOffset > 0) ) + { + /* Copy Prefix from source buffer to destination buffer */ + + status = mvCesaMbufCopy(pOrgCmd->pDst, 0, + pOrgCmd->pSrc, 0, pOrgCmd->cryptoOffset); +/* + status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc, + 0, pOrgCmd->cryptoOffset); + status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst, + 0, pOrgCmd->cryptoOffset); +*/ + } + + srcFrag = mvCesaMbufOffset(pOrgCmd->pSrc, pOrgCmd->cryptoOffset, &srcOffset); + pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr; + srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize; + + dstFrag = mvCesaMbufOffset(pOrgCmd->pDst, pOrgCmd->cryptoOffset, &dstOffset); + pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr; + dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize; + + while(cryptoSize > 0) + { + pDst[dstOffset] = (pSrc[srcOffset] ^ pKey[keyOffset]); + + cryptoSize--; + dstOffset++; + srcOffset++; + keyOffset++; + + if(srcOffset >= srcSize) + { + srcFrag++; + srcOffset = 0; + pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr; + srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize; + } + + if(dstOffset >= dstSize) + { + dstFrag++; + dstOffset = 0; + pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr; + dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize; + } + } + + if(pOrgCmd->pSrc != pOrgCmd->pDst) + { + /* Copy Suffix from source buffer to destination buffer */ + srcOffset = pOrgCmd->cryptoOffset + pOrgCmd->cryptoLength; + + if( (pOrgCmd->pDst->mbufSize - srcOffset) > 0) + { + status = mvCesaMbufCopy(pOrgCmd->pDst, srcOffset, + pOrgCmd->pSrc, srcOffset, + pOrgCmd->pDst->mbufSize - srcOffset); + } + +/* + status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc, + srcOffset, pOrgCmd->pSrc->mbufSize - srcOffset); + status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst, + srcOffset, pOrgCmd->pDst->mbufSize - srcOffset); +*/ + } + + /* Free buffer used for Key stream */ + mvOsIoCachedFree(cesaOsHandle,pCmd->pDst->pFrags[0].bufSize, + pCmd->pDst->pFrags[0].bufPhysAddr, + pCmd->pDst->pFrags[0].bufVirtPtr, + pCmd->pDst->pFrags[0].memHandle); + + return MV_OK; +} + +/******************************************************************************* +* mvCesaCtrModeFinish - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_COMMAND* pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static void mvCesaCtrModeFinish(MV_CESA_COMMAND* pCmd) +{ + mvOsFree(pCmd); +} + +/******************************************************************************* +* mvCesaParamCheck - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, + MV_U8* pFixOffset) +{ + MV_U8 fixOffset = 0xFF; + + /* Check AUTH operation parameters */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* MAC offset should be at least 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->macOffset, 4) ) + { + mvOsPrintf("mvCesaAction: macOffset %d must be 4 byte aligned\n", + pCmd->macOffset); + return MV_BAD_PARAM; + } + /* Digest offset must be 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->digestOffset, 4) ) + { + mvOsPrintf("mvCesaAction: digestOffset %d must be 4 byte aligned\n", + pCmd->digestOffset); + return MV_BAD_PARAM; + } + /* In addition all offsets should be the same alignment: 8 or 4 */ + if(fixOffset == 0xFF) + { + fixOffset = (pCmd->macOffset % 8); + } + else + { + if( (pCmd->macOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: macOffset %d mod 8 must be equal %d\n", + pCmd->macOffset, fixOffset); + return MV_BAD_PARAM; + } + } + if( (pCmd->digestOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: digestOffset %d mod 8 must be equal %d\n", + pCmd->digestOffset, fixOffset); + return MV_BAD_PARAM; + } + } + /* Check CRYPTO operation parameters */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* CryptoOffset should be at least 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->cryptoOffset, 4) ) + { + mvOsPrintf("CesaAction: cryptoOffset=%d must be 4 byte aligned\n", + pCmd->cryptoOffset); + return MV_BAD_PARAM; + } + /* cryptoLength should be the whole number of blocks */ + if( MV_IS_NOT_ALIGN(pCmd->cryptoLength, pSA->cryptoBlockSize) ) + { + mvOsPrintf("mvCesaAction: cryptoLength=%d must be %d byte aligned\n", + pCmd->cryptoLength, pSA->cryptoBlockSize); + return MV_BAD_PARAM; + } + if(fixOffset == 0xFF) + { + fixOffset = (pCmd->cryptoOffset % 8); + } + else + { + /* In addition all offsets should be the same alignment: 8 or 4 */ + if( (pCmd->cryptoOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: cryptoOffset %d mod 8 must be equal %d \n", + pCmd->cryptoOffset, fixOffset); + return MV_BAD_PARAM; + } + } + + /* check for CBC mode */ + if(pSA->cryptoIvSize > 0) + { + /* cryptoIV must not be part of CryptoLength */ + if( ((pCmd->ivOffset + pSA->cryptoIvSize) > pCmd->cryptoOffset) && + (pCmd->ivOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) ) + { + mvOsPrintf("mvCesaFragParamCheck: cryptoIvOffset (%d) is part of cryptoLength (%d+%d)\n", + pCmd->ivOffset, pCmd->macOffset, pCmd->macLength); + return MV_BAD_PARAM; + } + + /* ivOffset must be 4 byte aligned */ + if( MV_IS_NOT_ALIGN(pCmd->ivOffset, 4) ) + { + mvOsPrintf("CesaAction: ivOffset=%d must be 4 byte aligned\n", + pCmd->ivOffset); + return MV_BAD_PARAM; + } + /* In addition all offsets should be the same alignment: 8 or 4 */ + if( (pCmd->ivOffset % 8) != fixOffset) + { + mvOsPrintf("mvCesaAction: ivOffset %d mod 8 must be %d\n", + pCmd->ivOffset, fixOffset); + return MV_BAD_PARAM; + } + } + } + return MV_OK; +} + +/******************************************************************************* +* mvCesaFragParamCheck - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd) +{ + int offset; + + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* macOffset must be less that SRAM buffer size */ + if(pCmd->macOffset > (sizeof(cesaSramVirtPtr->buf) - MV_CESA_AUTH_BLOCK_SIZE)) + { + mvOsPrintf("mvCesaFragParamCheck: macOffset is too large (%d)\n", + pCmd->macOffset); + return MV_BAD_PARAM; + } + /* macOffset+macSize must be more than mbufSize - SRAM buffer size */ + if( ((pCmd->macOffset + pCmd->macLength) > pCmd->pSrc->mbufSize) || + ((pCmd->pSrc->mbufSize - (pCmd->macOffset + pCmd->macLength)) >= + sizeof(cesaSramVirtPtr->buf)) ) + { + mvOsPrintf("mvCesaFragParamCheck: macLength is too large (%d), mbufSize=%d\n", + pCmd->macLength, pCmd->pSrc->mbufSize); + return MV_BAD_PARAM; + } + } + + if( ((pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) ) + { + /* cryptoOffset must be less that SRAM buffer size */ + /* 4 for possible fixOffset */ + if( (pCmd->cryptoOffset + 4) > (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize)) + { + mvOsPrintf("mvCesaFragParamCheck: cryptoOffset is too large (%d)\n", + pCmd->cryptoOffset); + return MV_BAD_PARAM; + } + + /* cryptoOffset+cryptoSize must be more than mbufSize - SRAM buffer size */ + if( ((pCmd->cryptoOffset + pCmd->cryptoLength) > pCmd->pSrc->mbufSize) || + ((pCmd->pSrc->mbufSize - (pCmd->cryptoOffset + pCmd->cryptoLength)) >= + (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize)) ) + { + mvOsPrintf("mvCesaFragParamCheck: cryptoLength is too large (%d), mbufSize=%d\n", + pCmd->cryptoLength, pCmd->pSrc->mbufSize); + return MV_BAD_PARAM; + } + } + + /* When MAC_THEN_CRYPTO or CRYPTO_THEN_MAC */ + if( ((pSA->config & MV_CESA_OPERATION_MASK) == + (MV_CESA_MAC_THEN_CRYPTO << MV_CESA_OPERATION_OFFSET)) || + ((pSA->config & MV_CESA_OPERATION_MASK) == + (MV_CESA_CRYPTO_THEN_MAC << MV_CESA_OPERATION_OFFSET)) ) + { + if( (mvCtrlModelGet() == MV_5182_DEV_ID) || + ( (mvCtrlModelGet() == MV_5181_DEV_ID) && + (mvCtrlRevGet() >= MV_5181L_A0_REV) && + (pCmd->macLength >= (1 << 14)) ) ) + { + return MV_NOT_ALLOWED; + } + + /* abs(cryptoOffset-macOffset) must be aligned cryptoBlockSize */ + if(pCmd->cryptoOffset > pCmd->macOffset) + { + offset = pCmd->cryptoOffset - pCmd->macOffset; + } + else + { + offset = pCmd->macOffset - pCmd->cryptoOffset; + } + + if( MV_IS_NOT_ALIGN(offset, pSA->cryptoBlockSize) ) + { +/* + mvOsPrintf("mvCesaFragParamCheck: (cryptoOffset - macOffset) must be %d byte aligned\n", + pSA->cryptoBlockSize); +*/ + return MV_NOT_ALLOWED; + } + /* Digest must not be part of CryptoLength */ + if( ((pCmd->digestOffset + pSA->digestSize) > pCmd->cryptoOffset) && + (pCmd->digestOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) ) + { +/* + mvOsPrintf("mvCesaFragParamCheck: digestOffset (%d) is part of cryptoLength (%d+%d)\n", + pCmd->digestOffset, pCmd->cryptoOffset, pCmd->cryptoLength); +*/ + return MV_NOT_ALLOWED; + } + } + return MV_OK; +} + +/******************************************************************************* +* mvCesaFragSizeFind - +* +* DESCRIPTION: +* +* +* INPUT: +* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, +* int cryptoOffset, int macOffset, +* +* OUTPUT: +* int* pCopySize, int* pCryptoDataSize, int* pMacDataSize +* +* RETURN: +* MV_STATUS +* +*******************************************************************************/ +static void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq, + int cryptoOffset, int macOffset, + int* pCopySize, int* pCryptoDataSize, int* pMacDataSize) +{ + MV_CESA_COMMAND *pCmd = pReq->pCmd; + int cryptoDataSize, macDataSize, copySize; + + cryptoDataSize = macDataSize = 0; + copySize = *pCopySize; + + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + cryptoDataSize = MV_MIN( (copySize - cryptoOffset), + (pCmd->cryptoLength - (pReq->frags.cryptoSize + 1)) ); + + /* cryptoSize for each fragment must be the whole number of blocksSize */ + if( MV_IS_NOT_ALIGN(cryptoDataSize, pSA->cryptoBlockSize) ) + { + cryptoDataSize = MV_ALIGN_DOWN(cryptoDataSize, pSA->cryptoBlockSize); + copySize = cryptoOffset + cryptoDataSize; + } + } + if( (pSA->config & MV_CESA_OPERATION_MASK) != + (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) + { + macDataSize = MV_MIN( (copySize - macOffset), + (pCmd->macLength - (pReq->frags.macSize + 1))); + + /* macSize for each fragment (except last) must be the whole number of blocksSize */ + if( MV_IS_NOT_ALIGN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE) ) + { + macDataSize = MV_ALIGN_DOWN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE); + copySize = macOffset + macDataSize; + } + cryptoDataSize = copySize - cryptoOffset; + } + *pCopySize = copySize; + + if(pCryptoDataSize != NULL) + *pCryptoDataSize = cryptoDataSize; + + if(pMacDataSize != NULL) + *pMacDataSize = macDataSize; +} diff --git a/board/mv_feroceon/mv_hal/cesa/mvCesa.h b/board/mv_feroceon/mv_hal/cesa/mvCesa.h new file mode 100644 index 0000000..7f3f09d --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvCesa.h @@ -0,0 +1,402 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvCesa.h - Header File for Cryptographic Engines and Security Accelerator +* +* DESCRIPTION: +* This header file contains macros typedefs and function declaration for +* the Marvell Cryptographic Engines and Security Accelerator. +* +*******************************************************************************/ + +#ifndef __mvCesa_h__ +#define __mvCesa_h__ + +#include "mvOs.h" +#include "mvCommon.h" +#include "mvDebug.h" + +#include "ctrlEnv/mvCtrlEnvSpec.h" + +#include "cesa/mvMD5.h" +#include "cesa/mvSHA1.h" + +#include "cesa/mvCesa.h" +#include "cesa/AES/mvAes.h" +#include "mvSysHwConfig.h" + +#ifdef MV_INCLUDE_IDMA +#include "idma/mvIdma.h" +#include "idma/mvIdmaRegs.h" +#else +/* Redefine MV_DMA_DESC structure */ +typedef struct _mvDmaDesc +{ + MV_U32 byteCnt; /* The total number of bytes to transfer */ + MV_U32 phySrcAdd; /* The physical source address */ + MV_U32 phyDestAdd; /* The physical destination address */ + MV_U32 phyNextDescPtr; /* If we are using chain mode DMA transfer, */ + /* then this pointer should point to the */ + /* physical address of the next descriptor, */ + /* otherwise it should be NULL. */ +}MV_DMA_DESC; +#endif /* MV_INCLUDE_IDMA */ + +#include "cesa/mvCesaRegs.h" + +#define MV_CESA_AUTH_BLOCK_SIZE 64 /* bytes */ + +#define MV_CESA_MD5_DIGEST_SIZE 16 /* bytes */ +#define MV_CESA_SHA1_DIGEST_SIZE 20 /* bytes */ + +#define MV_CESA_MAX_DIGEST_SIZE MV_CESA_SHA1_DIGEST_SIZE + +#define MV_CESA_DES_KEY_LENGTH 8 /* bytes = 64 bits */ +#define MV_CESA_3DES_KEY_LENGTH 24 /* bytes = 192 bits */ +#define MV_CESA_AES_128_KEY_LENGTH 16 /* bytes = 128 bits */ +#define MV_CESA_AES_192_KEY_LENGTH 24 /* bytes = 192 bits */ +#define MV_CESA_AES_256_KEY_LENGTH 32 /* bytes = 256 bits */ + +#define MV_CESA_MAX_CRYPTO_KEY_LENGTH MV_CESA_AES_256_KEY_LENGTH + +#define MV_CESA_DES_BLOCK_SIZE 8 /* bytes = 64 bits */ +#define MV_CESA_3DES_BLOCK_SIZE 8 /* bytes = 64 bits */ + +#define MV_CESA_AES_BLOCK_SIZE 16 /* bytes = 128 bits */ + +#define MV_CESA_MAX_IV_LENGTH MV_CESA_AES_BLOCK_SIZE + +#define MV_CESA_MAX_MAC_KEY_LENGTH 64 /* bytes */ + +typedef struct +{ + MV_U8 cryptoKey[MV_CESA_MAX_CRYPTO_KEY_LENGTH]; + MV_U8 macKey[MV_CESA_MAX_MAC_KEY_LENGTH]; + MV_CESA_OPERATION operation; + MV_CESA_DIRECTION direction; + MV_CESA_CRYPTO_ALG cryptoAlgorithm; + MV_CESA_CRYPTO_MODE cryptoMode; + MV_U8 cryptoKeyLength; + MV_CESA_MAC_MODE macMode; + MV_U8 macKeyLength; + MV_U8 digestSize; + +} MV_CESA_OPEN_SESSION; + +typedef struct +{ + MV_BUF_INFO *pFrags; + MV_U16 numFrags; + MV_U16 mbufSize; + +} MV_CESA_MBUF; + +typedef struct +{ + void* pReqPrv; /* instead of reqId */ + MV_U32 retCode; + MV_16 sessionId; + +} MV_CESA_RESULT; + +typedef void (*MV_CESA_CALLBACK) (MV_CESA_RESULT* pResult); + + +typedef struct +{ + void* pReqPrv; /* instead of reqId */ + MV_CESA_MBUF* pSrc; + MV_CESA_MBUF* pDst; + MV_CESA_CALLBACK* pFuncCB; + MV_16 sessionId; + MV_U16 ivFromUser; + MV_U16 ivOffset; + MV_U16 cryptoOffset; + MV_U16 cryptoLength; + MV_U16 digestOffset; + MV_U16 macOffset; + MV_U16 macLength; + +} MV_CESA_COMMAND; + + + +MV_STATUS mvCesaHalInit (int numOfSession, int queueDepth, char* pSramBase, MV_U32 cryptEngBase, void *osHandle); +MV_STATUS mvCesaFinish (void); +MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short* pSid); +MV_STATUS mvCesaSessionClose(short sid); +MV_STATUS mvCesaCryptoIvSet(MV_U8* pIV, int ivSize); + +MV_STATUS mvCesaAction (MV_CESA_COMMAND* pCmd); + +MV_U32 mvCesaInProcessGet(void); +MV_STATUS mvCesaReadyDispatch(void); +MV_STATUS mvCesaReadyGet(MV_CESA_RESULT* pResult); +MV_BOOL mvCesaIsReady(void); + +int mvCesaMbufOffset(MV_CESA_MBUF* pMbuf, int offset, int* pBufOffset); +MV_STATUS mvCesaCopyFromMbuf(MV_U8* pDst, MV_CESA_MBUF* pSrcMbuf, + int offset, int size); +MV_STATUS mvCesaCopyToMbuf(MV_U8* pSrc, MV_CESA_MBUF* pDstMbuf, + int offset, int size); +MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF* pMbufDst, int dstMbufOffset, + MV_CESA_MBUF* pMbufSrc, int srcMbufOffset, int size); + +/********** Debug functions ********/ + +void mvCesaDebugMbuf(const char* str, MV_CESA_MBUF *pMbuf, int offset, int size); +void mvCesaDebugSA(short sid, int mode); +void mvCesaDebugStats(void); +void mvCesaDebugStatsClear(void); +void mvCesaDebugRegs(void); +void mvCesaDebugStatus(void); +void mvCesaDebugQueue(int mode); +void mvCesaDebugSram(int mode); +void mvCesaDebugSAD(int mode); + + +/******** CESA Private definitions ********/ +#if (MV_CESA_VERSION >= 2) +#if (MV_CACHE_COHERENCY == MV_CACHE_COHER_SW) +#define MV_CESA_TDMA_CTRL_VALUE MV_CESA_TDMA_DST_BURST_MASK(MV_CESA_TDMA_BURST_128B) \ + | MV_CESA_TDMA_SRC_BURST_MASK(MV_CESA_TDMA_BURST_128B) \ + | MV_CESA_TDMA_OUTSTAND_READ_EN_MASK \ + | MV_CESA_TDMA_NO_BYTE_SWAP_MASK \ + | MV_CESA_TDMA_ENABLE_MASK +#else +#define MV_CESA_TDMA_CTRL_VALUE MV_CESA_TDMA_DST_BURST_MASK(MV_CESA_TDMA_BURST_32B) \ + | MV_CESA_TDMA_SRC_BURST_MASK(MV_CESA_TDMA_BURST_128B) \ + /*| MV_CESA_TDMA_OUTSTAND_READ_EN_MASK */\ + | MV_CESA_TDMA_ENABLE_MASK + +#endif +#else +#define MV_CESA_IDMA_CTRL_LOW_VALUE ICCLR_DST_BURST_LIM_128BYTE \ + | ICCLR_SRC_BURST_LIM_128BYTE \ + | ICCLR_INT_MODE_MASK \ + | ICCLR_BLOCK_MODE \ + | ICCLR_CHAN_ENABLE \ + | ICCLR_DESC_MODE_16M +#endif /* MV_CESA_VERSION >= 2 */ + +#define MV_CESA_MAX_PKT_SIZE (64 * 1024) +#define MV_CESA_MAX_MBUF_FRAGS 20 + +#define MV_CESA_MAX_REQ_FRAGS ( (MV_CESA_MAX_PKT_SIZE / MV_CESA_MAX_BUF_SIZE) + 1) + +#define MV_CESA_MAX_DMA_DESC (MV_CESA_MAX_MBUF_FRAGS*2 + 5) + +typedef enum +{ + MV_CESA_IDLE = 0, + MV_CESA_PENDING, + MV_CESA_PROCESS, + MV_CESA_READY, + +} MV_CESA_STATE; + + +/* Session database */ + +/* Map of Key materials of the session in SRAM. + * Each field must be 8 byte aligned + * Total size: 32 + 24 + 24 = 80 bytes + */ +typedef struct +{ + MV_U8 cryptoKey[MV_CESA_MAX_CRYPTO_KEY_LENGTH]; + MV_U8 macInnerIV[MV_CESA_MAX_DIGEST_SIZE]; + MV_U8 reservedInner[4]; + MV_U8 macOuterIV[MV_CESA_MAX_DIGEST_SIZE]; + MV_U8 reservedOuter[4]; + +} MV_CESA_SRAM_SA; + +typedef struct +{ + MV_CESA_SRAM_SA* pSramSA; + MV_U32 config; + MV_U8 cryptoKeyLength; + MV_U8 cryptoIvSize; + MV_U8 cryptoBlockSize; + MV_U8 digestSize; + MV_U8 macKeyLength; + MV_U8 valid; + MV_U8 ctrMode; + MV_U32 count; + +} MV_CESA_SA; + +/* DMA list management */ +typedef struct +{ + MV_DMA_DESC* pDmaFirst; + MV_DMA_DESC* pDmaLast; + +} MV_CESA_DMA; + + +typedef struct +{ + MV_U8 numFrag; + MV_U8 nextFrag; + int bufOffset; + int cryptoSize; + int macSize; + int newDigestOffset; + MV_U8 orgDigest[MV_CESA_MAX_DIGEST_SIZE]; + +} MV_CESA_FRAGS; + +/* Request queue */ +typedef struct +{ + MV_U8 state; + MV_U8 fragMode; + MV_U8 fixOffset; + MV_CESA_COMMAND* pCmd; + MV_CESA_COMMAND* pOrgCmd; + MV_BUF_INFO dmaDescBuf; + MV_CESA_DMA dma[MV_CESA_MAX_REQ_FRAGS]; + MV_BUF_INFO cesaDescBuf; + MV_CESA_DESC* pCesaDesc; + MV_CESA_FRAGS frags; + + +} MV_CESA_REQ; + + +/* SRAM map */ +/* Total SRAM size calculation */ +/* SRAM size = + * MV_CESA_MAX_BUF_SIZE + + * sizeof(MV_CESA_DESC) + + * MV_CESA_MAX_IV_LENGTH + + * MV_CESA_MAX_IV_LENGTH + + * MV_CESA_MAX_DIGEST_SIZE + + * sizeof(MV_CESA_SRAM_SA) + * = 1600 + 32 + 16 + 16 + 24 + 80 + 280 (reserved) = 2048 bytes + * = 3200 + 32 + 16 + 16 + 24 + 80 + 728 (reserved) = 4096 bytes + */ +typedef struct +{ + MV_U8 buf[MV_CESA_MAX_BUF_SIZE]; + MV_CESA_DESC desc; + MV_U8 cryptoIV[MV_CESA_MAX_IV_LENGTH]; + MV_U8 tempCryptoIV[MV_CESA_MAX_IV_LENGTH]; + MV_U8 tempDigest[MV_CESA_MAX_DIGEST_SIZE+4]; + MV_CESA_SRAM_SA sramSA; + +} MV_CESA_SRAM_MAP; + + +typedef struct +{ + MV_U32 openedCount; + MV_U32 closedCount; + MV_U32 fragCount; + MV_U32 reqCount; + MV_U32 maxReqCount; + MV_U32 procCount; + MV_U32 readyCount; + MV_U32 notReadyCount; + MV_U32 startCount; + +} MV_CESA_STATS; + + +/* External variables */ + +extern MV_CESA_STATS cesaStats; +extern MV_CESA_FRAGS cesaFrags; + +extern MV_BUF_INFO cesaSramSaBuf; + +extern MV_CESA_SA* pCesaSAD; +extern MV_U16 cesaMaxSA; + +extern MV_CESA_REQ* pCesaReqFirst; +extern MV_CESA_REQ* pCesaReqLast; +extern MV_CESA_REQ* pCesaReqEmpty; +extern MV_CESA_REQ* pCesaReqProcess; +extern int cesaQueueDepth; +extern int cesaReqResources; + +extern MV_CESA_SRAM_MAP* cesaSramVirtPtr; +extern MV_U32 cesaSramPhysAddr; + +static INLINE MV_ULONG mvCesaVirtToPhys(MV_BUF_INFO* pBufInfo, void* pVirt) +{ + return (pBufInfo->bufPhysAddr + ((MV_U8*)pVirt - pBufInfo->bufVirtPtr)); +} + +/* Additional DEBUG functions */ +void mvCesaDebugSramSA(MV_CESA_SRAM_SA* pSramSA, int mode); +void mvCesaDebugCmd(MV_CESA_COMMAND* pCmd, int mode); +void mvCesaDebugDescriptor(MV_CESA_DESC* pDesc); + + + +#endif /* __mvCesa_h__ */ diff --git a/board/mv_feroceon/mv_hal/cesa/mvCesaDebug.c b/board/mv_feroceon/mv_hal/cesa/mvCesaDebug.c new file mode 100644 index 0000000..3e3ebf6 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvCesaDebug.c @@ -0,0 +1,477 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvOs.h" +#include "mvDebug.h" + +#include "cesa/mvMD5.h" +#include "cesa/mvSHA1.h" + +#include "cesa/mvCesa.h" +#include "cesa/mvCesaRegs.h" +#include "cesa/AES/mvAes.h" + +static const char* mvCesaDebugStateStr(MV_CESA_STATE state) +{ + switch(state) + { + case MV_CESA_IDLE: + return "Idle"; + + case MV_CESA_PENDING: + return "Pend"; + + case MV_CESA_PROCESS: + return "Proc"; + + case MV_CESA_READY: + return "Ready"; + + default: + break; + } + return "Unknown"; +} + +static const char* mvCesaDebugOperStr(MV_CESA_OPERATION oper) +{ + switch(oper) + { + case MV_CESA_MAC_ONLY: + return "MacOnly"; + + case MV_CESA_CRYPTO_ONLY: + return "CryptoOnly"; + + case MV_CESA_MAC_THEN_CRYPTO: + return "MacCrypto"; + + case MV_CESA_CRYPTO_THEN_MAC: + return "CryptoMac"; + + default: + break; + } + return "Null"; +} + +static const char* mvCesaDebugCryptoAlgStr(MV_CESA_CRYPTO_ALG cryptoAlg) +{ + switch(cryptoAlg) + { + case MV_CESA_CRYPTO_DES: + return "DES"; + + case MV_CESA_CRYPTO_3DES: + return "3DES"; + + case MV_CESA_CRYPTO_AES: + return "AES"; + + default: + break; + } + return "Null"; +} + +static const char* mvCesaDebugMacModeStr(MV_CESA_MAC_MODE macMode) +{ + switch(macMode) + { + case MV_CESA_MAC_MD5: + return "MD5"; + + case MV_CESA_MAC_SHA1: + return "SHA1"; + + case MV_CESA_MAC_HMAC_MD5: + return "HMAC-MD5"; + + case MV_CESA_MAC_HMAC_SHA1: + return "HMAC_SHA1"; + + default: + break; + } + return "Null"; +} + +void mvCesaDebugCmd(MV_CESA_COMMAND* pCmd, int mode) +{ + mvOsPrintf("pCmd=%p, pReqPrv=%p, pSrc=%p, pDst=%p, pCB=%p, sid=%d\n", + pCmd, pCmd->pReqPrv, pCmd->pSrc, pCmd->pDst, + pCmd->pFuncCB, pCmd->sessionId); + mvOsPrintf("isUser=%d, ivOffs=%d, crOffs=%d, crLen=%d, digest=%d, macOffs=%d, macLen=%d\n", + pCmd->ivFromUser, pCmd->ivOffset, pCmd->cryptoOffset, pCmd->cryptoLength, + pCmd->digestOffset, pCmd->macOffset, pCmd->macLength); +} + +/* no need to use in tool */ +void mvCesaDebugMbuf(const char* str, MV_CESA_MBUF *pMbuf, int offset, int size) +{ + int frag, len, fragOffset; + + if(str != NULL) + mvOsPrintf("%s: pMbuf=%p, numFrags=%d, mbufSize=%d\n", + str, pMbuf, pMbuf->numFrags, pMbuf->mbufSize); + + frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset); + if(frag == MV_INVALID) + { + mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset); + return; + } + + for(; fragnumFrags; frag++) + { + mvOsPrintf("#%2d. bufVirt=%p, bufSize=%d\n", + frag, pMbuf->pFrags[frag].bufVirtPtr, + pMbuf->pFrags[frag].bufSize); + if(size > 0) + { + len = MV_MIN(pMbuf->pFrags[frag].bufSize, size); + mvDebugMemDump(pMbuf->pFrags[frag].bufVirtPtr+fragOffset, len, 1); + size -= len; + fragOffset = 0; + } + } +} + +void mvCesaDebugRegs(void) +{ + mvOsPrintf("\t CESA Registers:\n"); + + mvOsPrintf("MV_CESA_CMD_REG : 0x%X = 0x%08x\n", + MV_CESA_CMD_REG, + MV_REG_READ( MV_CESA_CMD_REG ) ); + + mvOsPrintf("MV_CESA_CHAN_DESC_OFFSET_REG : 0x%X = 0x%08x\n", + MV_CESA_CHAN_DESC_OFFSET_REG, + MV_REG_READ(MV_CESA_CHAN_DESC_OFFSET_REG) ); + + mvOsPrintf("MV_CESA_CFG_REG : 0x%X = 0x%08x\n", + MV_CESA_CFG_REG, + MV_REG_READ( MV_CESA_CFG_REG ) ); + + mvOsPrintf("MV_CESA_STATUS_REG : 0x%X = 0x%08x\n", + MV_CESA_STATUS_REG, + MV_REG_READ( MV_CESA_STATUS_REG ) ); + + mvOsPrintf("MV_CESA_ISR_CAUSE_REG : 0x%X = 0x%08x\n", + MV_CESA_ISR_CAUSE_REG, + MV_REG_READ( MV_CESA_ISR_CAUSE_REG ) ); + + mvOsPrintf("MV_CESA_ISR_MASK_REG : 0x%X = 0x%08x\n", + MV_CESA_ISR_MASK_REG, + MV_REG_READ( MV_CESA_ISR_MASK_REG ) ); +#if (MV_CESA_VERSION >= 2) + mvOsPrintf("MV_CESA_TDMA_CTRL_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_CTRL_REG, + MV_REG_READ( MV_CESA_TDMA_CTRL_REG ) ); + + mvOsPrintf("MV_CESA_TDMA_BYTE_COUNT_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_BYTE_COUNT_REG, + MV_REG_READ( MV_CESA_TDMA_BYTE_COUNT_REG ) ); + + mvOsPrintf("MV_CESA_TDMA_SRC_ADDR_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_SRC_ADDR_REG, + MV_REG_READ( MV_CESA_TDMA_SRC_ADDR_REG ) ); + + mvOsPrintf("MV_CESA_TDMA_DST_ADDR_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_DST_ADDR_REG, + MV_REG_READ( MV_CESA_TDMA_DST_ADDR_REG ) ); + + mvOsPrintf("MV_CESA_TDMA_NEXT_DESC_PTR_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_NEXT_DESC_PTR_REG, + MV_REG_READ( MV_CESA_TDMA_NEXT_DESC_PTR_REG ) ); + + mvOsPrintf("MV_CESA_TDMA_CURR_DESC_PTR_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_CURR_DESC_PTR_REG, + MV_REG_READ( MV_CESA_TDMA_CURR_DESC_PTR_REG ) ); + + mvOsPrintf("MV_CESA_TDMA_ERROR_CAUSE_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_ERROR_CAUSE_REG, + MV_REG_READ( MV_CESA_TDMA_ERROR_CAUSE_REG ) ); + + mvOsPrintf("MV_CESA_TDMA_ERROR_MASK_REG : 0x%X = 0x%08x\n", + MV_CESA_TDMA_ERROR_MASK_REG, + MV_REG_READ( MV_CESA_TDMA_ERROR_CAUSE_REG ) ); + +#endif +} + +void mvCesaDebugStatus(void) +{ + mvOsPrintf("\n\t CESA Status\n\n"); + + mvOsPrintf("pReqQ=%p, qDepth=%d, reqSize=%u bytes, qRes=%d\n", + pCesaReqFirst, cesaQueueDepth, sizeof(MV_CESA_REQ), + cesaReqResources); + + mvOsPrintf("pSAD=%p, maxSA=%d, sizeSA=%u bytes\n", + pCesaSAD, cesaMaxSA, sizeof(MV_CESA_SA)); + + mvOsPrintf("\n"); + + mvCesaDebugRegs(); + mvCesaDebugStats(); + mvCesaDebugStatsClear(); +} + +void mvCesaDebugDescriptor(MV_CESA_DESC* pDesc) +{ + mvOsPrintf("config=0x%08x, crSrcOffs=0x%04x, crDstOffs=0x%04x\n", + pDesc->config, pDesc->cryptoSrcOffset, pDesc->cryptoDstOffset); + + mvOsPrintf("crLen=0x%04x, crKeyOffs=0x%04x, ivOffs=0x%04x, ivBufOffs=0x%04x\n", + pDesc->cryptoDataLen, pDesc->cryptoKeyOffset, + pDesc->cryptoIvOffset, pDesc->cryptoIvBufOffset); + + mvOsPrintf("macSrc=0x%04x, digest=0x%04x, macLen=0x%04x, inIv=0x%04x, outIv=0x%04x\n", + pDesc->macSrcOffset, pDesc->macDigestOffset, pDesc->macDataLen, + pDesc->macInnerIvOffset, pDesc->macOuterIvOffset); +} + +void mvCesaDebugQueue(int mode) +{ + mvOsPrintf("\n\t CESA Request Queue:\n\n"); + + mvOsPrintf("pFirstReq=%p, pLastReq=%p, qDepth=%d, reqSize=%u bytes\n", + pCesaReqFirst, pCesaReqLast, cesaQueueDepth, sizeof(MV_CESA_REQ)); + + mvOsPrintf("pEmpty=%p, pProcess=%p, qResources=%d\n", + pCesaReqEmpty, pCesaReqProcess, + cesaReqResources); + + if(mode != 0) + { + int count = 0; + MV_CESA_REQ* pReq = pCesaReqFirst; + + for(count=0; countstate), + pReq->fragMode, pReq->pCmd, pReq->dma[0].pDmaFirst, &pReq->pCesaDesc[0]); + if(pReq->fragMode != MV_CESA_FRAG_NONE) + { + int frag; + + mvOsPrintf("pFrags=%p, num=%d, next=%d, bufOffset=%d, cryptoSize=%d, macSize=%d\n", + &pReq->frags, pReq->frags.numFrag, pReq->frags.nextFrag, + pReq->frags.bufOffset, pReq->frags.cryptoSize, pReq->frags.macSize); + for(frag=0; fragfrags.numFrag; frag++) + { + mvOsPrintf("#%d: pDmaFirst=%p, pDesc=%p\n", frag, + pReq->dma[frag].pDmaFirst, &pReq->pCesaDesc[frag]); + } + } + if(mode > 1) + { + /* Print out Command */ + mvCesaDebugCmd(pReq->pCmd, mode); + + /* Print out Descriptor */ + mvCesaDebugDescriptor(&pReq->pCesaDesc[0]); + } + pReq++; + } + } +} + + +void mvCesaDebugSramSA(MV_CESA_SRAM_SA* pSramSA, int mode) +{ + if(pSramSA == NULL) + { + mvOsPrintf("cesaSramSA: Unexpected pSramSA=%p\n", pSramSA); + return; + } + mvOsPrintf("pSramSA=%p, sizeSramSA=%u bytes\n", + pSramSA, sizeof(MV_CESA_SRAM_SA)); + + if(mode != 0) + { + mvOsPrintf("cryptoKey=%p, maxCryptoKey=%d bytes\n", + pSramSA->cryptoKey, MV_CESA_MAX_CRYPTO_KEY_LENGTH); + mvDebugMemDump(pSramSA->cryptoKey, MV_CESA_MAX_CRYPTO_KEY_LENGTH, 1); + + mvOsPrintf("macInnerIV=%p, maxInnerIV=%d bytes\n", + pSramSA->macInnerIV, MV_CESA_MAX_DIGEST_SIZE); + mvDebugMemDump(pSramSA->macInnerIV, MV_CESA_MAX_DIGEST_SIZE, 1); + + mvOsPrintf("macOuterIV=%p, maxOuterIV=%d bytes\n", + pSramSA->macOuterIV, MV_CESA_MAX_DIGEST_SIZE); + mvDebugMemDump(pSramSA->macOuterIV, MV_CESA_MAX_DIGEST_SIZE, 1); + } +} + +void mvCesaDebugSA(short sid, int mode) +{ + MV_CESA_OPERATION oper; + MV_CESA_DIRECTION dir; + MV_CESA_CRYPTO_ALG cryptoAlg; + MV_CESA_CRYPTO_MODE cryptoMode; + MV_CESA_MAC_MODE macMode; + MV_CESA_SA* pSA = &pCesaSAD[sid]; + + if( (pSA->valid) || ((pSA->count != 0) && (mode > 0)) || (mode >= 2) ) + { + mvOsPrintf("\n\nCESA SA Entry #%d (%p) - %s (count=%d)\n", + sid, pSA, + pSA->valid ? "Valid" : "Invalid", pSA->count); + + oper = (pSA->config & MV_CESA_OPERATION_MASK) >> MV_CESA_OPERATION_OFFSET; + dir = (pSA->config & MV_CESA_DIRECTION_MASK) >> MV_CESA_DIRECTION_BIT; + mvOsPrintf("%s - %s ", mvCesaDebugOperStr(oper), + (dir == MV_CESA_DIR_ENCODE) ? "Encode" : "Decode"); + if(oper != MV_CESA_MAC_ONLY) + { + cryptoAlg = (pSA->config & MV_CESA_CRYPTO_ALG_MASK) >> MV_CESA_CRYPTO_ALG_OFFSET; + cryptoMode = (pSA->config & MV_CESA_CRYPTO_MODE_MASK) >> MV_CESA_CRYPTO_MODE_BIT; + mvOsPrintf("- %s - %s ", mvCesaDebugCryptoAlgStr(cryptoAlg), + (cryptoMode == MV_CESA_CRYPTO_ECB) ? "ECB" : "CBC"); + } + if(oper != MV_CESA_CRYPTO_ONLY) + { + macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET; + mvOsPrintf("- %s ", mvCesaDebugMacModeStr(macMode)); + } + mvOsPrintf("\n"); + + if(mode > 0) + { + mvOsPrintf("config=0x%08x, cryptoKeySize=%d, digestSize=%d\n", + pCesaSAD[sid].config, pCesaSAD[sid].cryptoKeyLength, + pCesaSAD[sid].digestSize); + + mvCesaDebugSramSA(pCesaSAD[sid].pSramSA, mode); + } + } +} + + +/**/ +void mvCesaDebugSram(int mode) +{ + mvOsPrintf("\n\t SRAM contents: size=%u, pVirt=%p\n\n", + sizeof(MV_CESA_SRAM_MAP), cesaSramVirtPtr); + + mvOsPrintf("\n\t Sram buffer: size=%d, pVirt=%p\n", + MV_CESA_MAX_BUF_SIZE, cesaSramVirtPtr->buf); + if(mode != 0) + mvDebugMemDump(cesaSramVirtPtr->buf, 64, 1); + + mvOsPrintf("\n"); + mvOsPrintf("\n\t Sram descriptor: size=%u, pVirt=%p\n", + sizeof(MV_CESA_DESC), &cesaSramVirtPtr->desc); + if(mode != 0) + { + mvOsPrintf("\n"); + mvCesaDebugDescriptor(&cesaSramVirtPtr->desc); + } + mvOsPrintf("\n\t Sram IV: size=%d, pVirt=%p\n", + MV_CESA_MAX_IV_LENGTH, &cesaSramVirtPtr->cryptoIV); + if(mode != 0) + { + mvOsPrintf("\n"); + mvDebugMemDump(cesaSramVirtPtr->cryptoIV, MV_CESA_MAX_IV_LENGTH, 1); + } + mvOsPrintf("\n"); + mvCesaDebugSramSA(&cesaSramVirtPtr->sramSA, 0); +} + +void mvCesaDebugSAD(int mode) +{ + int sid; + + mvOsPrintf("\n\t Cesa SAD status: pSAD=%p, maxSA=%d\n", + pCesaSAD, cesaMaxSA); + + for(sid=0; sid +wait_queue_head_t cesaTest_waitq; +spinlock_t cesaLock; + +#define CESA_TEST_LOCK(flags) spin_lock_irqsave( &cesaLock, flags) +#define CESA_TEST_UNLOCK(flags) spin_unlock_irqrestore( &cesaLock, flags); + +#define CESA_TEST_WAIT_INIT() init_waitqueue_head(&cesaTest_waitq) +#define CESA_TEST_WAKE_UP() wake_up(&cesaTest_waitq) +#define CESA_TEST_WAIT(cond, ms) wait_event_timeout(cesaTest_waitq, (cond), msecs_to_jiffies(ms)) + +#define CESA_TEST_TICK_GET() jiffies +#define CESA_TEST_TICK_TO_MS(tick) jiffies_to_msecs(tick) + +#elif defined(MV_NETBSD) + +#include +#include +static int cesaLock; + +#define CESA_TEST_LOCK(flags) flags = splnet() +#define CESA_TEST_UNLOCK(flags) splx(flags) + +#define CESA_TEST_WAIT_INIT() /* nothing */ +#define CESA_TEST_WAKE_UP() wakeup(&cesaLock) +#define CESA_TEST_WAIT(cond, ms) \ +do { \ + while (!(cond)) \ + tsleep(&cesaLock, PWAIT, "cesatest",mstohz(ms)); \ +} while (/*CONSTCOND*/0) + +#define CESA_TEST_TICK_GET() hardclock_ticks +#define CESA_TEST_TICK_TO_MS(tick) ((1000/hz)*(tick)) + +#define request_irq(i,h,t,n,a) \ + !mv_intr_establish((i),IPL_NET,(int(*)(void *))(h),(a)) + +#else +#error "Only Linux, VxWorks, or NetBSD OS are supported" +#endif + +#include "mvDebug.h" + +#include "mvSysHwConfig.h" +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "cntmr/mvCntmr.h" +#include "cesa/mvCesa.h" +#include "cesa/mvCesaRegs.h" +#include "cesa/mvMD5.h" +#include "cesa/mvSHA1.h" + +#if defined(CONFIG_MV646xx) +#include "marvell_pic.h" +#endif + +#define MV_CESA_USE_TIMER_ID 0 +#define CESA_DEF_BUF_SIZE 1500 +#define CESA_DEF_BUF_NUM 1 +#define CESA_DEF_SESSION_NUM 32 + +#define CESA_DEF_ITER_NUM 100 + +#define CESA_DEF_REQ_SIZE 256 + + +/* CESA Tests Debug */ +#undef CESA_TEST_DEBUG + +#ifdef CESA_TEST_DEBUG + +# define CESA_TEST_DEBUG_PRINT(msg) mvOsPrintf msg +# define CESA_TEST_DEBUG_CODE(code) code + +typedef struct +{ + int type; /* 0 - isrEmpty, 1 - cesaReadyGet, 2 - cesaAction */ + MV_U32 timeStamp; + MV_U32 cause; + MV_U32 realCause; + MV_U32 dmaCause; + int resources; + MV_CESA_REQ* pReqReady; + MV_CESA_REQ* pReqEmpty; + MV_CESA_REQ* pReqProcess; +} MV_CESA_TEST_TRACE; + +#define MV_CESA_TEST_TRACE_SIZE 25 + +static int cesaTestTraceIdx = 0; +static MV_CESA_TEST_TRACE cesaTestTrace[MV_CESA_TEST_TRACE_SIZE]; + +static void cesaTestTraceAdd(int type, MV_U32 cause) +{ + cesaTestTrace[cesaTestTraceIdx].type = type; + cesaTestTrace[cesaTestTraceIdx].cause = cause; + cesaTestTrace[cesaTestTraceIdx].realCause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG); + cesaTestTrace[cesaTestTraceIdx].dmaCause = MV_REG_READ(IDMA_CAUSE_REG); + cesaTestTrace[cesaTestTraceIdx].resources = cesaReqResources; + cesaTestTrace[cesaTestTraceIdx].pReqReady = pCesaReqReady; + cesaTestTrace[cesaTestTraceIdx].pReqEmpty = pCesaReqEmpty; + cesaTestTrace[cesaTestTraceIdx].pReqProcess = pCesaReqProcess; + cesaTestTrace[cesaTestTraceIdx].timeStamp = mvCntmrRead(MV_CESA_USE_TIMER_ID); + cesaTestTraceIdx++; + if(cesaTestTraceIdx == MV_CESA_TEST_TRACE_SIZE) + cesaTestTraceIdx = 0; +} + +#else + +# define CESA_TEST_DEBUG_PRINT(msg) +# define CESA_TEST_DEBUG_CODE(code) + +#endif /* CESA_TEST_DEBUG */ + +int cesaExpReqId=0; +int cesaCbIter=0; + +int cesaIdx; +int cesaIteration; +int cesaRateSize; +int cesaReqSize; +unsigned long cesaTaskId; +int cesaBufNum; +int cesaBufSize; +int cesaCheckOffset; +int cesaCheckSize; +int cesaCheckMode; +int cesaTestIdx; +int cesaCaseIdx; + + +MV_U32 cesaTestIsrCount = 0; +MV_U32 cesaTestIsrMissCount = 0; + +MV_U32 cesaCryptoError = 0; +MV_U32 cesaReqIdError = 0; +MV_U32 cesaError = 0; + +char* cesaHexBuffer = NULL; + +char* cesaBinBuffer = NULL; +char* cesaExpBinBuffer = NULL; + +char* cesaInputHexStr = NULL; +char* cesaOutputHexStr = NULL; + +MV_BUF_INFO cesaReqBufs[CESA_DEF_REQ_SIZE]; + +MV_CESA_COMMAND* cesaCmdRing; +MV_CESA_RESULT cesaResult; + +int cesaTestFull = 0; + +MV_BOOL cesaIsReady = MV_FALSE; +MV_U32 cesaCycles = 0; +MV_U32 cesaBeginTicks = 0; +MV_U32 cesaEndTicks = 0; +MV_U32 cesaRate = 0; +MV_U32 cesaRateAfterDot = 0; + +void *cesaTestOSHandle = NULL; + +enum +{ + CESA_FAST_CHECK_MODE = 0, + CESA_FULL_CHECK_MODE, + CESA_NULL_CHECK_MODE, + CESA_SHOW_CHECK_MODE, + CESA_SW_SHOW_CHECK_MODE, + CESA_SW_NULL_CHECK_MODE, + + CESA_MAX_CHECK_MODE +}; + +enum +{ + DES_TEST_TYPE = 0, + TRIPLE_DES_TEST_TYPE = 1, + AES_TEST_TYPE = 2, + MD5_TEST_TYPE = 3, + SHA_TEST_TYPE = 4, + COMBINED_TEST_TYPE = 5, + + MAX_TEST_TYPE +}; + +/* Tests data base */ +typedef struct +{ + short sid; + char cryptoAlgorithm; /* DES/3DES/AES */ + char cryptoMode; /* ECB or CBC */ + char macAlgorithm; /* MD5 / SHA1 */ + char operation; /* CRYPTO/HMAC/CRYPTO+HMAC/HMAC+CRYPTO */ + char direction; /* ENCODE(SIGN)/DECODE(VERIFY) */ + unsigned char* pCryptoKey; + int cryptoKeySize; + unsigned char* pMacKey; + int macKeySize; + const char* name; + +} MV_CESA_TEST_SESSION; + +typedef struct +{ + MV_CESA_TEST_SESSION* pSessions; + int numSessions; + +} MV_CESA_TEST_DB_ENTRY; + +typedef struct +{ + char* plainHexStr; + char* cipherHexStr; + unsigned char* pCryptoIV; + int cryptoLength; + int macLength; + int digestOffset; + +} MV_CESA_TEST_CASE; + +typedef struct +{ + int size; + const char* outputHexStr; + +} MV_CESA_SIZE_TEST; + +static unsigned char cryptoKey1[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; + +static unsigned char cryptoKey7[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; +static unsigned char iv1[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef}; + + +static unsigned char cryptoKey2[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; + +static unsigned char cryptoKey3[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}; + +static unsigned char cryptoKey4[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}; + +static unsigned char cryptoKey5[] = {0x56, 0xe4, 0x7a, 0x38, 0xc5, 0x59, 0x89, 0x74, + 0xbc, 0x46, 0x90, 0x3d, 0xba, 0x29, 0x03, 0x49}; + + +static unsigned char key3des1[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23}; + +/* Input ASCII string: The quick brown fox jump */ +static char plain3des1[] = "54686520717566636B2062726F776E20666F78206A756D70"; +static char cipher3des1[] = "A826FD8CE53B855FCCE21C8112256FE668D5C05DD9B6B900"; + +static unsigned char key3des2[] = {0x62, 0x7f, 0x46, 0x0e, 0x08, 0x10, 0x4a, 0x10, + 0x43, 0xcd, 0x26, 0x5d, 0x58, 0x40, 0xea, 0xf1, + 0x31, 0x3e, 0xdf, 0x97, 0xdf, 0x2a, 0x8a, 0x8c}; + +static unsigned char iv3des2[] = {0x8e, 0x29, 0xf7, 0x5e, 0xa7, 0x7e, 0x54, 0x75}; + +static char plain3des2[] = "326a494cd33fe756"; + +static char cipher3desCbc2[] = "8e29f75ea77e5475" + "b22b8d66de970692"; + +static unsigned char key3des3[] = {0x37, 0xae, 0x5e, 0xbf, 0x46, 0xdf, 0xf2, 0xdc, + 0x07, 0x54, 0xb9, 0x4f, 0x31, 0xcb, 0xb3, 0x85, + 0x5e, 0x7f, 0xd3, 0x6d, 0xc8, 0x70, 0xbf, 0xae}; + +static unsigned char iv3des3[] = {0x3d, 0x1d, 0xe3, 0xcc, 0x13, 0x2e, 0x3b, 0x65}; + +static char plain3des3[] = "84401f78fe6c10876d8ea23094ea5309"; + +static char cipher3desCbc3[] = "3d1de3cc132e3b65" + "7b1f7c7e3b1c948ebd04a75ffba7d2f5"; + +static unsigned char iv5[] = {0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9}; + +static unsigned char aesCtrKey[] = {0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC}; + +static unsigned char mdKey1[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}; + +static unsigned char mdKey2[] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}; + +static unsigned char shaKey1[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b}; + +static unsigned char shaKey2[] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa}; + +static unsigned char mdKey4[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; + +static unsigned char shaKey4[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14}; + + +static MV_CESA_TEST_SESSION desTestSessions[] = +{ +/*000*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey7, sizeof(cryptoKey7)/sizeof(cryptoKey7[0]), + NULL, 0, + "DES ECB encode", + }, +/*001*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey7, sizeof(cryptoKey7)/sizeof(cryptoKey7[0]), + NULL, 0, + "DES ECB decode", + }, +/*002*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey7, sizeof(cryptoKey7)/sizeof(cryptoKey7[0]), + NULL, 0, + "DES CBC encode" + }, +/*003*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey7, sizeof(cryptoKey7)/sizeof(cryptoKey7[0]), + NULL, 0, + "DES CBC decode" + }, +/*004*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, NULL, 0, + "NULL Crypto Algorithm encode" + }, +}; + + +static MV_CESA_TEST_SESSION tripleDesTestSessions[] = +{ +/*100*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + NULL, 0, + "3DES ECB encode", + }, +/*101*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + NULL, 0, + "3DES ECB decode", + }, +/*102*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + NULL, 0, + "3DES CBC encode" + }, +/*103*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + NULL, 0, + "3DES CBC decode" + }, +/*104*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + key3des1, sizeof(key3des1), + NULL, 0, + "3DES ECB encode" + }, +/*105*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + key3des2, sizeof(key3des2), + NULL, 0, + "3DES ECB encode" + }, +/*106*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + key3des3, sizeof(key3des3), + NULL, 0, + "3DES ECB encode" + }, +}; + + +static MV_CESA_TEST_SESSION aesTestSessions[] = +{ +/*200*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey2, sizeof(cryptoKey2)/sizeof(cryptoKey2[0]), + NULL, 0, + "AES-128 ECB encode" + }, +/*201*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey2, sizeof(cryptoKey2)/sizeof(cryptoKey2[0]), + NULL, 0, + "AES-128 ECB decode" + }, +/*202*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey5, sizeof(cryptoKey5)/sizeof(cryptoKey5[0]), + NULL, 0, + "AES-128 CBC encode" + }, +/*203*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey5, sizeof(cryptoKey5)/sizeof(cryptoKey5[0]), + NULL, 0, + "AES-128 CBC decode" + }, +/*204*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey3, sizeof(cryptoKey3)/sizeof(cryptoKey3[0]), + NULL, 0, + "AES-192 ECB encode" + }, +/*205*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey3, sizeof(cryptoKey3)/sizeof(cryptoKey3[0]), + NULL, 0, + "AES-192 ECB decode" + }, +/*206*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + cryptoKey4, sizeof(cryptoKey4)/sizeof(cryptoKey4[0]), + NULL, 0, + "AES-256 ECB encode" + }, +/*207*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_DECODE, + cryptoKey4, sizeof(cryptoKey4)/sizeof(cryptoKey4[0]), + NULL, 0, + "AES-256 ECB decode" + }, +/*208*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CTR, + MV_CESA_MAC_NULL, MV_CESA_CRYPTO_ONLY, + MV_CESA_DIR_ENCODE, + aesCtrKey, sizeof(aesCtrKey)/sizeof(aesCtrKey[0]), + NULL, 0, + "AES-128 CTR encode" + }, +}; + + +static MV_CESA_TEST_SESSION md5TestSessions[] = +{ +/*300*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + mdKey1, sizeof(mdKey1), + "HMAC-MD5 Generate Signature" + }, +/*301*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY, + MV_CESA_DIR_DECODE, + NULL, 0, + mdKey1, sizeof(mdKey1), + "HMAC-MD5 Verify Signature" + }, +/*302*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + mdKey2, sizeof(mdKey2), + "HMAC-MD5 Generate Signature" + }, +/*303*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY, + MV_CESA_DIR_DECODE, + NULL, 0, + mdKey2, sizeof(mdKey2), + "HMAC-MD5 Verify Signature" + }, +/*304*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + mdKey4, sizeof(mdKey4), + "HMAC-MD5 Generate Signature" + }, +/*305*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_MD5, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + NULL, 0, + "HASH-MD5 Generate Signature" + }, +}; + + +static MV_CESA_TEST_SESSION shaTestSessions[] = +{ +/*400*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + shaKey1, sizeof(shaKey1), + "HMAC-SHA1 Generate Signature" + }, +/*401*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY, + MV_CESA_DIR_DECODE, + NULL, 0, + shaKey1, sizeof(shaKey1), + "HMAC-SHA1 Verify Signature" + }, +/*402*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + shaKey2, sizeof(shaKey2), + "HMAC-SHA1 Generate Signature" + }, +/*403*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY, + MV_CESA_DIR_DECODE, + NULL, 0, + shaKey2, sizeof(shaKey2), + "HMAC-SHA1 Verify Signature" + }, +/*404*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + shaKey4, sizeof(shaKey4), + "HMAC-SHA1 Generate Signature" + }, +/*405*/ {-1, MV_CESA_CRYPTO_NULL, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_SHA1, MV_CESA_MAC_ONLY, + MV_CESA_DIR_ENCODE, + NULL, 0, + NULL, 0, + "HASH-SHA1 Generate Signature" + }, +}; + +static MV_CESA_TEST_SESSION combinedTestSessions[] = +{ +/*500*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey1, MV_CESA_DES_KEY_LENGTH, + mdKey4, sizeof(mdKey4), + "DES + MD5 encode" + }, +/*501*/ {-1, MV_CESA_CRYPTO_DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey1, MV_CESA_DES_KEY_LENGTH, + shaKey4, sizeof(shaKey4), + "DES + SHA1 encode" + }, +/*502*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + mdKey4, sizeof(mdKey4), + "3DES + MD5 encode" + }, +/*503*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + shaKey4, sizeof(shaKey4), + "3DES + SHA1 encode" + }, +/*504*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + mdKey4, sizeof(mdKey4), + "3DES CBC + MD5 encode" + }, +/*505*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + shaKey4, sizeof(shaKey4), + "3DES CBC + SHA1 encode" + }, +/*506*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_HMAC_MD5, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey5, sizeof(cryptoKey5)/sizeof(cryptoKey5[0]), + mdKey4, sizeof(mdKey4), + "AES-128 CBC + MD5 encode" + }, +/*507*/ {-1, MV_CESA_CRYPTO_AES, MV_CESA_CRYPTO_CBC, + MV_CESA_MAC_HMAC_SHA1, MV_CESA_CRYPTO_THEN_MAC, + MV_CESA_DIR_ENCODE, + cryptoKey5, sizeof(cryptoKey5)/sizeof(cryptoKey5[0]), + shaKey4, sizeof(shaKey4), + "AES-128 CBC + SHA1 encode" + }, +/*508*/ {-1, MV_CESA_CRYPTO_3DES, MV_CESA_CRYPTO_ECB, + MV_CESA_MAC_HMAC_MD5, MV_CESA_MAC_THEN_CRYPTO, + MV_CESA_DIR_DECODE, + cryptoKey1, sizeof(cryptoKey1)/sizeof(cryptoKey1[0]), + mdKey4, sizeof(mdKey4), + "HMAC-MD5 + 3DES decode" + }, +}; + + +static MV_CESA_TEST_DB_ENTRY cesaTestsDB[MAX_TEST_TYPE+1] = +{ + { desTestSessions, sizeof(desTestSessions)/sizeof(desTestSessions[0]) }, + { tripleDesTestSessions, sizeof(tripleDesTestSessions)/sizeof(tripleDesTestSessions[0]) }, + { aesTestSessions, sizeof(aesTestSessions)/sizeof(aesTestSessions[0]) }, + { md5TestSessions, sizeof(md5TestSessions)/sizeof(md5TestSessions[0]) }, + { shaTestSessions, sizeof(shaTestSessions)/sizeof(shaTestSessions[0]) }, + { combinedTestSessions, sizeof(combinedTestSessions)/sizeof(combinedTestSessions[0]) }, + { NULL, 0 } +}; + + +char cesaNullPlainHexText[] = "000000000000000000000000000000000000000000000000"; + +char cesaPlainAsciiText[] = "Now is the time for all "; +char cesaPlainHexEbc[] = "4e6f77206973207468652074696d6520666f7220616c6c20"; +char cesaCipherHexEcb[] = "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"; +char cesaPlainHexCbc[] = "1234567890abcdef4e6f77206973207468652074696d6520666f7220616c6c20"; +char cesaCipherHexCbc[] = "1234567890abcdefe5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"; + +char cesaAesPlainHexEcb[] = "000102030405060708090a0b0c0d0e0f"; +char cesaAes128cipherHexEcb[] = "0a940bb5416ef045f1c39458c653ea5a"; +char cesaAes192cipherHexEcb[] = "0060bffe46834bb8da5cf9a61ff220ae"; +char cesaAes256cipherHexEcb[] = "5a6e045708fb7196f02e553d02c3a692"; + +char cesaAsciiStr1[] = "Hi There"; +char cesaDataHexStr1[] = "4869205468657265"; +char cesaHmacMd5digestHex1[] = "9294727a3638bb1c13f48ef8158bfc9d"; +char cesaHmacSha1digestHex1[] = "b617318655057264e28bc0b6fb378c8ef146be00"; +char cesaDataAndMd5digest1[] = "48692054686572659294727a3638bb1c13f48ef8158bfc9d"; +char cesaDataAndSha1digest1[] = "4869205468657265b617318655057264e28bc0b6fb378c8ef146be00"; + +char cesaAesPlainText[] = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"; + +char cesaAes128CipherCbc[] = "c30e32ffedc0774e6aff6af0869f71aa" + "0f3af07a9a31a9c684db207eb0ef8e4e" + "35907aa632c3ffdf868bb7b29d3d46ad" + "83ce9f9a102ee99d49a53e87f4c3da55"; + +char cesaAesIvPlainText[] = "8ce82eefbea0da3c44699ed7db51b7d9" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"; + +char cesaAes128IvCipherCbc[] = "8ce82eefbea0da3c44699ed7db51b7d9" + "c30e32ffedc0774e6aff6af0869f71aa" + "0f3af07a9a31a9c684db207eb0ef8e4e" + "35907aa632c3ffdf868bb7b29d3d46ad" + "83ce9f9a102ee99d49a53e87f4c3da55"; + +char cesaAesCtrPlain[] = "00E0017B27777F3F4A1786F000000001" + "000102030405060708090A0B0C0D0E0F" + "101112131415161718191A1B1C1D1E1F" + "20212223"; + +char cesaAesCtrCipher[] = "00E0017B27777F3F4A1786F000000001" + "C1CF48A89F2FFDD9CF4652E9EFDB72D7" + "4540A42BDE6D7836D59A5CEAAEF31053" + "25B2072F"; + + + +/* Input cesaHmacHex3 is '0xdd' repeated 50 times */ +char cesaHmacMd5digestHex3[] = "56be34521d144c88dbb8c733f0e8b3f6"; +char cesaHmacSha1digestHex3[] = "125d7342b9ac11cd91a39af48aa17b4f63f175d3"; +char cesaDataHexStr3[50*2+1] = ""; +char cesaDataAndMd5digest3[sizeof(cesaDataHexStr3)+sizeof(cesaHmacMd5digestHex3)+8*2+1] = ""; +char cesaDataAndSha1digest3[sizeof(cesaDataHexStr3)+sizeof(cesaHmacSha1digestHex3)+8*2+1] = ""; + +/* Ascii string is "abc" */ +char hashHexStr3[] = "616263"; +char hashMd5digest3[] = "900150983cd24fb0d6963f7d28e17f72"; +char hashSha1digest3[] = "a9993e364706816aba3e25717850c26c9cd0d89d"; + +char hashHexStr80[] = "31323334353637383930" + "31323334353637383930" + "31323334353637383930" + "31323334353637383930" + "31323334353637383930" + "31323334353637383930" + "31323334353637383930" + "31323334353637383930"; + +char hashMd5digest80[] = "57edf4a22be3c955ac49da2e2107b67a"; + +char tripleDesThenMd5digest80[] = "b7726a03aad490bd6c5a452a89a1b271"; +char tripleDesThenSha1digest80[] = "b2ddeaca91030eab5b95a234ef2c0f6e738ff883"; + +char cbc3desThenMd5digest80[] = "6f463057e1a90e0e91ae505b527bcec0"; +char cbc3desThenSha1digest80[] = "1b002ed050be743aa98860cf35659646bb8efcc0"; + +char cbcAes128ThenMd5digest80[] = "6b6e863ac5a71d15e3e9b1c86c9ba05f"; +char cbcAes128ThenSha1digest80[] = "13558472d1fc1c90dffec6e5136c7203452d509b"; + + +static MV_CESA_TEST_CASE cesaTestCases[] = +{ + /* plainHexStr cipherHexStr IV crypto mac digest */ + /* Length Length Offset */ + /*0*/ { NULL, NULL, NULL, 0, 0, -1 }, + /*1*/ { cesaPlainHexEbc, cesaCipherHexEcb, NULL, 24, 0, -1 }, + /*2*/ { cesaPlainHexCbc, cesaCipherHexCbc, NULL, 24, 0, -1 }, + /*3*/ { cesaAesPlainHexEcb, cesaAes128cipherHexEcb, NULL, 16, 0, -1 }, + /*4*/ { cesaAesPlainHexEcb, cesaAes192cipherHexEcb, NULL, 16, 0, -1 }, + /*5*/ { cesaAesPlainHexEcb, cesaAes256cipherHexEcb, NULL, 16, 0, -1 }, + /*6*/ { cesaDataHexStr1, cesaHmacMd5digestHex1, NULL, 0, 8, -1 }, + /*7*/ { NULL, cesaDataAndMd5digest1, NULL, 0, 8, -1 }, + /*8*/ { cesaDataHexStr3, cesaHmacMd5digestHex3, NULL, 0, 50, -1 }, + /*9*/ { NULL, cesaDataAndMd5digest3, NULL, 0, 50, -1 }, +/*10*/ { cesaAesPlainText, cesaAes128IvCipherCbc, iv5, 64, 0, -1 }, +/*11*/ { cesaDataHexStr1, cesaHmacSha1digestHex1, NULL, 0, 8, -1 }, +/*12*/ { NULL, cesaDataAndSha1digest1, NULL, 0, 8, -1 }, +/*13*/ { cesaDataHexStr3, cesaHmacSha1digestHex3, NULL, 0, 50, -1 }, +/*14*/ { NULL, cesaDataAndSha1digest3, NULL, 0, 50, -1 }, +/*15*/ { hashHexStr3, hashMd5digest3, NULL, 0, 3, -1 }, +/*16*/ { hashHexStr3, hashSha1digest3, NULL, 0, 3, -1 }, +/*17*/ { hashHexStr80, tripleDesThenMd5digest80, NULL, 80, 80, -1 }, +/*18*/ { hashHexStr80, tripleDesThenSha1digest80, NULL, 80, 80, -1 }, +/*19*/ { hashHexStr80, cbc3desThenMd5digest80, iv1, 80, 80, -1 }, +/*20*/ { hashHexStr80, cbc3desThenSha1digest80, iv1, 80, 80, -1 }, +/*21*/ { hashHexStr80, cbcAes128ThenMd5digest80, iv5, 80, 80, -1 }, +/*22*/ { hashHexStr80, cbcAes128ThenSha1digest80, iv5, 80, 80, -1 }, +/*23*/ { cesaAesCtrPlain, cesaAesCtrCipher, NULL, 36, 0, -1 }, +/*24*/ { cesaAesIvPlainText, cesaAes128IvCipherCbc, NULL, 64, 0, -1 }, +/*25*/ { plain3des1, cipher3des1, NULL, 0, 0, -1 }, +/*26*/ { plain3des2, cipher3desCbc2, iv3des2,0, 0, -1 }, +/*27*/ { plain3des3, cipher3desCbc3, iv3des3,0, 0, -1 }, +}; + + +/* Key = 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + * 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + * Input 0xdd repeated "size" times + */ +static MV_CESA_SIZE_TEST mdMultiSizeTest302[] = +{ + { 80, "7a031a640c14a4872814930b1ef3a5b2" }, + { 512, "5488e6c5a14dc72a79f28312ca5b939b" }, + { 1000, "d00814f586a8b78a05724239d2531821" }, + { 1001, "bf07df7b7f49d3f5b5ecacd4e9e63281" }, + { 1002, "1ed4a1a802e87817a819d4e37bb4d0f7" }, + { 1003, "5972ab64a4f265ee371dac2f2f137f90" }, + { 1004, "71f95e7ec3aa7df2548e90898abdb28e" }, + { 1005, "e082790b4857fcfc266e92e59e608814" }, + { 1006, "9500f02fd8ac7fde8b10e4fece9a920d" }, + { 1336, "e42edcce57d0b75b01aa09d71427948b" }, + { 1344, "bb5454ada0deb49ba0a97ffd60f57071" }, + { 1399, "0f44d793e744b24d53f44f295082ee8c" }, + { 1400, "359de8a03a9b707928c6c60e0e8d79f1" }, + { 1401, "e913858b484cbe2b384099ea88d8855b" }, + { 1402, "d9848a164af53620e0540c1d7d87629e" }, + { 1403, "0c9ee1c2c9ef45e9b625c26cbaf3e822" }, + { 1404, "12edd4f609416e3c936170360561b064" }, + { 1405, "7fc912718a05446395345009132bf562" }, + { 1406, "882f17425e579ff0d85a91a59f308aa0" }, + { 1407, "005cae408630a2fb5db82ad9db7e59da" }, + { 1408, "64655f8b404b3fea7a3e3e609bc5088f" }, + { 1409, "4a145284a7f74e01b6bb1a0ec6a0dd80" }, + { 2048, "67caf64475650732def374ebb8bde3fd" }, + { 2049, "6c84f11f472825f7e6cd125c2981884b" }, + { 2050, "8999586754a73a99efbe4dbad2816d41" }, + { 2051, "ba6946b610e098d286bc81091659dfff" }, + { 2052, "d0afa01c92d4d13def2b024f36faed83" }, + { 3072, "61d8beac61806afa2585d74a9a0e6974" }, + { 3074, "f6501a28dcc24d1e4770505c51a87ed3" }, + { 3075, "ea4a6929be67e33e61ff475369248b73" }, + { 4048, "aa8c4d68f282a07e7385acdfa69f4bed" }, + { 4052, "afb5ed2c0e1d430ea59e59ed5ed6b18a" }, + { 4058, "9e8553f9bdd43aebe0bd729f0e600c99" }, + { 6144, "f628f3e5d183fe5cdd3a5abee39cf872" }, + { 6150, "89a3efcea9a2f25f919168ad4a1fd292" }, + { 6400, "cdd176b7fb747873efa4da5e32bdf88f" }, + { 6528, "b1d707b027354aca152c45ee559ccd3f" }, + { 8192, "c600ea4429ac47f9941f09182166e51a" }, + {16384, "16e8754bfbeb4c649218422792267a37" }, + {18432, "0fd0607521b0aa8b52219cfbe215f63e" }, + { 0, NULL }, +}; + +/* Key = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + */ +static MV_CESA_SIZE_TEST mdMultiSizeTest304[] = +{ + { 80, "a456c4723fee6068530af5a2afa71627" }, + { 512, "f85c2a2344f5de68b432208ad13e5794" }, + { 1000, "35464d6821fd4a293a41eb84e274c8c5" }, + { 1001, "c08eedbdce60cceb54bc2d732bb32c8b" }, + { 1002, "5664f71800c011cc311cb6943339c1b8" }, + { 1003, "779c723b044c585dc7802b13e8501bdc" }, + { 1004, "55e500766a2c307bc5c5fdd15e4cacd4" }, + { 1005, "d5f978954f5c38529d1679d2b714f068" }, + { 1006, "cd3efc827ce628b7281b72172693abf9" }, + { 1336, "6f04479910785878ae6335b8d1e87edf" }, + { 1344, "b6d27b50c2bce1ba2a8e1b5cc4324368" }, + { 1399, "65f70a1d4c86e5eaeb0704c8a7816795" }, + { 1400, "3394b5adc4cb3ff98843ca260a44a88a" }, + { 1401, "3a06f3582033a66a4e57e0603ce94e74" }, + { 1402, "e4d97f5ed51edc48abfa46eeb5c31752" }, + { 1403, "3d05e40b080ee3bedf293cb87b7140e7" }, + { 1404, "8cf294fc3cd153ab18dccb2a52cbf244" }, + { 1405, "d1487bd42f6edd9b4dab316631159221" }, + { 1406, "0527123b6bf6936cf5d369dc18c6c70f" }, + { 1407, "3224a06639db70212a0cd1ae1fcc570a" }, + { 1408, "a9e13335612c0356f5e2c27086e86c43" }, + { 1409, "a86d1f37d1ed8a3552e9a4f04dceea98" }, + { 2048, "396905c9b961cd0f6152abfb69c4449c" }, + { 2049, "49f39bff85d9dcf059fadb89efc4a70f" }, + { 2050, "3a2b4823bc4d0415656550226a63e34a" }, + { 2051, "dec60580d406c782540f398ad0bcc7e0" }, + { 2052, "32f76610a14310309eb748fe025081bf" }, + { 3072, "45edc1a42bf9d708a621076b63b774da" }, + { 3074, "9be1b333fe7c0c9f835fb369dc45f778" }, + { 3075, "8c06fcac7bd0e7b7a17fd6508c09a549" }, + { 4048, "0ddaef848184bf0ad98507a10f1e90e4" }, + { 4052, "81976bcaeb274223983996c137875cb8" }, + { 4058, "0b0a7a1c82bc7cbc64d8b7cd2dc2bb22" }, + { 6144, "1c24056f52725ede2dff0d7f9fc9855f" }, + { 6150, "b7f4b65681c4e43ee68ca466ca9ca4ec" }, + { 6400, "443bbaab9f7331ddd4bf11b659cd43c8" }, + { 6528, "216f44f23047cfee03a7a64f88f9a995" }, + { 8192, "ac7a993b2cad54879dba1bde63e39097" }, + { 8320, "55ed7be9682d6c0025b3221a62088d08" }, + {16384, "c6c722087653b62007aea668277175e5" }, + {18432, "f1faca8e907872c809e14ffbd85792d6" }, + { 0, NULL }, +}; + +/* HASH-MD5 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * repeated "size" times + */ +static MV_CESA_SIZE_TEST mdMultiSizeTest305[] = +{ + { 80, "57edf4a22be3c955ac49da2e2107b67a" }, + { 512, "c729ae8f0736cc377a9767a660eaa04e" }, + { 1000, "f1257a8659eb92d36fe14c6bf3852a6a" }, + { 1001, "f8a46fe8ea04fdc8c7de0e84042d3878" }, + { 1002, "da188dd67bff87d58aa3c02af2d0cc0f" }, + { 1003, "961753017feee04c9b93a8e51658a829" }, + { 1004, "dd68c4338608dcc87807a711636bf2af" }, + { 1005, "e338d567d3ce66bf69ada29658a8759b" }, + { 1006, "443c9811e8b92599b0b149e8d7ec700a" }, + { 1336, "89a98511706008ba4cbd0b4a24fa5646" }, + { 1344, "335a919805f370b9e402a62c6fe01739" }, + { 1399, "5d18d0eddcd84212fe28d812b5e80e3b" }, + { 1400, "6b695c240d2dffd0dffc99459ca76db6" }, + { 1401, "49590f61298a76719bc93a57a30136f5" }, + { 1402, "94c2999fa3ef1910a683d69b2b8476f2" }, + { 1403, "37073a02ab00ecba2645c57c228860db" }, + { 1404, "1bcd06994fce28b624f0c5fdc2dcdd2b" }, + { 1405, "11b93671a64c95079e8cf9e7cddc8b3d" }, + { 1406, "4b6695772a4c66313fa4871017d05f36" }, + { 1407, "d1539b97fbfda1c075624e958de19c5b" }, + { 1408, "b801b9b69920907cd018e8063092ede9" }, + { 1409, "b765f1406cfe78e238273ed01bbcaf7e" }, + { 2048, "1d7e2c64ac29e2b3fb4c272844ed31f5" }, + { 2049, "71d38fac49c6b1f4478d8d88447bcdd0" }, + { 2050, "141c34a5592b1bebfa731e0b23d0cdba" }, + { 2051, "c5e1853f21c59f5d6039bd13d4b380d8" }, + { 2052, "dd44a0d128b63d4b5cccd967906472d7" }, + { 3072, "37d158e33b21390822739d13db7b87fe" }, + { 3074, "aef3b209d01d39d0597fe03634bbf441" }, + { 3075, "335ffb428eabf210bada96d74d5a4012" }, + { 4048, "2434c2b43d798d2819487a886261fc64" }, + { 4052, "ac2fa84a8a33065b2e92e36432e861f8" }, + { 4058, "856781f85616c341c3533d090c1e1e84" }, + { 6144, "e5d134c652c18bf19833e115f7a82e9b" }, + { 6150, "a09a353be7795fac2401dac5601872e6" }, + { 6400, "08b9033ac6a1821398f50af75a2dbc83" }, + { 6528, "3d47aa193a8540c091e7e02f779e6751" }, + { 8192, "d3164e710c0626f6f395b38f20141cb7" }, + { 8320, "b727589d9183ff4e8491dd24466974a3" }, + {16384, "3f54d970793d2274d5b20d10a69938ac" }, + {18432, "f558511dcf81985b7a1bb57fad970531" }, + { 0, NULL }, +}; + + +/* Key = 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + * 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + * 0xaa, 0xaa, 0xaa, 0xaa + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + */ +static MV_CESA_SIZE_TEST shaMultiSizeTest402[] = +{ + { 80, "e812f370e659705a1649940d1f78cd7af18affd3" }, + { 512, "e547f886b2c15d995ed76a8a924cb408c8080f66" }, + { 1000, "239443194409f1a5342ecde1a092c8f3a3ed790a" }, + { 1001, "f278ab9a102850a9f48dc4e9e6822afe2d0c52b5" }, + { 1002, "8bcc667df5ab6ece988b3af361d09747c77f4e72" }, + { 1003, "0fae6046c7dc1d3e356b25af836f6077a363f338" }, + { 1004, "0ea48401cc92ae6bc92ae76685269cb0167fbe1a" }, + { 1005, "ecbcd7c879b295bafcd8766cbeac58cc371e31d1" }, + { 1006, "eb4a4a3d07d1e9a15e6f1ab8a9c47f243e27324c" }, + { 1336, "f5950ee1d77c10e9011d2149699c9366fe52529c" }, + { 1344, "b04263604a63c351b0b3b9cf1785b4bdba6c8838" }, + { 1399, "8cb1cff61d5b784045974a2fc69386e3b8d24218" }, + { 1400, "9bb2f3fcbeddb2b90f0be797cd647334a2816d51" }, + { 1401, "23ae462a7a0cb440f7445791079a5d75a535dd33" }, + { 1402, "832974b524a4d3f9cc2f45a3cabf5ccef65cd2aa" }, + { 1403, "d1c683742fe404c3c20d5704a5430e7832a7ec95" }, + { 1404, "867c79042e64f310628e219d8b85594cd0c7adc3" }, + { 1405, "c9d81d49d13d94358f56ccfd61af02b36c69f7c3" }, + { 1406, "0df43daab2786172f9b8d07d61f14a070cf1287a" }, + { 1407, "0fd8f3ad7f169534b274d4c66bbddd89f759e391" }, + { 1408, "3987511182b18473a564436003139b808fa46343" }, + { 1409, "ef667e063c9e9f539a8987a8d0bd3066ee85d901" }, + { 2048, "921109c99f3fedaca21727156d5f2b4460175327" }, + { 2049, "47188600dd165eb45f27c27196d3c46f4f042c1b" }, + { 2050, "8831939904009338de10e7fa670847041387807d" }, + { 2051, "2f8ebb5db2997d614e767be1050366f3641e7520" }, + { 2052, "669e51cd730dae158d3bef8adba075bd95a0d011" }, + { 3072, "cfee66cfd83abc8451af3c96c6b35a41cc6c55f5" }, + { 3074, "216ea26f02976a261b7d21a4dd3085157bedfabd" }, + { 3075, "bd612ebba021fd8e012b14c3bd60c8c5161fabc0" }, + { 4048, "c2564c1fdf2d5e9d7dde7aace2643428e90662e8" }, + { 4052, "91ce61fe924b445dfe7b5a1dcd10a27caec16df6" }, + { 4058, "db2a9be5ee8124f091c7ebd699266c5de223c164" }, + { 6144, "855109903feae2ba3a7a05a326b8a171116eb368" }, + { 6150, "37520bb3a668294d9c7b073e7e3daf8fee248a78" }, + { 6400, "60a353c841b6d2b1a05890349dad2fa33c7536b7" }, + { 6528, "9e53a43a69bb42d7c8522ca8bd632e421d5edb36" }, + { 8192, "a918cb0da862eaea0a33ee0efea50243e6b4927c" }, + { 8320, "29a5dcf55d1db29cd113fcf0572ae414f1c71329" }, + {16384, "6fb27966138e0c8d5a0d65ace817ebd53633cee1" }, + {18432, "ca09900d891c7c9ae2a559b10f63a217003341c1" }, + { 0, NULL }, +}; + +/* Key = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * 0x11, 0x12, 0x13, 0x14 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + */ +static MV_CESA_SIZE_TEST shaMultiSizeTest404[] = +{ + { 80, "beaf20a34b06a87558d156c0949bc3957d40222e" }, + { 512, "3353955358d886bc2940a3c7f337ff7dafb59c7b" }, + { 1000, "8737a542c5e9b2b6244b757ebb69d5bd602a829f" }, + { 1001, "fd9e7582d8a5d3c9fe3b923e4e6a41b07a1eb4d4" }, + { 1002, "a146d14a6fc3c274ff600568f4d75b977989e00d" }, + { 1003, "be22601bbc027ddef2dec97d30b3dc424fd803c5" }, + { 1004, "3e71fe99b2fe2b7bfdf4dbf0c7f3da25d7ea35e7" }, + { 1005, "2c422735d7295408fddd76f5e8a83a2a8da13df3" }, + { 1006, "6d875319049314b61855101a647b9ba3313428e6" }, + { 1336, "c1631ea80bad9dc43a180712461b65a0598c711c" }, + { 1344, "816069bf91d34581005746e2e0283d0f9c7b7605" }, + { 1399, "4e139866dc61cfcb8b67ca2ebd637b3a538593af" }, + { 1400, "ff2a0f8dd2b02c5417910f6f55d33a78e081a723" }, + { 1401, "ab00c12be62336964cbce31ae97fe2a0002984d5" }, + { 1402, "61349e7f999f3a1acc56c3e9a5060a9c4a7b05b6" }, + { 1403, "3edbc0f61e435bc1317fa27d840076093fb79353" }, + { 1404, "d052c6dfdbe63d45dab23ef9893e2aa4636aca1e" }, + { 1405, "0cc16b7388d67bf0add15a31e6e6c753cfae4987" }, + { 1406, "c96ba7eaad74253c38c22101b558d2850b1d1b90" }, + { 1407, "3445428a40d2c6556e7c55797ad8d323b61a48d9" }, + { 1408, "8d6444f937a09317c89834187b8ea9b8d3a8c56b" }, + { 1409, "c700acd3ecd19014ea2bdb4d42510c467e088475" }, + { 2048, "ee27d2a0cb77470c2f496212dfd68b5bb7b04e4b" }, + { 2049, "683762d7a02983b26a6d046e6451d9cd82c25932" }, + { 2050, "0fd20f1d55a9ee18363c2a6fd54aa13aee69992f" }, + { 2051, "86c267d8cc4bc8d59090e4f8b303da960fd228b7" }, + { 2052, "452395ae05b3ec503eea34f86fc0832485ad97c1" }, + { 3072, "75198e3cfd0b9bcff2dabdf8e38e6fdaa33ca49a" }, + { 3074, "4e24785ef080141ce4aab4675986d9acea624d7c" }, + { 3075, "3a20c5978dd637ec0e809bf84f0d9ccf30bc65bf" }, + { 4048, "3c32da256be7a7554922bf5fed51b0d2d09e59ad" }, + { 4052, "fff898426ea16e54325ae391a32c6c9bce4c23c0" }, + { 4058, "c800b9e562e1c91e1310116341a3c91d37f848ec" }, + { 6144, "d91d509d0cc4376c2d05bf9a5097717a373530e6" }, + { 6150, "d957030e0f13c5df07d9eec298542d8f94a07f12" }, + { 6400, "bb745313c3d7dc17b3f955e5534ad500a1082613" }, + { 6528, "77905f80d9ca82080bbb3e5654896dabfcfd1bdb" }, + { 8192, "5237fd9a81830c974396f99f32047586612ff3c0" }, + { 8320, "57668e28d5f2dba0839518a11db0f6af3d7e08bf" }, + {16384, "62e093fde467f0748087beea32e9af97d5c61241" }, + {18432, "845fb33130c7d6ea554fd5aacb9c50cf7ccb5929" }, + { 0, NULL }, +}; + +/* HASH-SHA1 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * repeated "size" times + */ +static MV_CESA_SIZE_TEST shaMultiSizeTest405[] = +{ + { 80, "50abf5706a150990a08b2c5ea40fa0e585554732" }, + { 512, "f14516a08948fa27917a974d219741a697ba0087" }, + { 1000, "0bd18c378d5788817eb4f1e5dc07d867efa5cbf4" }, + { 1001, "ca29b85c35db1b8aef83c977893a11159d1b7aa2" }, + { 1002, "d83bc973eaaedb8a31437994dabbb3304b0be086" }, + { 1003, "2cf7bbef0acd6c00536b5c58ca470df9a3a90b6c" }, + { 1004, "e4375d09b1223385a8a393066f8209acfd936a80" }, + { 1005, "1029b38043e027745d019ce1d2d68e3d8b9d8f99" }, + { 1006, "deea16dcebbd8ac137e2b984deb639b9fb5e9680" }, + { 1336, "ea031b065fff63dcfb6a41956e4777520cdbc55d" }, + { 1344, "b52096c6445e6c0a8355995c70dc36ae186c863c" }, + { 1399, "cde2f6f8379870db4b32cf17471dc828a8dbff2b" }, + { 1400, "e53ff664064bc09fe5054c650806bd42d8179518" }, + { 1401, "d1156db5ddafcace64cdb510ff0d4af9b9a8ad64" }, + { 1402, "34ede0e9a909dd84a2ae291539105c0507b958e1" }, + { 1403, "a772ca3536da77e6ad3251e4f9e1234a4d7b87c0" }, + { 1404, "29740fd2b04e7a8bfd32242db6233156ad699948" }, + { 1405, "65b17397495b70ce4865dad93bf991b74c97cce1" }, + { 1406, "a7ee89cd0754061fdb91af7ea6abad2c69d542e3" }, + { 1407, "3eebf82f7420188e23d328b7ce93580b279a5715" }, + { 1408, "e08d3363a8b9a490dfb3a4c453452b8f114deeec" }, + { 1409, "95d74df739181a4ff30b8c39e28793a36598e924" }, + { 2048, "aa40262509c2abf84aab0197f83187fc90056d91" }, + { 2049, "7dec28ef105bc313bade8d9a7cdeac58b99de5ea" }, + { 2050, "d2e30f77ec81197de20f56588a156094ecb88450" }, + { 2051, "6b22ccc874833e96551a39da0c0edcaa0d969d92" }, + { 2052, "f843141e57875cd669af58744bc60aa9ea59549c" }, + { 3072, "09c5fedeaa62c132e673cc3c608a00142273d086" }, + { 3074, "b09e95eea9c7b1b007a58accec488301901a7f3d" }, + { 3075, "e6226b77b4ada287a8c9bbcf4ed71eec5ce632dc" }, + { 4048, "e99394894f855821951ddddf5bfc628547435f5c" }, + { 4052, "32d2f1af38be9cfba6cd03d55a254d0b3e1eb382" }, + { 4058, "d906552a4f2aca3a22e1fecccbcd183d7289d0ef" }, + { 6144, "2e7f62d35a860988e1224dc0543204af19316041" }, + { 6150, "d6b89698ee133df46fec9d552fadc328aa5a1b51" }, + { 6400, "dff50e90c46853988fa3a4b4ce5dda6945aae976" }, + { 6528, "9e63ec0430b96db02d38bc78357a2f63de2ab7f8" }, + { 8192, "971eb71ed60394d5ab5abb12e88420bdd41b5992" }, + { 8320, "91606a31b46afeaac965cecf87297e791b211013" }, + {16384, "547f830a5ec1f5f170ce818f156b1002cabc7569" }, + {18432, "f16f272787f3b8d539652e4dc315af6ab4fda0ef" }, + { 0, NULL }, +}; + +/* CryptoKey = 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef; + * MacKey = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * Note: only sizes aligned to 3DES block size (8 bytes) allowed + */ +static MV_CESA_SIZE_TEST tripleDesMdMultiSizeTest502[] = +{ + { 64, "9586962a2aaaef28803dec2e17807a7f" }, + { 80, "b7726a03aad490bd6c5a452a89a1b271" }, + { 352, "f1ed9563aecc3c0d2766eb2bed3b4e4c" }, + { 512, "0f9decb11ab40fe86f4d4d9397bc020e" }, + { 1000, "3ba69deac12cab8ff9dff7dbd9669927" }, + { 1336, "6cf47bf1e80e03e2c1d0945bc50d37d2" }, + { 1344, "4be388dab21ceb3fa1b8d302e9b821f7" }, + { 1400, "a58b79fb21dd9bfc6ec93e3b99fb0ef1" }, + { 1408, "8bc97379fc2ac3237effcdd4f7a86528" }, + { 2048, "1339f03ab3076f25a20bc4cba16eb5bf" }, + { 3072, "731204d2d90c4b36ae41f5e1fb874288" }, + { 4048, "c028d998cfda5642547b7e1ed5ea16e4" }, + { 6144, "b1b19cd910cc51bd22992f1e59f1e068" }, + { 6400, "44e4613496ba622deb0e7cb768135a2f" }, + { 6528, "3b06b0a86f8db9cd67f9448dfcf10549" }, + { 8192, "d581780b7163138a0f412be681457d82" }, + {16384, "03b8ac05527faaf1bed03df149c65ccf" }, + {18432, "677c8a86a41dab6c5d81b85b8fb10ff6" }, + { 0, NULL }, +}; + + +/* CryptoKey = 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef; + * MacKey = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * 0x11, 0x12, 0x13, 0x14 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * Note: only sizes aligned to 3DES block size (8 bytes) allowed + */ +static MV_CESA_SIZE_TEST tripleDesShaMultiSizeTest503[] = +{ + { 64, "44a1e9bcbfc1429630d9ea68b7a48b0427a684f2" }, + { 80, "b2ddeaca91030eab5b95a234ef2c0f6e738ff883" }, + { 352, "4b91864c7ff629bdff75d9726421f76705452aaf" }, + { 512, "6dd37faceeb2aa98ba74f4242ed6734a4d546af5" }, + { 1000, "463661c30300be512a9df40904f0757cde5f1141" }, + { 1336, "b931f831d9034fe59c65176400b039fe9c1f44a5" }, + { 1344, "af8866b1cd4a4887d6185bfe72470ffdfb3648e1" }, + { 1400, "49c6caf07296d5e31d2504d088bc5b20c3ee7cdb" }, + { 1408, "fcae8deedbc6ebf0763575dc7e9de075b448a0f4" }, + { 2048, "edece5012146c1faa0dd10f50b183ba5d2af58ac" }, + { 3072, "5b83625adb43a488b8d64fecf39bb766818547b7" }, + { 4048, "d2c533678d26c970293af60f14c8279dc708bfc9" }, + { 6144, "b8f67af4f991b08b725f969b049ebf813bfacc5c" }, + { 6400, "d9a6c7f746ac7a60ef2edbed2841cf851c25cfb0" }, + { 6528, "376792b8c8d18161d15579fb7829e6e3a27e9946" }, + { 8192, "d890eabdca195b34ef8724b28360cffa92ae5655" }, + {16384, "a167ee52639ec7bf19aee9c6e8f76667c14134b9" }, + {18432, "e4396ab56f67296b220985a12078f4a0e365d2cc" }, + { 0, NULL }, +}; + +/* CryptoKey = 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef + * IV = 0x12345678, 0x90abcdef + * MacKey = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * Note: only sizes aligned to 3DES block size (8 bytes) allowed + */ +static MV_CESA_SIZE_TEST cbc3desMdMultiSizeTest504[] = +{ + { 64, "8d10e00802460ede0058c139ba48bd2d" }, + { 80, "6f463057e1a90e0e91ae505b527bcec0" }, + { 352, "4938d48bdf86aece2c6851e7c6079788" }, + { 512, "516705d59f3cf810ebf2a13a23a7d42e" }, + { 1000, "a5a000ee5c830e67ddc6a2d2e5644b31" }, + { 1336, "44af60087b74ed07950088efbe3b126a" }, + { 1344, "1f5b39e0577920af731dabbfcf6dfc2a" }, + { 1400, "6804ea640e29b9cd39e08bc37dbce734" }, + { 1408, "4fb436624b02516fc9d1535466574bf9" }, + { 2048, "c909b0985c423d8d86719f701e9e83db" }, + { 3072, "cfe0bc34ef97213ee3d3f8b10122db21" }, + { 4048, "03ea10b5ae4ddeb20aed6af373082ed1" }, + { 6144, "b9a0ff4f87fc14b3c2dc6f0ed0998fdf" }, + { 6400, "6995f85d9d4985dd99e974ec7dda9dd6" }, + { 6528, "bbbb548ce2fa3d58467f6a6a5168a0e6" }, + { 8192, "afe101fbe745bb449ae4f50d10801456" }, + {16384, "9741706d0b1c923340c4660ff97cacdf" }, + {18432, "b0217becb73cb8f61fd79c7ce9d023fb" }, + { 0, NULL }, +}; + + +/* CryptoKey = 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef; + * IV = 0x12345678, 0x90abcdef + * MacKey = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * 0x11, 0x12, 0x13, 0x14 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * Note: only sizes aligned to 3DES block size (8 bytes) allowed + */ +static MV_CESA_SIZE_TEST cbc3desShaMultiSizeTest505[] = +{ + { 64, "409187e5bdb0be4a7754ca3747f7433dc4f01b98" }, + { 80, "1b002ed050be743aa98860cf35659646bb8efcc0" }, + { 352, "6cbf7ebe50fa4fa6eecc19eca23f9eae553ccfff" }, + { 512, "cfb5253fb4bf72b743320c30c7e48c54965853b0" }, + { 1000, "95e04e1ca2937e7c5a9aba9e42d2bcdb8a7af21f" }, + { 1336, "3b5c1f5eee5837ebf67b83ae01405542d77a6627" }, + { 1344, "2b3d42ab25615437f98a1ee310b81d07a02badc2" }, + { 1400, "7f8687df7c1af44e4baf3c934b6cca5ab6bc993e" }, + { 1408, "473a581c5f04f7527d50793c845471ac87e86430" }, + { 2048, "e41d20cae7ebe34e6e828ed62b1e5734019037bb" }, + { 3072, "275664afd7a561d804e6b0d204e53939cde653ae" }, + { 4048, "0d220cc5b34aeeb46bbbd637dde6290b5a8285a3" }, + { 6144, "cb393ddcc8b1c206060625b7d822ef9839e67bc5" }, + { 6400, "dd3317e2a627fc04800f74a4b05bfda00fab0347" }, + { 6528, "8a74c3b2441ab3f5a7e08895cc432566219a7c41" }, + { 8192, "b8e6ef3a549ed0e005bd5b8b1a5fe6689e9711a7" }, + {16384, "55f59404008276cdac0e2ba0d193af2d40eac5ce" }, + {18432, "86ae6c4fc72369a54cce39938e2d0296cd9c6ec5" }, + { 0, NULL }, +}; + + +/* CryptoKey = 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef + * IV = 0x12345678, 0x90abcdef + * MacKey = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * Note: only sizes aligned to AES block size (16 bytes) allowed + */ +static MV_CESA_SIZE_TEST cbcAes128md5multiSizeTest506[] = +{ + { 16, "7ca4c2ba866751598720c5c4aa0d6786" }, + { 64, "7dba7fb988e80da609b1fea7254bced8" }, + { 80, "6b6e863ac5a71d15e3e9b1c86c9ba05f" }, + { 352, "a1ceb9c2e3021002400d525187a9f38c" }, + { 512, "596c055c1c55db748379223164075641" }, + { 1008, "f920989c02f3b3603f53c99d89492377" }, + { 1344, "2e496b73759d77ed32ea222dbd2e7b41" }, + { 1408, "7178c046b3a8d772efdb6a71c4991ea4" }, + { 2048, "a917f0099c69eb94079a8421714b6aad" }, + { 3072, "693cd5033d7f5391d3c958519fa9e934" }, + { 4048, "139dca91bcff65b3c40771749052906b" }, + { 6144, "428d9cef6df4fb70a6e9b6bbe4819e55" }, + { 6400, "9c0b909e76daa811e12b1fc17000a0c4" }, + { 6528, "ad876f6297186a7be1f1b907ed860eda" }, + { 8192, "479cbbaca37dd3191ea1f3e8134a0ef4" }, + {16384, "60fda559c74f91df538100c9842f2f15" }, + {18432, "4a3eb1cba1fa45f3981270953f720c42" }, + { 0, NULL }, +}; + + +/* CryptoKey = 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef, + * 0x01234567, 0x89abcdef; + * IV = 0x12345678, 0x90abcdef + * MacKey = 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + * 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + * 0x11, 0x12, 0x13, 0x14 + * InputHexStr = "31323334353637383930" (ASCII = "1234567890") + * Note: only sizes aligned to AES block size (16 bytes) allowed + */ +static MV_CESA_SIZE_TEST cbcAes128sha1multiSizeTest507[] = +{ + { 16, "9aa8dc1c45f0946daf78057fa978759c625c1fee" }, + { 64, "9f588fc1ede851e5f8b20256abc9979465ae2189" }, + { 80, "13558472d1fc1c90dffec6e5136c7203452d509b" }, + { 352, "6b93518e006cfaa1f7adb24615e7291fb0a27e06" }, + { 512, "096874951a77fbbf333e49d80c096ee2016e09bd" }, + { 1008, "696fc203c2e4b5ae0ec5d1db3f623c490bc6dbac" }, + { 1344, "79bf77509935ccd3528caaac6a5eb6481f74029b" }, + { 1408, "627f9462b95fc188e8cfa7eec15119bdc5d4fcf1" }, + { 2048, "3d50d0c005feba92fe41502d609fced9c882b4d1" }, + { 3072, "758807e5b983e3a91c06fb218fe0f73f77111e94" }, + { 4048, "ca90e85242e33f005da3504416a52098d0d31fb2" }, + { 6144, "8044c1d4fd06642dfc46990b4f18b61ef1e972cf" }, + { 6400, "166f1f4ea57409f04feba9fb1e39af0e00bd6f43" }, + { 6528, "0389016a39485d6e330f8b4215ddf718b404f7e9" }, + { 8192, "6df7ee2a8b61d6f7f860ce8dbf778f0c2a5b508b" }, + {16384, "a70a6d8dfa1f91ded621c3dbaed34162bc48783f" }, + {18432, "8dfad627922ce15df1eed10bdbed49244efa57db" }, + { 0, NULL }, +}; + + +void cesaTestPrintStatus(void); + + +/*------------------------- LOCAL FUNCTIONs ---------------------------------*/ +MV_STATUS testCmd(int sid, int iter, MV_CESA_COMMAND* pCmd, + MV_CESA_TEST_SESSION* pTestSession, MV_U8* pIV, int ivSize); +MV_STATUS testClose(int idx); +MV_STATUS testOpen(int idx); +void close_session(int sid); +void cesaTestCheckReady(const MV_CESA_RESULT *r); +void cesaCheckReady(MV_CESA_RESULT* r); +void printTestResults(int idx, MV_STATUS status, int checkMode); +void cesaLastResult(void); +void cesaTestPrintReq(int req, int offset, int size); + +void cesaTestPrintStatus(void); +void cesaTestPrintSession(int idx); +void sizeTest(int testIdx, int iter, int checkMode); +void multiTest(int iter, int reqSize, int checkMode); +void oneTest(int testIdx, int caseIdx,int iter, int reqSize, int checkMode); +void multiSizeTest(int idx, int iter, int checkMode, char* inputData); +void cesaTest(int iter, int reqSize, int checkMode); +void cesaOneTest(int testIdx, int caseIdx,int iter, int reqSize, int checkMode); +void combiTest(int iter, int reqSize, int checkMode); +void shaTest(int iter, int reqSize, int checkMode); +void mdTest(int iter, int reqSize, int checkMode); +void aesTest(int iter, int reqSize, int checkMode); +void tripleDesTest(int iter, int reqSize, int checkMode); +void desTest(int iter, int reqSize, int checkMode); +void cesaTestStop(void); +MV_STATUS testRun(int idx, int caseIdx, int iter,int reqSize, int checkMode); +void cesaTestStart(int bufNum, int bufSize); + + +static MV_U32 getRate(MV_U32* remainder) +{ + MV_U32 kBits, milliSec, rate; + + milliSec = 0; + if( (cesaEndTicks - cesaBeginTicks) > 0) + { + milliSec = CESA_TEST_TICK_TO_MS(cesaEndTicks - cesaBeginTicks); + } + if(milliSec == 0) + { + if(remainder != NULL) + *remainder = 0; + return 0; + } + + kBits = (cesaIteration*cesaRateSize*8)/1000; + rate = kBits/milliSec; + if(remainder != NULL) + *remainder = ((kBits % milliSec)*10)/milliSec; + + return rate; +} + +static char* extractMbuf(MV_CESA_MBUF *pMbuf, + int offset, int size, char* hexStr) +{ + mvCesaCopyFromMbuf((MV_U8*)cesaBinBuffer, pMbuf, offset, size); + mvBinToHex((const MV_U8*)cesaBinBuffer, hexStr, size); + + return hexStr; +} + +static MV_BOOL cesaCheckMbuf(MV_CESA_MBUF *pMbuf, + const char* hexString, int offset, + int checkSize) +{ + MV_BOOL isFailed = MV_FALSE; + MV_STATUS status; + int size = strlen(hexString)/2; + int checkedSize = 0; +/* + mvOsPrintf("cesaCheckMbuf: pMbuf=%p, offset=%d, checkSize=%d, mBufSize=%d\n", + pMbuf, offset, checkSize, pMbuf->mbufSize); +*/ + if(pMbuf->mbufSize < (checkSize + offset)) + { + mvOsPrintf("checkSize (%d) is too large: offset=%d, mbufSize=%d\n", + checkSize, offset, pMbuf->mbufSize); + return MV_TRUE; + } + status = mvCesaCopyFromMbuf((MV_U8*)cesaBinBuffer, pMbuf, offset, checkSize); + if(status != MV_OK) + { + mvOsPrintf("CesaTest: Can't copy %d bytes from Mbuf=%p to checkBuf=%p\n", + checkSize, pMbuf, cesaBinBuffer); + return MV_TRUE; + } +/* + mvDebugMemDump(cesaBinBuffer, size, 1); +*/ + mvHexToBin(hexString, (MV_U8*)cesaExpBinBuffer, size); + + /* Compare buffers */ + while(checkSize > checkedSize) + { + size = MV_MIN(size, (checkSize - checkedSize)); + if(memcmp(cesaExpBinBuffer, &cesaBinBuffer[checkedSize], size) != 0) + { + mvOsPrintf("CheckMbuf failed: checkSize=%d, size=%d, checkedSize=%d\n", + checkSize, size, checkedSize); + mvDebugMemDump(&cesaBinBuffer[checkedSize], size, 1); + mvDebugMemDump(cesaExpBinBuffer, size, 1); + + isFailed = MV_TRUE; + break; + } + checkedSize += size; + } + + return isFailed; +} + +static MV_STATUS cesaSetMbuf(MV_CESA_MBUF *pMbuf, + const char* hexString, + int offset, int reqSize) +{ + MV_STATUS status = MV_OK; + int copySize, size = strlen(hexString)/2; + + mvHexToBin(hexString, (MV_U8*)cesaBinBuffer, size); + + copySize = 0; + while(reqSize > copySize) + { + size = MV_MIN(size, (reqSize - copySize)); + + status = mvCesaCopyToMbuf((MV_U8*)cesaBinBuffer, pMbuf, offset+copySize, size); + if(status != MV_OK) + { + mvOsPrintf("cesaSetMbuf Error: Copy %d of %d bytes to MBuf\n", + copySize, reqSize); + break; + } + copySize += size; + } + pMbuf->mbufSize = offset+copySize; + return status; +} + +static MV_CESA_TEST_SESSION* getTestSessionDb(int idx, int* pTestIdx) +{ + int testIdx, dbIdx = idx/100; + + if(dbIdx > MAX_TEST_TYPE) + { + mvOsPrintf("Wrong index %d - No such test type\n", idx); + return NULL; + } + testIdx = idx % 100; + + if(testIdx >= cesaTestsDB[dbIdx].numSessions) + { + mvOsPrintf("Wrong index %d - No such test\n", idx); + return NULL; + } + if(pTestIdx != NULL) + *pTestIdx = testIdx; + + return cesaTestsDB[dbIdx].pSessions; +} + +/* Debug */ +void cesaTestPrintReq(int req, int offset, int size) +{ + MV_CESA_MBUF* pMbuf; + + mvOsPrintf("cesaTestPrintReq: req=%d, offset=%d, size=%d\n", + req, offset, size); + mvDebugMemDump(cesaCmdRing, 128, 4); + + pMbuf = cesaCmdRing[req].pSrc; + mvCesaDebugMbuf("src", pMbuf, offset,size); + pMbuf = cesaCmdRing[req].pDst; + mvCesaDebugMbuf("dst", pMbuf, offset, size); + + cesaTestPrintStatus(); +} + +void cesaLastResult(void) +{ + mvOsPrintf("Last Result: ReqId = %d, SessionId = %d, rc = (%d)\n", + (MV_U32)cesaResult.pReqPrv, cesaResult.sessionId, + cesaResult.retCode); +} + +void printTestResults(int idx, MV_STATUS status, int checkMode) +{ + int testIdx; + MV_CESA_TEST_SESSION* pTestSessions = getTestSessionDb(idx, &testIdx); + + if(pTestSessions == NULL) + return; + + mvOsPrintf("%-35s %4dx%-4d : ", pTestSessions[testIdx].name, + cesaIteration, cesaReqSize); + if( (status == MV_OK) && + (cesaCryptoError == 0) && + (cesaError == 0) && + (cesaReqIdError == 0) ) + { + mvOsPrintf("Passed, Rate=%3u.%u Mbps (%5u cpp)\n", + cesaRate, cesaRateAfterDot, cesaEndTicks - cesaBeginTicks); + } + else + { + mvOsPrintf("Failed, Status = 0x%x\n", status); + if(cesaCryptoError > 0) + mvOsPrintf("cryptoError : %d\n", cesaCryptoError); + if(cesaReqIdError > 0) + mvOsPrintf("reqIdError : %d\n", cesaReqIdError); + if(cesaError > 0) + mvOsPrintf("cesaError : %d\n", cesaError); + } + if(cesaTestIsrMissCount > 0) + mvOsPrintf("cesaIsrMissed : %d\n", cesaTestIsrMissCount); +} + +void cesaCheckReady(MV_CESA_RESULT* r) +{ + int reqId; + MV_CESA_MBUF *pMbuf; + MV_BOOL isFailed; + + cesaResult = *r; + reqId = (int)cesaResult.pReqPrv; + pMbuf = cesaCmdRing[reqId].pDst; + +/* + mvOsPrintf("cesaCheckReady: reqId=%d, checkOffset=%d, checkSize=%d\n", + reqId, cesaCheckOffset, cesaCheckSize); +*/ + /* Check expected reqId */ + if(reqId != cesaExpReqId) + { + cesaReqIdError++; +/* + mvOsPrintf("CESA reqId Error: cbIter=%d (%d), reqId=%d, expReqId=%d\n", + cesaCbIter, cesaIteration, reqId, cesaExpReqId); +*/ + } + else + { + if( (cesaCheckMode == CESA_FULL_CHECK_MODE) || + (cesaCheckMode == CESA_FAST_CHECK_MODE) ) + { + if(cesaResult.retCode != MV_OK) + { + cesaError++; + + mvOsPrintf("CESA Error: cbIter=%d (%d), reqId=%d, rc=%d\n", + cesaCbIter, cesaIteration, reqId, cesaResult.retCode); + } + else + { + if( (cesaCheckSize > 0) && (cesaOutputHexStr != NULL) ) + { + /* Check expected output */ + + isFailed = cesaCheckMbuf(pMbuf, cesaOutputHexStr, cesaCheckOffset, cesaCheckSize); + if(isFailed) + { + mvOsPrintf("CESA Crypto Error: cbIter=%d (%d), reqId=%d\n", + cesaCbIter, cesaIteration, reqId); + + CESA_TEST_DEBUG_PRINT(("Error: reqId=%d, reqSize=%d, checkOffset=%d, checkSize=%d\n", + reqId, cesaReqSize, cesaCheckOffset, cesaCheckSize)); + + CESA_TEST_DEBUG_PRINT(("Output str: %s\n", cesaOutputHexStr)); + + CESA_TEST_DEBUG_CODE( mvCesaDebugMbuf("error", pMbuf, 0, cesaCheckOffset+cesaCheckSize) ); + + cesaCryptoError++; + } + } + } + } + } + if(cesaCheckMode == CESA_SHOW_CHECK_MODE) + { + extractMbuf(pMbuf, cesaCheckOffset, cesaCheckSize, cesaHexBuffer); + mvOsPrintf("%4d, %s\n", cesaCheckOffset, cesaHexBuffer); + } + + cesaCbIter++; + if(cesaCbIter >= cesaIteration) + { + cesaCbIter = 0; + cesaExpReqId = 0; + cesaIsReady = MV_TRUE; + + cesaEndTicks = CESA_TEST_TICK_GET(); + cesaRate = getRate(&cesaRateAfterDot); + } + else + { + cesaExpReqId = reqId + 1; + if(cesaExpReqId == CESA_DEF_REQ_SIZE) + cesaExpReqId = 0; + } +} + + +#ifdef MV_NETBSD +static int cesaTestReadyIsr(void *arg) +#else +#ifdef __KERNEL__ +static irqreturn_t cesaTestReadyIsr( int irq , void *dev_id) +#endif +#ifdef MV_VXWORKS +static void cesaTestReadyIsr(void) +#endif +#endif +{ + MV_U32 cause; + MV_STATUS status; + MV_CESA_RESULT result; + + cesaTestIsrCount++; + /* Clear cause register */ + cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG); + if( (cause & MV_CESA_CAUSE_ACC_DMA_ALL_MASK) == 0) + { + mvOsPrintf("cesaTestReadyIsr: cause=0x%x\n", cause); +#ifdef MV_NETBSD + return 0; +#else +#ifdef __KERNEL__ + return 1; +#else + return; +#endif +#endif + } + + MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0); + + while(MV_TRUE) + { + /* Get Ready requests */ + status = mvCesaReadyGet(&result); + if(status == MV_OK) + cesaCheckReady(&result); + + break; + } + if( (cesaTestFull == 1) && (status != MV_BUSY) ) + { + cesaTestFull = 0; + CESA_TEST_WAKE_UP(); + } + +#ifdef __KERNEL__ + return 1; +#endif +} + +void +cesaTestCheckReady(const MV_CESA_RESULT *r) +{ + MV_CESA_RESULT result = *r; + + cesaCheckReady(&result); + + if (cesaTestFull == 1) { + cesaTestFull = 0; + CESA_TEST_WAKE_UP(); + } +} + +static INLINE int open_session(MV_CESA_OPEN_SESSION* pOs) +{ + MV_U16 sid; + MV_STATUS status; + + status = mvCesaSessionOpen(pOs, (short*)&sid); + if(status != MV_OK) + { + mvOsPrintf("CesaTest: Can't open new session - status = 0x%x\n", + status); + return -1; + } + + return (int)sid; +} + +void close_session(int sid) +{ + MV_STATUS status; + + status = mvCesaSessionClose(sid); + if(status != MV_OK) + { + mvOsPrintf("CesaTest: Can't close session %d - status = 0x%x\n", + sid, status); + } +} + +MV_STATUS testOpen(int idx) +{ + MV_CESA_OPEN_SESSION os; + int sid, i, testIdx; + MV_CESA_TEST_SESSION* pTestSession; + MV_U16 digestSize = 0; + + pTestSession = getTestSessionDb(idx, &testIdx); + if(pTestSession == NULL) + { + mvOsPrintf("Test %d is not exist\n", idx); + return MV_BAD_PARAM; + } + pTestSession = &pTestSession[testIdx]; + + if(pTestSession->sid != -1) + { + mvOsPrintf("Session for test %d already created: sid=%d\n", + idx, pTestSession->sid); + return MV_OK; + } + + os.cryptoAlgorithm = pTestSession->cryptoAlgorithm; + os.macMode = pTestSession->macAlgorithm; + switch(os.macMode) + { + case MV_CESA_MAC_MD5: + case MV_CESA_MAC_HMAC_MD5: + digestSize = MV_CESA_MD5_DIGEST_SIZE; + break; + + case MV_CESA_MAC_SHA1: + case MV_CESA_MAC_HMAC_SHA1: + digestSize = MV_CESA_SHA1_DIGEST_SIZE; + break; + + case MV_CESA_MAC_NULL: + digestSize = 0; + } + os.cryptoMode = pTestSession->cryptoMode; + os.direction = pTestSession->direction; + os.operation = pTestSession->operation; + + for(i=0; icryptoKeySize; i++) + os.cryptoKey[i] = pTestSession->pCryptoKey[i]; + + os.cryptoKeyLength = pTestSession->cryptoKeySize; + + for(i=0; imacKeySize; i++) + os.macKey[i] = pTestSession->pMacKey[i]; + + os.macKeyLength = pTestSession->macKeySize; + os.digestSize = digestSize; + + sid = open_session(&os); + if(sid == -1) + { + mvOsPrintf("Can't open session for test %d: rc=0x%x\n", + idx, cesaResult.retCode); + return cesaResult.retCode; + } + CESA_TEST_DEBUG_PRINT(("Opened session: sid = %d\n", sid)); + pTestSession->sid = sid; + return MV_OK; +} + +MV_STATUS testClose(int idx) +{ + int testIdx; + MV_CESA_TEST_SESSION* pTestSession; + + pTestSession = getTestSessionDb(idx, &testIdx); + if(pTestSession == NULL) + { + mvOsPrintf("Test %d is not exist\n", idx); + return MV_BAD_PARAM; + } + pTestSession = &pTestSession[testIdx]; + + if(pTestSession->sid == -1) + { + mvOsPrintf("Test session %d is not opened\n", idx); + return MV_NO_SUCH; + } + + close_session(pTestSession->sid); + pTestSession->sid = -1; + + return MV_OK; +} + +MV_STATUS testCmd(int sid, int iter, MV_CESA_COMMAND* pCmd, + MV_CESA_TEST_SESSION* pTestSession, MV_U8* pIV, int ivSize) +{ + int cmdReqId = 0; + int i; + MV_STATUS rc = MV_OK; + char ivZeroHex[] = "0000"; + + if(iter == 0) + iter = CESA_DEF_ITER_NUM; + + if(pCmd == NULL) + { + mvOsPrintf("testCmd failed: pCmd=NULL\n"); + return MV_BAD_PARAM; + } + pCmd->sessionId = sid; + + cesaCryptoError = 0; + cesaReqIdError = 0; + cesaError = 0; + cesaTestIsrMissCount = 0; + cesaIsReady = MV_FALSE; + cesaIteration = iter; + + if(cesaInputHexStr == NULL) + cesaInputHexStr = cesaPlainHexEbc; + + for(i=0; ipSrc = (MV_CESA_MBUF*)(cesaCmdRing[i].pSrc); + if(pIV != NULL) + { + /* If IV from SA - set IV in Source buffer to zeros */ + cesaSetMbuf(pCmd->pSrc, ivZeroHex, 0, pCmd->cryptoOffset); + cesaSetMbuf(pCmd->pSrc, cesaInputHexStr, pCmd->cryptoOffset, + (cesaReqSize - pCmd->cryptoOffset)); + } + else + { + cesaSetMbuf(pCmd->pSrc, cesaInputHexStr, 0, cesaReqSize); + } + pCmd->pDst = (MV_CESA_MBUF*)(cesaCmdRing[i].pDst); + cesaSetMbuf(pCmd->pDst, cesaNullPlainHexText, 0, cesaReqSize); + + memcpy(&cesaCmdRing[i], pCmd, sizeof(*pCmd)); + } + + if(cesaCheckMode == CESA_SW_SHOW_CHECK_MODE) + { + MV_U8 pDigest[MV_CESA_MAX_DIGEST_SIZE]; + + if(pTestSession->macAlgorithm == MV_CESA_MAC_MD5) + { + mvMD5(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, pDigest); + mvOsPrintf("SW HASH_MD5: reqSize=%d, macLength=%d\n", + cesaReqSize, pCmd->macLength); + mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1); + return MV_OK; + } + if(pTestSession->macAlgorithm == MV_CESA_MAC_SHA1) + { + mvSHA1(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, pDigest); + mvOsPrintf("SW HASH_SHA1: reqSize=%d, macLength=%d\n", + cesaReqSize, pCmd->macLength); + mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1); + return MV_OK; + } + } + + cesaBeginTicks = CESA_TEST_TICK_GET(); + CESA_TEST_DEBUG_CODE( memset(cesaTestTrace, 0, sizeof(cesaTestTrace)); + cesaTestTraceIdx = 0; + ); + + if(cesaCheckMode == CESA_SW_NULL_CHECK_MODE) + { + volatile MV_U8 pDigest[MV_CESA_MAX_DIGEST_SIZE]; + + for(i=0; imacAlgorithm == MV_CESA_MAC_MD5) + { + mvMD5(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, pDigest); + } + if(pTestSession->macAlgorithm == MV_CESA_MAC_SHA1) + { + mvSHA1(pCmd->pSrc->pFrags[0].bufVirtPtr, pCmd->macLength, pDigest); + } + } + cesaEndTicks = CESA_TEST_TICK_GET(); + cesaRate = getRate(&cesaRateAfterDot); + cesaIsReady = MV_TRUE; + + return MV_OK; + } + + /*cesaTestIsrCount = 0;*/ + /*mvCesaDebugStatsClear();*/ + +#ifndef MV_NETBSD + MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0); +#endif + + for(i=0; ipReqPrv = (void*)cmdReqId; + + CESA_TEST_LOCK(flags); + + rc = mvCesaAction(pCmd); + if(rc == MV_NO_RESOURCE) + cesaTestFull = 1; + + CESA_TEST_UNLOCK(flags); + + if(rc == MV_NO_RESOURCE) + { + CESA_TEST_LOCK(flags); + CESA_TEST_WAIT( (cesaTestFull == 0), 100); + CESA_TEST_UNLOCK(flags); + if(cesaTestFull == 1) + { + mvOsPrintf("CESA Test timeout: i=%d, iter=%d, cesaTestFull=%d\n", + i, iter, cesaTestFull); + cesaTestFull = 0; + return MV_TIMEOUT; + } + + CESA_TEST_LOCK(flags); + + rc = mvCesaAction(pCmd); + + CESA_TEST_UNLOCK(flags); + } + if( (rc != MV_OK) && (rc != MV_NO_MORE) ) + { + mvOsPrintf("mvCesaAction failed: rc=%d\n", rc); + return rc; + } + + cmdReqId++; + if(cmdReqId >= CESA_DEF_REQ_SIZE) + cmdReqId = 0; + +#ifdef MV_LINUX + /* Reschedule each 16 requests */ + if( (i & 0xF) == 0) + schedule(); +#endif + } + return MV_OK; +} + +void cesaTestStart(int bufNum, int bufSize) +{ + int i, j, idx; + MV_CESA_MBUF *pMbufSrc, *pMbufDst; + MV_BUF_INFO *pFragsSrc, *pFragsDst; + char *pBuf; +#ifndef MV_NETBSD + int numOfSessions, queueDepth; + char *pSram; + MV_STATUS status; + MV_CPU_DEC_WIN addrDecWin; +#endif + + cesaCmdRing = mvOsMalloc(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE); + if(cesaCmdRing == NULL) + { + mvOsPrintf("testStart: Can't allocate %ld bytes of memory\n", + sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE); + return; + } + memset(cesaCmdRing, 0, sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE); + + if(bufNum == 0) + bufNum = CESA_DEF_BUF_NUM; + + if(bufSize == 0) + bufSize = CESA_DEF_BUF_SIZE; + + cesaBufNum = bufNum; + cesaBufSize = bufSize; + mvOsPrintf("CESA test started: bufNum = %d, bufSize = %d\n", + bufNum, bufSize); + + cesaHexBuffer = mvOsMalloc(2*bufNum*bufSize); + if(cesaHexBuffer == NULL) + { + mvOsPrintf("testStart: Can't malloc %d bytes for cesaHexBuffer.\n", + 2*bufNum*bufSize); + return; + } + memset(cesaHexBuffer, 0, (2*bufNum*bufSize)); + + cesaBinBuffer = mvOsMalloc(bufNum*bufSize); + if(cesaBinBuffer == NULL) + { + mvOsPrintf("testStart: Can't malloc %d bytes for cesaBinBuffer\n", + bufNum*bufSize); + return; + } + memset(cesaBinBuffer, 0, (bufNum*bufSize)); + + cesaExpBinBuffer = mvOsMalloc(bufNum*bufSize); + if(cesaExpBinBuffer == NULL) + { + mvOsPrintf("testStart: Can't malloc %d bytes for cesaExpBinBuffer\n", + bufNum*bufSize); + return; + } + memset(cesaExpBinBuffer, 0, (bufNum*bufSize)); + + CESA_TEST_WAIT_INIT(); + + pMbufSrc = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE); + pFragsSrc = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE); + + pMbufDst = mvOsMalloc(sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE); + pFragsDst = mvOsMalloc(sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE); + + if( (pMbufSrc == NULL) || (pFragsSrc == NULL) || + (pMbufDst == NULL) || (pFragsDst == NULL) ) + { + mvOsPrintf("testStart: Can't malloc Src and Dst pMbuf and pFrags structures.\n"); + /* !!!! Dima cesaTestCleanup();*/ + return; + } + + memset(pMbufSrc, 0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE); + memset(pFragsSrc, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE); + + memset(pMbufDst, 0, sizeof(MV_CESA_MBUF) * CESA_DEF_REQ_SIZE); + memset(pFragsDst, 0, sizeof(MV_BUF_INFO) * bufNum * CESA_DEF_REQ_SIZE); + + mvOsPrintf("Cesa Test Start: pMbufSrc=%p, pFragsSrc=%p, pMbufDst=%p, pFragsDst=%p\n", + pMbufSrc, pFragsSrc, pMbufDst, pFragsDst); + + idx = 0; + for(i=0; ipFrags = &pFragsSrc[idx]; + cesaCmdRing[i].pSrc->numFrags = bufNum; + cesaCmdRing[i].pSrc->mbufSize = 0; + + cesaCmdRing[i].pDst = &pMbufDst[i]; + cesaCmdRing[i].pDst->pFrags = &pFragsDst[idx]; + cesaCmdRing[i].pDst->numFrags = bufNum; + cesaCmdRing[i].pDst->mbufSize = 0; + + for(j=0; jpFrags[j].bufVirtPtr = (MV_U8*)pBuf; + cesaCmdRing[i].pSrc->pFrags[j].bufSize = bufSize; + pBuf += bufSize; + cesaCmdRing[i].pDst->pFrags[j].bufVirtPtr = (MV_U8*)pBuf; + cesaCmdRing[i].pDst->pFrags[j].bufSize = bufSize; + pBuf += bufSize; + } + idx += bufNum; + } + +#ifndef MV_NETBSD + if (mvCpuIfTargetWinGet(CRYPT_ENG, &addrDecWin) == MV_OK) + pSram = (char*)addrDecWin.addrWin.baseLow; + else + { + mvOsPrintf("mvCesaInit: ERR. mvCpuIfTargetWinGet failed\n"); + return; + } + +#ifdef MV_CESA_NO_SRAM + pSram = mvOsMalloc(4*1024+8); + if(pSram == NULL) + { + mvOsPrintf("CesaTest: can't allocate %d bytes for SRAM simulation\n", + 4*1024+8); + /* !!!! Dima cesaTestCleanup();*/ + return; + } + pSram = (MV_U8*)MV_ALIGN_UP((MV_U32)pSram, 8); +#endif /* MV_CESA_NO_SRAM */ + + numOfSessions = CESA_DEF_SESSION_NUM; + queueDepth = CESA_DEF_REQ_SIZE - MV_CESA_MAX_CHAN; + + status = mvCesaInit(numOfSessions, queueDepth, pSram, NULL); + if(status != MV_OK) + { + mvOsPrintf("mvCesaInit is Failed: status = 0x%x\n", status); + /* !!!! Dima cesaTestCleanup();*/ + return; + } +#endif /* !MV_NETBSD */ + + /* Prepare data for tests */ + for(i=0; i<50; i++) + strcat((char*)cesaDataHexStr3, "dd"); + + strcpy((char*)cesaDataAndMd5digest3, cesaDataHexStr3); + strcpy((char*)cesaDataAndSha1digest3, cesaDataHexStr3); + + /* Digest must be 8 byte aligned */ + for(; i<56; i++) + { + strcat((char*)cesaDataAndMd5digest3, "00"); + strcat((char*)cesaDataAndSha1digest3, "00"); + } + strcat((char*)cesaDataAndMd5digest3, cesaHmacMd5digestHex3); + strcat((char*)cesaDataAndSha1digest3, cesaHmacSha1digestHex3); + +#ifndef MV_NETBSD + MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0); + MV_REG_WRITE( MV_CESA_ISR_MASK_REG, MV_CESA_CAUSE_ACC_DMA_MASK); +#endif + +#ifdef MV_VXWORKS + { + MV_STATUS status; + + status = intConnect(INUM_TO_IVEC(INT_LVL_CESA), cesaTestReadyIsr, (int)NULL); + if (status != OK) + { + mvOsPrintf("CESA: Can't connect CESA (%d) interrupt, status=0x%x \n", + INT_LVL_CESA, status); + /* !!!! Dima cesaTestCleanup();*/ + return; + } + cesaSemId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); + if(cesaSemId == NULL) + { + mvOsPrintf("cesaTestStart: Can't create semaphore\n"); + return; + } + intEnable(INT_LVL_CESA); + } +#endif /* MV_VXWORKS */ + +#if !defined(MV_NETBSD) && defined(__KERNEL__) + if( request_irq(CESA_IRQ, cesaTestReadyIsr, (SA_INTERRUPT) , "cesa_test", NULL ) ) + { + mvOsPrintf( "cannot assign irq\n" ); + /* !!!! Dima cesaTestCleanup();*/ + return; + } + spin_lock_init( &cesaLock ); +#endif +} + +MV_STATUS testRun(int idx, int caseIdx, int iter, + int reqSize, int checkMode) +{ + int testIdx, count, sid, digestSize; + int blockSize; + MV_CESA_TEST_SESSION* pTestSession; + MV_CESA_COMMAND cmd; + MV_STATUS status; + + memset(&cmd, 0, sizeof(cmd)); + + pTestSession = getTestSessionDb(idx, &testIdx); + if(pTestSession == NULL) + { + mvOsPrintf("Test %d is not exist\n", idx); + return MV_BAD_PARAM; + } + pTestSession = &pTestSession[testIdx]; + + sid = pTestSession->sid; + if(sid == -1) + { + mvOsPrintf("Test %d is not opened\n", idx); + return MV_BAD_STATE; + } + switch(pTestSession->cryptoAlgorithm) + { + case MV_CESA_CRYPTO_DES: + case MV_CESA_CRYPTO_3DES: + blockSize = MV_CESA_DES_BLOCK_SIZE; + break; + + case MV_CESA_CRYPTO_AES: + blockSize = MV_CESA_AES_BLOCK_SIZE; + break; + + case MV_CESA_CRYPTO_NULL: + blockSize = 0; + break; + + default: + mvOsPrintf("cesaTestRun: Bad CryptoAlgorithm=%d\n", + pTestSession->cryptoAlgorithm); + return MV_BAD_PARAM; + } + switch(pTestSession->macAlgorithm) + { + case MV_CESA_MAC_MD5: + case MV_CESA_MAC_HMAC_MD5: + digestSize = MV_CESA_MD5_DIGEST_SIZE; + break; + + case MV_CESA_MAC_SHA1: + case MV_CESA_MAC_HMAC_SHA1: + digestSize = MV_CESA_SHA1_DIGEST_SIZE; + break; + default: + digestSize = 0; + } + + if(iter == 0) + iter = CESA_DEF_ITER_NUM; + + if(pTestSession->direction == MV_CESA_DIR_ENCODE) + { + cesaOutputHexStr = cesaTestCases[caseIdx].cipherHexStr; + cesaInputHexStr = cesaTestCases[caseIdx].plainHexStr; + } + else + { + cesaOutputHexStr = cesaTestCases[caseIdx].plainHexStr; + cesaInputHexStr = cesaTestCases[caseIdx].cipherHexStr; + } + + cmd.sessionId = sid; + if(checkMode == CESA_FAST_CHECK_MODE) + { + cmd.cryptoLength = cesaTestCases[caseIdx].cryptoLength; + cmd.macLength = cesaTestCases[caseIdx].macLength; + } + else + { + cmd.cryptoLength = reqSize; + cmd.macLength = reqSize; + } + cesaRateSize = cmd.cryptoLength; + cesaReqSize = cmd.cryptoLength; + cmd.cryptoOffset = 0; + if(pTestSession->operation != MV_CESA_MAC_ONLY) + { + if( (pTestSession->cryptoMode == MV_CESA_CRYPTO_CBC) || + (pTestSession->cryptoMode == MV_CESA_CRYPTO_CTR) ) + { + cmd.ivOffset = 0; + cmd.cryptoOffset = blockSize; + if(cesaTestCases[caseIdx].pCryptoIV == NULL) + { + cmd.ivFromUser = 1; + } + else + { + cmd.ivFromUser = 0; + mvCesaCryptoIvSet(cesaTestCases[caseIdx].pCryptoIV, blockSize); + } + cesaReqSize = cmd.cryptoOffset + cmd.cryptoLength; + } + } + +/* + mvOsPrintf("ivFromUser=%d, cryptoLength=%d, cesaReqSize=%d, cryptoOffset=%d\n", + cmd.ivFromUser, cmd.cryptoLength, cesaReqSize, cmd.cryptoOffset); +*/ + if(pTestSession->operation != MV_CESA_CRYPTO_ONLY) + { + cmd.macOffset = cmd.cryptoOffset; + + if(cesaTestCases[caseIdx].digestOffset == -1) + { + cmd.digestOffset = cmd.macOffset + cmd.macLength; + cmd.digestOffset = MV_ALIGN_UP(cmd.digestOffset, 8); + } + else + { + cmd.digestOffset = cesaTestCases[caseIdx].digestOffset; + } + if( (cmd.digestOffset + digestSize) > cesaReqSize) + cesaReqSize = cmd.digestOffset + digestSize; + } + + cesaCheckMode = checkMode; + + if(checkMode == CESA_NULL_CHECK_MODE) + { + cesaCheckSize = 0; + cesaCheckOffset = 0; + } + else + { + if(pTestSession->operation == MV_CESA_CRYPTO_ONLY) + { + cesaCheckOffset = 0; + cesaCheckSize = cmd.cryptoLength; + } + else + { + cesaCheckSize = digestSize; + cesaCheckOffset = cmd.digestOffset; + } + } +/* + mvOsPrintf("reqSize=%d, checkSize=%d, checkOffset=%d, checkMode=%d\n", + cesaReqSize, cesaCheckSize, cesaCheckOffset, cesaCheckMode); + + mvOsPrintf("blockSize=%d, ivOffset=%d, ivFromUser=%d, crOffset=%d, crLength=%d\n", + blockSize, cmd.ivOffset, cmd.ivFromUser, + cmd.cryptoOffset, cmd.cryptoLength); + + mvOsPrintf("macOffset=%d, digestOffset=%d, macLength=%d\n", + cmd.macOffset, cmd.digestOffset, cmd.macLength); +*/ + status = testCmd(sid, iter, &cmd, pTestSession, + cesaTestCases[caseIdx].pCryptoIV, blockSize); + + if(status != MV_OK) + return status; + + /* Wait when all callbacks is received */ + count = 0; + while(cesaIsReady == MV_FALSE) + { + mvOsSleep(10); + count++; + if(count > 100) + { + mvOsPrintf("testRun: Timeout occured\n"); + return MV_TIMEOUT; + } + } + + return MV_OK; +} + + +void cesaTestStop(void) +{ + MV_CESA_MBUF *pMbufSrc, *pMbufDst; + MV_BUF_INFO *pFragsSrc, *pFragsDst; + int i; + + /* Release all allocated memories */ + pMbufSrc = (MV_CESA_MBUF*)(cesaCmdRing[0].pSrc); + pFragsSrc = cesaCmdRing[0].pSrc->pFrags; + + pMbufDst = (MV_CESA_MBUF*)(cesaCmdRing[0].pDst); + pFragsDst = cesaCmdRing[0].pDst->pFrags; + + mvOsFree(pMbufSrc); + mvOsFree(pMbufDst); + mvOsFree(pFragsSrc); + mvOsFree(pFragsDst); + + for(i=0; i 0) + cryptoError++; + if(cesaReqIdError > 0) + reqIdError++; + + testClose(idx); + } + } + if(cryptoError > 0) + mvOsPrintf("cryptoError : %d\n", cryptoError); + if(reqIdError > 0) + mvOsPrintf("reqIdError : %d\n", reqIdError); + + if(openErrors > 0) + { + mvOsPrintf("Open Errors = %d\n", openErrors); + for(i=0; i<100; i++) + { + if(openErrDisp[i] != 0) + mvOsPrintf("Error %d - occurs %d times\n", i, openErrDisp[i]); + } + } +} + + +void loopback_test(int idx, int iter, int size, char* pPlainData) +{ +} + + +#if defined(MV_VXWORKS) +int testMode = 0; +unsigned __TASKCONV cesaTask(void* args) +{ + int reqSize = cesaReqSize; + + if(testMode == 0) + { + cesaOneTest(cesaTestIdx, cesaCaseIdx, cesaIteration, + reqSize, cesaCheckMode); + } + else + { + if(testMode == 1) + { + cesaTest(cesaIteration, reqSize, cesaCheckMode); + combiTest(cesaIteration, reqSize, cesaCheckMode); + } + else + { + multiSizeTest(cesaIdx, cesaIteration, cesaCheckMode, NULL); + } + } + return 0; +} + +void oneTest(int testIdx, int caseIdx, + int iter, int reqSize, int checkMode) +{ + long rc; + + cesaIteration = iter; + cesaReqSize = cesaRateSize = reqSize; + cesaCheckMode = checkMode; + testMode = 0; + cesaTestIdx = testIdx; + cesaCaseIdx = caseIdx; + rc = mvOsTaskCreate("CESA_T", 100, 4*1024, cesaTask, NULL, &cesaTaskId); + if (rc != MV_OK) + { + mvOsPrintf("hMW: Can't create CESA multiCmd test task, rc = %ld\n", rc); + } +} + +void multiTest(int iter, int reqSize, int checkMode) +{ + long rc; + + cesaIteration = iter; + cesaCheckMode = checkMode; + cesaReqSize = reqSize; + testMode = 1; + rc = mvOsTaskCreate("CESA_T", 100, 4*1024, cesaTask, NULL, &cesaTaskId); + if (rc != MV_OK) + { + mvOsPrintf("hMW: Can't create CESA multiCmd test task, rc = %ld\n", rc); + } +} + +void sizeTest(int testIdx, int iter, int checkMode) +{ + long rc; + + cesaIteration = iter; + cesaCheckMode = checkMode; + testMode = 2; + cesaIdx = testIdx; + rc = mvOsTaskCreate("CESA_T", 100, 4*1024, cesaTask, NULL, &cesaTaskId); + if (rc != MV_OK) + { + mvOsPrintf("hMW: Can't create CESA test task, rc = %ld\n", rc); + } +} + +#endif /* MV_VXWORKS */ + +extern void mvCesaDebugSA(short sid, int mode); +void cesaTestPrintSession(int idx) +{ + int testIdx; + MV_CESA_TEST_SESSION* pTestSession; + + pTestSession = getTestSessionDb(idx, &testIdx); + if(pTestSession == NULL) + { + mvOsPrintf("Test %d is not exist\n", idx); + return; + } + pTestSession = &pTestSession[testIdx]; + + if(pTestSession->sid == -1) + { + mvOsPrintf("Test session %d is not opened\n", idx); + return; + } + + mvCesaDebugSA(pTestSession->sid, 1); +} + +void cesaTestPrintStatus(void) +{ + mvOsPrintf("\n\t Cesa Test Status\n\n"); + + mvOsPrintf("isrCount=%d\n", + cesaTestIsrCount); + +#ifdef CESA_TEST_DEBUG + { + int i, j; + j = cesaTestTraceIdx; + mvOsPrintf("No Type Cause rCause iCause Res Time pReady pProc pEmpty\n"); + for(i=0; itable = mvOsMalloc(numOfEntries*sizeof(MV_LRU_ENTRY)); + if(pLruCache->table == NULL) + { + mvOsFree(pLruCache); + return NULL; + } + memset(pLruCache->table, 0, numOfEntries*sizeof(MV_LRU_ENTRY)); + pLruCache->tableSize = numOfEntries; + + for(i=0; itable[i].next = i+1; + pLruCache->table[i].prev = i-1; + } + pLruCache->least = 0; + pLruCache->most = numOfEntries-1; + + return pLruCache; +} + +void mvLruCacheFinish(MV_LRU_CACHE* pLruCache) +{ + mvOsFree(pLruCache->table); + mvOsFree(pLruCache); +} + +/* Update LRU cache database after using cache Index */ +void mvLruCacheIdxUpdate(MV_LRU_CACHE* pLruHndl, int cacheIdx) +{ + int prev, next; + + if(cacheIdx == pLruHndl->most) + return; + + next = pLruHndl->table[cacheIdx].next; + if(cacheIdx == pLruHndl->least) + { + pLruHndl->least = next; + } + else + { + prev = pLruHndl->table[cacheIdx].prev; + + pLruHndl->table[next].prev = prev; + pLruHndl->table[prev].next = next; + } + + pLruHndl->table[pLruHndl->most].next = cacheIdx; + pLruHndl->table[cacheIdx].prev = pLruHndl->most; + pLruHndl->most = cacheIdx; +} + +/* Delete LRU cache entry */ +void mvLruCacheIdxDelete(MV_LRU_CACHE* pLruHndl, int cacheIdx) +{ + int prev, next; + + if(cacheIdx == pLruHndl->least) + return; + + prev = pLruHndl->table[cacheIdx].prev; + if(cacheIdx == pLruHndl->most) + { + pLruHndl->most = prev; + } + else + { + next = pLruHndl->table[cacheIdx].next; + + pLruHndl->table[next].prev = prev; + pLruHndl->table[prev].next = next; + } + pLruHndl->table[pLruHndl->least].prev = cacheIdx; + pLruHndl->table[cacheIdx].next = pLruHndl->least; + pLruHndl->least = cacheIdx; +} diff --git a/board/mv_feroceon/mv_hal/cesa/mvLru.h b/board/mv_feroceon/mv_hal/cesa/mvLru.h new file mode 100644 index 0000000..896e7f8 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvLru.h @@ -0,0 +1,112 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvLru.h - Header File for Least Recently Used Cache algorithm +* +* DESCRIPTION: +* This header file contains macros typedefs and function declaration for +* the Least Recently Used Cache algorithm. +* +*******************************************************************************/ + +#ifndef __mvLru_h__ +#define __mvLru_h__ + + +typedef struct +{ + int next; + int prev; +} MV_LRU_ENTRY; + +typedef struct +{ + int least; + int most; + MV_LRU_ENTRY* table; + int tableSize; + +}MV_LRU_CACHE; + + +/* Find Cache index for replacement LRU */ +static INLINE int mvLruCacheIdxFind(MV_LRU_CACHE* pLruHndl) +{ + return pLruHndl->least; +} + +/* Init LRU cache module */ +MV_LRU_CACHE* mvLruCacheInit(int numOfEntries); + +/* Finish LRU cache module */ +void mvLruCacheFinish(MV_LRU_CACHE* pLruHndl); + +/* Update LRU cache database after using cache Index */ +void mvLruCacheIdxUpdate(MV_LRU_CACHE* pLruHndl, int cacheIdx); + +/* Delete LRU cache entry */ +void mvLruCacheIdxDelete(MV_LRU_CACHE* pLruHndl, int cacheIdx); + + +#endif /* __mvLru_h__ */ diff --git a/board/mv_feroceon/mv_hal/cesa/mvMD5.c b/board/mv_feroceon/mv_hal/cesa/mvMD5.c new file mode 100644 index 0000000..189f629 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvMD5.c @@ -0,0 +1,349 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvOs.h" +#include "mvMD5.h" + +static void mvMD5Transform(MV_U32 buf[4], MV_U32 const in[MV_MD5_MAC_LEN]); + +#ifdef MV_CPU_LE +#define mvByteReverse(buf, len) /* Nothing */ +#else +static void mvByteReverse(unsigned char *buf, unsigned longs); + +/* + * Note: this code is harmless on little-endian machines. + */ +static void mvByteReverse(unsigned char *buf, unsigned longs) +{ + MV_U32 t; + + do + { + t = (MV_U32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(MV_U32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void mvMD5Init(MV_MD5_CONTEXT *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void mvMD5Update(MV_MD5_CONTEXT *ctx, unsigned char const *buf, unsigned len) +{ + MV_U32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((MV_U32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) + { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) + { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + mvByteReverse(ctx->in, MV_MD5_MAC_LEN); + mvMD5Transform(ctx->buf, (MV_U32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) + { + memcpy(ctx->in, buf, 64); + mvByteReverse(ctx->in, MV_MD5_MAC_LEN); + mvMD5Transform(ctx->buf, (MV_U32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void mvMD5Final(unsigned char digest[MV_MD5_MAC_LEN], MV_MD5_CONTEXT *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + mvByteReverse(ctx->in, MV_MD5_MAC_LEN); + mvMD5Transform(ctx->buf, (MV_U32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } + else + { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + mvByteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((MV_U32 *) ctx->in)[14] = ctx->bits[0]; + ((MV_U32 *) ctx->in)[15] = ctx->bits[1]; + + mvMD5Transform(ctx->buf, (MV_U32 *) ctx->in); + mvByteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, MV_MD5_MAC_LEN); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void mvMD5Transform(MV_U32 buf[4], MV_U32 const in[MV_MD5_MAC_LEN]) +{ + register MV_U32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +void mvMD5(unsigned char const *buf, unsigned len, unsigned char* digest) +{ + MV_MD5_CONTEXT ctx; + + mvMD5Init(&ctx); + mvMD5Update(&ctx, buf, len); + mvMD5Final(digest, &ctx); +} + + +void mvHmacMd5(unsigned char const* text, int text_len, + unsigned char const* key, int key_len, + unsigned char* digest) +{ + int i; + MV_MD5_CONTEXT ctx; + unsigned char k_ipad[64+1]; /* inner padding - key XORd with ipad */ + unsigned char k_opad[64+1]; /* outer padding - key XORd with opad */ + + /* start out by storing key in pads */ + memset(k_ipad, 0, 64); + memcpy(k_ipad, key, key_len); + memset(k_opad, 0, 64); + memcpy(k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) + { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner MD5 */ + mvMD5Init(&ctx); /* init ctx for 1st pass */ + mvMD5Update(&ctx, k_ipad, 64); /* start with inner pad */ + mvMD5Update(&ctx, text, text_len); /* then text of datagram */ + mvMD5Final(digest, &ctx); /* finish up 1st pass */ + + /* perform outer MD5 */ + mvMD5Init(&ctx); /* init ctx for 2nd pass */ + mvMD5Update(&ctx, k_opad, 64); /* start with outer pad */ + mvMD5Update(&ctx, digest, 16); /* then results of 1st hash */ + mvMD5Final(digest, &ctx); /* finish up 2nd pass */ +} diff --git a/board/mv_feroceon/mv_hal/cesa/mvMD5.h b/board/mv_feroceon/mv_hal/cesa/mvMD5.h new file mode 100644 index 0000000..d05c6b6 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvMD5.h @@ -0,0 +1,93 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __mvMD5_h__ +#define __mvMD5_h__ + +#include "mvMD5.h" + +#define MV_MD5_MAC_LEN 16 + + +typedef struct +{ + MV_U32 buf[4]; + MV_U32 bits[2]; + MV_U8 in[64]; + +} MV_MD5_CONTEXT; + +void mvMD5Init(MV_MD5_CONTEXT *context); +void mvMD5Update(MV_MD5_CONTEXT *context, unsigned char const *buf, + unsigned len); +void mvMD5Final(unsigned char digest[16], MV_MD5_CONTEXT *context); + +void mvMD5(unsigned char const *buf, unsigned len, unsigned char* digest); + +void mvHmacMd5(unsigned char const* text, int text_len, + unsigned char const* key, int key_len, + unsigned char* digest); + + +#endif /* __mvMD5_h__ */ diff --git a/board/mv_feroceon/mv_hal/cesa/mvSHA1.c b/board/mv_feroceon/mv_hal/cesa/mvSHA1.c new file mode 100644 index 0000000..0e0786b --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvSHA1.c @@ -0,0 +1,239 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvOs.h" +#include "mvSHA1.h" + +#define SHA1HANDSOFF + +typedef union +{ + MV_U8 c[64]; + MV_U32 l[16]; + +} CHAR64LONG16; + +static void mvSHA1Transform(MV_U32 state[5], const MV_U8 *buffer); + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + + +#ifdef MV_CPU_LE +#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ + (rol(block->l[i], 8) & 0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ + block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) \ + z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R1(v,w,x,y,z,i) \ + z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R2(v,w,x,y,z,i) \ + z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); +#define R3(v,w,x,y,z,i) \ + z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ + w = rol(w, 30); +#define R4(v,w,x,y,z,i) \ + z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ + w=rol(w, 30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void mvSHA1Transform(MV_U32 state[5], const MV_U8 *buffer) +{ + MV_U32 a, b, c, d, e; + CHAR64LONG16* block; + +#ifdef SHA1HANDSOFF + static MV_U32 workspace[16]; + + block = (CHAR64LONG16 *) workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + +void mvSHA1Init(MV_SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ +void mvSHA1Update(MV_SHA1_CTX *context, MV_U8 const *data, + unsigned int len) +{ + MV_U32 i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) + context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) + { + memcpy(&context->buffer[j], data, (i = 64-j)); + mvSHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) + { + mvSHA1Transform(context->state, &data[i]); + } + j = 0; + } + else + { + i = 0; + } + memcpy(&context->buffer[j], &data[i], len - i); +} + +void mvSHA1Final(MV_U8* digest, MV_SHA1_CTX* context) +{ + MV_U32 i; + MV_U8 finalcount[8]; + + for (i = 0; i < 8; i++) + { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> + ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + mvSHA1Update(context, (const unsigned char *) "\200", 1); + while ((context->count[0] & 504) != 448) + { + mvSHA1Update(context, (const unsigned char *) "\0", 1); + } + mvSHA1Update(context, finalcount, 8); /* Should cause a mvSHA1Transform() + */ + for (i = 0; i < 20; i++) + { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + i = 0; + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(finalcount, 0, 8); + +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + mvSHA1Transform(context->state, context->buffer); +#endif +} + + +void mvSHA1(MV_U8 const *buf, unsigned int len, MV_U8* digest) +{ + MV_SHA1_CTX ctx; + + mvSHA1Init(&ctx); + mvSHA1Update(&ctx, buf, len); + mvSHA1Final(digest, &ctx); +} diff --git a/board/mv_feroceon/mv_hal/cesa/mvSHA1.h b/board/mv_feroceon/mv_hal/cesa/mvSHA1.h new file mode 100644 index 0000000..17df9fc --- /dev/null +++ b/board/mv_feroceon/mv_hal/cesa/mvSHA1.h @@ -0,0 +1,88 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __mvSHA1_h__ +#define __mvSHA1_h__ + +#include "mvSHA1.h" + +#define MV_SHA1_MAC_LEN 20 + + +typedef struct +{ + MV_U32 state[5]; + MV_U32 count[2]; + MV_U8 buffer[64]; + +} MV_SHA1_CTX; + +void mvSHA1Init(MV_SHA1_CTX *context); +void mvSHA1Update(MV_SHA1_CTX *context, MV_U8 const *buf, unsigned int len); +void mvSHA1Final(MV_U8* digest, MV_SHA1_CTX *context); + +void mvSHA1(MV_U8 const *buf, unsigned int len, MV_U8* digest); + + +#endif /* __mvSHA1_h__ */ diff --git a/board/mv_feroceon/mv_hal/cntmr/mvCntmr.c b/board/mv_feroceon/mv_hal/cntmr/mvCntmr.c new file mode 100644 index 0000000..85c0d26 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cntmr/mvCntmr.c @@ -0,0 +1,373 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvCntmr.h" + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/******************************************************************************* +* mvCntmrLoad - +* +* DESCRIPTION: +* Load an init Value to a given counter/timer +* +* INPUT: +* countNum - counter number +* value - value to be loaded +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess +*******************************************************************************/ +MV_STATUS mvCntmrLoad(MV_U32 countNum, MV_U32 value) +{ + if (countNum >= MV_CNTMR_MAX_COUNTER ) + { + + mvOsPrintf(("mvCntmrLoad: Err. Illigal counter number \n")); + return MV_BAD_PARAM;; + + } + + MV_REG_WRITE(CNTMR_RELOAD_REG(countNum),value); + MV_REG_WRITE(CNTMR_VAL_REG(countNum),value); + + return MV_OK; +} + +/******************************************************************************* +* mvCntmrRead - +* +* DESCRIPTION: +* Returns the value of the given Counter/Timer +* +* INPUT: +* countNum - counter number +* +* OUTPUT: +* None. +* +* RETURN: +* MV_U32 counter value +*******************************************************************************/ +MV_U32 mvCntmrRead(MV_U32 countNum) +{ + return MV_REG_READ(CNTMR_VAL_REG(countNum)); +} + +/******************************************************************************* +* mvCntmrWrite - +* +* DESCRIPTION: +* Returns the value of the given Counter/Timer +* +* INPUT: +* countNum - counter number +* countVal - value to write +* +* OUTPUT: +* None. +* +* RETURN: +* None +*******************************************************************************/ +void mvCntmrWrite(MV_U32 countNum,MV_U32 countVal) +{ + MV_REG_WRITE(CNTMR_VAL_REG(countNum),countVal); +} + +/******************************************************************************* +* mvCntmrCtrlSet - +* +* DESCRIPTION: +* Set the Control to a given counter/timer +* +* INPUT: +* countNum - counter number +* pCtrl - pointer to MV_CNTMR_CTRL structure +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess +*******************************************************************************/ +MV_STATUS mvCntmrCtrlSet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl) +{ + MV_U32 cntmrCtrl; + + if (countNum >= MV_CNTMR_MAX_COUNTER ) + { + + DB(mvOsPrintf(("mvCntmrCtrlSet: Err. Illigal counter number \n"))); + return MV_BAD_PARAM;; + + } + + /* read control register */ + cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG); + + + if (pCtrl->enable) /* enable counter\timer */ + { + cntmrCtrl |= CTCR_ARM_TIMER_EN(countNum); + } + else /* disable counter\timer */ + { + cntmrCtrl &= ~CTCR_ARM_TIMER_EN(countNum); + } + + if ( pCtrl->autoEnable ) /* Auto mode */ + { + cntmrCtrl |= CTCR_ARM_TIMER_AUTO_EN(countNum); + + } + else /* no auto mode */ + { + cntmrCtrl &= ~CTCR_ARM_TIMER_AUTO_EN(countNum); + } + + MV_REG_WRITE(CNTMR_CTRL_REG,cntmrCtrl); + + return MV_OK; + +} + +/******************************************************************************* +* mvCntmrCtrlGet - +* +* DESCRIPTION: +* Get the Control value of a given counter/timer +* +* INPUT: +* countNum - counter number +* pCtrl - pointer to MV_CNTMR_CTRL structure +* +* OUTPUT: +* Counter\Timer control value +* +* RETURN: +* MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess +*******************************************************************************/ +MV_STATUS mvCntmrCtrlGet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl) +{ + MV_U32 cntmrCtrl; + + if (countNum >= MV_CNTMR_MAX_COUNTER ) + { + DB(mvOsPrintf(("mvCntmrCtrlGet: Err. Illigal counter number \n"))); + return MV_BAD_PARAM;; + } + + /* read control register */ + cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG); + + /* enable counter\timer */ + if (cntmrCtrl & CTCR_ARM_TIMER_EN(countNum)) + { + pCtrl->enable = MV_TRUE; + } + else + { + pCtrl->enable = MV_FALSE; + } + + /* counter mode */ + if (cntmrCtrl & CTCR_ARM_TIMER_AUTO_EN(countNum)) + { + pCtrl->autoEnable = MV_TRUE; + } + else + { + pCtrl->autoEnable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvCntmrEnable - +* +* DESCRIPTION: +* Set the Enable-Bit to logic '1' ==> starting the counter +* +* INPUT: +* countNum - counter number +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess +*******************************************************************************/ +MV_STATUS mvCntmrEnable(MV_U32 countNum) +{ + MV_U32 cntmrCtrl; + + if (countNum >= MV_CNTMR_MAX_COUNTER ) + { + + DB(mvOsPrintf(("mvCntmrEnable: Err. Illigal counter number \n"))); + return MV_BAD_PARAM;; + + } + + /* read control register */ + cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG); + + /* enable counter\timer */ + cntmrCtrl |= CTCR_ARM_TIMER_EN(countNum); + + + MV_REG_WRITE(CNTMR_CTRL_REG,cntmrCtrl); + + return MV_OK; +} + +/******************************************************************************* +* mvCntmrDisable - +* +* DESCRIPTION: +* Stop the counter/timer running, and returns its Value +* +* INPUT: +* countNum - counter number +* +* OUTPUT: +* None. +* +* RETURN: +* MV_U32 counter\timer value +*******************************************************************************/ +MV_STATUS mvCntmrDisable(MV_U32 countNum) +{ + MV_U32 cntmrCtrl; + + if (countNum >= MV_CNTMR_MAX_COUNTER ) + { + + DB(mvOsPrintf(("mvCntmrDisable: Err. Illigal counter number \n"))); + return MV_BAD_PARAM;; + + } + + /* read control register */ + cntmrCtrl = MV_REG_READ(CNTMR_CTRL_REG); + + /* disable counter\timer */ + cntmrCtrl &= ~CTCR_ARM_TIMER_EN(countNum); + + MV_REG_WRITE(CNTMR_CTRL_REG,cntmrCtrl); + + return MV_OK; +} + +/******************************************************************************* +* mvCntmrStart - +* +* DESCRIPTION: +* Combined all the sub-operations above to one function: Load,setMode,Enable +* +* INPUT: +* countNum - counter number +* value - value of the counter\timer to be set +* pCtrl - pointer to MV_CNTMR_CTRL structure +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM on bad parameters , MV_ERROR on error ,MV_OK on sucess +*******************************************************************************/ +MV_STATUS mvCntmrStart(MV_U32 countNum, MV_U32 value, + MV_CNTMR_CTRL *pCtrl) +{ + + if (countNum >= MV_CNTMR_MAX_COUNTER ) + { + + mvOsPrintf(("mvCntmrDisable: Err. Illigal counter number \n")); + return MV_BAD_PARAM;; + + } + + /* load value onto counter\timer */ + mvCntmrLoad(countNum,value); + + /* set the counter to load in the first time */ + mvCntmrWrite(countNum,value); + + /* set control for timer \ cunter and enable */ + mvCntmrCtrlSet(countNum,pCtrl); + + return MV_OK; +} + diff --git a/board/mv_feroceon/mv_hal/cntmr/mvCntmr.h b/board/mv_feroceon/mv_hal/cntmr/mvCntmr.h new file mode 100644 index 0000000..b911d0f --- /dev/null +++ b/board/mv_feroceon/mv_hal/cntmr/mvCntmr.h @@ -0,0 +1,121 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvTmrWtdgh +#define __INCmvTmrWtdgh + +/* includes */ +#include "mvCommon.h" +#include "mvOs.h" +#include "cntmr/mvCntmrRegs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + + +/* This enumerator describe counters\watchdog numbers */ +typedef enum _mvCntmrID +{ + TIMER0 = 0, + TIMER1, + WATCHDOG, + TIMER2, + TIMER3, +}MV_CNTMR_ID; + + +/* Counter / Timer control structure */ +typedef struct _mvCntmrCtrl +{ + MV_BOOL enable; /* enable */ + MV_BOOL autoEnable; /* counter/Timer */ +}MV_CNTMR_CTRL; + + +/* Functions */ + +/* Load an init Value to a given counter/timer */ +MV_STATUS mvCntmrLoad(MV_U32 countNum, MV_U32 value); + +/* Returns the value of the given Counter/Timer */ +MV_U32 mvCntmrRead(MV_U32 countNum); + +/* Write a value of the given Counter/Timer */ +void mvCntmrWrite(MV_U32 countNum,MV_U32 countVal); + +/* Set the Control to a given counter/timer */ +MV_STATUS mvCntmrCtrlSet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl); + +/* Get the value of a given counter/timer */ +MV_STATUS mvCntmrCtrlGet(MV_U32 countNum, MV_CNTMR_CTRL *pCtrl); + +/* Set the Enable-Bit to logic '1' ==> starting the counter. */ +MV_STATUS mvCntmrEnable(MV_U32 countNum); + +/* Stop the counter/timer running, and returns its Value. */ +MV_STATUS mvCntmrDisable(MV_U32 countNum); + +/* Combined all the sub-operations above to one function: Load,setMode,Enable */ +MV_STATUS mvCntmrStart(MV_U32 countNum, MV_U32 value, + MV_CNTMR_CTRL *pCtrl); + +#endif /* __INCmvTmrWtdgh */ diff --git a/board/mv_feroceon/mv_hal/cntmr/mvCntmrRegs.h b/board/mv_feroceon/mv_hal/cntmr/mvCntmrRegs.h new file mode 100644 index 0000000..7a0a902 --- /dev/null +++ b/board/mv_feroceon/mv_hal/cntmr/mvCntmrRegs.h @@ -0,0 +1,119 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvTmrwtdgRegsh +#define __INCmvTmrwtdgRegsh + +/*******************************************/ +/* ARM Timers Registers Map */ +/*******************************************/ + +#define CNTMR_RELOAD_REG(tmrNum) (CNTMR_BASE + 0x10 + (tmrNum)*8) +#define CNTMR_VAL_REG(tmrNum) (CNTMR_BASE + 0x14 + (tmrNum)*8) +#define CNTMR_CTRL_REG (CNTMR_BASE) + +/*For MV78XX0*/ +#define CNTMR_CAUSE_REG (CPU_AHB_MBUS_CAUSE_INT_REG(0)) +#define CNTMR_MASK_REG (CPU_AHB_MBUS_MASK_INT_REG(0)) + +/* ARM Timers Registers Map */ +/*******************************************/ + + +/* ARM Timers Control Register */ +/* CPU_TIMERS_CTRL_REG (CTCR) */ + +#define TIMER0_NUM 0 +#define TIMER1_NUM 1 +#define WATCHDOG_NUM 2 +#define TIMER2_NUM 3 +#define TIMER3_NUM 4 + +#define CTCR_ARM_TIMER_EN_OFFS(cntr) (cntr * 2) +#define CTCR_ARM_TIMER_EN_MASK(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS) +#define CTCR_ARM_TIMER_EN(cntr) (1 << CTCR_ARM_TIMER_EN_OFFS(cntr)) +#define CTCR_ARM_TIMER_DIS(cntr) (0 << CTCR_ARM_TIMER_EN_OFFS(cntr)) + +#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1) +#define CTCR_ARM_TIMER_AUTO_MASK(cntr) BIT1 +#define CTCR_ARM_TIMER_AUTO_EN(cntr) (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) +#define CTCR_ARM_TIMER_AUTO_DIS(cntr) (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr)) + + +/* ARM Timer\Watchdog Reload Register */ +/* CNTMR_RELOAD_REG (TRR) */ + +#define TRG_ARM_TIMER_REL_OFFS 0 +#define TRG_ARM_TIMER_REL_MASK 0xffffffff + +/* ARM Timer\Watchdog Register */ +/* CNTMR_VAL_REG (TVRG) */ + +#define TVR_ARM_TIMER_OFFS 0 +#define TVR_ARM_TIMER_MASK 0xffffffff +#define TVR_ARM_TIMER_MAX 0xffffffff + + + +#endif /* __INCmvTmrwtdgRegsh */ diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDram.c b/board/mv_feroceon/mv_hal/ddr1_2/mvDram.c new file mode 100644 index 0000000..6572510 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDram.c @@ -0,0 +1,1476 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "ddr1_2/mvDram.h" +#include "boardEnv/mvBoardEnvLib.h" + +#undef MV_DEBUG +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +static MV_VOID cpyDimm2BankInfo(MV_DIMM_INFO *pDimmInfo, + MV_DRAM_BANK_INFO *pBankInfo); +static MV_U32 cas2ps(MV_U8 spd_byte); +/******************************************************************************* +* mvDramBankGet - Get the DRAM bank paramters. +* +* DESCRIPTION: +* This function retrieves DRAM bank parameters as described in +* DRAM_BANK_INFO struct to the controller DRAM unit. In case the board +* has its DRAM on DIMMs it will use its EEPROM to extract SPD data +* from it. Otherwise, if the DRAM is soldered on board, the function +* should insert its bank information into MV_DRAM_BANK_INFO struct. +* +* INPUT: +* bankNum - Board DRAM bank number. +* +* OUTPUT: +* pBankInfo - DRAM bank information struct. +* +* RETURN: +* MV_FAIL - Bank parameters could not be read. +* +*******************************************************************************/ +MV_STATUS mvDramBankInfoGet(MV_U32 bankNum, MV_DRAM_BANK_INFO *pBankInfo) +{ + MV_DIMM_INFO dimmInfo; + + DB(mvOsPrintf("Dram: mvDramBankInfoGet bank %d\n", bankNum)); + /* zero pBankInfo structure */ + memset(pBankInfo, 0, sizeof(*pBankInfo)); + + if((NULL == pBankInfo) || (bankNum >= MV_DRAM_MAX_CS )) + { + DB(mvOsPrintf("Dram: mvDramBankInfoGet bad params \n")); + return MV_BAD_PARAM; + } + if( MV_OK != dimmSpdGet((MV_U32)(bankNum/2), &dimmInfo)) + { + DB(mvOsPrintf("Dram: ERR dimmSpdGet failed to get dimm info \n")); + return MV_FAIL; + } + if((dimmInfo.numOfModuleBanks == 1) && ((bankNum % 2) == 1)) + { + DB(mvOsPrintf("Dram: ERR dimmSpdGet. Can't find DIMM bank 2 \n")); + return MV_FAIL; + } + + /* convert Dimm info to Bank info */ + cpyDimm2BankInfo(&dimmInfo, pBankInfo); + + return MV_OK; +} + +/******************************************************************************* +* cpyDimm2BankInfo - Convert a Dimm info struct into a bank info struct. +* +* DESCRIPTION: +* Convert a Dimm info struct into a bank info struct. +* +* INPUT: +* pDimmInfo - DIMM information structure. +* +* OUTPUT: +* pBankInfo - DRAM bank information struct. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID cpyDimm2BankInfo(MV_DIMM_INFO *pDimmInfo, + MV_DRAM_BANK_INFO *pBankInfo) +{ + pBankInfo->memoryType = pDimmInfo->memoryType; + + /* DIMM dimensions */ + pBankInfo->numOfRowAddr = pDimmInfo->numOfRowAddr; + pBankInfo->numOfColAddr = pDimmInfo->numOfColAddr; + pBankInfo->dataWidth = pDimmInfo->dataWidth; + pBankInfo->errorCheckType = pDimmInfo->errorCheckType; + pBankInfo->sdramWidth = pDimmInfo->sdramWidth; + pBankInfo->errorCheckDataWidth = pDimmInfo->errorCheckDataWidth; + pBankInfo->numOfBanksOnEachDevice = pDimmInfo->numOfBanksOnEachDevice; + pBankInfo->suportedCasLatencies = pDimmInfo->suportedCasLatencies; + pBankInfo->refreshInterval = pDimmInfo->refreshInterval; + + /* DIMM timing parameters */ + pBankInfo->minCycleTimeAtMaxCasLatPs = pDimmInfo->minCycleTimeAtMaxCasLatPs; + pBankInfo->minCycleTimeAtMaxCasLatMinus1Ps = + pDimmInfo->minCycleTimeAtMaxCasLatMinus1Ps; + pBankInfo->minCycleTimeAtMaxCasLatMinus2Ps = + pDimmInfo->minCycleTimeAtMaxCasLatMinus2Ps; + + pBankInfo->minRowPrechargeTime = pDimmInfo->minRowPrechargeTime; + pBankInfo->minRowActiveToRowActive = pDimmInfo->minRowActiveToRowActive; + pBankInfo->minRasToCasDelay = pDimmInfo->minRasToCasDelay; + pBankInfo->minRasPulseWidth = pDimmInfo->minRasPulseWidth; + pBankInfo->minWriteRecoveryTime = pDimmInfo->minWriteRecoveryTime; + pBankInfo->minWriteToReadCmdDelay = pDimmInfo->minWriteToReadCmdDelay; + pBankInfo->minReadToPrechCmdDelay = pDimmInfo->minReadToPrechCmdDelay; + pBankInfo->minRefreshToActiveCmd = pDimmInfo->minRefreshToActiveCmd; + + /* Parameters calculated from the extracted DIMM information */ + pBankInfo->size = pDimmInfo->size/pDimmInfo->numOfModuleBanks; + pBankInfo->deviceDensity = pDimmInfo->deviceDensity; + pBankInfo->numberOfDevices = pDimmInfo->numberOfDevices / + pDimmInfo->numOfModuleBanks; + + /* DIMM attributes (MV_TRUE for yes) */ + + if ((pDimmInfo->memoryType == MEM_TYPE_SDRAM) || + (pDimmInfo->memoryType == MEM_TYPE_DDR1) ) + { + if (pDimmInfo->dimmAttributes & BIT1) + pBankInfo->registeredAddrAndControlInputs = MV_TRUE; + else + pBankInfo->registeredAddrAndControlInputs = MV_FALSE; + } + else /* pDimmInfo->memoryType == MEM_TYPE_DDR2 */ + { + if (pDimmInfo->dimmTypeInfo & (BIT0 | BIT4)) + pBankInfo->registeredAddrAndControlInputs = MV_TRUE; + else + pBankInfo->registeredAddrAndControlInputs = MV_FALSE; + } + + return; +} + +/******************************************************************************* +* dimmSpdCpy - Cpy SPD parameters from dimm 0 to dimm 1. +* +* DESCRIPTION: +* Read the DIMM SPD parameters from dimm 0 into dimm 1 SPD. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if function could read DIMM parameters, MV_FALSE otherwise. +* +*******************************************************************************/ +MV_STATUS dimmSpdCpy(MV_VOID) +{ + MV_U32 i; + MV_U32 spdChecksum; + + MV_TWSI_SLAVE twsiSlave; + MV_U8 data[SPD_SIZE]; + + /* zero dimmInfo structure */ + memset(data, 0, SPD_SIZE); + + /* read the dimm eeprom */ + DB(mvOsPrintf("DRAM: Read Dimm eeprom\n")); + twsiSlave.slaveAddr.address = MV_BOARD_DIMM0_I2C_ADDR; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_FALSE; + + if( MV_OK != mvTwsiRead (&twsiSlave, data, SPD_SIZE) ) + { + DB(mvOsPrintf("DRAM: ERR. no DIMM in dimmNum 0\n")); + return MV_FAIL; + } + DB(puts("DRAM: Reading dimm info succeded.\n")); + + /* calculate SPD checksum */ + spdChecksum = 0; + + for(i = 0 ; i <= 62 ; i++) + { + spdChecksum += data[i]; + } + + if ((spdChecksum & 0xff) != data[63]) + { + DB(mvOsPrintf("DRAM: Warning. Wrong SPD Checksum %2x, expValue=%2x\n", + (MV_U32)(spdChecksum & 0xff), data[63])); + } + else + { + DB(mvOsPrintf("DRAM: SPD Checksum ok!\n")); + } + + /* copy the SPD content 1:1 into the DIMM 1 SPD */ + twsiSlave.slaveAddr.address = MV_BOARD_DIMM1_I2C_ADDR; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_FALSE; + + for(i = 0 ; i < SPD_SIZE ; i++) + { + twsiSlave.offset = i; + if( MV_OK != mvTwsiWrite (&twsiSlave, &data[i], 1) ) + { + mvOsPrintf("DRAM: ERR. no DIMM in dimmNum 1 byte %d \n",i); + return MV_FAIL; + } + mvOsDelay(5); + } + + DB(puts("DRAM: Reading dimm info succeded.\n")); + return MV_OK; +} + +/******************************************************************************* +* dimmSpdGet - Get the SPD parameters. +* +* DESCRIPTION: +* Read the DIMM SPD parameters into given struct parameter. +* +* INPUT: +* dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator. +* +* OUTPUT: +* pDimmInfo - DIMM information structure. +* +* RETURN: +* MV_TRUE if function could read DIMM parameters, MV_FALSE otherwise. +* +*******************************************************************************/ +MV_STATUS dimmSpdGet(MV_U32 dimmNum, MV_DIMM_INFO *pDimmInfo) +{ + MV_U32 i; + MV_U32 density = 1; + MV_U32 spdChecksum; + + MV_TWSI_SLAVE twsiSlave; + MV_U8 data[SPD_SIZE]; + + if((NULL == pDimmInfo)|| (dimmNum >= MAX_DIMM_NUM)) + { + DB(mvOsPrintf("Dram: mvDramBankInfoGet bad params \n")); + return MV_BAD_PARAM; + } + + /* zero dimmInfo structure */ + memset(data, 0, SPD_SIZE); + + /* read the dimm eeprom */ + DB(mvOsPrintf("DRAM: Read Dimm eeprom\n")); + twsiSlave.slaveAddr.address = (dimmNum == 0) ? + MV_BOARD_DIMM0_I2C_ADDR : MV_BOARD_DIMM1_I2C_ADDR; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_FALSE; + + if( MV_OK != mvTwsiRead (&twsiSlave, data, SPD_SIZE) ) + { + DB(mvOsPrintf("DRAM: ERR. no DIMM in dimmNum %d \n", dimmNum)); + return MV_FAIL; + } + DB(puts("DRAM: Reading dimm info succeded.\n")); + + /* calculate SPD checksum */ + spdChecksum = 0; + + for(i = 0 ; i <= 62 ; i++) + { + spdChecksum += data[i]; + } + + if ((spdChecksum & 0xff) != data[63]) + { + DB(mvOsPrintf("DRAM: Warning. Wrong SPD Checksum %2x, expValue=%2x\n", + (MV_U32)(spdChecksum & 0xff), data[63])); + } + else + { + DB(mvOsPrintf("DRAM: SPD Checksum ok!\n")); + } + + /* copy the SPD content 1:1 into the dimmInfo structure*/ + for(i = 0 ; i < SPD_SIZE ; i++) + { + pDimmInfo->spdRawData[i] = data[i]; + DB(mvOsPrintf("SPD-EEPROM Byte %3d = %3x (%3d)\n",i, data[i], data[i])); + } + + DB(mvOsPrintf("DRAM SPD Information:\n")); + + /* Memory type (DDR / SDRAM) */ + switch (data[DIMM_MEM_TYPE]) + { + case (DIMM_MEM_TYPE_SDRAM): + pDimmInfo->memoryType = MEM_TYPE_SDRAM; + DB(mvOsPrintf("DRAM Memeory type SDRAM\n")); + break; + case (DIMM_MEM_TYPE_DDR1): + pDimmInfo->memoryType = MEM_TYPE_DDR1; + DB(mvOsPrintf("DRAM Memeory type DDR1\n")); + break; + case (DIMM_MEM_TYPE_DDR2): + pDimmInfo->memoryType = MEM_TYPE_DDR2; + DB(mvOsPrintf("DRAM Memeory type DDR2\n")); + break; + default: + mvOsPrintf("ERROR: Undefined memory type!\n"); + return MV_ERROR; + } + + + /* Number Of Row Addresses */ + pDimmInfo->numOfRowAddr = data[DIMM_ROW_NUM]; + DB(mvOsPrintf("DRAM numOfRowAddr[3] %d\n",pDimmInfo->numOfRowAddr)); + + /* Number Of Column Addresses */ + pDimmInfo->numOfColAddr = data[DIMM_COL_NUM]; + DB(mvOsPrintf("DRAM numOfColAddr[4] %d\n",pDimmInfo->numOfColAddr)); + + /* Number Of Module Banks */ + pDimmInfo->numOfModuleBanks = data[DIMM_MODULE_BANK_NUM]; + DB(mvOsPrintf("DRAM numOfModuleBanks[5] 0x%x\n", + pDimmInfo->numOfModuleBanks)); + + /* Number of module banks encoded differently for DDR2 */ + if (pDimmInfo->memoryType == MEM_TYPE_DDR2) + pDimmInfo->numOfModuleBanks = (pDimmInfo->numOfModuleBanks & 0x7)+1; + + /* Data Width */ + pDimmInfo->dataWidth = data[DIMM_DATA_WIDTH]; + DB(mvOsPrintf("DRAM dataWidth[6] 0x%x\n", pDimmInfo->dataWidth)); + + /* Minimum Cycle Time At Max CasLatancy */ + pDimmInfo->minCycleTimeAtMaxCasLatPs = cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS]); + + /* Error Check Type */ + pDimmInfo->errorCheckType = data[DIMM_ERR_CHECK_TYPE]; + DB(mvOsPrintf("DRAM errorCheckType[11] 0x%x\n", + pDimmInfo->errorCheckType)); + + /* Refresh Interval */ + pDimmInfo->refreshInterval = data[DIMM_REFRESH_INTERVAL]; + DB(mvOsPrintf("DRAM refreshInterval[12] 0x%x\n", + pDimmInfo->refreshInterval)); + + /* Sdram Width */ + pDimmInfo->sdramWidth = data[DIMM_SDRAM_WIDTH]; + DB(mvOsPrintf("DRAM sdramWidth[13] 0x%x\n",pDimmInfo->sdramWidth)); + + /* Error Check Data Width */ + pDimmInfo->errorCheckDataWidth = data[DIMM_ERR_CHECK_DATA_WIDTH]; + DB(mvOsPrintf("DRAM errorCheckDataWidth[14] 0x%x\n", + pDimmInfo->errorCheckDataWidth)); + + /* Burst Length Supported */ + /* SDRAM/DDR1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | 2 | 1 * + *********************************************************/ + /* DDR2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | TBD | TBD * + *********************************************************/ + + pDimmInfo->burstLengthSupported = data[DIMM_BURST_LEN_SUP]; + DB(mvOsPrintf("DRAM burstLengthSupported[16] 0x%x\n", + pDimmInfo->burstLengthSupported)); + + /* Number Of Banks On Each Device */ + pDimmInfo->numOfBanksOnEachDevice = data[DIMM_DEV_BANK_NUM]; + DB(mvOsPrintf("DRAM numOfBanksOnEachDevice[17] 0x%x\n", + pDimmInfo->numOfBanksOnEachDevice)); + + /* Suported Cas Latencies */ + + /* SDRAM: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 7 | 6 | 5 | 4 | 3 | 2 | 1 * + ********************************************************/ + + /* DDR 1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 4 | 3.5 | 3 | 2.5 | 2 | 1.5 | 1 * + *********************************************************/ + + /* DDR 2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 5 | 4 | 3 | 2 | TBD | TBD * + *********************************************************/ + + pDimmInfo->suportedCasLatencies = data[DIMM_SUP_CAL]; + DB(mvOsPrintf("DRAM suportedCasLatencies[18] 0x%x\n", + pDimmInfo->suportedCasLatencies)); + + /* For DDR2 only, get the DIMM type information */ + if (pDimmInfo->memoryType == MEM_TYPE_DDR2) + { + pDimmInfo->dimmTypeInfo = data[DIMM_DDR2_TYPE_INFORMATION]; + DB(mvOsPrintf("DRAM dimmTypeInfo[20] (DDR2) 0x%x\n", + pDimmInfo->dimmTypeInfo)); + } + + /* SDRAM Modules Attributes */ + pDimmInfo->dimmAttributes = data[DIMM_BUF_ADDR_CONT_IN]; + DB(mvOsPrintf("DRAM dimmAttributes[21] 0x%x\n", + pDimmInfo->dimmAttributes)); + + /* Minimum Cycle Time At Max CasLatancy Minus 1*/ + pDimmInfo->minCycleTimeAtMaxCasLatMinus1Ps = + cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS_MINUS1]); + + /* Minimum Cycle Time At Max CasLatancy Minus 2*/ + pDimmInfo->minCycleTimeAtMaxCasLatMinus2Ps = + cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS_MINUS2]); + + pDimmInfo->minRowPrechargeTime = data[DIMM_MIN_ROW_PRECHARGE_TIME]; + DB(mvOsPrintf("DRAM minRowPrechargeTime[27] 0x%x\n", + pDimmInfo->minRowPrechargeTime)); + pDimmInfo->minRowActiveToRowActive = data[DIMM_MIN_ROW_ACTIVE_TO_ROW_ACTIVE]; + DB(mvOsPrintf("DRAM minRowActiveToRowActive[28] 0x%x\n", + pDimmInfo->minRowActiveToRowActive)); + pDimmInfo->minRasToCasDelay = data[DIMM_MIN_RAS_TO_CAS_DELAY]; + DB(mvOsPrintf("DRAM minRasToCasDelay[29] 0x%x\n", + pDimmInfo->minRasToCasDelay)); + pDimmInfo->minRasPulseWidth = data[DIMM_MIN_RAS_PULSE_WIDTH]; + DB(mvOsPrintf("DRAM minRasPulseWidth[30] 0x%x\n", + pDimmInfo->minRasPulseWidth)); + + /* DIMM Bank Density */ + pDimmInfo->dimmBankDensity = data[DIMM_BANK_DENSITY]; + DB(mvOsPrintf("DRAM dimmBankDensity[31] 0x%x\n", + pDimmInfo->dimmBankDensity)); + + /* Only DDR2 includes Write Recovery Time field. Other SDRAM ignore */ + pDimmInfo->minWriteRecoveryTime = data[DIMM_MIN_WRITE_RECOVERY_TIME]; + DB(mvOsPrintf("DRAM minWriteRecoveryTime[36] 0x%x\n", + pDimmInfo->minWriteRecoveryTime)); + + /* Only DDR2 includes Internal Write To Read Command Delay field. */ + pDimmInfo->minWriteToReadCmdDelay = data[DIMM_MIN_WRITE_TO_READ_CMD_DELAY]; + DB(mvOsPrintf("DRAM minWriteToReadCmdDelay[37] 0x%x\n", + pDimmInfo->minWriteToReadCmdDelay)); + + /* Only DDR2 includes Internal Read To Precharge Command Delay field. */ + pDimmInfo->minReadToPrechCmdDelay = data[DIMM_MIN_READ_TO_PRECH_CMD_DELAY]; + DB(mvOsPrintf("DRAM minReadToPrechCmdDelay[38] 0x%x\n", + pDimmInfo->minReadToPrechCmdDelay)); + + /* Only DDR2 includes Minimum Refresh to Activate/Refresh Command field */ + pDimmInfo->minRefreshToActiveCmd = data[DIMM_MIN_REFRESH_TO_ACTIVATE_CMD]; + DB(mvOsPrintf("DRAM minRefreshToActiveCmd[42] 0x%x\n", + pDimmInfo->minRefreshToActiveCmd)); + + /* calculating the sdram density. Representing device density from */ + /* bit 20 to allow representation of 4GB and above. */ + /* For example, if density is 512Mbit 0x20000000, will be represent in */ + /* deviceDensity by 0x20000000 >> 16 --> 0x00000200. Another example */ + /* is density 8GB 0x200000000 >> 16 --> 0x00002000. */ + density = (1 << ((pDimmInfo->numOfRowAddr + pDimmInfo->numOfColAddr) - 20)); + pDimmInfo->deviceDensity = density * + pDimmInfo->numOfBanksOnEachDevice * + pDimmInfo->sdramWidth; + DB(mvOsPrintf("DRAM deviceDensity %d\n",pDimmInfo->deviceDensity)); + + /* Number of devices includeing Error correction */ + pDimmInfo->numberOfDevices = (pDimmInfo->dataWidth/pDimmInfo->sdramWidth) * + pDimmInfo->numOfModuleBanks; + DB(mvOsPrintf("DRAM numberOfDevices %d\n", + pDimmInfo->numberOfDevices)); + + pDimmInfo->size = 0; + + /* Note that pDimmInfo->size is in MB units */ + if (pDimmInfo->memoryType == MEM_TYPE_SDRAM) + { + if (pDimmInfo->dimmBankDensity & BIT0) + pDimmInfo->size += 1024; /* Equal to 1GB */ + else if (pDimmInfo->dimmBankDensity & BIT1) + pDimmInfo->size += 8; /* Equal to 8MB */ + else if (pDimmInfo->dimmBankDensity & BIT2) + pDimmInfo->size += 16; /* Equal to 16MB */ + else if (pDimmInfo->dimmBankDensity & BIT3) + pDimmInfo->size += 32; /* Equal to 32MB */ + else if (pDimmInfo->dimmBankDensity & BIT4) + pDimmInfo->size += 64; /* Equal to 64MB */ + else if (pDimmInfo->dimmBankDensity & BIT5) + pDimmInfo->size += 128; /* Equal to 128MB */ + else if (pDimmInfo->dimmBankDensity & BIT6) + pDimmInfo->size += 256; /* Equal to 256MB */ + else if (pDimmInfo->dimmBankDensity & BIT7) + pDimmInfo->size += 512; /* Equal to 512MB */ + } + else if (pDimmInfo->memoryType == MEM_TYPE_DDR1) + { + if (pDimmInfo->dimmBankDensity & BIT0) + pDimmInfo->size += 1024; /* Equal to 1GB */ + else if (pDimmInfo->dimmBankDensity & BIT1) + pDimmInfo->size += 2048; /* Equal to 2GB */ + else if (pDimmInfo->dimmBankDensity & BIT2) + pDimmInfo->size += 16; /* Equal to 16MB */ + else if (pDimmInfo->dimmBankDensity & BIT3) + pDimmInfo->size += 32; /* Equal to 32MB */ + else if (pDimmInfo->dimmBankDensity & BIT4) + pDimmInfo->size += 64; /* Equal to 64MB */ + else if (pDimmInfo->dimmBankDensity & BIT5) + pDimmInfo->size += 128; /* Equal to 128MB */ + else if (pDimmInfo->dimmBankDensity & BIT6) + pDimmInfo->size += 256; /* Equal to 256MB */ + else if (pDimmInfo->dimmBankDensity & BIT7) + pDimmInfo->size += 512; /* Equal to 512MB */ + } + else /* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */ + { + if (pDimmInfo->dimmBankDensity & BIT0) + pDimmInfo->size += 1024; /* Equal to 1GB */ + else if (pDimmInfo->dimmBankDensity & BIT1) + pDimmInfo->size += 2048; /* Equal to 2GB */ + else if (pDimmInfo->dimmBankDensity & BIT2) + pDimmInfo->size += 4096; /* Equal to 4GB */ + else if (pDimmInfo->dimmBankDensity & BIT3) + pDimmInfo->size += 8192; /* Equal to 8GB */ + else if (pDimmInfo->dimmBankDensity & BIT4) + pDimmInfo->size += 16384; /* Equal to 16GB */ + else if (pDimmInfo->dimmBankDensity & BIT5) + pDimmInfo->size += 128; /* Equal to 128MB */ + else if (pDimmInfo->dimmBankDensity & BIT6) + pDimmInfo->size += 256; /* Equal to 256MB */ + else if (pDimmInfo->dimmBankDensity & BIT7) + pDimmInfo->size += 512; /* Equal to 512MB */ + } + + pDimmInfo->size *= pDimmInfo->numOfModuleBanks; + + DB(mvOsPrintf("Dram: dimm size %dMB \n",pDimmInfo->size)); + + return MV_OK; +} + +/******************************************************************************* +* dimmSpdPrint - Print the SPD parameters. +* +* DESCRIPTION: +* Print the Dimm SPD parameters. +* +* INPUT: +* pDimmInfo - DIMM information structure. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID dimmSpdPrint(MV_U32 dimmNum) +{ + MV_DIMM_INFO dimmInfo; + MV_U32 i, temp = 0; + MV_U32 k, maskLeftOfPoint = 0, maskRightOfPoint = 0; + MV_U32 rightOfPoint = 0,leftOfPoint = 0, div, time_tmp, shift; + MV_U32 busClkPs; + MV_U8 trp_clocks=0, trcd_clocks, tras_clocks, trrd_clocks, + temp_buf[40], *spdRawData; + + busClkPs = 1000000000 / (mvBoardSysClkGet() / 100); /* in 10 ps units */ + + spdRawData = dimmInfo.spdRawData; + + if(MV_OK != dimmSpdGet(dimmNum, &dimmInfo)) + { + mvOsOutput("ERROR: Could not read SPD information!\n"); + return; + } + + /* find Manufactura of Dimm Module */ + mvOsOutput("\nManufacturer's JEDEC ID Code: "); + for(i = 0 ; i < DIMM_MODULE_MANU_SIZE ; i++) + { + mvOsOutput("%x",spdRawData[DIMM_MODULE_MANU_OFFS + i]); + } + mvOsOutput("\n"); + + /* Manufacturer's Specific Data */ + for(i = 0 ; i < DIMM_MODULE_ID_SIZE ; i++) + { + temp_buf[i] = spdRawData[DIMM_MODULE_ID_OFFS + i]; + } + mvOsOutput("Manufacturer's Specific Data: %s\n", temp_buf); + + /* Module Part Number */ + for(i = 0 ; i < DIMM_MODULE_VEN_SIZE ; i++) + { + temp_buf[i] = spdRawData[DIMM_MODULE_VEN_OFFS + i]; + } + mvOsOutput("Module Part Number: %s\n", temp_buf); + + /* Module Serial Number */ + for(i = 0; i < sizeof(MV_U32); i++) + { + temp |= spdRawData[95+i] << 8*i; + } + mvOsOutput("DIMM Serial No. %ld (%lx)\n", (long)temp, + (long)temp); + + /* find Manufac-Data of Dimm Module */ + mvOsOutput("Manufactoring Date: Year 20%d%d/ ww %d%d\n", + ((spdRawData[93] & 0xf0) >> 4), (spdRawData[93] & 0xf), + ((spdRawData[94] & 0xf0) >> 4), (spdRawData[94] & 0xf)); + /* find modul_revision of Dimm Module */ + mvOsOutput("Module Revision: %d.%d\n", + spdRawData[91], spdRawData[92]); + + /* find manufac_place of Dimm Module */ + mvOsOutput("manufac_place: %d\n", spdRawData[72]); + + /* go over the first 35 I2C data bytes */ + for(i = 2 ; i <= 35 ; i++) + switch(i) + { + case 2: /* Memory type (DDR1/2 / SDRAM) */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + mvOsOutput("Dram Type is: SDRAM\n"); + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + mvOsOutput("Dram Type is: SDRAM DDR1\n"); + else if (dimmInfo.memoryType == MEM_TYPE_DDR2) + mvOsOutput("Dram Type is: SDRAM DDR2\n"); + else + mvOsOutput("Dram Type unknown\n"); + break; +/*----------------------------------------------------------------------------*/ + + case 3: /* Number Of Row Addresses */ + mvOsOutput("Module Number of row addresses: %d\n", + dimmInfo.numOfRowAddr); + break; +/*----------------------------------------------------------------------------*/ + + case 4: /* Number Of Column Addresses */ + mvOsOutput("Module Number of col addresses: %d\n", + dimmInfo.numOfColAddr); + break; +/*----------------------------------------------------------------------------*/ + + case 5: /* Number Of Module Banks */ + mvOsOutput("Number of Banks on Mod.: %d\n", + dimmInfo.numOfModuleBanks); + break; +/*----------------------------------------------------------------------------*/ + + case 6: /* Data Width */ + mvOsOutput("Module Data Width: %d bit\n", + dimmInfo.dataWidth); + break; +/*----------------------------------------------------------------------------*/ + + case 8: /* Voltage Interface */ + switch(spdRawData[i]) + { + case 0x0: + mvOsOutput("Module is TTL_5V_TOLERANT\n"); + break; + case 0x1: + mvOsOutput("Module is LVTTL\n"); + break; + case 0x2: + mvOsOutput("Module is HSTL_1_5V\n"); + break; + case 0x3: + mvOsOutput("Module is SSTL_3_3V\n"); + break; + case 0x4: + mvOsOutput("Module is SSTL_2_5V\n"); + break; + case 0x5: + if (dimmInfo.memoryType != MEM_TYPE_SDRAM) + { + mvOsOutput("Module is SSTL_1_8V\n"); + break; + } + default: + mvOsOutput("Module is VOLTAGE_UNKNOWN\n"); + break; + } + break; +/*----------------------------------------------------------------------------*/ + + case 9: /* Minimum Cycle Time At Max CasLatancy */ + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + rightOfPoint = (spdRawData[i] & 0x0f) * 10; + + /* DDR2 addition of right of point */ + if ((spdRawData[i] & 0x0f) == 0xA) + { + rightOfPoint = 25; + } + if ((spdRawData[i] & 0x0f) == 0xB) + { + rightOfPoint = 33; + } + if ((spdRawData[i] & 0x0f) == 0xC) + { + rightOfPoint = 66; + } + if ((spdRawData[i] & 0x0f) == 0xD) + { + rightOfPoint = 75; + } + mvOsOutput("Minimum Cycle Time At Max CL: %d.%d [ns]\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 10: /* Clock To Data Out */ + div = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 10:100; + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + mvOsOutput("Clock To Data Out: %d.%d [ns]\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 11: /* Error Check Type */ + mvOsOutput("Error Check Type (0=NONE): %d\n", + dimmInfo.errorCheckType); + break; +/*----------------------------------------------------------------------------*/ + + case 12: /* Refresh Interval */ + mvOsOutput("Refresh Rate: %x\n", + dimmInfo.refreshInterval); + break; +/*----------------------------------------------------------------------------*/ + + case 13: /* Sdram Width */ + mvOsOutput("Sdram Width: %d bits\n", + dimmInfo.sdramWidth); + break; +/*----------------------------------------------------------------------------*/ + + case 14: /* Error Check Data Width */ + mvOsOutput("Error Check Data Width: %d bits\n", + dimmInfo.errorCheckDataWidth); + break; +/*----------------------------------------------------------------------------*/ + + case 15: /* Minimum Clock Delay is unsupported */ + if ((dimmInfo.memoryType == MEM_TYPE_SDRAM) || + (dimmInfo.memoryType == MEM_TYPE_DDR1)) + { + mvOsOutput("Minimum Clk Delay back to back: %d\n", + spdRawData[i]); + } + break; +/*----------------------------------------------------------------------------*/ + + case 16: /* Burst Length Supported */ + /* SDRAM/DDR1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | 2 | 1 * + *********************************************************/ + /* DDR2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | TBD | TBD * + *********************************************************/ + mvOsOutput("Burst Length Supported: "); + if ((dimmInfo.memoryType == MEM_TYPE_SDRAM) || + (dimmInfo.memoryType == MEM_TYPE_DDR1)) + { + if (dimmInfo.burstLengthSupported & BIT0) + mvOsOutput("1, "); + if (dimmInfo.burstLengthSupported & BIT1) + mvOsOutput("2, "); + } + if (dimmInfo.burstLengthSupported & BIT2) + mvOsOutput("4, "); + if (dimmInfo.burstLengthSupported & BIT3) + mvOsOutput("8, "); + + mvOsOutput(" Bit \n"); + break; +/*----------------------------------------------------------------------------*/ + + case 17: /* Number Of Banks On Each Device */ + mvOsOutput("Number Of Banks On Each Chip: %d\n", + dimmInfo.numOfBanksOnEachDevice); + break; +/*----------------------------------------------------------------------------*/ + + case 18: /* Suported Cas Latencies */ + + /* SDRAM: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 7 | 6 | 5 | 4 | 3 | 2 | 1 * + ********************************************************/ + + /* DDR 1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 4 | 3.5 | 3 | 2.5 | 2 | 1.5 | 1 * + *********************************************************/ + + /* DDR 2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 5 | 4 | 3 | 2 | TBD | TBD * + *********************************************************/ + + mvOsOutput("Suported Cas Latencies: (CL) "); + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + for (k = 0; k <=7; k++) + { + if (dimmInfo.suportedCasLatencies & (1 << k)) + mvOsOutput("%d, ", k+1); + } + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if (dimmInfo.suportedCasLatencies & BIT0) + mvOsOutput("1, "); + if (dimmInfo.suportedCasLatencies & BIT1) + mvOsOutput("1.5, "); + if (dimmInfo.suportedCasLatencies & BIT2) + mvOsOutput("2, "); + if (dimmInfo.suportedCasLatencies & BIT3) + mvOsOutput("2.5, "); + if (dimmInfo.suportedCasLatencies & BIT4) + mvOsOutput("3, "); + if (dimmInfo.suportedCasLatencies & BIT5) + mvOsOutput("3.5, "); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR2) + { + if (dimmInfo.suportedCasLatencies & BIT2) + mvOsOutput("2, "); + if (dimmInfo.suportedCasLatencies & BIT3) + mvOsOutput("3, "); + if (dimmInfo.suportedCasLatencies & BIT4) + mvOsOutput("4, "); + if (dimmInfo.suportedCasLatencies & BIT5) + mvOsOutput("5, "); + } + else + mvOsOutput("?.?, "); + mvOsOutput("\n"); + break; +/*----------------------------------------------------------------------------*/ + + case 20: /* DDR2 DIMM type info */ + if (dimmInfo.memoryType == MEM_TYPE_DDR2) + { + if (dimmInfo.dimmTypeInfo & (BIT0 | BIT4)) + mvOsOutput("Registered DIMM (RDIMM)\n"); + else if (dimmInfo.dimmTypeInfo & (BIT1 | BIT5)) + mvOsOutput("Unbuffered DIMM (UDIMM)\n"); + else + mvOsOutput("Unknown DIMM type.\n"); + } + + break; +/*----------------------------------------------------------------------------*/ + + case 21: /* SDRAM Modules Attributes */ + mvOsOutput("\nModule Attributes (SPD Byte 21): \n"); + + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + if (dimmInfo.dimmAttributes & BIT0) + mvOsOutput(" Buffered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Buffered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT1) + mvOsOutput(" Registered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Registered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT2) + mvOsOutput(" On-Card PLL (clock): Yes \n"); + else + mvOsOutput(" On-Card PLL (clock): No \n"); + + if (dimmInfo.dimmAttributes & BIT3) + mvOsOutput(" Bufferd DQMB Input: Yes \n"); + else + mvOsOutput(" Bufferd DQMB Inputs: No \n"); + + if (dimmInfo.dimmAttributes & BIT4) + mvOsOutput(" Registered DQMB Inputs: Yes \n"); + else + mvOsOutput(" Registered DQMB Inputs: No \n"); + + if (dimmInfo.dimmAttributes & BIT5) + mvOsOutput(" Differential Clock Input: Yes \n"); + else + mvOsOutput(" Differential Clock Input: No \n"); + + if (dimmInfo.dimmAttributes & BIT6) + mvOsOutput(" redundant Row Addressing: Yes \n"); + else + mvOsOutput(" redundant Row Addressing: No \n"); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if (dimmInfo.dimmAttributes & BIT0) + mvOsOutput(" Buffered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Buffered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT1) + mvOsOutput(" Registered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Registered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT2) + mvOsOutput(" On-Card PLL (clock): Yes \n"); + else + mvOsOutput(" On-Card PLL (clock): No \n"); + + if (dimmInfo.dimmAttributes & BIT3) + mvOsOutput(" FET Switch On-Card Enabled: Yes \n"); + else + mvOsOutput(" FET Switch On-Card Enabled: No \n"); + + if (dimmInfo.dimmAttributes & BIT4) + mvOsOutput(" FET Switch External Enabled: Yes \n"); + else + mvOsOutput(" FET Switch External Enabled: No \n"); + + if (dimmInfo.dimmAttributes & BIT5) + mvOsOutput(" Differential Clock Input: Yes \n"); + else + mvOsOutput(" Differential Clock Input: No \n"); + } + else /* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */ + { + mvOsOutput(" Number of Active Registers on the DIMM: %d\n", + (dimmInfo.dimmAttributes & 0x3) + 1); + + mvOsOutput(" Number of PLLs on the DIMM: %d\n", + ((dimmInfo.dimmAttributes) >> 2) & 0x3); + + if (dimmInfo.dimmAttributes & BIT4) + mvOsOutput(" FET Switch External Enabled: Yes \n"); + else + mvOsOutput(" FET Switch External Enabled: No \n"); + + if (dimmInfo.dimmAttributes & BIT6) + mvOsOutput(" Analysis probe installed: Yes \n"); + else + mvOsOutput(" Analysis probe installed: No \n"); + } + + break; +/*----------------------------------------------------------------------------*/ + + case 22: /* Suported AutoPreCharge */ + mvOsOutput("\nModul Attributes (SPD Byte 22): \n"); + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + if ( spdRawData[i] & BIT0 ) + mvOsOutput(" Early Ras Precharge: Yes \n"); + else + mvOsOutput(" Early Ras Precharge: No \n"); + + if ( spdRawData[i] & BIT1 ) + mvOsOutput(" AutoPreCharge: Yes \n"); + else + mvOsOutput(" AutoPreCharge: No \n"); + + if ( spdRawData[i] & BIT2 ) + mvOsOutput(" Precharge All: Yes \n"); + else + mvOsOutput(" Precharge All: No \n"); + + if ( spdRawData[i] & BIT3 ) + mvOsOutput(" Write 1/ReadBurst: Yes \n"); + else + mvOsOutput(" Write 1/ReadBurst: No \n"); + + if ( spdRawData[i] & BIT4 ) + mvOsOutput(" lower VCC tolerance: 5%%\n"); + else + mvOsOutput(" lower VCC tolerance: 10%%\n"); + + if ( spdRawData[i] & BIT5 ) + mvOsOutput(" upper VCC tolerance: 5%%\n"); + else + mvOsOutput(" upper VCC tolerance: 10%%\n"); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if ( spdRawData[i] & BIT0 ) + mvOsOutput(" Supports Weak Driver: Yes \n"); + else + mvOsOutput(" Supports Weak Driver: No \n"); + + if ( !(spdRawData[i] & BIT4) ) + mvOsOutput(" lower VCC tolerance: 0.2V\n"); + + if ( !(spdRawData[i] & BIT5) ) + mvOsOutput(" upper VCC tolerance: 0.2V\n"); + + if ( spdRawData[i] & BIT6 ) + mvOsOutput(" Concurrent Auto Preharge: Yes \n"); + else + mvOsOutput(" Concurrent Auto Preharge: No \n"); + + if ( spdRawData[i] & BIT7 ) + mvOsOutput(" Supports Fast AP: Yes \n"); + else + mvOsOutput(" Supports Fast AP: No \n"); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR2) + { + if ( spdRawData[i] & BIT0 ) + mvOsOutput(" Supports Weak Driver: Yes \n"); + else + mvOsOutput(" Supports Weak Driver: No \n"); + } + break; +/*----------------------------------------------------------------------------*/ + + case 23: + /* Minimum Cycle Time At Maximum Cas Latancy Minus 1 (2nd highest CL) */ + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + rightOfPoint = (spdRawData[i] & 0x0f) * 10; + + /* DDR2 addition of right of point */ + if ((spdRawData[i] & 0x0f) == 0xA) + { + rightOfPoint = 25; + } + if ((spdRawData[i] & 0x0f) == 0xB) + { + rightOfPoint = 33; + } + if ((spdRawData[i] & 0x0f) == 0xC) + { + rightOfPoint = 66; + } + if ((spdRawData[i] & 0x0f) == 0xD) + { + rightOfPoint = 75; + } + + mvOsOutput("Minimum Cycle Time At 2nd highest CasLatancy" + "(0 = Not supported): %d.%d [ns]\n", + leftOfPoint, rightOfPoint ); + break; +/*----------------------------------------------------------------------------*/ + + case 24: /* Clock To Data Out 2nd highest Cas Latency Value*/ + div = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 10:100; + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + mvOsOutput("Clock To Data Out (2nd CL value): %d.%d [ns]\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 25: + /* Minimum Cycle Time At Maximum Cas Latancy Minus 2 (3rd highest CL) */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + leftOfPoint = (spdRawData[i] & 0xfc) >> 2; + rightOfPoint = (spdRawData[i] & 0x3) * 25; + } + else /* DDR1 or DDR2 */ + { + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + rightOfPoint = (spdRawData[i] & 0x0f) * 10; + + /* DDR2 addition of right of point */ + if ((spdRawData[i] & 0x0f) == 0xA) + { + rightOfPoint = 25; + } + if ((spdRawData[i] & 0x0f) == 0xB) + { + rightOfPoint = 33; + } + if ((spdRawData[i] & 0x0f) == 0xC) + { + rightOfPoint = 66; + } + if ((spdRawData[i] & 0x0f) == 0xD) + { + rightOfPoint = 75; + } + } + mvOsOutput("Minimum Cycle Time At 3rd highest CasLatancy" + "(0 = Not supported): %d.%d [ns]\n", + leftOfPoint, rightOfPoint ); + break; +/*----------------------------------------------------------------------------*/ + + case 26: /* Clock To Data Out 3rd highest Cas Latency Value*/ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + leftOfPoint = (spdRawData[i] & 0xfc) >> 2; + rightOfPoint = (spdRawData[i] & 0x3) * 25; + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = 0; + rightOfPoint = time_tmp; + } + mvOsOutput("Clock To Data Out (3rd CL value): %d.%2d[ns]\n", + leftOfPoint, rightOfPoint ); + break; +/*----------------------------------------------------------------------------*/ + + case 27: /* Minimum Row Precharge Time */ + shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 0:2; + maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0xff : 0xfc; + maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0x00 : 0x03; + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (spdRawData[i] & maskRightOfPoint)*25; + temp = ((leftOfPoint*100) + rightOfPoint);/* in 10ps Intervals*/ + trp_clocks = (temp + (busClkPs-1)) / busClkPs; + mvOsOutput("Minimum Row Precharge Time [ns]: %d.%d = " + "in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 28: /* Minimum Row Active to Row Active Time */ + shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 0:2; + maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0xff : 0xfc; + maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0x00 : 0x03; + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (spdRawData[i] & maskRightOfPoint)*25; + temp = ((leftOfPoint*100) + rightOfPoint);/* in 100ns Interval*/ + trrd_clocks = (temp + (busClkPs-1)) / busClkPs; + mvOsOutput("Minimum Row Active -To- Row Active Delay [ns]: " + "%d.%d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 29: /* Minimum Ras-To-Cas Delay */ + shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 0:2; + maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0xff : 0xfc; + maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0x00 : 0x03; + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (spdRawData[i] & maskRightOfPoint)*25; + temp = ((leftOfPoint*100) + rightOfPoint);/* in 100ns Interval*/ + trcd_clocks = (temp + (busClkPs-1) )/ busClkPs; + mvOsOutput("Minimum Ras-To-Cas Delay [ns]: %d.%d = " + "in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 30: /* Minimum Ras Pulse Width */ + tras_clocks = (cas2ps(spdRawData[i])+(busClkPs-1)) / busClkPs; + mvOsOutput("Minimum Ras Pulse Width [ns]: %d = " + "in Clk cycles %d\n", spdRawData[i], tras_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 31: /* Module Bank Density */ + mvOsOutput("Module Bank Density (more than 1= Multisize-Module):"); + + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + if (dimmInfo.dimmBankDensity & BIT0) + mvOsOutput("1GB, "); + if (dimmInfo.dimmBankDensity & BIT1) + mvOsOutput("8MB, "); + if (dimmInfo.dimmBankDensity & BIT2) + mvOsOutput("16MB, "); + if (dimmInfo.dimmBankDensity & BIT3) + mvOsOutput("32MB, "); + if (dimmInfo.dimmBankDensity & BIT4) + mvOsOutput("64MB, "); + if (dimmInfo.dimmBankDensity & BIT5) + mvOsOutput("128MB, "); + if (dimmInfo.dimmBankDensity & BIT6) + mvOsOutput("256MB, "); + if (dimmInfo.dimmBankDensity & BIT7) + mvOsOutput("512MB, "); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if (dimmInfo.dimmBankDensity & BIT0) + mvOsOutput("1GB, "); + if (dimmInfo.dimmBankDensity & BIT1) + mvOsOutput("2GB, "); + if (dimmInfo.dimmBankDensity & BIT2) + mvOsOutput("16MB, "); + if (dimmInfo.dimmBankDensity & BIT3) + mvOsOutput("32MB, "); + if (dimmInfo.dimmBankDensity & BIT4) + mvOsOutput("64MB, "); + if (dimmInfo.dimmBankDensity & BIT5) + mvOsOutput("128MB, "); + if (dimmInfo.dimmBankDensity & BIT6) + mvOsOutput("256MB, "); + if (dimmInfo.dimmBankDensity & BIT7) + mvOsOutput("512MB, "); + } + else /* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */ + { + if (dimmInfo.dimmBankDensity & BIT0) + mvOsOutput("1GB, "); + if (dimmInfo.dimmBankDensity & BIT1) + mvOsOutput("2GB, "); + if (dimmInfo.dimmBankDensity & BIT2) + mvOsOutput("4GB, "); + if (dimmInfo.dimmBankDensity & BIT3) + mvOsOutput("8GB, "); + if (dimmInfo.dimmBankDensity & BIT4) + mvOsOutput("16GB, "); + if (dimmInfo.dimmBankDensity & BIT5) + mvOsOutput("128MB, "); + if (dimmInfo.dimmBankDensity & BIT6) + mvOsOutput("256MB, "); + if (dimmInfo.dimmBankDensity & BIT7) + mvOsOutput("512MB, "); + } + mvOsOutput("\n"); + break; +/*----------------------------------------------------------------------------*/ + + case 32: /* Address And Command Setup Time (measured in ns/1000) */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Address And Command Setup Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 33: /* Address And Command Hold Time */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Address And Command Hold Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 34: /* Data Input Setup Time */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Data Input Setup Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 35: /* Data Input Hold Time */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Data Input Hold Time [ns]: %d.%d\n\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 36: /* Relevant for DDR2 only: Write Recovery Time */ + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> 2); + rightOfPoint = (spdRawData[i] & maskRightOfPoint) * 25; + mvOsOutput("Write Recovery Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + } + +} + + +/* + * translate ns.ns/10 coding of SPD timing values + * into ps unit values + */ +/******************************************************************************* +* cas2ps - Translate x.y ns parameter to pico-seconds values +* +* DESCRIPTION: +* This function translates x.y nano seconds to its value in pico seconds. +* For example 3.75ns will return 3750. +* +* INPUT: +* spd_byte - DIMM SPD byte. +* +* OUTPUT: +* None. +* +* RETURN: +* value in pico seconds. +* +*******************************************************************************/ +static MV_U32 cas2ps(MV_U8 spd_byte) +{ + MV_U32 ns, ns10; + + /* isolate upper nibble */ + ns = (spd_byte >> 4) & 0x0F; + /* isolate lower nibble */ + ns10 = (spd_byte & 0x0F); + + if( ns10 < 10 ) { + ns10 *= 10; + } + else if( ns10 == 10 ) + ns10 = 25; + else if( ns10 == 11 ) + ns10 = 33; + else if( ns10 == 12 ) + ns10 = 66; + else if( ns10 == 13 ) + ns10 = 75; + else + { + mvOsOutput("cas2ps Err. unsupported cycle time.\n"); + } + + return (ns*1000 + ns10*10); +} + diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDram.h b/board/mv_feroceon/mv_hal/ddr1_2/mvDram.h new file mode 100644 index 0000000..678e224 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDram.h @@ -0,0 +1,191 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDram +#define __INCmvDram + +#include "ddr1_2/mvDramIf.h" +#include "twsi/mvTwsi.h" + +#define MAX_DIMM_NUM 2 +#define SPD_SIZE 128 + +/* Dimm spd offsets */ +#define DIMM_MEM_TYPE 2 +#define DIMM_ROW_NUM 3 +#define DIMM_COL_NUM 4 +#define DIMM_MODULE_BANK_NUM 5 +#define DIMM_DATA_WIDTH 6 +#define DIMM_VOLT_IF 8 +#define DIMM_MIN_CC_AT_MAX_CAS 9 +#define DIMM_ERR_CHECK_TYPE 11 +#define DIMM_REFRESH_INTERVAL 12 +#define DIMM_SDRAM_WIDTH 13 +#define DIMM_ERR_CHECK_DATA_WIDTH 14 +#define DIMM_MIN_CLK_DEL 15 +#define DIMM_BURST_LEN_SUP 16 +#define DIMM_DEV_BANK_NUM 17 +#define DIMM_SUP_CAL 18 +#define DIMM_DDR2_TYPE_INFORMATION 20 /* DDR2 only */ +#define DIMM_BUF_ADDR_CONT_IN 21 +#define DIMM_MIN_CC_AT_MAX_CAS_MINUS1 23 +#define DIMM_MIN_CC_AT_MAX_CAS_MINUS2 25 +#define DIMM_MIN_ROW_PRECHARGE_TIME 27 +#define DIMM_MIN_ROW_ACTIVE_TO_ROW_ACTIVE 28 +#define DIMM_MIN_RAS_TO_CAS_DELAY 29 +#define DIMM_MIN_RAS_PULSE_WIDTH 30 +#define DIMM_BANK_DENSITY 31 +#define DIMM_MIN_WRITE_RECOVERY_TIME 36 +#define DIMM_MIN_WRITE_TO_READ_CMD_DELAY 37 +#define DIMM_MIN_READ_TO_PRECH_CMD_DELAY 38 +#define DIMM_MIN_REFRESH_TO_ACTIVATE_CMD 42 + +/* Dimm Memory Type values */ +#define DIMM_MEM_TYPE_SDRAM 0x4 +#define DIMM_MEM_TYPE_DDR1 0x7 +#define DIMM_MEM_TYPE_DDR2 0x8 + +#define DIMM_MODULE_MANU_OFFS 64 +#define DIMM_MODULE_MANU_SIZE 8 +#define DIMM_MODULE_VEN_OFFS 73 +#define DIMM_MODULE_VEN_SIZE 25 +#define DIMM_MODULE_ID_OFFS 99 +#define DIMM_MODULE_ID_SIZE 18 + +/* enumeration for voltage levels. */ +typedef enum _mvDimmVoltageIf +{ + TTL_5V_TOLERANT, + LVTTL, + HSTL_1_5V, + SSTL_3_3V, + SSTL_2_5V, + VOLTAGE_UNKNOWN, +} MV_DIMM_VOLTAGE_IF; + + +/* enumaration for SDRAM CAS Latencies. */ +typedef enum _mvDimmSdramCas +{ + SD_CL_1 =1, + SD_CL_2, + SD_CL_3, + SD_CL_4, + SD_CL_5, + SD_CL_6, + SD_CL_7, + SD_FAULT +}MV_DIMM_SDRAM_CAS; + + +/* DIMM information structure */ +typedef struct _mvDimmInfo +{ + MV_MEMORY_TYPE memoryType; /* DDR or SDRAM */ + + MV_U8 spdRawData[SPD_SIZE]; /* Content of SPD-EEPROM copied 1:1 */ + + /* DIMM dimensions */ + MV_U32 numOfRowAddr; + MV_U32 numOfColAddr; + MV_U32 numOfModuleBanks; + MV_U32 dataWidth; + MV_U32 errorCheckType; /* ECC , PARITY..*/ + MV_U32 sdramWidth; /* 4,8,16 or 32 */ + MV_U32 errorCheckDataWidth; /* 0 - no, 1 - Yes */ + MV_U32 burstLengthSupported; + MV_U32 numOfBanksOnEachDevice; + MV_U32 suportedCasLatencies; + MV_U32 refreshInterval; + MV_U32 dimmBankDensity; + MV_U32 dimmTypeInfo; /* DDR2 only */ + MV_U32 dimmAttributes; + + /* DIMM timing parameters */ + MV_U32 minCycleTimeAtMaxCasLatPs; + MV_U32 minCycleTimeAtMaxCasLatMinus1Ps; + MV_U32 minCycleTimeAtMaxCasLatMinus2Ps; + MV_U32 minRowPrechargeTime; + MV_U32 minRowActiveToRowActive; + MV_U32 minRasToCasDelay; + MV_U32 minRasPulseWidth; + MV_U32 minWriteRecoveryTime; /* DDR2 only */ + MV_U32 minWriteToReadCmdDelay; /* DDR2 only */ + MV_U32 minReadToPrechCmdDelay; /* DDR2 only */ + MV_U32 minRefreshToActiveCmd; /* DDR2 only */ + + /* Parameters calculated from the extracted DIMM information */ + MV_U32 size; /* 16,64,128,256 or 512 MByte in MB units */ + MV_U32 deviceDensity; /* 16,64,128,256 or 512 Mbit in MB units */ + MV_U32 numberOfDevices; + +} MV_DIMM_INFO; + + +MV_STATUS mvDramBankInfoGet(MV_U32 bankNum, MV_DRAM_BANK_INFO *pBankInfo); +MV_STATUS dimmSpdGet(MV_U32 dimmNum, MV_DIMM_INFO *pDimmInfo); +MV_VOID dimmSpdPrint(MV_U32 dimmNum); +MV_STATUS dimmSpdCpy(MV_VOID); + +#endif /* __INCmvDram */ diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.c b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.c new file mode 100644 index 0000000..12fb26a --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.c @@ -0,0 +1,1599 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "ddr1_2/mvDramIf.h" +#include "ctrlEnv/sys/mvCpuIf.h" + + + +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +/* DRAM bank presence encoding */ +#define BANK_PRESENT_CS0 0x1 +#define BANK_PRESENT_CS0_CS1 0x3 +#define BANK_PRESENT_CS0_CS2 0x5 +#define BANK_PRESENT_CS0_CS1_CS2 0x7 +#define BANK_PRESENT_CS0_CS2_CS3 0xd +#define BANK_PRESENT_CS0_CS2_CS3_CS4 0xf + +/* locals */ +static MV_BOOL sdramIfWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin); +#if defined(MV_INC_BOARD_DDIM) +static void sdramDDr2OdtConfig(MV_DRAM_BANK_INFO *pBankInfo); +static MV_U32 dunitCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas); +static MV_U32 sdramModeRegCalc(MV_U32 minCas); +static MV_U32 sdramExtModeRegCalc(MV_DRAM_BANK_INFO *pBankInfo); +static MV_U32 sdramAddrCtrlRegCalc(MV_DRAM_BANK_INFO *pBankInfo); +static MV_U32 sdramConfigRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk); +static MV_U32 minCasCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk, + MV_U32 forcedCl); +static MV_U32 sdramTimeCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, + MV_U32 minCas, MV_U32 busClk); +static MV_U32 sdramTimeCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo, + MV_U32 busClk); + +/******************************************************************************* +* mvDramIfDetect - Prepare DRAM interface configuration values. +* +* DESCRIPTION: +* This function implements the full DRAM detection and timing +* configuration for best system performance. +* Since this routine runs from a ROM device (Boot Flash), its stack +* resides on RAM, that might be the system DRAM. Changing DRAM +* configuration values while keeping vital data in DRAM is risky. That +* is why the function does not preform the configuration setting but +* prepare those in predefined 32bit registers (in this case IDMA +* registers are used) for other routine to perform the settings. +* The function will call for board DRAM SPD information for each DRAM +* chip select. The function will then analyze those SPD parameters of +* all DRAM banks in order to decide on DRAM configuration compatible +* for all DRAM banks. +* The function will set the CPU DRAM address decode registers. +* Note: This routine prepares values that will overide configuration of +* mvDramBasicAsmInit(). +* +* INPUT: +* forcedCl - Forced CAL Latency. If equal to zero, do not force. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvDramIfDetect(MV_U32 forcedCl) +{ + MV_U32 retVal = MV_OK; /* return value */ + MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS]; + MV_U32 busClk, size, base = 0, i, temp, deviceW, dimmW; + MV_U8 minCas; + MV_DRAM_DEC_WIN dramDecWin; + + dramDecWin.addrWin.baseHigh = 0; + + busClk = mvBoardSysClkGet(); + + if (0 == busClk) + { + mvOsPrintf("Dram: ERR. Can't detect system clock! \n"); + return MV_ERROR; + } + + /* Close DRAM banks except bank 0 (in case code is excecuting from it...) */ +#if defined(MV_INCLUDE_SDRAM_CS1) + for(i= SDRAM_CS1; i < MV_DRAM_MAX_CS; i++) + mvCpuIfTargetWinEnable(i, MV_FALSE); +#endif + + /* we will use bank 0 as the representative of the all the DRAM banks, */ + /* since bank 0 must exist. */ + for(i = 0; i < MV_DRAM_MAX_CS; i++) + { + /* if Bank exist */ + if(MV_OK == mvDramBankInfoGet(i, &bankInfo[i])) + { + /* check it isn't SDRAM */ + if(bankInfo[i].memoryType == MEM_TYPE_SDRAM) + { + mvOsPrintf("Dram: ERR. SDRAM type not supported !!!\n"); + return MV_ERROR; + } + /* All banks must support registry in order to activate it */ + if(bankInfo[i].registeredAddrAndControlInputs != + bankInfo[0].registeredAddrAndControlInputs) + { + mvOsPrintf("Dram: ERR. different Registered settings !!!\n"); + return MV_ERROR; + } + + /* Init the CPU window decode */ + /* Note that the size in Bank info is in MB units */ + /* Note that the Dimm width might be different then the device DRAM width */ + temp = MV_REG_READ(SDRAM_CONFIG_REG); + + deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_16BIT )? 16 : 32; + dimmW = bankInfo[0].dataWidth - (bankInfo[0].dataWidth % 16); + size = ((bankInfo[i].size << 20) / (dimmW/deviceW)); + + /* We can not change DRAM window settings while excecuting */ + /* code from it. That is why we skip the DRAM CS[0], saving */ + /* it to the ROM configuration routine */ + if(i == SDRAM_CS0) + { + MV_U32 sizeToReg; + + /* Translate the given window size to register format */ + sizeToReg = ctrlSizeToReg(size, SCSR_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n" + ,i); + return MV_BAD_PARAM; + } + + /* Size is located at upper 16 bits */ + sizeToReg <<= SCSR_SIZE_OFFS; + + /* enable it */ + sizeToReg |= SCSR_WIN_EN; + + MV_REG_WRITE(DRAM_BUF_REG0, sizeToReg); + } + else + { + dramDecWin.addrWin.baseLow = base; + dramDecWin.addrWin.size = size; + dramDecWin.enable = MV_TRUE; + + if (MV_OK != mvDramIfWinSet(SDRAM_CS0 + i, &dramDecWin)) + { + mvOsPrintf("Dram: ERR. Fail to set bank %d!!!\n", + SDRAM_CS0 + i); + return MV_ERROR; + } + } + + base += size; + + /* update the suportedCasLatencies mask */ + bankInfo[0].suportedCasLatencies &= bankInfo[i].suportedCasLatencies; + + } + else + { + if( i == 0 ) /* bank 0 doesn't exist */ + { + mvOsPrintf("Dram: ERR. Fail to detect bank 0 !!!\n"); + return MV_ERROR; + } + else + { + DB(mvOsPrintf("Dram: Could not find bank %d\n", i)); + bankInfo[i].size = 0; /* Mark this bank as non exist */ + } + } + } + + /* calculate minimum CAS */ + minCas = minCasCalc(&bankInfo[0], busClk, forcedCl); + if (0 == minCas) + { + mvOsOutput("Dram: Warn: Could not find CAS compatible to SysClk %dMhz\n", + (busClk / 1000000)); + + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + minCas = DDR2_CL_4; /* Continue with this CAS */ + mvOsPrintf("Set default CAS latency 4\n"); + } + else + { + minCas = DDR1_CL_3; /* Continue with this CAS */ + mvOsPrintf("Set default CAS latency 3\n"); + } + } + + /* calc SDRAM_CONFIG_REG and save it to temp register */ + temp = sdramConfigRegCalc(&bankInfo[0], busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramConfigRegCalc failed !!!\n"); + return MV_ERROR; + } + MV_REG_WRITE(DRAM_BUF_REG1, temp); + + /* calc SDRAM_MODE_REG and save it to temp register */ + temp = sdramModeRegCalc(minCas); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n"); + return MV_ERROR; + } + MV_REG_WRITE(DRAM_BUF_REG2, temp); + + /* calc SDRAM_EXTENDED_MODE_REG and save it to temp register */ + temp = sdramExtModeRegCalc(&bankInfo[0]); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n"); + return MV_ERROR; + } + MV_REG_WRITE(DRAM_BUF_REG10, temp); + + /* calc D_UNIT_CONTROL_LOW and save it to temp register */ + temp = dunitCtrlLowRegCalc(&bankInfo[0], minCas); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. dunitCtrlLowRegCalc failed !!!\n"); + return MV_ERROR; + } + MV_REG_WRITE(DRAM_BUF_REG3, temp); + + /* calc SDRAM_ADDR_CTRL_REG and save it to temp register */ + temp = sdramAddrCtrlRegCalc(&bankInfo[0]); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramAddrCtrlRegCalc failed !!!\n"); + return MV_ERROR; + } + MV_REG_WRITE(DRAM_BUF_REG4, temp); + + /* calc SDRAM_TIMING_CTRL_LOW_REG and save it to temp register */ + temp = sdramTimeCtrlLowRegCalc(&bankInfo[0], minCas, busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramTimeCtrlLowRegCalc failed !!!\n"); + return MV_ERROR; + } + MV_REG_WRITE(DRAM_BUF_REG5, temp); + + /* calc SDRAM_TIMING_CTRL_HIGH_REG and save it to temp register */ + temp = sdramTimeCtrlHighRegCalc(&bankInfo[0], busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramTimeCtrlHighRegCalc failed !!!\n"); + return MV_ERROR; + } + MV_REG_WRITE(DRAM_BUF_REG6, temp); + + /* Config DDR2 On Die Termination (ODT) registers */ + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + sdramDDr2OdtConfig(bankInfo); + } + + /* Note that DDR SDRAM Address/Control and Data pad calibration */ + /* settings is done in mvSdramIfConfig.s */ + + return retVal; +} + +/******************************************************************************* +* minCasCalc - Calculate the Minimum CAS latency which can be used. +* +* DESCRIPTION: +* Calculate the minimum CAS latency that can be used, base on the DRAM +* parameters and the SDRAM bus Clock freq. +* +* INPUT: +* busClk - the DRAM bus Clock. +* pBankInfo - bank info parameters. +* +* OUTPUT: +* None +* +* RETURN: +* The minimum CAS Latency. The function returns 0 if max CAS latency +* supported by banks is incompatible with system bus clock frequancy. +* +*******************************************************************************/ +static MV_U32 minCasCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk, + MV_U32 forcedCl) +{ + MV_U32 count = 1, j; + MV_U32 busClkPs = 1000000000 / (busClk / 1000); /* in ps units */ + MV_U32 startBit, stopBit; + + /* DDR 1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 4 | 3.5 | 3 | 2.5 | 2 | 1.5 | 1 * + *********************************************************/ + + /* DDR 2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 5 | 4 | 3 | 2 | TBD | TBD * + *********************************************************/ + + + /* If we are asked to use the forced CAL */ + if (forcedCl) + { + mvOsPrintf("DRAM: Using forced CL %d.%d\n", (forcedCl / 10), + (forcedCl % 10)); + + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + if (forcedCl == 30) + pBankInfo->suportedCasLatencies = 0x08; + else if (forcedCl == 40) + pBankInfo->suportedCasLatencies = 0x10; + else + { + mvOsPrintf("Forced CL %d.%d not supported. Set default CL 4\n", + (forcedCl / 10), (forcedCl % 10)); + pBankInfo->suportedCasLatencies = 0x10; + } + } + else + { + if (forcedCl == 15) + pBankInfo->suportedCasLatencies = 0x02; + else if (forcedCl == 20) + pBankInfo->suportedCasLatencies = 0x04; + else if (forcedCl == 25) + pBankInfo->suportedCasLatencies = 0x08; + else if (forcedCl == 30) + pBankInfo->suportedCasLatencies = 0x10; + else if (forcedCl == 40) + pBankInfo->suportedCasLatencies = 0x40; + else + { + mvOsPrintf("Forced CL %d.%d not supported. Set default CL 3\n", + (forcedCl / 10), (forcedCl % 10)); + pBankInfo->suportedCasLatencies = 0x10; + } + } + + return pBankInfo->suportedCasLatencies; + } + + /* go over the supported cas mask from Max Cas down and check if the */ + /* SysClk stands in its time requirments. */ + + + DB(mvOsPrintf("Dram: minCasCalc supported mask = %x busClkPs = %x \n", + pBankInfo->suportedCasLatencies,busClkPs )); + for(j = 7; j > 0; j--) + { + if((pBankInfo->suportedCasLatencies >> j) & BIT0 ) + { + /* Reset the bits for CL incompatible for the sysClk */ + switch (count) + { + case 1: + if (pBankInfo->minCycleTimeAtMaxCasLatPs > busClkPs) + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + case 2: + if (pBankInfo->minCycleTimeAtMaxCasLatMinus1Ps > busClkPs) + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + case 3: + if (pBankInfo->minCycleTimeAtMaxCasLatMinus2Ps > busClkPs) + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + default: + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + break; + } + } + } + + DB(mvOsPrintf("Dram: minCasCalc support = %x (after SysCC calc)\n", + pBankInfo->suportedCasLatencies )); + + /* SDRAM DDR1 controller supports CL 1.5 to 3.5 */ + /* SDRAM DDR2 controller supports CL 3 to 5 */ + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + startBit = 3; /* DDR2 support CL start with CL3 (bit 3) */ + stopBit = 5; /* DDR2 support CL stops with CL5 (bit 5) */ + } + else + { + startBit = 1; /* DDR1 support CL start with CL1.5 (bit 3) */ + stopBit = 4; /* DDR1 support CL stops with CL3 (bit 4) */ + } + + for(j = startBit; j <= stopBit ; j++) + { + if((pBankInfo->suportedCasLatencies >> j) & BIT0 ) + { + DB(mvOsPrintf("Dram: minCasCalc choose CAS %x \n",(BIT0 << j))); + return (BIT0 << j); + } + } + + return 0; +} + +/******************************************************************************* +* sdramConfigRegCalc - Calculate sdram config register +* +* DESCRIPTION: Calculate sdram config register optimized value based +* on the bank info parameters. +* +* INPUT: +* pBankInfo - sdram bank parameters +* +* OUTPUT: +* None +* +* RETURN: +* sdram config reg value. +* +*******************************************************************************/ +static MV_U32 sdramConfigRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk) +{ + MV_U32 sdramConfig = 0; + MV_U32 refreshPeriod; + + busClk /= 1000000; /* we work with busClk in MHz */ + + sdramConfig = MV_REG_READ(SDRAM_CONFIG_REG); + + /* figure out the memory refresh internal */ + switch (pBankInfo->refreshInterval & 0xf) + { + case 0x0: /* refresh period is 15.625 usec */ + refreshPeriod = 15625; + break; + case 0x1: /* refresh period is 3.9 usec */ + refreshPeriod = 3900; + break; + case 0x2: /* refresh period is 7.8 usec */ + refreshPeriod = 7800; + break; + case 0x3: /* refresh period is 31.3 usec */ + refreshPeriod = 31300; + break; + case 0x4: /* refresh period is 62.5 usec */ + refreshPeriod = 62500; + break; + case 0x5: /* refresh period is 125 usec */ + refreshPeriod = 125000; + break; + default: /* refresh period undefined */ + mvOsPrintf("Dram: ERR. DRAM refresh period is unknown!\n"); + return -1; + } + + /* Now the refreshPeriod is in register format value */ + refreshPeriod = (busClk * refreshPeriod) / 1000; + + DB(mvOsPrintf("Dram: sdramConfigRegCalc calculated refresh interval %0x\n", + refreshPeriod)); + + /* make sure the refresh value is only 14 bits */ + if(refreshPeriod > SDRAM_REFRESH_MAX) + { + refreshPeriod = SDRAM_REFRESH_MAX; + DB(mvOsPrintf("Dram: sdramConfigRegCalc adjusted refresh interval %0x\n", + refreshPeriod)); + } + + /* Clear the refresh field */ + sdramConfig &= ~SDRAM_REFRESH_MASK; + + /* Set new value to refresh field */ + sdramConfig |= (refreshPeriod & SDRAM_REFRESH_MASK); + + /* registered DRAM ? */ + if ( pBankInfo->registeredAddrAndControlInputs ) + { + /* it's registered DRAM, so set the reg. DRAM bit */ + sdramConfig |= SDRAM_REGISTERED; + mvOsPrintf("DRAM Attribute: Registered address and control inputs.\n"); + } + + /* set DDR SDRAM devices configuration */ + sdramConfig &= ~SDRAM_DCFG_MASK; /* Clear Dcfg field */ + + switch (pBankInfo->sdramWidth) + { + case 8: /* memory is x8 */ + sdramConfig |= SDRAM_DCFG_X8_DEV; + DB(mvOsPrintf("Dram: sdramConfigRegCalc SDRAM device width x8\n")); + break; + case 16: + sdramConfig |= SDRAM_DCFG_X16_DEV; + DB(mvOsPrintf("Dram: sdramConfigRegCalc SDRAM device width x16\n")); + break; + default: /* memory width unsupported */ + mvOsPrintf("Dram: ERR. DRAM chip width is unknown!\n"); + return -1; + } + + /* Set static default settings */ + sdramConfig |= SDRAM_CONFIG_DV; + + DB(mvOsPrintf("Dram: sdramConfigRegCalc set sdramConfig to 0x%x\n", + sdramConfig)); + + return sdramConfig; +} + +/******************************************************************************* +* sdramModeRegCalc - Calculate sdram mode register +* +* DESCRIPTION: Calculate sdram mode register optimized value based +* on the bank info parameters and the minCas. +* +* INPUT: +* minCas - minimum CAS supported. +* +* OUTPUT: +* None +* +* RETURN: +* sdram mode reg value. +* +*******************************************************************************/ +static MV_U32 sdramModeRegCalc(MV_U32 minCas) +{ + MV_U32 sdramMode; + + sdramMode = MV_REG_READ(SDRAM_MODE_REG); + + /* Clear CAS Latency field */ + sdramMode &= ~SDRAM_CL_MASK; + + mvOsPrintf("DRAM CAS Latency "); + + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + switch (minCas) + { + case DDR2_CL_3: + sdramMode |= SDRAM_DDR2_CL_3; + mvOsPrintf("3.\n"); + break; + case DDR2_CL_4: + sdramMode |= SDRAM_DDR2_CL_4; + mvOsPrintf("4.\n"); + break; + case DDR2_CL_5: + sdramMode |= SDRAM_DDR2_CL_5; + mvOsPrintf("5.\n"); + break; + default: + mvOsPrintf("\nsdramModeRegCalc ERROR: Max. CL out of range\n"); + return -1; + } + sdramMode |= DDR2_MODE_REG_DV; + } + else /* DDR1 */ + { + switch (minCas) + { + case DDR1_CL_1_5: + sdramMode |= SDRAM_DDR1_CL_1_5; + mvOsPrintf("1.5\n"); + break; + case DDR1_CL_2: + sdramMode |= SDRAM_DDR1_CL_2; + mvOsPrintf("2\n"); + break; + case DDR1_CL_2_5: + sdramMode |= SDRAM_DDR1_CL_2_5; + mvOsPrintf("2.5\n"); + break; + case DDR1_CL_3: + sdramMode |= SDRAM_DDR1_CL_3; + mvOsPrintf("3\n"); + break; + case DDR1_CL_4: + sdramMode |= SDRAM_DDR1_CL_4; + mvOsPrintf("4\n"); + break; + default: + mvOsPrintf("\nsdramModeRegCalc ERROR: Max. CL out of range\n"); + return -1; + } + sdramMode |= DDR1_MODE_REG_DV; + } + + DB(mvOsPrintf("nsdramModeRegCalc register 0x%x\n", sdramMode )); + + return sdramMode; +} + +/******************************************************************************* +* sdramExtModeRegCalc - Calculate sdram Extended mode register +* +* DESCRIPTION: +* Return sdram Extended mode register value based +* on the bank info parameters and bank presence. +* +* INPUT: +* pBankInfo - sdram bank parameters +* +* OUTPUT: +* None +* +* RETURN: +* sdram Extended mode reg value. +* +*******************************************************************************/ +static MV_U32 sdramExtModeRegCalc(MV_DRAM_BANK_INFO *pBankInfo) +{ + MV_U32 populateBanks = 0; + int bankNum; + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + /* Represent the populate banks in binary form */ + for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + if (0 != pBankInfo[bankNum].size) + { + populateBanks |= (1 << bankNum); + } + } + + switch(populateBanks) + { + case(BANK_PRESENT_CS0): + return DDR_SDRAM_EXT_MODE_CS0_DV; + + case(BANK_PRESENT_CS0_CS1): + return DDR_SDRAM_EXT_MODE_CS0_DV; + + case(BANK_PRESENT_CS0_CS2): + return DDR_SDRAM_EXT_MODE_CS0_CS2_DV; + + case(BANK_PRESENT_CS0_CS1_CS2): + return DDR_SDRAM_EXT_MODE_CS0_CS2_DV; + + case(BANK_PRESENT_CS0_CS2_CS3): + return DDR_SDRAM_EXT_MODE_CS0_CS2_DV; + + case(BANK_PRESENT_CS0_CS2_CS3_CS4): + return DDR_SDRAM_EXT_MODE_CS0_CS2_DV; + + default: + mvOsPrintf("sdramExtModeRegCalc: Invalid DRAM bank presence\n"); + return -1; + } + } + return 0; +} + +/******************************************************************************* +* dunitCtrlLowRegCalc - Calculate sdram dunit control low register +* +* DESCRIPTION: Calculate sdram dunit control low register optimized value based +* on the bank info parameters and the minCas. +* +* INPUT: +* pBankInfo - sdram bank parameters +* minCas - minimum CAS supported. +* +* OUTPUT: +* None +* +* RETURN: +* sdram dunit control low reg value. +* +*******************************************************************************/ +static MV_U32 dunitCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas) +{ + MV_U32 dunitCtrlLow; + + dunitCtrlLow = MV_REG_READ(SDRAM_DUNIT_CTRL_REG); + + /* Clear StBurstDel field */ + dunitCtrlLow &= ~SDRAM_ST_BURST_DEL_MASK; + +#ifdef MV_88W8660 + /* Clear address/control output timing field */ + dunitCtrlLow &= ~SDRAM_CTRL_POS_RISE; +#endif /* MV_88W8660 */ + + DB(mvOsPrintf("Dram: dunitCtrlLowRegCalc\n")); + + /* For proper sample of read data set the Dunit Control register's */ + /* stBurstDel bits [27:24] */ + /********-********-********-********-********-********* + * CL=1.5 | CL=2 | CL=2.5 | CL=3 | CL=4 | CL=5 * + *********-********-********-********-********-********* +Not Reg. * 0011 | 0011 | 0100 | 0100 | 0101 | TBD * + *********-********-********-********-********-********* +Registered * 0100 | 0100 | 0101 | 0101 | 0110 | TBD * + *********-********-********-********-********-*********/ + + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + switch (minCas) + { + case DDR2_CL_3: + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS; + else + dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS; + break; + case DDR2_CL_4: + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + dunitCtrlLow |= 0x6 << SDRAM_ST_BURST_DEL_OFFS; + else + dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS; + break; + default: + mvOsPrintf("Dram: dunitCtrlLowRegCalc Max. CL out of range %d\n", + minCas); + return -1; + } + } + else /* DDR1 */ + { + switch (minCas) + { + case DDR1_CL_1_5: + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS; + else + dunitCtrlLow |= 0x3 << SDRAM_ST_BURST_DEL_OFFS; + break; + case DDR1_CL_2: + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS; + else + dunitCtrlLow |= 0x3 << SDRAM_ST_BURST_DEL_OFFS; + break; + case DDR1_CL_2_5: + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS; + else + dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS; + break; + case DDR1_CL_3: + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS; + else + dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS; + break; + case DDR1_CL_4: + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + dunitCtrlLow |= 0x6 << SDRAM_ST_BURST_DEL_OFFS; + else + dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS; + break; + default: + mvOsPrintf("Dram: dunitCtrlLowRegCalc Max. CL out of range %d\n", + minCas); + return -1; + } + + } + DB(mvOsPrintf("Dram: Reg dunit control low = %x\n", dunitCtrlLow )); + + return dunitCtrlLow; +} + +/******************************************************************************* +* sdramAddrCtrlRegCalc - Calculate sdram address control register +* +* DESCRIPTION: Calculate sdram address control register optimized value based +* on the bank info parameters and the minCas. +* +* INPUT: +* pBankInfo - sdram bank parameters +* +* OUTPUT: +* None +* +* RETURN: +* sdram address control reg value. +* +*******************************************************************************/ +static MV_U32 sdramAddrCtrlRegCalc(MV_DRAM_BANK_INFO *pBankInfo) +{ + MV_U32 addrCtrl = 0; + + /* Set Address Control register static configuration bits */ + addrCtrl = MV_REG_READ(SDRAM_ADDR_CTRL_REG); + + /* Set address control default value */ + addrCtrl |= SDRAM_ADDR_CTRL_DV; + + /* Clear DSize field */ + addrCtrl &= ~SDRAM_DSIZE_MASK; + + /* Note that density is in MB units */ + switch (pBankInfo->deviceDensity) + { + case 128: /* 128 Mbit */ + DB(mvOsPrintf("DRAM Device Density 128Mbit\n")); + addrCtrl |= SDRAM_DSIZE_128Mb; + break; + case 256: /* 256 Mbit */ + DB(mvOsPrintf("DRAM Device Density 256Mbit\n")); + addrCtrl |= SDRAM_DSIZE_256Mb; + break; + case 512: /* 512 Mbit */ + DB(mvOsPrintf("DRAM Device Density 512Mbit\n")); + addrCtrl |= SDRAM_DSIZE_512Mb; + break; + default: + mvOsPrintf("Dram: sdramAddrCtrl unsupported RAM-Device size %d\n", + pBankInfo->deviceDensity); + return -1; + } + + /* SDRAM address control */ + DB(mvOsPrintf("Dram: setting sdram address control with: %x \n", addrCtrl)); + + return addrCtrl; +} + +/******************************************************************************* +* sdramTimeCtrlLowRegCalc - Calculate sdram timing control low register +* +* DESCRIPTION: +* This function calculates sdram timing control low register +* optimized value based on the bank info parameters and the minCas. +* +* INPUT: +* pBankInfo - sdram bank parameters +* busClk - Bus clock +* +* OUTPUT: +* None +* +* RETURN: +* sdram timinf control low reg value. +* +*******************************************************************************/ +static MV_U32 sdramTimeCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, + MV_U32 minCas, MV_U32 busClk) +{ + MV_U32 tRp = 0; + MV_U32 tRrd = 0; + MV_U32 tRcd = 0; + MV_U32 tRas = 0; + MV_U32 tWr = 0; + MV_U32 tWtr = 0; + MV_U32 tRtp = 0; + + MV_U32 bankNum; + + busClk = busClk / 1000000; /* In MHz */ + + /* Scan all DRAM banks to find maximum timing values */ + for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + tRp = MV_MAX(tRp, pBankInfo[bankNum].minRowPrechargeTime); + tRrd = MV_MAX(tRrd, pBankInfo[bankNum].minRowActiveToRowActive); + tRcd = MV_MAX(tRcd, pBankInfo[bankNum].minRasToCasDelay); + tRas = MV_MAX(tRas, pBankInfo[bankNum].minRasPulseWidth); + } + + /* Extract timing (in ns) from SPD value. We ignore the tenth ns part. */ + /* by shifting the data two bits right. */ + tRp = tRp >> 2; /* For example 0x50 -> 20ns */ + tRrd = tRrd >> 2; + tRcd = tRcd >> 2; + + /* Extract clock cycles from time parameter. We need to round up */ + tRp = ((busClk * tRp) / 1000) + (((busClk * tRp) % 1000) ? 1 : 0); + /* Micron work around for 133MHz */ + if (busClk == 133) + tRp += 1; + DB(mvOsPrintf("Dram Timing Low: tRp = %d ", tRp)); + tRrd = ((busClk * tRrd) / 1000) + (((busClk * tRrd) % 1000) ? 1 : 0); + /* JEDEC min reqeirments tRrd = 2 */ + if (tRrd < 2) + tRrd = 2; + DB(mvOsPrintf("tRrd = %d ", tRrd)); + tRcd = ((busClk * tRcd) / 1000) + (((busClk * tRcd) % 1000) ? 1 : 0); + DB(mvOsPrintf("tRcd = %d ", tRcd)); + tRas = ((busClk * tRas) / 1000) + (((busClk * tRas) % 1000) ? 1 : 0); + DB(mvOsPrintf("tRas = %d ", tRas)); + + /* tWr and tWtr is different for DDR1 and DDR2. tRtp is only for DDR2 */ + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + /* Scan all DRAM banks to find maximum timing values */ + for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + tWr = MV_MAX(tWr, pBankInfo[bankNum].minWriteRecoveryTime); + tWtr = MV_MAX(tWtr, pBankInfo[bankNum].minWriteToReadCmdDelay); + tRtp = MV_MAX(tRtp, pBankInfo[bankNum].minReadToPrechCmdDelay); + } + + /* Extract timing (in ns) from SPD value. We ignore the tenth ns */ + /* part by shifting the data two bits right. */ + tWr = tWr >> 2; /* For example 0x50 -> 20ns */ + tWtr = tWtr >> 2; + tRtp = tRtp >> 2; + + /* Extract clock cycles from time parameter. We need to round up */ + tWr = ((busClk * tWr) / 1000) + (((busClk * tWr) % 1000) ? 1 : 0); + DB(mvOsPrintf("tWr = %d ", tWr)); + tWtr = ((busClk * tWtr) / 1000) + (((busClk * tWtr) % 1000) ? 1 : 0); + /* JEDEC min reqeirments tWtr = 2 */ + if (tWtr < 2) + tWtr = 2; + DB(mvOsPrintf("tWtr = %d ", tWtr)); + tRtp = ((busClk * tRtp) / 1000) + (((busClk * tRtp) % 1000) ? 1 : 0); + /* JEDEC min reqeirments tRtp = 2 */ + if (tRtp < 2) + tRtp = 2; + DB(mvOsPrintf("tRtp = %d ", tRtp)); + } + else + { + tWr = ((busClk*SDRAM_TWR) / 1000) + (((busClk*SDRAM_TWR) % 1000)?1:0); + + if ((200 == busClk) || ((100 == busClk) && (DDR1_CL_1_5 == minCas))) + { + tWtr = 2; + } + else + { + tWtr = 1; + } + + tRtp = 2; /* Must be set to 0x1 (two cycles) when using DDR1 */ + } + + DB(mvOsPrintf("tWtr = %d\n", tWtr)); + + /* Note: value of 0 in register means one cycle, 1 means two and so on */ + return (((tRp - 1) << SDRAM_TRP_OFFS) | + ((tRrd - 1) << SDRAM_TRRD_OFFS) | + ((tRcd - 1) << SDRAM_TRCD_OFFS) | + ((tRas - 1) << SDRAM_TRAS_OFFS) | + ((tWr - 1) << SDRAM_TWR_OFFS) | + ((tWtr - 1) << SDRAM_TWTR_OFFS) | + ((tRtp - 1) << SDRAM_TRTP_OFFS)); +} + +/******************************************************************************* +* sdramTimeCtrlHighRegCalc - Calculate sdram timing control high register +* +* DESCRIPTION: +* This function calculates sdram timing control high register +* optimized value based on the bank info parameters and the bus clock. +* +* INPUT: +* pBankInfo - sdram bank parameters +* busClk - Bus clock +* +* OUTPUT: +* None +* +* RETURN: +* sdram timinf control high reg value. +* +*******************************************************************************/ +static MV_U32 sdramTimeCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo, + MV_U32 busClk) +{ + MV_U32 tRfc; + MV_U32 timeNs = 0; + int bankNum; + MV_U32 sdramTw2wCyc = 0; + + busClk = busClk / 1000000; /* In MHz */ + + /* tRfc is different for DDR1 and DDR2. */ + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + MV_U32 bankNum; + + /* Scan all DRAM banks to find maximum timing values */ + for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + timeNs = MV_MAX(timeNs, pBankInfo[bankNum].minRefreshToActiveCmd); + } + else + { + if (pBankInfo[0].deviceDensity == _1G) + { + timeNs = SDRAM_TRFC_1G; + } + else + { + if (200 == busClk) + { + timeNs = SDRAM_TRFC_64_512M_AT_200MHZ; + } + else + { + timeNs = SDRAM_TRFC_64_512M; + } + } + } + + tRfc = ((busClk * timeNs) / 1000) + (((busClk * timeNs) % 1000) ? 1 : 0); + + DB(mvOsPrintf("Dram Timing High: tRfc = %d\n", tRfc)); + + + /* Represent the populate banks in binary form */ + for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + if (0 != pBankInfo[bankNum].size) + sdramTw2wCyc++; + } + + /* If we have more the 1 bank then we need the TW2W in 1 for ODT switch */ + if (sdramTw2wCyc > 1) + sdramTw2wCyc = 1; + else + sdramTw2wCyc = 0; + + /* Note: value of 0 in register means one cycle, 1 means two and so on */ + return ((((tRfc - 1) & SDRAM_TRFC_MASK) << SDRAM_TRFC_OFFS) | + ((SDRAM_TR2R_CYC - 1) << SDRAM_TR2R_OFFS) | + ((SDRAM_TR2WW2R_CYC - 1) << SDRAM_TR2W_W2R_OFFS) | + (((tRfc - 1) >> 4) << SDRAM_TRFC_EXT_OFFS) | + (sdramTw2wCyc << SDRAM_TW2W_OFFS)); + +} + +/******************************************************************************* +* sdramDDr2OdtConfig - Set DRAM DDR2 On Die Termination registers. +* +* DESCRIPTION: +* This function config DDR2 On Die Termination (ODT) registers. +* ODT configuration is done according to DIMM presence: +* +* Presence Ctrl Low Ctrl High Dunit Ctrl Ext Mode +* CS0 0x84210000 0x00000000 0x0000780F 0x00000440 +* CS0+CS1 0x84210000 0x00000000 0x0000780F 0x00000440 +* CS0+CS2 0x030C030C 0x00000000 0x0000740F 0x00000404 +* CS0+CS1+CS2 0x030C030C 0x00000000 0x0000740F 0x00000404 +* CS0+CS2+CS3 0x030C030C 0x00000000 0x0000740F 0x00000404 +* CS0+CS1+CS2+CS3 0x030C030C 0x00000000 0x0000740F 0x00000404 +* +* INPUT: +* pBankInfo - bank info parameters. +* +* OUTPUT: +* None +* +* RETURN: +* None +*******************************************************************************/ +static void sdramDDr2OdtConfig(MV_DRAM_BANK_INFO *pBankInfo) +{ + MV_U32 populateBanks = 0; + MV_U32 odtCtrlLow, odtCtrlHigh, dunitOdtCtrl; + int bankNum; + + /* Represent the populate banks in binary form */ + for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + if (0 != pBankInfo[bankNum].size) + { + populateBanks |= (1 << bankNum); + } + } + + switch(populateBanks) + { + case(BANK_PRESENT_CS0): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_DV; + break; + case(BANK_PRESENT_CS0_CS1): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_DV; + break; + case(BANK_PRESENT_CS0_CS2): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS2_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV; + break; + case(BANK_PRESENT_CS0_CS1_CS2): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS2_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV; + break; + case(BANK_PRESENT_CS0_CS2_CS3): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS2_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV; + break; + case(BANK_PRESENT_CS0_CS2_CS3_CS4): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS2_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV; + break; + default: + mvOsPrintf("sdramDDr2OdtConfig: Invalid DRAM bank presence\n"); + return; + } + MV_REG_WRITE(DRAM_BUF_REG7, odtCtrlLow); + MV_REG_WRITE(DRAM_BUF_REG8, odtCtrlHigh); + MV_REG_WRITE(DRAM_BUF_REG9, dunitOdtCtrl); + return; +} +#endif /* defined(MV_INC_BOARD_DDIM) */ + +/******************************************************************************* +* mvDramIfWinSet - Set DRAM interface address decode window +* +* DESCRIPTION: +* This function sets DRAM interface address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* pAddrDecWin - SDRAM address window structure. +* +* OUTPUT: +* None +* +* RETURN: +* MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK +* otherwise. +*******************************************************************************/ +MV_STATUS mvDramIfWinSet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) +{ + MV_U32 baseReg=0,sizeReg=0; + MV_U32 baseToReg=0 , sizeToReg=0; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinSet: target %d is not SDRAM\n", target); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlaps with current enabled windows */ + if (MV_TRUE == sdramIfWinOverlap(target, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvDramIfWinSet: ERR. Target %d overlaps\n", target); + return MV_BAD_PARAM; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvDramIfWinSet:Error setting DRAM interface window %d."\ + "\nAddress 0x%08x is unaligned to size 0x%x.\n", + target, + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + /* read base register*/ + baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(target)); + + /* read size register */ + sizeReg = MV_REG_READ(SDRAM_SIZE_REG(target)); + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->addrWin.baseLow & SCBAR_BASE_MASK; + + /* Write to address decode Base Address Register */ + baseReg &= ~SCBAR_BASE_MASK; + baseReg |= baseToReg; + + /* Translate the given window size to register format */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, SCSR_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n",target); + return MV_BAD_PARAM; + } + + /* set size */ + sizeReg &= ~SCSR_SIZE_MASK; + /* Size is located at upper 16 bits */ + sizeReg |= (sizeToReg << SCSR_SIZE_OFFS); + + /* enable/Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + sizeReg |= SCSR_WIN_EN; + } + else + { + sizeReg &= ~SCSR_WIN_EN; + } + + /* 3) Write to address decode Base Address Register */ + MV_REG_WRITE(SDRAM_BASE_ADDR_REG(target), baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(SDRAM_SIZE_REG(target), sizeReg); + + return MV_OK; +} +/******************************************************************************* +* mvDramIfWinGet - Get DRAM interface address decode window +* +* DESCRIPTION: +* This function gets DRAM interface address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* +* OUTPUT: +* pAddrDecWin - SDRAM address window structure. +* +* RETURN: +* MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK +* otherwise. +*******************************************************************************/ +MV_STATUS mvDramIfWinGet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) +{ + MV_U32 baseReg,sizeReg; + MV_U32 sizeRegVal; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinGet: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* Read base and size registers */ + sizeReg = MV_REG_READ(SDRAM_SIZE_REG(target)); + baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(target)); + + sizeRegVal = (sizeReg & SCSR_SIZE_MASK) >> SCSR_SIZE_OFFS; + + pAddrDecWin->addrWin.size = ctrlRegToSize(sizeRegVal, + SCSR_SIZE_ALIGNMENT); + + /* Check if ctrlRegToSize returned OK */ + if (-1 == pAddrDecWin->addrWin.size) + { + mvOsPrintf("mvDramIfWinGet: size of target %d is Illigal\n", target); + return MV_ERROR; + } + + /* Extract base address */ + /* Base register [31:16] ==> baseLow[31:16] */ + pAddrDecWin->addrWin.baseLow = baseReg & SCBAR_BASE_MASK; + + pAddrDecWin->addrWin.baseHigh = 0; + + + if (sizeReg & SCSR_WIN_EN) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} +/******************************************************************************* +* mvDramIfWinEnable - Enable/Disable SDRAM address decode window +* +* DESCRIPTION: +* This function enable/Disable SDRAM address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR in case function parameter are invalid, MV_OK otherewise. +* +*******************************************************************************/ +MV_STATUS mvDramIfWinEnable(MV_TARGET target,MV_BOOL enable) +{ + MV_DRAM_DEC_WIN addrDecWin; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinEnable: target %d is Illigal\n", target); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + if (MV_OK != mvDramIfWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvDramIfWinEnable:ERR. Getting target %d failed.\n", + target); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == sdramIfWinOverlap(target, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode winNum window */ + MV_REG_BIT_SET(SDRAM_SIZE_REG(target), SCSR_WIN_EN); + } + else + { /* Overlap detected */ + mvOsPrintf("mvDramIfWinEnable: ERR. Target %d overlap detect\n", + target); + return MV_ERROR; + } + } + else + { /* Disable address decode winNum window */ + MV_REG_BIT_RESET(SDRAM_SIZE_REG(target), SCSR_WIN_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* sdramIfWinOverlap - Check if an address window overlap an SDRAM address window +* +* DESCRIPTION: +* This function scan each SDRAM address decode window to test if it +* overlapps the given address windoow +* +* INPUT: +* target - SDRAM target where the function skips checking. +* pAddrDecWin - The tested address window for overlapping with +* SDRAM windows. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlaps any enabled address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL sdramIfWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin) +{ + MV_TARGET targetNum; + MV_DRAM_DEC_WIN addrDecWin; + + for(targetNum = SDRAM_CS0; targetNum < MV_DRAM_MAX_CS ; targetNum++) + { + /* don't check our winNum or illegal targets */ + if (targetNum == target) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvDramIfWinGet(targetNum, &addrDecWin)) + { + mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n"); + return MV_ERROR; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + mvOsPrintf( + "sdramIfWinOverlap: Required target %d overlap winNum %d\n", + target, targetNum); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* mvDramIfBankSizeGet - Get DRAM interface bank size. +* +* DESCRIPTION: +* This function returns the size of a given DRAM bank. +* +* INPUT: +* bankNum - Bank number. +* +* OUTPUT: +* None. +* +* RETURN: +* DRAM bank size. If bank is disabled the function return '0'. In case +* or paramter is invalid, the function returns -1. +* +*******************************************************************************/ +MV_32 mvDramIfBankSizeGet(MV_U32 bankNum) +{ + MV_DRAM_DEC_WIN addrDecWin; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(bankNum)) + { + mvOsPrintf("mvDramIfBankBaseGet: bankNum %d is invalid\n", bankNum); + return -1; + } + /* Get window parameters */ + if (MV_OK != mvDramIfWinGet(bankNum, &addrDecWin)) + { + mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n"); + return -1; + } + + if (MV_TRUE == addrDecWin.enable) + { + return addrDecWin.addrWin.size; + } + else + { + return 0; + } +} + + +/******************************************************************************* +* mvDramIfSizeGet - Get DRAM interface total size. +* +* DESCRIPTION: +* This function get the DRAM total size. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* DRAM total size. In case or paramter is invalid, the function +* returns -1. +* +*******************************************************************************/ +MV_32 mvDramIfSizeGet(MV_VOID) +{ + MV_U32 totalSize = 0, bankSize = 0, bankNum; + + for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + bankSize = mvDramIfBankSizeGet(bankNum); + + if (-1 == bankSize) + { + mvOsPrintf("Dram: mvDramIfSizeGet error with bank %d \n",bankNum); + return -1; + } + else + { + totalSize += bankSize; + } + } + + DB(mvOsPrintf("Dram: Total DRAM size is 0x%x \n",totalSize)); + + return totalSize; +} + +/******************************************************************************* +* mvDramIfBankBaseGet - Get DRAM interface bank base. +* +* DESCRIPTION: +* This function returns the 32 bit base address of a given DRAM bank. +* +* INPUT: +* bankNum - Bank number. +* +* OUTPUT: +* None. +* +* RETURN: +* DRAM bank size. If bank is disabled or paramter is invalid, the +* function returns -1. +* +*******************************************************************************/ +MV_32 mvDramIfBankBaseGet(MV_U32 bankNum) +{ + MV_DRAM_DEC_WIN addrDecWin; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(bankNum)) + { + mvOsPrintf("mvDramIfBankBaseGet: bankNum %d is invalid\n", bankNum); + return -1; + } + /* Get window parameters */ + if (MV_OK != mvDramIfWinGet(bankNum, &addrDecWin)) + { + mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n"); + return -1; + } + + if (MV_TRUE == addrDecWin.enable) + { + return addrDecWin.addrWin.baseLow; + } + else + { + return -1; + } +} + + diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.h b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.h new file mode 100644 index 0000000..8bfa3e8 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIf.h @@ -0,0 +1,179 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDramIfh +#define __INCmvDramIfh + +/* includes */ +#include "ddr1_2/mvDramIfRegs.h" +#include "ddr1_2/mvDramIfConfig.h" +#include "ctrlEnv/mvCtrlEnvLib.h" + +/* defines */ +/* DRAM Timing parameters */ +#define SDRAM_TWR 15 /* ns tWr */ +#define SDRAM_TRFC_64_512M_AT_200MHZ 70 /* ns tRfc for dens 64-512 @ 200MHz */ +#define SDRAM_TRFC_64_512M 75 /* ns tRfc for dens 64-512 */ +#define SDRAM_TRFC_1G 120 /* ns tRfc for dens 1GB */ +#define SDRAM_TR2R_CYC 1 /* cycle for tR2r */ +#define SDRAM_TR2WW2R_CYC 1 /* cycle for tR2wW2r */ + +/* typedefs */ + +/* enumeration for memory types */ +typedef enum _mvMemoryType +{ + MEM_TYPE_SDRAM, + MEM_TYPE_DDR1, + MEM_TYPE_DDR2 +}MV_MEMORY_TYPE; + +/* enumeration for DDR1 supported CAS Latencies */ +typedef enum _mvDimmDdr1Cas +{ + DDR1_CL_1_5 = 0x02, + DDR1_CL_2 = 0x04, + DDR1_CL_2_5 = 0x08, + DDR1_CL_3 = 0x10, + DDR1_CL_4 = 0x40, + DDR1_CL_FAULT +} MV_DIMM_DDR1_CAS; + +/* enumeration for DDR2 supported CAS Latencies */ +typedef enum _mvDimmDdr2Cas +{ + DDR2_CL_3 = 0x08, + DDR2_CL_4 = 0x10, + DDR2_CL_5 = 0x20, + DDR2_CL_FAULT +} MV_DIMM_DDR2_CAS; + + +typedef struct _mvDramBankInfo +{ + MV_MEMORY_TYPE memoryType; /* DDR1, DDR2 or SDRAM */ + + /* DIMM dimensions */ + MV_U32 numOfRowAddr; + MV_U32 numOfColAddr; + MV_U32 dataWidth; + MV_U32 errorCheckType; /* ECC , PARITY..*/ + MV_U32 sdramWidth; /* 4,8,16 or 32 */ + MV_U32 errorCheckDataWidth; /* 0 - no, 1 - Yes */ + MV_U32 burstLengthSupported; + MV_U32 numOfBanksOnEachDevice; + MV_U32 suportedCasLatencies; + MV_U32 refreshInterval; + + /* DIMM timing parameters */ + MV_U32 minCycleTimeAtMaxCasLatPs; + MV_U32 minCycleTimeAtMaxCasLatMinus1Ps; + MV_U32 minCycleTimeAtMaxCasLatMinus2Ps; + MV_U32 minRowPrechargeTime; + MV_U32 minRowActiveToRowActive; + MV_U32 minRasToCasDelay; + MV_U32 minRasPulseWidth; + MV_U32 minWriteRecoveryTime; /* DDR2 only */ + MV_U32 minWriteToReadCmdDelay; /* DDR2 only */ + MV_U32 minReadToPrechCmdDelay; /* DDR2 only */ + MV_U32 minRefreshToActiveCmd; /* DDR2 only */ + + /* Parameters calculated from the extracted DIMM information */ + MV_U32 size; + MV_U32 deviceDensity; /* 16,64,128,256 or 512 Mbit */ + MV_U32 numberOfDevices; + + /* DIMM attributes (MV_TRUE for yes) */ + MV_BOOL registeredAddrAndControlInputs; + +}MV_DRAM_BANK_INFO; + +/* This structure describes CPU interface address decode window */ +typedef struct _mvDramIfDecWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ +}MV_DRAM_DEC_WIN; + +#include "ddr1_2/mvDram.h" + +/* mvDramIf.h API list */ +MV_VOID mvDramIfBasicAsmInit(MV_VOID); +MV_STATUS mvDramIfDetect(MV_U32 forcedCl); +MV_VOID _mvDramIfConfig(MV_VOID); + +MV_STATUS mvDramIfWinSet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin); +MV_STATUS mvDramIfWinGet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin); +MV_STATUS mvDramIfWinEnable(MV_TARGET target,MV_BOOL enable); +MV_32 mvDramIfBankSizeGet(MV_U32 bankNum); +MV_32 mvDramIfBankBaseGet(MV_U32 bankNum); +MV_32 mvDramIfSizeGet(MV_VOID); + +#if 0 +MV_STATUS mvDramIfMbusCtrlSet(MV_XBAR_TARGET *pPizzaArbArray); +MV_STATUS mvDramIfMbusToutSet(MV_U32 timeout, MV_BOOL enable); +#endif + +#endif /* __INCmvDramIfh */ diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfBasicInit.S b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfBasicInit.S new file mode 100644 index 0000000..f2a9365 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfBasicInit.S @@ -0,0 +1,988 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define MV_ASMLANGUAGE +#include "mvSysHwConfig.h" +#include "mvOsAsm.h" +#include "mvBoardEnvSpec.h" +#include "mvCpuIfRegs.h" +#include "mvDramIfConfig.h" +#include "mvDramIfRegs.h" +#include "pex/mvPexRegs.h" +#include "pci/mvPciRegs.h" +#include "mvCtrlEnvSpec.h" +#include "mvCtrlEnvAsm.h" +#include "cpu/mvCpuArm.h" +#include "mvCommon.h" + +/* defines */ + +#if !defined(MV_INC_BOARD_DDIM) +.globl dramBoot1 +dramBoot1: + .word 0 + +/****************************************************************************** +* +* +* +* +*******************************************************************************/ +#if defined(DB_PRPMC) || defined(DB_PEX_PCI) || defined(DB_MNG) + +/* PEX_PCI and PRPMC boards 256 MB*/ +#define STATIC_SDRAM0_BANK0_SIZE 0x0fff0001 +#define STATIC_SDRAM_CONFIG 0x03248400 +#define STATIC_SDRAM_MODE 0x62 +#define STATIC_DUNIT_CTRL_LOW 0x4041000 +#define STATIC_SDRAM_ADDR_CTRL 0x00000020 +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11602220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x0000030F +#define STATIC_SDRAM_ODT_CTRL_LOW 0x0 +#define STATIC_SDRAM_ODT_CTRL_HI 0x0 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0 +#define STATIC_SDRAM_EXT_MODE 0x0 + +#elif defined(DB_FPGA) + +/* FPGA DC boards 256 MB*/ +#define STATIC_SDRAM0_BANK0_SIZE 0x0fff0001 +#define STATIC_SDRAM_CONFIG 0x03208400 /* 32bit */ +#define STATIC_SDRAM_MODE 0x22 +#define STATIC_DUNIT_CTRL_LOW 0x03041000 +#define STATIC_SDRAM_ADDR_CTRL 0x00000020 +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11112220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x0000000D +#define STATIC_SDRAM_ODT_CTRL_LOW 0x0 +#define STATIC_SDRAM_ODT_CTRL_HI 0x0 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0 +#define STATIC_SDRAM_EXT_MODE 0x1 + +#elif defined(RD_88F6183GP) || defined(DB_CUSTOMER) + +/* Customer 1 DDR2 2 devices 512Mbit by 16 bit */ +#define STATIC_SDRAM0_BANK0_SIZE 0x07ff0001 +#define STATIC_SDRAM_CONFIG 0x03158400 +#define STATIC_SDRAM_MODE 0x452 +#define STATIC_DUNIT_CTRL_LOW 0x06041000 +#define STATIC_SDRAM_ADDR_CTRL 0x00000020 +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11912220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x00000502 +#define STATIC_SDRAM_ODT_CTRL_LOW 0x00010000 +#define STATIC_SDRAM_ODT_CTRL_HI 0x00000002 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x00000601 +#define STATIC_SDRAM_EXT_MODE 0x00000440 + + +#elif defined(RD_88F6183AP) + +/* DDR2 1 devices 512Mbit by 16 bit */ +#define STATIC_SDRAM0_BANK0_SIZE 0x03ff0001 +#define STATIC_SDRAM_CONFIG 0x1f154400 +#define STATIC_SDRAM_MODE 0x432 +#define STATIC_DUNIT_CTRL_LOW 0x04041000 +#define STATIC_SDRAM_ADDR_CTRL 0x00000020 +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11912220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x00000502 +#define STATIC_SDRAM_ODT_CTRL_LOW 0x00010000 +#define STATIC_SDRAM_ODT_CTRL_HI 0x00000002 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x00000601 +#define STATIC_SDRAM_EXT_MODE 0x00000440 + +/* 6082L MARVELL DIMM */ +#elif defined(DB_88F6082LBP) +#define STATIC_SDRAM0_BANK0_SIZE 0x07ff0001 +#define STATIC_SDRAM_CONFIG 0x7f158400 +#define STATIC_SDRAM_MODE 0x432 +#define STATIC_DUNIT_CTRL_LOW 0x04041040 +#define STATIC_SDRAM_ADDR_CTRL 0x00000020 +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11612220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x00000501 +#define STATIC_SDRAM_ODT_CTRL_LOW 0x00010000 +#define STATIC_SDRAM_ODT_CTRL_HI 0x00000002 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x00000a01 +#define STATIC_SDRAM_EXT_MODE 0x00000440 + +#elif defined(RD_88W8660_AP82S) + +/* Shark RD */ + +#if defined(MV_DRAM_32M) +#define STATIC_SDRAM0_BANK0_SIZE 0x01ff0001 +#define STATIC_SDRAM_ADDR_CTRL 0x00000010 +#elif defined(MV_DRAM_16M) + +#define STATIC_SDRAM0_BANK0_SIZE 0x00ff0001 +#define STATIC_SDRAM_ADDR_CTRL 0x00000000 + +#else +#error "NO DDR size selected" +#endif + +#define STATIC_SDRAM_CONFIG 0x03144400 +#define STATIC_SDRAM_MODE 0x62 +#define STATIC_DUNIT_CTRL_LOW 0x4041000 + +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11602220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x0000040b +#define STATIC_SDRAM_ODT_CTRL_LOW 0x0 +#define STATIC_SDRAM_ODT_CTRL_HI 0x0 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0 +#define STATIC_SDRAM_EXT_MODE 0x0 + +#elif defined(RD_88W8660) + +/* Shark RD */ +#define STATIC_SDRAM0_BANK0_SIZE 0x03ff0001 +#define STATIC_SDRAM_CONFIG 0x03144400 +#define STATIC_SDRAM_MODE 0x62 +#define STATIC_DUNIT_CTRL_LOW 0x4041000 +#define STATIC_SDRAM_ADDR_CTRL 0x00000010 +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11602220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x0000040b +#define STATIC_SDRAM_ODT_CTRL_LOW 0x0 +#define STATIC_SDRAM_ODT_CTRL_HI 0x0 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0 +#define STATIC_SDRAM_EXT_MODE 0x0 + +#else /* NAS */ + + +#if defined(RD_88F5182) + +#if defined(MV_88F5082) +#define STATIC_SDRAM0_BANK0_SIZE 0x3ff0001 +#define STATIC_SDRAM_ADDR_CTRL 0x20 +#else +#define STATIC_SDRAM0_BANK0_SIZE 0x7ff0001 +#define STATIC_SDRAM_ADDR_CTRL 0x20 +#endif + +#elif defined(RD_88F5182_3) + +#if defined(MV_88F5082) +#define STATIC_SDRAM0_BANK0_SIZE 0x3ff0001 +#define STATIC_SDRAM_ADDR_CTRL 0x20 +#else +#define STATIC_SDRAM0_BANK0_SIZE 0x7ff0001 +#define STATIC_SDRAM_ADDR_CTRL 0x20 +#endif + +#else + +#define STATIC_SDRAM0_BANK0_SIZE 0x1ff0001 +#define STATIC_SDRAM_ADDR_CTRL 0x0 + +#endif + +#if defined(MV_88F5082) +#define STATIC_SDRAM_CONFIG 0x3144400 +#else +#define STATIC_SDRAM_CONFIG 0x3148400 +#endif +#define STATIC_SDRAM_MODE 0x62 +#define STATIC_DUNIT_CTRL_LOW 0x4041000 +#define STATIC_SDRAM_TIME_CTRL_LOW 0x11602220 +#define STATIC_SDRAM_TIME_CTRL_HI 0x40c +#define STATIC_SDRAM_ODT_CTRL_LOW 0x0 +#define STATIC_SDRAM_ODT_CTRL_HI 0x0 +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0 +#define STATIC_SDRAM_EXT_MODE 0x0 + +#endif + + .globl _mvDramIfStaticInit +_mvDramIfStaticInit: + + mov r11, LR /* Save link register */ + mov r10, r2 + + /* If we boot from NAND jump to DRAM sddress */ + + mov r5, #1 + ldr r6, =dramBoot1 + str r5, [r6] /* We started executing from DRAM */ + + ldr r6, dramBoot1 + cmp r6, #0 + bne 1f + + + /* set all dram windows to 0 */ + mov r6, #0 + MV_REG_WRITE_ASM(r6, r5, 0x1504) + MV_REG_WRITE_ASM(r6, r5, 0x150c) + MV_REG_WRITE_ASM(r6, r5, 0x1514) + MV_REG_WRITE_ASM(r6, r5, 0x151c) + + /* set all dram configuration in temp registers */ + ldr r6, = STATIC_SDRAM0_BANK0_SIZE + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG0) + ldr r6, = STATIC_SDRAM_CONFIG + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG1) + ldr r6, = STATIC_SDRAM_MODE + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG2) + ldr r6, = STATIC_DUNIT_CTRL_LOW + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG3) + ldr r6, = STATIC_SDRAM_ADDR_CTRL + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG4) + ldr r6, = STATIC_SDRAM_TIME_CTRL_LOW + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG5) + ldr r6, = STATIC_SDRAM_TIME_CTRL_HI + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG6) + ldr r6, = STATIC_SDRAM_ODT_CTRL_LOW + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG7) + ldr r6, = STATIC_SDRAM_ODT_CTRL_HI + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG8) + ldr r6, = STATIC_SDRAM_DUNIT_ODT_CTRL + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG9) + ldr r6, = STATIC_SDRAM_EXT_MODE + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG10) + + mov sp, #0 + bl _mvDramIfConfig +1: + mov r2, r10 + mov PC, r11 /* r11 is saved link register */ + +#else /* #if !defined(MV_INC_BOARD_DDIM) */ + +.globl dramBoot1 +dramBoot1: + .word 0 + +/******************************************************************************* +* mvDramIfBasicInit - Basic initialization of DRAM interface +* +* DESCRIPTION: +* The function will initialize the DRAM for basic usage. The function +* will use the TWSI assembly API to extract DIMM parameters according +* to which DRAM interface will be initialized. +* The function referes to the following DRAM parameters: +* 1) DIMM is registered or not. +* 2) DIMM width detection. +* 3) DIMM density. +* +* INPUT: +* r3 - required size for initial DRAM. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +* Note: +* r4 holds I2C EEPROM address +* r5 holds SDRAM register base address +* r7 holds returned values +* r8 holds SDRAM various configuration registers value. +* r11 holds return function address. +*******************************************************************************/ +/* Setting the offsets of the I2C registers */ +#define NUM_OF_ROWS_OFFSET 3 +#define NUM_OF_COLS_OFFSET 4 +#define NUM_OF_RANKS 5 +#define SDRAM_WIDTH_OFFSET 13 +#define NUM_OF_BANKS_OFFSET 17 +#define SUPPORTED_CL_OFFSET 18 +#define DIMM_TYPE_INFO_OFFSET 20 /* DDR2 only */ +#define SDRAM_MODULES_ATTR_OFFSET 21 + +#define DRAM_DEV_DENSITY_128M 0x080 +#define DRAM_DEV_DENSITY_256M 0x100 +#define DRAM_DEV_DENSITY_512M 0x200 + .globl _mvDramIfBasicInit + .extern _i2cInit + +_mvDramIfBasicInit: + + mov r11, LR /* Save link register */ + + mov r5, #1 + ldr r8, =dramBoot1 + str r5, [r8] /* We started executing from DRAM */ + + /* If we boot from NAND jump to DRAM sddress */ + ldr r8, dramBoot1 + cmp r8, #0 + movne pc, r11 + + + + bl _i2cInit /* Initialize TWSI master */ + + /* Get default SDRAM Config values */ + MV_REG_READ_ASM (r8, r5, SDRAM_CONFIG_REG) + bic r8, r8, #SDRAM_DCFG_MASK + + + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r4, r5); + + /* Return if OrionN */ + ldr r5, =MV_5180_DEV_ID + cmp r4, r5 + beq cat_through_end + + /* Return if Orion1 */ + ldr r5, =MV_5181_DEV_ID + cmp r4, r5 + beq cat_through_end + + /* Return if Nas */ + ldr r5, =MV_5182_DEV_ID + cmp r4, r5 + beq cat_through_end + + /* Return if Shark */ + ldr r5, =MV_8660_DEV_ID + cmp r4, r5 + beq cat_through_end + + /* goto calcConfigReg if bigger than Orion2*/ + ldr r5, =MV_5281_DEV_ID + cmp r4, r5 + bne cat_through + +cat_through: + /* set cat through - for better performance - in orion2 b0 and higher*/ + orr r8, r8, #SDRAM_CATTHR_EN + +cat_through_end: + + + /* Get registered/non registered info from DIMM */ + bl _is_Registered + beq nonRegistered + +setRegistered: + orr r8, r8, #SDRAM_REGISTERED /* Set registered bit(17) */ + +nonRegistered: + /* Get SDRAM width */ + bl _get_width + + orr r6, r8, #SDRAM_DCFG_X16_DEV /* x16 devices */ + cmp r7, #16 + beq setConfigReg + + orr r6, r8, #SDRAM_DCFG_X8_DEV /* x8 devices */ + cmp r7, #8 + beq setConfigReg + + /* This is an error. return */ + b exit_ddrAutoConfig + +setConfigReg: + mov r8, r6 + ldr r6, =SDRAM_CONFIG_DV + orr r8, r8, r6 /* Add default settings */ + mov r6, r8 /* Do not swap r8 content */ + MV_REG_WRITE_ASM (r6, r5, SDRAM_CONFIG_REG) + + /* Set maximum CL supported by DIMM */ + bl _get_CAL + + /* r7 is DIMM supported CAS (e.g: 3 --> 0x1C) */ + clz r6, r7 + rsb r6, r6, #31 /* r6 = the bit number of MAX CAS supported */ + + /* Check the DDR version */ + tst r8, #SDRAM_DTYPE_DDR2 + bne casDdr2 + +casDdr1: + ldr r7, =3 /* stBurstDel field value */ + ldr r8, =0x52 /* Assuming MAX CL = 1.5 */ + cmp r6, #1 /* If CL = 1.5 break */ + beq setModeReg + + ldr r7, =3 /* stBurstDel field value */ + ldr r8, =0x22 /* Assuming MAX CL = 2 */ + cmp r6, #2 /* If CL = 2 break */ + beq setModeReg + + ldr r7, =4 /* stBurstDel field value */ + ldr r8, =0x62 /* Assuming MAX CL = 2.5 */ + cmp r6, #3 /* If CL = 2.5 break */ + beq setModeReg + + ldr r7, =4 /* stBurstDel field value */ + ldr r8, =0x32 /* Assuming MAX CL = 3 */ + cmp r6, #4 /* If CL = 3 break */ + beq setModeReg + + ldr r7, =5 /* stBurstDel field value */ + ldr r8, =0x42 /* Assuming MAX CL = 4 */ + cmp r6, #6 /* If CL = 4 break */ + b setModeReg + + b exit_ddrAutoConfig /* This is an error !! */ + +casDdr2: + ldr r7, =4 /* stBurstDel field value */ + ldr r8, =0x32 /* Assuming MAX CL = 3 */ + cmp r6, #3 /* If CL = 3 break */ + beq casDdr2Cont + + ldr r7, =5 /* stBurstDel field value */ + ldr r8, =0x42 /* Assuming MAX CL = 4 */ + cmp r6, #4 /* If CL = 4 break */ + beq casDdr2Cont + + /* CL 5 currently unsupported. We use CL 4 instead */ + ldr r7, =5 /* stBurstDel field value */ + ldr r8, =0x42 /* Assuming MAX CL = 5 */ + cmp r6, #5 /* If CL = 5 break */ + beq casDdr2Cont + + b exit_ddrAutoConfig /* This is an error !! */ +casDdr2Cont: + /* Write recovery for auto-precharge relevant only in DDR2 */ + orr r8, r8, #0x400 /* Default value */ + +setModeReg: + /* The CPU must not attempt to change the SDRAM Mode register setting */ + /* prior to DRAM controller completion of the DRAM initialization */ + /* sequence. To guarantee this restriction, it is recommended that */ + /* the CPU sets the SDRAM Operation register to NOP command, performs */ + /* read polling until the register is back in Normal operation value, */ + /* and then sets SDRAM Mode register to it's new value. */ + + /* write 'nop' to SDRAM operation */ + mov r6, #0x5 /* 'NOP' command */ + MV_REG_WRITE_ASM (r6, r5, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll1: + ldr r6, [r5] + cmp r6, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll1 + + /* Now its safe to write new value to SDRAM Mode register */ + MV_REG_WRITE_ASM (r8, r5, SDRAM_MODE_REG) + + /* Make the Dunit write the DRAM its new mode */ + mov r6, #0x3 /* Mode Register Set command */ + MV_REG_WRITE_ASM (r6, r5, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll2: + ldr r6, [r5] + cmp r6, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll2 + + /* Set Dunit control register according to max CL detected */ + /* If we use registered DIMM, add 1 to stBurstDel */ + MV_REG_READ_ASM (r6, r5, SDRAM_CONFIG_REG) + tst r6, #SDRAM_REGISTERED + beq setDunitReg + add r7, r7, #1 + +setDunitReg: + ldr r6, =SDRAM_DUNIT_CTRL_LOW_DV + orr r6, r6, r7, LSL #SDRAM_ST_BURST_DEL_OFFS + MV_REG_WRITE_ASM (r6, r5, SDRAM_DUNIT_CTRL_REG) + + + /* DIMM density configuration*/ + /* Density = (1 << (rowNum + colNum)) * dramWidth * dramBankNum */ +Density: + bl _getDensity + mov r8, r7 + mov r8, r8, LSR #20 /* Move density 20 bits to the right */ + /* For example 0x10000000 --> 0x1000 */ + + mov r6, #0x00 + cmp r8, #DRAM_DEV_DENSITY_128M + beq densCont + + mov r6, #0x10 + cmp r8, #DRAM_DEV_DENSITY_256M + beq densCont + + mov r6, #0x20 + cmp r8, #DRAM_DEV_DENSITY_512M + beq densCont + + /* This is an error. return */ + b exit_ddrAutoConfig + +densCont: + MV_REG_WRITE_ASM (r6, r5, SDRAM_ADDR_CTRL_REG) + + /* Config DDR2 registers (Extended mode, ODTs and pad calibration) */ + MV_REG_READ_ASM (r8, r5, SDRAM_CONFIG_REG) + tst r8, #SDRAM_DTYPE_DDR2 + beq _extModeODTEnd + + + /* Set DDR Extended Mode register for working with CS[0] */ + /* write 'nop' to SDRAM operation */ + mov r6, #0x5 /* 'NOP' command */ + MV_REG_WRITE_ASM (r6, r5, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll3: + ldr r6, [r5] + cmp r6, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll3 + + /* Now its safe to write new value to SDRAM Extended Mode register */ + ldr r6, =DDR_SDRAM_EXT_MODE_CS0_DV + MV_REG_WRITE_ASM (r6, r5, SDRAM_EXTENDED_MODE_REG) + + /* Make the Dunit write the DRAM its new extended mode */ + mov r6, #0x4 /* Extended Mode Register Set command */ + MV_REG_WRITE_ASM (r6, r5, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll4: + ldr r6, [r5] + cmp r6, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll4 + + /* ODT configuration is done for single bank CS[0] only */ + /* Config DDR2 On Die Termination (ODT) registers */ + ldr r6, =DDR2_ODT_CTRL_LOW_CS0_DV + MV_REG_WRITE_ASM (r6, r5, DDR2_SDRAM_ODT_CTRL_LOW_REG) + + ldr r6, =DDR2_ODT_CTRL_HIGH_CS0_DV + MV_REG_WRITE_ASM (r6, r5, DDR2_SDRAM_ODT_CTRL_HIGH_REG) + + ldr r6, =DDR2_DUNIT_ODT_CTRL_CS0_DV + MV_REG_WRITE_ASM (r6, r5, DDR2_DUNIT_ODT_CONTROL_REG) + + + /* we will check what device we are running and perform + Initialization according to device value */ + +_extModeODTEnd: + + /* Implement Guideline (GL# MEM-2) P_CAL Automatic Calibration */ + /* Does Not Work for Address/Control and Data Pads. */ + /* Relevant for: 88F5181-A1/B0 and 88F5281-A0 */ + + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r6, r5); + /* Read device revision */ + MV_CTRL_REV_GET_ASM(r8, r5); + + /* Continue if OrionN */ + ldr r5, =MV_5180_DEV_ID + cmp r6, r5 + bne 1f + b glMem2End +1: + + /* Continue if Orion1 and device revision B1 */ + ldr r5, =MV_5181_DEV_ID + cmp r6, r5 + bne 1f + + cmp r8, #MV_5181_B1_REV + bge glMem2End + b glMem2Start +1: + + /* Orion NAS */ + ldr r5, =MV_5182_DEV_ID + cmp r6, r5 + beq glMem2Start + + /* Orion Shark */ + ldr r5, =MV_8660_DEV_ID + cmp r6, r5 + beq glMem2Start + + b glMem2End + +glMem2Start: + + /* DDR SDRAM Address/Control Pads Calibration */ + MV_REG_READ_ASM (r6, r5, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + /* Set Bit [31] to make the register writable */ + orr r8, r6, #SDRAM_WR_EN + + MV_REG_WRITE_ASM (r8, r5, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + bic r6, r6, #SDRAM_WR_EN /* Make register read-only */ + bic r6, r6, #SDRAM_TUNE_EN /* Disable auto calibration */ + bic r6, r6, #SDRAM_DRVN_MASK /* Clear r5[5:0] */ + bic r6, r6, #SDRAM_DRVP_MASK /* Clear r5[11:6] */ + + /* Get the final N locked value of driving strength [22:17] */ + mov r5, r6 + mov r5, r5, LSL #9 + mov r5, r5, LSR #26 /* r5[5:0] = r6[22:17] */ + orr r5, r5, r5, LSL #6 /* r5[11:6] = r5[5:0] */ + + /* Write to both bits [5:0] and bits [11:6] */ + orr r6, r6, r5 + + MV_REG_WRITE_ASM (r6, r5, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + + /* DDR SDRAM Data Pads Calibration */ + MV_REG_READ_ASM (r6, r5, SDRAM_DATA_PADS_CAL_REG) + + /* Set Bit [31] to make the register writable */ + orr r8, r6, #SDRAM_WR_EN + + MV_REG_WRITE_ASM (r8, r5, SDRAM_DATA_PADS_CAL_REG) + + bic r6, r6, #SDRAM_WR_EN /* Make register read-only */ + bic r6, r6, #SDRAM_TUNE_EN /* Disable auto calibration */ + bic r6, r6, #SDRAM_DRVN_MASK /* Clear r5[5:0] */ + bic r6, r6, #SDRAM_DRVP_MASK /* Clear r5[11:6] */ + + /* Get the final N locked value of driving strength [22:17] */ + mov r5, r6 + mov r5, r5, LSL #9 + mov r5, r5, LSR #26 + orr r5, r5, r5, LSL #6 /* r5[5:0] = r6[22:17] */ + + /* Write to both bits [5:0] and bits [11:6] */ + orr r6, r6, r5 + + MV_REG_WRITE_ASM (r6, r5, SDRAM_DATA_PADS_CAL_REG) + +glMem2End: + /* Implement Guideline (GL# MEM-3) Drive Strength Value */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + + /* Get SDRAM Config value */ + MV_REG_READ_ASM (r8, r5, SDRAM_CONFIG_REG) + + /* Get DIMM type */ + tst r8, #SDRAM_DTYPE_DDR2 + beq ddr1StrengthVal + +ddr2StrengthVal: + ldr r4, =DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV + ldr r8, =DDR2_DATA_PAD_STRENGTH_TYPICAL_DV + b setDrvStrength +ddr1StrengthVal: + ldr r4, =DDR1_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV + ldr r8, =DDR1_DATA_PAD_STRENGTH_TYPICAL_DV + +setDrvStrength: + /* DDR SDRAM Address/Control Pads Calibration */ + MV_REG_READ_ASM (r6, r5, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + orr r6, r6, #SDRAM_WR_EN /* Make register writeable */ + + MV_REG_WRITE_ASM (r6, r5, SDRAM_ADDR_CTRL_PADS_CAL_REG) + HTOLL(r6,r5) + + bic r6, r6, #SDRAM_WR_EN /* Make register read-only */ + bic r6, r6, #SDRAM_PRE_DRIVER_STRENGTH_MASK + orr r6, r4, r6 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r6, r5, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + + /* DDR SDRAM Data Pads Calibration */ + MV_REG_READ_ASM (r6, r5, SDRAM_DATA_PADS_CAL_REG) + + orr r6, r6, #SDRAM_WR_EN /* Make register writeable */ + + MV_REG_WRITE_ASM (r6, r5, SDRAM_DATA_PADS_CAL_REG) + HTOLL(r6,r5) + + bic r6, r6, #SDRAM_WR_EN /* Make register read-only */ + bic r6, r6, #SDRAM_PRE_DRIVER_STRENGTH_MASK + orr r6, r8, r6 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r6, r5, SDRAM_DATA_PADS_CAL_REG) + + + /* Implement Guideline (GL# MEM-4) DQS Reference Delay Tuning */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + /* Get the "sample on reset" register for the DDR frequancy */ + +#if defined(MV_RUN_FROM_FLASH) + /* Calc the absolute address of the _cpuARMDDRCLK[] in the boot flash */ + ldr r7, = _cpuARMDDRCLK + ldr r4, =_start + ldr r4, [r4] + sub r7, r7, r4 + ldr r4, = Lrom_start_of_data + ldr r4, [r4] + add r7, r4, r7 +#else + /* Calc the absolute address of the _cpuARMDDRCLK[] in the boot flash */ + ldr r7, = _cpuARMDDRCLK + ldr r4, =_start + sub r7, r7, r4 + add r7, r7, #CFG_MONITOR_BASE +#endif + /* Get the "sample on reset" register for the DDR frequancy */ + MV_REG_READ_ASM (r4, r5, MPP_SAMPLE_AT_RESET) + ldr r5, =MSAR_ARMDDRCLCK_MASK + and r5, r4, r5 +#if 0 /* YOTAM TO BE FIX */ + mov r5, r5, LSR #MSAR_ARMDDRCLCK_OFFS +#endif + + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r6, r8); + + /* Continue if TC90 */ + ldr r8, =MV_1281_DEV_ID + cmp r6, r6 + beq armClkMsb + + /* Continue if Orion2 */ + ldr r8, =MV_5281_DEV_ID + cmp r6, r8 +#if 0 /* YOTAM TO BE FIX */ + bne 1f +#endif + +armClkMsb: +#if 0 /* YOTAM TO BE FIX */ + tst r4, #MSAR_ARMDDRCLCK_H_MASK + beq 1f + orr r5, r5, #BIT4 +1: + ldr r4, =MV_CPU_ARM_CLK_ELM_SIZE + mul r5, r4, r5 + add r7, r7, r5 + add r7, r7, #MV_CPU_ARM_CLK_DDR_OFF + ldr r5, [r7] +#endif + + /* Get SDRAM Config value */ + MV_REG_READ_ASM (r8, r4, SDRAM_CONFIG_REG) + + /* Get DIMM type */ + tst r8, #SDRAM_DTYPE_DDR2 + beq ddr1FtdllVal + +ddr2FtdllVal: + ldr r4, =FTDLL_DDR2_250MHZ + ldr r7, =_250MHz + cmp r5, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_200MHZ + ldr r7, =_200MHz + cmp r5, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_166MHZ + ldr r7, =_166MHz + cmp r5, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_133MHZ + b setFtdllReg + +ddr1FtdllVal: + ldr r4, =FTDLL_DDR1_200MHZ + ldr r7, =_200MHz + cmp r5, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR1_166MHZ + ldr r7, =_166MHz + cmp r5, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR1_133MHZ + ldr r7, =_133MHz + cmp r5, r7 + beq setFtdllReg + ldr r4, =0 + +setFtdllReg: + +#if !defined(MV_88W8660) && !defined(MV_88F6183) && !defined(MV_88F6183L) + MV_REG_READ_ASM (r8, r5, SDRAM_FTDLL_CONFIG_REG) + orr r8, r8, r4 + MV_REG_WRITE_ASM (r8, r5, SDRAM_FTDLL_CONFIG_REG) + bic r8, r8, #1 + MV_REG_WRITE_ASM (r8, r5, SDRAM_FTDLL_CONFIG_REG) +#endif /* !defined(MV_88W8660) && !defined(MV_88F6183) && !defined(MV_88F6183L)*/ + + +setTimingReg: + /* Set default Timing parameters */ + MV_REG_READ_ASM (r8, r5, SDRAM_CONFIG_REG) + tst r8, #SDRAM_DTYPE_DDR2 + bne ddr2TimeParam + +ddr1TimeParam: + ldr r6, =DDR1_TIMING_LOW_DV + MV_REG_WRITE_ASM (r6, r5, SDRAM_TIMING_CTRL_LOW_REG) + ldr r6, =DDR1_TIMING_HIGH_DV + MV_REG_WRITE_ASM (r6, r5, SDRAM_TIMING_CTRL_HIGH_REG) + b timeParamDone + +ddr2TimeParam: + ldr r6, =DDR2_TIMING_LOW_DV + MV_REG_WRITE_ASM (r6, r5, SDRAM_TIMING_CTRL_LOW_REG) + ldr r6, =DDR2_TIMING_HIGH_DV + MV_REG_WRITE_ASM (r6, r5, SDRAM_TIMING_CTRL_HIGH_REG) + +timeParamDone: + /* Open CS[0] window to requested size and enable it. Disable other */ + /* windows */ + ldr r6, =SCBAR_BASE_MASK + sub r3, r3, #1 + and r3, r3, r6 + orr r3, r3, #1 /* Enable bank */ + MV_REG_WRITE_ASM (r3, r5, SDRAM_SIZE_REG(0)) + ldr r6, =0 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(1)) + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(2)) + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(3)) + +exit_ddrAutoConfig: + mov PC, r11 /* r11 is saved link register */ + + +/***************************************************************************************/ +/* r4 holds I2C EEPROM address + * r7 holds I2C EEPROM offset parameter for i2cRead and its --> returned value + * r8 holds SDRAM various configuration registers value. + * r13 holds Link register + */ +/**************************/ +_getDensity: + mov r13, LR /* Save link register */ + + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #NUM_OF_ROWS_OFFSET /* offset 3 */ + bl _i2cRead + mov r8, r7 /* r8 save number of rows */ + + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #NUM_OF_COLS_OFFSET /* offset 4 */ + bl _i2cRead + add r8, r8, r7 /* r8 = number of rows + number of col */ + + mov r7, #0x1 + mov r8, r7, LSL r8 /* r8 = (1 << r8) */ + + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #SDRAM_WIDTH_OFFSET /* offset 13 */ + bl _i2cRead + mul r8, r7, r8 + + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #NUM_OF_BANKS_OFFSET /* offset 17 */ + bl _i2cRead + mul r7, r8, r7 + + mov PC, r13 + +/**************************/ +_get_width: + mov r13, LR /* Save link register */ + + /* Get SDRAM width (SPD offset 13) */ + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #SDRAM_WIDTH_OFFSET + bl _i2cRead /* result in r7 */ + + mov PC, r13 + +/**************************/ +_get_CAL: + mov r13, LR /* Save link register */ + + /* Set maximum CL supported by DIMM */ + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #SUPPORTED_CL_OFFSET /* offset 18 */ + bl _i2cRead + + mov PC, r13 + +/**************************/ +/* R8 - sdram configuration register. + * Return value in flag if no-registered then Z-flag is set + */ +_is_Registered: + mov r13, LR /* Save link register */ + + /* Get registered/non registered info from DIMM */ + tst r8, #SDRAM_DTYPE_DDR2 + bne regDdr2 + +regDdr1: + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #SDRAM_MODULES_ATTR_OFFSET + bl _i2cRead /* result in r7 */ + tst r7, #0x2 + b exit +regDdr2: + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #DIMM_TYPE_INFO_OFFSET + bl _i2cRead /* result in r7 */ + tst r7, #0x11 /* DIMM type = regular RDIMM (0x01) */ + /* or Mini-RDIMM (0x10) */ +exit: + mov PC, r13 + + +#endif diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.S b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.S new file mode 100644 index 0000000..e34ebbf --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.S @@ -0,0 +1,668 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvDramIfBasicAsm.s +* +* DESCRIPTION: +* Memory full detection and best timing configuration is done in +* C code. C runtime environment requires a stack. This module API +* initialize DRAM interface chip select 0 for basic functionality for +* the use of stack. +* The module API assumes DRAM information is stored in I2C EEPROM reside +* in a given I2C address MV_BOARD_DIMM0_I2C_ADDR. The I2C EEPROM +* internal data structure is assumed to be orgenzied in common DRAM +* vendor SPD structure. +* NOTE: DFCDL values are assumed to be already initialized prior to +* this module API activity. +* +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +/* includes */ +#define MV_ASMLANGUAGE +#include "mvOsAsm.h" +#include "mvSysHwConfig.h" +#include "mvDramIfRegs.h" +#include "mvDramIfConfig.h" +#include "mvCpuIfRegs.h" +#include "pex/mvPexRegs.h" +#include "pci/mvPciRegs.h" +#include "mvCtrlEnvSpec.h" +#include "mvCtrlEnvAsm.h" +#include "cpu/mvCpuArm.h" +#include "mvCommon.h" + +/* defines */ + +/* locals */ +.data +.globl _mvDramIfConfig + +.text + +/******************************************************************************* +* _mvDramIfConfig - Basic DRAM interface initialization. +* +* DESCRIPTION: +* The function will initialize the following DRAM parameters using the +* values prepared by mvDramIfDetect routine. Values are located +* in predefined registers. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ + +_mvDramIfConfig: + + /* Save register on stack */ + cmp sp, #0 + beq no_stack_s +save_on_stack: + stmdb sp!, {r1, r2, r3, r4, r7, r11} +no_stack_s: + + /* 1) Write to SDRAM coniguration register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG1) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_CONFIG_REG) + str r4, [r1] + + /* 2) Write Dunit control low register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG3) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_DUNIT_CTRL_REG) + str r4, [r1] + + /* 3) Write SDRAM address control register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG4) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_ADDR_CTRL_REG) + str r4, [r1] + + /* 4) Write SDRAM bank 0 size register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG0) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_SIZE_REG(0)) + str r4, [r1] + + /* 5) Write SDRAM open pages control register */ + ldr r1, =(INTER_REGS_BASE + SDRAM_OPEN_PAGE_CTRL_REG) + ldr r4, =SDRAM_OPEN_PAGES_CTRL_REG_DV + str r4, [r1] + + /* 6) Write SDRAM timing Low register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG5) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_TIMING_CTRL_LOW_REG) + str r4, [r1] + + /* 7) Write SDRAM timing High register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG6) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_TIMING_CTRL_HIGH_REG) + str r4, [r1] + + /* 8) Write SDRAM mode register */ + /* The CPU must not attempt to change the SDRAM Mode register setting */ + /* prior to DRAM controller completion of the DRAM initialization */ + /* sequence. To guarantee this restriction, it is recommended that */ + /* the CPU sets the SDRAM Operation register to NOP command, performs */ + /* read polling until the register is back in Normal operation value, */ + /* and then sets SDRAM Mode register to it’s new value. */ + + /* 8.1 write 'nop' to SDRAM operation */ + mov r4, #0x5 /* 'NOP' command */ + MV_REG_WRITE_ASM(r4, r1, SDRAM_OPERATION_REG) + + /* 8.2 poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll1: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll1 + + /* 8.3 Now its safe to write new value to SDRAM Mode register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG2) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_MODE_REG) + str r4, [r1] + + /* 8.4 Make the Dunit write the DRAM its new mode */ + mov r4, #0x3 /* Mode Register Set command */ + MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG) + + /* 8.5 poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll2: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll2 + +#ifndef DB_FPGA + /* Config DDR2 registers (Extended mode, ODTs and pad calibration) */ + MV_REG_READ_ASM (r4, r1, SDRAM_CONFIG_REG) + tst r4, #SDRAM_DTYPE_DDR2 + beq _extModeODTEnd +#endif /* DB_FPGA */ + + /* 9) Write SDRAM Extended mode register This operation should be */ + /* done for each memory bank */ + /* write 'nop' to SDRAM operation */ + mov r4, #0x5 /* 'NOP' command */ + MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll3: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll3 + + /* Now its safe to write new value to SDRAM Extended Mode register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG10) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_EXTENDED_MODE_REG) + str r4, [r1] + + /* Go over each of the Banks */ + ldr r3, =0 /* r3 = DRAM bank Num */ + +extModeLoop: + /* Set the SDRAM Operation Control to each of the DRAM banks */ + mov r2, r3 /* Do not swap the bank counter value */ + MV_REG_WRITE_ASM (r2, r1, SDRAM_OPERATION_CTRL_REG) + + /* Make the Dunit write the DRAM its new mode */ + mov r4, #0x4 /* Extended Mode Register Set command */ + MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll4: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll4 +#ifndef DB_FPGA + add r3, r3, #1 + cmp r3, #4 /* 4 = Number of banks */ + bne extModeLoop + +extModeEnd: + /* Config DDR2 On Die Termination (ODT) registers */ + /* Write SDRAM DDR2 ODT control low register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG7) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + DDR2_SDRAM_ODT_CTRL_LOW_REG) + str r4, [r1] + + /* Write SDRAM DDR2 ODT control high register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG8) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + DDR2_SDRAM_ODT_CTRL_HIGH_REG) + str r4, [r1] + + /* Write SDRAM DDR2 Dunit ODT control register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG9) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + DDR2_DUNIT_ODT_CONTROL_REG) + str r4, [r1] + +#endif /* DB_FPGA */ +_extModeODTEnd: +#ifndef DB_FPGA + /* Implement Guideline (GL# MEM-2) P_CAL Automatic Calibration */ + /* Does Not Work for Address/Control and Data Pads. */ + /* Relevant for: 88F5181-A1/B0 and 88F5281-A0 */ + + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r3, r1); + /* Read device revision */ + MV_CTRL_REV_GET_ASM(r2, r1); + + /* Continue if OrionN */ + ldr r1, =MV_5180_DEV_ID + cmp r3, r1 + bne 1f + b glMem2End +1: + /* Continue if Orion1 and device revision B1 */ + ldr r1, =MV_5181_DEV_ID + cmp r3, r1 + bne 1f + + cmp r2, #MV_5181_B1_REV + bge glMem2End + b glMem2Start +1: + + /* Orion NAS */ + ldr r1, =MV_5182_DEV_ID + cmp r3, r1 + beq glMem2Start + + /* Orion NAS */ + ldr r1, =MV_5082_DEV_ID + cmp r3, r1 + beq glMem2Start + + /* Orion Shark */ + ldr r1, =MV_8660_DEV_ID + cmp r3, r1 + beq glMem2Start + + b glMem2End + +glMem2Start: + + /* DDR SDRAM Address/Control Pads Calibration */ + MV_REG_READ_ASM (r3, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + /* Set Bit [31] to make the register writable */ + orr r2, r3, #SDRAM_WR_EN + + MV_REG_WRITE_ASM (r2, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + bic r3, r3, #SDRAM_WR_EN /* Make register read-only */ + bic r3, r3, #SDRAM_TUNE_EN /* Disable auto calibration */ + bic r3, r3, #SDRAM_DRVN_MASK /* Clear r1[5:0] */ + bic r3, r3, #SDRAM_DRVP_MASK /* Clear r1[11:6] */ + + /* Get the final N locked value of driving strength [22:17] */ + mov r1, r3 + mov r1, r1, LSL #9 + mov r1, r1, LSR #26 /* r1[5:0] = r3[22:17] */ + orr r1, r1, r1, LSL #6 /* r1[11:6] = r1[5:0] */ + + /* Write to both bits [5:0] and bits [11:6] */ + orr r3, r3, r1 + + MV_REG_WRITE_ASM (r3, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + + /* DDR SDRAM Data Pads Calibration */ + MV_REG_READ_ASM (r3, r1, SDRAM_DATA_PADS_CAL_REG) + + /* Set Bit [31] to make the register writable */ + orr r2, r3, #SDRAM_WR_EN + + MV_REG_WRITE_ASM (r2, r1, SDRAM_DATA_PADS_CAL_REG) + + bic r3, r3, #SDRAM_WR_EN /* Make register read-only */ + bic r3, r3, #SDRAM_TUNE_EN /* Disable auto calibration */ + bic r3, r3, #SDRAM_DRVN_MASK /* Clear r1[5:0] */ + bic r3, r3, #SDRAM_DRVP_MASK /* Clear r1[11:6] */ + + /* Get the final N locked value of driving strength [22:17] */ + mov r1, r3 + mov r1, r1, LSL #9 + mov r1, r1, LSR #26 + orr r1, r1, r1, LSL #6 /* r1[5:0] = r3[22:17] */ + + /* Write to both bits [5:0] and bits [11:6] */ + orr r3, r3, r1 + + MV_REG_WRITE_ASM (r3, r1, SDRAM_DATA_PADS_CAL_REG) + +glMem2End: + + + /* Implement Guideline (GL# MEM-3) Drive Strength Value */ + /* Relevant for: 88F5181-A1/B0/B1, 88F5281-A0/B0/C/D, 88F5182, */ + /* 88F5082, 88F5181L, 88F6082/L, 88F6183, 88F6183L */ + + /* Get SDRAM Config value */ + MV_REG_READ_ASM (r2, r1, SDRAM_CONFIG_REG) + + /* Get DIMM type */ + tst r2, #SDRAM_DTYPE_DDR2 + beq ddr1StrengthVal + +ddr2StrengthVal: + ldr r4, =DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV + ldr r2, =DDR2_DATA_PAD_STRENGTH_TYPICAL_DV + b setDrvStrength +ddr1StrengthVal: + ldr r4, =DDR1_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV + ldr r2, =DDR1_DATA_PAD_STRENGTH_TYPICAL_DV + +setDrvStrength: + /* DDR SDRAM Address/Control Pads Calibration */ + MV_REG_READ_ASM (r3, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + orr r3, r3, #SDRAM_WR_EN /* Make register writeable */ + + MV_REG_WRITE_ASM (r3, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + HTOLL(r3,r1) + + bic r3, r3, #SDRAM_WR_EN /* Make register read-only */ + bic r3, r3, #SDRAM_PRE_DRIVER_STRENGTH_MASK + orr r3, r4, r3 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r3, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + + /* DDR SDRAM Data Pads Calibration */ + MV_REG_READ_ASM (r3, r1, SDRAM_DATA_PADS_CAL_REG) + + orr r3, r3, #SDRAM_WR_EN /* Make register writeable */ + + MV_REG_WRITE_ASM (r3, r1, SDRAM_DATA_PADS_CAL_REG) + HTOLL(r3,r1) + + bic r3, r3, #SDRAM_WR_EN /* Make register read-only */ + bic r3, r3, #SDRAM_PRE_DRIVER_STRENGTH_MASK + orr r3, r2, r3 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r3, r1, SDRAM_DATA_PADS_CAL_REG) + +#if !defined(MV_88W8660) && !defined(MV_88F6183) && !defined(MV_88F6183L) + /* Implement Guideline (GL# MEM-4) DQS Reference Delay Tuning */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0/C/D, 88F5182 */ + /* 88F5082, 88F5181L, 88F6082/L */ + + /* Calc the absolute address of the _cpuARMDDRCLK[] in the boot flash */ + ldr r7, = _cpuARMDDRCLK + ldr r4, =_start + sub r7, r7, r4 + add r7, r7, #CFG_MONITOR_BASE + + /* Get the "sample on reset" register for the DDR frequancy */ + MV_REG_READ_ASM (r4, r1, MPP_SAMPLE_AT_RESET) + ldr r1, =MSAR_ARMDDRCLCK_MASK + and r1, r4, r1 +#if 0 /* YOTAM TO BE FIX */ + mov r1, r1, LSR #MSAR_ARMDDRCLCK_OFFS +#endif + + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r3, r2); + + /* Continue if TC90 */ + ldr r2, =MV_1281_DEV_ID + cmp r3, r2 + beq armClkMsb + + /* Continue if Orion2 */ + ldr r2, =MV_5281_DEV_ID + cmp r3, r2 +#if 0 /* YOTAM TO BE FIX */ + bne 1f +#endif + +armClkMsb: +#if 0 /* YOTAM TO BE FIX */ + tst r4, #MSAR_ARMDDRCLCK_H_MASK + beq 1f + orr r1, r1, #BIT4 +1: + ldr r4, =MV_CPU_ARM_CLK_ELM_SIZE + mul r1, r4, r1 + add r7, r7, r1 + add r7, r7, #MV_CPU_ARM_CLK_DDR_OFF + ldr r1, [r7] +#endif + + /* Get SDRAM Config value */ + MV_REG_READ_ASM (r2, r4, SDRAM_CONFIG_REG) + + /* Get DIMM type */ + tst r2, #SDRAM_DTYPE_DDR2 + beq ddr1FtdllVal + +ddr2FtdllVal: + ldr r2, =MV_5281_DEV_ID + cmp r3, r2 + bne 2f + MV_CTRL_REV_GET_ASM(r3, r2) + cmp r3, #MV_5281_D0_REV + beq orin2_d0_ddr2_ftdll_val + cmp r3, #MV_5281_D1_REV + beq orin2_d1_ddr2_ftdll_val + cmp r3, #MV_5281_D2_REV + beq orin2_d1_ddr2_ftdll_val + b ddr2_default_val + +/* Set Orion 2 D1 ftdll values for DDR2 */ +orin2_d1_ddr2_ftdll_val: + ldr r4, =FTDLL_DDR2_250MHZ_5281_D1 + ldr r7, =_250MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_200MHZ_5281_D1 + ldr r7, =_200MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_166MHZ_5281_D0 + ldr r7, =_166MHz + cmp r1, r7 + beq setFtdllReg + b ddr2_default_val + +/* Set Orion 2 D0 ftdll values for DDR2 */ +orin2_d0_ddr2_ftdll_val: + ldr r4, =FTDLL_DDR2_250MHZ_5281_D0 + ldr r7, =_250MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_200MHZ_5281_D0 + ldr r7, =_200MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_166MHZ_5281_D0 + ldr r7, =_166MHz + cmp r1, r7 + beq setFtdllReg + b ddr2_default_val +2: + ldr r2, =MV_5182_DEV_ID + cmp r3, r2 + bne 3f + +/* Set Orion nas ftdll values for DDR2 */ +orin_nas_ftdll_val: + ldr r4, =FTDLL_DDR2_166MHZ_5182 + ldr r7, =_166MHz + cmp r1, r7 + beq setFtdllReg + +/* default values for all other devices */ +3: +ddr2_default_val: + ldr r4, =FTDLL_DDR2_250MHZ + ldr r7, =_250MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_200MHZ + ldr r7, =_200MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_166MHZ + ldr r7, =_166MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR2_133MHZ + ldr r7, =_133MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =0 + b setFtdllReg + +ddr1FtdllVal: + ldr r2, =MV_5281_DEV_ID + cmp r3, r2 + bne 2f + MV_CTRL_REV_GET_ASM(r3, r2) + cmp r3, #MV_5281_D0_REV + bge orin2_ddr1_ftdll_val + b ddr1_default_val + +/* Set Orion 2 D0 and above ftdll values for DDR1 */ +orin2_ddr1_ftdll_val: + ldr r4, =FTDLL_DDR1_200MHZ_5281_D0 + ldr r7, =_200MHz + cmp r1, r7 + beq setFtdllReg + ldr r4, =FTDLL_DDR1_166MHZ_5281_D0 + ldr r7, =_166MHz + cmp r1, r7 + beq setFtdllReg + b ddr1_default_val +2: + ldr r2, =MV_5181_DEV_ID + cmp r3, r2 + bne 3f + MV_CTRL_REV_GET_ASM(r3, r2) + cmp r3, #MV_5181_B1_REV + bge orin1_ddr1_ftdll_val + b ddr1_default_val + +/* Set Orion 1 ftdll values for DDR1 */ +orin1_ddr1_ftdll_val: + ldr r4, =FTDLL_DDR1_166MHZ_5181_B1 + ldr r7, =_166MHz + cmp r1, r7 + beq setFtdllReg +3: +ddr1_default_val: + ldr r4, =FTDLL_DDR1_133MHZ + ldr r7, =_133MHz + cmp r1, r7 + beq setFtdllReg + + ldr r4, =FTDLL_DDR1_166MHZ + ldr r7, =_166MHz + cmp r1, r7 + beq setFtdllReg + + ldr r4, =FTDLL_DDR1_200MHZ + ldr r7, =_200MHz + cmp r1, r7 + beq setFtdllReg + + ldr r4, =0 + +setFtdllReg: + + MV_REG_WRITE_ASM (r4, r1, SDRAM_FTDLL_CONFIG_REG) + HTOLL(r4,r1) + bic r4, r4, #1 + MV_REG_WRITE_ASM (r4, r1, SDRAM_FTDLL_CONFIG_REG) + +#endif /* !defined(MV_88W8660) && !defined(MV_88F6183) && !defined(MV_88F6183L) */ +#endif /* DB_FPGA */ + +restoreTmpRegs: + /* Restore the registers we used to save the DDR detect values */ + + ldr r4, =DRAM_BUF_REG0_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG0) + + ldr r4, =DRAM_BUF_REG1_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG1) + + ldr r4, =DRAM_BUF_REG2_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG2) + + ldr r4, =DRAM_BUF_REG3_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG3) + + ldr r4, =DRAM_BUF_REG4_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG4) + + ldr r4, =DRAM_BUF_REG5_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG5) + + ldr r4, =DRAM_BUF_REG6_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG6) + + ldr r4, =DRAM_BUF_REG7_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG7) + + ldr r4, =DRAM_BUF_REG8_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG8) + + ldr r4, =DRAM_BUF_REG9_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG9) + + ldr r4, =DRAM_BUF_REG10_DV + MV_REG_WRITE_ASM (r4, r1, DRAM_BUF_REG10) + + + /* Restore registers */ + /* Save register on stack */ + cmp sp, #0 + beq no_stack_l +load_from_stack: + ldmia sp!, {r1, r2, r3, r4, r7, r11} +no_stack_l: + + mov pc, lr + diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.h b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.h new file mode 100644 index 0000000..a7c6644 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfConfig.h @@ -0,0 +1,192 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDramIfConfigh +#define __INCmvDramIfConfigh + +/* includes */ + +/* defines */ + +/* registers defaults values */ + +#define SDRAM_CONFIG_DV \ + (SDRAM_PERR_WRITE | \ + SDRAM_SRMODE | \ + SDRAM_SRCLK_GATED) + +#define SDRAM_DUNIT_CTRL_LOW_DV \ + (SDRAM_CTRL_POS_RISE | \ + SDRAM_CLK1DRV_NORMAL | \ + SDRAM_LOCKEN_ENABLE) + +#define SDRAM_ADDR_CTRL_DV 0 + +#define SDRAM_TIMING_CTRL_LOW_REG_DV \ + ((0x2 << SDRAM_TRCD_OFFS) | \ + (0x2 << SDRAM_TRP_OFFS) | \ + (0x1 << SDRAM_TWR_OFFS) | \ + (0x0 << SDRAM_TWTR_OFFS) | \ + (0x5 << SDRAM_TRAS_OFFS) | \ + (0x1 << SDRAM_TRRD_OFFS)) +/* TRFC 0x27, TW2W 0x1 */ +#define SDRAM_TIMING_CTRL_HIGH_REG_DV (( 0x7 << SDRAM_TRFC_OFFS ) |\ + ( 0x2 << SDRAM_TRFC_EXT_OFFS) |\ + ( 0x1 << SDRAM_TW2W_OFFS)) + +#define SDRAM_OPEN_PAGES_CTRL_REG_DV SDRAM_OPEN_PAGE_EN + +/* DDR2 ODT default register values */ + +/* Presence Ctrl Low Ctrl High Dunit Ctrl Ext Mode */ +/* CS0 0x84210000 0x00000000 0x0000780F 0x00000440 */ +/* CS0+CS1 0x84210000 0x00000000 0x0000780F 0x00000440 */ +/* CS0+CS2 0x030C030C 0x00000000 0x0000740F 0x00000404 */ +/* CS0+CS1+CS2 0x030C030C 0x00000000 0x0000740F 0x00000404 */ +/* CS0+CS2+CS3 0x030C030C 0x00000000 0x0000740F 0x00000404 */ +/* CS0+CS1+CS2+CS3 0x030C030C 0x00000000 0x0000740F 0x00000404 */ + +#define DDR2_ODT_CTRL_LOW_CS0_DV 0x84210000 +#define DDR2_ODT_CTRL_HIGH_CS0_DV 0x00000000 +#define DDR2_DUNIT_ODT_CTRL_CS0_DV 0x0000780F +#define DDR_SDRAM_EXT_MODE_CS0_DV 0x00000440 + +#define DDR2_ODT_CTRL_LOW_CS0_CS2_DV 0x030C030C +#define DDR2_ODT_CTRL_HIGH_CS0_CS2_DV 0x00000000 +#define DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV 0x0000740F +#define DDR_SDRAM_EXT_MODE_CS0_CS2_DV 0x00000404 + + +/* DDR SDRAM Adderss/Control and Data Pads Calibration default values */ +#define DDR1_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV \ + (1 << SDRAM_PRE_DRIVER_STRENGTH_OFFS) +#define DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV \ + (3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS) + + +#define DDR1_DATA_PAD_STRENGTH_TYPICAL_DV \ + (1 << SDRAM_PRE_DRIVER_STRENGTH_OFFS) +#define DDR2_DATA_PAD_STRENGTH_TYPICAL_DV \ + (3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS) + +/* DDR SDRAM Mode Register default value */ +#define DDR1_MODE_REG_DV 0x00000000 +#define DDR2_MODE_REG_DV 0x00000400 + +/* DDR SDRAM Timing parameter default values */ +#define DDR1_TIMING_LOW_DV 0x11602220 +#define DDR1_TIMING_HIGH_DV 0x0000000d + +#define DDR2_TIMING_LOW_DV 0x11812220 +#define DDR2_TIMING_HIGH_DV 0x0000030f + +/* For Guideline (GL# MEM-4) DQS Reference Delay Tuning */ +#define FTDLL_DDR1_166MHZ ((0x1 << 0) | \ + (0x7F<< 12) | \ + (0x1 << 22)) + +#define FTDLL_DDR1_133MHZ FTDLL_DDR1_166MHZ + +#define FTDLL_DDR1_200MHZ ((0x1 << 0) | \ + (0x1 << 12) | \ + (0x3 << 14) | \ + (0x1 << 18) | \ + (0x1 << 22)) + + +#define FTDLL_DDR2_166MHZ ((0x1 << 0) | \ + (0x1 << 12) | \ + (0x1 << 14) | \ + (0x1 << 16) | \ + (0x1 << 19) | \ + (0xF << 20)) + +#define FTDLL_DDR2_133MHZ FTDLL_DDR2_166MHZ + +#define FTDLL_DDR2_200MHZ ((0x1 << 0) | \ + (0x1 << 12) | \ + (0x1 << 14) | \ + (0x1 << 16) | \ + (0x1 << 19) | \ + (0xF << 20)) + +#define FTDLL_DDR2_250MHZ 0x445001 + +/* Orion 1 B1 and above */ +#define FTDLL_DDR1_166MHZ_5181_B1 0x45D001 + +/* Orion nas */ +#define FTDLL_DDR2_166MHZ_5182 0x597001 + +/* Orion 2 D0 and above */ +#define FTDLL_DDR1_166MHZ_5281_D0 0x8D0001 +#define FTDLL_DDR1_200MHZ_5281_D0 0x8D0001 +#define FTDLL_DDR2_166MHZ_5281_D0 0x485001 +#define FTDLL_DDR2_200MHZ_5281_D0 0x485001 +#define FTDLL_DDR2_250MHZ_5281_D0 0x445001 +#define FTDLL_DDR2_200MHZ_5281_D1 0x995001 +#define FTDLL_DDR2_250MHZ_5281_D1 0x984801 + +#endif /* __INCmvDramIfh */ diff --git a/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfRegs.h b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfRegs.h new file mode 100644 index 0000000..e9cd7c4 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr1_2/mvDramIfRegs.h @@ -0,0 +1,306 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDramIfRegsh +#define __INCmvDramIfRegsh + + +/* DDR SDRAM Controller Address Decode Registers */ +/* SDRAM CSn Base Address Register (SCBAR) */ +#define SDRAM_BASE_ADDR_REG(csNum) (0x1500 + (csNum * 8)) +#define SCBAR_BASE_OFFS 16 +#define SCBAR_BASE_MASK (0xffff << SCBAR_BASE_OFFS) +#define SCBAR_BASE_ALIGNMENT 0x10000 + +/* SDRAM CSn Size Register (SCSR) */ +#define SDRAM_SIZE_REG(csNum) (0x1504 + (csNum * 8)) +#define SCSR_WIN_EN BIT0 +#define SCSR_SIZE_OFFS 16 +#define SCSR_SIZE_MASK (0xffff << SCSR_SIZE_OFFS) +#define SCSR_SIZE_ALIGNMENT 0x10000 + +/* configuration register */ +#define SDRAM_CONFIG_REG 0x1400 +#define SDRAM_REFRESH_OFFS 0 +#define SDRAM_REFRESH_MAX 0x3000 +#define SDRAM_REFRESH_MASK (SDRAM_REFRESH_MAX << SDRAM_REFRESH_OFFS) +#define SDRAM_DWIDTH_OFFS 14 +#define SDRAM_DWIDTH_MASK (3 << SDRAM_DWIDTH_OFFS) +#define SDRAM_DWIDTH_16BIT (1 << SDRAM_DWIDTH_OFFS) +#define SDRAM_DWIDTH_32BIT (2 << SDRAM_DWIDTH_OFFS) +#define SDRAM_DTYPE_OFFS 16 +#define SDRAM_DTYPE_MASK (1 << SDRAM_DTYPE_OFFS) +#define SDRAM_DTYPE_DDR1 (0 << SDRAM_DTYPE_OFFS) +#define SDRAM_DTYPE_DDR2 (1 << SDRAM_DTYPE_OFFS) +#define SDRAM_REGISTERED (1 << 17) +#define SDRAM_PERR_OFFS 18 +#define SDRAM_PERR_MASK (1 << SDRAM_PERR_OFFS) +#define SDRAM_PERR_NO_WRITE (0 << SDRAM_PERR_OFFS) +#define SDRAM_PERR_WRITE (1 << SDRAM_PERR_OFFS) +#define SDRAM_DCFG_OFFS 20 +#define SDRAM_DCFG_MASK (0x3 << SDRAM_DCFG_OFFS) +#define SDRAM_DCFG_X16_DEV (1 << SDRAM_DCFG_OFFS) +#define SDRAM_DCFG_X8_DEV (2 << SDRAM_DCFG_OFFS) +#define SDRAM_SRMODE (1 << 24) +#define SDRAM_SRCLK_OFFS 25 +#define SDRAM_SRCLK_MASK (1 << SDRAM_SRCLK_OFFS) +#define SDRAM_SRCLK_KEPT (0 << SDRAM_SRCLK_OFFS) +#define SDRAM_SRCLK_GATED (1 << SDRAM_SRCLK_OFFS) +#define SDRAM_CATTH_OFFS 26 +#define SDRAM_CATTHR_EN (1 << SDRAM_CATTH_OFFS) + + +/* dunit control register */ +#define SDRAM_DUNIT_CTRL_REG 0x1404 +#define SDRAM_CTRL_POS_OFFS 6 +#define SDRAM_CTRL_POS_FALL (0 << SDRAM_CTRL_POS_OFFS) +#define SDRAM_CTRL_POS_RISE (1 << SDRAM_CTRL_POS_OFFS) +#define SDRAM_CLK1DRV_OFFS 12 +#define SDRAM_CLK1DRV_MASK (1 << SDRAM_CLK1DRV_OFFS) +#define SDRAM_CLK1DRV_HIGH_Z (0 << SDRAM_CLK1DRV_OFFS) +#define SDRAM_CLK1DRV_NORMAL (1 << SDRAM_CLK1DRV_OFFS) +#define SDRAM_LOCKEN_OFFS 18 +#define SDRAM_LOCKEN_MASK (1 << SDRAM_LOCKEN_OFFS) +#define SDRAM_LOCKEN_DISABLE (0 << SDRAM_LOCKEN_OFFS) +#define SDRAM_LOCKEN_ENABLE (1 << SDRAM_LOCKEN_OFFS) +#define SDRAM_ST_BURST_DEL_OFFS 24 +#define SDRAM_ST_BURST_DEL_MAX 0xf +#define SDRAM_ST_BURST_DEL_MASK (SDRAM_ST_BURST_DEL_MAX< busClkPs) + { + mvOsPrintf("Dram: ERR. Bank %d doesn't support memory clock!!!\n", i); + return MV_ERROR; + } + + /* All banks must support registry in order to activate it */ + if(bankInfo[i].registeredAddrAndControlInputs != + bankInfo[0].registeredAddrAndControlInputs) + { + mvOsPrintf("Dram: ERR. different Registered settings !!!\n"); + return MV_ERROR; + } + + /* All banks must support same ECC mode */ + if(bankInfo[i].errorCheckType != + bankInfo[0].errorCheckType) + { + mvOsPrintf("Dram: ERR. different ECC settings !!!\n"); + return MV_ERROR; + } + + } + else + { + if( i == 0 ) /* bank 0 doesn't exist */ + { + mvOsPrintf("Dram: ERR. Fail to detect bank 0 !!!\n"); + return MV_ERROR; + } + else + { + DB(mvOsPrintf("Dram: Could not find bank %d\n", i)); + bankInfo[i].size = 0; /* Mark this bank as non exist */ + } + } + } + + if (bankInfo[SDRAM_CS0].size < bankInfo[SDRAM_CS2].size) + { + MV_DRAM_CS_order[0] = SDRAM_CS2; + MV_DRAM_CS_order[1] = SDRAM_CS3; + MV_DRAM_CS_order[2] = SDRAM_CS0; + MV_DRAM_CS_order[3] = SDRAM_CS1; + DRAM_CS_Order[0] = SDRAM_CS2; + DRAM_CS_Order[1] = SDRAM_CS3; + DRAM_CS_Order[2] = SDRAM_CS0; + DRAM_CS_Order[3] = SDRAM_CS1; + + } + else + { + MV_DRAM_CS_order[0] = SDRAM_CS0; + MV_DRAM_CS_order[1] = SDRAM_CS1; + MV_DRAM_CS_order[2] = SDRAM_CS2; + MV_DRAM_CS_order[3] = SDRAM_CS3; + DRAM_CS_Order[0] = SDRAM_CS0; + DRAM_CS_Order[1] = SDRAM_CS1; + DRAM_CS_Order[2] = SDRAM_CS2; + DRAM_CS_Order[3] = SDRAM_CS3; + } + + for(j = 0; j < MV_DRAM_MAX_CS; j++) + { + i = MV_DRAM_CS_order[j]; + + if (0 == bankInfo[i].size) + continue; + + /* Init the CPU window decode */ + /* Note that the Dimm width might be different then the device DRAM width */ +#ifdef MV78XX0 + temp = MV_REG_READ(SDRAM_CONFIG_REG); + deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_32BIT )? 32 : 64; +#else + deviceW = 16 /* KW family */; +#endif + dimmW = bankInfo[0].dataWidth - (bankInfo[0].dataWidth % 16); + size = ((bankInfo[i].size << 20) / (dimmW/deviceW)); + + /* We can not change DRAM window settings while excecuting */ + /* code from it. That is why we skip the DRAM CS[0], saving */ + /* it to the ROM configuration routine */ + + numOfAllDevices += bankInfo[i].numberOfDevices; + if (i == MV_DRAM_CS_order[0]) + { + MV_U32 sizeToReg; + /* Translate the given window size to register format */ + sizeToReg = ctrlSizeToReg(size, SCSR_SIZE_ALIGNMENT); + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("DRAM: mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n" + ,i); + return MV_BAD_PARAM; + } + + DB(mvOsPrintf("Dram: Bank 0 Size - %x\n",sizeToReg);) + sizeToReg = (sizeToReg << SCSR_SIZE_OFFS); + sizeToReg |= SCSR_WIN_EN; + MV_REG_WRITE(DRAM_BUF_REG0, sizeToReg); + } + else + { + dramDecWin.addrWin.baseLow = base; + dramDecWin.addrWin.size = size; + dramDecWin.enable = MV_TRUE; + DB(mvOsPrintf("Dram: Enable window %d base 0x%x, size=0x%x\n",i, base, size)); + + /* Check if the DRAM size is more then 3GByte */ + if (base < 0xC0000000) + { + DB(mvOsPrintf("Dram: Enable window %d base 0x%x, size=0x%x\n",i, base, size)); + if (MV_OK != mvCpuIfTargetWinSet(i, &dramDecWin)) + { + mvOsPrintf("Dram: ERR. Fail to set bank %d!!!\n", SDRAM_CS0 + i); + return MV_ERROR; + } + } + } + + base += size; + + /* update the suportedCasLatencies mask */ + bankInfo[0].suportedCasLatencies &= bankInfo[i].suportedCasLatencies; + } + + /* calculate minimum CAS */ + minCas = minCasCalc(&bankInfo[0], &bankInfo[2], busClk, forcedCl); + if (0 == minCas) + { + mvOsOutput("Dram: Warn: Could not find CAS compatible to SysClk %dMhz\n", + (busClk / 1000000)); + + minCas = DDR2_CL_4; /* Continue with this CAS */ + mvOsPrintf("Set default CAS latency 4\n"); + } + + /* calc SDRAM_CONFIG_REG and save it to temp register */ + temp = sdramConfigRegCalc(&bankInfo[0],&bankInfo[2], busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramConfigRegCalc failed !!!\n"); + return MV_ERROR; + } + + /* check if ECC is enabled by the user */ + if(eccDisable) + { + /* turn off ECC*/ + temp &= ~BIT18; + } + DB(mvOsPrintf("Dram: sdramConfigRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG1, temp); + + /* calc SDRAM_MODE_REG and save it to temp register */ + temp = sdramModeRegCalc(minCas); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: sdramModeRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG2, temp); + + /* calc SDRAM_EXTENDED_MODE_REG and save it to temp register */ + temp = sdramExtModeRegCalc(&bankInfo[0], busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramExtModeRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: sdramExtModeRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG10, temp); + + /* calc D_UNIT_CONTROL_LOW and save it to temp register */ + TTMode = MV_FALSE; + DB(mvOsPrintf("Dram: numOfAllDevices = %x\n",numOfAllDevices);) + if( (numOfAllDevices > 9) && (bankInfo[0].registeredAddrAndControlInputs == MV_FALSE) ) + { + if ( ( (numOfAllDevices > 9) && (busClk > MV_BOARD_SYSCLK_200MHZ) ) || + (numOfAllDevices > 18) ) + { + mvOsOutput("Enable 2T "); + TTMode = MV_TRUE; + } + } + + temp = dunitCtrlLowRegCalc(&bankInfo[0], minCas, busClk, TTMode ); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. dunitCtrlLowRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: dunitCtrlLowRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG3, temp); + + /* calc D_UNIT_CONTROL_HIGH and save it to temp register */ + temp = dunitCtrlHighRegCalc(busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. dunitCtrlHighRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: dunitCtrlHighRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG13, temp); + + /* calc SDRAM_ADDR_CTRL_REG and save it to temp register */ + temp = sdramAddrCtrlRegCalc(&bankInfo[0],&bankInfo[2]); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramAddrCtrlRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: sdramAddrCtrlRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG4, temp); + + /* calc SDRAM_TIMING_CTRL_LOW_REG and save it to temp register */ + temp = sdramTimeCtrlLowRegCalc(&bankInfo[0], minCas, busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramTimeCtrlLowRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: sdramTimeCtrlLowRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG5, temp); + + /* calc SDRAM_TIMING_CTRL_HIGH_REG and save it to temp register */ + temp = sdramTimeCtrlHighRegCalc(&bankInfo[0], busClk); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramTimeCtrlHighRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: sdramTimeCtrlHighRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG6, temp); + + sdramDDr2OdtConfig(bankInfo); + + /* calc DDR2_SDRAM_TIMING_LOW_REG and save it to temp register */ + temp = sdramDdr2TimeLoRegCalc(minCas); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramDdr2TimeLoRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: sdramDdr2TimeLoRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG11, temp); + + /* calc DDR2_SDRAM_TIMING_HIGH_REG and save it to temp register */ + temp = sdramDdr2TimeHiRegCalc(minCas); + if(-1 == temp) + { + mvOsPrintf("Dram: ERR. sdramDdr2TimeHiRegCalc failed !!!\n"); + return MV_ERROR; + } + DB(mvOsPrintf("Dram: sdramDdr2TimeHiRegCalc - %x\n",temp);) + MV_REG_WRITE(DRAM_BUF_REG12, temp); +#endif + + /* Note that DDR SDRAM Address/Control and Data pad calibration */ + /* settings is done in mvSdramIfConfig.s */ + + return MV_OK; +} + + +/******************************************************************************* +* mvDramIfBankBaseGet - Get DRAM interface bank base. +* +* DESCRIPTION: +* This function returns the 32 bit base address of a given DRAM bank. +* +* INPUT: +* bankNum - Bank number. +* +* OUTPUT: +* None. +* +* RETURN: +* DRAM bank size. If bank is disabled or paramter is invalid, the +* function returns -1. +* +*******************************************************************************/ +MV_U32 mvDramIfBankBaseGet(MV_U32 bankNum) +{ + DB(mvOsPrintf("Dram: mvDramIfBankBaseGet Bank %d base addr is %x \n", + bankNum, mvCpuIfTargetWinBaseLowGet(SDRAM_CS0 + bankNum))); + return mvCpuIfTargetWinBaseLowGet(SDRAM_CS0 + bankNum); +} + +/******************************************************************************* +* mvDramIfBankSizeGet - Get DRAM interface bank size. +* +* DESCRIPTION: +* This function returns the size of a given DRAM bank. +* +* INPUT: +* bankNum - Bank number. +* +* OUTPUT: +* None. +* +* RETURN: +* DRAM bank size. If bank is disabled the function return '0'. In case +* or paramter is invalid, the function returns -1. +* +*******************************************************************************/ +MV_U32 mvDramIfBankSizeGet(MV_U32 bankNum) +{ + DB(mvOsPrintf("Dram: mvDramIfBankSizeGet Bank %d size is %x \n", + bankNum, mvCpuIfTargetWinSizeGet(SDRAM_CS0 + bankNum))); + return mvCpuIfTargetWinSizeGet(SDRAM_CS0 + bankNum); +} + + +/******************************************************************************* +* mvDramIfSizeGet - Get DRAM interface total size. +* +* DESCRIPTION: +* This function get the DRAM total size. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* DRAM total size. In case or paramter is invalid, the function +* returns -1. +* +*******************************************************************************/ +MV_U32 mvDramIfSizeGet(MV_VOID) +{ + MV_U32 size = 0, i; + + for(i = 0; i < MV_DRAM_MAX_CS; i++) + size += mvDramIfBankSizeGet(i); + + DB(mvOsPrintf("Dram: mvDramIfSizeGet size is %x \n",size)); + return size; +} + +/******************************************************************************* +* mvDramIfSingleBitErrThresholdSet - Set single bit ECC threshold. +* +* DESCRIPTION: +* The ECC single bit error threshold is the number of single bit +* errors to happen before the Dunit generates an interrupt. +* This function set single bit ECC threshold. +* +* INPUT: +* threshold - threshold. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if threshold is to big, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvDramIfSingleBitErrThresholdSet(MV_U32 threshold) +{ + MV_U32 regVal; + + if (threshold > SECR_THRECC_MAX) + { + return MV_BAD_PARAM; + } + + regVal = MV_REG_READ(SDRAM_ECC_CONTROL_REG); + regVal &= ~SECR_THRECC_MASK; + regVal |= ((SECR_THRECC(threshold) & SECR_THRECC_MASK)); + MV_REG_WRITE(SDRAM_ECC_CONTROL_REG, regVal); + + return MV_OK; +} + +#ifndef MV_STATIC_DRAM_ON_BOARD +/******************************************************************************* +* minCasCalc - Calculate the Minimum CAS latency which can be used. +* +* DESCRIPTION: +* Calculate the minimum CAS latency that can be used, base on the DRAM +* parameters and the SDRAM bus Clock freq. +* +* INPUT: +* busClk - the DRAM bus Clock. +* pBankInfo - bank info parameters. +* forcedCl - Forced CAS Latency multiplied by 10. If equal to zero, do not force. +* +* OUTPUT: +* None +* +* RETURN: +* The minimum CAS Latency. The function returns 0 if max CAS latency +* supported by banks is incompatible with system bus clock frequancy. +* +*******************************************************************************/ + +static MV_U32 minCasCalc(MV_DRAM_BANK_INFO *pBankInfo,MV_DRAM_BANK_INFO *pBankInfo2, MV_U32 busClk, MV_U32 forcedCl) +{ + MV_U32 count = 1, j; + MV_U32 busClkPs = 1000000000 / (busClk / 1000); /* in ps units */ + MV_U32 startBit, stopBit; + MV_U32 minCas0 = 0, minCas2 = 0; + + + /* DDR 2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 5 | 4 | 3 | 2 | TBD | TBD * + Disco VI= * TBD | TBD | 5 | 4 | 3 | TBD | TBD | TBD * + Disco Duo= * TBD | 6 | 5 | 4 | 3 | TBD | TBD | TBD * + *********************************************************/ + + + /* If we are asked to use the forced CAL we change the suported CAL to be forcedCl only */ + if (forcedCl) + { + mvOsPrintf("DRAM: Using forced CL %d.%d\n", (forcedCl / 10), (forcedCl % 10)); + + if (forcedCl == 30) + pBankInfo->suportedCasLatencies = 0x08; + else if (forcedCl == 40) + pBankInfo->suportedCasLatencies = 0x10; + else if (forcedCl == 50) + pBankInfo->suportedCasLatencies = 0x20; + else if (forcedCl == 60) + pBankInfo->suportedCasLatencies = 0x40; + else + { + mvOsPrintf("Forced CL %d.%d not supported. Set default CL 4\n", + (forcedCl / 10), (forcedCl % 10)); + pBankInfo->suportedCasLatencies = 0x10; + } + + return pBankInfo->suportedCasLatencies; + } + + /* go over the supported cas mask from Max Cas down and check if the */ + /* SysClk stands in its time requirments. */ + + DB(mvOsPrintf("Dram: minCasCalc supported mask = %x busClkPs = %x \n", + pBankInfo->suportedCasLatencies,busClkPs )); + count = 1; + for(j = 7; j > 0; j--) + { + if((pBankInfo->suportedCasLatencies >> j) & BIT0 ) + { + /* Reset the bits for CL incompatible for the sysClk */ + switch (count) + { + case 1: + if (pBankInfo->minCycleTimeAtMaxCasLatPs > busClkPs) + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + case 2: + if (pBankInfo->minCycleTimeAtMaxCasLatMinus1Ps > busClkPs) + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + case 3: + if (pBankInfo->minCycleTimeAtMaxCasLatMinus2Ps > busClkPs) + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + default: + pBankInfo->suportedCasLatencies &= ~(BIT0 << j); + break; + } + } + } + + DB(mvOsPrintf("Dram: minCasCalc support = %x (after SysCC calc)\n", + pBankInfo->suportedCasLatencies )); + + count = 1; + DB(mvOsPrintf("Dram2: minCasCalc supported mask = %x busClkPs = %x \n", + pBankInfo2->suportedCasLatencies,busClkPs )); + for(j = 7; j > 0; j--) + { + if((pBankInfo2->suportedCasLatencies >> j) & BIT0 ) + { + /* Reset the bits for CL incompatible for the sysClk */ + switch (count) + { + case 1: + if (pBankInfo2->minCycleTimeAtMaxCasLatPs > busClkPs) + pBankInfo2->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + case 2: + if (pBankInfo2->minCycleTimeAtMaxCasLatMinus1Ps > busClkPs) + pBankInfo2->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + case 3: + if (pBankInfo2->minCycleTimeAtMaxCasLatMinus2Ps > busClkPs) + pBankInfo2->suportedCasLatencies &= ~(BIT0 << j); + count++; + break; + default: + pBankInfo2->suportedCasLatencies &= ~(BIT0 << j); + break; + } + } + } + + DB(mvOsPrintf("Dram2: minCasCalc support = %x (after SysCC calc)\n", + pBankInfo2->suportedCasLatencies )); + + startBit = 3; /* DDR2 support CL start with CL3 (bit 3) */ + stopBit = 6; /* DDR2 support CL stops with CL6 (bit 6) */ + + for(j = startBit; j <= stopBit ; j++) + { + if((pBankInfo->suportedCasLatencies >> j) & BIT0 ) + { + DB(mvOsPrintf("Dram: minCasCalc choose CAS %x \n",(BIT0 << j))); + minCas0 = (BIT0 << j); + break; + } + } + + for(j = startBit; j <= stopBit ; j++) + { + if((pBankInfo2->suportedCasLatencies >> j) & BIT0 ) + { + DB(mvOsPrintf("Dram: minCasCalc choose CAS %x \n",(BIT0 << j))); + minCas2 = (BIT0 << j); + break; + } + } + + if (minCas2 > minCas0) + return minCas2; + else + return minCas0; + + return 0; +} + +/******************************************************************************* +* sdramConfigRegCalc - Calculate sdram config register +* +* DESCRIPTION: Calculate sdram config register optimized value based +* on the bank info parameters. +* +* INPUT: +* busClk - the DRAM bus Clock. +* pBankInfo - sdram bank parameters +* +* OUTPUT: +* None +* +* RETURN: +* sdram config reg value. +* +*******************************************************************************/ +static MV_U32 sdramConfigRegCalc(MV_DRAM_BANK_INFO *pBankInfo,MV_DRAM_BANK_INFO *pBankInfo2, MV_U32 busClk) +{ + MV_U32 sdramConfig = 0; + MV_U32 refreshPeriod; + + busClk /= 1000000; /* we work with busClk in MHz */ + + sdramConfig = MV_REG_READ(SDRAM_CONFIG_REG); + + /* figure out the memory refresh internal */ + switch (pBankInfo->refreshInterval & 0xf) + { + case 0x0: /* refresh period is 15.625 usec */ + refreshPeriod = 15625; + break; + case 0x1: /* refresh period is 3.9 usec */ + refreshPeriod = 3900; + break; + case 0x2: /* refresh period is 7.8 usec */ + refreshPeriod = 7800; + break; + case 0x3: /* refresh period is 31.3 usec */ + refreshPeriod = 31300; + break; + case 0x4: /* refresh period is 62.5 usec */ + refreshPeriod = 62500; + break; + case 0x5: /* refresh period is 125 usec */ + refreshPeriod = 125000; + break; + default: /* refresh period undefined */ + mvOsPrintf("Dram: ERR. DRAM refresh period is unknown!\n"); + return -1; + } + + /* Now the refreshPeriod is in register format value */ + refreshPeriod = (busClk * refreshPeriod) / 1000; + + DB(mvOsPrintf("Dram: sdramConfigRegCalc calculated refresh interval %0x\n", + refreshPeriod)); + + /* make sure the refresh value is only 14 bits */ + if(refreshPeriod > SDRAM_REFRESH_MAX) + { + refreshPeriod = SDRAM_REFRESH_MAX; + DB(mvOsPrintf("Dram: sdramConfigRegCalc adjusted refresh interval %0x\n", + refreshPeriod)); + } + + /* Clear the refresh field */ + sdramConfig &= ~SDRAM_REFRESH_MASK; + + /* Set new value to refresh field */ + sdramConfig |= (refreshPeriod & SDRAM_REFRESH_MASK); + + /* registered DRAM ? */ + if ( pBankInfo->registeredAddrAndControlInputs ) + { + /* it's registered DRAM, so set the reg. DRAM bit */ + sdramConfig |= SDRAM_REGISTERED; + DB(mvOsPrintf("DRAM Attribute: Registered address and control inputs.\n");) + } + + /* ECC and IERR support */ + sdramConfig &= ~SDRAM_ECC_MASK; /* Clear ECC field */ + sdramConfig &= ~SDRAM_IERR_MASK; /* Clear IErr field */ + + if ( pBankInfo->errorCheckType ) + { + sdramConfig |= SDRAM_ECC_EN; + sdramConfig |= SDRAM_IERR_REPORTE; + DB(mvOsPrintf("Dram: mvDramIfDetect Enabling ECC\n")); + } + else + { + sdramConfig |= SDRAM_ECC_DIS; + sdramConfig |= SDRAM_IERR_IGNORE; + DB(mvOsPrintf("Dram: mvDramIfDetect Disabling ECC!\n")); + } + /* Set static default settings */ + sdramConfig |= SDRAM_CONFIG_DV; + + DB(mvOsPrintf("Dram: sdramConfigRegCalc set sdramConfig to 0x%x\n", + sdramConfig)); + + return sdramConfig; +} + +/******************************************************************************* +* sdramModeRegCalc - Calculate sdram mode register +* +* DESCRIPTION: Calculate sdram mode register optimized value based +* on the bank info parameters and the minCas. +* +* INPUT: +* minCas - minimum CAS supported. +* +* OUTPUT: +* None +* +* RETURN: +* sdram mode reg value. +* +*******************************************************************************/ +static MV_U32 sdramModeRegCalc(MV_U32 minCas) +{ + MV_U32 sdramMode; + + sdramMode = MV_REG_READ(SDRAM_MODE_REG); + + /* Clear CAS Latency field */ + sdramMode &= ~SDRAM_CL_MASK; + + DB(mvOsPrintf("DRAM CAS Latency ");) + + switch (minCas) + { + case DDR2_CL_3: + sdramMode |= SDRAM_DDR2_CL_3; + DB(mvOsPrintf("3.\n");) + break; + case DDR2_CL_4: + sdramMode |= SDRAM_DDR2_CL_4; + DB(mvOsPrintf("4.\n");) + break; + case DDR2_CL_5: + sdramMode |= SDRAM_DDR2_CL_5; + DB(mvOsPrintf("5.\n");) + break; + case DDR2_CL_6: + sdramMode |= SDRAM_DDR2_CL_6; + DB(mvOsPrintf("6.\n");) + break; + default: + mvOsPrintf("\nsdramModeRegCalc ERROR: Max. CL out of range\n"); + return -1; + } + + DB(mvOsPrintf("\nsdramModeRegCalc register 0x%x\n", sdramMode )); + + return sdramMode; +} +/******************************************************************************* +* sdramExtModeRegCalc - Calculate sdram Extended mode register +* +* DESCRIPTION: +* Return sdram Extended mode register value based +* on the bank info parameters and bank presence. +* +* INPUT: +* pBankInfo - sdram bank parameters +* busClk - DRAM frequency +* +* OUTPUT: +* None +* +* RETURN: +* sdram Extended mode reg value. +* +*******************************************************************************/ +static MV_U32 sdramExtModeRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk) +{ + MV_U32 populateBanks = 0; + int bankNum; + + /* Represent the populate banks in binary form */ + for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + if (0 != pBankInfo[bankNum].size) + { + populateBanks |= (1 << bankNum); + } + } + + switch(populateBanks) + { + case(BANK_PRESENT_CS0): + case(BANK_PRESENT_CS0_CS1): + return DDR_SDRAM_EXT_MODE_CS0_CS1_DV; + + case(BANK_PRESENT_CS0_CS2): + case(BANK_PRESENT_CS0_CS1_CS2): + case(BANK_PRESENT_CS0_CS2_CS3): + case(BANK_PRESENT_CS0_CS2_CS3_CS4): + if (busClk >= MV_BOARD_SYSCLK_267MHZ) + return DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV; + else + return DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV; + + default: + mvOsPrintf("sdramExtModeRegCalc: Invalid DRAM bank presence\n"); + return -1; + } + return 0; +} + +/******************************************************************************* +* dunitCtrlLowRegCalc - Calculate sdram dunit control low register +* +* DESCRIPTION: Calculate sdram dunit control low register optimized value based +* on the bank info parameters and the minCas. +* +* INPUT: +* pBankInfo - sdram bank parameters +* minCas - minimum CAS supported. +* +* OUTPUT: +* None +* +* RETURN: +* sdram dunit control low reg value. +* +*******************************************************************************/ +static MV_U32 dunitCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas, MV_U32 busClk, MV_STATUS TTMode) +{ + MV_U32 dunitCtrlLow, cl; + MV_U32 sbOutR[4]={3,5,7,9} ; + MV_U32 sbOutU[4]={1,3,5,7} ; + + MV_U32 ctrlId = mvCtrlModelGet(); + + dunitCtrlLow = MV_REG_READ(SDRAM_DUNIT_CTRL_REG); + + DB(mvOsPrintf("Dram: dunitCtrlLowRegCalc\n")); + + /* Clear StBurstOutDel field */ + dunitCtrlLow &= ~SDRAM_SB_OUT_MASK; + + /* Clear StBurstInDel field */ + dunitCtrlLow &= ~SDRAM_SB_IN_MASK; + + /* Clear CtrlPos field */ + dunitCtrlLow &= ~SDRAM_CTRL_POS_MASK; + + /* Clear 2T field */ + dunitCtrlLow &= ~SDRAM_2T_MASK; + if (TTMode == MV_TRUE) + { + dunitCtrlLow |= SDRAM_2T_MODE; + } + + /* For proper sample of read data set the Dunit Control register's */ + /* stBurstInDel bits [27:24] */ + /* 200MHz - 266MHz None reg = CL + 2 */ + /* 200MHz - 266MHz reg = CL + 3 */ + /* 266MHz - 333MHz None reg = CL + 3 */ + /* 266MHz - 333MHz reg = CL + 4 */ + + /* For proper sample of read data set the Dunit Control register's */ + /* stBurstOutDel bits [23:20] */ + /********-********-********-********- + * CL=3 | CL=4 | CL=5 | CL=6 | + *********-********-********-********- + Not Reg. * 0001 | 0011 | 0101 | 0111 | + *********-********-********-********- + Registered * 0011 | 0101 | 0111 | 1001 | + *********-********-********-********/ + + /* Set Dunit Control low default value */ + dunitCtrlLow |= SDRAM_DUNIT_CTRL_LOW_DDR2_DV; + + switch (minCas) + { + case DDR2_CL_3: cl = 3; break; + case DDR2_CL_4: cl = 4; break; + case DDR2_CL_5: cl = 5; break; + case DDR2_CL_6: cl = 6; break; + default: + mvOsPrintf("Dram: dunitCtrlLowRegCalc Max. CL out of range %d\n", minCas); + return -1; + } + + /* registerd DDR SDRAM? */ + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + { + #if 0 + if ( ( (MV_78100_DEV_ID == ctrlId) || (MV_78200_DEV_ID == ctrlId) ) && + (busClk > MV_BOARD_SYSCLK_333MHZ) ) + /* Add 0.5 clk cycle to SBout on DD with DRAM clock 400MHz */ + dunitCtrlLow |= (sbOutR[cl-3] + 1) << SDRAM_SB_OUT_DEL_OFFS; + else + #endif + dunitCtrlLow |= (sbOutR[cl-3]) << SDRAM_SB_OUT_DEL_OFFS; + } + else + { + #if 0 + if ( ( (MV_78100_DEV_ID == ctrlId) || (MV_78200_DEV_ID == ctrlId) ) && + (busClk > MV_BOARD_SYSCLK_333MHZ) ) + /* Add 0.5 clk cycle to SBout on DD with DRAM clock 400MHz */ + dunitCtrlLow |= (sbOutU[cl-3] + 1) << SDRAM_SB_OUT_DEL_OFFS; + else + #endif + dunitCtrlLow |= (sbOutU[cl-3]) << SDRAM_SB_OUT_DEL_OFFS; + } + + DB(mvOsPrintf("\n\ndunitCtrlLowRegCalc: CL = %d, frequencies=%d\n", cl, busClk)); + + if (busClk > MV_BOARD_SYSCLK_333MHZ) + { + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + cl = cl + 5; + else + cl = cl + 4; + } + else if (busClk >= MV_BOARD_SYSCLK_267MHZ) + { + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + cl = cl + 4; + else + cl = cl + 3; + } + else if (busClk >= MV_BOARD_SYSCLK_200MHZ) + { + if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE) + cl = cl + 3; + else + cl = cl + 2; + + if ((MV_78100_DEV_ID == ctrlId) || (MV_78200_DEV_ID == ctrlId)) + cl = cl + 1; + + dunitCtrlLow |= SDRAM_CTRL_POS_RISE; + } + + DB(mvOsPrintf("dunitCtrlLowRegCalc: SDRAM_SB_IN_DEL_OFFS = %d \n", cl)); + dunitCtrlLow |= cl << SDRAM_SB_IN_DEL_OFFS; + + DB(mvOsPrintf("Dram: Reg dunit control low = %x\n", dunitCtrlLow )); + + return dunitCtrlLow; +} + +/******************************************************************************* +* dunitCtrlHighRegCalc - Calculate sdram dunit control high register +* +* DESCRIPTION: Calculate sdram dunit control high register optimized value based +* on the bus clock. +* +* INPUT: +* busClk - DRAM frequency. +* +* OUTPUT: +* None +* +* RETURN: +* sdram dunit control high reg value. +* +*******************************************************************************/ +static MV_U32 dunitCtrlHighRegCalc(MV_U32 busClk) +{ + MV_U32 dunitCtrlHigh; + dunitCtrlHigh = MV_REG_READ(SDRAM_DUNIT_CTRL_HI_REG); + if(busClk == MV_BOARD_SYSCLK_400MHZ) + dunitCtrlHigh |= (SDRAM__D2P_EN | SDRAM__P2D_EN); + else + dunitCtrlHigh &= ~(SDRAM__D2P_EN | SDRAM__P2D_EN); + + if(busClk >= MV_BOARD_SYSCLK_267MHZ) + dunitCtrlHigh |= (SDRAM__WR_MESH_DELAY_EN | SDRAM__PUP_ZERO_SKEW_EN | SDRAM__ADD_HALF_FCC_EN); + + return dunitCtrlHigh; +} + +/******************************************************************************* +* sdramAddrCtrlRegCalc - Calculate sdram address control register +* +* DESCRIPTION: Calculate sdram address control register optimized value based +* on the bank info parameters and the minCas. +* +* INPUT: +* pBankInfo - sdram bank parameters +* +* OUTPUT: +* None +* +* RETURN: +* sdram address control reg value. +* +*******************************************************************************/ +static MV_U32 sdramAddrCtrlRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_DRAM_BANK_INFO *pBankInfoDIMM1) +{ + MV_U32 addrCtrl = 0; + + if (pBankInfoDIMM1->size) + { + switch (pBankInfoDIMM1->sdramWidth) + { + case 4: /* memory is x4 */ + mvOsPrintf("sdramAddrCtrlRegCalc: Error - x4 not supported!\n"); + return -1; + break; + case 8: /* memory is x8 */ + addrCtrl |= SDRAM_ADDRSEL_X8(2) | SDRAM_ADDRSEL_X8(3); + DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device DIMM2 width x8\n")); + break; + case 16: + addrCtrl |= SDRAM_ADDRSEL_X16(2) | SDRAM_ADDRSEL_X16(3); + DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device DIMM2 width x16\n")); + break; + default: /* memory width unsupported */ + mvOsPrintf("sdramAddrCtrlRegCalc: ERR. DRAM chip width is unknown!\n"); + return -1; + } + } + + switch (pBankInfo->sdramWidth) + { + case 4: /* memory is x4 */ + mvOsPrintf("sdramAddrCtrlRegCalc: Error - x4 not supported!\n"); + return -1; + break; + case 8: /* memory is x8 */ + addrCtrl |= SDRAM_ADDRSEL_X8(0) | SDRAM_ADDRSEL_X8(1); + DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device width x8\n")); + break; + case 16: + addrCtrl |= SDRAM_ADDRSEL_X16(0) | SDRAM_ADDRSEL_X16(1); + DB(mvOsPrintf("sdramAddrCtrlRegCalc: sdramAddrCtrlRegCalc SDRAM device width x16\n")); + break; + default: /* memory width unsupported */ + mvOsPrintf("sdramAddrCtrlRegCalc: ERR. DRAM chip width is unknown!\n"); + return -1; + } + + /* Note that density is in MB units */ + switch (pBankInfo->deviceDensity) + { + case 256: /* 256 Mbit */ + DB(mvOsPrintf("DRAM Device Density 256Mbit\n")); + addrCtrl |= SDRAM_DSIZE_256Mb(0) | SDRAM_DSIZE_256Mb(1); + break; + case 512: /* 512 Mbit */ + DB(mvOsPrintf("DRAM Device Density 512Mbit\n")); + addrCtrl |= SDRAM_DSIZE_512Mb(0) | SDRAM_DSIZE_512Mb(1); + break; + case 1024: /* 1 Gbit */ + DB(mvOsPrintf("DRAM Device Density 1Gbit\n")); + addrCtrl |= SDRAM_DSIZE_1Gb(0) | SDRAM_DSIZE_1Gb(1); + break; + case 2048: /* 2 Gbit */ + DB(mvOsPrintf("DRAM Device Density 2Gbit\n")); + addrCtrl |= SDRAM_DSIZE_2Gb(0) | SDRAM_DSIZE_2Gb(1); + break; + default: + mvOsPrintf("Dram: sdramAddrCtrl unsupported RAM-Device size %d\n", + pBankInfo->deviceDensity); + return -1; + } + + if (pBankInfoDIMM1->size) + { + switch (pBankInfoDIMM1->deviceDensity) + { + case 256: /* 256 Mbit */ + DB(mvOsPrintf("DIMM2: DRAM Device Density 256Mbit\n")); + addrCtrl |= SDRAM_DSIZE_256Mb(2) | SDRAM_DSIZE_256Mb(3); + break; + case 512: /* 512 Mbit */ + DB(mvOsPrintf("DIMM2: DRAM Device Density 512Mbit\n")); + addrCtrl |= SDRAM_DSIZE_512Mb(2) | SDRAM_DSIZE_512Mb(3); + break; + case 1024: /* 1 Gbit */ + DB(mvOsPrintf("DIMM2: DRAM Device Density 1Gbit\n")); + addrCtrl |= SDRAM_DSIZE_1Gb(2) | SDRAM_DSIZE_1Gb(3); + break; + case 2048: /* 2 Gbit */ + DB(mvOsPrintf("DIMM2: DRAM Device Density 2Gbit\n")); + addrCtrl |= SDRAM_DSIZE_2Gb(2) | SDRAM_DSIZE_2Gb(3); + break; + default: + mvOsPrintf("DIMM2: Dram: sdramAddrCtrl unsupported RAM-Device size %d\n", + pBankInfoDIMM1->deviceDensity); + return -1; + } + } + /* SDRAM address control */ + DB(mvOsPrintf("Dram: setting sdram address control with: %x \n", addrCtrl)); + + return addrCtrl; +} + +/******************************************************************************* +* sdramTimeCtrlLowRegCalc - Calculate sdram timing control low register +* +* DESCRIPTION: +* This function calculates sdram timing control low register +* optimized value based on the bank info parameters and the minCas. +* +* INPUT: +* pBankInfo - sdram bank parameters +* minCas - minimum CAS supported. +* busClk - Bus clock +* +* OUTPUT: +* None +* +* RETURN: +* sdram timing control low reg value. +* +*******************************************************************************/ +static MV_U32 sdramTimeCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas, MV_U32 busClk) +{ + MV_U32 tRp = 0; + MV_U32 tRrd = 0; + MV_U32 tRcd = 0; + MV_U32 tRas = 0; + MV_U32 tWr = 0; + MV_U32 tWtr = 0; + MV_U32 tRtp = 0; + MV_U32 timeCtrlLow = 0; + + MV_U32 bankNum; + + busClk = busClk / 1000000; /* In MHz */ + + /* Scan all DRAM banks to find maximum timing values */ + for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + tRp = MV_MAX(tRp, pBankInfo[bankNum].minRowPrechargeTime); + tRrd = MV_MAX(tRrd, pBankInfo[bankNum].minRowActiveToRowActive); + tRcd = MV_MAX(tRcd, pBankInfo[bankNum].minRasToCasDelay); + tRas = MV_MAX(tRas, pBankInfo[bankNum].minRasPulseWidth); + } + + /* Extract timing (in ns) from SPD value. We ignore the tenth ns part. */ + /* by shifting the data two bits right. */ + tRp = tRp >> 2; /* For example 0x50 -> 20ns */ + tRrd = tRrd >> 2; + tRcd = tRcd >> 2; + + /* Extract clock cycles from time parameter. We need to round up */ + tRp = ((busClk * tRp) / 1000) + (((busClk * tRp) % 1000) ? 1 : 0); + DB(mvOsPrintf("Dram Timing Low: tRp = %d ", tRp)); + tRrd = ((busClk * tRrd) / 1000) + (((busClk * tRrd) % 1000) ? 1 : 0); + /* JEDEC min reqeirments tRrd = 2 */ + if (tRrd < 2) + tRrd = 2; + DB(mvOsPrintf("tRrd = %d ", tRrd)); + tRcd = ((busClk * tRcd) / 1000) + (((busClk * tRcd) % 1000) ? 1 : 0); + DB(mvOsPrintf("tRcd = %d ", tRcd)); + tRas = ((busClk * tRas) / 1000) + (((busClk * tRas) % 1000) ? 1 : 0); + DB(mvOsPrintf("tRas = %d ", tRas)); + + /* tWr and tWtr is different for DDR1 and DDR2. tRtp is only for DDR2 */ + /* Scan all DRAM banks to find maximum timing values */ + for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + tWr = MV_MAX(tWr, pBankInfo[bankNum].minWriteRecoveryTime); + tWtr = MV_MAX(tWtr, pBankInfo[bankNum].minWriteToReadCmdDelay); + tRtp = MV_MAX(tRtp, pBankInfo[bankNum].minReadToPrechCmdDelay); + } + + /* Extract timing (in ns) from SPD value. We ignore the tenth ns */ + /* part by shifting the data two bits right. */ + tWr = tWr >> 2; /* For example 0x50 -> 20ns */ + tWtr = tWtr >> 2; + tRtp = tRtp >> 2; + /* Extract clock cycles from time parameter. We need to round up */ + tWr = ((busClk * tWr) / 1000) + (((busClk * tWr) % 1000) ? 1 : 0); + DB(mvOsPrintf("tWr = %d ", tWr)); + tWtr = ((busClk * tWtr) / 1000) + (((busClk * tWtr) % 1000) ? 1 : 0); + /* JEDEC min reqeirments tWtr = 2 */ + if (tWtr < 2) + tWtr = 2; + DB(mvOsPrintf("tWtr = %d ", tWtr)); + tRtp = ((busClk * tRtp) / 1000) + (((busClk * tRtp) % 1000) ? 1 : 0); + /* JEDEC min reqeirments tRtp = 2 */ + if (tRtp < 2) + tRtp = 2; + DB(mvOsPrintf("tRtp = %d ", tRtp)); + + /* Note: value of 0 in register means one cycle, 1 means two and so on */ + timeCtrlLow = (((tRp - 1) << SDRAM_TRP_OFFS) | + ((tRrd - 1) << SDRAM_TRRD_OFFS) | + ((tRcd - 1) << SDRAM_TRCD_OFFS) | + (((tRas - 1) << SDRAM_TRAS_OFFS) & SDRAM_TRAS_MASK)| + ((tWr - 1) << SDRAM_TWR_OFFS) | + ((tWtr - 1) << SDRAM_TWTR_OFFS) | + ((tRtp - 1) << SDRAM_TRTP_OFFS)); + + /* Check extended tRas bit */ + if ((tRas - 1) & BIT4) + timeCtrlLow |= (1 << SDRAM_EXT_TRAS_OFFS); + + return timeCtrlLow; +} + +/******************************************************************************* +* sdramTimeCtrlHighRegCalc - Calculate sdram timing control high register +* +* DESCRIPTION: +* This function calculates sdram timing control high register +* optimized value based on the bank info parameters and the bus clock. +* +* INPUT: +* pBankInfo - sdram bank parameters +* busClk - Bus clock +* +* OUTPUT: +* None +* +* RETURN: +* sdram timing control high reg value. +* +*******************************************************************************/ +static MV_U32 sdramTimeCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk) +{ + MV_U32 tRfc; + MV_U32 timingHigh; + MV_U32 timeNs = 0; + MV_U32 bankNum; + + busClk = busClk / 1000000; /* In MHz */ + + /* Set DDR timing high register static configuration bits */ + timingHigh = MV_REG_READ(SDRAM_TIMING_CTRL_HIGH_REG); + + /* Set DDR timing high register default value */ + timingHigh |= SDRAM_TIMING_CTRL_HIGH_REG_DV; + + /* Clear tRfc field */ + timingHigh &= ~SDRAM_TRFC_MASK; + + /* Scan all DRAM banks to find maximum timing values */ + for (bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + timeNs = MV_MAX(timeNs, pBankInfo[bankNum].minRefreshToActiveCmd); + DB(mvOsPrintf("Dram: Timing High: minRefreshToActiveCmd = %d\n", + pBankInfo[bankNum].minRefreshToActiveCmd)); + } + + tRfc = ((busClk * timeNs) / 1000) + (((busClk * timeNs) % 1000) ? 1 : 0); + /* Note: value of 0 in register means one cycle, 1 means two and so on */ + DB(mvOsPrintf("Dram: Timing High: tRfc = %d\n", tRfc)); + timingHigh |= (((tRfc - 1) & SDRAM_TRFC_MASK) << SDRAM_TRFC_OFFS); + DB(mvOsPrintf("Dram: Timing High: tRfc = %d\n", tRfc)); + + /* SDRAM timing high */ + DB(mvOsPrintf("Dram: setting timing high with: %x \n", timingHigh)); + + return timingHigh; +} +/******************************************************************************* +* sdramDDr2OdtConfig - Set DRAM DDR2 On Die Termination registers. +* +* DESCRIPTION: +* This function config DDR2 On Die Termination (ODT) registers. +* +* INPUT: +* pBankInfo - bank info parameters. +* +* OUTPUT: +* None +* +* RETURN: +* None +*******************************************************************************/ +static void sdramDDr2OdtConfig(MV_DRAM_BANK_INFO *pBankInfo) +{ + MV_U32 populateBanks = 0; + MV_U32 odtCtrlLow, odtCtrlHigh, dunitOdtCtrl; + int bankNum; + + /* Represent the populate banks in binary form */ + for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++) + { + if (0 != pBankInfo[bankNum].size) + { + populateBanks |= (1 << bankNum); + } + } + + switch(populateBanks) + { + case(BANK_PRESENT_CS0): + case(BANK_PRESENT_CS0_CS1): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS1_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS1_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS1_DV; + break; + case(BANK_PRESENT_CS0_CS2): + case(BANK_PRESENT_CS0_CS1_CS2): + case(BANK_PRESENT_CS0_CS2_CS3): + case(BANK_PRESENT_CS0_CS2_CS3_CS4): + odtCtrlLow = DDR2_ODT_CTRL_LOW_CS0_CS1_CS2_CS3_DV; + odtCtrlHigh = DDR2_ODT_CTRL_HIGH_CS0_CS1_CS2_CS3_DV; + dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS1_CS2_CS3_DV; + break; + default: + DB(mvOsPrintf("sdramDDr2OdtConfig: Invalid DRAM bank presence\n")); + return; + } + /* DDR2 SDRAM ODT ctrl low */ + DB(mvOsPrintf("Dram: DDR2 setting ODT ctrl low with: %x \n", odtCtrlLow)); + MV_REG_WRITE(DRAM_BUF_REG7, odtCtrlLow); + + /* DDR2 SDRAM ODT ctrl high */ + DB(mvOsPrintf("Dram: DDR2 setting ODT ctrl high with: %x \n", odtCtrlHigh)); + MV_REG_WRITE(DRAM_BUF_REG8, odtCtrlHigh); + + /* DDR2 DUNIT ODT ctrl */ + if ( ((mvCtrlModelGet() == MV_78XX0_DEV_ID) && (mvCtrlRevGet() == MV_78XX0_Y0_REV)) || + (mvCtrlModelGet() == MV_78100_DEV_ID) || + (mvCtrlModelGet() == MV_78200_DEV_ID) ) + dunitOdtCtrl &= ~(BIT9|BIT8); /* Clear ODT always on */ + + DB(mvOsPrintf("DUNIT: DDR2 setting ODT ctrl with: %x \n", dunitOdtCtrl)); + MV_REG_WRITE(DRAM_BUF_REG9, dunitOdtCtrl); + return; +} +/******************************************************************************* +* sdramDdr2TimeLoRegCalc - Set DDR2 DRAM Timing Low registers. +* +* DESCRIPTION: +* This function config DDR2 DRAM Timing low registers. +* +* INPUT: +* minCas - minimum CAS supported. +* +* OUTPUT: +* None +* +* RETURN: +* DDR2 sdram timing low reg value. +*******************************************************************************/ +static MV_U32 sdramDdr2TimeLoRegCalc(MV_U32 minCas) +{ + MV_U8 cl = -1; + MV_U32 ddr2TimeLoReg; + + /* read and clear the feilds we are going to set */ + ddr2TimeLoReg = MV_REG_READ(SDRAM_DDR2_TIMING_LO_REG); + ddr2TimeLoReg &= ~(SD2TLR_TODT_ON_RD_MASK | + SD2TLR_TODT_OFF_RD_MASK | + SD2TLR_TODT_ON_CTRL_RD_MASK | + SD2TLR_TODT_OFF_CTRL_RD_MASK); + + if( minCas == DDR2_CL_3 ) + { + cl = 3; + } + else if( minCas == DDR2_CL_4 ) + { + cl = 4; + } + else if( minCas == DDR2_CL_5 ) + { + cl = 5; + } + else if( minCas == DDR2_CL_6 ) + { + cl = 6; + } + else + { + DB(mvOsPrintf("sdramDdr2TimeLoRegCalc: CAS latency %d unsupported. using CAS latency 4\n", + minCas)); + cl = 4; + } + + ddr2TimeLoReg |= ((cl-3) << SD2TLR_TODT_ON_RD_OFFS); + ddr2TimeLoReg |= ( cl << SD2TLR_TODT_OFF_RD_OFFS); + ddr2TimeLoReg |= ( cl << SD2TLR_TODT_ON_CTRL_RD_OFFS); + ddr2TimeLoReg |= ((cl+3) << SD2TLR_TODT_OFF_CTRL_RD_OFFS); + + /* DDR2 SDRAM timing low */ + DB(mvOsPrintf("Dram: DDR2 setting timing low with: %x \n", ddr2TimeLoReg)); + + return ddr2TimeLoReg; +} + +/******************************************************************************* +* sdramDdr2TimeHiRegCalc - Set DDR2 DRAM Timing High registers. +* +* DESCRIPTION: +* This function config DDR2 DRAM Timing high registers. +* +* INPUT: +* minCas - minimum CAS supported. +* +* OUTPUT: +* None +* +* RETURN: +* DDR2 sdram timing high reg value. +*******************************************************************************/ +static MV_U32 sdramDdr2TimeHiRegCalc(MV_U32 minCas) +{ + MV_U8 cl = -1; + MV_U32 ddr2TimeHiReg; + + /* read and clear the feilds we are going to set */ + ddr2TimeHiReg = MV_REG_READ(SDRAM_DDR2_TIMING_HI_REG); + ddr2TimeHiReg &= ~(SD2THR_TODT_ON_WR_MASK | + SD2THR_TODT_OFF_WR_MASK | + SD2THR_TODT_ON_CTRL_WR_MASK | + SD2THR_TODT_OFF_CTRL_WR_MASK); + + if( minCas == DDR2_CL_3 ) + { + cl = 3; + } + else if( minCas == DDR2_CL_4 ) + { + cl = 4; + } + else if( minCas == DDR2_CL_5 ) + { + cl = 5; + } + else if( minCas == DDR2_CL_6 ) + { + cl = 6; + } + else + { + mvOsPrintf("sdramDdr2TimeHiRegCalc: CAS latency %d unsupported. using CAS latency 4\n", + minCas); + cl = 4; + } + + ddr2TimeHiReg |= ((cl-3) << SD2THR_TODT_ON_WR_OFFS); + ddr2TimeHiReg |= ( cl << SD2THR_TODT_OFF_WR_OFFS); + ddr2TimeHiReg |= ( cl << SD2THR_TODT_ON_CTRL_WR_OFFS); + ddr2TimeHiReg |= ((cl+3) << SD2THR_TODT_OFF_CTRL_WR_OFFS); + + /* DDR2 SDRAM timin high */ + DB(mvOsPrintf("Dram: DDR2 setting timing high with: %x \n", ddr2TimeHiReg)); + + return ddr2TimeHiReg; +} +#endif + +/******************************************************************************* +* mvDramIfCalGet - Get CAS Latency +* +* DESCRIPTION: +* This function get the CAS Latency. +* +* INPUT: +* None +* +* OUTPUT: +* None +* +* RETURN: +* CAS latency times 10 (to avoid using floating point). +* +*******************************************************************************/ +MV_U32 mvDramIfCalGet(void) +{ + MV_U32 sdramCasLat, casLatMask; + + casLatMask = (MV_REG_READ(SDRAM_MODE_REG) & SDRAM_CL_MASK); + + switch (casLatMask) + { + case SDRAM_DDR2_CL_3: + sdramCasLat = 30; + break; + case SDRAM_DDR2_CL_4: + sdramCasLat = 40; + break; + case SDRAM_DDR2_CL_5: + sdramCasLat = 50; + break; + case SDRAM_DDR2_CL_6: + sdramCasLat = 60; + break; + default: + mvOsPrintf("mvDramIfCalGet: Err, unknown DDR2 CAL\n"); + return -1; + } + + return sdramCasLat; +} + + +/******************************************************************************* +* mvDramIfSelfRefreshSet - Put the dram in self refresh mode - +* +* DESCRIPTION: +* add support in power management. +* +* +* INPUT: +* None +* +* OUTPUT: +* None +* +* RETURN: +* None +* +*******************************************************************************/ + +MV_VOID mvDramIfSelfRefreshSet() +{ + MV_U32 operReg; + + operReg = MV_REG_READ(SDRAM_OPERATION_REG); + MV_REG_WRITE(SDRAM_OPERATION_REG ,operReg |SDRAM_CMD_SLF_RFRSH); + /* Read until register is reset to 0 */ + while(MV_REG_READ(SDRAM_OPERATION_REG)); +} +/******************************************************************************* +* mvDramIfDimGetSPDversion - return DIMM SPD version. +* +* DESCRIPTION: +* This function prints the DRAM controller information. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void mvDramIfDimGetSPDversion(MV_U32 *pMajor, MV_U32 *pMinor, MV_U32 bankNum) +{ + MV_DIMM_INFO dimmInfo; + if (bankNum >= MV_DRAM_MAX_CS ) + { + DB(mvOsPrintf("Dram: mvDramIfDimGetSPDversion bad params \n")); + return ; + } + memset(&dimmInfo,0,sizeof(dimmInfo)); + if ( MV_OK != dimmSpdGet((MV_U32)(bankNum/2), &dimmInfo)) + { + DB(mvOsPrintf("Dram: ERR dimmSpdGet failed to get dimm info \n")); + return ; + } + *pMajor = dimmInfo.spdRawData[DIMM_SPD_VERSION]/10; + *pMinor = dimmInfo.spdRawData[DIMM_SPD_VERSION]%10; +} +/******************************************************************************* +* mvDramIfShow - Show DRAM controller information. +* +* DESCRIPTION: +* This function prints the DRAM controller information. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +void mvDramIfShow(void) +{ + int i, sdramCasLat, sdramCsSize; + MV_U32 Major=0, Minor=0; + + mvOsPrintf("DRAM Controller info:\n"); + + mvOsPrintf("Total DRAM "); + mvSizePrint(mvDramIfSizeGet()); + mvOsPrintf("\n"); + + for(i = 0; i < MV_DRAM_MAX_CS; i++) + { + sdramCsSize = mvDramIfBankSizeGet(i); + if (sdramCsSize) + { + if (0 == (i & 1)) + { + mvDramIfDimGetSPDversion(&Major, &Minor,i); + mvOsPrintf("DIMM %d version %d.%d\n", i/2, Major, Minor); + } + mvOsPrintf("\tDRAM CS[%d] ", i); + mvSizePrint(sdramCsSize); + mvOsPrintf("\n"); + } + } + sdramCasLat = mvDramIfCalGet(); + + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_ECC_EN) + { + mvOsPrintf("ECC enabled, "); + } + else + { + mvOsPrintf("ECC Disabled, "); + } + + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_REGISTERED) + { + mvOsPrintf("Registered DIMM\n"); + } + else + { + mvOsPrintf("Non registered DIMM\n"); + } + + mvOsPrintf("Configured CAS Latency %d.%d\n", sdramCasLat/10, sdramCasLat%10); +} +/******************************************************************************* +* mvDramIfGetFirstCS - find the DRAM bank on the lower address +* +* +* DESCRIPTION: +* This function return the fisrt CS on address 0 +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* SDRAM_CS0 or SDRAM_CS2 +* +*******************************************************************************/ +MV_U32 mvDramIfGetFirstCS(void) +{ + MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS]; + + if (DRAM_CS_Order[0] == N_A) + { + mvDramBankInfoGet(SDRAM_CS0, &bankInfo[SDRAM_CS0]); + mvDramBankInfoGet(SDRAM_CS2, &bankInfo[SDRAM_CS2]); + + if (bankInfo[SDRAM_CS0].size < bankInfo[SDRAM_CS2].size) + { + DRAM_CS_Order[0] = SDRAM_CS2; + DRAM_CS_Order[1] = SDRAM_CS3; + DRAM_CS_Order[2] = SDRAM_CS0; + DRAM_CS_Order[3] = SDRAM_CS1; + + return SDRAM_CS2; + } + DRAM_CS_Order[0] = SDRAM_CS0; + DRAM_CS_Order[1] = SDRAM_CS1; + DRAM_CS_Order[2] = SDRAM_CS2; + DRAM_CS_Order[3] = SDRAM_CS3; + + return SDRAM_CS0; + } + return DRAM_CS_Order[0]; +} + diff --git a/board/mv_feroceon/mv_hal/ddr2/mvDramIf.h b/board/mv_feroceon/mv_hal/ddr2/mvDramIf.h new file mode 100644 index 0000000..fe96576 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr2/mvDramIf.h @@ -0,0 +1,170 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDramIfh +#define __INCmvDramIfh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ +#include "ddr2/mvDramIfRegs.h" +#include "ddr2/mvDramIfConfig.h" +#include "ctrlEnv/mvCtrlEnvLib.h" + +/* defines */ +/* DRAM Timing parameters */ +#define SDRAM_TWR 15 /* ns tWr */ +#define SDRAM_TRFC_64_512M_AT_200MHZ 70 /* ns tRfc for dens 64-512 @ 200MHz */ +#define SDRAM_TRFC_64_512M 75 /* ns tRfc for dens 64-512 */ +#define SDRAM_TRFC_1G 120 /* ns tRfc for dens 1GB */ +#define SDRAM_TR2R_CYC 1 /* cycle for tR2r */ + +#define CAL_AUTO_DETECT 0 /* Do not force CAS latancy (mvDramIfDetect) */ +#define ECC_DISABLE 1 /* Force ECC to Disable */ +#define ECC_ENABLE 0 /* Force ECC to ENABLE */ +/* typedefs */ + +/* enumeration for memory types */ +typedef enum _mvMemoryType +{ + MEM_TYPE_SDRAM, + MEM_TYPE_DDR1, + MEM_TYPE_DDR2 +}MV_MEMORY_TYPE; + +/* enumeration for DDR2 supported CAS Latencies */ +typedef enum _mvDimmDdr2Cas +{ + DDR2_CL_3 = 0x08, + DDR2_CL_4 = 0x10, + DDR2_CL_5 = 0x20, + DDR2_CL_6 = 0x40, + DDR2_CL_FAULT +} MV_DIMM_DDR2_CAS; + + +typedef struct _mvDramBankInfo +{ + MV_MEMORY_TYPE memoryType; /* DDR1, DDR2 or SDRAM */ + + /* DIMM dimensions */ + MV_U32 numOfRowAddr; + MV_U32 numOfColAddr; + MV_U32 dataWidth; + MV_U32 errorCheckType; /* ECC , PARITY..*/ + MV_U32 sdramWidth; /* 4,8,16 or 32 */ + MV_U32 errorCheckDataWidth; /* 0 - no, 1 - Yes */ + MV_U32 burstLengthSupported; + MV_U32 numOfBanksOnEachDevice; + MV_U32 suportedCasLatencies; + MV_U32 refreshInterval; + + /* DIMM timing parameters */ + MV_U32 minCycleTimeAtMaxCasLatPs; + MV_U32 minCycleTimeAtMaxCasLatMinus1Ps; + MV_U32 minCycleTimeAtMaxCasLatMinus2Ps; + MV_U32 minRowPrechargeTime; + MV_U32 minRowActiveToRowActive; + MV_U32 minRasToCasDelay; + MV_U32 minRasPulseWidth; + MV_U32 minWriteRecoveryTime; /* DDR2 only */ + MV_U32 minWriteToReadCmdDelay; /* DDR2 only */ + MV_U32 minReadToPrechCmdDelay; /* DDR2 only */ + MV_U32 minRefreshToActiveCmd; /* DDR2 only */ + + /* Parameters calculated from the extracted DIMM information */ + MV_U32 size; + MV_U32 deviceDensity; /* 16,64,128,256 or 512 Mbit */ + MV_U32 numberOfDevices; + + /* DIMM attributes (MV_TRUE for yes) */ + MV_BOOL registeredAddrAndControlInputs; + MV_BOOL registeredDQMBinputs; + +}MV_DRAM_BANK_INFO; + +#include "ddr2/spd/mvSpd.h" + +/* mvDramIf.h API list */ +MV_VOID mvDramIfBasicAsmInit(MV_VOID); +MV_STATUS mvDramIfDetect(MV_U32 forcedCl, MV_BOOL eccDisable); +MV_VOID _mvDramIfConfig(int entryNum); + +MV_U32 mvDramIfBankSizeGet(MV_U32 bankNum); +MV_U32 mvDramIfBankBaseGet(MV_U32 bankNum); +MV_U32 mvDramIfSizeGet(MV_VOID); +MV_U32 mvDramIfCalGet(void); +MV_STATUS mvDramIfSingleBitErrThresholdSet(MV_U32 threshold); +MV_VOID mvDramIfSelfRefreshSet(void); +void mvDramIfShow(void); +MV_U32 mvDramIfGetFirstCS(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvDramIfh */ diff --git a/board/mv_feroceon/mv_hal/ddr2/mvDramIfBasicInit.S b/board/mv_feroceon/mv_hal/ddr2/mvDramIfBasicInit.S new file mode 100644 index 0000000..9f6fa0a --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr2/mvDramIfBasicInit.S @@ -0,0 +1,907 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define _ASMLANGUAGE +#define MV_ASMLANGUAGE +#include "mvSysHwConfig.h" +#include "mvOsAsm.h" +#include "mvBoardEnvSpec.h" +#include "mvCpuIfRegs.h" +#include "mvDramIfConfig.h" +#include "mvDramIfRegs.h" +#include "pex/mvPexRegs.h" +#include "mvCtrlEnvSpec.h" +#include "mvCtrlEnvAsm.h" +#include "mvCommon.h" + +/* defines */ + +#if defined(MV_STATIC_DRAM_ON_BOARD) +.globl dramBoot1 +dramBoot1: + .word 0 + +/****************************************************************************** +* +* +* +* +*******************************************************************************/ +#if defined(DB_MV78XX0) +/* DDR2 boards 512MB 333MHz */ +#define STATIC_SDRAM0_BANK0_SIZE 0x1ffffff1 /* 0x1504 */ +#define STATIC_SDRAM_CONFIG 0x43048C30 /* 0x1400 */ +#define STATIC_SDRAM_MODE 0x00000652 /* 0x141c */ +#define STATIC_DUNIT_CTRL_LOW 0x38543000 /* 0x1404 */ +#define STATIC_DUNIT_CTRL_HI 0x0000FFFF /* 0x1424 */ +#define STATIC_SDRAM_ADDR_CTRL 0x00000088 /* 0x1410 */ +#define STATIC_SDRAM_TIME_CTRL_LOW 0x22125441 /* 0x1408 */ +#define STATIC_SDRAM_TIME_CTRL_HI 0x00000829 /* 0x140c */ +#define STATIC_SDRAM_ODT_CTRL_LOW 0x84210000 /* 0x1494 */ +#define STATIC_SDRAM_ODT_CTRL_HI 0x00000000 /* 0x1498 */ +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0000E80F /* 0x149c */ +#define STATIC_SDRAM_EXT_MODE 0x00000040 /* 0x1420 */ +#define STATIC_SDRAM_DDR2_TIMING_LO 0x00085520 /* 0x1428 */ +#define STATIC_SDRAM_DDR2_TIMING_HI 0x00008552 /* 0x147C */ + +#elif defined(RD_MV78XX0_H3C) +/* DDR2 boards 512MB 333MHz */ +#define STATIC_SDRAM0_BANK0_SIZE 0x1ffffff1 /* 0x1504 */ +#define STATIC_SDRAM_CONFIG 0x43048a25 /* 0x1400 */ +#define STATIC_SDRAM_MODE 0x00000652 /* 0x141c */ +#define STATIC_DUNIT_CTRL_LOW 0x38543000 /* 0x1404 */ +#define STATIC_DUNIT_CTRL_HI 0x0000F07F /* 0x1424 */ +#define STATIC_SDRAM_ADDR_CTRL 0x00000088 /* 0x1410 */ +#define STATIC_SDRAM_TIME_CTRL_LOW 0x2202444e /* 0x1408 */ +#define STATIC_SDRAM_TIME_CTRL_HI 0x00000822 /* 0x140c */ +#define STATIC_SDRAM_ODT_CTRL_LOW 0x84210000 /* 0x1494 */ +#define STATIC_SDRAM_ODT_CTRL_HI 0x00000000 /* 0x1498 */ +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0000EB0F /* 0x149c */ +#define STATIC_SDRAM_EXT_MODE 0x00000040 /* 0x1420 */ +#define STATIC_SDRAM_DDR2_TIMING_LO 0x00085520 /* 0x1428 */ +#define STATIC_SDRAM_DDR2_TIMING_HI 0x00008552 /* 0x147C */ +#else +/* DDR2 MV88F6281 boards 256MB 400MHz */ +#define STATIC_SDRAM0_BANK0_SIZE 0x0FFFFFF1 /* 0x1504 */ +#define STATIC_SDRAM_CONFIG 0x43000c30 /* 0x1400 */ +#define STATIC_SDRAM_MODE 0x00000C52 /* 0x141c */ +#define STATIC_DUNIT_CTRL_LOW 0x39543000 /* 0x1404 */ +#define STATIC_DUNIT_CTRL_HI 0x0000F1FF /* 0x1424 */ +#define STATIC_SDRAM_ADDR_CTRL 0x000000cc /* 0x1410 */ +#define STATIC_SDRAM_TIME_CTRL_LOW 0x22125451 /* 0x1408 */ +#define STATIC_SDRAM_TIME_CTRL_HI 0x00000833 /* 0x140c */ +#define STATIC_SDRAM_ODT_CTRL_LOW 0x003C0000 /* 0x1494 */ +#define STATIC_SDRAM_ODT_CTRL_HI 0x00000000 /* 0x1498 */ +#define STATIC_SDRAM_DUNIT_ODT_CTRL 0x0000F80F /* 0x149c */ +#define STATIC_SDRAM_EXT_MODE 0x00000042 /* 0x1420 */ +#define STATIC_SDRAM_DDR2_TIMING_LO 0x00085520 /* 0x1428 */ +#define STATIC_SDRAM_DDR2_TIMING_HI 0x00008552 /* 0x147C */ +#endif /* MV78XX0 */ + + .globl _mvDramIfStaticInit +_mvDramIfStaticInit: + + mov r11, LR /* Save link register */ + mov r10, r2 + + /*DDR SDRAM Initialization Control */ + ldr r6, =DSICR_INIT_EN + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +2: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + and r6, r6, #DSICR_INIT_EN + cmp r6, #0 + bne 2b + + /* If we boot from NAND jump to DRAM address */ + mov r5, #1 + ldr r6, =dramBoot1 + str r5, [r6] /* We started executing from DRAM */ + + ldr r6, dramBoot1 + cmp r6, #0 + bne 1f + + /* set all dram windows to 0 */ + mov r6, #0 + MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,0)) + MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,1)) + MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,2)) + MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,3)) + ldr r6, = STATIC_SDRAM0_BANK0_SIZE + MV_REG_WRITE_ASM(r6, r5, SDRAM_SIZE_REG(0,0)) + + + /* set all dram configuration in temp registers */ + ldr r6, = STATIC_SDRAM0_BANK0_SIZE + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG0) + ldr r6, = STATIC_SDRAM_CONFIG + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG1) + ldr r6, = STATIC_SDRAM_MODE + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG2) + ldr r6, = STATIC_DUNIT_CTRL_LOW + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG3) + ldr r6, = STATIC_SDRAM_ADDR_CTRL + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG4) + ldr r6, = STATIC_SDRAM_TIME_CTRL_LOW + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG5) + ldr r6, = STATIC_SDRAM_TIME_CTRL_HI + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG6) + ldr r6, = STATIC_SDRAM_ODT_CTRL_LOW + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG7) + ldr r6, = STATIC_SDRAM_ODT_CTRL_HI + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG8) + ldr r6, = STATIC_SDRAM_DUNIT_ODT_CTRL + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG9) + ldr r6, = STATIC_SDRAM_EXT_MODE + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG10) + ldr r6, = STATIC_SDRAM_DDR2_TIMING_LO + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG11) + ldr r6, = STATIC_SDRAM_DDR2_TIMING_HI + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG12) +#ifndef MV_NAND_BOOT + ldr r6, = STATIC_DUNIT_CTRL_HI + MV_REG_WRITE_ASM(r6, r5, DRAM_BUF_REG13) +#endif + + ldr sp,=0 + bl _mvDramIfConfig + ldr r0, =0 +#ifdef MV78XX0 + bl _mvDramIfEccMemInit +#endif +1: + mov r2, r10 + mov PC, r11 /* r11 is saved link register */ + +#else /* #if defined(MV_STATIC_DRAM_ON_BOARD) */ + +.globl dramBoot1 +dramBoot1: + .word 0 + +/******************************************************************************* +* mvDramIfBasicInit - Basic initialization of DRAM interface +* +* DESCRIPTION: +* The function will initialize the DRAM for basic usage. The function +* will use the TWSI assembly API to extract DIMM parameters according +* to which DRAM interface will be initialized. +* The function referes to the following DRAM parameters: +* 1) DIMM is registered or not. +* 2) DIMM width detection. +* 3) DIMM density. +* +* INPUT: +* r3 - required size for initial DRAM. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +* Note: +* r4 holds I2C EEPROM address +* r5 holds SDRAM register base address +* r7 holds returned values +* r8 holds SDRAM various configuration registers value. +* r11 holds return function address. +*******************************************************************************/ +/* Setting the offsets of the I2C registers */ +#define DIMM_TYPE_OFFSET 2 +#define NUM_OF_ROWS_OFFSET 3 +#define NUM_OF_COLS_OFFSET 4 +#define NUM_OF_RANKS 5 +#define DIMM_CONFIG_TYPE 11 +#define SDRAM_WIDTH_OFFSET 13 +#define NUM_OF_BANKS_OFFSET 17 +#define SUPPORTED_CL_OFFSET 18 +#define DIMM_TYPE_INFO_OFFSET 20 /* DDR2 only */ +#define SDRAM_MODULES_ATTR_OFFSET 21 +#define RANK_SIZE_OFFSET 31 + +#define DRAM_DEV_DENSITY_128M 128 +#define DRAM_DEV_DENSITY_256M 256 +#define DRAM_DEV_DENSITY_512M 512 +#define DRAM_DEV_DENSITY_1G 1024 +#define DRAM_DEV_DENSITY_2G 2048 + +#define DRAM_RANK_DENSITY_128M 0x20 +#define DRAM_RANK_DENSITY_256M 0x40 +#define DRAM_RANK_DENSITY_512M 0x80 +#define DRAM_RANK_DENSITY_1G 0x1 +#define DRAM_RANK_DENSITY_2G 0x2 + + .globl _mvDramIfBasicInit + .extern _i2cInit +_mvDramIfBasicInit: + + mov r11, LR /* Save link register */ + + /* Set Dunit high control register */ + MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_HI_REG) + orr r6, r6, #BIT7 /* SDRAM__D2P_EN */ + orr r6, r6, #BIT8 /* SDRAM__P2D_EN */ +#ifdef MV78XX0 + orr r6, r6, #BIT9 /* SDRAM__ADD_HALF_FCC_EN */ + orr r6, r6, #BIT10 /* SDRAM__PUP_ZERO_SKEW_EN */ + orr r6, r6, #BIT11 /* SDRAM__WR_MASH_DELAY_EN */ +#endif + MV_REG_WRITE_ASM (r6, r5, SDRAM_DUNIT_CTRL_HI_REG) + +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_REG) + orr r6, r6, #BIT4 /* Enable 2T mode */ + bic r6, r6, #BIT6 /* clear ctrlPos */ + MV_REG_WRITE_ASM (r6, r5, SDRAM_DUNIT_CTRL_REG) +#endif + + /*DDR SDRAM Initialization Control */ + ldr r6, =DSICR_INIT_EN + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +2: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + and r6, r6, #DSICR_INIT_EN + cmp r6, #0 + bne 2b + + mov r5, #1 + ldr r8, =dramBoot1 + str r5, [r8] /* We started executing from DRAM */ + + /* If we boot from NAND jump to DRAM sddress */ + ldr r8, dramBoot1 + cmp r8, #0 + movne pc, r11 + + bl _i2cInit /* Initialize TWSI master */ + + /* Check if we have more then 1 dimm */ + ldr r6, =0 + MV_REG_WRITE_ASM (r6, r1, DRAM_BUF_REG14) +#ifdef MV78XX0 + bl _is_Second_Dimm_Exist + beq single_dimm + ldr r6, =1 + MV_REG_WRITE_ASM (r6, r1, DRAM_BUF_REG14) +single_dimm: + bl _i2cInit /* Initialize TWSI master */ +#endif + + /* Get default SDRAM Config values */ + MV_REG_READ_ASM (r8, r5, SDRAM_CONFIG_REG) + + /* Get registered/non registered info from DIMM */ + bl _is_Registered + beq nonRegistered + +setRegistered: + orr r8, r8, #SDRAM_REGISTERED /* Set registered bit(17) */ +nonRegistered: +#ifdef MV78XX0 + /* Get ECC/non ECC info from DIMM */ + bl _is_Ecc + beq setConfigReg + +setEcc: + orr r8, r8, #SDRAM_ECC_EN /* Set ecc bit(18) */ +#endif +setConfigReg: + MV_REG_WRITE_ASM (r8, r5, DRAM_BUF_REG1) + + /* Set maximum CL supported by DIMM */ + bl _get_CAL + + /* r7 is DIMM supported CAS (e.g: 3 --> 0x1C) */ + clz r6, r7 + rsb r6, r6, #31 /* r6 = the bit number of MAX CAS supported */ + +casDdr2: + ldr r7, =0x62 /* stBurstInDel|stBurstOutDel field value */ + ldr r3, =0x74 /* stBurstInDel|stBurstOutDel registered value*/ + ldr r8, =0x32 /* Assuming MAX CL = 3 */ + cmp r6, #3 /* If CL = 3 break */ + beq casDdr2Cont + + ldr r7, =0x74 /* stBurstInDel|stBurstOutDel field value */ + ldr r3, =0x86 /* stBurstInDel|stBurstOutDel registered value*/ + ldr r8, =0x42 /* Assuming MAX CL = 4 */ + cmp r6, #4 /* If CL = 4 break */ + beq casDdr2Cont + + ldr r7, =0x96 /* stBurstInDel|stBurstOutDel field value */ + ldr r3, =0xa8 /* stBurstInDel|stBurstOutDel registered value*/ + ldr r8, =0x52 /* Assuming MAX CL = 5 */ + cmp r6, #5 /* If CL = 5 break */ + beq casDdr2Cont + + ldr r7, =0xa8 /* stBurstInDel|stBurstOutDel field value */ + ldr r3, =0xba /* stBurstInDel|stBurstOutDel registered value*/ + ldr r8, =0x62 /* Assuming MAX CL = 6 */ + cmp r6, #6 /* If CL = 5 break */ + beq casDdr2Cont + + /* This is an error. return */ + b exit_ddrAutoConfig /* This is an error !! */ +casDdr2Cont: + + /* Get default SDRAM Mode values */ + MV_REG_READ_ASM (r6, r5, SDRAM_MODE_REG) + bic r6, r6, #(BIT6 | BIT5 | BIT4) /* Clear CL filed */ + orr r6, r6, r8 + MV_REG_WRITE_ASM (r6, r5, DRAM_BUF_REG2) + + /* Set Dunit control register according to max CL detected */ + MV_REG_READ_ASM (r6, r5, DRAM_BUF_REG1) + tst r6, #SDRAM_REGISTERED + beq setDunitReg + mov r7, r3 + +setDunitReg: + MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_REG) + bic r6, r6, #(0xff << 20) /* Clear SBout and SBin */ + orr r6, r6, #BIT4 /* Enable 2T mode */ + bic r6, r6, #BIT6 /* clear ctrlPos */ + orr r6, r6, r7, LSL #20 + MV_REG_WRITE_ASM (r6, r5, DRAM_BUF_REG3) + + /* Set Dunit high control register */ + MV_REG_READ_ASM (r6, r5, SDRAM_DUNIT_CTRL_HI_REG) + orr r6, r6, #BIT7 /* SDRAM__D2P_EN */ + orr r6, r6, #BIT8 /* SDRAM__P2D_EN */ +#ifdef MV78XX0 + orr r6, r6, #BIT9 /* SDRAM__ADD_HALF_FCC_EN */ + orr r6, r6, #BIT10 /* SDRAM__PUP_ZERO_SKEW_EN */ + orr r6, r6, #BIT11 /* SDRAM__WR_MASH_DELAY_EN */ +#endif + MV_REG_WRITE_ASM (r6, r5, DRAM_BUF_REG13) + + /* DIMM density configuration*/ + /* Density = (1 << (rowNum + colNum)) * dramWidth * dramBankNum */ +Density: + /* Get bank 0 and 1 density */ + ldr r6, =0 + bl _getDensity + + mov r8, r7 + mov r8, r8, LSR #20 /* Move density 20 bits to the right */ + /* For example 0x10000000 --> 0x1000 */ + + mov r3, #(SDRAM_DSIZE_256Mb(0) | SDRAM_DSIZE_256Mb(1)) + cmp r8, #DRAM_DEV_DENSITY_256M + beq get_bank_2_density + + mov r3, #(SDRAM_DSIZE_512Mb(0) | SDRAM_DSIZE_512Mb(1)) + cmp r8, #DRAM_DEV_DENSITY_512M + beq get_bank_2_density + + mov r3, #(SDRAM_DSIZE_1Gb(0) | SDRAM_DSIZE_1Gb(1)) + cmp r8, #DRAM_DEV_DENSITY_1G + beq get_bank_2_density + + mov r3, #(SDRAM_DSIZE_2Gb(0) | SDRAM_DSIZE_2Gb(1)) + cmp r8, #DRAM_DEV_DENSITY_2G + beq get_bank_2_density + + /* This is an error. return */ + b exit_ddrAutoConfig + +get_bank_2_density: + /* Check for second dimm */ + MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14) + cmp r6, #1 + bne get_width + + /* Get bank 2 and 3 density */ + ldr r6, =2 + bl _getDensity + + mov r8, r7 + mov r8, r8, LSR #20 /* Move density 20 bits to the right */ + /* For example 0x10000000 --> 0x1000 */ + + orr r3, r3, #(SDRAM_DSIZE_256Mb(2) | SDRAM_DSIZE_256Mb(3)) + cmp r8, #DRAM_DEV_DENSITY_256M + beq get_width + + and r3, r3, #~(SDRAM_DSIZE_MASK(2) | SDRAM_DSIZE_MASK(3)) + orr r3, r3, #(SDRAM_DSIZE_512Mb(2) | SDRAM_DSIZE_512Mb(3)) + cmp r8, #DRAM_DEV_DENSITY_512M + beq get_width + + and r3, r3, #~(SDRAM_DSIZE_MASK(2) | SDRAM_DSIZE_MASK(3)) + orr r3, r3, #(SDRAM_DSIZE_1Gb(2) | SDRAM_DSIZE_1Gb(3)) + cmp r8, #DRAM_DEV_DENSITY_1G + beq get_width + + and r3, r3, #~(SDRAM_DSIZE_MASK(2) | SDRAM_DSIZE_MASK(3)) + orr r3, r3, #(SDRAM_DSIZE_2Gb(2) | SDRAM_DSIZE_2Gb(3)) + cmp r8, #DRAM_DEV_DENSITY_2G + beq get_width + + /* This is an error. return */ + b exit_ddrAutoConfig + + /* Get SDRAM width */ +get_width: + /* Get bank 0 and 1 width */ + ldr r6, =0 + bl _get_width + + cmp r7, #8 /* x8 devices */ + beq get_bank_2_width + + orr r3, r3, #(SDRAM_ADDRSEL_X16(0) | SDRAM_ADDRSEL_X16(1)) /* x16 devices */ + cmp r7, #16 + beq get_bank_2_width + + /* This is an error. return */ + b exit_ddrAutoConfig + +get_bank_2_width: + /* Check for second dimm */ + MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14) + cmp r6, #1 + bne densCont + + /* Get bank 2 and 3 width */ + ldr r6, =2 + bl _get_width + + cmp r7, #8 /* x8 devices */ + beq densCont + + orr r3, r3, #(SDRAM_ADDRSEL_X16(2) | SDRAM_ADDRSEL_X16(3)) /* x16 devices */ + cmp r7, #16 + beq densCont + + /* This is an error. return */ + b exit_ddrAutoConfig + +densCont: + MV_REG_WRITE_ASM (r3, r5, DRAM_BUF_REG4) + + /* Set SDRAM timing control low register */ + ldr r4, =SDRAM_TIMING_CTRL_LOW_REG_DEFAULT + /* MV_REG_READ_ASM (r4, r5, SDRAM_TIMING_CTRL_LOW_REG) */ + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG5) + + /* Set SDRAM timing control high register */ + ldr r4, =SDRAM_TIMING_CTRL_HIGH_REG_DEFAULT + /* MV_REG_READ_ASM (r4, r5, SDRAM_TIMING_CTRL_HIGH_REG) */ + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG6) + + /* Check for second dimm */ + MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14) + cmp r6, #1 + bne single_dimm_odt + + /* Set SDRAM ODT control low register for double DIMM*/ + ldr r4, =DDR2_ODT_CTRL_LOW_CS0_CS1_CS2_CS3_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG7) + + /* Set DUNIT ODT control register for double DIMM */ + ldr r4, =DDR2_DUNIT_ODT_CTRL_CS0_CS1_CS2_CS3_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG9) + +#ifdef MV78XX0 + /* Set SDRAM Extended Mode register for double DIMM */ + /* Check DRAM frequency for more then 267MHz set ODT Rtt to 50ohm */ + + MV_REG_READ_ASM (r4, r5, CPU_RESET_SAMPLE_L_REG) + ldr r5, =MSAR_SYSCLCK_MASK + and r4, r4, r5 + ldr r5, =MSAR_SYSCLCK_267 + cmp r4, r5 + beq fast_dram_clock_rtt + ldr r5, =MSAR_SYSCLCK_300 + cmp r4, r5 + beq fast_dram_clock_rtt + ldr r5, =MSAR_SYSCLCK_333 + cmp r4, r5 + beq fast_dram_clock_rtt + ldr r5, =MSAR_SYSCLCK_400 + cmp r4, r5 + beq fast_dram_clock_rtt + + b slow_dram_clock_rtt + +fast_dram_clock_rtt: + ldr r4, =DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG10) + b odt_config_end +#endif +slow_dram_clock_rtt: + ldr r4, =DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG10) + b odt_config_end + +single_dimm_odt: + /* Set SDRAM ODT control low register */ + ldr r4, =DDR2_ODT_CTRL_LOW_CS0_CS1_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG7) + + /* Set DUNIT ODT control register */ + ldr r4, =DDR2_DUNIT_ODT_CTRL_CS0_CS1_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG9) + + /* Set SDRAM Extended Mode register */ + ldr r4, =DDR_SDRAM_EXT_MODE_CS0_CS1_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG10) + +odt_config_end: + /* SDRAM ODT control high register is left as default */ + MV_REG_READ_ASM (r4, r5, DDR2_SDRAM_ODT_CTRL_HIGH_REG) + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG8) + + /* Set SDRAM Ddr2 Timing Low register */ + ldr r4, =DD2_SDRAM_TIMING_LOW_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG11) + + /* Set SDRAM Ddr2 Timing High register */ + ldr r4, =DDR2_SDRAM_TIMING_HIGH_DV + MV_REG_WRITE_ASM(r4, r5, DRAM_BUF_REG12) + +timeParamDone: + /* Close all windows */ + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,0)) + and r6, r6,#~SCSR_SIZE_MASK + and r6, r6,#~1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,0)) + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,1)) + and r6, r6,#~SCSR_SIZE_MASK + and r6, r6,#~1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,1)) + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,2)) + and r6, r6,#~SCSR_SIZE_MASK + and r6, r6,#~1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,2)) + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,3)) + and r6, r6,#~SCSR_SIZE_MASK + and r6, r6,#~1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,3)) + + /* Set sdram bank 0 size and enable it */ + ldr r6, =0 + bl _mvDramIfGetDimmSizeFromSpd +#ifdef MV78XX0 + /* Check DRAM width */ + MV_REG_READ_ASM (r4, r5, SDRAM_CONFIG_REG) + ldr r5, =SDRAM_DWIDTH_MASK + and r4, r4, r5 + ldr r5, =SDRAM_DWIDTH_64BIT + cmp r4, r5 + beq dram_64bit_width + /* Utilize only 32bit width */ + mov r8, r8, LSR #1 +#else + /* Utilize only 16bit width */ + mov r8, r8, LSR #2 +#endif +dram_64bit_width: + /* Update first dimm size return value R8 */ + MV_REG_READ_ASM (r5, r6, SDRAM_SIZE_REG(0,0)) + ldr r6, =~SCSR_SIZE_MASK + and r5, r5, r6 + orr r5, r5, r8 + MV_REG_WRITE_ASM(r5, r8, SDRAM_SIZE_REG(0,0)) + + /* Clear bank 2 size */ + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,2)) + and r6, r6,#~SCSR_SIZE_MASK + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,2)) + + /* Check for second dimm */ + MV_REG_READ_ASM (r6, r1, DRAM_BUF_REG14) + cmp r6, #1 + bne defualt_order + + /* Set sdram bank 2 size */ + ldr r6, =2 + bl _mvDramIfGetDimmSizeFromSpd +#ifdef MV78XX0 + /* Check DRAM width */ + MV_REG_READ_ASM (r4, r5, SDRAM_CONFIG_REG) + ldr r5, =SDRAM_DWIDTH_MASK + and r4, r4, r5 + ldr r5, =SDRAM_DWIDTH_64BIT + cmp r4, r5 + beq dram_64bit_width2 + /* Utilize only 32bit width */ + mov r8, r8, LSR #1 +#else + /* Utilize only 16bit width */ + mov r8, r8, LSR #2 +#endif +dram_64bit_width2: + /* Update first dimm size return value R8 */ + MV_REG_READ_ASM (r5, r6, SDRAM_SIZE_REG(0,2)) + ldr r6, =~SCSR_SIZE_MASK + and r5, r5, r6 + orr r5, r5, r8 + MV_REG_WRITE_ASM(r5, r8, SDRAM_SIZE_REG(0,2)) + + /* Close windows 1 and 3 */ + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,1)) + and r6, r6,#~1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,1)) + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,3)) + and r6, r6,#~1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,3)) + + /* Check dimm size for setting dram bank order */ + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,0)) + MV_REG_READ_ASM (r4, r5, SDRAM_SIZE_REG(0,2)) + and r6, r6,#SCSR_SIZE_MASK + and r4, r4,#SCSR_SIZE_MASK + cmp r6, r4 + bge defualt_order + + /* Bank 2 is biger then bank 0 */ + ldr r6,=0 + MV_REG_WRITE_ASM (r6, r5, SDRAM_BASE_ADDR_REG(0,2)) + + /* Open win 2 */ + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,2)) + orr r6, r6,#1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,2)) + + ldr sp,=0 + bl _mvDramIfConfig +#ifdef MV78XX0 + /* Init ECC on CS 2 */ + ldr r0, =2 + bl _mvDramIfEccMemInit +#endif + mov PC, r11 /* r11 is saved link register */ + +defualt_order: + + /* Open win 0 */ + MV_REG_READ_ASM (r6, r5, SDRAM_SIZE_REG(0,0)) + orr r6, r6,#1 + MV_REG_WRITE_ASM (r6, r5, SDRAM_SIZE_REG(0,0)) + + ldr sp,=0 + bl _mvDramIfConfig +#ifdef MV78XX0 + /* Init ECC on CS 0 */ + ldr r0, =0 + bl _mvDramIfEccMemInit +#endif +exit_ddrAutoConfig: + mov PC, r11 /* r11 is saved link register */ + + +/***************************************************************************************/ +/* r4 holds I2C EEPROM address + * r7 holds I2C EEPROM offset parameter for i2cRead and its --> returned value + * r8 holds SDRAM various configuration registers value. + * r13 holds Link register + */ +/**************************/ +_getDensity: + mov r13, LR /* Save link register */ + + /* Read SPD rank size from DIMM0 */ + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + + cmp r6, #0 + beq 1f + + /* Read SPD rank size from DIMM1 */ + mov r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM1 */ + +1: + mov r7, #NUM_OF_ROWS_OFFSET /* offset 3 */ + bl _i2cRead + mov r8, r7 /* r8 save number of rows */ + + mov r7, #NUM_OF_COLS_OFFSET /* offset 4 */ + bl _i2cRead + add r8, r8, r7 /* r8 = number of rows + number of col */ + + mov r7, #0x1 + mov r8, r7, LSL r8 /* r8 = (1 << r8) */ + + mov r7, #SDRAM_WIDTH_OFFSET /* offset 13 */ + bl _i2cRead + mul r8, r7, r8 + + mov r7, #NUM_OF_BANKS_OFFSET /* offset 17 */ + bl _i2cRead + mul r7, r8, r7 + + mov PC, r13 + +/**************************/ +_get_width: + mov r13, LR /* Save link register */ + + /* Read SPD rank size from DIMM0 */ + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + + cmp r6, #0 + beq 1f + + /* Read SPD rank size from DIMM1 */ + mov r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM1 */ + +1: + /* Get SDRAM width (SPD offset 13) */ + mov r7, #SDRAM_WIDTH_OFFSET + bl _i2cRead /* result in r7 */ + + mov PC, r13 + +/**************************/ +_get_CAL: + mov r13, LR /* Save link register */ + + /* Set maximum CL supported by DIMM */ + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #SUPPORTED_CL_OFFSET /* offset 18 */ + bl _i2cRead + + mov PC, r13 + +/**************************/ +/* R8 - sdram configuration register. + * Return value in flag if no-registered then Z-flag is set + */ +_is_Registered: + mov r13, LR /* Save link register */ +#if defined(MV645xx) + /* Get registered/non registered info from DIMM */ + tst r8, #SDRAM_DTYPE_DDR2 + bne regDdr2 + +regDdr1: + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #SDRAM_MODULES_ATTR_OFFSET + bl _i2cRead /* result in r7 */ + + tst r7, #0x2 + b exit +#endif +regDdr2: + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #DIMM_TYPE_INFO_OFFSET + bl _i2cRead /* result in r7 */ + + tst r7, #0x11 /* DIMM type = regular RDIMM (0x01) */ + /* or Mini-RDIMM (0x10) */ +exit: + mov PC, r13 + + +/**************************/ +/* Return value in flag if no-Ecc then Z-flag is set */ +_is_Ecc: + mov r13, LR /* Save link register */ + + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + mov r7, #DIMM_CONFIG_TYPE + bl _i2cRead /* result in r7 */ + + tst r7, #0x2 /* bit 1 -> Data ECC */ + mov PC, r13 + +/**************************/ +/* Return value in flag if no second DIMM then Z-flag is set */ +_is_Second_Dimm_Exist: + mov r13, LR /* Save link register */ + + mov r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM0 */ + mov r7, #DIMM_TYPE_OFFSET + bl _i2cRead /* result in r7 */ + + tst r7, #0x8 /* bit3 is '1' -> DDR 2 */ + mov PC, r13 + +/******************************************************************************* +* _mvDramIfGetDimmSizeFromSpd - read bank 0 dram's size +* +* DESCRIPTION: +* The function will read the bank 0 dram size(SPD version 1.0 and above ) +* +* INPUT: +* r6 - dram bank number. +* +* OUTPUT: +* none +*/ +_mvDramIfGetDimmSizeFromSpd: + + mov r13, LR /* Save link register */ + + /* Read SPD rank size from DIMM0 */ + mov r4, #MV_BOARD_DIMM0_I2C_ADDR /* reading from DIMM0 */ + + cmp r6, #0 + beq 1f + + /* Read SPD rank size from DIMM1 */ + mov r4, #MV_BOARD_DIMM1_I2C_ADDR /* reading from DIMM1 */ + +1: + mov r7, #RANK_SIZE_OFFSET /* offset 31 */ + bl _i2cRead + +pass_read: + ldr r8, =(0xf << SCSR_SIZE_OFFS) + cmp r7, #DRAM_RANK_DENSITY_256M + beq endDimmSize + + ldr r8, =(0x1f << SCSR_SIZE_OFFS) + cmp r7, #DRAM_RANK_DENSITY_512M + beq endDimmSize + + ldr r8, =(0x3f << SCSR_SIZE_OFFS) + cmp r7, #DRAM_RANK_DENSITY_1G + beq endDimmSize + + ldr r8, =(0x7f << SCSR_SIZE_OFFS) /* DRAM_RANK_DENSITY_2G */ +endDimmSize: + mov PC, r13 +#endif diff --git a/board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.S b/board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.S new file mode 100644 index 0000000..80308fd --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.S @@ -0,0 +1,513 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvDramIfBasicAsm.s +* +* DESCRIPTION: +* Memory full detection and best timing configuration is done in +* C code. C runtime environment requires a stack. This module API +* initialize DRAM interface chip select 0 for basic functionality for +* the use of stack. +* The module API assumes DRAM information is stored in I2C EEPROM reside +* in a given I2C address MV_BOARD_DIMM0_I2C_ADDR. The I2C EEPROM +* internal data structure is assumed to be orgenzied in common DRAM +* vendor SPD structure. +* NOTE: DFCDL values are assumed to be already initialized prior to +* this module API activity. +* +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +/* includes */ +#define _ASMLANGUAGE +#define MV_ASMLANGUAGE +#include "mvOsAsm.h" +#include "mvSysHwConfig.h" +#include "mvDramIfRegs.h" +#include "mvDramIfConfig.h" +#include "mvCpuIfRegs.h" +#include "pex/mvPexRegs.h" +#include "mvCtrlEnvSpec.h" +#include "mvCommon.h" + +/* defines */ + +/* locals */ +.data +.globl _mvDramIfConfig +.text +.globl _mvDramIfMemInit + +/******************************************************************************* +* _mvDramIfConfig - Basic DRAM interface initialization. +* +* DESCRIPTION: +* The function will initialize the following DRAM parameters using the +* values prepared by mvDramIfDetect routine. Values are located +* in predefined registers. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ + +_mvDramIfConfig: + + /* Save register on stack */ + cmp sp, #0 + beq no_stack_s +save_on_stack: + stmdb sp!, {r1, r2, r3, r4} +no_stack_s: + + /* 1) Write to SDRAM coniguration register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG1) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_CONFIG_REG) + str r4, [r1] + + /* 2) Write Dunit control low register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG3) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_DUNIT_CTRL_REG) + str r4, [r1] + + /* 2) Write Dunit control high register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG13) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_DUNIT_CTRL_HI_REG) + str r4, [r1] + + /* 3) Write SDRAM address control register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG4) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_ADDR_CTRL_REG) + str r4, [r1] +#if defined(MV_STATIC_DRAM_ON_BOARD) + /* 4) Write SDRAM bank 0 size register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG0) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_SIZE_REG(0,0)) + str r4, [r1] +#endif + + /* 5) Write SDRAM open pages control register */ + ldr r1, =(INTER_REGS_BASE + SDRAM_OPEN_PAGE_CTRL_REG) + ldr r4, =SDRAM_OPEN_PAGES_CTRL_REG_DV + str r4, [r1] + + /* 6) Write SDRAM timing Low register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG5) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_TIMING_CTRL_LOW_REG) + str r4, [r1] + + /* 7) Write SDRAM timing High register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG6) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_TIMING_CTRL_HIGH_REG) + str r4, [r1] + + /* Config DDR2 On Die Termination (ODT) registers */ + /* Write SDRAM DDR2 ODT control low register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG7) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + DDR2_SDRAM_ODT_CTRL_LOW_REG) + str r4, [r1] + + /* Write SDRAM DDR2 ODT control high register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG8) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + DDR2_SDRAM_ODT_CTRL_HIGH_REG) + str r4, [r1] + + /* Write SDRAM DDR2 Dunit ODT control register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG9) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + DDR2_DUNIT_ODT_CONTROL_REG) + str r4, [r1] + + /* Write DDR2 SDRAM timing Low register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG11) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_DDR2_TIMING_LO_REG) + str r4, [r1] + + /* Write DDR2 SDRAM timing High register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG12) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_DDR2_TIMING_HI_REG) + str r4, [r1] + + /* 8) Write SDRAM mode register */ + /* The CPU must not attempt to change the SDRAM Mode register setting */ + /* prior to DRAM controller completion of the DRAM initialization */ + /* sequence. To guarantee this restriction, it is recommended that */ + /* the CPU sets the SDRAM Operation register to NOP command, performs */ + /* read polling until the register is back in Normal operation value, */ + /* and then sets SDRAM Mode register to its new value. */ + + /* 8.1 write 'nop' to SDRAM operation */ + mov r4, #0x5 /* 'NOP' command */ + MV_REG_WRITE_ASM(r4, r1, SDRAM_OPERATION_REG) + + /* 8.2 poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll1: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll1 + + /* 8.3 Now its safe to write new value to SDRAM Mode register */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG2) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_MODE_REG) + str r4, [r1] + + /* 8.4 Make the Dunit write the DRAM its new mode */ + mov r4, #0x3 /* Mode Register Set command */ + MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG) + + /* 8.5 poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll2: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll2 + + /* Now its safe to write new value to SDRAM Extended Mode regist */ + ldr r1, =(INTER_REGS_BASE + DRAM_BUF_REG10) + ldr r4, [r1] + ldr r1, =(INTER_REGS_BASE + SDRAM_EXTENDED_MODE_REG) + str r4, [r1] + + /* 9) Write SDRAM Extended mode register This operation should be */ + /* done for each memory bank */ + /* write 'nop' to SDRAM operation */ + mov r4, #0x5 /* 'NOP' command */ + MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll3: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll3 + /* Go over each of the Banks */ + ldr r3, =0 /* r3 = DRAM bank Num */ + +extModeLoop: + /* Set the SDRAM Operation Control to each of the DRAM banks */ + mov r4, r3 /* Do not swap the bank counter value */ + MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_CTRL_REG) + + /* Make the Dunit write the DRAM its new mode */ + mov r4, #0x4 /* Extended Mode Register Set command */ + MV_REG_WRITE_ASM (r4, r1, SDRAM_OPERATION_REG) + + /* poll SDRAM operation. Make sure its back to normal operation */ +_sdramOpPoll4: + ldr r4, [r1] + cmp r4, #0 /* '0' = Normal SDRAM Mode */ + bne _sdramOpPoll4 + + add r3, r3, #1 + cmp r3, #4 /* 4 = Number of banks */ + bne extModeLoop + +extModeEnd: +cmp sp, #0 + beq no_stack_l + mov r1, LR /* Save link register */ +#if defined(MV78XX0) + bl _mvDramIfMemInit +#endif + mov LR,r1 /* restore link register */ +load_from_stack: + /* Restore registers */ + ldmia sp!, {r1, r2, r3, r4} +no_stack_l: + + mov pc, lr + + +/******************************************************************************* +* _mvDramIfEccMemInit - Basic DRAM ECC initialization. +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +#define XOR_CHAN0 0 /* XOR channel 0 used for memory initialization */ +#define XOR_ADDR_DEC_WIN0 0 /* Enable DRAM access using XOR decode window 0 */ +/* XOR engine register offsets macros */ +#define XOR_CONFIG_REG(chan) (XOR_UNIT_BASE(0) + 0x10 + ((chan) * 4)) +#define XOR_ACTIVATION_REG(chan) (XOR_UNIT_BASE(0) + 0x20 + ((chan) * 4)) +#define XOR_CAUSE_REG (XOR_UNIT_BASE(0) + 0x30) +#define XOR_ERROR_CAUSE_REG (XOR_UNIT_BASE(0) + 0x50) +#define XOR_ERROR_ADDR_REG (XOR_UNIT_BASE(0) + 0x60) +#define XOR_WINDOW_CTRL_REG(chan) (XOR_UNIT_BASE(0) + 0x240 + ((chan) * 4)) +#define XOR_BASE_ADDR_REG(winNum) (XOR_UNIT_BASE(0) + 0x250 + ((winNum) * 4)) +#define XOR_SIZE_MASK_REG(winNum) (XOR_UNIT_BASE(0) + 0x270 + ((winNum) * 4)) +#define XOR_INIT_VAL_LOW_REG (XOR_UNIT_BASE(0) + 0x2E0) +#define XOR_INIT_VAL_HIGH_REG (XOR_UNIT_BASE(0) + 0x2E4) +#define XOR_DST_PTR_REG(chan) (XOR_UNIT_BASE(0) + 0x2B0 + ((chan) * 4)) +#define XOR_BLOCK_SIZE_REG(chan) (XOR_UNIT_BASE(0) + 0x2C0 + ((chan) * 4)) + +.globl _mvDramIfEccMemInit +/******************************************************************************* +* _mvDramIfEccMemInit - mem init for dram cs +* +* DESCRIPTION: +* This function will clean the cs by ussing the XOR mem init. +* +* INPUT: +* r0 - dram bank number. +* +* OUTPUT: +* none +*/ +_mvDramIfEccMemInit: + + /* Save register on stack */ + cmp sp, #0 + beq no_stack_s1 +save_on_stack1: + stmdb sp!, {r0,r1, r2, r3, r4, r5, r6} +no_stack_s1: + + ldr r1, = 0 + + /* Disable all XOR address decode windows to avoid possible overlap */ + MV_REG_WRITE_ASM (r1, r5, (XOR_WINDOW_CTRL_REG(XOR_CHAN0))) + + /* Init r5 to first XOR_SIZE_MASK_REG */ + mov r5, r0, LSL #3 + add r5, r5,#0x1500 + add r5, r5,#0x04 + add r5, r5,#(INTER_REGS_BASE) + ldr r6, [r5] + HTOLL(r6,r5) + MV_REG_WRITE_ASM (r6, r5, XOR_SIZE_MASK_REG(XOR_ADDR_DEC_WIN0)) + + mov r5, r0, LSL #3 + add r5, r5,#0x1500 + add r5, r5,#(INTER_REGS_BASE) + ldr r6, [r5] + /* Update destination & size */ + MV_REG_WRITE_ASM(r6, r5, XOR_DST_PTR_REG(XOR_CHAN0)) + HTOLL(r6,r5) + /* Init r6 to first XOR_BASE_ADDR_REG */ + ldr r4, = 0xf + ldr r5, = 0x1 + mov r5, r5, LSL r0 + bic r4, r4, r5 + mov r4, r4, LSL #8 + + orr r6, r6, r4 + MV_REG_WRITE_ASM (r6, r5, XOR_BASE_ADDR_REG(XOR_ADDR_DEC_WIN0)) + + ldr r6, = 0xff0001 + MV_REG_WRITE_ASM (r6, r5, XOR_WINDOW_CTRL_REG(XOR_CHAN0)) + + /* Configure XOR engine for memory init function. */ + MV_REG_READ_ASM (r6, r5, XOR_CONFIG_REG(XOR_CHAN0)) + and r6, r6, #~0x7 /* Clear operation mode field */ + orr r6, r6, #0x4 /* Set operation to memory init */ + MV_REG_WRITE_ASM(r6, r5, XOR_CONFIG_REG(XOR_CHAN0)) + + /* Set initVal in the XOR Engine Initial Value Registers */ + ldr r6, = 0xfeedfeed + MV_REG_WRITE_ASM(r6, r5, XOR_INIT_VAL_LOW_REG) + ldr r6, = 0xfeedfeed + MV_REG_WRITE_ASM(r6, r5, XOR_INIT_VAL_HIGH_REG) + + /* Set block size using DRAM bank size */ + + mov r5, r0, LSL #3 + add r5, r5,#0x1500 + add r5, r5,#0x04 + add r5, r5,#(INTER_REGS_BASE) + + ldr r6, [r5] + HTOLL(r6,r5) + and r6, r6, #SCSR_SIZE_MASK + mov r5, r6, LSR #SCSR_SIZE_OFFS + add r5, r5, #1 + mov r6, r5, LSL #SCSR_SIZE_OFFS + MV_REG_WRITE_ASM(r6, r5, XOR_BLOCK_SIZE_REG(XOR_CHAN0)) + + /* Clean interrupt cause*/ + MV_REG_WRITE_ASM(r1, r5, XOR_CAUSE_REG) + + /* Clean error interrupt cause*/ + MV_REG_READ_ASM(r6, r5, XOR_ERROR_CAUSE_REG) + MV_REG_READ_ASM(r6, r5, XOR_ERROR_ADDR_REG) + + /* Start transfer */ + MV_REG_READ_ASM (r6, r5, XOR_ACTIVATION_REG(XOR_CHAN0)) + orr r6, r6, #0x1 /* Preform start command */ + MV_REG_WRITE_ASM(r6, r5, XOR_ACTIVATION_REG(XOR_CHAN0)) + + /* Wait for engine to finish */ +waitForComplete: + MV_REG_READ_ASM(r6, r5, XOR_CAUSE_REG) + and r6, r6, #2 + cmp r6, #0 + beq waitForComplete + + /* Clear all error report registers */ + MV_REG_WRITE_ASM(r1, r5, SDRAM_SINGLE_BIT_ERR_CNTR_REG) + MV_REG_WRITE_ASM(r1, r5, SDRAM_DOUBLE_BIT_ERR_CNTR_REG) + + MV_REG_WRITE_ASM(r1, r5, SDRAM_ERROR_CAUSE_REG) + + cmp sp, #0 + beq no_stack_l1 +load_from_stack1: + ldmia sp!, {r0, r1, r2, r3, r4, r5, r6} +no_stack_l1: + mov pc, lr + + +/******************************************************************************* +* mvDramIfMemInit - Use XOR to clear all memory. +* +* DESCRIPTION: +* Use assembler function _mvDramIfEccMemInit to fill all memory with FEADFEAD pattern. +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +#if defined(MV78XX0) + +_mvDramIfMemInit: + stmdb sp!, {r0,r1, r2, r3, r4, r5, r6} + mov r6, LR /* Save link register */ + /* Check if dram bank 0 has to be init for ECC */ + MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,0)) + and r3, r0, #SCSR_WIN_EN + cmp r3, #0 + beq no_bank_0 + MV_REG_READ_ASM(r0, r5, SDRAM_BASE_ADDR_REG(0,0)) + cmp r0, #0 + beq no_bank_0 + mov r0,#0 + bl _mvDramIfEccMemInit + +no_bank_0: + /* Check if dram bank 1 has to be init for ECC */ + MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,1)) + and r0, r0, #SCSR_WIN_EN + cmp r0, #0 + beq no_bank_1 + mov r0,#1 + bl _mvDramIfEccMemInit +no_bank_1: + /* Check if dram bank 2 has to be init for ECC */ + MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,2)) + and r0, r0, #SCSR_WIN_EN + cmp r0, #0 + beq no_bank_2 + MV_REG_READ_ASM(r0, r5, SDRAM_BASE_ADDR_REG(0,2)) + cmp r0, #0 + beq no_bank_2 + mov r0,#2 + bl _mvDramIfEccMemInit + +no_bank_2: + /* Check if dram bank 3 has to be init for ECC */ + MV_REG_READ_ASM (r0, r5, SDRAM_SIZE_REG(0,3)) + and r0, r0, #SCSR_WIN_EN + cmp r0, #0 + beq no_bank_3 + mov r0,#3 + bl _mvDramIfEccMemInit +no_bank_3: + mov LR ,r6 /* restore link register */ + ldmia sp!, {r0, r1, r2, r3, r4, r5, r6} + mov pc, lr +#endif + diff --git a/board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.h b/board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.h new file mode 100644 index 0000000..ab9377a --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr2/mvDramIfConfig.h @@ -0,0 +1,155 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDramIfConfigh +#define __INCmvDramIfConfigh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ + +/* defines */ + +/* registers defaults values */ + +#define SDRAM_CONFIG_DV (SDRAM_SRMODE_DRAM | BIT25 | BIT30) + +#define SDRAM_DUNIT_CTRL_LOW_DDR2_DV \ + (SDRAM_SRCLK_KEPT | \ + SDRAM_CLK1DRV_NORMAL | \ + (BIT28 | BIT29)) + +#define SDRAM_ADDR_CTRL_DV 2 + +#define SDRAM_TIMING_CTRL_LOW_REG_DV \ + ((0x2 << SDRAM_TRCD_OFFS) | \ + (0x2 << SDRAM_TRP_OFFS) | \ + (0x1 << SDRAM_TWR_OFFS) | \ + (0x0 << SDRAM_TWTR_OFFS) | \ + (0x5 << SDRAM_TRAS_OFFS) | \ + (0x1 << SDRAM_TRRD_OFFS)) + +/* Note: value of 0 in register means one cycle, 1 means two and so on */ +#define SDRAM_TIMING_CTRL_HIGH_REG_DV \ + ((0x0 << SDRAM_TR2R_OFFS) | \ + (0x0 << SDRAM_TR2W_W2R_OFFS) | \ + (0x1 << SDRAM_TW2W_OFFS)) + +#define SDRAM_OPEN_PAGES_CTRL_REG_DV SDRAM_OPEN_PAGE_EN + +/* Presence Ctrl Low Ctrl High Dunit Ctrl Ext Mode */ +/* CS0 0x84210000 0x00000000 0x0000780F 0x00000440 */ +/* CS0+CS1 0x84210000 0x00000000 0x0000780F 0x00000440 */ +/* CS0+CS2 0x030C030C 0x00000000 0x0000740F 0x00000404 */ +/* CS0+CS1+CS2 0x030C030C 0x00000000 0x0000740F 0x00000404 */ +/* CS0+CS2+CS3 0x030C030C 0x00000000 0x0000740F 0x00000404 */ +/* CS0+CS1+CS2+CS3 0x030C030C 0x00000000 0x0000740F 0x00000404 */ + +#define DDR2_ODT_CTRL_LOW_CS0_CS1_DV 0x84210000 +#define DDR2_ODT_CTRL_HIGH_CS0_CS1_DV 0x00000000 +#define DDR2_DUNIT_ODT_CTRL_CS0_CS1_DV 0x0000E80F +#ifdef MV78XX0 +#define DDR_SDRAM_EXT_MODE_CS0_CS1_DV 0x00000040 +#else +#define DDR_SDRAM_EXT_MODE_CS0_CS1_DV 0x00000440 +#endif + +#define DDR2_ODT_CTRL_LOW_CS0_CS1_CS2_CS3_DV 0x030C030C +#define DDR2_ODT_CTRL_HIGH_CS0_CS1_CS2_CS3_DV 0x00000000 +#define DDR2_DUNIT_ODT_CTRL_CS0_CS1_CS2_CS3_DV 0x0000FC0F +#ifdef MV78XX0 +#define DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV 0x00000004 +#define DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV 0x00000044 +#else +#define DDR_SDRAM_EXT_MODE_CS0_CS1_CS2_CS3_DV 0x00000404 +#define DDR_SDRAM_EXT_MODE_FAST_CS0_CS1_CS2_CS3_DV 0x00000444 +#endif + +/* DDR SDRAM Adderss/Control and Data Pads Calibration default values */ +#define DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV \ + (3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS) + +#define DDR2_DATA_PAD_STRENGTH_TYPICAL_DV \ + (3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS) + +/* DDR SDRAM Mode Register default value */ +#define DDR2_MODE_REG_DV (SDRAM_BURST_LEN_4 | SDRAM_WR_3_CYC) +/* DDR SDRAM Timing parameter default values */ +#define DD2_SDRAM_TIMING_LOW_DV 0x85520 +#define DDR2_SDRAM_TIMING_HIGH_DV 0x8552 +#define SDRAM_TIMING_CTRL_LOW_REG_DEFAULT 0x33136552 +#define SDRAM_TRFC_DEFAULT_VALUE 0x34 +#define SDRAM_TRFC_DEFAULT SDRAM_TRFC_DEFAULT_VALUE +#define SDRAM_TW2W_DEFALT (0x1 << SDRAM_TW2W_OFFS) + +#define SDRAM_TIMING_CTRL_HIGH_REG_DEFAULT (SDRAM_TRFC_DEFAULT | SDRAM_TW2W_DEFALT) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvDramIfh */ diff --git a/board/mv_feroceon/mv_hal/ddr2/mvDramIfRegs.h b/board/mv_feroceon/mv_hal/ddr2/mvDramIfRegs.h new file mode 100644 index 0000000..b0cf9f0 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr2/mvDramIfRegs.h @@ -0,0 +1,421 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDramIfRegsh +#define __INCmvDramIfRegsh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* DDR SDRAM Controller Address Decode Registers */ + /* SDRAM CSn Base Address Register (SCBAR) */ +#define SDRAM_BASE_ADDR_REG(cpu,csNum) (0x1500 + ((csNum) * 8) + ((cpu) * 0x70)) +#define SCBAR_BASE_OFFS 16 +#define SCBAR_BASE_MASK (0xffff << SCBAR_BASE_OFFS) +#define SCBAR_BASE_ALIGNMENT 0x10000 + +/* SDRAM CSn Size Register (SCSR) */ +#define SDRAM_SIZE_REG(cpu,csNum) (0x1504 + ((csNum) * 8) + ((cpu) * 0x70)) +#define SCSR_SIZE_OFFS 24 +#define SCSR_SIZE_MASK (0xff << SCSR_SIZE_OFFS) +#define SCSR_SIZE_ALIGNMENT 0x1000000 +#define SCSR_WIN_EN BIT0 + +/* configuration register */ +#define SDRAM_CONFIG_REG (DRAM_BASE + 0x1400) +#define SDRAM_REFRESH_OFFS 0 +#define SDRAM_REFRESH_MAX 0x3FFF +#define SDRAM_REFRESH_MASK (SDRAM_REFRESH_MAX << SDRAM_REFRESH_OFFS) +#define SDRAM_DWIDTH_OFFS 15 +#define SDRAM_DWIDTH_MASK (1 << SDRAM_DWIDTH_OFFS) +#define SDRAM_DWIDTH_32BIT (0 << SDRAM_DWIDTH_OFFS) +#define SDRAM_DWIDTH_64BIT (1 << SDRAM_DWIDTH_OFFS) +#define SDRAM_REGISTERED (1 << 17) +#define SDRAM_ECC_OFFS 18 +#define SDRAM_ECC_MASK (1 << SDRAM_ECC_OFFS) +#define SDRAM_ECC_DIS (0 << SDRAM_ECC_OFFS) +#define SDRAM_ECC_EN (1 << SDRAM_ECC_OFFS) +#define SDRAM_IERR_OFFS 19 +#define SDRAM_IERR_MASK (1 << SDRAM_IERR_OFFS) +#define SDRAM_IERR_REPORTE (0 << SDRAM_IERR_OFFS) +#define SDRAM_IERR_IGNORE (1 << SDRAM_IERR_OFFS) +#define SDRAM_SRMODE_OFFS 24 +#define SDRAM_SRMODE_MASK (1 << SDRAM_SRMODE_OFFS) +#define SDRAM_SRMODE_POWER (0 << SDRAM_SRMODE_OFFS) +#define SDRAM_SRMODE_DRAM (1 << SDRAM_SRMODE_OFFS) + +/* dunit control low register */ +#define SDRAM_DUNIT_CTRL_REG (DRAM_BASE + 0x1404) +#define SDRAM_2T_OFFS 4 +#define SDRAM_2T_MASK (1 << SDRAM_2T_OFFS) +#define SDRAM_2T_MODE (1 << SDRAM_2T_OFFS) + +#define SDRAM_SRCLK_OFFS 5 +#define SDRAM_SRCLK_MASK (1 << SDRAM_SRCLK_OFFS) +#define SDRAM_SRCLK_KEPT (0 << SDRAM_SRCLK_OFFS) +#define SDRAM_SRCLK_GATED (1 << SDRAM_SRCLK_OFFS) +#define SDRAM_CTRL_POS_OFFS 6 +#define SDRAM_CTRL_POS_MASK (1 << SDRAM_CTRL_POS_OFFS) +#define SDRAM_CTRL_POS_FALL (0 << SDRAM_CTRL_POS_OFFS) +#define SDRAM_CTRL_POS_RISE (1 << SDRAM_CTRL_POS_OFFS) +#define SDRAM_CLK1DRV_OFFS 12 +#define SDRAM_CLK1DRV_MASK (1 << SDRAM_CLK1DRV_OFFS) +#define SDRAM_CLK1DRV_HIGH_Z (0 << SDRAM_CLK1DRV_OFFS) +#define SDRAM_CLK1DRV_NORMAL (1 << SDRAM_CLK1DRV_OFFS) +#define SDRAM_CLK2DRV_OFFS 13 +#define SDRAM_CLK2DRV_MASK (1 << SDRAM_CLK2DRV_OFFS) +#define SDRAM_CLK2DRV_HIGH_Z (0 << SDRAM_CLK2DRV_OFFS) +#define SDRAM_CLK2DRV_NORMAL (1 << SDRAM_CLK2DRV_OFFS) +#define SDRAM_SB_OUT_DEL_OFFS 20 +#define SDRAM_SB_OUT_DEL_MAX 0xf +#define SDRAM_SB_OUT_MASK (SDRAM_SB_OUT_DEL_MAX<= MV_DRAM_MAX_CS )) + { + DB(mvOsPrintf("Dram: mvDramBankInfoGet bad params \n")); + return MV_BAD_PARAM; + } + memset(pBankInfo, 0, sizeof(*pBankInfo)); + + if ( MV_OK != dimmSpdGet((MV_U32)(bankNum/2), &dimmInfo)) + { + DB(mvOsPrintf("Dram: ERR dimmSpdGet failed to get dimm info \n")); + return MV_FAIL; + } + if ((dimmInfo.numOfModuleBanks == 1) && ((bankNum % 2) == 1)) + { + DB(mvOsPrintf("Dram: ERR dimmSpdGet. Can't find DIMM bank 2 \n")); + return MV_FAIL; + } + /* convert Dimm info to Bank info */ + cpyDimm2BankInfo(&dimmInfo, pBankInfo); + return MV_OK; +} + +/******************************************************************************* +* cpyDimm2BankInfo - Convert a Dimm info struct into a bank info struct. +* +* DESCRIPTION: +* Convert a Dimm info struct into a bank info struct. +* +* INPUT: +* pDimmInfo - DIMM information structure. +* +* OUTPUT: +* pBankInfo - DRAM bank information struct. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID cpyDimm2BankInfo(MV_DIMM_INFO *pDimmInfo, + MV_DRAM_BANK_INFO *pBankInfo) +{ + pBankInfo->memoryType = pDimmInfo->memoryType; + + /* DIMM dimensions */ + pBankInfo->numOfRowAddr = pDimmInfo->numOfRowAddr; + pBankInfo->numOfColAddr = pDimmInfo->numOfColAddr; + pBankInfo->dataWidth = pDimmInfo->dataWidth; + pBankInfo->errorCheckType = pDimmInfo->errorCheckType; + pBankInfo->sdramWidth = pDimmInfo->sdramWidth; + pBankInfo->errorCheckDataWidth = pDimmInfo->errorCheckDataWidth; + pBankInfo->numOfBanksOnEachDevice = pDimmInfo->numOfBanksOnEachDevice; + pBankInfo->suportedCasLatencies = pDimmInfo->suportedCasLatencies; + pBankInfo->refreshInterval = pDimmInfo->refreshInterval; + + /* DIMM timing parameters */ + pBankInfo->minCycleTimeAtMaxCasLatPs = pDimmInfo->minCycleTimeAtMaxCasLatPs; + pBankInfo->minCycleTimeAtMaxCasLatMinus1Ps = + pDimmInfo->minCycleTimeAtMaxCasLatMinus1Ps; + pBankInfo->minCycleTimeAtMaxCasLatMinus2Ps = + pDimmInfo->minCycleTimeAtMaxCasLatMinus2Ps; + + pBankInfo->minRowPrechargeTime = pDimmInfo->minRowPrechargeTime; + pBankInfo->minRowActiveToRowActive = pDimmInfo->minRowActiveToRowActive; + pBankInfo->minRasToCasDelay = pDimmInfo->minRasToCasDelay; + pBankInfo->minRasPulseWidth = pDimmInfo->minRasPulseWidth; + pBankInfo->minWriteRecoveryTime = pDimmInfo->minWriteRecoveryTime; + pBankInfo->minWriteToReadCmdDelay = pDimmInfo->minWriteToReadCmdDelay; + pBankInfo->minReadToPrechCmdDelay = pDimmInfo->minReadToPrechCmdDelay; + pBankInfo->minRefreshToActiveCmd = pDimmInfo->minRefreshToActiveCmd; + + /* Parameters calculated from the extracted DIMM information */ + pBankInfo->size = pDimmInfo->size/pDimmInfo->numOfModuleBanks; + pBankInfo->deviceDensity = pDimmInfo->deviceDensity; + pBankInfo->numberOfDevices = pDimmInfo->numberOfDevices / + pDimmInfo->numOfModuleBanks; + + /* DIMM attributes (MV_TRUE for yes) */ + + if ((pDimmInfo->memoryType == MEM_TYPE_SDRAM) || + (pDimmInfo->memoryType == MEM_TYPE_DDR1) ) + { + if (pDimmInfo->dimmAttributes & BIT1) + pBankInfo->registeredAddrAndControlInputs = MV_TRUE; + else + pBankInfo->registeredAddrAndControlInputs = MV_FALSE; + } + else /* pDimmInfo->memoryType == MEM_TYPE_DDR2 */ + { + if (pDimmInfo->dimmTypeInfo & (BIT0 | BIT4)) + pBankInfo->registeredAddrAndControlInputs = MV_TRUE; + else + pBankInfo->registeredAddrAndControlInputs = MV_FALSE; + } + + return; +} +/******************************************************************************* +* dimmSpdCpy - Cpy SPD parameters from dimm 0 to dimm 1. +* +* DESCRIPTION: +* Read the DIMM SPD parameters from dimm 0 into dimm 1 SPD. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if function could read DIMM parameters, MV_FALSE otherwise. +* +*******************************************************************************/ +MV_STATUS dimmSpdCpy(MV_VOID) +{ + MV_U32 i; + MV_U32 spdChecksum; + + MV_TWSI_SLAVE twsiSlave; + MV_U8 data[SPD_SIZE]; + + /* zero dimmInfo structure */ + memset(data, 0, SPD_SIZE); + + /* read the dimm eeprom */ + DB(mvOsPrintf("DRAM: Read Dimm eeprom\n")); + twsiSlave.slaveAddr.address = MV_BOARD_DIMM0_I2C_ADDR; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_FALSE; + + if( MV_OK != mvTwsiRead (MV_BOARD_DIMM_I2C_CHANNEL, &twsiSlave, data, SPD_SIZE) ) + { + DB(mvOsPrintf("DRAM: ERR. no DIMM in dimmNum 0\n")); + return MV_FAIL; + } + DB(puts("DRAM: Reading dimm info succeded.\n")); + + /* calculate SPD checksum */ + spdChecksum = 0; + + for(i = 0 ; i <= 62 ; i++) + { + spdChecksum += data[i]; + } + + if ((spdChecksum & 0xff) != data[63]) + { + DB(mvOsPrintf("DRAM: Warning. Wrong SPD Checksum %2x, expValue=%2x\n", + (MV_U32)(spdChecksum & 0xff), data[63])); + } + else + { + DB(mvOsPrintf("DRAM: SPD Checksum ok!\n")); + } + + /* copy the SPD content 1:1 into the DIMM 1 SPD */ + twsiSlave.slaveAddr.address = MV_BOARD_DIMM1_I2C_ADDR; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_FALSE; + + for(i = 0 ; i < SPD_SIZE ; i++) + { + twsiSlave.offset = i; + if( MV_OK != mvTwsiWrite (MV_BOARD_DIMM_I2C_CHANNEL, &twsiSlave, &data[i], 1) ) + { + mvOsPrintf("DRAM: ERR. no DIMM in dimmNum 1 byte %d \n",i); + return MV_FAIL; + } + mvOsDelay(5); + } + + DB(puts("DRAM: Reading dimm info succeded.\n")); + return MV_OK; +} + +/******************************************************************************* +* dimmSpdGet - Get the SPD parameters. +* +* DESCRIPTION: +* Read the DIMM SPD parameters into given struct parameter. +* +* INPUT: +* dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator. +* +* OUTPUT: +* pDimmInfo - DIMM information structure. +* +* RETURN: +* MV_TRUE if function could read DIMM parameters, MV_FALSE otherwise. +* +*******************************************************************************/ +MV_STATUS dimmSpdGet(MV_U32 dimmNum, MV_DIMM_INFO *pDimmInfo) +{ + MV_U32 i; + MV_U32 density = 1; + MV_U32 spdChecksum; + + MV_TWSI_SLAVE twsiSlave; + MV_U8 data[SPD_SIZE]; + + if((NULL == pDimmInfo)|| (dimmNum >= MAX_DIMM_NUM)) + { + DB(mvOsPrintf("Dram: mvDramBankInfoGet bad params \n")); + return MV_BAD_PARAM; + } + + /* zero dimmInfo structure */ + memset(data, 0, SPD_SIZE); + + /* read the dimm eeprom */ + DB(mvOsPrintf("DRAM: Read Dimm eeprom\n")); + twsiSlave.slaveAddr.address = (dimmNum == 0) ? + MV_BOARD_DIMM0_I2C_ADDR : MV_BOARD_DIMM1_I2C_ADDR; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_FALSE; + + if( MV_OK != mvTwsiRead (MV_BOARD_DIMM_I2C_CHANNEL, &twsiSlave, data, SPD_SIZE) ) + { + DB(mvOsPrintf("DRAM: ERR. no DIMM in dimmNum %d \n", dimmNum)); + return MV_FAIL; + } + DB(puts("DRAM: Reading dimm info succeded.\n")); + + /* calculate SPD checksum */ + spdChecksum = 0; + + for(i = 0 ; i <= 62 ; i++) + { + spdChecksum += data[i]; + } + + if ((spdChecksum & 0xff) != data[63]) + { + DB(mvOsPrintf("DRAM: Warning. Wrong SPD Checksum %2x, expValue=%2x\n", + (MV_U32)(spdChecksum & 0xff), data[63])); + } + else + { + DB(mvOsPrintf("DRAM: SPD Checksum ok!\n")); + } + + /* copy the SPD content 1:1 into the dimmInfo structure*/ + for(i = 0 ; i < SPD_SIZE ; i++) + { + pDimmInfo->spdRawData[i] = data[i]; + DB(mvOsPrintf("SPD-EEPROM Byte %3d = %3x (%3d)\n",i, data[i], data[i])); + } + + DB(mvOsPrintf("DRAM SPD Information:\n")); + + /* Memory type (DDR / SDRAM) */ + switch (data[DIMM_MEM_TYPE]) + { + case (DIMM_MEM_TYPE_SDRAM): + pDimmInfo->memoryType = MEM_TYPE_SDRAM; + DB(mvOsPrintf("DRAM Memeory type SDRAM\n")); + break; + case (DIMM_MEM_TYPE_DDR1): + pDimmInfo->memoryType = MEM_TYPE_DDR1; + DB(mvOsPrintf("DRAM Memeory type DDR1\n")); + break; + case (DIMM_MEM_TYPE_DDR2): + pDimmInfo->memoryType = MEM_TYPE_DDR2; + DB(mvOsPrintf("DRAM Memeory type DDR2\n")); + break; + default: + mvOsPrintf("ERROR: Undefined memory type!\n"); + return MV_ERROR; + } + + + /* Number Of Row Addresses */ + pDimmInfo->numOfRowAddr = data[DIMM_ROW_NUM]; + DB(mvOsPrintf("DRAM numOfRowAddr[3] %d\n",pDimmInfo->numOfRowAddr)); + + /* Number Of Column Addresses */ + pDimmInfo->numOfColAddr = data[DIMM_COL_NUM]; + DB(mvOsPrintf("DRAM numOfColAddr[4] %d\n",pDimmInfo->numOfColAddr)); + + /* Number Of Module Banks */ + pDimmInfo->numOfModuleBanks = data[DIMM_MODULE_BANK_NUM]; + DB(mvOsPrintf("DRAM numOfModuleBanks[5] 0x%x\n", + pDimmInfo->numOfModuleBanks)); + + /* Number of module banks encoded differently for DDR2 */ + if (pDimmInfo->memoryType == MEM_TYPE_DDR2) + pDimmInfo->numOfModuleBanks = (pDimmInfo->numOfModuleBanks & 0x7)+1; + + /* Data Width */ + pDimmInfo->dataWidth = data[DIMM_DATA_WIDTH]; + DB(mvOsPrintf("DRAM dataWidth[6] 0x%x\n", pDimmInfo->dataWidth)); + + /* Minimum Cycle Time At Max CasLatancy */ + pDimmInfo->minCycleTimeAtMaxCasLatPs = cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS]); + + /* Error Check Type */ + pDimmInfo->errorCheckType = data[DIMM_ERR_CHECK_TYPE]; + DB(mvOsPrintf("DRAM errorCheckType[11] 0x%x\n", + pDimmInfo->errorCheckType)); + + /* Refresh Interval */ + pDimmInfo->refreshInterval = data[DIMM_REFRESH_INTERVAL]; + DB(mvOsPrintf("DRAM refreshInterval[12] 0x%x\n", + pDimmInfo->refreshInterval)); + + /* Sdram Width */ + pDimmInfo->sdramWidth = data[DIMM_SDRAM_WIDTH]; + DB(mvOsPrintf("DRAM sdramWidth[13] 0x%x\n",pDimmInfo->sdramWidth)); + + /* Error Check Data Width */ + pDimmInfo->errorCheckDataWidth = data[DIMM_ERR_CHECK_DATA_WIDTH]; + DB(mvOsPrintf("DRAM errorCheckDataWidth[14] 0x%x\n", + pDimmInfo->errorCheckDataWidth)); + + /* Burst Length Supported */ + /* SDRAM/DDR1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | 2 | 1 * + *********************************************************/ + /* DDR2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | TBD | TBD * + *********************************************************/ + + pDimmInfo->burstLengthSupported = data[DIMM_BURST_LEN_SUP]; + DB(mvOsPrintf("DRAM burstLengthSupported[16] 0x%x\n", + pDimmInfo->burstLengthSupported)); + + /* Number Of Banks On Each Device */ + pDimmInfo->numOfBanksOnEachDevice = data[DIMM_DEV_BANK_NUM]; + DB(mvOsPrintf("DRAM numOfBanksOnEachDevice[17] 0x%x\n", + pDimmInfo->numOfBanksOnEachDevice)); + + /* Suported Cas Latencies */ + + /* SDRAM: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 7 | 6 | 5 | 4 | 3 | 2 | 1 * + ********************************************************/ + + /* DDR 1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 4 | 3.5 | 3 | 2.5 | 2 | 1.5 | 1 * + *********************************************************/ + + /* DDR 2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 5 | 4 | 3 | 2 | TBD | TBD * + *********************************************************/ + + pDimmInfo->suportedCasLatencies = data[DIMM_SUP_CAL]; + DB(mvOsPrintf("DRAM suportedCasLatencies[18] 0x%x\n", + pDimmInfo->suportedCasLatencies)); + + /* For DDR2 only, get the DIMM type information */ + if (pDimmInfo->memoryType == MEM_TYPE_DDR2) + { + pDimmInfo->dimmTypeInfo = data[DIMM_DDR2_TYPE_INFORMATION]; + DB(mvOsPrintf("DRAM dimmTypeInfo[20] (DDR2) 0x%x\n", + pDimmInfo->dimmTypeInfo)); + } + + /* SDRAM Modules Attributes */ + pDimmInfo->dimmAttributes = data[DIMM_BUF_ADDR_CONT_IN]; + DB(mvOsPrintf("DRAM dimmAttributes[21] 0x%x\n", + pDimmInfo->dimmAttributes)); + + /* Minimum Cycle Time At Max CasLatancy Minus 1*/ + pDimmInfo->minCycleTimeAtMaxCasLatMinus1Ps = + cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS_MINUS1]); + + /* Minimum Cycle Time At Max CasLatancy Minus 2*/ + pDimmInfo->minCycleTimeAtMaxCasLatMinus2Ps = + cas2ps(data[DIMM_MIN_CC_AT_MAX_CAS_MINUS2]); + + pDimmInfo->minRowPrechargeTime = data[DIMM_MIN_ROW_PRECHARGE_TIME]; + DB(mvOsPrintf("DRAM minRowPrechargeTime[27] 0x%x\n", + pDimmInfo->minRowPrechargeTime)); + pDimmInfo->minRowActiveToRowActive = data[DIMM_MIN_ROW_ACTIVE_TO_ROW_ACTIVE]; + DB(mvOsPrintf("DRAM minRowActiveToRowActive[28] 0x%x\n", + pDimmInfo->minRowActiveToRowActive)); + pDimmInfo->minRasToCasDelay = data[DIMM_MIN_RAS_TO_CAS_DELAY]; + DB(mvOsPrintf("DRAM minRasToCasDelay[29] 0x%x\n", + pDimmInfo->minRasToCasDelay)); + pDimmInfo->minRasPulseWidth = data[DIMM_MIN_RAS_PULSE_WIDTH]; + DB(mvOsPrintf("DRAM minRasPulseWidth[30] 0x%x\n", + pDimmInfo->minRasPulseWidth)); + + /* DIMM Bank Density */ + pDimmInfo->dimmBankDensity = data[DIMM_BANK_DENSITY]; + DB(mvOsPrintf("DRAM dimmBankDensity[31] 0x%x\n", + pDimmInfo->dimmBankDensity)); + + /* Only DDR2 includes Write Recovery Time field. Other SDRAM ignore */ + pDimmInfo->minWriteRecoveryTime = data[DIMM_MIN_WRITE_RECOVERY_TIME]; + DB(mvOsPrintf("DRAM minWriteRecoveryTime[36] 0x%x\n", + pDimmInfo->minWriteRecoveryTime)); + + /* Only DDR2 includes Internal Write To Read Command Delay field. */ + pDimmInfo->minWriteToReadCmdDelay = data[DIMM_MIN_WRITE_TO_READ_CMD_DELAY]; + DB(mvOsPrintf("DRAM minWriteToReadCmdDelay[37] 0x%x\n", + pDimmInfo->minWriteToReadCmdDelay)); + + /* Only DDR2 includes Internal Read To Precharge Command Delay field. */ + pDimmInfo->minReadToPrechCmdDelay = data[DIMM_MIN_READ_TO_PRECH_CMD_DELAY]; + DB(mvOsPrintf("DRAM minReadToPrechCmdDelay[38] 0x%x\n", + pDimmInfo->minReadToPrechCmdDelay)); + + /* Only DDR2 includes Minimum Refresh to Activate/Refresh Command field */ + pDimmInfo->minRefreshToActiveCmd = data[DIMM_MIN_REFRESH_TO_ACTIVATE_CMD]; + DB(mvOsPrintf("DRAM minRefreshToActiveCmd[42] 0x%x\n", + pDimmInfo->minRefreshToActiveCmd)); + + /* calculating the sdram density. Representing device density from */ + /* bit 20 to allow representation of 4GB and above. */ + /* For example, if density is 512Mbit 0x20000000, will be represent in */ + /* deviceDensity by 0x20000000 >> 16 --> 0x00000200. Another example */ + /* is density 8GB 0x200000000 >> 16 --> 0x00002000. */ + density = (1 << ((pDimmInfo->numOfRowAddr + pDimmInfo->numOfColAddr) - 20)); + pDimmInfo->deviceDensity = density * + pDimmInfo->numOfBanksOnEachDevice * + pDimmInfo->sdramWidth; + DB(mvOsPrintf("DRAM deviceDensity %d\n",pDimmInfo->deviceDensity)); + + /* Number of devices includeing Error correction */ + pDimmInfo->numberOfDevices = (pDimmInfo->dataWidth/pDimmInfo->sdramWidth) * + pDimmInfo->numOfModuleBanks; + DB(mvOsPrintf("DRAM numberOfDevices %d\n", + pDimmInfo->numberOfDevices)); + + pDimmInfo->size = 0; + + /* Note that pDimmInfo->size is in MB units */ + if (pDimmInfo->memoryType == MEM_TYPE_SDRAM) + { + if (pDimmInfo->dimmBankDensity & BIT0) + pDimmInfo->size += 1024; /* Equal to 1GB */ + else if (pDimmInfo->dimmBankDensity & BIT1) + pDimmInfo->size += 8; /* Equal to 8MB */ + else if (pDimmInfo->dimmBankDensity & BIT2) + pDimmInfo->size += 16; /* Equal to 16MB */ + else if (pDimmInfo->dimmBankDensity & BIT3) + pDimmInfo->size += 32; /* Equal to 32MB */ + else if (pDimmInfo->dimmBankDensity & BIT4) + pDimmInfo->size += 64; /* Equal to 64MB */ + else if (pDimmInfo->dimmBankDensity & BIT5) + pDimmInfo->size += 128; /* Equal to 128MB */ + else if (pDimmInfo->dimmBankDensity & BIT6) + pDimmInfo->size += 256; /* Equal to 256MB */ + else if (pDimmInfo->dimmBankDensity & BIT7) + pDimmInfo->size += 512; /* Equal to 512MB */ + } + else if (pDimmInfo->memoryType == MEM_TYPE_DDR1) + { + if (pDimmInfo->dimmBankDensity & BIT0) + pDimmInfo->size += 1024; /* Equal to 1GB */ + else if (pDimmInfo->dimmBankDensity & BIT1) + pDimmInfo->size += 2048; /* Equal to 2GB */ + else if (pDimmInfo->dimmBankDensity & BIT2) + pDimmInfo->size += 16; /* Equal to 16MB */ + else if (pDimmInfo->dimmBankDensity & BIT3) + pDimmInfo->size += 32; /* Equal to 32MB */ + else if (pDimmInfo->dimmBankDensity & BIT4) + pDimmInfo->size += 64; /* Equal to 64MB */ + else if (pDimmInfo->dimmBankDensity & BIT5) + pDimmInfo->size += 128; /* Equal to 128MB */ + else if (pDimmInfo->dimmBankDensity & BIT6) + pDimmInfo->size += 256; /* Equal to 256MB */ + else if (pDimmInfo->dimmBankDensity & BIT7) + pDimmInfo->size += 512; /* Equal to 512MB */ + } + else /* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */ + { + if (pDimmInfo->dimmBankDensity & BIT0) + pDimmInfo->size += 1024; /* Equal to 1GB */ + else if (pDimmInfo->dimmBankDensity & BIT1) + pDimmInfo->size += 2048; /* Equal to 2GB */ + else if (pDimmInfo->dimmBankDensity & BIT2) + pDimmInfo->size += 4096; /* Equal to 4GB */ + else if (pDimmInfo->dimmBankDensity & BIT3) + pDimmInfo->size += 8192; /* Equal to 8GB */ + else if (pDimmInfo->dimmBankDensity & BIT4) + pDimmInfo->size += 16384; /* Equal to 16GB */ + else if (pDimmInfo->dimmBankDensity & BIT5) + pDimmInfo->size += 128; /* Equal to 128MB */ + else if (pDimmInfo->dimmBankDensity & BIT6) + pDimmInfo->size += 256; /* Equal to 256MB */ + else if (pDimmInfo->dimmBankDensity & BIT7) + pDimmInfo->size += 512; /* Equal to 512MB */ + } + + pDimmInfo->size *= pDimmInfo->numOfModuleBanks; + + DB(mvOsPrintf("Dram: dimm size %dMB \n",pDimmInfo->size)); + + return MV_OK; +} + +/******************************************************************************* +* dimmSpdPrint - Print the SPD parameters. +* +* DESCRIPTION: +* Print the Dimm SPD parameters. +* +* INPUT: +* pDimmInfo - DIMM information structure. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID dimmSpdPrint(MV_U32 dimmNum) +{ + MV_DIMM_INFO dimmInfo; + MV_U32 i, temp = 0; + MV_U32 k, maskLeftOfPoint = 0, maskRightOfPoint = 0; + MV_U32 rightOfPoint = 0,leftOfPoint = 0, div, time_tmp, shift; + MV_U32 busClkPs; + MV_U8 trp_clocks=0, trcd_clocks, tras_clocks, trrd_clocks, + temp_buf[40], *spdRawData; + + busClkPs = 1000000000 / (mvBoardSysClkGet() / 100); /* in 10 ps units */ + + spdRawData = dimmInfo.spdRawData; + + if(MV_OK != dimmSpdGet(dimmNum, &dimmInfo)) + { + mvOsOutput("ERROR: Could not read SPD information!\n"); + return; + } + + /* find Manufactura of Dimm Module */ + mvOsOutput("\nManufacturer's JEDEC ID Code: "); + for(i = 0 ; i < DIMM_MODULE_MANU_SIZE ; i++) + { + mvOsOutput("%x",spdRawData[DIMM_MODULE_MANU_OFFS + i]); + } + mvOsOutput("\n"); + + /* Manufacturer's Specific Data */ + for(i = 0 ; i < DIMM_MODULE_ID_SIZE ; i++) + { + temp_buf[i] = spdRawData[DIMM_MODULE_ID_OFFS + i]; + } + mvOsOutput("Manufacturer's Specific Data: %s\n", temp_buf); + + /* Module Part Number */ + for(i = 0 ; i < DIMM_MODULE_VEN_SIZE ; i++) + { + temp_buf[i] = spdRawData[DIMM_MODULE_VEN_OFFS + i]; + } + mvOsOutput("Module Part Number: %s\n", temp_buf); + + /* Module Serial Number */ + for(i = 0; i < sizeof(MV_U32); i++) + { + temp |= spdRawData[95+i] << 8*i; + } + mvOsOutput("DIMM Serial No. %ld (%lx)\n", (long)temp, + (long)temp); + + /* find Manufac-Data of Dimm Module */ + mvOsOutput("Manufactoring Date: Year 20%d%d/ ww %d%d\n", + ((spdRawData[93] & 0xf0) >> 4), (spdRawData[93] & 0xf), + ((spdRawData[94] & 0xf0) >> 4), (spdRawData[94] & 0xf)); + /* find modul_revision of Dimm Module */ + mvOsOutput("Module Revision: %d.%d\n", + spdRawData[62]/10, spdRawData[62]%10); + + /* find manufac_place of Dimm Module */ + mvOsOutput("manufac_place: %d\n", spdRawData[72]); + + /* go over the first 35 I2C data bytes */ + for(i = 2 ; i <= 35 ; i++) + switch(i) + { + case 2: /* Memory type (DDR1/2 / SDRAM) */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + mvOsOutput("Dram Type is: SDRAM\n"); + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + mvOsOutput("Dram Type is: SDRAM DDR1\n"); + else if (dimmInfo.memoryType == MEM_TYPE_DDR2) + mvOsOutput("Dram Type is: SDRAM DDR2\n"); + else + mvOsOutput("Dram Type unknown\n"); + break; +/*----------------------------------------------------------------------------*/ + + case 3: /* Number Of Row Addresses */ + mvOsOutput("Module Number of row addresses: %d\n", + dimmInfo.numOfRowAddr); + break; +/*----------------------------------------------------------------------------*/ + + case 4: /* Number Of Column Addresses */ + mvOsOutput("Module Number of col addresses: %d\n", + dimmInfo.numOfColAddr); + break; +/*----------------------------------------------------------------------------*/ + + case 5: /* Number Of Module Banks */ + mvOsOutput("Number of Banks on Mod.: %d\n", + dimmInfo.numOfModuleBanks); + break; +/*----------------------------------------------------------------------------*/ + + case 6: /* Data Width */ + mvOsOutput("Module Data Width: %d bit\n", + dimmInfo.dataWidth); + break; +/*----------------------------------------------------------------------------*/ + + case 8: /* Voltage Interface */ + switch(spdRawData[i]) + { + case 0x0: + mvOsOutput("Module is TTL_5V_TOLERANT\n"); + break; + case 0x1: + mvOsOutput("Module is LVTTL\n"); + break; + case 0x2: + mvOsOutput("Module is HSTL_1_5V\n"); + break; + case 0x3: + mvOsOutput("Module is SSTL_3_3V\n"); + break; + case 0x4: + mvOsOutput("Module is SSTL_2_5V\n"); + break; + case 0x5: + if (dimmInfo.memoryType != MEM_TYPE_SDRAM) + { + mvOsOutput("Module is SSTL_1_8V\n"); + break; + } + default: + mvOsOutput("Module is VOLTAGE_UNKNOWN\n"); + break; + } + break; +/*----------------------------------------------------------------------------*/ + + case 9: /* Minimum Cycle Time At Max CasLatancy */ + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + rightOfPoint = (spdRawData[i] & 0x0f) * 10; + + /* DDR2 addition of right of point */ + if ((spdRawData[i] & 0x0f) == 0xA) + { + rightOfPoint = 25; + } + if ((spdRawData[i] & 0x0f) == 0xB) + { + rightOfPoint = 33; + } + if ((spdRawData[i] & 0x0f) == 0xC) + { + rightOfPoint = 66; + } + if ((spdRawData[i] & 0x0f) == 0xD) + { + rightOfPoint = 75; + } + mvOsOutput("Minimum Cycle Time At Max CL: %d.%d [ns]\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 10: /* Clock To Data Out */ + div = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 10:100; + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + mvOsOutput("Clock To Data Out: %d.%d [ns]\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 11: /* Error Check Type */ + mvOsOutput("Error Check Type (0=NONE): %d\n", + dimmInfo.errorCheckType); + break; +/*----------------------------------------------------------------------------*/ + + case 12: /* Refresh Interval */ + mvOsOutput("Refresh Rate: %x\n", + dimmInfo.refreshInterval); + break; +/*----------------------------------------------------------------------------*/ + + case 13: /* Sdram Width */ + mvOsOutput("Sdram Width: %d bits\n", + dimmInfo.sdramWidth); + break; +/*----------------------------------------------------------------------------*/ + + case 14: /* Error Check Data Width */ + mvOsOutput("Error Check Data Width: %d bits\n", + dimmInfo.errorCheckDataWidth); + break; +/*----------------------------------------------------------------------------*/ + + case 15: /* Minimum Clock Delay is unsupported */ + if ((dimmInfo.memoryType == MEM_TYPE_SDRAM) || + (dimmInfo.memoryType == MEM_TYPE_DDR1)) + { + mvOsOutput("Minimum Clk Delay back to back: %d\n", + spdRawData[i]); + } + break; +/*----------------------------------------------------------------------------*/ + + case 16: /* Burst Length Supported */ + /* SDRAM/DDR1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | 2 | 1 * + *********************************************************/ + /* DDR2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + burst length = * Page | TBD | TBD | TBD | 8 | 4 | TBD | TBD * + *********************************************************/ + mvOsOutput("Burst Length Supported: "); + if ((dimmInfo.memoryType == MEM_TYPE_SDRAM) || + (dimmInfo.memoryType == MEM_TYPE_DDR1)) + { + if (dimmInfo.burstLengthSupported & BIT0) + mvOsOutput("1, "); + if (dimmInfo.burstLengthSupported & BIT1) + mvOsOutput("2, "); + } + if (dimmInfo.burstLengthSupported & BIT2) + mvOsOutput("4, "); + if (dimmInfo.burstLengthSupported & BIT3) + mvOsOutput("8, "); + + mvOsOutput(" Bit \n"); + break; +/*----------------------------------------------------------------------------*/ + + case 17: /* Number Of Banks On Each Device */ + mvOsOutput("Number Of Banks On Each Chip: %d\n", + dimmInfo.numOfBanksOnEachDevice); + break; +/*----------------------------------------------------------------------------*/ + + case 18: /* Suported Cas Latencies */ + + /* SDRAM: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 7 | 6 | 5 | 4 | 3 | 2 | 1 * + ********************************************************/ + + /* DDR 1: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | 4 | 3.5 | 3 | 2.5 | 2 | 1.5 | 1 * + *********************************************************/ + + /* DDR 2: + *******-******-******-******-******-******-******-******* + * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * + *******-******-******-******-******-******-******-******* + CAS = * TBD | TBD | 5 | 4 | 3 | 2 | TBD | TBD * + *********************************************************/ + + mvOsOutput("Suported Cas Latencies: (CL) "); + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + for (k = 0; k <=7; k++) + { + if (dimmInfo.suportedCasLatencies & (1 << k)) + mvOsOutput("%d, ", k+1); + } + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if (dimmInfo.suportedCasLatencies & BIT0) + mvOsOutput("1, "); + if (dimmInfo.suportedCasLatencies & BIT1) + mvOsOutput("1.5, "); + if (dimmInfo.suportedCasLatencies & BIT2) + mvOsOutput("2, "); + if (dimmInfo.suportedCasLatencies & BIT3) + mvOsOutput("2.5, "); + if (dimmInfo.suportedCasLatencies & BIT4) + mvOsOutput("3, "); + if (dimmInfo.suportedCasLatencies & BIT5) + mvOsOutput("3.5, "); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR2) + { + if (dimmInfo.suportedCasLatencies & BIT2) + mvOsOutput("2, "); + if (dimmInfo.suportedCasLatencies & BIT3) + mvOsOutput("3, "); + if (dimmInfo.suportedCasLatencies & BIT4) + mvOsOutput("4, "); + if (dimmInfo.suportedCasLatencies & BIT5) + mvOsOutput("5, "); + } + else + mvOsOutput("?.?, "); + mvOsOutput("\n"); + break; +/*----------------------------------------------------------------------------*/ + + case 20: /* DDR2 DIMM type info */ + if (dimmInfo.memoryType == MEM_TYPE_DDR2) + { + if (dimmInfo.dimmTypeInfo & (BIT0 | BIT4)) + mvOsOutput("Registered DIMM (RDIMM)\n"); + else if (dimmInfo.dimmTypeInfo & (BIT1 | BIT5)) + mvOsOutput("Unbuffered DIMM (UDIMM)\n"); + else + mvOsOutput("Unknown DIMM type.\n"); + } + + break; +/*----------------------------------------------------------------------------*/ + + case 21: /* SDRAM Modules Attributes */ + mvOsOutput("\nModule Attributes (SPD Byte 21): \n"); + + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + if (dimmInfo.dimmAttributes & BIT0) + mvOsOutput(" Buffered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Buffered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT1) + mvOsOutput(" Registered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Registered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT2) + mvOsOutput(" On-Card PLL (clock): Yes \n"); + else + mvOsOutput(" On-Card PLL (clock): No \n"); + + if (dimmInfo.dimmAttributes & BIT3) + mvOsOutput(" Bufferd DQMB Input: Yes \n"); + else + mvOsOutput(" Bufferd DQMB Inputs: No \n"); + + if (dimmInfo.dimmAttributes & BIT4) + mvOsOutput(" Registered DQMB Inputs: Yes \n"); + else + mvOsOutput(" Registered DQMB Inputs: No \n"); + + if (dimmInfo.dimmAttributes & BIT5) + mvOsOutput(" Differential Clock Input: Yes \n"); + else + mvOsOutput(" Differential Clock Input: No \n"); + + if (dimmInfo.dimmAttributes & BIT6) + mvOsOutput(" redundant Row Addressing: Yes \n"); + else + mvOsOutput(" redundant Row Addressing: No \n"); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if (dimmInfo.dimmAttributes & BIT0) + mvOsOutput(" Buffered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Buffered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT1) + mvOsOutput(" Registered Addr/Control Input: Yes\n"); + else + mvOsOutput(" Registered Addr/Control Input: No\n"); + + if (dimmInfo.dimmAttributes & BIT2) + mvOsOutput(" On-Card PLL (clock): Yes \n"); + else + mvOsOutput(" On-Card PLL (clock): No \n"); + + if (dimmInfo.dimmAttributes & BIT3) + mvOsOutput(" FET Switch On-Card Enabled: Yes \n"); + else + mvOsOutput(" FET Switch On-Card Enabled: No \n"); + + if (dimmInfo.dimmAttributes & BIT4) + mvOsOutput(" FET Switch External Enabled: Yes \n"); + else + mvOsOutput(" FET Switch External Enabled: No \n"); + + if (dimmInfo.dimmAttributes & BIT5) + mvOsOutput(" Differential Clock Input: Yes \n"); + else + mvOsOutput(" Differential Clock Input: No \n"); + } + else /* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */ + { + mvOsOutput(" Number of Active Registers on the DIMM: %d\n", + (dimmInfo.dimmAttributes & 0x3) + 1); + + mvOsOutput(" Number of PLLs on the DIMM: %d\n", + ((dimmInfo.dimmAttributes) >> 2) & 0x3); + + if (dimmInfo.dimmAttributes & BIT4) + mvOsOutput(" FET Switch External Enabled: Yes \n"); + else + mvOsOutput(" FET Switch External Enabled: No \n"); + + if (dimmInfo.dimmAttributes & BIT6) + mvOsOutput(" Analysis probe installed: Yes \n"); + else + mvOsOutput(" Analysis probe installed: No \n"); + } + + break; +/*----------------------------------------------------------------------------*/ + + case 22: /* Suported AutoPreCharge */ + mvOsOutput("\nModul Attributes (SPD Byte 22): \n"); + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + if ( spdRawData[i] & BIT0 ) + mvOsOutput(" Early Ras Precharge: Yes \n"); + else + mvOsOutput(" Early Ras Precharge: No \n"); + + if ( spdRawData[i] & BIT1 ) + mvOsOutput(" AutoPreCharge: Yes \n"); + else + mvOsOutput(" AutoPreCharge: No \n"); + + if ( spdRawData[i] & BIT2 ) + mvOsOutput(" Precharge All: Yes \n"); + else + mvOsOutput(" Precharge All: No \n"); + + if ( spdRawData[i] & BIT3 ) + mvOsOutput(" Write 1/ReadBurst: Yes \n"); + else + mvOsOutput(" Write 1/ReadBurst: No \n"); + + if ( spdRawData[i] & BIT4 ) + mvOsOutput(" lower VCC tolerance: 5%%\n"); + else + mvOsOutput(" lower VCC tolerance: 10%%\n"); + + if ( spdRawData[i] & BIT5 ) + mvOsOutput(" upper VCC tolerance: 5%%\n"); + else + mvOsOutput(" upper VCC tolerance: 10%%\n"); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if ( spdRawData[i] & BIT0 ) + mvOsOutput(" Supports Weak Driver: Yes \n"); + else + mvOsOutput(" Supports Weak Driver: No \n"); + + if ( !(spdRawData[i] & BIT4) ) + mvOsOutput(" lower VCC tolerance: 0.2V\n"); + + if ( !(spdRawData[i] & BIT5) ) + mvOsOutput(" upper VCC tolerance: 0.2V\n"); + + if ( spdRawData[i] & BIT6 ) + mvOsOutput(" Concurrent Auto Preharge: Yes \n"); + else + mvOsOutput(" Concurrent Auto Preharge: No \n"); + + if ( spdRawData[i] & BIT7 ) + mvOsOutput(" Supports Fast AP: Yes \n"); + else + mvOsOutput(" Supports Fast AP: No \n"); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR2) + { + if ( spdRawData[i] & BIT0 ) + mvOsOutput(" Supports Weak Driver: Yes \n"); + else + mvOsOutput(" Supports Weak Driver: No \n"); + } + break; +/*----------------------------------------------------------------------------*/ + + case 23: + /* Minimum Cycle Time At Maximum Cas Latancy Minus 1 (2nd highest CL) */ + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + rightOfPoint = (spdRawData[i] & 0x0f) * 10; + + /* DDR2 addition of right of point */ + if ((spdRawData[i] & 0x0f) == 0xA) + { + rightOfPoint = 25; + } + if ((spdRawData[i] & 0x0f) == 0xB) + { + rightOfPoint = 33; + } + if ((spdRawData[i] & 0x0f) == 0xC) + { + rightOfPoint = 66; + } + if ((spdRawData[i] & 0x0f) == 0xD) + { + rightOfPoint = 75; + } + + mvOsOutput("Minimum Cycle Time At 2nd highest CasLatancy" + "(0 = Not supported): %d.%d [ns]\n", + leftOfPoint, rightOfPoint ); + break; +/*----------------------------------------------------------------------------*/ + + case 24: /* Clock To Data Out 2nd highest Cas Latency Value*/ + div = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? 10:100; + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / div; + rightOfPoint = time_tmp % div; + mvOsOutput("Clock To Data Out (2nd CL value): %d.%d [ns]\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 25: + /* Minimum Cycle Time At Maximum Cas Latancy Minus 2 (3rd highest CL) */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + leftOfPoint = (spdRawData[i] & 0xfc) >> 2; + rightOfPoint = (spdRawData[i] & 0x3) * 25; + } + else /* DDR1 or DDR2 */ + { + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + rightOfPoint = (spdRawData[i] & 0x0f) * 10; + + /* DDR2 addition of right of point */ + if ((spdRawData[i] & 0x0f) == 0xA) + { + rightOfPoint = 25; + } + if ((spdRawData[i] & 0x0f) == 0xB) + { + rightOfPoint = 33; + } + if ((spdRawData[i] & 0x0f) == 0xC) + { + rightOfPoint = 66; + } + if ((spdRawData[i] & 0x0f) == 0xD) + { + rightOfPoint = 75; + } + } + mvOsOutput("Minimum Cycle Time At 3rd highest CasLatancy" + "(0 = Not supported): %d.%d [ns]\n", + leftOfPoint, rightOfPoint ); + break; +/*----------------------------------------------------------------------------*/ + + case 26: /* Clock To Data Out 3rd highest Cas Latency Value*/ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + leftOfPoint = (spdRawData[i] & 0xfc) >> 2; + rightOfPoint = (spdRawData[i] & 0x3) * 25; + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = 0; + rightOfPoint = time_tmp; + } + mvOsOutput("Clock To Data Out (3rd CL value): %d.%2d[ns]\n", + leftOfPoint, rightOfPoint ); + break; +/*----------------------------------------------------------------------------*/ + + case 27: /* Minimum Row Precharge Time */ + shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 0:2; + maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0xff : 0xfc; + maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0x00 : 0x03; + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (spdRawData[i] & maskRightOfPoint)*25; + temp = ((leftOfPoint*100) + rightOfPoint);/* in 10ps Intervals*/ + trp_clocks = (temp + (busClkPs-1)) / busClkPs; + mvOsOutput("Minimum Row Precharge Time [ns]: %d.%d = " + "in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 28: /* Minimum Row Active to Row Active Time */ + shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 0:2; + maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0xff : 0xfc; + maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0x00 : 0x03; + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (spdRawData[i] & maskRightOfPoint)*25; + temp = ((leftOfPoint*100) + rightOfPoint);/* in 100ns Interval*/ + trrd_clocks = (temp + (busClkPs-1)) / busClkPs; + mvOsOutput("Minimum Row Active -To- Row Active Delay [ns]: " + "%d.%d = in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 29: /* Minimum Ras-To-Cas Delay */ + shift = (dimmInfo.memoryType == MEM_TYPE_SDRAM)? 0:2; + maskLeftOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0xff : 0xfc; + maskRightOfPoint = (dimmInfo.memoryType == MEM_TYPE_SDRAM) ? + 0x00 : 0x03; + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> shift); + rightOfPoint = (spdRawData[i] & maskRightOfPoint)*25; + temp = ((leftOfPoint*100) + rightOfPoint);/* in 100ns Interval*/ + trcd_clocks = (temp + (busClkPs-1) )/ busClkPs; + mvOsOutput("Minimum Ras-To-Cas Delay [ns]: %d.%d = " + "in Clk cycles %d\n", + leftOfPoint, rightOfPoint, trp_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 30: /* Minimum Ras Pulse Width */ + tras_clocks = (cas2ps(spdRawData[i])+(busClkPs-1)) / busClkPs; + mvOsOutput("Minimum Ras Pulse Width [ns]: %d = " + "in Clk cycles %d\n", spdRawData[i], tras_clocks); + break; +/*----------------------------------------------------------------------------*/ + + case 31: /* Module Bank Density */ + mvOsOutput("Module Bank Density (more than 1= Multisize-Module):"); + + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + if (dimmInfo.dimmBankDensity & BIT0) + mvOsOutput("1GB, "); + if (dimmInfo.dimmBankDensity & BIT1) + mvOsOutput("8MB, "); + if (dimmInfo.dimmBankDensity & BIT2) + mvOsOutput("16MB, "); + if (dimmInfo.dimmBankDensity & BIT3) + mvOsOutput("32MB, "); + if (dimmInfo.dimmBankDensity & BIT4) + mvOsOutput("64MB, "); + if (dimmInfo.dimmBankDensity & BIT5) + mvOsOutput("128MB, "); + if (dimmInfo.dimmBankDensity & BIT6) + mvOsOutput("256MB, "); + if (dimmInfo.dimmBankDensity & BIT7) + mvOsOutput("512MB, "); + } + else if (dimmInfo.memoryType == MEM_TYPE_DDR1) + { + if (dimmInfo.dimmBankDensity & BIT0) + mvOsOutput("1GB, "); + if (dimmInfo.dimmBankDensity & BIT1) + mvOsOutput("2GB, "); + if (dimmInfo.dimmBankDensity & BIT2) + mvOsOutput("16MB, "); + if (dimmInfo.dimmBankDensity & BIT3) + mvOsOutput("32MB, "); + if (dimmInfo.dimmBankDensity & BIT4) + mvOsOutput("64MB, "); + if (dimmInfo.dimmBankDensity & BIT5) + mvOsOutput("128MB, "); + if (dimmInfo.dimmBankDensity & BIT6) + mvOsOutput("256MB, "); + if (dimmInfo.dimmBankDensity & BIT7) + mvOsOutput("512MB, "); + } + else /* if (dimmInfo.memoryType == MEM_TYPE_DDR2) */ + { + if (dimmInfo.dimmBankDensity & BIT0) + mvOsOutput("1GB, "); + if (dimmInfo.dimmBankDensity & BIT1) + mvOsOutput("2GB, "); + if (dimmInfo.dimmBankDensity & BIT2) + mvOsOutput("4GB, "); + if (dimmInfo.dimmBankDensity & BIT3) + mvOsOutput("8GB, "); + if (dimmInfo.dimmBankDensity & BIT4) + mvOsOutput("16GB, "); + if (dimmInfo.dimmBankDensity & BIT5) + mvOsOutput("128MB, "); + if (dimmInfo.dimmBankDensity & BIT6) + mvOsOutput("256MB, "); + if (dimmInfo.dimmBankDensity & BIT7) + mvOsOutput("512MB, "); + } + mvOsOutput("\n"); + break; +/*----------------------------------------------------------------------------*/ + + case 32: /* Address And Command Setup Time (measured in ns/1000) */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Address And Command Setup Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 33: /* Address And Command Hold Time */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Address And Command Hold Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 34: /* Data Input Setup Time */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Data Input Setup Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 35: /* Data Input Hold Time */ + if (dimmInfo.memoryType == MEM_TYPE_SDRAM) + { + rightOfPoint = (spdRawData[i] & 0x0f); + leftOfPoint = (spdRawData[i] & 0xf0) >> 4; + if(leftOfPoint > 7) + { + leftOfPoint *= -1; + } + } + else /* DDR1 or DDR2 */ + { + time_tmp = (((spdRawData[i] & 0xf0) >> 4)*10) + + ((spdRawData[i] & 0x0f)); + leftOfPoint = time_tmp / 100; + rightOfPoint = time_tmp % 100; + } + mvOsOutput("Data Input Hold Time [ns]: %d.%d\n\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + + case 36: /* Relevant for DDR2 only: Write Recovery Time */ + leftOfPoint = ((spdRawData[i] & maskLeftOfPoint) >> 2); + rightOfPoint = (spdRawData[i] & maskRightOfPoint) * 25; + mvOsOutput("Write Recovery Time [ns]: %d.%d\n", + leftOfPoint, rightOfPoint); + break; +/*----------------------------------------------------------------------------*/ + } + +} + + +/* + * translate ns.ns/10 coding of SPD timing values + * into ps unit values + */ +/******************************************************************************* +* cas2ps - Translate x.y ns parameter to pico-seconds values +* +* DESCRIPTION: +* This function translates x.y nano seconds to its value in pico seconds. +* For example 3.75ns will return 3750. +* +* INPUT: +* spd_byte - DIMM SPD byte. +* +* OUTPUT: +* None. +* +* RETURN: +* value in pico seconds. +* +*******************************************************************************/ +static MV_U32 cas2ps(MV_U8 spd_byte) +{ + MV_U32 ns, ns10; + + /* isolate upper nibble */ + ns = (spd_byte >> 4) & 0x0F; + /* isolate lower nibble */ + ns10 = (spd_byte & 0x0F); + + if( ns10 < 10 ) { + ns10 *= 10; + } + else if( ns10 == 10 ) + ns10 = 25; + else if( ns10 == 11 ) + ns10 = 33; + else if( ns10 == 12 ) + ns10 = 66; + else if( ns10 == 13 ) + ns10 = 75; + else + { + mvOsOutput("cas2ps Err. unsupported cycle time.\n"); + } + + return (ns*1000 + ns10*10); +} + diff --git a/board/mv_feroceon/mv_hal/ddr2/spd/mvSpd.h b/board/mv_feroceon/mv_hal/ddr2/spd/mvSpd.h new file mode 100644 index 0000000..f955466 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ddr2/spd/mvSpd.h @@ -0,0 +1,192 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDram +#define __INCmvDram + +#include "ddr2/mvDramIf.h" +#include "twsi/mvTwsi.h" + +#define MAX_DIMM_NUM 2 +#define SPD_SIZE 128 + +/* Dimm spd offsets */ +#define DIMM_MEM_TYPE 2 +#define DIMM_ROW_NUM 3 +#define DIMM_COL_NUM 4 +#define DIMM_MODULE_BANK_NUM 5 +#define DIMM_DATA_WIDTH 6 +#define DIMM_VOLT_IF 8 +#define DIMM_MIN_CC_AT_MAX_CAS 9 +#define DIMM_ERR_CHECK_TYPE 11 +#define DIMM_REFRESH_INTERVAL 12 +#define DIMM_SDRAM_WIDTH 13 +#define DIMM_ERR_CHECK_DATA_WIDTH 14 +#define DIMM_MIN_CLK_DEL 15 +#define DIMM_BURST_LEN_SUP 16 +#define DIMM_DEV_BANK_NUM 17 +#define DIMM_SUP_CAL 18 +#define DIMM_DDR2_TYPE_INFORMATION 20 /* DDR2 only */ +#define DIMM_BUF_ADDR_CONT_IN 21 +#define DIMM_MIN_CC_AT_MAX_CAS_MINUS1 23 +#define DIMM_MIN_CC_AT_MAX_CAS_MINUS2 25 +#define DIMM_MIN_ROW_PRECHARGE_TIME 27 +#define DIMM_MIN_ROW_ACTIVE_TO_ROW_ACTIVE 28 +#define DIMM_MIN_RAS_TO_CAS_DELAY 29 +#define DIMM_MIN_RAS_PULSE_WIDTH 30 +#define DIMM_BANK_DENSITY 31 +#define DIMM_MIN_WRITE_RECOVERY_TIME 36 +#define DIMM_MIN_WRITE_TO_READ_CMD_DELAY 37 +#define DIMM_MIN_READ_TO_PRECH_CMD_DELAY 38 +#define DIMM_MIN_REFRESH_TO_ACTIVATE_CMD 42 +#define DIMM_SPD_VERSION 62 + +/* Dimm Memory Type values */ +#define DIMM_MEM_TYPE_SDRAM 0x4 +#define DIMM_MEM_TYPE_DDR1 0x7 +#define DIMM_MEM_TYPE_DDR2 0x8 + +#define DIMM_MODULE_MANU_OFFS 64 +#define DIMM_MODULE_MANU_SIZE 8 +#define DIMM_MODULE_VEN_OFFS 73 +#define DIMM_MODULE_VEN_SIZE 25 +#define DIMM_MODULE_ID_OFFS 99 +#define DIMM_MODULE_ID_SIZE 18 + +/* enumeration for voltage levels. */ +typedef enum _mvDimmVoltageIf +{ + TTL_5V_TOLERANT, + LVTTL, + HSTL_1_5V, + SSTL_3_3V, + SSTL_2_5V, + VOLTAGE_UNKNOWN, +} MV_DIMM_VOLTAGE_IF; + + +/* enumaration for SDRAM CAS Latencies. */ +typedef enum _mvDimmSdramCas +{ + SD_CL_1 =1, + SD_CL_2, + SD_CL_3, + SD_CL_4, + SD_CL_5, + SD_CL_6, + SD_CL_7, + SD_FAULT +}MV_DIMM_SDRAM_CAS; + + +/* DIMM information structure */ +typedef struct _mvDimmInfo +{ + MV_MEMORY_TYPE memoryType; /* DDR or SDRAM */ + + MV_U8 spdRawData[SPD_SIZE]; /* Content of SPD-EEPROM copied 1:1 */ + + /* DIMM dimensions */ + MV_U32 numOfRowAddr; + MV_U32 numOfColAddr; + MV_U32 numOfModuleBanks; + MV_U32 dataWidth; + MV_U32 errorCheckType; /* ECC , PARITY..*/ + MV_U32 sdramWidth; /* 4,8,16 or 32 */ + MV_U32 errorCheckDataWidth; /* 0 - no, 1 - Yes */ + MV_U32 burstLengthSupported; + MV_U32 numOfBanksOnEachDevice; + MV_U32 suportedCasLatencies; + MV_U32 refreshInterval; + MV_U32 dimmBankDensity; + MV_U32 dimmTypeInfo; /* DDR2 only */ + MV_U32 dimmAttributes; + + /* DIMM timing parameters */ + MV_U32 minCycleTimeAtMaxCasLatPs; + MV_U32 minCycleTimeAtMaxCasLatMinus1Ps; + MV_U32 minCycleTimeAtMaxCasLatMinus2Ps; + MV_U32 minRowPrechargeTime; + MV_U32 minRowActiveToRowActive; + MV_U32 minRasToCasDelay; + MV_U32 minRasPulseWidth; + MV_U32 minWriteRecoveryTime; /* DDR2 only */ + MV_U32 minWriteToReadCmdDelay; /* DDR2 only */ + MV_U32 minReadToPrechCmdDelay; /* DDR2 only */ + MV_U32 minRefreshToActiveCmd; /* DDR2 only */ + + /* Parameters calculated from the extracted DIMM information */ + MV_U32 size; /* 16,64,128,256 or 512 MByte in MB units */ + MV_U32 deviceDensity; /* 16,64,128,256 or 512 Mbit in MB units */ + MV_U32 numberOfDevices; + +} MV_DIMM_INFO; + + +MV_STATUS mvDramBankInfoGet(MV_U32 bankNum, MV_DRAM_BANK_INFO *pBankInfo); +MV_STATUS dimmSpdGet(MV_U32 dimmNum, MV_DIMM_INFO *pDimmInfo); +MV_VOID dimmSpdPrint(MV_U32 dimmNum); +MV_STATUS dimmSpdCpy(MV_VOID); + +#endif /* __INCmvDram */ diff --git a/board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.c b/board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.c new file mode 100644 index 0000000..f09e33e --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.c @@ -0,0 +1,818 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "eth-phy/mvEthPhy.h" +#include "eth/gbe/mvEthRegs.h" +#include "boardEnv/mvBoardEnvLib.h" + +static MV_VOID mvEthPhyPower(MV_U32 ethPortNum, MV_BOOL enable); + +/******************************************************************************* +* mvEthPhyRegRead - Read from ethernet phy register. +* +* DESCRIPTION: +* This function reads ethernet phy register. +* +* INPUT: +* phyAddr - Phy address. +* regOffs - Phy register offset. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit phy register value, or 0xffff on error +* +*******************************************************************************/ +MV_STATUS mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data) +{ + MV_U32 smiReg; + volatile MV_U32 timeout; + + /* check parameters */ + if ((phyAddr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) + { + mvOsPrintf("mvEthPhyRegRead: Err. Illegal PHY device address %d\n", + phyAddr); + return MV_FAIL; + } + if ((regOffs << ETH_PHY_SMI_REG_ADDR_OFFS) & ~ETH_PHY_SMI_REG_ADDR_MASK) + { + mvOsPrintf("mvEthPhyRegRead: Err. Illegal PHY register offset %d\n", + regOffs); + return MV_FAIL; + } + + timeout = ETH_PHY_TIMEOUT; + /* wait till the SMI is not busy*/ + do + { + /* read smi register */ + smiReg = MV_REG_READ(ETH_PHY_SMI_REG); + if (timeout-- == 0) + { + mvOsPrintf("mvEthPhyRegRead: SMI busy timeout\n"); + return MV_FAIL; + } + }while (smiReg & ETH_PHY_SMI_BUSY_MASK); + + /* fill the phy address and regiser offset and read opcode */ + smiReg = (phyAddr << ETH_PHY_SMI_DEV_ADDR_OFFS) | (regOffs << ETH_PHY_SMI_REG_ADDR_OFFS )| + ETH_PHY_SMI_OPCODE_READ; + + /* write the smi register */ + MV_REG_WRITE(ETH_PHY_SMI_REG, smiReg); + + timeout=ETH_PHY_TIMEOUT; + + /*wait till readed value is ready */ + do + { + /* read smi register */ + smiReg=MV_REG_READ(ETH_PHY_SMI_REG); + + if (timeout-- == 0) { + mvOsPrintf("mvEthPhyRegRead: SMI read-valid timeout\n"); + return MV_FAIL; + } + }while (!(smiReg & ETH_PHY_SMI_READ_VALID_MASK)); + + /* Wait for the data to update in the SMI register */ + for(timeout = 0 ; timeout < ETH_PHY_TIMEOUT ; timeout++); + + *data = (MV_U16)( MV_REG_READ(ETH_PHY_SMI_REG) & ETH_PHY_SMI_DATA_MASK); + + return MV_OK; +} + +/******************************************************************************* +* mvEthPhyRegWrite - Write to ethernet phy register. +* +* DESCRIPTION: +* This function write to ethernet phy register. +* +* INPUT: +* phyAddr - Phy address. +* regOffs - Phy register offset. +* data - 16bit data. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if write succeed, MV_BAD_PARAM on bad parameters , MV_ERROR on error . +* MV_TIMEOUT on timeout +* +*******************************************************************************/ +MV_STATUS mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data) +{ + MV_U32 smiReg; + volatile MV_U32 timeout; + + /* check parameters */ + if ((phyAddr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) + { + mvOsPrintf("mvEthPhyRegWrite: Err. Illegal phy address \n"); + return MV_BAD_PARAM; + } + if ((regOffs << ETH_PHY_SMI_REG_ADDR_OFFS) & ~ETH_PHY_SMI_REG_ADDR_MASK) + { + mvOsPrintf("mvEthPhyRegWrite: Err. Illegal register offset \n"); + return MV_BAD_PARAM; + } + + timeout=ETH_PHY_TIMEOUT; + + /* wait till the SMI is not busy*/ + do + { + /* read smi register */ + smiReg=MV_REG_READ(ETH_PHY_SMI_REG); + if (timeout-- == 0) { + mvOsPrintf("mvEthPhyRegWrite: SMI busy timeout\n"); + return MV_TIMEOUT; + } + }while (smiReg & ETH_PHY_SMI_BUSY_MASK); + + /* fill the phy address and regiser offset and write opcode and data*/ + smiReg = (data << ETH_PHY_SMI_DATA_OFFS); + smiReg |= (phyAddr << ETH_PHY_SMI_DEV_ADDR_OFFS) | (regOffs << ETH_PHY_SMI_REG_ADDR_OFFS ); + smiReg &= ~ETH_PHY_SMI_OPCODE_READ; + + /* write the smi register */ + MV_REG_WRITE(ETH_PHY_SMI_REG, smiReg); + + return MV_OK; + + +} + +/******************************************************************************* +* mvEthPhyReset - Reset ethernet Phy. +* +* DESCRIPTION: +* This function resets a given ethernet Phy. +* +* INPUT: +* phyAddr - Phy address. +* timeout - in millisec +* +* OUTPUT: +* None. +* +* RETURN: MV_OK - Success +* MV_TIMEOUT - Timeout +* +*******************************************************************************/ +MV_STATUS mvEthPhyReset(MV_U32 phyAddr, int timeout) +{ + MV_U16 phyRegData; + + /* Reset the PHY */ + if(mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK) + return MV_FAIL; + /* Set bit 15 to reset the PHY */ + phyRegData |= ETH_PHY_CTRL_RESET_MASK; + mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData); + + /* Wait untill Auotonegotiation completed */ + while(timeout > 0) + { + mvOsSleep(100); + timeout -= 100; + + if( mvEthPhyRegRead(phyAddr, ETH_PHY_STATUS_REG, &phyRegData) != MV_OK) + return MV_FAIL; + if(phyRegData & ETH_PHY_STATUS_AN_DONE_MASK) + return MV_OK; + } + return MV_TIMEOUT; +} + + +/******************************************************************************* +* mvEthPhyRestartAN - Restart ethernet Phy Auto-Negotiation. +* +* DESCRIPTION: +* This function resets a given ethernet Phy. +* +* INPUT: +* phyAddr - Phy address. +* timeout - in millisec +* +* OUTPUT: +* None. +* +* RETURN: MV_OK - Success +* MV_TIMEOUT - Timeout +* +*******************************************************************************/ +MV_STATUS mvEthPhyRestartAN(MV_U32 phyAddr, int timeout) +{ + MV_U16 phyRegData; + + /* Reset the PHY */ + if(mvEthPhyRegRead (phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK) + return MV_FAIL; + /* Set bit 12 to Enable autonegotiation of the PHY */ + phyRegData |= ETH_PHY_CTRL_AN_ENABLE_MASK; + /* Set bit 9 to Restart autonegotiation of the PHY */ + phyRegData |= ETH_PHY_CTRL_AN_RESTART_MASK; + mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData); + + /* Wait untill Auotonegotiation completed */ + while(timeout > 0) + { + mvOsSleep(100); + timeout -= 100; + + if( mvEthPhyRegRead(phyAddr, ETH_PHY_STATUS_REG, &phyRegData) != MV_OK) + return MV_FAIL; + if(phyRegData & ETH_PHY_STATUS_AN_DONE_MASK) + return MV_OK; + } + return MV_TIMEOUT; +} + + +/******************************************************************************* +* mvEthPhyCheckLink - +* +* DESCRIPTION: +* check link in phy port +* +* INPUT: +* phyAddr - Phy address. +* +* OUTPUT: +* None. +* +* RETURN: MV_TRUE if link is up, MV_FALSE if down +* +*******************************************************************************/ +MV_BOOL mvEthPhyCheckLink( MV_U32 phyAddr ) +{ + MV_U16 val_st, val_ctrl, val_spec_st; + + /* read status reg */ + if( mvEthPhyRegRead( phyAddr, ETH_PHY_STATUS_REG, &val_st) != MV_OK ) + return MV_FALSE; + + /* read control reg */ + if( mvEthPhyRegRead( phyAddr, ETH_PHY_CTRL_REG, &val_ctrl) != MV_OK ) + return MV_FALSE; + + /* read special status reg */ + if( mvEthPhyRegRead( phyAddr, ETH_PHY_SPEC_STATUS_REG, &val_spec_st) != MV_OK ) + return MV_FALSE; + + /* Check for PHY exist */ + if((val_ctrl == ETH_PHY_SMI_DATA_MASK) && (val_st & ETH_PHY_SMI_DATA_MASK)) + return MV_FALSE; + + + if(val_ctrl & ETH_PHY_CTRL_AN_ENABLE_MASK) + { + if(val_st & ETH_PHY_STATUS_AN_DONE_MASK) + return MV_TRUE; + else + return MV_FALSE; + } + else + { + if(val_spec_st & ETH_PHY_SPEC_STATUS_LINK_MASK) + return MV_TRUE; + } + return MV_FALSE; +} + +/******************************************************************************* +* mvEthPhyPrintStatus - +* +* DESCRIPTION: +* print port Speed, Duplex, Auto-negotiation, Link. +* +* INPUT: +* phyAddr - Phy address. +* +* OUTPUT: +* None. +* +* RETURN: 16bit phy register value, or 0xffff on error +* +*******************************************************************************/ +MV_STATUS mvEthPhyPrintStatus( MV_U32 phyAddr ) +{ + MV_U16 val; + + /* read control reg */ + if( mvEthPhyRegRead( phyAddr, ETH_PHY_CTRL_REG, &val) != MV_OK ) + return MV_ERROR; + + if( val & ETH_PHY_CTRL_AN_ENABLE_MASK ) + mvOsOutput( "Auto negotiation: Enabled\n" ); + else + mvOsOutput( "Auto negotiation: Disabled\n" ); + + + /* read specific status reg */ + if( mvEthPhyRegRead( phyAddr, ETH_PHY_SPEC_STATUS_REG, &val) != MV_OK ) + return MV_ERROR; + + switch (val & ETH_PHY_SPEC_STATUS_SPEED_MASK) + { + case ETH_PHY_SPEC_STATUS_SPEED_1000MBPS: + mvOsOutput( "Speed: 1000 Mbps\n" ); + break; + case ETH_PHY_SPEC_STATUS_SPEED_100MBPS: + mvOsOutput( "Speed: 100 Mbps\n" ); + break; + case ETH_PHY_SPEC_STATUS_SPEED_10MBPS: + mvOsOutput( "Speed: 10 Mbps\n" ); + default: + mvOsOutput( "Speed: Uknown\n" ); + break; + + } + + if( val & ETH_PHY_SPEC_STATUS_DUPLEX_MASK ) + mvOsOutput( "Duplex: Full\n" ); + else + mvOsOutput( "Duplex: Half\n" ); + + + if( val & ETH_PHY_SPEC_STATUS_LINK_MASK ) + mvOsOutput("Link: up\n"); + else + mvOsOutput("Link: down\n"); + + return MV_OK; +} + +/******************************************************************************* +* mvEthE1111PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE1111PhyBasicInit(MV_U32 ethPortNum) +{ + MV_U16 reg; + MV_U32 regOff, data; + + /* Phy recv and tx delay */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),20,®); + reg |= BIT1 | BIT7; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),20,reg); + + /* Leds link and activity*/ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),24,0x4111); + + /* reset the phy */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),0,®); + reg |= BIT15; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),0,reg); + + if(mvBoardSpecInitGet(®Off, &data) == MV_TRUE) + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),regOff , data); + +} + +/******************************************************************************* +* mvEthE1112PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE1112PhyBasicInit(MV_U32 ethPortNum) +{ + MV_U16 reg; + + /* Set phy address */ + /*MV_REG_WRITE(ETH_PHY_ADDR_REG(ethPortNum), mvBoardPhyAddrGet(ethPortNum));*/ + + /* Implement PHY errata */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,2); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),0,0x140); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),0,0x8140); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0); + + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,3); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,0x103); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0); + + /* reset the phy */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),0,®); + reg |= BIT15; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),0,reg); + +} + +/******************************************************************************* +* mvEthE1116PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE1116PhyBasicInit(MV_U32 ethPortNum) +{ + MV_U16 reg; + + /* Set phy address */ + MV_REG_WRITE(ETH_PHY_ADDR_REG(ethPortNum), mvBoardPhyAddrGet(ethPortNum)); + + /* Leds link and activity*/ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0x3); + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),16,®); + reg &= ~0xf; +//Patch by QNAP:Fix OnBoard SATA LED and Ethernet LED +// reg |= 0x1; + reg = 0x812; +///////////////////////////////////////////////// + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,reg); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0x0); + + /* Set RGMII delay */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,2); + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),21,®); + reg |= (BIT5 | BIT4); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),21,reg); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0); + + /* reset the phy */ +//Patch by QNAP:Fix OnBoard SATA LED and Ethernet LED +// mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),0,®); +// reg |= BIT15; +// mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),0,reg); +} + +/******************************************************************************* +* mvEthE1011PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE1011PhyBasicInit(MV_U32 ethPortNum) +{ + MV_U16 reg; + + /* Phy recv and tx delay */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),20,®); + reg &= ~(BIT1 | BIT7); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),20,reg); + + /* Leds link and activity*/ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),24,0x4111); + + /* reset the phy */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),0, ®); + reg |= BIT15; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),0,reg); + +} + +/******************************************************************************* +* mvEthE1112PhyPowerDown - +* +* DESCRIPTION: +* Power down the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE1112PhyPowerDown(MV_U32 ethPortNum) +{ + mvEthPhyPower(ethPortNum, MV_FALSE); +} + +/******************************************************************************* +* mvEthE1112PhyPowerUp - +* +* DESCRIPTION: +* Power up the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE1112PhyPowerUp(MV_U32 ethPortNum) +{ + mvEthPhyPower(ethPortNum, MV_TRUE); +} + +/******************************************************************************* +* mvEthPhyPower - +* +* DESCRIPTION: +* Do a basic power down/up to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* enable - MV_TRUE - power up +* MV_FALSE - power down +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +static MV_VOID mvEthPhyPower(MV_U32 ethPortNum, MV_BOOL enable) +{ + MV_U16 reg; + if (enable == MV_FALSE) + { + /* Power down command */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,2); /* select page 2 */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),16,®); + reg |= BIT3; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,reg); /* select to disable the SERDES */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0); /* select page 0 */ + + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,3); /* Power off LED's */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,0x88); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0); + + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,®); + reg |= ETH_PHY_CTRL_RESET_BIT; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,reg); /* software reset */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,®); + reg |= ETH_PHY_CTRL_POWER_DOWN_BIT; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,reg); /* power down the PHY */ + } + else + { + /* Power up command */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,2); /* select page 2 */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),16,®); + reg &= ~BIT3; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,reg); /* select to enable the SERDES */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0); /* select page 0 */ + + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,3); /* Power on LED's */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,0x03); + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0); + + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,®); + reg |= ETH_PHY_CTRL_RESET_BIT; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,reg); /* software reset */ + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,®); + reg &= ~ETH_PHY_CTRL_POWER_DOWN_BIT; + mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),ETH_PHY_CTRL_REG,reg); /* power up the PHY */ + } +} + + +/******************************************************************************* +* mvEth1145PhyInit - Initialize MARVELL 1145 Phy +* +* DESCRIPTION: +* +* INPUT: +* phyAddr - Phy address. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvEth1145PhyBasicInit(MV_U32 port) +{ + MV_U16 value; + + /* Set phy address for each port */ + MV_REG_WRITE(ETH_PHY_ADDR_REG(port), mvBoardPhyAddrGet(port)); + /* Set Link1000 output pin to be link indication, set Tx output pin to be activity */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x18, ETH_PHY_LED_ACT_LNK_DV); + mvOsDelay(10); + + /* Add delay to RGMII Tx and Rx */ + mvEthPhyRegRead(mvBoardPhyAddrGet(port), 0x14, &value); + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x14,(value | BIT1 | BIT7)); + mvOsDelay(10); +#if 0 /* Fix by yotam */ + if (boardId != RD_78XX0_AMC_ID && + boardId != RD_78XX0_H3C_ID) { + /* Set port 2 - Phy addr 9 to RGMII */ + if (port == 2) + { + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x1b, 0x808b); + mvOsDelay(10); + } + + /* Set port 1 - Phy addr a to SGMII */ + if (port == 1) + { + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x1b, 0x8084); + mvOsDelay(10); + + /* Reset Phy */ + mvEthPhyRegRead( mvBoardPhyAddrGet(port), 0x00, &value); + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x00, (value | BIT15)); + mvOsDelay(10); + #if defined(SGMII_OUTBAND_AN) + /* Set port 1 - Phy addr A Page 1 */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x16, 0x1); + mvOsDelay(10); + + /* Set port 1 - Phy addr A disable A.N. */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x0, 0x140); + mvOsDelay(10); + + /* Set port 1 - Phy addr A reset */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x0, 0x8140); + mvOsDelay(10); + + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x16, 0x0); + mvOsDelay(10); + #endif + } + } +#endif + + /* Set Phy TPVL to 0 */ + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x10, 0x60); + mvOsDelay(10); + + /* Reset Phy */ + mvEthPhyRegRead(mvBoardPhyAddrGet(port), 0x00, &value); + mvEthPhyRegWrite(mvBoardPhyAddrGet(port), 0x00, (value | BIT15)); + mvOsDelay(10); + + return; +} + + +/******************************************************************************* +* mvEthSgmiiToCopperPhyInit - Initialize Test board 1112 Phy +* +* DESCRIPTION: +* +* INPUT: +* phyAddr - Phy address. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvEthSgmiiToCopperPhyBasicInit(MV_U32 port) +{ + MV_U16 value; + MV_U16 phyAddr = 0xC; + + /* Port 0 phyAdd c */ + /* Port 1 phyAdd d */ + mvEthPhyRegWrite(phyAddr + port,22,3); + mvEthPhyRegWrite(phyAddr + port,16,0x103); + mvEthPhyRegWrite(phyAddr + port,22,0); + + /* reset the phy */ + mvEthPhyRegRead(phyAddr + port,0,&value); + value |= BIT15; + mvEthPhyRegWrite(phyAddr + port,0,value); +} + + +MV_VOID mvEth1121PhyBasicInit(MV_U32 port) +{ + MV_U16 value; + MV_U16 phyAddr = mvBoardPhyAddrGet(port); + + MV_REG_WRITE(ETH_PHY_ADDR_REG(port), phyAddr); + + /* Change page select to 2 */ + value = 2; + mvEthPhyRegWrite(phyAddr, 22, value); + mvOsDelay(10); + + /* Set RGMII rx delay */ + mvEthPhyRegRead(phyAddr, 21, &value); + value |= BIT5; + mvEthPhyRegWrite(phyAddr, 21, value); + mvOsDelay(10); + + /* Change page select to 0 */ + value = 0; + mvEthPhyRegWrite(phyAddr, 22, value); + mvOsDelay(10); + + /* reset the phy */ + mvEthPhyRegRead(phyAddr, 0, &value); + value |= BIT15; + mvEthPhyRegWrite(phyAddr, 0, value); + mvOsDelay(10); +} + diff --git a/board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.h b/board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.h new file mode 100644 index 0000000..45127a2 --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth-phy/mvEthPhy.h @@ -0,0 +1,90 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCETHPHYH +#define __INCETHPHYH + +#include "mvCommon.h" +#include "mvOs.h" +#include "mvEthPhyRegs.h" + + +MV_STATUS mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data); +MV_STATUS mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data); +MV_STATUS mvEthPhyReset(MV_U32 phyAddr, int timeout); +MV_STATUS mvEthPhyRestartAN(MV_U32 phyAddr, int timeout); +MV_BOOL mvEthPhyCheckLink( MV_U32 phyAddr ); +MV_STATUS mvEthPhyPrintStatus( MV_U32 phyAddr ); + +MV_VOID mvEthE1111PhyBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE1112PhyBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE1112PhyPowerDown(MV_U32 ethPortNum); +MV_VOID mvEthE1112PhyPowerUp(MV_U32 ethPortNum); +MV_VOID mvEthE1116PhyBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE1011PhyBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthSgmiiToCopperPhyBasicInit(MV_U32 ethPortNum); +MV_VOID mvEth1145PhyBasicInit(MV_U32 ethPortNum); +MV_VOID mvEth1121PhyBasicInit(MV_U32 ethPortNum); + +#endif /* #ifndef __INCETHPHYH */ diff --git a/board/mv_feroceon/mv_hal/eth-phy/mvEthPhyRegs.h b/board/mv_feroceon/mv_hal/eth-phy/mvEthPhyRegs.h new file mode 100644 index 0000000..d3f1da0 --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth-phy/mvEthPhyRegs.h @@ -0,0 +1,166 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCethphyregsh +#define __INCethphyregsh + +#include "ctrlEnv/mvCtrlEnvSpec.h" + +/* defines */ +#define ETH_PHY_TIMEOUT 10000 + +/* registers offsetes defines */ +#ifdef MV_88W8660 +#define ETH_PHY_SMI_REG (MV_ETH_REG_BASE(0) + 0x6010) +#else +#define ETH_PHY_SMI_REG (MV_ETH_REG_BASE(0) + 0x004) +#endif + +/* SMI register fields (ETH_PHY_SMI_REG) */ + +#define ETH_PHY_SMI_DATA_OFFS 0 /* Data */ +#define ETH_PHY_SMI_DATA_MASK (0xffff << ETH_PHY_SMI_DATA_OFFS) + +#define ETH_PHY_SMI_DEV_ADDR_OFFS 16 /* PHY device address */ +#define ETH_PHY_SMI_DEV_ADDR_MASK (0x1f << ETH_PHY_SMI_DEV_ADDR_OFFS) + +#define ETH_PHY_SMI_REG_ADDR_OFFS 21 /* PHY device register address */ +#define ETH_PHY_SMI_REG_ADDR_MASK (0x1f << ETH_PHY_SMI_REG_ADDR_OFFS) + +#define ETH_PHY_SMI_OPCODE_OFFS 26 /* Write/Read opcode */ +#define ETH_PHY_SMI_OPCODE_MASK (3 << ETH_PHY_SMI_OPCODE_OFFS) +#define ETH_PHY_SMI_OPCODE_WRITE (0 << ETH_PHY_SMI_OPCODE_OFFS) +#define ETH_PHY_SMI_OPCODE_READ (1 << ETH_PHY_SMI_OPCODE_OFFS) + +#define ETH_PHY_SMI_READ_VALID_BIT 27 /* Read Valid */ +#define ETH_PHY_SMI_READ_VALID_MASK (1 << ETH_PHY_SMI_READ_VALID_BIT) + +#define ETH_PHY_SMI_BUSY_BIT 28 /* Busy */ +#define ETH_PHY_SMI_BUSY_MASK (1 << ETH_PHY_SMI_BUSY_BIT) + +/* PHY registers and bits */ +#define ETH_PHY_CTRL_REG 0 +#define ETH_PHY_STATUS_REG 1 +#define ETH_PHY_AUTONEGO_AD_REG 0x4 +#define ETH_PHY_1000BASE_T_CTRL_REG 9 +#define ETH_PHY_SPEC_STATUS_REG 17 + +/* ETH_PHY_CTRL_REG bits */ +#define ETH_PHY_CTRL_SPEED_MSB_BIT 6 +#define ETH_PHY_CTRL_SPEED_MSB_MASK (1 << ETH_PHY_CTRL_SPEED_MSB_BIT) + +#define ETH_PHY_CTRL_COLISION_TEST_BIT 7 +#define ETH_PHY_CTRL_COLISION_TEST_MASK (1 << ETH_PHY_CTRL_COLISION_TEST_BIT) + +#define ETH_PHY_CTRL_DUPLEX_BIT 8 +#define ETH_PHY_CTRL_DUPLEX_MASK (1 << ETH_PHY_CTRL_DUPLEX_BIT) + +#define ETH_PHY_CTRL_AN_RESTART_BIT 9 +#define ETH_PHY_CTRL_AN_RESTART_MASK (1 << ETH_PHY_CTRL_AN_RESTART_BIT) + +#define ETH_PHY_CTRL_ISOLATE_BIT 10 +#define ETH_PHY_CTRL_ISOLATE_MASK (1 << ETH_PHY_CTRL_ISOLATE_BIT) + +#define ETH_PHY_CTRL_POWER_DOWN_BIT 11 +#define ETH_PHY_CTRL_POWER_DOWN_MASK (1 << ETH_PHY_CTRL_POWER_DOWN_BIT) + +#define ETH_PHY_CTRL_AN_ENABLE_BIT 12 +#define ETH_PHY_CTRL_AN_ENABLE_MASK (1 << ETH_PHY_CTRL_AN_ENABLE_BIT) + +#define ETH_PHY_CTRL_SPEED_LSB_BIT 13 +#define ETH_PHY_CTRL_SPEED_LSB_MASK (1 << ETH_PHY_CTRL_SPEED_LSB_BIT) + +#define ETH_PHY_CTRL_LOOPBACK_BIT 14 +#define ETH_PHY_CTRL_LOOPBACK_MASK (1 << ETH_PHY_CTRL_LOOPBACK_BIT) + +#define ETH_PHY_CTRL_RESET_BIT 15 +#define ETH_PHY_CTRL_RESET_MASK (1 << ETH_PHY_CTRL_RESET_BIT) + +/* ETH_PHY_STATUS_REG bits */ +#define ETH_PHY_STATUS_AN_DONE_BIT 5 +#define ETH_PHY_STATUS_AN_DONE_MASK (1 << ETH_PHY_STATUS_AN_DONE_BIT) + +/* ETH_PHY_1000BASE_T_CTRL_REG bits */ +#define ETH_PHY_1000BASE_ADVERTISE_OFFSET 8 +#define ETH_PHY_1000BASE_ADVERTISE_MASK (0x3 << ETH_PHY_1000BASE_ADVERTISE_OFFSET) + +/* ETH_PHY_SPEC_STATUS_REG bits */ +#define ETH_PHY_SPEC_STATUS_SPEED_OFFS 14 +#define ETH_PHY_SPEC_STATUS_SPEED_MASK (0x3 << ETH_PHY_SPEC_STATUS_SPEED_OFFS) + +#define ETH_PHY_SPEC_STATUS_SPEED_10MBPS (0x0 << ETH_PHY_SPEC_STATUS_SPEED_OFFS) +#define ETH_PHY_SPEC_STATUS_SPEED_100MBPS (0x1 << ETH_PHY_SPEC_STATUS_SPEED_OFFS) +#define ETH_PHY_SPEC_STATUS_SPEED_1000MBPS (0x2 << ETH_PHY_SPEC_STATUS_SPEED_OFFS) + + +#define ETH_PHY_SPEC_STATUS_DUPLEX_BIT 13 +#define ETH_PHY_SPEC_STATUS_DUPLEX_MASK (0x1 << ETH_PHY_SPEC_STATUS_DUPLEX_BIT) + +#define ETH_PHY_SPEC_STATUS_LINK_BIT 10 +#define ETH_PHY_SPEC_STATUS_LINK_MASK (0x1 << ETH_PHY_SPEC_STATUS_LINK_BIT) + +/* ETH_PHY_SPEC_STATUS_REG bits */ +#define ETH_PHY_LED_ACT_LNK_DV 0x4109 + +#endif /* __INCethphyregsh */ diff --git a/board/mv_feroceon/mv_hal/eth/gbe/mvEth.c b/board/mv_feroceon/mv_hal/eth/gbe/mvEth.c new file mode 100644 index 0000000..5f1996c --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth/gbe/mvEth.c @@ -0,0 +1,2940 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEth.c - Marvell's Gigabit Ethernet controller low level driver +* +* DESCRIPTION: +* This file introduce OS independent APIs to Marvell's Gigabit Ethernet +* controller. This Gigabit Ethernet Controller driver API controls +* 1) Operations (i.e. port Init, Finish, Up, Down, PhyReset etc'). +* 2) Data flow (i.e. port Send, Receive etc'). +* 3) MAC Filtering functions (ethSetMcastAddr, ethSetRxFilterMode, etc.) +* 4) MIB counters support (ethReadMibCounter) +* 5) Debug functions (ethPortRegs, ethPortCounters, ethPortQueues, etc.) +* Each Gigabit Ethernet port is controlled via ETH_PORT_CTRL struct. +* This struct includes configuration information as well as driver +* internal data needed for its operations. +* +* Supported Features: +* - OS independent. All required OS services are implemented via external +* OS dependent components (like osLayer or ethOsg) +* - The user is free from Rx/Tx queue managing. +* - Simple Gigabit Ethernet port operation API. +* - Simple Gigabit Ethernet port data flow API. +* - Data flow and operation API support per queue functionality. +* - Support cached descriptors for better performance. +* - PHY access and control API. +* - Port Configuration API. +* - Full control over Special and Other Multicast MAC tables. +* +*******************************************************************************/ +/* includes */ +#include "mvTypes.h" +#include "mv802_3.h" +#include "mvDebug.h" +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "eth-phy/mvEthPhy.h" +#include "eth/mvEth.h" +#include "eth/gbe/mvEthGbe.h" +#include "cpu/mvCpu.h" + +#ifdef INCLUDE_SYNC_BARR +#include "sys/mvCpuIf.h" +#endif + +#ifdef MV_RT_DEBUG +# define ETH_DEBUG +#endif + + +/* locals */ +MV_BOOL ethDescInSram; +MV_BOOL ethDescSwCoher; + +/* This array holds the control structure of each port */ +ETH_PORT_CTRL* ethPortCtrl[MV_ETH_MAX_PORTS]; + +/* Ethernet Port Local routines */ + +static void ethInitRxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue); + +static void ethInitTxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue); + +static void ethSetUcastTable(int portNo, int queue); + +static MV_BOOL ethSetUcastAddr (int ethPortNum, MV_U8 lastNibble, int queue); +static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue); +static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue); + +static void ethFreeDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, MV_BUF_INFO* pDescBuf); +static MV_U8* ethAllocDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, int size, + MV_ULONG* pPhysAddr, MV_U32 *memHandle); + +static MV_U32 mvEthMruGet(MV_U32 maxRxPktSize); + +static void mvEthPortSgmiiConfig(int port); + + + +/******************************************************************************/ +/* EthDrv Initialization functions */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthInit - Initialize the Giga Ethernet unit +* +* DESCRIPTION: +* This function initialize the Giga Ethernet unit. +* 1) Configure Address decode windows of the unit +* 2) Set registers to HW default values. +* 3) Clear and Disable interrupts +* +* INPUT: NONE +* +* RETURN: NONE +* +* NOTE: this function is called once in the boot process. +*******************************************************************************/ +void mvEthHalInit(void) +{ + int port; + + /* Init static data structures */ + for (port=0; port 0) + { + isSram = MV_TRUE; + #if (INTEG_SRAM_COHER == MV_CACHE_COHER_SW) + isSwCoher = MV_TRUE; + #else + isSwCoher = MV_FALSE; + #endif + } +#endif /* ETH_DESCR_IN_SRAM */ + + if(pIsSram != NULL) + *pIsSram = isSram; + + if(pIsSwCoher != NULL) + *pIsSwCoher = isSwCoher; +} + + + +/******************************************************************************/ +/* Port Initialization functions */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthPortInit - Initialize the Ethernet port driver +* +* DESCRIPTION: +* This function initialize the ethernet port. +* 1) Allocate and initialize internal port Control structure. +* 2) Create RX and TX descriptor rings for default RX and TX queues +* 3) Disable RX and TX operations, clear cause registers and +* mask all interrupts. +* 4) Set all registers to default values and clean all MAC tables. +* +* INPUT: +* int portNo - Ethernet port number +* ETH_PORT_INIT *pEthPortInit - Ethernet port init structure +* +* RETURN: +* void* - ethernet port handler, that should be passed to the most other +* functions dealing with this port. +* +* NOTE: This function is called once per port when loading the eth module. +*******************************************************************************/ +void* mvEthPortInit(int portNo, MV_ETH_PORT_INIT *pEthPortInit) +{ + int queue, descSize; + ETH_PORT_CTRL* pPortCtrl; + + /* Check validity of parameters */ + if( (portNo >= (int)mvCtrlEthMaxPortGet()) || + (pEthPortInit->rxDefQ >= MV_ETH_RX_Q_NUM) || + (pEthPortInit->maxRxPktSize < 1518) ) + { + mvOsPrintf("EthPort #%d: Bad initialization parameters\n", portNo); + return NULL; + } + if( (pEthPortInit->rxDescrNum[pEthPortInit->rxDefQ]) == 0) + { + mvOsPrintf("EthPort #%d: rxDefQ (%d) must be created\n", + portNo, pEthPortInit->rxDefQ); + return NULL; + } + + pPortCtrl = (ETH_PORT_CTRL*)mvOsMalloc( sizeof(ETH_PORT_CTRL) ); + if(pPortCtrl == NULL) + { + mvOsPrintf("EthDrv: Can't allocate %dB for port #%d control structure!\n", + (int)sizeof(ETH_PORT_CTRL), portNo); + return NULL; + } + + memset(pPortCtrl, 0, sizeof(ETH_PORT_CTRL) ); + ethPortCtrl[portNo] = pPortCtrl; + + pPortCtrl->portState = MV_UNDEFINED_STATE; + + pPortCtrl->portNo = portNo; + + pPortCtrl->osHandle = pEthPortInit->osHandle; + + /* Copy Configuration parameters */ + pPortCtrl->portConfig.maxRxPktSize = pEthPortInit->maxRxPktSize; + pPortCtrl->portConfig.rxDefQ = pEthPortInit->rxDefQ; + pPortCtrl->portConfig.ejpMode = 0; + + for( queue=0; queuerxQueueConfig[queue].descrNum = pEthPortInit->rxDescrNum[queue]; + } + for( queue=0; queuetxQueueConfig[queue].descrNum = pEthPortInit->txDescrNum[queue]; + } + + mvEthPortDisable(pPortCtrl); + + /* Set the board information regarding PHY address */ +//Patch by QNAP:Fix OnBoard SATA LED and Ethernet LED + mvEthE1116PhyBasicInit(portNo); +// mvEthPhyAddrSet(pPortCtrl, mvBoardPhyAddrGet(portNo) ); +/////////////////////////////////////////////////// + /* Create all requested RX queues */ + for(queue=0; queuerxQueueConfig[queue].descrNum == 0) + continue; + + /* Allocate memory for RX descriptors */ + descSize = ((pPortCtrl->rxQueueConfig[queue].descrNum * ETH_RX_DESC_ALIGNED_SIZE) + + CPU_D_CACHE_LINE_SIZE); + + pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr = + ethAllocDescrMemory(pPortCtrl, descSize, + &pPortCtrl->rxQueue[queue].descBuf.bufPhysAddr, + &pPortCtrl->rxQueue[queue].descBuf.memHandle); + pPortCtrl->rxQueue[queue].descBuf.bufSize = descSize; + if(pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr == NULL) + { + mvOsPrintf("EthPort #%d, rxQ=%d: Can't allocate %d bytes in %s for %d RX descr\n", + pPortCtrl->portNo, queue, descSize, + ethDescInSram ? "SRAM" : "DRAM", + pPortCtrl->rxQueueConfig[queue].descrNum); + return NULL; + } + + ethInitRxDescRing(pPortCtrl, queue); + } + /* Create TX queues */ + for(queue=0; queuetxQueueConfig[queue].descrNum == 0) + continue; + + /* Allocate memory for TX descriptors */ + descSize = ((pPortCtrl->txQueueConfig[queue].descrNum * ETH_TX_DESC_ALIGNED_SIZE) + + CPU_D_CACHE_LINE_SIZE); + + pPortCtrl->txQueue[queue].descBuf.bufVirtPtr = + ethAllocDescrMemory(pPortCtrl, descSize, + &pPortCtrl->txQueue[queue].descBuf.bufPhysAddr, + &pPortCtrl->txQueue[queue].descBuf.memHandle); + pPortCtrl->txQueue[queue].descBuf.bufSize = descSize; + if(pPortCtrl->txQueue[queue].descBuf.bufVirtPtr == NULL) + { + mvOsPrintf("EthPort #%d, txQ=%d: Can't allocate %d bytes in %s for %d TX descr\n", + pPortCtrl->portNo, queue, descSize, ethDescInSram ? "SRAM" : "DRAM", + pPortCtrl->txQueueConfig[queue].descrNum); + return NULL; + } + + ethInitTxDescRing(pPortCtrl, queue); + } + mvEthDefaultsSet(pPortCtrl); + + pPortCtrl->portState = MV_IDLE; + return pPortCtrl; +} + +/******************************************************************************* +* ethPortFinish - Finish the Ethernet port driver +* +* DESCRIPTION: +* This function finish the ethernet port. +* 1) Down ethernet port if needed. +* 2) Delete RX and TX descriptor rings for all created RX and TX queues +* 3) Free internal port Control structure. +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: NONE. +* +*******************************************************************************/ +void mvEthPortFinish(void* pPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + int queue, portNo = pPortCtrl->portNo; + + if(pPortCtrl->portState == MV_ACTIVE) + { + mvOsPrintf("ethPort #%d: Warning !!! Finish port in Active state\n", + portNo); + mvEthPortDisable(pPortHndl); + } + + /* Free all allocated RX queues */ + for(queue=0; queuerxQueue[queue].descBuf); + } + + /* Free all allocated TX queues */ + for(queue=0; queuetxQueue[queue].descBuf); + } + + /* Free port control structure */ + mvOsFree(pPortCtrl); + + ethPortCtrl[portNo] = NULL; +} + +/******************************************************************************* +* mvEthDefaultsSet - Set defaults to the ethernet port +* +* DESCRIPTION: +* This function set default values to the ethernet port. +* 1) Clear Cause registers and Mask all interrupts +* 2) Clear all MAC tables +* 3) Set defaults to all registers +* 4) Reset all created RX and TX descriptors ring +* 5) Reset PHY +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure +* NOTE: +* This function update all the port configuration except those set +* Initialy by the OsGlue by MV_ETH_PORT_INIT. +* This function can be called after portDown to return the port setting +* to defaults. +*******************************************************************************/ +MV_STATUS mvEthDefaultsSet(void* pPortHndl) +{ + int ethPortNo, queue; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + MV_U32 txPrio; + MV_U32 portCfgReg, portCfgExtReg, portSerialCtrlReg, portSerialCtrl1Reg, portSdmaCfgReg; + MV_BOARD_MAC_SPEED boardMacCfg; + + ethPortNo = pPortCtrl->portNo; + + /* Clear Cause registers */ + MV_REG_WRITE(ETH_INTR_CAUSE_REG(ethPortNo),0); + MV_REG_WRITE(ETH_INTR_CAUSE_EXT_REG(ethPortNo),0); + + /* Mask all interrupts */ + MV_REG_WRITE(ETH_INTR_MASK_REG(ethPortNo),0); + MV_REG_WRITE(ETH_INTR_MASK_EXT_REG(ethPortNo),0); + + portCfgReg = PORT_CONFIG_VALUE; + portCfgExtReg = PORT_CONFIG_EXTEND_VALUE; + + boardMacCfg = mvBoardMacSpeedGet(ethPortNo); + + if(boardMacCfg == BOARD_MAC_SPEED_100M) + { + portSerialCtrlReg = PORT_SERIAL_CONTROL_100MB_FORCE_VALUE; + } + else if(boardMacCfg == BOARD_MAC_SPEED_1000M) + { + portSerialCtrlReg = PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE; + } + else + { + portSerialCtrlReg = PORT_SERIAL_CONTROL_VALUE; + } + + /* build PORT_SDMA_CONFIG_REG */ + portSdmaCfgReg = ETH_TX_INTR_COAL_MASK(0); + portSdmaCfgReg |= ETH_TX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE); + +#if ( (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) || \ + (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) ) + /* some devices have restricted RX burst size when using HW coherency */ + portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_4_64BIT_VALUE); +#else + portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE); +#endif + +#if defined(MV_CPU_BE) + /* big endian */ +# if defined(MV_ARM) + portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK | + ETH_TX_NO_DATA_SWAP_MASK | + ETH_DESC_SWAP_MASK); +# elif defined(MV_PPC) + portSdmaCfgReg |= (ETH_RX_DATA_SWAP_MASK | + ETH_TX_DATA_SWAP_MASK | + ETH_NO_DESC_SWAP_MASK); +# else +# error "Giga Ethernet Swap policy is not defined for the CPU_ARCH" +# endif /* MV_ARM / MV_PPC */ + +#else /* MV_CPU_LE */ + /* little endian */ + portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK | + ETH_TX_NO_DATA_SWAP_MASK | + ETH_NO_DESC_SWAP_MASK); +#endif /* MV_CPU_BE / MV_CPU_LE */ + + pPortCtrl->portRxQueueCmdReg = 0; + pPortCtrl->portTxQueueCmdReg = 0; + +#if (MV_ETH_VERSION >= 4) + if(pPortCtrl->portConfig.ejpMode == MV_FALSE) + { + MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo), ETH_TX_EJP_ENABLE_MASK); + } + else + { + MV_REG_WRITE(ETH_TXQ_CMD_1_REG(ethPortNo), 0) + } +#endif /* (MV_ETH_VERSION >= 4) */ + + ethSetUcastTable(ethPortNo, -1); + mvEthSetSpecialMcastTable(ethPortNo, -1); + mvEthSetOtherMcastTable(ethPortNo, -1); + + portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK; + + portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize); + + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg); + + /* Update value of PortConfig register accordingly with all RxQueue types */ + pPortCtrl->portConfig.rxArpQ = pPortCtrl->portConfig.rxDefQ; + pPortCtrl->portConfig.rxBpduQ = pPortCtrl->portConfig.rxDefQ; + pPortCtrl->portConfig.rxTcpQ = pPortCtrl->portConfig.rxDefQ; + pPortCtrl->portConfig.rxUdpQ = pPortCtrl->portConfig.rxDefQ; + + portCfgReg &= ~ETH_DEF_RX_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_QUEUE_MASK(pPortCtrl->portConfig.rxDefQ); + + portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ); + + portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ); + + portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ); + + portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ); + + /* Assignment of Tx CTRP of given queue */ + txPrio = 0; + + for(queue=0; queuetxQueue[queue]; + + if(pQueueCtrl->pFirstDescr != NULL) + { + ethResetTxDescRing(pPortCtrl, queue); + + MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue), + 0x3fffffff); + MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue), + 0x03ffffff); + } + else + { + MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue), 0x0); + MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue), 0x0); + } + } + + /* Assignment of Rx CRDP of given queue */ + for(queue=0; queueportNo; + + if( (pPortCtrl->portState != MV_ACTIVE) && + (pPortCtrl->portState != MV_PAUSED) ) + { + mvOsPrintf("ethDrv port%d: Unexpected port state %d\n", + ethPortNo, pPortCtrl->portState); + return MV_BAD_STATE; + } + + ethPortNo = pPortCtrl->portNo; + + /* Enable port RX. */ + MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNo), pPortCtrl->portRxQueueCmdReg); + + /* Enable port TX. */ + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(ethPortNo)) = pPortCtrl->portTxQueueCmdReg; + + pPortCtrl->portState = MV_ACTIVE; + + return MV_OK; +} + +/******************************************************************************* +* ethPortDown - Stop the Ethernet port activity. +* +* DESCRIPTION: +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure. +* +* NOTE : used for port link down. +*******************************************************************************/ +MV_STATUS mvEthPortDown(void* pEthPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + int ethPortNum = pPortCtrl->portNo; + unsigned int regData; + volatile int uDelay, mDelay; + + /* Stop Rx port activity. Check port Rx activity. */ + regData = (MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_RXQ_ENABLE_MASK; + if(regData != 0) + { + /* Issue stop command for active channels only */ + MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNum), (regData << ETH_RXQ_DISABLE_OFFSET)); + } + + /* Stop Tx port activity. Check port Tx activity. */ + regData = (MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_TXQ_ENABLE_MASK; + if(regData != 0) + { + /* Issue stop command for active channels only */ + MV_REG_WRITE(ETH_TX_QUEUE_COMMAND_REG(ethPortNum), + (regData << ETH_TXQ_DISABLE_OFFSET) ); + } + + /* Force link down */ +/* + regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum)); + regData &= ~(ETH_DO_NOT_FORCE_LINK_FAIL_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData); +*/ + /* Wait for all Rx activity to terminate. */ + mDelay = 0; + do + { + if(mDelay >= RX_DISABLE_TIMEOUT_MSEC) + { + mvOsPrintf("ethPort_%d: TIMEOUT for RX stopped !!! rxQueueCmd - 0x08%x\n", + ethPortNum, regData); + break; + } + mvOsDelay(1); + mDelay++; + + /* Check port RX Command register that all Rx queues are stopped */ + regData = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum)); + } + while(regData & 0xFF); + + /* Wait for all Tx activity to terminate. */ + mDelay = 0; + do + { + if(mDelay >= TX_DISABLE_TIMEOUT_MSEC) + { + mvOsPrintf("ethPort_%d: TIMEOUT for TX stoped !!! txQueueCmd - 0x08%x\n", + ethPortNum, regData); + break; + } + mvOsDelay(1); + mDelay++; + + /* Check port TX Command register that all Tx queues are stopped */ + regData = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum)); + } + while(regData & 0xFF); + + /* Double check to Verify that TX FIFO is Empty */ + mDelay = 0; + while(MV_TRUE) + { + do + { + if(mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC) + { + mvOsPrintf("\n ethPort_%d: TIMEOUT for TX FIFO empty !!! portStatus - 0x08%x\n", + ethPortNum, regData); + break; + } + mvOsDelay(1); + mDelay++; + + regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum)); + } + while( ((regData & ETH_TX_FIFO_EMPTY_MASK) == 0) || + ((regData & ETH_TX_IN_PROGRESS_MASK) != 0) ); + + if(mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC) + break; + + /* Double check */ + regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum)); + if( ((regData & ETH_TX_FIFO_EMPTY_MASK) != 0) && + ((regData & ETH_TX_IN_PROGRESS_MASK) == 0) ) + { + break; + } + else + mvOsPrintf("ethPort_%d: TX FIFO Empty double check failed. %d msec, portStatus=0x%x\n", + ethPortNum, mDelay, regData); + } + + /* Do NOT force link down */ +/* + regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum)); + regData |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData); +*/ + /* Wait about 2500 tclk cycles */ + uDelay = (PORT_DISABLE_WAIT_TCLOCKS/(mvBoardTclkGet()/1000000)); + mvOsUDelay(uDelay); + + pPortCtrl->portState = MV_PAUSED; + + return MV_OK; +} + + +/******************************************************************************* +* ethPortEnable - Enable the Ethernet port and Start RX and TX. +* +* DESCRIPTION: +* This routine enable the Ethernet port and Rx and Tx activity: +* +* Note: Each Rx and Tx queue descriptor's list must be initialized prior +* to calling this function (use etherInitTxDescRing for Tx queues and +* etherInitRxDescRing for Rx queues). +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure. +* +* NOTE: main usage is to enable the port after ifconfig up. +*******************************************************************************/ +MV_STATUS mvEthPortEnable(void* pEthPortHndl) +{ + int ethPortNo; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + MV_U32 portSerialCtrlReg; + + ethPortNo = pPortCtrl->portNo; + + /* Enable port */ + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNo)); + portSerialCtrlReg |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK | ETH_PORT_ENABLE_MASK); + + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg); + + mvEthMibCountersClear(pEthPortHndl); + + pPortCtrl->portState = MV_PAUSED; + + /* If Link is UP, Start RX and TX traffic */ + if( MV_REG_READ( ETH_PORT_STATUS_REG(ethPortNo) ) & ETH_LINK_UP_MASK) + return( mvEthPortUp(pEthPortHndl) ); + + return MV_NOT_READY; +} + + +/******************************************************************************* +* mvEthPortDisable - Stop RX and TX activities and Disable the Ethernet port. +* +* DESCRIPTION: +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure. +* +* NOTE: main usage is to disable the port after ifconfig down. +*******************************************************************************/ +MV_STATUS mvEthPortDisable(void* pEthPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + int ethPortNum = pPortCtrl->portNo; + unsigned int regData; + volatile int delay; + + if(pPortCtrl->portState == MV_ACTIVE) + { + /* Stop RX and TX activities */ + mvEthPortDown(pEthPortHndl); + } + + /* Reset the Enable bit in the Serial Control Register */ + regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum)); + regData &= ~(ETH_PORT_ENABLE_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData); + + /* Wait about 2500 tclk cycles */ + delay = (PORT_DISABLE_WAIT_TCLOCKS*(mvCpuPclkGet()/mvBoardTclkGet())); + for(delay; delay>0; delay--); + + pPortCtrl->portState = MV_IDLE; + return MV_OK; +} + +/******************************************************************************* +* mvEthPortForceTxDone - Get next buffer from TX queue in spite of buffer ownership. +* +* DESCRIPTION: +* This routine used to free buffers attached to the Tx ring and should +* be called only when Giga Ethernet port is Down +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of TX queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to packet was sent. +* +* RETURN: +* MV_EMPTY - There is no more buffers in this queue. +* MV_OK - Buffer detached from the queue and pPktInfo structure +* filled with relevant information. +* +*******************************************************************************/ +MV_PKT_INFO* mvEthPortForceTxDone(void* pEthPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + MV_PKT_INFO* pPktInfo; + ETH_TX_DESC* pTxDesc; + int port = pPortCtrl->portNo; + + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + while( (pQueueCtrl->pUsedDescr != pQueueCtrl->pCurrentDescr) || + (pQueueCtrl->resource == 0) ) + { + /* Free next descriptor */ + pQueueCtrl->resource++; + pTxDesc = (ETH_TX_DESC*)pQueueCtrl->pUsedDescr; + pPktInfo = (MV_PKT_INFO*)pTxDesc->returnInfo; + pPktInfo->status = pTxDesc->cmdSts; + pTxDesc->cmdSts = 0x0; + pTxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc); + + pQueueCtrl->pUsedDescr = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl); + + if(pPktInfo->status & ETH_TX_LAST_DESC_MASK) + return pPktInfo; + } + MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(port, txQueue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + return NULL; +} + + + +/******************************************************************************* +* mvEthPortForceRx - Get next buffer from RX queue in spite of buffer ownership. +* +* DESCRIPTION: +* This routine used to free buffers attached to the Rx ring and should +* be called only when Giga Ethernet port is Down +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int rxQueue - Number of Rx queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to received packet. +* +* RETURN: +* MV_EMPTY - There is no more buffers in this queue. +* MV_OK - Buffer detached from the queue and pBufInfo structure +* filled with relevant information. +* +*******************************************************************************/ +MV_PKT_INFO* mvEthPortForceRx(void* pEthPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_RX_DESC* pRxDesc; + MV_PKT_INFO* pPktInfo; + int port = pPortCtrl->portNo; + + pQueueCtrl = &pPortCtrl->rxQueue[rxQueue]; + + if(pQueueCtrl->resource == 0) + { + MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(port, rxQueue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + + return NULL; + } + /* Free next descriptor */ + pQueueCtrl->resource--; + pRxDesc = (ETH_RX_DESC*)pQueueCtrl->pCurrentDescr; + pPktInfo = (MV_PKT_INFO*)pRxDesc->returnInfo; + + pPktInfo->status = pRxDesc->cmdSts; + pRxDesc->cmdSts = 0x0; + pRxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc); + + pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl); + return pPktInfo; +} + + +/******************************************************************************/ +/* Port Configuration functions */ +/******************************************************************************/ +/******************************************************************************* +* mvEthMruGet - Get MRU configuration for Max Rx packet size. +* +* INPUT: +* MV_U32 maxRxPktSize - max packet size. +* +* RETURN: MV_U32 - MRU configuration. +* +*******************************************************************************/ +static MV_U32 mvEthMruGet(MV_U32 maxRxPktSize) +{ + MV_U32 portSerialCtrlReg = 0; + + if(maxRxPktSize > 9192) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_9700BYTE; + else if(maxRxPktSize > 9022) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_9192BYTE; + else if(maxRxPktSize > 1552) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_9022BYTE; + else if(maxRxPktSize > 1522) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_1552BYTE; + else if(maxRxPktSize > 1518) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_1522BYTE; + else + portSerialCtrlReg |= ETH_MAX_RX_PACKET_1518BYTE; + + return portSerialCtrlReg; +} + +/******************************************************************************* +* mvEthRxCoalSet - Sets coalescing interrupt mechanism on RX path +* +* DESCRIPTION: +* This routine sets the RX coalescing interrupt mechanism parameter. +* This parameter is a timeout counter, that counts in 64 tClk +* chunks, that when timeout event occurs a maskable interrupt occurs. +* The parameter is calculated using the tCLK frequency of the +* MV-64xxx chip, and the required number is in micro seconds. +* +* INPUT: +* void* pPortHndl - Ethernet Port handler. +* MV_U32 uSec - Number of micro seconds between +* RX interrupts +* +* RETURN: +* None. +* +* COMMENT: +* 1 sec - TCLK_RATE clocks +* 1 uSec - TCLK_RATE / 1,000,000 clocks +* +* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64) +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_U32 mvEthRxCoalSet (void* pPortHndl, MV_U32 uSec) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + MV_U32 coal = ((uSec * (mvBoardTclkGet() / 1000000)) / 64); + MV_U32 portSdmaCfgReg; + + portSdmaCfgReg = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo)); + portSdmaCfgReg &= ~ETH_RX_INTR_COAL_ALL_MASK; + + portSdmaCfgReg |= ETH_RX_INTR_COAL_MASK(coal); + +#if (MV_ETH_VERSION >= 2) + /* Set additional bit if needed ETH_RX_INTR_COAL_MSB_BIT (25) */ + if(ETH_RX_INTR_COAL_MASK(coal) > ETH_RX_INTR_COAL_ALL_MASK) + portSdmaCfgReg |= ETH_RX_INTR_COAL_MSB_MASK; +#endif /* MV_ETH_VERSION >= 2 */ + + MV_REG_WRITE (ETH_SDMA_CONFIG_REG(pPortCtrl->portNo), portSdmaCfgReg); + return coal; +} + +/******************************************************************************* +* mvEthTxCoalSet - Sets coalescing interrupt mechanism on TX path +* +* DESCRIPTION: +* This routine sets the TX coalescing interrupt mechanism parameter. +* This parameter is a timeout counter, that counts in 64 tClk +* chunks, that when timeout event occurs a maskable interrupt +* occurs. +* The parameter is calculated using the tCLK frequency of the +* MV-64xxx chip, and the required number is in micro seconds. +* +* INPUT: +* void* pPortHndl - Ethernet Port handler. +* MV_U32 uSec - Number of micro seconds between +* RX interrupts +* +* RETURN: +* None. +* +* COMMENT: +* 1 sec - TCLK_RATE clocks +* 1 uSec - TCLK_RATE / 1,000,000 clocks +* +* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64) +* +*******************************************************************************/ +MV_U32 mvEthTxCoalSet(void* pPortHndl, MV_U32 uSec) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + MV_U32 coal = ((uSec * (mvBoardTclkGet() / 1000000)) / 64); + MV_U32 regVal; + + regVal = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo)); + regVal &= ~ETH_TX_INTR_COAL_ALL_MASK; + regVal |= ETH_TX_INTR_COAL_MASK(coal); + + /* Set TX Coalescing mechanism */ + MV_REG_WRITE (ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo), regVal); + return coal; +} + +/******************************************************************************* +* mvEthCoalGet - Gets RX and TX coalescing values in micro seconds +* +* DESCRIPTION: +* This routine gets the RX and TX coalescing interrupt values. +* The parameter is calculated using the tCLK frequency of the +* MV-64xxx chip, and the returned numbers are in micro seconds. +* +* INPUTs: +* void* pPortHndl - Ethernet Port handler. +* +* OUTPUTs: +* MV_U32* pRxCoal - Number of micro seconds between RX interrupts +* MV_U32* pTxCoal - Number of micro seconds between TX interrupts +* +* RETURN: +* MV_STATUS MV_OK - success +* Others - failure. +* +* COMMENT: +* 1 sec - TCLK_RATE clocks +* 1 uSec - TCLK_RATE / 1,000,000 clocks +* +* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64) +* +*******************************************************************************/ +MV_STATUS mvEthCoalGet(void* pPortHndl, MV_U32* pRxCoal, MV_U32* pTxCoal) +{ + MV_U32 regVal, coal, usec; + + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + /* get TX Coalescing */ + regVal = MV_REG_READ (ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo)); + coal = ((regVal & ETH_TX_INTR_COAL_ALL_MASK) >> ETH_TX_INTR_COAL_OFFSET); + + usec = (coal * 64) / (mvBoardTclkGet() / 1000000); + if(pTxCoal != NULL) + *pTxCoal = usec; + + /* Get RX Coalescing */ + regVal = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo)); + coal = ((regVal & ETH_RX_INTR_COAL_ALL_MASK) >> ETH_RX_INTR_COAL_OFFSET); + +#if (MV_ETH_VERSION >= 2) + if(regVal & ETH_RX_INTR_COAL_MSB_MASK) + { + /* Add MSB */ + coal |= (ETH_RX_INTR_COAL_ALL_MASK + 1); + } +#endif /* MV_ETH_VERSION >= 2 */ + + usec = (coal * 64) / (mvBoardTclkGet() / 1000000); + if(pRxCoal != NULL) + *pRxCoal = usec; + + return MV_OK; +} + +/******************************************************************************* +* mvEthMaxRxSizeSet - +* +* DESCRIPTION: +* Change maximum receive size of the port. This configuration will take place +* after next call of ethPortSetDefaults() function. +* +* INPUT: +* +* RETURN: +*******************************************************************************/ +MV_STATUS mvEthMaxRxSizeSet(void* pPortHndl, int maxRxSize) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + MV_U32 portSerialCtrlReg; + + if((maxRxSize < 1518) || (maxRxSize & ~ETH_RX_BUFFER_MASK)) + return MV_BAD_PARAM; + + pPortCtrl->portConfig.maxRxPktSize = maxRxSize; + + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo)); + portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK; + portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo), portSerialCtrlReg); + + return MV_OK; +} + + +/******************************************************************************/ +/* MAC Filtering functions */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthRxFilterModeSet - Configure Fitering mode of Ethernet port +* +* DESCRIPTION: +* This routine used to free buffers attached to the Rx ring and should +* be called only when Giga Ethernet port is Down +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* MV_BOOL isPromisc - Promiscous mode +* MV_TRUE - accept all Broadcast, Multicast +* and Unicast packets +* MV_FALSE - accept all Broadcast, +* specially added Multicast and +* single Unicast packets +* +* RETURN: MV_STATUS MV_OK - Success, Other - Failure +* +*******************************************************************************/ +MV_STATUS mvEthRxFilterModeSet(void* pEthPortHndl, MV_BOOL isPromisc) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + int queue; + MV_U32 portCfgReg; + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + /* Set / Clear UPM bit in port configuration register */ + if(isPromisc) + { + /* Accept all multicast packets to RX default queue */ + queue = pPortCtrl->portConfig.rxDefQ; + portCfgReg |= ETH_UNICAST_PROMISCUOUS_MODE_MASK; + memset(pPortCtrl->mcastCount, 1, sizeof(pPortCtrl->mcastCount)); + MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo),0xFFFF); + MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo),0xFFFFFFFF); + } + else + { + /* Reject all Multicast addresses */ + queue = -1; + portCfgReg &= ~ETH_UNICAST_PROMISCUOUS_MODE_MASK; + /* Clear all mcastCount */ + memset(pPortCtrl->mcastCount, 0, sizeof(pPortCtrl->mcastCount)); + } + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + /* Set Special Multicast and Other Multicast tables */ + mvEthSetSpecialMcastTable(pPortCtrl->portNo, queue); + mvEthSetOtherMcastTable(pPortCtrl->portNo, queue); + ethSetUcastTable(pPortCtrl->portNo, queue); + + return MV_OK; +} + +/******************************************************************************* +* mvEthMacAddrSet - This function Set the port Unicast address. +* +* DESCRIPTION: +* This function Set the port Ethernet MAC address. This address +* will be used to send Pause frames if enabled. Packets with this +* address will be accepted and dispatched to default RX queue +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler. +* char* pAddr - Address to be set +* +* RETURN: MV_STATUS +* MV_OK - Success, Other - Faulure +* +*******************************************************************************/ +MV_STATUS mvEthMacAddrSet(void* pPortHndl, unsigned char *pAddr, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + unsigned int macH; + unsigned int macL; + + if(queue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", queue); + return MV_BAD_PARAM; + } + + if(queue != -1) + { + macL = (pAddr[4] << 8) | (pAddr[5]); + macH = (pAddr[0] << 24)| (pAddr[1] << 16) | + (pAddr[2] << 8) | (pAddr[3] << 0); + + MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo), macL); + MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo), macH); + } + + /* Accept frames of this address */ + ethSetUcastAddr(pPortCtrl->portNo, pAddr[5], queue); + + return MV_OK; +} + +/******************************************************************************* +* mvEthMacAddrGet - This function returns the port Unicast address. +* +* DESCRIPTION: +* This function returns the port Ethernet MAC address. +* +* INPUT: +* int portNo - Ethernet port number. +* char* pAddr - Pointer where address will be written to +* +* RETURN: MV_STATUS +* MV_OK - Success, Other - Faulure +* +*******************************************************************************/ +MV_STATUS mvEthMacAddrGet(int portNo, unsigned char *pAddr) +{ + unsigned int macH; + unsigned int macL; + + if(pAddr == NULL) + { + mvOsPrintf("mvEthMacAddrGet: NULL pointer.\n"); + return MV_BAD_PARAM; + } + + macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(portNo)); + macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(portNo)); + pAddr[0] = (macH >> 24) & 0xff; + pAddr[1] = (macH >> 16) & 0xff; + pAddr[2] = (macH >> 8) & 0xff; + pAddr[3] = macH & 0xff; + pAddr[4] = (macL >> 8) & 0xff; + pAddr[5] = macL & 0xff; + + return MV_OK; +} + +/******************************************************************************* +* mvEthMcastCrc8Get - Calculate CRC8 of MAC address. +* +* DESCRIPTION: +* +* INPUT: +* MV_U8* pAddr - Address to calculate CRC-8 +* +* RETURN: MV_U8 - CRC-8 of this MAC address +* +*******************************************************************************/ +MV_U8 mvEthMcastCrc8Get(MV_U8* pAddr) +{ + unsigned int macH; + unsigned int macL; + int macArray[48]; + int crc[8]; + int i; + unsigned char crcResult = 0; + + /* Calculate CRC-8 out of the given address */ + macH = (pAddr[0] << 8) | (pAddr[1]); + macL = (pAddr[2] << 24)| (pAddr[3] << 16) | + (pAddr[4] << 8) | (pAddr[5] << 0); + + for(i=0; i<32; i++) + macArray[i] = (macL >> i) & 0x1; + + for(i=32; i<48; i++) + macArray[i] = (macH >> (i - 32)) & 0x1; + + crc[0] = macArray[45] ^ macArray[43] ^ macArray[40] ^ macArray[39] ^ + macArray[35] ^ macArray[34] ^ macArray[31] ^ macArray[30] ^ + macArray[28] ^ macArray[23] ^ macArray[21] ^ macArray[19] ^ + macArray[18] ^ macArray[16] ^ macArray[14] ^ macArray[12] ^ + macArray[8] ^ macArray[7] ^ macArray[6] ^ macArray[0]; + + crc[1] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^ + macArray[41] ^ macArray[39] ^ macArray[36] ^ macArray[34] ^ + macArray[32] ^ macArray[30] ^ macArray[29] ^ macArray[28] ^ + macArray[24] ^ macArray[23] ^ macArray[22] ^ macArray[21] ^ + macArray[20] ^ macArray[18] ^ macArray[17] ^ macArray[16] ^ + macArray[15] ^ macArray[14] ^ macArray[13] ^ macArray[12] ^ + macArray[9] ^ macArray[6] ^ macArray[1] ^ macArray[0]; + + crc[2] = macArray[47] ^ macArray[46] ^ macArray[44] ^ macArray[43] ^ + macArray[42] ^ macArray[39] ^ macArray[37] ^ macArray[34] ^ + macArray[33] ^ macArray[29] ^ macArray[28] ^ macArray[25] ^ + macArray[24] ^ macArray[22] ^ macArray[17] ^ macArray[15] ^ + macArray[13] ^ macArray[12] ^ macArray[10] ^ macArray[8] ^ + macArray[6] ^ macArray[2] ^ macArray[1] ^ macArray[0]; + + crc[3] = macArray[47] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^ + macArray[40] ^ macArray[38] ^ macArray[35] ^ macArray[34] ^ + macArray[30] ^ macArray[29] ^ macArray[26] ^ macArray[25] ^ + macArray[23] ^ macArray[18] ^ macArray[16] ^ macArray[14] ^ + macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[7] ^ + macArray[3] ^ macArray[2] ^ macArray[1]; + + crc[4] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[41] ^ + macArray[39] ^ macArray[36] ^ macArray[35] ^ macArray[31] ^ + macArray[30] ^ macArray[27] ^ macArray[26] ^ macArray[24] ^ + macArray[19] ^ macArray[17] ^ macArray[15] ^ macArray[14] ^ + macArray[12] ^ macArray[10] ^ macArray[8] ^ macArray[4] ^ + macArray[3] ^ macArray[2]; + + crc[5] = macArray[47] ^ macArray[46] ^ macArray[45] ^ macArray[42] ^ + macArray[40] ^ macArray[37] ^ macArray[36] ^ macArray[32] ^ + macArray[31] ^ macArray[28] ^ macArray[27] ^ macArray[25] ^ + macArray[20] ^ macArray[18] ^ macArray[16] ^ macArray[15] ^ + macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[5] ^ + macArray[4] ^ macArray[3]; + + crc[6] = macArray[47] ^ macArray[46] ^ macArray[43] ^ macArray[41] ^ + macArray[38] ^ macArray[37] ^ macArray[33] ^ macArray[32] ^ + macArray[29] ^ macArray[28] ^ macArray[26] ^ macArray[21] ^ + macArray[19] ^ macArray[17] ^ macArray[16] ^ macArray[14] ^ + macArray[12] ^ macArray[10] ^ macArray[6] ^ macArray[5] ^ + macArray[4]; + + crc[7] = macArray[47] ^ macArray[44] ^ macArray[42] ^ macArray[39] ^ + macArray[38] ^ macArray[34] ^ macArray[33] ^ macArray[30] ^ + macArray[29] ^ macArray[27] ^ macArray[22] ^ macArray[20] ^ + macArray[18] ^ macArray[17] ^ macArray[15] ^ macArray[13] ^ + macArray[11] ^ macArray[7] ^ macArray[6] ^ macArray[5]; + + for(i=0; i<8; i++) + crcResult = crcResult | (crc[i] << i); + + return crcResult; +} +/******************************************************************************* +* mvEthMcastAddrSet - Multicast address settings. +* +* DESCRIPTION: +* This API controls the MV device MAC multicast support. +* The MV device supports multicast using two tables: +* 1) Special Multicast Table for MAC addresses of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* In this case, the function calls ethPortSmcAddr() routine to set the +* Special Multicast Table. +* 2) Other Multicast Table for multicast of another type. A CRC-8bit +* is used as an index to the Other Multicast Table entries in the +* DA-Filter table. +* In this case, the function calculates the CRC-8bit value and calls +* ethPortOmcAddr() routine to set the Other Multicast Table. +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler. +* MV_U8* pAddr - Address to be set +* int queue - RX queue to capture all packets with this +* Multicast MAC address. +* -1 means delete this Multicast address. +* +* RETURN: MV_STATUS +* MV_TRUE - Success, Other - Failure +* +*******************************************************************************/ +MV_STATUS mvEthMcastAddrSet(void* pPortHndl, MV_U8 *pAddr, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + unsigned char crcResult = 0; + + if(queue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethPort %d: RX queue #%d is out of range\n", + pPortCtrl->portNo, queue); + return MV_BAD_PARAM; + } + + if((pAddr[0] == 0x01) && + (pAddr[1] == 0x00) && + (pAddr[2] == 0x5E) && + (pAddr[3] == 0x00) && + (pAddr[4] == 0x00)) + { + ethSetSpecialMcastAddr(pPortCtrl->portNo, pAddr[5], queue); + } + else + { + crcResult = mvEthMcastCrc8Get(pAddr); + + /* Check Add counter for this CRC value */ + if(queue == -1) + { + if(pPortCtrl->mcastCount[crcResult] == 0) + { + mvOsPrintf("ethPort #%d: No valid Mcast for crc8=0x%02x\n", + pPortCtrl->portNo, (unsigned)crcResult); + return MV_NO_SUCH; + } + + pPortCtrl->mcastCount[crcResult]--; + if(pPortCtrl->mcastCount[crcResult] != 0) + { + mvOsPrintf("ethPort #%d: After delete there are %d valid Mcast for crc8=0x%02x\n", + pPortCtrl->portNo, pPortCtrl->mcastCount[crcResult], + (unsigned)crcResult); + return MV_NO_CHANGE; + } + } + else + { + pPortCtrl->mcastCount[crcResult]++; + if(pPortCtrl->mcastCount[crcResult] > 1) + { + mvOsPrintf("ethPort #%d: Valid Mcast for crc8=0x%02x already exists\n", + pPortCtrl->portNo, (unsigned)crcResult); + return MV_NO_CHANGE; + } + } + ethSetOtherMcastAddr(pPortCtrl->portNo, crcResult, queue); + } + return MV_OK; +} + +/******************************************************************************* +* ethSetUcastTable - Unicast address settings. +* +* DESCRIPTION: +* Set all entries in the Unicast MAC Table queue==-1 means reject all +* INPUT: +* +* RETURN: +* +*******************************************************************************/ +static void ethSetUcastTable(int portNo, int queue) +{ + int offset; + MV_U32 regValue; + + if(queue == -1) + { + regValue = 0; + } + else + { + regValue = (((0x01 | (queue<<1)) << 0) | + ((0x01 | (queue<<1)) << 8) | + ((0x01 | (queue<<1)) << 16) | + ((0x01 | (queue<<1)) << 24)); + } + + for (offset=0; offset<=0xC; offset+=4) + MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(portNo) + offset), regValue); +} + +/******************************************************************************* +* mvEthSetSpecialMcastTable - Special Multicast address settings. +* +* DESCRIPTION: +* Set all entries to the Special Multicast MAC Table. queue==-1 means reject all +* INPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvEthSetSpecialMcastTable(int portNo, int queue) +{ + int offset; + MV_U32 regValue; + + if(queue == -1) + { + regValue = 0; + } + else + { + regValue = (((0x01 | (queue<<1)) << 0) | + ((0x01 | (queue<<1)) << 8) | + ((0x01 | (queue<<1)) << 16) | + ((0x01 | (queue<<1)) << 24)); + } + + for (offset=0; offset<=0xFC; offset+=4) + { + MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(portNo) + + offset), regValue); + } +} + +/******************************************************************************* +* mvEthSetOtherMcastTable - Other Multicast address settings. +* +* DESCRIPTION: +* Set all entries to the Other Multicast MAC Table. queue==-1 means reject all +* INPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvEthSetOtherMcastTable(int portNo, int queue) +{ + int offset; + MV_U32 regValue; + + if(queue == -1) + { + regValue = 0; + } + else + { + regValue = (((0x01 | (queue<<1)) << 0) | + ((0x01 | (queue<<1)) << 8) | + ((0x01 | (queue<<1)) << 16) | + ((0x01 | (queue<<1)) << 24)); + } + + for (offset=0; offset<=0xFC; offset+=4) + { + MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(portNo) + + offset), regValue); + } +} + +/******************************************************************************* +* ethSetUcastAddr - This function Set the port unicast address table +* +* DESCRIPTION: +* This function locates the proper entry in the Unicast table for the +* specified MAC nibble and sets its properties according to function +* parameters. +* +* INPUT: +* int ethPortNum - Port number. +* MV_U8 lastNibble - Unicast MAC Address last nibble. +* int queue - Rx queue number for this MAC address. +* value "-1" means remove address +* +* OUTPUT: +* This function add/removes MAC addresses from the port unicast address +* table. +* +* RETURN: +* MV_TRUE is output succeeded. +* MV_FALSE if option parameter is invalid. +* +*******************************************************************************/ +static MV_BOOL ethSetUcastAddr(int portNo, MV_U8 lastNibble, int queue) +{ + unsigned int unicastReg; + unsigned int tblOffset; + unsigned int regOffset; + + /* Locate the Unicast table entry */ + lastNibble = (0xf & lastNibble); + tblOffset = (lastNibble / 4) * 4; /* Register offset from unicast table base*/ + regOffset = lastNibble % 4; /* Entry offset within the above register */ + + + unicastReg = MV_REG_READ( (ETH_DA_FILTER_UCAST_BASE(portNo) + + tblOffset)); + + + if(queue == -1) + { + /* Clear accepts frame bit at specified unicast DA table entry */ + unicastReg &= ~(0xFF << (8*regOffset)); + } + else + { + unicastReg &= ~(0xFF << (8*regOffset)); + unicastReg |= ((0x01 | (queue<<1)) << (8*regOffset)); + } + MV_REG_WRITE( (ETH_DA_FILTER_UCAST_BASE(portNo) + tblOffset), + unicastReg); + + return MV_TRUE; +} + +/******************************************************************************* +* ethSetSpecialMcastAddr - Special Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device special MAC multicast support. +* The Special Multicast Table for MAC addresses supports MAC of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* This function set the Special Multicast Table appropriate entry +* according to the argument given. +* +* INPUT: +* int ethPortNum Port number. +* unsigned char mcByte Multicast addr last byte (MAC DA[7:0] bits). +* int queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* MV_TRUE is output succeeded. +* MV_FALSE if option parameter is invalid. +* +*******************************************************************************/ +static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue) +{ + unsigned int smcTableReg; + unsigned int tblOffset; + unsigned int regOffset; + + /* Locate the SMC table entry */ + tblOffset = (lastByte / 4); /* Register offset from SMC table base */ + regOffset = lastByte % 4; /* Entry offset within the above register */ + + smcTableReg = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) + tblOffset*4)); + + if(queue == -1) + { + /* Clear accepts frame bit at specified Special DA table entry */ + smcTableReg &= ~(0xFF << (8 * regOffset)); + } + else + { + smcTableReg &= ~(0xFF << (8 * regOffset)); + smcTableReg |= ((0x01 | (queue<<1)) << (8 * regOffset)); + } + MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) + + tblOffset*4), smcTableReg); + + return MV_TRUE; +} + +/******************************************************************************* +* ethSetOtherMcastAddr - Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device Other MAC multicast support. +* The Other Multicast Table is used for multicast of another type. +* A CRC-8bit is used as an index to the Other Multicast Table entries +* in the DA-Filter table. +* The function gets the CRC-8bit value from the calling routine and +* set the Other Multicast Table appropriate entry according to the +* CRC-8 argument given. +* +* INPUT: +* int ethPortNum Port number. +* MV_U8 crc8 A CRC-8bit (Polynomial: x^8+x^2+x^1+1). +* int queue Rx queue number for this MAC address. +* +* OUTPUT: +* See description. +* +* RETURN: +* MV_TRUE is output succeeded. +* MV_FALSE if option parameter is invalid. +* +*******************************************************************************/ +static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue) +{ + unsigned int omcTableReg; + unsigned int tblOffset; + unsigned int regOffset; + + /* Locate the OMC table entry */ + tblOffset = (crc8 / 4) * 4; /* Register offset from OMC table base */ + regOffset = crc8 % 4; /* Entry offset within the above register */ + + omcTableReg = MV_REG_READ( + (ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset)); + + if(queue == -1) + { + /* Clear accepts frame bit at specified Other DA table entry */ + omcTableReg &= ~(0xFF << (8 * regOffset)); + } + else + { + omcTableReg &= ~(0xFF << (8 * regOffset)); + omcTableReg |= ((0x01 | (queue<<1)) << (8 * regOffset)); + } + + MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset), + omcTableReg); + + return MV_TRUE; +} + + +/******************************************************************************/ +/* MIB Counters functions */ +/******************************************************************************/ + + +/******************************************************************************* +* mvEthMibCounterRead - Read a MIB counter +* +* DESCRIPTION: +* This function reads a MIB counter of a specific ethernet port. +* NOTE - Read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW or +* ETH_MIB_GOOD_OCTETS_SENT_LOW counters will return 64 bits value, +* so pHigh32 pointer should not be NULL in this case. +* +* INPUT: +* int ethPortNum - Ethernet Port number. +* unsigned int mibOffset - MIB counter offset. +* +* OUTPUT: +* MV_U32* pHigh32 - pointer to place where 32 most significant bits +* of the counter will be stored. +* +* RETURN: +* 32 low sgnificant bits of MIB counter value. +* +*******************************************************************************/ +MV_U32 mvEthMibCounterRead(void* pPortHandle, unsigned int mibOffset, + MV_U32* pHigh32) +{ + int portNo; + MV_U32 valLow32, valHigh32; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + + portNo = pPortCtrl->portNo; + + valLow32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset); + + /* Implement FEr ETH. Erroneous Value when Reading the Upper 32-bits */ + /* of a 64-bit MIB Counter. */ + if( (mibOffset == ETH_MIB_GOOD_OCTETS_RECEIVED_LOW) || + (mibOffset == ETH_MIB_GOOD_OCTETS_SENT_LOW) ) + { + valHigh32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset + 4); + if(pHigh32 != NULL) + *pHigh32 = valHigh32; + } + return valLow32; +} + +/******************************************************************************* +* mvEthMibCountersClear - Clear all MIB counters +* +* DESCRIPTION: +* This function clears all MIB counters +* +* INPUT: +* int ethPortNum - Ethernet Port number. +* +* +* RETURN: void +* +*******************************************************************************/ +void mvEthMibCountersClear(void* pPortHandle) +{ + int i, portNo; + unsigned int dummy; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + + portNo = pPortCtrl->portNo; + + /* Perform dummy reads from MIB counters */ + for(i=ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i 0xFF) + { + mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl->portNo, tos); + return -1; + } + regIdx = mvOsDivide(tos>>2, 10); + regOffs = mvOsReminder(tos>>2, 10); + + regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx) ); + rxq = (regValue >> (regOffs*3)); + rxq &= 0x7; + + return rxq; +} + +/******************************************************************************* +* mvEthTosToRxqSet - Map packets with special TOS value to special RX queue +* +* DESCRIPTION: +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int tos - TOS value in the IP header of the packet +* int rxq - RX Queue for packets with the configured TOS value +* Negative value (-1) means no special processing for these packets, +* so they will be processed as regular packets. +* +* RETURN: MV_STATUS +*******************************************************************************/ +MV_STATUS mvEthTosToRxqSet(void* pPortHandle, int tos, int rxq) +{ + MV_U32 regValue; + int regIdx, regOffs; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + + if( (rxq < 0) || (rxq >= MV_ETH_RX_Q_NUM) ) + { + mvOsPrintf("eth_%d: RX queue #%d is out of range\n", pPortCtrl->portNo, rxq); + return MV_BAD_PARAM; + } + if(tos > 0xFF) + { + mvOsPrintf("eth_%d: tos=0x%x is out of range\n", pPortCtrl->portNo, tos); + return MV_BAD_PARAM; + } + regIdx = mvOsDivide(tos>>2, 10); + regOffs = mvOsReminder(tos>>2, 10); + + regValue = MV_REG_READ(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx) ); + regValue &= ~(0x7 << (regOffs*3)); + regValue |= (rxq << (regOffs*3)); + + MV_REG_WRITE(ETH_DIFF_SERV_PRIO_REG(pPortCtrl->portNo, regIdx), regValue); + return MV_OK; +} + +/******************************************************************************* +* mvEthVlanPrioRxQueue - Configure RX queue to capture VLAN tagged packets with +* special priority bits [0-2] +* +* DESCRIPTION: +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int bpduQueue - Special queue to capture VLAN tagged packets with special +* priority. +* Negative value (-1) means no special processing for these packets, +* so they will be processed as regular packets. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthVlanPrioRxQueue(void* pPortHandle, int vlanPrio, int vlanPrioQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 vlanPrioReg; + + if(vlanPrioQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", vlanPrioQueue); + return MV_BAD_PARAM; + } + if(vlanPrio >= 8) + { + mvOsPrintf("ethDrv: vlanPrio=%d is out of range\n", vlanPrio); + return MV_BAD_PARAM; + } + + vlanPrioReg = MV_REG_READ(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo)); + vlanPrioReg &= ~(0x7 << (vlanPrio*3)); + vlanPrioReg |= (vlanPrioQueue << (vlanPrio*3)); + MV_REG_WRITE(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo), vlanPrioReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthBpduRxQueue - Configure RX queue to capture BPDU packets. +* +* DESCRIPTION: +* This function defines processing of BPDU packets. +* BPDU packets can be accepted and captured to one of RX queues +* or can be processing as regular Multicast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int bpduQueue - Special queue to capture BPDU packets (DA is equal to +* 01-80-C2-00-00-00 through 01-80-C2-00-00-FF, +* except for the Flow-Control Pause packets). +* Negative value (-1) means no special processing for BPDU, +* packets so they will be processed as regular Multicast packets. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthBpduRxQueue(void* pPortHandle, int bpduQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + MV_U32 portCfgExtReg; + + if(bpduQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", bpduQueue); + return MV_BAD_PARAM; + } + + portCfgExtReg = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo)); + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + if(bpduQueue >= 0) + { + pPortCtrl->portConfig.rxBpduQ = bpduQueue; + + portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ); + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + portCfgExtReg |= ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK; + } + else + { + pPortCtrl->portConfig.rxBpduQ = -1; + /* no special processing for BPDU packets */ + portCfgExtReg &= (~ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK); + } + + MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo), portCfgExtReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthArpRxQueue - Configure RX queue to capture ARP packets. +* +* DESCRIPTION: +* This function defines processing of ARP (type=0x0806) packets. +* ARP packets can be accepted and captured to one of RX queues +* or can be processed as other Broadcast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int arpQueue - Special queue to capture ARP packets (type=0x806). +* Negative value (-1) means discard ARP packets +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthArpRxQueue(void* pPortHandle, int arpQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + + if(arpQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", arpQueue); + return MV_BAD_PARAM; + } + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + + if(arpQueue >= 0) + { + pPortCtrl->portConfig.rxArpQ = arpQueue; + portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ); + + portCfgReg &= (~ETH_REJECT_ARP_BCAST_MASK); + } + else + { + pPortCtrl->portConfig.rxArpQ = -1; + portCfgReg |= ETH_REJECT_ARP_BCAST_MASK; + } + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthTcpRxQueue - Configure RX queue to capture TCP packets. +* +* DESCRIPTION: +* This function defines processing of TCP packets. +* TCP packets can be accepted and captured to one of RX queues +* or can be processed as regular Unicast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int tcpQueue - Special queue to capture TCP packets. Value "-1" +* means no special processing for TCP packets, +* so they will be processed as regular +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthTcpRxQueue(void* pPortHandle, int tcpQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + + if(tcpQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", tcpQueue); + return MV_BAD_PARAM; + } + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + + if(tcpQueue >= 0) + { + pPortCtrl->portConfig.rxTcpQ = tcpQueue; + portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ); + + portCfgReg |= ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK; + } + else + { + pPortCtrl->portConfig.rxTcpQ = -1; + portCfgReg &= (~ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK); + } + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthUdpRxQueue - Configure RX queue to capture UDP packets. +* +* DESCRIPTION: +* This function defines processing of UDP packets. +* TCP packets can be accepted and captured to one of RX queues +* or can be processed as regular Unicast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int udpQueue - Special queue to capture UDP packets. Value "-1" +* means no special processing for UDP packets, +* so they will be processed as regular +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthUdpRxQueue(void* pPortHandle, int udpQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + + if(udpQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", udpQueue); + return MV_BAD_PARAM; + } + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + + if(udpQueue >= 0) + { + pPortCtrl->portConfig.rxUdpQ = udpQueue; + portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ); + + portCfgReg |= ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK; + } + else + { + pPortCtrl->portConfig.rxUdpQ = -1; + portCfgReg &= ~ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK; + } + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + return MV_OK; +} + + +/******************************************************************************/ +/* Speed, Duplex, FlowControl routines */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthSpeedDuplexSet - Set Speed and Duplex of the port. +* +* DESCRIPTION: +* This function configure the port to work with desirable Duplex and Speed. +* Changing of these parameters are allowed only when port is disabled. +* This function disable the port if was enabled, change duplex and speed +* and, enable the port back if needed. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* ETH_PORT_SPEED speed - Speed of the port. +* ETH_PORT_SPEED duplex - Duplex of the port. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_OUT_OF_RANGE - Failed. Port is out of valid range +* MV_NOT_FOUND - Failed. Port is not initialized. +* MV_BAD_PARAM - Input parameters (speed/duplex) in conflict. +* MV_BAD_VALUE - Value of one of input parameters (speed, duplex) +* is not valid +* +*******************************************************************************/ +MV_STATUS mvEthSpeedDuplexSet(void* pPortHandle, MV_ETH_PORT_SPEED speed, + MV_ETH_PORT_DUPLEX duplex) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + MV_U32 portSerialCtrlReg; + + if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet()) ) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + /* Check validity */ + if( (speed == MV_ETH_SPEED_1000) && (duplex == MV_ETH_DUPLEX_HALF) ) + return MV_BAD_PARAM; + + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port)); + /* Set Speed */ + switch(speed) + { + case MV_ETH_SPEED_AN: + portSerialCtrlReg &= ~ETH_DISABLE_SPEED_AUTO_NEG_MASK; + break; + + case MV_ETH_SPEED_10: + portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK; + portSerialCtrlReg &= ~ETH_SET_MII_SPEED_100_MASK; + break; + + case MV_ETH_SPEED_100: + portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK; + portSerialCtrlReg |= ETH_SET_MII_SPEED_100_MASK; + break; + + case MV_ETH_SPEED_1000: + portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_SET_GMII_SPEED_1000_MASK; + break; + + default: + mvOsPrintf("ethDrv: Unexpected Speed value %d\n", speed); + return MV_BAD_VALUE; + } + /* Set duplex */ + switch(duplex) + { + case MV_ETH_DUPLEX_AN: + portSerialCtrlReg &= ~ETH_DISABLE_DUPLEX_AUTO_NEG_MASK; + break; + + case MV_ETH_DUPLEX_HALF: + portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_FULL_DUPLEX_MASK; + break; + + case MV_ETH_DUPLEX_FULL: + portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_SET_FULL_DUPLEX_MASK; + break; + + default: + mvOsPrintf("ethDrv: Unexpected Duplex value %d\n", duplex); + return MV_BAD_VALUE; + } + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), portSerialCtrlReg); + + return MV_OK; +} + +/******************************************************************************* +* mvEthFlowCtrlSet - Set Flow Control of the port. +* +* DESCRIPTION: +* This function configure the port to work with desirable Duplex and +* Speed. Changing of these parameters are allowed only when port is +* disabled. This function disable the port if was enabled, change +* duplex and speed and, enable the port back if needed. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* MV_ETH_PORT_FC flowControl - Flow control of the port. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_OUT_OF_RANGE - Failed. Port is out of valid range +* MV_NOT_FOUND - Failed. Port is not initialized. +* MV_BAD_VALUE - Value flowControl parameters is not valid +* +*******************************************************************************/ +MV_STATUS mvEthFlowCtrlSet(void* pPortHandle, MV_ETH_PORT_FC flowControl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + MV_U32 portSerialCtrlReg; + + if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet() ) ) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port)); + switch(flowControl) + { + case MV_ETH_FC_AN_ADV_DIS: + portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_ADVERTISE_SYM_FC_MASK; + break; + + case MV_ETH_FC_AN_ADV_SYM: + portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_ADVERTISE_SYM_FC_MASK; + break; + + case MV_ETH_FC_DISABLE: + portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_FLOW_CTRL_MASK; + break; + + case MV_ETH_FC_ENABLE: + portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_SET_FLOW_CTRL_MASK; + break; + + default: + mvOsPrintf("ethDrv: Unexpected FlowControl value %d\n", flowControl); + return MV_BAD_VALUE; + } + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), portSerialCtrlReg); + + return MV_OK; +} + +/******************************************************************************* +* mvEthHeaderModeSet - Set port header mode. +* +* DESCRIPTION: +* This function configures the port to work in Marvell-Header mode. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* MV_ETH_HEADER_MODE headerMode - The header mode to set the port in. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_NOT_SUPPORTED- Feature not supported. +* MV_OUT_OF_RANGE - Failed. Port is out of valid range +* MV_NOT_FOUND - Failed. Port is not initialized. +* MV_BAD_VALUE - Value of headerMode or numRxQueue parameter is not valid. +* +*******************************************************************************/ +MV_STATUS mvEthHeaderModeSet(void* pPortHandle, MV_ETH_HEADER_MODE headerMode) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + MV_U32 mvHeaderReg; + MV_U32 numRxQ = MV_ETH_RX_Q_NUM; + + if((port < 0) || (port >= mvCtrlEthMaxPortGet())) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + mvHeaderReg = MV_REG_READ(ETH_PORT_MARVELL_HEADER_REG(port)); + /* Disable header mode. */ + mvHeaderReg &= ~ETH_MVHDR_EN_MASK; + + if(headerMode != MV_ETH_DISABLE_HEADER_MODE) + { + /* Enable Header mode. */ + mvHeaderReg |= ETH_MVHDR_EN_MASK; + + /* Clear DA-Prefix & MHMask fields.*/ + mvHeaderReg &= ~(ETH_MVHDR_DAPREFIX_MASK | ETH_MVHDR_MHMASK_MASK); + + if(numRxQ > 1) + { + switch (headerMode) + { + case(MV_ETH_ENABLE_HEADER_MODE_PRI_2_1): + mvHeaderReg |= ETH_MVHDR_DAPREFIX_PRI_1_2; + break; + case(MV_ETH_ENABLE_HEADER_MODE_PRI_DBNUM): + mvHeaderReg |= ETH_MVHDR_DAPREFIX_DBNUM_PRI; + break; + case(MV_ETH_ENABLE_HEADER_MODE_PRI_SPID): + mvHeaderReg |= ETH_MVHDR_DAPREFIX_SPID_PRI; + break; + default: + break; + } + + switch (numRxQ) + { + case (4): + mvHeaderReg |= ETH_MVHDR_MHMASK_4_QUEUE; + break; + case (8): + mvHeaderReg |= ETH_MVHDR_MHMASK_8_QUEUE; + break; + default: + break; + } + } + } + + MV_REG_WRITE(ETH_PORT_MARVELL_HEADER_REG(port), mvHeaderReg); + + return MV_OK; +} + +#if (MV_ETH_VERSION >= 4) +/******************************************************************************* +* mvEthEjpModeSet - Enable / Disable EJP policy for TX. +* +* DESCRIPTION: +* This function +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* MV_BOOL TRUE - enable EJP mode +* FALSE - disable EJP mode +* +* OUTPUT: MV_STATUS +* MV_OK - Success +* Other - Failure +* +* RETURN: None. +* +*******************************************************************************/ +MV_STATUS mvEthEjpModeSet(void* pPortHandle, int mode) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + + if((port < 0) || (port >= mvCtrlEthMaxPortGet())) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + pPortCtrl->portConfig.ejpMode = mode; + if(mode) + { + /* EJP enabled */ + MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port), ETH_TX_EJP_ENABLE_MASK); + } + else + { + /* EJP disabled */ + MV_REG_WRITE(ETH_TXQ_CMD_1_REG(port), 0); + } + mvOsPrintf("eth_%d: EJP %s - ETH_TXQ_CMD_1_REG: 0x%x = 0x%08x\n", + port, mode ? "Enabled" : "Disabled", ETH_TXQ_CMD_1_REG(port), + MV_REG_READ(ETH_TXQ_CMD_1_REG(port))); + + return MV_OK; +} +#endif /* MV_ETH_VERSION >= 4 */ + +/******************************************************************************* +* mvEthStatusGet - Get major properties of the port . +* +* DESCRIPTION: +* This function get major properties of the port (link, speed, duplex, +* flowControl, etc) and return them using the single structure. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* +* OUTPUT: +* MV_ETH_PORT_STATUS* pStatus - Pointer to structure, were port status +* will be placed. +* +* RETURN: None. +* +*******************************************************************************/ +void mvEthStatusGet(void* pPortHandle, MV_ETH_PORT_STATUS* pStatus) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + + MV_U32 regValue; + + regValue = MV_REG_READ( ETH_PORT_STATUS_REG(port) ); + + if(regValue & ETH_GMII_SPEED_1000_MASK) + pStatus->speed = MV_ETH_SPEED_1000; + else if(regValue & ETH_MII_SPEED_100_MASK) + pStatus->speed = MV_ETH_SPEED_100; + else + pStatus->speed = MV_ETH_SPEED_10; + + if(regValue & ETH_LINK_UP_MASK) + pStatus->isLinkUp = MV_TRUE; + else + pStatus->isLinkUp = MV_FALSE; + + if(regValue & ETH_FULL_DUPLEX_MASK) + pStatus->duplex = MV_ETH_DUPLEX_FULL; + else + pStatus->duplex = MV_ETH_DUPLEX_HALF; + + + if(regValue & ETH_ENABLE_RCV_FLOW_CTRL_MASK) + pStatus->flowControl = MV_ETH_FC_ENABLE; + else + pStatus->flowControl = MV_ETH_FC_DISABLE; +} + + +/******************************************************************************/ +/* PHY Control Functions */ +/******************************************************************************/ + + +/******************************************************************************* +* mvEthPhyAddrSet - Set the ethernet port PHY address. +* +* DESCRIPTION: +* This routine set the ethernet port PHY address according to given +* parameter. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int phyAddr - PHY address +* +* RETURN: +* None. +* +*******************************************************************************/ +void mvEthPhyAddrSet(void* pPortHandle, int phyAddr) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + unsigned int regData; + + regData = MV_REG_READ(ETH_PHY_ADDR_REG(port)); + + regData &= ~ETH_PHY_ADDR_MASK; + regData |= phyAddr; + + MV_REG_WRITE(ETH_PHY_ADDR_REG(port), regData); + + return; +} + +/******************************************************************************* +* mvEthPhyAddrGet - Get the ethernet port PHY address. +* +* DESCRIPTION: +* This routine returns the given ethernet port PHY address. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* +* +* RETURN: int - PHY address. +* +*******************************************************************************/ +int mvEthPhyAddrGet(void* pPortHandle) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + unsigned int regData; + + regData = MV_REG_READ(ETH_PHY_ADDR_REG(port)); + + return ((regData >> (5 * port)) & 0x1f); +} + +/******************************************************************************/ +/* Descriptor handling Functions */ +/******************************************************************************/ + +/******************************************************************************* +* etherInitRxDescRing - Curve a Rx chain desc list and buffer in memory. +* +* DESCRIPTION: +* This function prepares a Rx chained list of descriptors and packet +* buffers in a form of a ring. The routine must be called after port +* initialization routine and before port start routine. +* The Ethernet SDMA engine uses CPU bus addresses to access the various +* devices in the system (i.e. DRAM). This function uses the ethernet +* struct 'virtual to physical' routine (set by the user) to set the ring +* with physical addresses. +* +* INPUT: +* ETH_QUEUE_CTRL *pEthPortCtrl Ethernet Port Control srtuct. +* int rxQueue Number of Rx queue. +* int rxDescNum Number of Rx descriptors +* MV_U8* rxDescBaseAddr Rx descriptors memory area base addr. +* +* OUTPUT: +* The routine updates the Ethernet port control struct with information +* regarding the Rx descriptors and buffers. +* +* RETURN: None +* +*******************************************************************************/ +static void ethInitRxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue) +{ + ETH_RX_DESC *pRxDescBase, *pRxDesc, *pRxPrevDesc; + int ix, rxDescNum = pPortCtrl->rxQueueConfig[queue].descrNum; + ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->rxQueue[queue]; + + /* Make sure descriptor address is cache line size aligned */ + pRxDescBase = (ETH_RX_DESC*)MV_ALIGN_UP((MV_ULONG)pQueueCtrl->descBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + pRxDesc = (ETH_RX_DESC*)pRxDescBase; + pRxPrevDesc = pRxDesc; + + /* initialize the Rx descriptors ring */ + for (ix=0; ixbufSize = 0x0; + pRxDesc->byteCnt = 0x0; + pRxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pRxDesc->bufPtr = 0x0; + pRxDesc->returnInfo = 0x0; + pRxPrevDesc = pRxDesc; + if(ix == (rxDescNum-1)) + { + /* Closing Rx descriptors ring */ + pRxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pRxDescBase); + } + else + { + pRxDesc = (ETH_RX_DESC*)((MV_ULONG)pRxDesc + ETH_RX_DESC_ALIGNED_SIZE); + pRxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pRxDesc); + } + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxPrevDesc); + } + + pQueueCtrl->pCurrentDescr = pRxDescBase; + pQueueCtrl->pUsedDescr = pRxDescBase; + + pQueueCtrl->pFirstDescr = pRxDescBase; + pQueueCtrl->pLastDescr = pRxDesc; + pQueueCtrl->resource = 0; +} + +void ethResetRxDescRing(void* pPortHndl, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->rxQueue[queue]; + ETH_RX_DESC* pRxDesc = (ETH_RX_DESC*)pQueueCtrl->pFirstDescr; + + pQueueCtrl->resource = 0; + if(pQueueCtrl->pFirstDescr != NULL) + { + while(MV_TRUE) + { + pRxDesc->bufSize = 0x0; + pRxDesc->byteCnt = 0x0; + pRxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pRxDesc->bufPtr = 0x0; + pRxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc); + if( (void*)pRxDesc == pQueueCtrl->pLastDescr) + break; + pRxDesc = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl); + } + pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr; + pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr; + + /* Update RX Command register */ + pPortCtrl->portRxQueueCmdReg |= (1 << queue); + + /* update HW */ + MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + } + else + { + /* Update RX Command register */ + pPortCtrl->portRxQueueCmdReg &= ~(1 << queue); + + /* update HW */ + MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0); + } +} + +/******************************************************************************* +* etherInitTxDescRing - Curve a Tx chain desc list and buffer in memory. +* +* DESCRIPTION: +* This function prepares a Tx chained list of descriptors and packet +* buffers in a form of a ring. The routine must be called after port +* initialization routine and before port start routine. +* The Ethernet SDMA engine uses CPU bus addresses to access the various +* devices in the system (i.e. DRAM). This function uses the ethernet +* struct 'virtual to physical' routine (set by the user) to set the ring +* with physical addresses. +* +* INPUT: +* ETH_PORT_CTRL *pEthPortCtrl Ethernet Port Control srtuct. +* int txQueue Number of Tx queue. +* int txDescNum Number of Tx descriptors +* int txBuffSize Size of Tx buffer +* MV_U8* pTxDescBase Tx descriptors memory area base addr. +* +* OUTPUT: +* The routine updates the Ethernet port control struct with information +* regarding the Tx descriptors and buffers. +* +* RETURN: None. +* +*******************************************************************************/ +static void ethInitTxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue) +{ + ETH_TX_DESC *pTxDescBase, *pTxDesc, *pTxPrevDesc; + int ix, txDescNum = pPortCtrl->txQueueConfig[queue].descrNum; + ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->txQueue[queue]; + + /* Make sure descriptor address is cache line size aligned */ + pTxDescBase = (ETH_TX_DESC*)MV_ALIGN_UP((MV_ULONG)pQueueCtrl->descBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + pTxDesc = (ETH_TX_DESC*)pTxDescBase; + pTxPrevDesc = pTxDesc; + + /* initialize the Tx descriptors ring */ + for (ix=0; ixbyteCnt = 0x0000; + pTxDesc->L4iChk = 0x0000; + pTxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pTxDesc->bufPtr = 0x0; + pTxDesc->returnInfo = 0x0; + + pTxPrevDesc = pTxDesc; + + if(ix == (txDescNum-1)) + { + /* Closing Tx descriptors ring */ + pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDescBase); + } + else + { + pTxDesc = (ETH_TX_DESC*)((MV_ULONG)pTxDesc + ETH_TX_DESC_ALIGNED_SIZE); + pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDesc); + } + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxPrevDesc); + } + + pQueueCtrl->pCurrentDescr = pTxDescBase; + pQueueCtrl->pUsedDescr = pTxDescBase; + + pQueueCtrl->pFirstDescr = pTxDescBase; + pQueueCtrl->pLastDescr = pTxDesc; + /* Leave one TX descriptor out of use */ + pQueueCtrl->resource = txDescNum - 1; +} + +void ethResetTxDescRing(void* pPortHndl, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->txQueue[queue]; + ETH_TX_DESC* pTxDesc = (ETH_TX_DESC*)pQueueCtrl->pFirstDescr; + + pQueueCtrl->resource = 0; + if(pQueueCtrl->pFirstDescr != NULL) + { + while(MV_TRUE) + { + pTxDesc->byteCnt = 0x0000; + pTxDesc->L4iChk = 0x0000; + pTxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pTxDesc->bufPtr = 0x0; + pTxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc); + pQueueCtrl->resource++; + if( (void*)pTxDesc == pQueueCtrl->pLastDescr) + break; + pTxDesc = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl); + } + /* Leave one TX descriptor out of use */ + pQueueCtrl->resource--; + pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr; + pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr; + + /* Update TX Command register */ + pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(1 << queue); + /* update HW */ + MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + } + else + { + /* Update TX Command register */ + pPortCtrl->portTxQueueCmdReg &= MV_32BIT_LE_FAST(~(1 << queue)); + /* update HW */ + MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0 ); + } +} + +/******************************************************************************* +* ethAllocDescrMemory - Free memory allocated for RX and TX descriptors. +* +* DESCRIPTION: +* This function allocates memory for RX and TX descriptors. +* - If ETH_DESCR_IN_SRAM defined, allocate memory from SRAM. +* - If ETH_DESCR_IN_SDRAM defined, allocate memory in SDRAM. +* +* INPUT: +* int size - size of memory should be allocated. +* +* RETURN: None +* +*******************************************************************************/ +static MV_U8* ethAllocDescrMemory(ETH_PORT_CTRL* pPortCtrl, int descSize, + MV_ULONG* pPhysAddr, MV_U32 *memHandle) +{ + MV_U8* pVirt; + +#if defined(ETH_DESCR_IN_SRAM) + if(ethDescInSram == MV_TRUE) + pVirt = (char*)mvSramMalloc(descSize, pPhysAddr); + else +#endif /* ETH_DESCR_IN_SRAM */ + { +#ifdef ETH_DESCR_UNCACHED + pVirt = (char*)mvOsIoUncachedMalloc(pPortCtrl->osHandle, descSize, + pPhysAddr,memHandle); +#else + pVirt = (char*)mvOsIoCachedMalloc(pPortCtrl->osHandle, descSize, + pPhysAddr, memHandle); +#endif /* ETH_DESCR_UNCACHED */ + } + memset(pVirt, 0, descSize); + + return pVirt; +} + +/******************************************************************************* +* ethFreeDescrMemory - Free memory allocated for RX and TX descriptors. +* +* DESCRIPTION: +* This function frees memory allocated for RX and TX descriptors. +* - If ETH_DESCR_IN_SRAM defined, free memory using gtSramFree() function. +* - If ETH_DESCR_IN_SDRAM defined, free memory using mvOsFree() function. +* +* INPUT: +* void* pVirtAddr - virtual pointer to memory allocated for RX and TX +* desriptors. +* +* RETURN: None +* +*******************************************************************************/ +void ethFreeDescrMemory(ETH_PORT_CTRL* pPortCtrl, MV_BUF_INFO* pDescBuf) +{ + if( (pDescBuf == NULL) || (pDescBuf->bufVirtPtr == NULL) ) + return; + +#if defined(ETH_DESCR_IN_SRAM) + if( ethDescInSram ) + { + mvSramFree(pDescBuf->bufSize, pDescBuf->bufPhysAddr, pDescBuf->bufVirtPtr); + return; + } +#endif /* ETH_DESCR_IN_SRAM */ + +#ifdef ETH_DESCR_UNCACHED + mvOsIoUncachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr, + pDescBuf->bufVirtPtr,pDescBuf->memHandle); +#else + mvOsIoCachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr, + pDescBuf->bufVirtPtr,pDescBuf->memHandle); +#endif /* ETH_DESCR_UNCACHED */ +} + +/******************************************************************************/ +/* Other Functions */ +/******************************************************************************/ + +void mvEthPortPowerUp(int port) +{ + MV_U32 regVal; + + /* MAC Cause register should be cleared */ + MV_REG_WRITE(ETH_UNIT_INTR_CAUSE_REG(port), 0); + + if (mvBoardIsPortInSgmii(port)) + mvEthPortSgmiiConfig(port); + + /* Cancel Port Reset */ + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)); + regVal &= (~ETH_PORT_RESET_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal); + while( (MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) != 0); +} + +void mvEthPortPowerDown(int port) +{ + MV_U32 regVal; + + /* Port must be DISABLED */ + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port)); + if( (regVal & ETH_PORT_ENABLE_MASK) != 0) + { + mvOsPrintf("ethPort #%d: PowerDown - port must be Disabled (PSC=0x%x)\n", + port, regVal); + return; + } + + /* Port Reset (Read after write the register as a precaution) */ + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal | ETH_PORT_RESET_MASK); + while((MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) == 0); +} + +static void mvEthPortSgmiiConfig(int port) +{ + MV_U32 regVal; + + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)); + + regVal |= (ETH_SGMII_MODE_MASK /*| ETH_INBAND_AUTO_NEG_ENABLE_MASK */); + regVal &= (~ETH_INBAND_AUTO_NEG_BYPASS_MASK); + + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal); +} + + + + + + + + + diff --git a/board/mv_feroceon/mv_hal/eth/gbe/mvEthDebug.c b/board/mv_feroceon/mv_hal/eth/gbe/mvEthDebug.c new file mode 100644 index 0000000..536faf6 --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth/gbe/mvEthDebug.c @@ -0,0 +1,746 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEthDebug.c - Source file for user friendly debug functions +* +* DESCRIPTION: +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#include "mvOs.h" +#include "mvCommon.h" +#include "mvTypes.h" +#include "mv802_3.h" +#include "mvDebug.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "eth-phy/mvEthPhy.h" +#include "eth/mvEth.h" + +/* #define mvOsPrintf printf */ + +void mvEthPortShow(void* pHndl); +void mvEthQueuesShow(void* pHndl, int rxQueue, int txQueue, int mode); +/******************************************************************************/ +/* Debug functions */ +/******************************************************************************/ +void ethRxCoal(int port, int usec) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthRxCoalSet(pHndl, usec); + } +} + +void ethTxCoal(int port, int usec) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthTxCoalSet(pHndl, usec); + } +} + +#if (MV_ETH_VERSION >= 4) +void ethEjpModeSet(int port, int mode) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthEjpModeSet(pHndl, mode); + } +} +#endif /* (MV_ETH_VERSION >= 4) */ + +void ethBpduRxQ(int port, int bpduQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthBpduRxQueue(pHndl, bpduQueue); + } +} + +void ethArpRxQ(int port, int arpQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthArpRxQueue(pHndl, arpQueue); + } +} + +void ethTcpRxQ(int port, int tcpQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthTcpRxQueue(pHndl, tcpQueue); + } +} + +void ethUdpRxQ(int port, int udpQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthUdpRxQueue(pHndl, udpQueue); + } +} + +void ethTxPolicyRegs(int port) +{ + int queue; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)mvEthPortHndlGet(port); + + if(pPortCtrl == NULL) + { + return; + } + mvOsPrintf("Port #%d TX Policy: EJP=%d, TXQs: ", + port, pPortCtrl->portConfig.ejpMode); + for(queue=0; queuetxQueueConfig[queue].descrNum > 0) + mvOsPrintf("%d, ", queue); + } + mvOsPrintf("\n"); + + mvOsPrintf("\n\t TX policy Port #%d configuration registers\n", port); + + mvOsPrintf("ETH_TX_QUEUE_COMMAND_REG : 0x%X = 0x%08x\n", + ETH_TX_QUEUE_COMMAND_REG(port), + MV_REG_READ( ETH_TX_QUEUE_COMMAND_REG(port) ) ); + + mvOsPrintf("ETH_TX_FIXED_PRIO_CFG_REG : 0x%X = 0x%08x\n", + ETH_TX_FIXED_PRIO_CFG_REG(port), + MV_REG_READ( ETH_TX_FIXED_PRIO_CFG_REG(port) ) ); + + mvOsPrintf("ETH_TX_TOKEN_RATE_CFG_REG : 0x%X = 0x%08x\n", + ETH_TX_TOKEN_RATE_CFG_REG(port), + MV_REG_READ( ETH_TX_TOKEN_RATE_CFG_REG(port) ) ); + + mvOsPrintf("ETH_MAX_TRANSMIT_UNIT_REG : 0x%X = 0x%08x\n", + ETH_MAX_TRANSMIT_UNIT_REG(port), + MV_REG_READ( ETH_MAX_TRANSMIT_UNIT_REG(port) ) ); + + mvOsPrintf("ETH_TX_TOKEN_BUCKET_SIZE_REG : 0x%X = 0x%08x\n", + ETH_TX_TOKEN_BUCKET_SIZE_REG(port), + MV_REG_READ( ETH_TX_TOKEN_BUCKET_SIZE_REG(port) ) ); + + mvOsPrintf("ETH_TX_TOKEN_BUCKET_COUNT_REG : 0x%X = 0x%08x\n", + ETH_TX_TOKEN_BUCKET_COUNT_REG(port), + MV_REG_READ( ETH_TX_TOKEN_BUCKET_COUNT_REG(port) ) ); + + for(queue=0; queue> 24) & 0xff), ((macH >> 16) & 0xff), + ((macH >> 8) & 0xff), (macH & 0xff), + ((macL >> 8) & 0xff), (macL & 0xff) ); + + for (i=0; i<4; i++) + { + unicastReg = MV_REG_READ( (ETH_DA_FILTER_UCAST_BASE(port) + i*4)); + for(j=0; j<4; j++) + { + MV_U8 macEntry = (unicastReg >> (8*j)) & 0xFF; + + mvOsPrintf("%X: %8s, Q = %d\n", i*4+j, + (macEntry & BIT0) ? "Accept" : "Reject", (macEntry >> 1) & 0x7); + } + } +} + +void ethMcastAdd(int port, char* macStr, int queue) +{ + void* pHndl; + MV_U8 macAddr[MV_MAC_ADDR_SIZE]; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvMacStrToHex(macStr, macAddr); + mvEthMcastAddrSet(pHndl, macAddr, queue); + } +} + +void ethPortMcast(int port) +{ + int tblIdx, regIdx; + MV_U32 regVal; + + mvOsPrintf("\n\t Port #%d Special (IP) Multicast table: 01:00:5E:00:00:XX\n\n", + port); + + for(tblIdx=0; tblIdx<(256/4); tblIdx++) + { + regVal = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(port) + tblIdx*4)); + for(regIdx=0; regIdx<4; regIdx++) + { + if((regVal & (0x01 << (regIdx*8))) != 0) + { + mvOsPrintf("0x%02X: Accepted, rxQ = %d\n", + tblIdx*4+regIdx, ((regVal >> (regIdx*8+1)) & 0x07)); + } + } + } + mvOsPrintf("\n\t Port #%d Other Multicast table\n\n", port); + for(tblIdx=0; tblIdx<(256/4); tblIdx++) + { + regVal = MV_REG_READ((ETH_DA_FILTER_OTH_MCAST_BASE(port) + tblIdx*4)); + for(regIdx=0; regIdx<4; regIdx++) + { + if((regVal & (0x01 << (regIdx*8))) != 0) + { + mvOsPrintf("Crc8=0x%02X: Accepted, rxQ = %d\n", + tblIdx*4+regIdx, ((regVal >> (regIdx*8+1)) & 0x07)); + } + } + } +} + + +/* Print status of Ethernet port */ +void mvEthPortShow(void* pHndl) +{ + MV_U32 regValue, rxCoal, txCoal; + int speed, queue, port; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pHndl; + + port = pPortCtrl->portNo; + + regValue = MV_REG_READ( ETH_PORT_STATUS_REG(port) ); + + mvOsPrintf("\n\t ethGiga #%d port Status: 0x%04x = 0x%08x\n\n", + port, ETH_PORT_STATUS_REG(port), regValue); + + mvOsPrintf("descInSram=%d, descSwCoher=%d\n", + ethDescInSram, ethDescSwCoher); + + if(regValue & ETH_GMII_SPEED_1000_MASK) + speed = 1000; + else if(regValue & ETH_MII_SPEED_100_MASK) + speed = 100; + else + speed = 10; + + mvEthCoalGet(pPortCtrl, &rxCoal, &txCoal); + + /* Link, Speed, Duplex, FlowControl */ + mvOsPrintf("Link=%s, Speed=%d, Duplex=%s, RxFlowControl=%s", + (regValue & ETH_LINK_UP_MASK) ? "UP" : "DOWN", + speed, + (regValue & ETH_FULL_DUPLEX_MASK) ? "FULL" : "HALF", + (regValue & ETH_ENABLE_RCV_FLOW_CTRL_MASK) ? "ENABLE" : "DISABLE"); + + mvOsPrintf("\n"); + + mvOsPrintf("RxCoal = %d usec, TxCoal = %d usec\n", + rxCoal, txCoal); + + mvOsPrintf("rxDefQ=%d, arpQ=%d, bpduQ=%d, tcpQ=%d, udpQ=%d\n\n", + pPortCtrl->portConfig.rxDefQ, pPortCtrl->portConfig.rxArpQ, + pPortCtrl->portConfig.rxBpduQ, + pPortCtrl->portConfig.rxTcpQ, pPortCtrl->portConfig.rxUdpQ); + + /* Print all RX and TX queues */ + for(queue=0; queuerxQueue[queue].pFirstDescr, + mvEthRxResourceGet(pPortCtrl, queue) ); + } + mvOsPrintf("\n"); + for(queue=0; queuetxQueue[queue].pFirstDescr, + mvEthTxResourceGet(pPortCtrl, queue) ); + } +} + +/* Print RX and TX queue of the Ethernet port */ +void mvEthQueuesShow(void* pHndl, int rxQueue, int txQueue, int mode) +{ + ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL*)pHndl; + ETH_QUEUE_CTRL *pQueueCtrl; + MV_U32 regValue; + ETH_RX_DESC *pRxDescr; + ETH_TX_DESC *pTxDescr; + int i, port = pPortCtrl->portNo; + + if( (rxQueue >=0) && (rxQueue < MV_ETH_RX_Q_NUM) ) + { + pQueueCtrl = &(pPortCtrl->rxQueue[rxQueue]); + mvOsPrintf("Port #%d, RX Queue #%d\n\n", port, rxQueue); + + mvOsPrintf("CURR_RX_DESC_PTR : 0x%X = 0x%08x\n", + ETH_RX_CUR_DESC_PTR_REG(port, rxQueue), + MV_REG_READ( ETH_RX_CUR_DESC_PTR_REG(port, rxQueue))); + + + if(pQueueCtrl->pFirstDescr != NULL) + { + mvOsPrintf("pFirstDescr=0x%lx, pLastDescr=0x%lx, numOfResources=%d\n", + (MV_ULONG)pQueueCtrl->pFirstDescr, (MV_ULONG)pQueueCtrl->pLastDescr, + pQueueCtrl->resource); + mvOsPrintf("pCurrDescr: 0x%lx, pUsedDescr: 0x%lx\n", + (MV_ULONG)pQueueCtrl->pCurrentDescr, + (MV_ULONG)pQueueCtrl->pUsedDescr); + + if(mode == 1) + { + pRxDescr = (ETH_RX_DESC*)pQueueCtrl->pFirstDescr; + i = 0; + do + { + mvOsPrintf("%3d. desc=%08x (%08x), cmd=%08x, data=%4d, buf=%4d, buf=%08x, pkt=%lx, os=%lx\n", + i, (MV_U32)pRxDescr, (MV_U32)ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pRxDescr), + pRxDescr->cmdSts, pRxDescr->byteCnt, (MV_U32)pRxDescr->bufSize, + (unsigned int)pRxDescr->bufPtr, (MV_ULONG)pRxDescr->returnInfo, + ((MV_PKT_INFO*)pRxDescr->returnInfo)->osInfo); + + ETH_DESCR_INV(pPortCtrl, pRxDescr); + pRxDescr = RX_NEXT_DESC_PTR(pRxDescr, pQueueCtrl); + i++; + } while (pRxDescr != pQueueCtrl->pFirstDescr); + } + } + else + mvOsPrintf("RX Queue #%d is NOT CREATED\n", rxQueue); + } + + if( (txQueue >=0) && (txQueue < MV_ETH_TX_Q_NUM) ) + { + pQueueCtrl = &(pPortCtrl->txQueue[txQueue]); + mvOsPrintf("Port #%d, TX Queue #%d\n\n", port, txQueue); + + regValue = MV_REG_READ( ETH_TX_CUR_DESC_PTR_REG(port, txQueue)); + mvOsPrintf("CURR_TX_DESC_PTR : 0x%X = 0x%08x\n", + ETH_TX_CUR_DESC_PTR_REG(port, txQueue), regValue); + + if(pQueueCtrl->pFirstDescr != NULL) + { + mvOsPrintf("pFirstDescr=0x%lx, pLastDescr=0x%lx, numOfResources=%d\n", + (MV_ULONG)pQueueCtrl->pFirstDescr, + (MV_ULONG)pQueueCtrl->pLastDescr, + pQueueCtrl->resource); + mvOsPrintf("pCurrDescr: 0x%lx, pUsedDescr: 0x%lx\n", + (MV_ULONG)pQueueCtrl->pCurrentDescr, + (MV_ULONG)pQueueCtrl->pUsedDescr); + + if(mode == 1) + { + pTxDescr = (ETH_TX_DESC*)pQueueCtrl->pFirstDescr; + i = 0; + do + { + mvOsPrintf("%3d. desc=%08x (%08x), cmd=%08x, data=%4d, buf=%08x, pkt=%lx, os=%lx\n", + i, (MV_U32)pTxDescr, (MV_U32)ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pTxDescr), + pTxDescr->cmdSts, pTxDescr->byteCnt, + (MV_U32)pTxDescr->bufPtr, (MV_ULONG)pTxDescr->returnInfo, + pTxDescr->returnInfo ? (((MV_PKT_INFO*)pTxDescr->returnInfo)->osInfo) : 0x0); + + ETH_DESCR_INV(pPortCtrl, pTxDescr); + pTxDescr = TX_NEXT_DESC_PTR(pTxDescr, pQueueCtrl); + i++; + } while (pTxDescr != pQueueCtrl->pFirstDescr); + } + } + else + mvOsPrintf("TX Queue #%d is NOT CREATED\n", txQueue); + } +} diff --git a/board/mv_feroceon/mv_hal/eth/gbe/mvEthGbe.h b/board/mv_feroceon/mv_hal/eth/gbe/mvEthGbe.h new file mode 100644 index 0000000..a7f7cdf --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth/gbe/mvEthGbe.h @@ -0,0 +1,743 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEth.h - Header File for : Marvell Gigabit Ethernet Controller +* +* DESCRIPTION: +* This header file contains macros typedefs and function declaration specific to +* the Marvell Gigabit Ethernet Controller. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __mvEthGbe_h__ +#define __mvEthGbe_h__ + +extern MV_BOOL ethDescInSram; +extern MV_BOOL ethDescSwCoher; +extern ETH_PORT_CTRL* ethPortCtrl[]; + +static INLINE MV_ULONG ethDescVirtToPhy(ETH_QUEUE_CTRL* pQueueCtrl, MV_U8* pDesc) +{ +#if defined (ETH_DESCR_IN_SRAM) + if( ethDescInSram ) + return mvSramVirtToPhy(pDesc); + else +#endif /* ETH_DESCR_IN_SRAM */ + return (pQueueCtrl->descBuf.bufPhysAddr + (pDesc - pQueueCtrl->descBuf.bufVirtPtr)); +} +/* Return port handler */ +#define mvEthPortHndlGet(port) ethPortCtrl[port] + +/* Used as WA for HW/SW race on TX */ +static INLINE int mvEthPortTxEnable(void* pPortHndl, int queue, int max_deep) +{ + int deep = 0; + MV_U32 txCurrReg, txEnReg; + ETH_TX_DESC* pTxLastDesc; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + txEnReg = MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)); + if( (txEnReg & MV_32BIT_LE_FAST(ETH_TXQ_ENABLE_MASK)) == 0) + { + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg; + return 0; + } + + pQueueCtrl = &pPortCtrl->txQueue[queue]; + pTxLastDesc = pQueueCtrl->pCurrentDescr; + txCurrReg = MV_REG_READ(ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue)); + if(ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pTxLastDesc) == txCurrReg) + { + /* All descriptors are processed, no chance for race */ + return 0; + } + + /* Check distance betwee HW and SW location: */ + /* If distance between HW and SW pointers is less than max_deep descriptors */ + /* Race condition is possible, so wait end of TX and restart TXQ */ + while(deep < max_deep) + { + pTxLastDesc = TX_PREV_DESC_PTR(pTxLastDesc, pQueueCtrl); + if(ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pTxLastDesc) == txCurrReg) + { + int count = 0; + + while( (txEnReg & MV_32BIT_LE_FAST(ETH_TXQ_ENABLE_MASK)) != 0) + { + count++; + if(count > 10000) + { + mvOsPrintf("mvEthPortTxEnable: timeout - TXQ_CMD=0x%08x\n", + MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) ); + break; + } + txEnReg = MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)); + } + + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg; + return count; + } + deep++; + } + /* Distance between HW and SW pointers is more than max_deep descriptors, */ + /* So NO race condition - do nothing */ + return -1; +} + + +/* defines */ +#define ETH_CSUM_MIN_BYTE_COUNT 72 + +/* Tailgate and Kirwood have only 2K TX FIFO */ +#if (MV_ETH_VERSION == 2) || (MV_ETH_VERSION == 4) +#define ETH_CSUM_MAX_BYTE_COUNT 1600 +#else +#define ETH_CSUM_MAX_BYTE_COUNT 9*1024 +#endif /* MV_ETH_VERSION */ + +#define ETH_MV_HEADER_SIZE 2 +#define ETH_MV_TX_EN + +/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */ +#define MIN_TX_BUFF_LOAD 8 +#define TX_BUF_OFFSET_IN_DESC (ETH_TX_DESC_ALIGNED_SIZE - MIN_TX_BUFF_LOAD) + +/* Default port configuration value */ +#define PORT_CONFIG_VALUE \ + ETH_DEF_RX_QUEUE_MASK(0) | \ + ETH_DEF_RX_ARP_QUEUE_MASK(0) | \ + ETH_DEF_RX_TCP_QUEUE_MASK(0) | \ + ETH_DEF_RX_UDP_QUEUE_MASK(0) | \ + ETH_DEF_RX_BPDU_QUEUE_MASK(0) | \ + ETH_RX_CHECKSUM_WITH_PSEUDO_HDR + +/* Default port extend configuration value */ +#define PORT_CONFIG_EXTEND_VALUE 0 + +#define PORT_SERIAL_CONTROL_VALUE \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE | \ + ETH_SET_FULL_DUPLEX_MASK + +#define PORT_SERIAL_CONTROL_100MB_FORCE_VALUE \ + ETH_FORCE_LINK_PASS_MASK | \ + ETH_DISABLE_DUPLEX_AUTO_NEG_MASK | \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_DISABLE_SPEED_AUTO_NEG_MASK | \ + ETH_SET_FULL_DUPLEX_MASK | \ + ETH_SET_MII_SPEED_100_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE + + +#define PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE \ + ETH_FORCE_LINK_PASS_MASK | \ + ETH_DISABLE_DUPLEX_AUTO_NEG_MASK | \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_DISABLE_SPEED_AUTO_NEG_MASK | \ + ETH_SET_FULL_DUPLEX_MASK | \ + ETH_SET_GMII_SPEED_1000_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE + +#define PORT_SERIAL_CONTROL_SGMII_IBAN_VALUE \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_IN_BAND_AN_EN_MASK | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE + +/* Function headers: */ +MV_VOID mvEthSetSpecialMcastTable(int portNo, int queue); +MV_STATUS mvEthArpRxQueue(void* pPortHandle, int arpQueue); +MV_STATUS mvEthUdpRxQueue(void* pPortHandle, int udpQueue); +MV_STATUS mvEthTcpRxQueue(void* pPortHandle, int tcpQueue); +MV_STATUS mvEthMacAddrGet(int portNo, unsigned char *pAddr); +MV_VOID mvEthSetOtherMcastTable(int portNo, int queue); +MV_STATUS mvEthHeaderModeSet(void* pPortHandle, MV_ETH_HEADER_MODE headerMode); +/* Interrupt Coalesting functions */ +MV_U32 mvEthRxCoalSet(void* pPortHndl, MV_U32 uSec); +MV_U32 mvEthTxCoalSet(void* pPortHndl, MV_U32 uSec); +MV_STATUS mvEthCoalGet(void* pPortHndl, MV_U32* pRxCoal, MV_U32* pTxCoal); + +/******************************************************************************/ +/* Data Flow functions */ +/******************************************************************************/ +static INLINE void mvEthPortTxRestart(void* pPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg; +} + +/* Get number of Free resources in specific TX queue */ +static INLINE int mvEthTxResourceGet(void* pPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + return (pPortCtrl->txQueue[txQueue].resource); +} + +/* Get number of Free resources in specific RX queue */ +static INLINE int mvEthRxResourceGet(void* pPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + return (pPortCtrl->rxQueue[rxQueue].resource); +} + +static INLINE int mvEthTxQueueIsFull(void* pPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + if(pPortCtrl->txQueue[txQueue].resource == 0) + return MV_TRUE; + + return MV_FALSE; +} + +/* Get number of Free resources in specific RX queue */ +static INLINE int mvEthRxQueueIsFull(void* pPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->rxQueue[rxQueue]; + + if( (pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && + (pQueueCtrl->resource != 0) ) + return MV_TRUE; + + return MV_FALSE; +} + +static INLINE int mvEthTxQueueIsEmpty(void* pPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + if( (pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && + (pQueueCtrl->resource != 0) ) + { + return MV_TRUE; + } + return MV_FALSE; +} + +/* Get number of Free resources in specific RX queue */ +static INLINE int mvEthRxQueueIsEmpty(void* pPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + if(pPortCtrl->rxQueue[rxQueue].resource == 0) + return MV_TRUE; + + return MV_FALSE; +} + +/******************************************************************************* +* mvEthPortTx - Send an Ethernet packet +* +* DESCRIPTION: +* This routine send a given packet described by pPktInfo parameter. +* Single buffer only. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of Tx queue. +* MV_PKT_INFO *pPktInfo - User packet to send. +* +* RETURN: +* MV_NO_RESOURCE - No enough resources to send this packet. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - Packet send successfully. +* +*******************************************************************************/ +static INLINE MV_STATUS mvEthPortTx(void* pEthPortHndl, int txQueue, MV_PKT_INFO* pPktInfo) +{ + ETH_TX_DESC* pTxCurrDesc; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + int portNo; + MV_BUF_INFO* pBufInfo = pPktInfo->pFrags; + +#ifdef ETH_DEBUG + if(pPortCtrl->portState != MV_ACTIVE) + return MV_BAD_STATE; +#endif /* ETH_DEBUG */ + + portNo = pPortCtrl->portNo; + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + /* Get the Tx Desc ring indexes */ + pTxCurrDesc = pQueueCtrl->pCurrentDescr; + + /* Check if there is enough resources to send the packet */ + if(pQueueCtrl->resource == 0) + return MV_NO_RESOURCE; + + pTxCurrDesc->byteCnt = pBufInfo->dataSize; + + /* Flash Buffer */ + if(pPktInfo->pktSize != 0) + { + pTxCurrDesc->bufPtr = + ETH_PACKET_CACHE_FLUSH(pBufInfo->bufVirtPtr, pPktInfo->pktSize); + pPktInfo->pktSize = 0; + } + else + pTxCurrDesc->bufPtr = pBufInfo->bufPhysAddr; + + pTxCurrDesc->returnInfo = (MV_ULONG)pPktInfo; + + /* There is only one buffer in the packet */ + /* The OSG might set some bits for checksum offload, so add them to first descriptor */ + pTxCurrDesc->cmdSts = pPktInfo->status | + ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_GENERATE_CRC_MASK | + ETH_TX_ENABLE_INTERRUPT_MASK | + ETH_TX_ZERO_PADDING_MASK | + ETH_TX_FIRST_DESC_MASK | + ETH_TX_LAST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + + pQueueCtrl->resource--; + pQueueCtrl->pCurrentDescr = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl); + + /* Apply send command */ + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(portNo)) = pPortCtrl->portTxQueueCmdReg; + + return MV_OK; +} + + +/******************************************************************************* +* mvEthPortSgTx - Send an Ethernet packet +* +* DESCRIPTION: +* This routine send a given packet described by pBufInfo parameter. It +* supports transmitting of a packet spaned over multiple buffers. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of Tx queue. +* MV_PKT_INFO *pPktInfo - User packet to send. +* +* RETURN: +* MV_NO_RESOURCE - No enough resources to send this packet. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - Packet send successfully. +* +*******************************************************************************/ +static INLINE MV_STATUS mvEthPortSgTx(void* pEthPortHndl, int txQueue, MV_PKT_INFO* pPktInfo) +{ + ETH_TX_DESC* pTxFirstDesc; + ETH_TX_DESC* pTxCurrDesc; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + int portNo, bufCount; + MV_BUF_INFO* pBufInfo = pPktInfo->pFrags; + MV_U8* pTxBuf; + +#ifdef ETH_DEBUG + if(pPortCtrl->portState != MV_ACTIVE) + return MV_BAD_STATE; +#endif /* ETH_DEBUG */ + + portNo = pPortCtrl->portNo; + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + /* Get the Tx Desc ring indexes */ + pTxCurrDesc = pQueueCtrl->pCurrentDescr; + + /* Check if there is enough resources to send the packet */ + if(pQueueCtrl->resource < pPktInfo->numFrags) + return MV_NO_RESOURCE; + + /* Remember first desc */ + pTxFirstDesc = pTxCurrDesc; + + bufCount = 0; + while(MV_TRUE) + { + if(pBufInfo[bufCount].dataSize <= MIN_TX_BUFF_LOAD) + { + /* Buffers with a payload smaller than MIN_TX_BUFF_LOAD (8 bytes) must be aligned */ + /* to 64-bit boundary. Two options here: */ + /* 1) Usually, copy the payload to the reserved 8 bytes inside descriptor. */ + /* 2) In the Half duplex workaround, the reserved 8 bytes inside descriptor are used */ + /* as a pointer to the aligned buffer, copy the small payload to this buffer. */ + pTxBuf = ((MV_U8*)pTxCurrDesc)+TX_BUF_OFFSET_IN_DESC; + mvOsBCopy(pBufInfo[bufCount].bufVirtPtr, pTxBuf, pBufInfo[bufCount].dataSize); + pTxCurrDesc->bufPtr = ethDescVirtToPhy(pQueueCtrl, pTxBuf); + } + else + { + /* Flash Buffer */ + pTxCurrDesc->bufPtr = + ETH_PACKET_CACHE_FLUSH(pBufInfo[bufCount].bufVirtPtr, pBufInfo[bufCount].dataSize); + } + + pTxCurrDesc->byteCnt = pBufInfo[bufCount].dataSize; + bufCount++; + + if(bufCount >= pPktInfo->numFrags) + break; + + if(bufCount > 1) + { + /* There is middle buffer of the packet Not First and Not Last */ + pTxCurrDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA; + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + } + /* Go to next descriptor and next buffer */ + pTxCurrDesc = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl); + } + /* Set last desc with DMA ownership and interrupt enable. */ + pTxCurrDesc->returnInfo = (MV_ULONG)pPktInfo; + if(bufCount == 1) + { + /* There is only one buffer in the packet */ + /* The OSG might set some bits for checksum offload, so add them to first descriptor */ + pTxCurrDesc->cmdSts = pPktInfo->status | + ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_GENERATE_CRC_MASK | + ETH_TX_ENABLE_INTERRUPT_MASK | + ETH_TX_ZERO_PADDING_MASK | + ETH_TX_FIRST_DESC_MASK | + ETH_TX_LAST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + } + else + { + /* Last but not First */ + pTxCurrDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_ENABLE_INTERRUPT_MASK | + ETH_TX_ZERO_PADDING_MASK | + ETH_TX_LAST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + + /* Update First when more than one buffer in the packet */ + /* The OSG might set some bits for checksum offload, so add them to first descriptor */ + pTxFirstDesc->cmdSts = pPktInfo->status | + ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_GENERATE_CRC_MASK | + ETH_TX_FIRST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxFirstDesc); + } + /* Update txQueue state */ + pQueueCtrl->resource -= bufCount; + pQueueCtrl->pCurrentDescr = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl); + + /* Apply send command */ + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(portNo)) = pPortCtrl->portTxQueueCmdReg; + + return MV_OK; +} + +/******************************************************************************* +* mvEthPortTxDone - Free all used Tx descriptors and mBlks. +* +* DESCRIPTION: +* This routine returns the transmitted packet information to the caller. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of Tx queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to packet was sent. +* +* RETURN: +* MV_NOT_FOUND - No transmitted packets to return. Transmit in progress. +* MV_EMPTY - No transmitted packets to return. TX Queue is empty. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - There is transmitted packet in the queue, +* 'pPktInfo' filled with relevant information. +* +*******************************************************************************/ +static INLINE MV_PKT_INFO* mvEthPortTxDone(void* pEthPortHndl, int txQueue) +{ + ETH_TX_DESC* pTxCurrDesc; + ETH_TX_DESC* pTxUsedDesc; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + MV_PKT_INFO* pPktInfo; + MV_U32 commandStatus; + + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + pTxUsedDesc = pQueueCtrl->pUsedDescr; + pTxCurrDesc = pQueueCtrl->pCurrentDescr; + + while(MV_TRUE) + { + /* No more used descriptors */ + commandStatus = pTxUsedDesc->cmdSts; + if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) + { + ETH_DESCR_INV(pPortCtrl, pTxUsedDesc); + return NULL; + } + if( (pTxUsedDesc == pTxCurrDesc) && + (pQueueCtrl->resource != 0) ) + { + return NULL; + } + pQueueCtrl->resource++; + pQueueCtrl->pUsedDescr = TX_NEXT_DESC_PTR(pTxUsedDesc, pQueueCtrl); + if(commandStatus & (ETH_TX_LAST_DESC_MASK)) + { + pPktInfo = (MV_PKT_INFO*)pTxUsedDesc->returnInfo; + pPktInfo->status = commandStatus; + return pPktInfo; + } + pTxUsedDesc = pQueueCtrl->pUsedDescr; + } +} + +/******************************************************************************* +* mvEthPortRx - Get new received packets from Rx queue. +* +* DESCRIPTION: +* This routine returns the received data to the caller. There is no +* data copying during routine operation. All information is returned +* using pointer to packet information struct passed from the caller. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int rxQueue - Number of Rx queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to received packet. +* +* RETURN: +* MV_NO_RESOURCE - No free resources in RX queue. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - New packet received and 'pBufInfo' structure filled +* with relevant information. +* +*******************************************************************************/ +static INLINE MV_PKT_INFO* mvEthPortRx(void* pEthPortHndl, int rxQueue) +{ + ETH_RX_DESC *pRxCurrDesc; + MV_U32 commandStatus; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + MV_PKT_INFO* pPktInfo; + + pQueueCtrl = &(pPortCtrl->rxQueue[rxQueue]); + + /* Check resources */ + if(pQueueCtrl->resource == 0) + { + mvOsPrintf("ethPortRx: no more resources\n"); + return NULL; + } + while(MV_TRUE) + { + /* Get the Rx Desc ring 'curr and 'used' indexes */ + pRxCurrDesc = pQueueCtrl->pCurrentDescr; + + commandStatus = pRxCurrDesc->cmdSts; + if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) + { + /* Nothing to receive... */ + ETH_DESCR_INV(pPortCtrl, pRxCurrDesc); + return NULL; + } + + /* Valid RX only if FIRST and LAST bits are set */ + if( (commandStatus & (ETH_RX_LAST_DESC_MASK | ETH_RX_FIRST_DESC_MASK)) == + (ETH_RX_LAST_DESC_MASK | ETH_RX_FIRST_DESC_MASK) ) + { + pPktInfo = (MV_PKT_INFO*)pRxCurrDesc->returnInfo; + pPktInfo->pFrags->dataSize = pRxCurrDesc->byteCnt - 4; + pPktInfo->status = commandStatus; + pPktInfo->fragIP = pRxCurrDesc->bufSize & ETH_RX_IP_FRAGMENTED_FRAME_MASK; + + pQueueCtrl->resource--; + /* Update 'curr' in data structure */ + pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxCurrDesc, pQueueCtrl); + +#ifdef INCLUDE_SYNC_BARR + mvCpuIfSyncBarr(DRAM_TARGET); +#endif + return pPktInfo; + } + else + { + ETH_RX_DESC* pRxUsedDesc = pQueueCtrl->pUsedDescr; + +#ifdef ETH_DEBUG + mvOsPrintf("ethDrv: Unexpected Jumbo frame: " + "status=0x%08x, byteCnt=%d, pData=0x%x\n", + commandStatus, pRxCurrDesc->byteCnt, pRxCurrDesc->bufPtr); +#endif /* ETH_DEBUG */ + + /* move buffer from pCurrentDescr position to pUsedDescr position */ + pRxUsedDesc->bufPtr = pRxCurrDesc->bufPtr; + pRxUsedDesc->returnInfo = pRxCurrDesc->returnInfo; + pRxUsedDesc->bufSize = pRxCurrDesc->bufSize & ETH_RX_BUFFER_MASK; + + /* Return the descriptor to DMA ownership */ + pRxUsedDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA | + ETH_RX_ENABLE_INTERRUPT_MASK; + + /* Flush descriptor and CPU pipe */ + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxUsedDesc); + + /* Move the used descriptor pointer to the next descriptor */ + pQueueCtrl->pUsedDescr = RX_NEXT_DESC_PTR(pRxUsedDesc, pQueueCtrl); + pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxCurrDesc, pQueueCtrl); + } + } +} + +/******************************************************************************* +* mvEthPortRxDone - Returns a Rx buffer back to the Rx ring. +* +* DESCRIPTION: +* This routine returns a Rx buffer back to the Rx ring. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int rxQueue - Number of Rx queue. +* MV_PKT_INFO *pPktInfo - Pointer to received packet. +* +* RETURN: +* MV_ERROR - Unexpected Fatal error. +* MV_OUT_OF_RANGE - RX queue is already FULL, so this buffer can't be +* returned to this queue. +* MV_FULL - Buffer returned successfully and RX queue became full. +* More buffers should not be returned at the time. +* MV_OK - Buffer returned successfully and there are more free +* places in the queue. +* +*******************************************************************************/ +static INLINE MV_STATUS mvEthPortRxDone(void* pEthPortHndl, int rxQueue, MV_PKT_INFO *pPktInfo) +{ + ETH_RX_DESC* pRxUsedDesc; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + + pQueueCtrl = &pPortCtrl->rxQueue[rxQueue]; + + /* Get 'used' Rx descriptor */ + pRxUsedDesc = pQueueCtrl->pUsedDescr; + + /* Check that ring is not FULL */ + if( (pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && + (pQueueCtrl->resource != 0) ) + { + mvOsPrintf("%s %d: out of range Error resource=%d, curr=%p, used=%p\n", + __FUNCTION__, pPortCtrl->portNo, pQueueCtrl->resource, + pQueueCtrl->pCurrentDescr, pQueueCtrl->pUsedDescr); + return MV_OUT_OF_RANGE; + } + + pRxUsedDesc->bufPtr = pPktInfo->pFrags->bufPhysAddr; + pRxUsedDesc->returnInfo = (MV_ULONG)pPktInfo; + pRxUsedDesc->bufSize = pPktInfo->pFrags->bufSize & ETH_RX_BUFFER_MASK; + + /* Invalidate data buffer accordingly with pktSize */ + if(pPktInfo->pktSize != 0) + { + ETH_PACKET_CACHE_INVALIDATE(pPktInfo->pFrags->bufVirtPtr, pPktInfo->pktSize); + pPktInfo->pktSize = 0; + } + + /* Return the descriptor to DMA ownership */ + pRxUsedDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT_MASK; + + /* Flush descriptor and CPU pipe */ + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxUsedDesc); + + pQueueCtrl->resource++; + + /* Move the used descriptor pointer to the next descriptor */ + pQueueCtrl->pUsedDescr = RX_NEXT_DESC_PTR(pRxUsedDesc, pQueueCtrl); + + /* If ring became Full return MV_FULL */ + if(pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) + return MV_FULL; + + return MV_OK; +} + + +#endif /* __mvEthGbe_h__ */ + + diff --git a/board/mv_feroceon/mv_hal/eth/gbe/mvEthRegs.h b/board/mv_feroceon/mv_hal/eth/gbe/mvEthRegs.h new file mode 100644 index 0000000..8f20339 --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth/gbe/mvEthRegs.h @@ -0,0 +1,676 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvEthRegsh +#define __INCmvEthRegsh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "ctrlEnv/mvCtrlEnvSpec.h" + +/****************************************/ +/* Ethernet Unit Registers */ +/****************************************/ +#define ETH_REG_BASE MV_ETH_REG_BASE + +#define ETH_PHY_ADDR_REG(port) (ETH_REG_BASE(port) + 0x000) +#define ETH_SMI_REG(port) (ETH_REG_BASE(port) + 0x004) +#define ETH_UNIT_DEF_ADDR_REG(port) (ETH_REG_BASE(port) + 0x008) +#define ETH_UNIT_DEF_ID_REG(port) (ETH_REG_BASE(port) + 0x00c) +#define ETH_UNIT_RESERVED(port) (ETH_REG_BASE(port) + 0x014) +#define ETH_UNIT_INTR_CAUSE_REG(port) (ETH_REG_BASE(port) + 0x080) +#define ETH_UNIT_INTR_MASK_REG(port) (ETH_REG_BASE(port) + 0x084) + + +#define ETH_UNIT_ERROR_ADDR_REG(port) (ETH_REG_BASE(port) + 0x094) +#define ETH_UNIT_INT_ADDR_ERROR_REG(port) (ETH_REG_BASE(port) + 0x098) +#define ETH_UNIT_CONTROL_REG(port) (ETH_REG_BASE(port) + 0x0B0) + +#define ETH_PORT_CONFIG_REG(port) (ETH_REG_BASE(port) + 0x400) +#define ETH_PORT_CONFIG_EXTEND_REG(port) (ETH_REG_BASE(port) + 0x404) +#define ETH_MII_SERIAL_PARAM_REG(port) (ETH_REG_BASE(port) + 0x408) +#define ETH_GMII_SERIAL_PARAM_REG(port) (ETH_REG_BASE(port) + 0x40c) +#define ETH_VLAN_ETHER_TYPE_REG(port) (ETH_REG_BASE(port) + 0x410) +#define ETH_MAC_ADDR_LOW_REG(port) (ETH_REG_BASE(port) + 0x414) +#define ETH_MAC_ADDR_HIGH_REG(port) (ETH_REG_BASE(port) + 0x418) +#define ETH_SDMA_CONFIG_REG(port) (ETH_REG_BASE(port) + 0x41c) +#define ETH_DIFF_SERV_PRIO_REG(port, code) (ETH_REG_BASE(port) + 0x420 + ((code)<<2)) +#define ETH_PORT_SERIAL_CTRL_REG(port) (ETH_REG_BASE(port) + 0x43c) +#define ETH_VLAN_TAG_TO_PRIO_REG(port) (ETH_REG_BASE(port) + 0x440) +#define ETH_PORT_STATUS_REG(port) (ETH_REG_BASE(port) + 0x444) + +#define ETH_RX_QUEUE_COMMAND_REG(port) (ETH_REG_BASE(port) + 0x680) +#define ETH_TX_QUEUE_COMMAND_REG(port) (ETH_REG_BASE(port) + 0x448) + +#define ETH_PORT_SERIAL_CTRL_1_REG(port) (ETH_REG_BASE(port) + 0x44c) +#define ETH_PORT_STATUS_1_REG(port) (ETH_REG_BASE(port) + 0x450) +#define ETH_PORT_MARVELL_HEADER_REG(port) (ETH_REG_BASE(port) + 0x454) +#define ETH_PORT_FIFO_PARAMS_REG(port) (ETH_REG_BASE(port) + 0x458) +#define ETH_MAX_TOKEN_BUCKET_SIZE_REG(port) (ETH_REG_BASE(port) + 0x45c) +#define ETH_INTR_CAUSE_REG(port) (ETH_REG_BASE(port) + 0x460) +#define ETH_INTR_CAUSE_EXT_REG(port) (ETH_REG_BASE(port) + 0x464) +#define ETH_INTR_MASK_REG(port) (ETH_REG_BASE(port) + 0x468) +#define ETH_INTR_MASK_EXT_REG(port) (ETH_REG_BASE(port) + 0x46c) +#define ETH_TX_FIFO_URGENT_THRESH_REG(port) (ETH_REG_BASE(port) + 0x474) +#define ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (ETH_REG_BASE(port) + 0x47c) +#define ETH_RX_DISCARD_PKTS_CNTR_REG(port) (ETH_REG_BASE(port) + 0x484) +#define ETH_RX_OVERRUN_PKTS_CNTR_REG(port) (ETH_REG_BASE(port) + 0x488) +#define ETH_INTERNAL_ADDR_ERROR_REG(port) (ETH_REG_BASE(port) + 0x494) +#define ETH_TX_FIXED_PRIO_CFG_REG(port) (ETH_REG_BASE(port) + 0x4dc) +#define ETH_TX_TOKEN_RATE_CFG_REG(port) (ETH_REG_BASE(port) + 0x4e0) +#define ETH_TX_QUEUE_COMMAND1_REG(port) (ETH_REG_BASE(port) + 0x4e4) +#define ETH_MAX_TRANSMIT_UNIT_REG(port) (ETH_REG_BASE(port) + 0x4e8) +#define ETH_TX_TOKEN_BUCKET_SIZE_REG(port) (ETH_REG_BASE(port) + 0x4ec) +#define ETH_TX_TOKEN_BUCKET_COUNT_REG(port) (ETH_REG_BASE(port) + 0x780) +#define ETH_RX_DESCR_STAT_CMD_REG(port, q) (ETH_REG_BASE(port) + 0x600 + ((q)<<4)) +#define ETH_RX_BYTE_COUNT_REG(port, q) (ETH_REG_BASE(port) + 0x604 + ((q)<<4)) +#define ETH_RX_BUF_PTR_REG(port, q) (ETH_REG_BASE(port) + 0x608 + ((q)<<4)) +#define ETH_RX_CUR_DESC_PTR_REG(port, q) (ETH_REG_BASE(port) + 0x60c + ((q)<<4)) +#define ETH_TX_CUR_DESC_PTR_REG(port, q) (ETH_REG_BASE(port) + 0x6c0 + ((q)<<2)) + +#define ETH_TXQ_TOKEN_COUNT_REG(port, q) (ETH_REG_BASE(port) + 0x700 + ((q)<<4)) +#define ETH_TXQ_TOKEN_CFG_REG(port, q) (ETH_REG_BASE(port) + 0x704 + ((q)<<4)) +#define ETH_TXQ_ARBITER_CFG_REG(port, q) (ETH_REG_BASE(port) + 0x708 + ((q)<<4)) + +#if (MV_ETH_VERSION >= 4) +#define ETH_TXQ_CMD_1_REG(port) (ETH_REG_BASE(port) + 0x4E4) +#define ETH_EJP_TX_HI_IPG_REG(port) (ETH_REG_BASE(port) + 0x7A8) +#define ETH_EJP_TX_LO_IPG_REG(port) (ETH_REG_BASE(port) + 0x7B8) +#define ETH_EJP_HI_TKN_LO_PKT_REG(port) (ETH_REG_BASE(port) + 0x7C0) +#define ETH_EJP_HI_TKN_ASYNC_PKT_REG(port) (ETH_REG_BASE(port) + 0x7C4) +#define ETH_EJP_LO_TKN_ASYNC_PKT_REG(port) (ETH_REG_BASE(port) + 0x7C8) +#define ETH_EJP_TX_SPEED_REG(port) (ETH_REG_BASE(port) + 0x7D0) +#endif /* MV_ETH_VERSION >= 4 */ + +#define ETH_MIB_COUNTERS_BASE(port) (ETH_REG_BASE(port) + 0x1000) +#define ETH_DA_FILTER_SPEC_MCAST_BASE(port) (ETH_REG_BASE(port) + 0x1400) +#define ETH_DA_FILTER_OTH_MCAST_BASE(port) (ETH_REG_BASE(port) + 0x1500) +#define ETH_DA_FILTER_UCAST_BASE(port) (ETH_REG_BASE(port) + 0x1600) + +/* Phy address register definitions */ +#define ETH_PHY_ADDR_OFFS 0 +#define ETH_PHY_ADDR_MASK (0x1f <= 4) +#define ETH_TX_EJP_RESET_BIT 0 +#define ETH_TX_EJP_RESET_MASK (1 << ETH_TX_EJP_RESET_BIT) + +#define ETH_TX_EJP_ENABLE_BIT 2 +#define ETH_TX_EJP_ENABLE_MASK (1 << ETH_TX_EJP_ENABLE_BIT) + +#define ETH_TX_LEGACY_WRR_BIT 3 +#define ETH_TX_LEGACY_WRR_MASK (1 << ETH_TX_LEGACY_WRR_BIT) +#endif /* (MV_ETH_VERSION >= 4) */ + +/***** BITs of Ethernet Port Status reg (PSR) *****/ +#define ETH_LINK_UP_BIT 1 +#define ETH_LINK_UP_MASK (1<= 4) +MV_STATUS mvEthEjpModeSet(void* pPortHandle, int mode); +#endif /* (MV_ETH_VERSION >= 4) */ + +void mvEthStatusGet(void* pPortHandle, MV_ETH_PORT_STATUS* pStatus); + +/* Marvell Header control */ +MV_STATUS mvEthHeaderModeSet(void* pPortHandle, MV_ETH_HEADER_MODE headerMode); + +/* PHY routines */ +void mvEthPhyAddrSet(void* pPortHandle, int phyAddr); +int mvEthPhyAddrGet(void* pPortHandle); + +/* Power management routines */ +void mvEthPortPowerDown(int port); +void mvEthPortPowerUp(int port); + +/******************** ETH PRIVATE ************************/ + +/*#define UNCACHED_TX_BUFFERS*/ +/*#define UNCACHED_RX_BUFFERS*/ + + +/* Port attributes */ +/* Size of a Tx/Rx descriptor used in chain list data structure */ +#define ETH_RX_DESC_ALIGNED_SIZE 32 +#define ETH_TX_DESC_ALIGNED_SIZE 32 + +#define TX_DISABLE_TIMEOUT_MSEC 1000 +#define RX_DISABLE_TIMEOUT_MSEC 1000 +#define TX_FIFO_EMPTY_TIMEOUT_MSEC 10000 +#define PORT_DISABLE_WAIT_TCLOCKS 5000 + +/* Macros that save access to desc in order to find next desc pointer */ +#define RX_NEXT_DESC_PTR(pRxDescr, pQueueCtrl) \ + ((pRxDescr) == (pQueueCtrl)->pLastDescr) ? \ + (ETH_RX_DESC*)((pQueueCtrl)->pFirstDescr) : \ + (ETH_RX_DESC*)(((MV_ULONG)(pRxDescr)) + ETH_RX_DESC_ALIGNED_SIZE) + +#define TX_NEXT_DESC_PTR(pTxDescr, pQueueCtrl) \ + ((pTxDescr) == (pQueueCtrl)->pLastDescr) ? \ + (ETH_TX_DESC*)((pQueueCtrl)->pFirstDescr) : \ + (ETH_TX_DESC*)(((MV_ULONG)(pTxDescr)) + ETH_TX_DESC_ALIGNED_SIZE) + +#define RX_PREV_DESC_PTR(pRxDescr, pQueueCtrl) \ + ((pRxDescr) == (pQueueCtrl)->pFirstDescr) ? \ + (ETH_RX_DESC*)((pQueueCtrl)->pLastDescr) : \ + (ETH_RX_DESC*)(((MV_ULONG)(pRxDescr)) - ETH_RX_DESC_ALIGNED_SIZE) + +#define TX_PREV_DESC_PTR(pTxDescr, pQueueCtrl) \ + ((pTxDescr) == (pQueueCtrl)->pFirstDescr) ? \ + (ETH_TX_DESC*)((pQueueCtrl)->pLastDescr) : \ + (ETH_TX_DESC*)(((MV_ULONG)(pTxDescr)) - ETH_TX_DESC_ALIGNED_SIZE) + + +/* Queue specific information */ +typedef struct +{ + void* pFirstDescr; + void* pLastDescr; + void* pCurrentDescr; + void* pUsedDescr; + int resource; + MV_BUF_INFO descBuf; +} ETH_QUEUE_CTRL; + + +/* Ethernet port specific infomation */ +typedef struct _ethPortCtrl +{ + int portNo; + ETH_QUEUE_CTRL rxQueue[MV_ETH_RX_Q_NUM]; /* Rx ring resource */ + ETH_QUEUE_CTRL txQueue[MV_ETH_TX_Q_NUM]; /* Tx ring resource */ + + MV_ETH_PORT_CFG portConfig; + MV_ETH_RX_Q_CFG rxQueueConfig[MV_ETH_RX_Q_NUM]; + MV_ETH_TX_Q_CFG txQueueConfig[MV_ETH_TX_Q_NUM]; + + /* Register images - For DP */ + MV_U32 portTxQueueCmdReg; /* Port active Tx queues summary */ + MV_U32 portRxQueueCmdReg; /* Port active Rx queues summary */ + + MV_STATE portState; + + MV_U8 mcastCount[256]; + MV_U32* hashPtr; + void *osHandle; +} ETH_PORT_CTRL; + +/************** MACROs ****************/ + +/* MACROs to Flush / Invalidate TX / RX Buffers */ +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) && !defined(UNCACHED_TX_BUFFERS) +# define ETH_PACKET_CACHE_FLUSH(pAddr, size) \ + mvOsCacheClear(NULL, (pAddr), (size)); \ + /*CPU_PIPE_FLUSH;*/ +#else +# define ETH_PACKET_CACHE_FLUSH(pAddr, size) \ + mvOsIoVirtToPhy(NULL, (pAddr)); +#endif /* ETHER_DRAM_COHER == MV_CACHE_COHER_SW */ + +#if ( (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) && !defined(UNCACHED_RX_BUFFERS) ) +# define ETH_PACKET_CACHE_INVALIDATE(pAddr, size) \ + mvOsCacheInvalidate (NULL, (pAddr), (size)); \ + /*CPU_PIPE_FLUSH;*/ +#else +# define ETH_PACKET_CACHE_INVALIDATE(pAddr, size) +#endif /* ETHER_DRAM_COHER == MV_CACHE_COHER_SW && !UNCACHED_RX_BUFFERS */ + +#ifdef ETH_DESCR_UNCACHED + +#define ETH_DESCR_FLUSH_INV(pPortCtrl, pDescr) +#define ETH_DESCR_INV(pPortCtrl, pDescr) + +#else + +#define ETH_DESCR_FLUSH_INV(pPortCtrl, pDescr) \ + mvOsCacheLineFlushInv(pPortCtrl->osHandle, (MV_ULONG)(pDescr)) + +#define ETH_DESCR_INV(pPortCtrl, pDescr) \ + mvOsCacheLineInv(pPortCtrl->osHandle, (MV_ULONG)(pDescr)) + +#endif /* ETH_DESCR_UNCACHED */ + +#include "eth/gbe/mvEthGbe.h" + +#endif /* __mvEth_h__ */ + + diff --git a/board/mv_feroceon/mv_hal/eth/nfp/mvNfp.c b/board/mv_feroceon/mv_hal/eth/nfp/mvNfp.c new file mode 100644 index 0000000..ecc8cfd --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth/nfp/mvNfp.c @@ -0,0 +1,742 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvNfp.c - Marvell Network Fast Processing (Routing and NAT) +* +* DESCRIPTION: +* +* Supported Features: +* - OS independent. +* +*******************************************************************************/ + +/* includes */ +#include "mvOs.h" +#include "mvDebug.h" +#include "eth/nfp/mvNfp.h" +#include "eth/mvEth.h" + +MV_U32 ip_hash_depth[ETH_FP_MAX_HASH_DEPTH+1]; +MV_U32 nat_hash_depth[ETH_FP_MAX_HASH_DEPTH+1]; + + +static struct ruleHashBucket *ruleDb; +static MV_U32 ruleDbSize; + +static MV_U32 nfpRuleSetCount; +static MV_U32 nfpRuleUpdateCount; +static MV_U32 nfpRuleDeleteCount; + +MV_U32 fp_ip_jhash_iv = 0; + + +MV_STATUS mvFpInit(void) +{ + memset(nat_hash_depth, 0, (ETH_FP_MAX_HASH_DEPTH+1)*sizeof(MV_U32)); + memset(ip_hash_depth, 0, (ETH_FP_MAX_HASH_DEPTH+1)*sizeof(MV_U32)); + fp_ip_jhash_iv = mvOsRand(); + + return MV_OK; +} + + +/* Initialize NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbInit(MV_U32 dbSize) +{ + ruleDb = (struct ruleHashBucket *)mvOsMalloc(sizeof(struct ruleHashBucket)*dbSize); + if (ruleDb == NULL) { + mvOsPrintf("NFP Rule DB: Not Enough Memory\n"); + return MV_NO_RESOURCE; + } + ruleDbSize = dbSize; + memset(ruleDb, 0, sizeof(struct ruleHashBucket)*ruleDbSize); + nfpRuleSetCount = nfpRuleUpdateCount = nfpRuleDeleteCount = 0; + + mvOsPrintf("mvFpRuleDb (%p): %d entries, %d bytes\n", + ruleDb, ruleDbSize, sizeof(struct ruleHashBucket)*ruleDbSize); + + return MV_OK; +} + +/* Clear NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbClear(void) +{ + MV_U32 i = 0; + MV_FP_RULE *currRule; + MV_FP_RULE *tmpRule; + + if (ruleDb == NULL) + return MV_NOT_INITIALIZED; + + for (i = 0; i < ruleDbSize; i++) { + currRule = ruleDb[i].ruleChain; + while (currRule != NULL) { + tmpRule = currRule; + currRule = currRule->next; + mvOsFree(tmpRule); + } + ruleDb[i].ruleChain = NULL; + } + return MV_OK; +} + + +/* Free Rule Database memory */ +void mvFpRuleDbDestroy(void) +{ + if (ruleDb != NULL) + mvOsFree(ruleDb); +} + +/* Print rule action type. Assume rule is not NULL. */ +static void mvFpActionTypePrint(const MV_FP_RULE *rule) +{ + switch(rule->mgmtInfo.actionType) { + case MV_FP_ROUTE_CMD: + mvOsPrintf("A=Route, "); + break; + case MV_FP_DROP_CMD: + mvOsPrintf("A=Drop, "); + break; + case MV_FP_TO_STACK_CMD: + mvOsPrintf("A=Stack, "); + break; + default: + mvOsPrintf("A=Unknown (%d), ", rule->mgmtInfo.actionType); + break; + } +} + +/* Print rule type (static or dynamic). Assume rule is not NULL. */ +static void mvFpRuleTypePrint(const MV_FP_RULE *rule) +{ + switch(rule->mgmtInfo.ruleType) { + case MV_FP_STATIC_RULE: + mvOsPrintf("T=Static"); + break; + case MV_FP_DYNAMIC_RULE: + mvOsPrintf("T=Dynamic"); + break; + default: + mvOsPrintf("T=Unknown"); + break; + } +} + +/* Print a NFP Rule */ +void mvFpRulePrint(const MV_FP_RULE *rule) +{ + mvFpActionTypePrint(rule); + mvFpRuleTypePrint(rule); + mvOsPrintf(", SIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.srcIp)); + mvOsPrintf(", DIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.dstIp)); + mvOsPrintf(", GTW="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.defGtwIp)); + mvOsPrintf(", DA="); + mvDebugPrintMacAddr(rule->routingInfo.dstMac); + mvOsPrintf(", SA="); + mvDebugPrintMacAddr(rule->routingInfo.srcMac); + mvOsPrintf(", inIf=%d", rule->routingInfo.inIfIndex); + mvOsPrintf(", outIf=%d", rule->routingInfo.outIfIndex); + + mvOsPrintf(", count=%d, aware_flags=0x%X", rule->mgmtInfo.new_count, rule->routingInfo.aware_flags); + mvOsPrintf("\n"); +} + +/* Print NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbPrint(void) +{ + MV_U32 count, i; + MV_FP_RULE *currRule; + + mvOsPrintf("\nPrinting NFP Rule Database\n"); + count = 0; + + for(i=0; inext; + count++; + } + } + return MV_OK; +} + + +/* Copy all the information from src_rule to new_rule */ +/* Warning - doesn't perform any checks on memory, just copies */ +/* count is set to zero in new_rule */ +/* Note: the next pointer is not updated . */ +void mvFpRuleCopy(MV_FP_RULE *dstRule, const MV_FP_RULE *srcRule) +{ + dstRule->mgmtInfo.actionType = srcRule->mgmtInfo.actionType; + dstRule->mgmtInfo.new_count = srcRule->mgmtInfo.new_count; + dstRule->mgmtInfo.old_count = srcRule->mgmtInfo.old_count; + dstRule->mgmtInfo.ruleType = srcRule->mgmtInfo.ruleType; + dstRule->mgmtInfo.snat_aware_refcnt = srcRule->mgmtInfo.snat_aware_refcnt; + dstRule->mgmtInfo.dnat_aware_refcnt = srcRule->mgmtInfo.dnat_aware_refcnt; + + dstRule->routingInfo.aware_flags = srcRule->routingInfo.aware_flags; + dstRule->routingInfo.srcIp = srcRule->routingInfo.srcIp; + dstRule->routingInfo.dstIp = srcRule->routingInfo.dstIp; + dstRule->routingInfo.defGtwIp = srcRule->routingInfo.defGtwIp; + memcpy(dstRule->routingInfo.srcMac, srcRule->routingInfo.srcMac, MV_MAC_ADDR_SIZE); + memcpy(dstRule->routingInfo.dstMac, srcRule->routingInfo.dstMac, MV_MAC_ADDR_SIZE); + dstRule->routingInfo.inIfIndex = srcRule->routingInfo.inIfIndex; + dstRule->routingInfo.outIfIndex = srcRule->routingInfo.outIfIndex; +} + +/* Get the count value for a rule that matches the given SIP, DIP */ +MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *pRule; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + while(pRule) + { + /* look for a matching rule */ + if( (pRule->routingInfo.dstIp == dstIp) && + (pRule->routingInfo.srcIp == srcIp) ) + { + return pRule->mgmtInfo.new_count; + } + pRule = pRule->next; + } + return 0; +} + +MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *pRule; + + hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, + (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + while(pRule) + { + if( (pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp) && + (pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp) ) { + + + pRule->routingInfo.aware_flags = pSetRule->routingInfo.aware_flags; +#ifdef MV_FP_DEBUG + mvOsPrintf("Update FP aware: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash0x%x, flags=0x%x\n", + MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), + hash_tr, pSetRule->routingInfo.aware_flags); +#endif + return MV_OK; + } + pRule = pRule->next; + } +#ifdef MV_FP_DEBUG + mvOsPrintf("FP aware NOT found: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%x, flags=0x%x\n", + MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), + hash_tr, pSetRule->routingInfo.aware_flags); +#endif + return MV_NOT_FOUND; +} + +/* Set a Routing Rule: create a new rule or update an existing rule */ +/* in the Routing + ARP information table */ +MV_STATUS mvFpRuleSet(MV_FP_RULE *pSetRule) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *pRule, *pNewRule; + + hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, + (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + while(pRule) + { + if( (pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp && + pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp) ) { + + mvFpRuleCopy(pRule, pSetRule); + nfpRuleUpdateCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("UpdNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x\n", + nfpRuleUpdateCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr); +#endif + return MV_OK; + } + pRule = pRule->next; + } + + /* Allocate new entry */ + pNewRule = mvOsMalloc(sizeof(MV_FP_RULE)); + if(pNewRule == NULL) + { + mvOsPrintf("mvFpRuleSet: Can't allocate new rule\n"); + return MV_FAIL; + } + + mvFpRuleCopy(pNewRule, pSetRule); + pNewRule->next = NULL; + + if(ruleDb[hash_tr].ruleChain == NULL) + ruleDb[hash_tr].ruleChain = pNewRule; + else { + pRule = ruleDb[hash_tr].ruleChain; + while (pRule->next != NULL) + pRule = pRule->next; + pRule->next = pNewRule; + } + nfpRuleSetCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("SetNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x, aware=0x%02x\n", + nfpRuleSetCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), + hash_tr, pSetRule->routingInfo.aware_flags); +#endif + return MV_OK; +} + +/* Delete a specified rule from the Routing + ARP information table */ +MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *currRule, *prevRule; + + nfpRuleDeleteCount++; + hash = mv_jhash_3words(rule->routingInfo.dstIp, rule->routingInfo.srcIp, + (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + prevRule = NULL; + for (currRule = ruleDb[hash_tr].ruleChain; + currRule != NULL; + prevRule = currRule, currRule = currRule->next) + { + if( (currRule->routingInfo.srcIp == rule->routingInfo.srcIp) && + (currRule->routingInfo.dstIp == rule->routingInfo.dstIp) ) + { + if (prevRule == NULL) + ruleDb[hash_tr].ruleChain = currRule->next; + else + prevRule->next = currRule->next; +#ifdef MV_FP_DEBUG + mvOsPrintf("DelNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x\n", + nfpRuleDeleteCount, MV_IP_QUAD(currRule->routingInfo.dstIp), + MV_IP_QUAD(currRule->routingInfo.srcIp), hash_tr); +#endif + mvOsFree(currRule); + return MV_OK; + } + } + return MV_NOT_FOUND; +} + +/* Find and return the first matching rule in the Routing + ARP information table */ +static INLINE MV_FP_RULE* mvFpRuleFind(MV_U32 dstIp, MV_U32 srcIp) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE* pRule; + int count = 0; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + + while(pRule) + { + /* look for a matching rule */ + if( (pRule->routingInfo.dstIp == dstIp) && + (pRule->routingInfo.srcIp == srcIp) ) + { + MV_NFP_STAT( ip_hash_depth[count]++); + pRule->mgmtInfo.new_count++; + return pRule; + } + pRule = pRule->next; + count++; + } + return NULL; +} + +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT +static INLINE MV_U32 mvFpFdbMember(MV_U32 ifIndex) +{ + return (ifIndex < ETH_FP_IFINDEX_MAX) ? fdbMember[ifIndex] : 0; +} + +static MV_FP_FDB_RULE* mvFpFdbLookup(MV_U32 ifIndex, MV_U8* pDA) +{ + MV_U32 hash, hash_tr; + MV_FP_FDB_RULE* pRule; + MV_U32 bridgeId; + int count = 0; + + if (ifIndex >= ETH_FP_IFINDEX_MAX) + return NULL; + + if (!(bridgeId = fdbMember[ifIndex])) + return NULL; + + hash = mv_jhash_3words(bridgeId, 0, *(MV_U32*)(pDA+2), fp_ip_jhash_iv); + hash_tr = hash & (fdbRuleDbSize - 1); + + pRule = fdbRuleDb[hash_tr].ruleChain; + + while (pRule) { +/* + MV_NFP_DBG("%s: looking %d %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, bridgeId, + pRule->fdbInfo.mac[0], + pRule->fdbInfo.mac[1], + pRule->fdbInfo.mac[2], + pRule->fdbInfo.mac[3], + pRule->fdbInfo.mac[4], + pRule->fdbInfo.mac[5]); +*/ + if ((bridgeId == pRule->fdbInfo.bridge) && + (*((MV_U16*)(pDA+0)) == *(MV_U16*)(&pRule->fdbInfo.mac[0])) && + (*((MV_U16*)(pDA+2)) == *(MV_U16*)(&pRule->fdbInfo.mac[2])) && + (*((MV_U16*)(pDA+4)) == *(MV_U16*)(&pRule->fdbInfo.mac[4]))) + { + MV_NFP_STAT(ip_hash_depth[count]++); + pRule->mgmtInfo.new_count++; + break; + } + pRule = pRule->next; + count++; + } +/* + if (pRule) + MV_NFP_DBG("%s: lookup bridge=%d %02x:%02x:%02x:%02x:%02x:%02x => if=%d flags=%x\n", + __FUNCTION__, bridgeId, pDA[0],pDA[1],pDA[2],pDA[3],pDA[4],pDA[5], + pRule->fdbInfo.ifIndex, pRule->fdbInfo.flags); + else + MV_NFP_DBG("%s: lookup bridge=%d %02x:%02x:%02x:%02x:%02x:%02x => unknown\n", + __FUNCTION__, bridgeId, pDA[0],pDA[1],pDA[2],pDA[3],pDA[4],pDA[5]); + +*/ + return pRule; +} +#endif /* CONFIG_MV_ETH_NFP_FDB_SUPPORT */ +int mvFpProcess(MV_U32 ifIndex, MV_U8* pData, MV_IP_HEADER* pIpHdr, MV_FP_STATS* pFpStats) +{ + MV_FP_RULE *pFpRoute; + MV_U32 dip, sip; +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + MV_U8 proto; + MV_U16 srcPort, dstPort; + MV_FP_NAT_RULE *pDnatRule, *pSnatRule; +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT + MV_FP_FDB_RULE *pFdb; +#endif + MV_U8* pEthHeader = pData + ETH_MV_HEADER_SIZE; + + MV_NFP_STAT( pFpStats->process++ ); + + /* Check MAC address: + * WAN - non-promiscous mode. + * Unicast packets - NFP, + * Multicast, Broadcast - Linux + * LAN - Promiscous mode. + * LAN Unicast MAC - NFP, + * Multicast, Broadcast, Unknown Unicast - Linux + */ + if(pEthHeader[0] & 0x1) + { + /* Go to Linux IP stack */ + MV_NFP_STAT( pFpStats->multicast++); + return -1; + } + +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT + if (mvFpFdbMember(ifIndex)) + { + pFdb = mvFpFdbLookup(ifIndex, pEthHeader); + if (!pFdb) { + MV_NFP_STAT( pFpStats->fdb_rx_unknown++ ); + return -1; + } + if (pFdb->fdbInfo.flags & MV_FP_FDB_IS_LOCAL) { + /* DA is local, continue with routing */ + MV_NFP_STAT( pFpStats->fdb_rx_local++ ); + } + else { + /* perform bridging */ + MV_NFP_STAT( pFpStats->fdb_bridged++ ); + return pFdb->fdbInfo.ifIndex; + } + } +#endif /* CONFIG_MV_ETH_NFP_FDB_SUPPORT */ + /* Check TTL value */ + if(pIpHdr->ttl <= 1) + { + /* TTL expired */ + MV_NFP_STAT( pFpStats->ip_ttl_expired++ ); + return -1; + } + + dip = pIpHdr->dstIP; + sip = pIpHdr->srcIP; + +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + proto = mvFpNatPortsGet(pIpHdr, &dstPort, &srcPort); + if(proto == MV_IP_PROTO_NULL) + { + /* NAT not supported for this protocol */ + MV_NFP_STAT( pFpStats->nat_bad_proto++ ); + pDnatRule = NULL; + } + else + { + /* Lookup NAT database accordingly with 5 tuple key */ + pDnatRule = mvFpNatRuleFind(dip, sip, proto, dstPort, srcPort); + } + if(pDnatRule != NULL) + { + if(pDnatRule->flags & MV_FP_DIP_CMD_MAP) + { + dip = pDnatRule->newIp; + } + if(pDnatRule->flags & MV_FP_DPORT_CMD_MAP) + { + dstPort = pDnatRule->newPort; + } + } + else + { + MV_NFP_STAT( pFpStats->dnat_not_found++ ); + } + +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ + + pFpRoute = mvFpRuleFind(dip, sip); + if(pFpRoute == NULL) + { + /* IP Routing rule is not found: go to Linux IP stack */ + MV_NFP_STAT( pFpStats->ip_not_found++ ); + return -1; + } + MV_NFP_STAT(pFpStats->ip_found++); + +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + if( (pDnatRule != NULL) && (pDnatRule->flags & MV_FP_DNAT_CMD_MAP) ) + { + MV_NFP_STAT( pFpStats->dnat_found++ ); + pSnatRule = mvFpNatRuleFind(dip, sip, proto, dstPort, srcPort); + } + else + { + pSnatRule = pDnatRule; + } + + if( (pSnatRule != NULL) && (pSnatRule->flags & MV_FP_SNAT_CMD_MAP) ) + { + MV_NFP_STAT( pFpStats->snat_found++ ); + } + else + { + MV_NFP_STAT( pFpStats->snat_not_found++ ); + } + + /* Check IP awareness */ + if( (pFpRoute->routingInfo.aware_flags & MV_FP_DIP_CMD_MAP) && + (pDnatRule == NULL) ) + { + MV_NFP_STAT( pFpStats->dnat_aware++ ); + return -1; + } + + if( (pFpRoute->routingInfo.aware_flags & MV_FP_SIP_CMD_MAP) && + (pSnatRule == NULL) ) + { + MV_NFP_STAT( pFpStats->snat_aware++ ); + return -1; + } + + /* Update packet accordingly with NAT rules */ + if( (pDnatRule != NULL) || (pSnatRule != NULL) ) + { + mvFpNatPktUpdate(pIpHdr, pDnatRule, pSnatRule); + } +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ + + if( (unsigned int)pEthHeader & 0x2) + { + *((MV_U16*)(pEthHeader)) = *(MV_U16*)(&pFpRoute->routingInfo.dstMac[0]); + *((MV_U32*)(pEthHeader + 2)) = *(MV_U32*)(&pFpRoute->routingInfo.dstMac[2]); + *((MV_U32*)(pEthHeader + 2 + 4)) = *(MV_U32*)(&pFpRoute->routingInfo.srcMac[0]); + *((MV_U16*)(pEthHeader + 2 + 4 + 4)) = *(MV_U16*)(&pFpRoute->routingInfo.srcMac[4]); + } + else + { + memcpy(pEthHeader, pFpRoute->routingInfo.dstMac, MV_MAC_ADDR_SIZE*2); + } + pIpHdr->ttl--; + +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT + /* find actual port inside bridge, otherwise br->xmit is called */ + if (mvFpFdbMember(pFpRoute->routingInfo.outIfIndex)) { + pFdb = mvFpFdbLookup(pFpRoute->routingInfo.outIfIndex, pEthHeader); + if (pFdb) { + MV_NFP_STAT( pFpStats->fdb_tx_found++ ); + return pFdb->fdbInfo.ifIndex; + } + } +#endif /* CONFIG_MV_ETH_NFP_FDB_SUPPORT */ + + return pFpRoute->routingInfo.outIfIndex; +} + +void mvFpStatsPrint(MV_FP_STATS *pFpStats) +{ +#ifdef MV_FP_STATISTICS + int i = 0; + + mvOsPrintf( "\n====================================================\n" ); + mvOsPrintf( " NFP statistics"); + mvOsPrintf( "\n-------------------------------\n" ); + + mvOsPrintf( "nfp_parsing....................%10u\n", pFpStats->parsing ); + mvOsPrintf( "nfp_process....................%10u\n", pFpStats->process ); + mvOsPrintf( "nfp_multicast..................%10u\n", pFpStats->multicast ); + mvOsPrintf( "nfp_non_ip.....................%10u\n", pFpStats->non_ip ); + mvOsPrintf( "nfp_vlan_tagged................%10u\n", pFpStats->vlan_tagged ); + mvOsPrintf( "nfp_ip_not_found...............%10u\n", pFpStats->ip_not_found ); + mvOsPrintf( "nfp_ttl_expired................%10u\n", pFpStats->ip_ttl_expired ); + mvOsPrintf( "nfp_ip_found...................%10u\n", pFpStats->ip_found ); + +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + mvOsPrintf( "nfp_nat_bad_proto..............%10u\n", pFpStats->nat_bad_proto); + mvOsPrintf( "nfp_nat_dnat_found.............%10u\n", pFpStats->dnat_found); + mvOsPrintf( "nfp_nat_snat_found.............%10u\n", pFpStats->snat_found); + mvOsPrintf( "nfp_nat_dnat_not_found.........%10u\n", pFpStats->dnat_not_found); + mvOsPrintf( "nfp_nat_snat_not_found.........%10u\n", pFpStats->snat_not_found); + mvOsPrintf( "nfp_nat_dnat_aware.............%10u\n", pFpStats->dnat_aware); + mvOsPrintf( "nfp_nat_snat_aware.............%10u\n", pFpStats->snat_aware); +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ + +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT + mvOsPrintf( "nfp_fdb_rx_local...............%10u\n", pFpStats->fdb_rx_local); + mvOsPrintf( "nfp_fdb_rx_unknown.............%10u\n", pFpStats->fdb_rx_unknown); + mvOsPrintf( "nfp_fdb_tx_found...............%10u\n", pFpStats->fdb_tx_found); + mvOsPrintf( "nfp_fdb_bridged................%10u\n", pFpStats->fdb_bridged); +#endif /* CONFIG_MV_ETH_NFP_FDB_SUPPORT */ + + mvOsPrintf("\nHASH Depth IP stats\n"); + for(i=0; i<=ETH_FP_MAX_HASH_DEPTH; i++) + { + if(ip_hash_depth[i] != 0) + { + mvOsPrintf("%d depth - %u times\n", i, ip_hash_depth[i]); + ip_hash_depth[i] = 0; + } + } + +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + mvOsPrintf("\nHASH Depth NAT stats\n"); + for(i=0; i<=ETH_FP_MAX_HASH_DEPTH; i++) + { + if(nat_hash_depth[i] != 0) + { + mvOsPrintf("%d depth - %u times\n", i, nat_hash_depth[i]); + nat_hash_depth[i] = 0; + } + } +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ + + memset(pFpStats, 0, sizeof(MV_FP_STATS)); +#endif /* MV_FP_STATISTICS */ + + mvOsPrintf("\n"); + mvOsPrintf("nfpRuleSetCount=%u, nfpRuleUpdateCount=%u, nfpRuleDeleteCount=%u\n", + nfpRuleSetCount, nfpRuleUpdateCount, nfpRuleDeleteCount); + +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + mvOsPrintf("\n"); + mvOsPrintf("natRuleSetCount=%u, natRuleUpdateCount=%u, natRuleDeleteCount=%u\n", + natRuleSetCount, natRuleUpdateCount, natRuleDeleteCount); +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ +} + diff --git a/board/mv_feroceon/mv_hal/eth/nfp/mvNfp.h b/board/mv_feroceon/mv_hal/eth/nfp/mvNfp.h new file mode 100644 index 0000000..7a6a8b5 --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth/nfp/mvNfp.h @@ -0,0 +1,471 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvNfp.h - Header File for Marvell NFP (Routing and NAT) +* +* DESCRIPTION: +* This header file contains macros, typedefs and function declarations +* specific to the Marvell Network Fast Processing (Routing and NAT). +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __mvNfp_h__ +#define __mvNfp_h__ + +/* includes */ +#include "mvTypes.h" +#include "mvCommon.h" +#include "mvStack.h" +#include "mv802_3.h" +#include "eth/mvEth.h" +#include "mvSysHwConfig.h" + +/* defines */ +#define ETH_FP_MAX_HASH_DEPTH 8 +#define ETH_FP_IFINDEX_MAX 32 + +/* uncomment to open some debug prints on adding and updating NFP rules */ +#undef MV_FP_DEBUG + +#ifdef MV_FP_DEBUG +# define MV_NFP_DBG(fmt, arg...) printk(KERN_INFO fmt, ##arg) +#else +# define MV_NFP_DBG(fmt, arg...) +#endif + +#ifdef MV_FP_STATISTICS +# define MV_NFP_STAT(CODE) CODE; +#else +# define MV_NFP_STAT(CODE) +#endif + +/* enumerations */ +typedef enum { + MV_FP_ROUTE_CMD, /* perform NFP routing */ + MV_FP_DROP_CMD, /* drop packet */ + MV_FP_TO_STACK_CMD, /* pass packet to linux stack */ + MV_FP_DIP_CMD, /* replace DIP */ + MV_FP_SIP_CMD, /* replace SIP */ + MV_FP_DPORT_CMD, /* replace DPORT */ + MV_FP_SPORT_CMD, /* replace SPORT */ + MV_FP_BRIDGE_CMD, /* perform fast path bridging */ +} MV_FP_CMD_TYPE; + +#define MV_FP_NULL_BINDING 0 +#define MV_FP_NULL_BINDING_SET (1 << MV_FP_ROUTE_CMD) + +#define MV_FP_DIP_CMD_MAP (1 << MV_FP_DIP_CMD) +#define MV_FP_DPORT_CMD_MAP (1 << MV_FP_DPORT_CMD) +#define MV_FP_DNAT_CMD_MAP (MV_FP_DIP_CMD_MAP | MV_FP_DPORT_CMD_MAP) + +#define MV_FP_SIP_CMD_MAP (1 << MV_FP_SIP_CMD) +#define MV_FP_SPORT_CMD_MAP (1 << MV_FP_SPORT_CMD) +#define MV_FP_SNAT_CMD_MAP (MV_FP_SIP_CMD_MAP | MV_FP_SPORT_CMD_MAP) + +typedef enum { + MV_FP_STATIC_RULE, /* a static rule created by the user */ + MV_FP_DYNAMIC_RULE /* a dynamic rule */ + +} MV_FP_RULE_TYPE; + +/* structure definitions (used by the NFP Manager and the NFP Database)*/ +typedef struct { + MV_FP_CMD_TYPE actionType; + MV_U32 old_count; + int new_count; + MV_FP_RULE_TYPE ruleType; + int dnat_aware_refcnt; + int snat_aware_refcnt; + +} MV_FP_RULE_MGMT_INFO; + +typedef struct { + MV_U32 dstIp; + MV_U32 srcIp; + MV_U32 defGtwIp; + MV_U8 reserved; + MV_U8 aware_flags; + /* dstMac should be 2 byte aligned */ + MV_U8 dstMac[MV_MAC_ADDR_SIZE]; + MV_U8 srcMac[MV_MAC_ADDR_SIZE]; + MV_U8 inIfIndex; /* Linux interface index */ + MV_U8 outIfIndex; /* Linux interface index */ + +} MV_FP_RULE_ROUTING_INFO; + +typedef struct _mv_fp_rule { + struct _mv_fp_rule *next; + + MV_FP_RULE_MGMT_INFO mgmtInfo; + MV_FP_RULE_ROUTING_INFO routingInfo; + +} MV_FP_RULE; + +struct ruleHashBucket { + MV_FP_RULE *ruleChain; /* This is an entry in the rule hash table. */ + + /* Add additional fields (such as a lock) here if required */ +}; + +#define MV_JHASH_MIX(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define MV_JHASH_GOLDEN_RATIO 0x9e3779b9 + +extern MV_U32 fp_ip_jhash_iv; + +static INLINE MV_U32 mv_jhash_3words(MV_U32 a, MV_U32 b, MV_U32 c, MV_U32 initval) +{ + a += MV_JHASH_GOLDEN_RATIO; + b += MV_JHASH_GOLDEN_RATIO; + c += initval; + MV_JHASH_MIX(a, b, c); + + return c; +} +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + +typedef struct _mv_fp_nat_rule { + struct _mv_fp_nat_rule *next; + MV_U32 old_count; + MV_U32 new_count; + + /* Original packet information */ + /* Fields will contain invalid values if they are irrelevant */ + MV_U32 srcIp; + MV_U32 dstIp; + MV_U16 srcPort; + MV_U16 dstPort; + MV_U8 proto; + + /* NAT information */ + MV_U8 flags; + MV_U32 newIp; + MV_U16 newPort; + +} MV_FP_NAT_RULE; + +struct natRuleHashBucket { + MV_FP_NAT_RULE *natRuleChain; /* This is an entry in the NAT rule hash table. */ + + /* Add additional fields (such as a lock) here if required */ +}; + +extern MV_U32 nat_hash_depth[]; + +extern struct natRuleHashBucket *natRuleDb; +extern MV_U32 natRuleDbSize; +extern MV_U32 natRuleUpdateCount, natRuleSetCount, natRuleDeleteCount; +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ + +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT + +#define MV_FP_FDB_IS_LOCAL 1 + +typedef struct { + MV_U16 flags; + MV_U8 mac[6]; + MV_U32 ifIndex; + MV_U32 bridge; +} MV_FP_RULE_FDB_INFO; + +typedef struct _mv_fp_fdb_rule { + struct _mv_fp_fdb_rule *next; + + MV_FP_RULE_MGMT_INFO mgmtInfo; + MV_FP_RULE_FDB_INFO fdbInfo; + +} MV_FP_FDB_RULE; + +struct fdbRuleHashBucket { + MV_FP_FDB_RULE *ruleChain; +}; + +extern MV_U32 fdb_hash_depth[]; +extern struct fdbRuleHashBucket *fdbRuleDb; +extern MV_U32 fdbRuleDbSize; +extern MV_U32 fdbMember[]; + +#endif /* CONFIG_MV_ETH_NFP_FDB_SUPPORT */ + +typedef struct +{ + MV_U32 parsing, process, multicast, non_ip, vlan_tagged; + MV_U32 ip_not_found, ip_ttl_expired, ip_found; + +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT + MV_U32 nat_bad_proto; + MV_U32 dnat_aware; + MV_U32 snat_aware; + MV_U32 dnat_found; + MV_U32 snat_found; + MV_U32 dnat_not_found; + MV_U32 snat_not_found; +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ + +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT + MV_U32 fdb_rx_local; + MV_U32 fdb_rx_unknown; + MV_U32 fdb_tx_found; + MV_U32 fdb_bridged; +#endif /* CONFIG_MV_ETH_NFP_FDB_SUPPORT */ + +} MV_FP_STATS; + +static INLINE MV_IP_HEADER* mvFpParsing(MV_PKT_INFO *pPktInfo, MV_FP_STATS* pFpStats) +{ + MV_U8 *pData; + MV_IP_HEADER *pIpHdr; + MV_U32 tx_status; + + pData = (MV_U8*)pPktInfo->pFrags[0].bufVirtPtr + ETH_MV_HEADER_SIZE; + + MV_NFP_STAT( pFpStats->parsing++ ); + + /* Check LLC/SNAP and IP header */ + if( ((pPktInfo->status & ETH_RX_NOT_LLC_SNAP_FORMAT_MASK) == 0) || + ((pPktInfo->status & ETH_RX_IP_HEADER_OK_MASK) == 0) || + (pPktInfo->fragIP) ) + { + /* Non IP packet: go to Linux IP stack */ + MV_NFP_STAT( pFpStats->non_ip++ ); + return NULL; + } + tx_status = ( ETH_TX_GENERATE_IP_CHKSUM_MASK + | ETH_TX_IP_NO_FRAG + | (5 << ETH_TX_IP_HEADER_LEN_OFFSET) ); + + /* Calculate start of IP header */ + if( (pPktInfo->status & ETH_RX_VLAN_TAGGED_FRAME_MASK) ) + { + MV_NFP_STAT(pFpStats->vlan_tagged++); + pIpHdr = (MV_IP_HEADER*)(pData + sizeof(MV_802_3_HEADER) + MV_VLAN_HLEN); + tx_status |= ETH_TX_VLAN_TAGGED_FRAME_MASK; + } + else + { + pIpHdr = (MV_IP_HEADER*)(pData + sizeof(MV_802_3_HEADER)); + } + + if( (pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_TCP_TYPE ) + { + tx_status |= (ETH_TX_L4_TCP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK); + } + else if( (pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_UDP_TYPE ) + { + tx_status |= (ETH_TX_L4_UDP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK); + } + + pPktInfo->status = tx_status; + + return pIpHdr; +} + +/* Initialize NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbInit(MV_U32 dbSize); +/* Clear NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbClear(void); +/* Free Rule Database memory */ +void mvFpRuleDbDestroy(void); +/* Print NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbPrint(void); +/* Copy all the information from src_rule to new_rule */ +/* Warning - doesn't perform any checks on memory, just copies */ +/* count is set to zero in new_rule */ +/* Note: the next pointer is not updated . */ +void mvFpRuleCopy(MV_FP_RULE *newRule, const MV_FP_RULE *srcRule); +/* Get the maximum count value for a rule with srcIp == given ip */ +MV_U32 mvFpMaxArpCountGet(MV_U32 ip); +/* Get the count value for a rule that matches the given SIP, DIP */ +MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp); +/* Set a Routing Rule: create a new rule or update an existing rule */ +/* in the Routing + ARP information table */ +MV_STATUS mvFpRuleSet(MV_FP_RULE *rule); +/* Delete a specified rule from the Routing + ARP information table */ +MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule); +/* Print a Rule */ +void mvFpRulePrint(const MV_FP_RULE *rule); +/* Enable NFP */ +void mvFpEnable(void); +/* Give all packets to Linux IP stack */ +void mvFpDisable(void); +MV_STATUS mvFpInit(void); +int mvFpProcess(MV_U32 inIfIndex, MV_U8* pData, MV_IP_HEADER* pIpHdr, MV_FP_STATS* pFpStats); +void mvFpStatsPrint(MV_FP_STATS *pFpStats); + +/* NAT SUPPORT Functions */ + +#ifdef CONFIG_MV_ETH_NFP_NAT_SUPPORT +/* Find and return the first matching rule */ +static INLINE MV_FP_NAT_RULE* mvFpNatRuleFind(MV_U32 dstIp, MV_U32 srcIp, + MV_U8 proto, MV_U16 dport, MV_U16 sport) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE* pNatRule; + int count = 0; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)((dport << 16) | sport), + (MV_U32)((fp_ip_jhash_iv << 8) | proto)); + hash_tr = hash & (natRuleDbSize - 1); +/* + mvOsPrintf("mvFpNatRuleFind: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%08x (0x%x)\n", + dstIp, srcIp, proto, dport, sport, hash, hash_tr); +*/ + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while(pNatRule) + { + /* look for a matching rule */ + if( (pNatRule->dstIp == dstIp) && + (pNatRule->srcIp == srcIp) && + (pNatRule->proto == proto) && + (pNatRule->dstPort == dport) && + (pNatRule->srcPort == sport) ) + { + MV_NFP_STAT( nat_hash_depth[count]++); + pNatRule->new_count++; + return pNatRule; + } + pNatRule = pNatRule->next; + count++; + } + return NULL; +} + +/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbInit(MV_U32 dbSize); + +/* Clear NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbClear(void); + +/* Free NAT Database memory */ +void mvFpNatDbDestroy(void); + +/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *natRule); + +MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule); + +/* Delete a specified NAT rule from the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule); + +/* Get the count value for a NAT rule */ +MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto); + +/* Print NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbPrint(void); + +/* Print a NAT Rule */ +void mvFpNatRulePrint(const MV_FP_NAT_RULE *rule); + +/* Extract dstPort and srcPort values from the packet */ +MV_U8 mvFpNatPortsGet(MV_IP_HEADER* pIpHdr, MV_U16* pDstPort, MV_U16* pSrcPort); + +int mvFpNatPktUpdate(MV_IP_HEADER* pIpHdr, MV_FP_NAT_RULE* pDnatRule, MV_FP_NAT_RULE* pSnatRule); + +#endif /* CONFIG_MV_ETH_NFP_NAT_SUPPORT */ + + +#ifdef CONFIG_MV_ETH_NFP_FDB_SUPPORT + +/* Init NFP Bridge Rule Database */ +MV_STATUS mvFpFdbInit(MV_U32 dbSize); + +/* Clear NFP Bridge Rule Database */ +MV_STATUS mvFpFdbClear(void); + +/* Destroy NFP Bridge Rule Database */ +void mvFpFdbDestroy(void); + +/* Add NFP Bridge Rule */ +MV_STATUS mvFpFdbRuleSet(MV_FP_FDB_RULE *rule); + +/* Delete NFP Bridge Rule Database */ +MV_STATUS mvFpFdbRuleDel(MV_FP_FDB_RULE *rule); + +/* Aging NFP Bridge Rule Database */ +MV_U32 mvFpFdbRuleAge(MV_FP_FDB_RULE *rule); + +/* Print NFP Bridge Rule Database */ +MV_STATUS mvFpFdbPrint(void); + +#endif /* CONFIG_MV_ETH_NFP_FDB_SUPPORT */ +#endif /* __mvNfp_h__ */ + + diff --git a/board/mv_feroceon/mv_hal/eth/nfp/mvNfpNat.c b/board/mv_feroceon/mv_hal/eth/nfp/mvNfpNat.c new file mode 100644 index 0000000..10e484f --- /dev/null +++ b/board/mv_feroceon/mv_hal/eth/nfp/mvNfpNat.c @@ -0,0 +1,450 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "mvTypes.h" +#include "mvOs.h" +#include "mvStack.h" +#include "mvDebug.h" +#include "eth/nfp/mvNfp.h" +#include "eth/mvEth.h" + + +struct natRuleHashBucket *natRuleDb; +MV_U32 natRuleDbSize; + +MV_U32 natRuleUpdateCount = 0; +MV_U32 natRuleSetCount = 0; +MV_U32 natRuleDeleteCount = 0; + +/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbInit(MV_U32 dbSize) +{ + natRuleDb = (struct natRuleHashBucket *)mvOsMalloc(sizeof(struct natRuleHashBucket)*dbSize); + if (natRuleDb == NULL) { + mvOsPrintf("NFP NAT Rule DB: Not Enough Memory\n"); + return MV_NO_RESOURCE; + } + natRuleDbSize = dbSize; + memset(natRuleDb, 0, sizeof(struct natRuleHashBucket)*natRuleDbSize); + + natRuleSetCount = natRuleDeleteCount = natRuleUpdateCount = 0; + + mvOsPrintf("mvFpNatDb (%p): %d entries, %d bytes\n", + natRuleDb, natRuleDbSize, sizeof(struct natRuleHashBucket)*natRuleDbSize); + + return MV_OK; +} + +/* Clear NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbClear(void) +{ + MV_U32 i = 0; + MV_FP_NAT_RULE *currRule; + MV_FP_NAT_RULE *tmpRule; + + if (natRuleDb == NULL) + return MV_NOT_INITIALIZED; + + for (i = 0; i < natRuleDbSize; i++) { + currRule = natRuleDb[i].natRuleChain; + while (currRule != NULL) { + tmpRule = currRule; + currRule = currRule->next; + mvOsFree(tmpRule); + } + natRuleDb[i].natRuleChain = NULL; + } + return MV_OK; +} + +/* Free NAT Database memory */ +void mvFpNatDbDestroy(void) +{ + if (natRuleDb != NULL) + mvOsFree(natRuleDb); +} + +static void mvFpNatRuleUpdate(MV_FP_NAT_RULE *dstRule, const MV_FP_NAT_RULE *srcRule) +{ + dstRule->flags = srcRule->flags; + dstRule->newIp = srcRule->newIp; + dstRule->newPort = srcRule->newPort; + dstRule->new_count = srcRule->new_count; + dstRule->old_count = srcRule->old_count; +} + +/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *pSetRule) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE *pNatRule, *pNewRule; + + hash = mv_jhash_3words(pSetRule->dstIp, pSetRule->srcIp, + (MV_U32)((pSetRule->dstPort << 16) | pSetRule->srcPort), + (MV_U32)((fp_ip_jhash_iv << 8) | pSetRule->proto)); + hash_tr = hash & (natRuleDbSize - 1); + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while(pNatRule) + { + /* look for a matching rule */ + if( (pNatRule->dstIp == pSetRule->dstIp) && + (pNatRule->srcIp == pSetRule->srcIp) && + (pNatRule->proto == pSetRule->proto) && + (pNatRule->dstPort == pSetRule->dstPort) && + (pNatRule->srcPort == pSetRule->srcPort) ) + { + /* update rule */ + mvFpNatRuleUpdate(pNatRule, pSetRule); + natRuleUpdateCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("UpdNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n", + natRuleUpdateCount, pNatRule->dstIp, pNatRule->srcIp, pNatRule->proto, + MV_16BIT_BE(pNatRule->dstPort), MV_16BIT_BE(pNatRule->srcPort), hash_tr, pNatRule->flags); +#endif + return MV_OK; + } + pNatRule = pNatRule->next; + } + /* Allocate new entry */ + pNewRule = mvOsMalloc(sizeof(MV_FP_NAT_RULE)); + if(pNewRule == NULL) + { + mvOsPrintf("mvFpNatRuleSet: Can't allocate new rule\n"); + return MV_FAIL; + } + + memcpy(pNewRule, pSetRule, sizeof(*pNewRule)); + pNewRule->next = NULL; + + if(natRuleDb[hash_tr].natRuleChain == NULL) + { + natRuleDb[hash_tr].natRuleChain = pNewRule; + } + else + { + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while (pNatRule->next != NULL) + pNatRule = pNatRule->next; + + pNatRule->next = pNewRule; + } + natRuleSetCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("SetNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n", + natRuleSetCount, pNewRule->dstIp, pNewRule->srcIp, pNewRule->proto, + MV_16BIT_BE(pNewRule->dstPort), MV_16BIT_BE(pNewRule->srcPort), hash_tr, pNewRule->flags); +#endif + return MV_OK; +} + +/* Delete a specified NAT rule from the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE *currRule, *prevRule; + + natRuleDeleteCount++; + + hash = mv_jhash_3words(natRule->dstIp, natRule->srcIp, + (MV_U32)((natRule->dstPort << 16) | natRule->srcPort), + (MV_U32)((fp_ip_jhash_iv << 8) | natRule->proto)); + hash_tr = hash & (natRuleDbSize - 1); + + prevRule = NULL; + for (currRule = natRuleDb[hash_tr].natRuleChain; + currRule != NULL; + prevRule = currRule, currRule = currRule->next) + { + if (currRule->srcIp == natRule->srcIp && + currRule->dstIp == natRule->dstIp && + currRule->srcPort == natRule->srcPort && + currRule->dstPort == natRule->dstPort && + currRule->proto == natRule->proto ) + { + if (prevRule == NULL) + natRuleDb[hash_tr].natRuleChain = currRule->next; + else + prevRule->next = currRule->next; + +#ifdef MV_FP_DEBUG + mvOsPrintf("DelNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x\n", + natRuleDeleteCount, currRule->dstIp, currRule->srcIp, currRule->proto, + MV_16BIT_BE(currRule->dstPort), MV_16BIT_BE(currRule->srcPort), hash_tr); +#endif + mvOsFree(currRule); + return MV_OK; + } + } + return MV_NOT_FOUND; +} + +/* Check that protocol supported for FP NAT and extract srcPort and dstPort + * (or their equivalents) from the packet. + */ +MV_U8 mvFpNatPortsGet(MV_IP_HEADER* pIpHdr, MV_U16* pDstPort, MV_U16* pSrcPort) +{ + MV_U8 proto = pIpHdr->protocol; + MV_UDP_HEADER *pUdpHdr; + MV_TCP_HEADER *pTcpHdr; + MV_ICMP_ECHO_HEADER *pIcmpHdr; + + switch(proto) + { + case MV_IP_PROTO_TCP: + pTcpHdr = (MV_TCP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + *pDstPort = pTcpHdr->dest; + *pSrcPort = pTcpHdr->source; + break; + + case MV_IP_PROTO_UDP: + pUdpHdr = (MV_UDP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + *pDstPort = pUdpHdr->dest; + *pSrcPort = pUdpHdr->source; + break; + + case MV_IP_PROTO_ICMP: + pIcmpHdr = (MV_ICMP_ECHO_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + if( (pIcmpHdr->type == MV_ICMP_ECHO) || (pIcmpHdr->type == MV_ICMP_ECHOREPLY) ) + { + *pDstPort = (pIcmpHdr->code << 8) | (pIcmpHdr->type); + *pSrcPort = pIcmpHdr->id; + } + else + { + /* Do NAT for IP + protocol only (without ports) */ + *pDstPort = 0; + *pSrcPort = 0; + } + break; + + case MV_IP_PROTO_ZERO_HOP: + /* Do NAT for IP + protocol only (without ports) */ + *pDstPort = 0; + *pSrcPort = 0; + break; + + /* Other protocols supporting NAT only without ports + * case ???????: + * case ???????: + * *pDstPort = 0; + * *pSrcPort = 0; + * break + * + */ + + default: + /* Skip NAT processing at all */ + proto = MV_IP_PROTO_NULL; + } + return proto; +} + +int mvFpNatPktUpdate(MV_IP_HEADER* pIpHdr, MV_FP_NAT_RULE* pDnatRule, MV_FP_NAT_RULE* pSnatRule) +{ + MV_UDP_HEADER *pUdpHdr; + MV_TCP_HEADER *pTcpHdr; + MV_ICMP_ECHO_HEADER *pIcmpHdr; + int hdr_size = 0; + MV_U16 *pDstPort=NULL, *pSrcPort=NULL; + + switch(pIpHdr->protocol) + { + case MV_IP_PROTO_TCP: + pTcpHdr = (MV_TCP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + pDstPort = &pTcpHdr->dest; + pSrcPort = &pTcpHdr->source; + hdr_size = sizeof(MV_TCP_HEADER); + break; + + case MV_IP_PROTO_UDP: + pUdpHdr = (MV_UDP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + pDstPort = &pUdpHdr->dest; + pSrcPort = &pUdpHdr->source; + hdr_size = sizeof(MV_UDP_HEADER); + break; + + case MV_IP_PROTO_ICMP: + pIcmpHdr = (MV_ICMP_ECHO_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + if( (pIcmpHdr->type == MV_ICMP_ECHO) || (pIcmpHdr->type == MV_ICMP_ECHOREPLY) ) + { + pDstPort = &pIcmpHdr->id; + pSrcPort = &pIcmpHdr->id; + hdr_size = sizeof(MV_ICMP_ECHO_HEADER); + } + else + { + mvOsPrintf("Wrong ICMP type: 0x%x\n", pIcmpHdr->type & 0xFF); + } + break; + + case MV_IP_PROTO_ZERO_HOP: + /* Do nothing - only IP addresses are updated for this protocol */ + break; + + default: + mvOsPrintf("Unexpected IP protocol: 0x%x\n", + pIpHdr->protocol); + } + if(pDnatRule != NULL) + { + if(pDnatRule->flags & MV_FP_DIP_CMD_MAP) + pIpHdr->dstIP = pDnatRule->newIp; + if( (pDnatRule->flags & MV_FP_DPORT_CMD_MAP) && + (pDstPort != NULL) ) + *pDstPort = pDnatRule->newPort; + } + + if(pSnatRule != NULL) + { + if(pSnatRule->flags & MV_FP_SIP_CMD_MAP) + pIpHdr->srcIP = pSnatRule->newIp; + + if( (pSnatRule->flags & MV_FP_SPORT_CMD_MAP) && + (pSrcPort != NULL) ) + *pSrcPort = pSnatRule->newPort; + } + return hdr_size; +} + +/* Print a NFP NAT Rule */ +void mvFpNatRulePrint(const MV_FP_NAT_RULE *rule) +{ + /* Note: some of the fields in the NAT rule may contain invalid values */ + mvOsPrintf("Original packet: "); + mvOsPrintf("SIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->srcIp)), + mvOsPrintf(", DIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->dstIp)), + mvOsPrintf(", SPort=%d", MV_16BIT_BE(rule->srcPort)); + mvOsPrintf(", DPort=%d", MV_16BIT_BE(rule->dstPort)); + mvOsPrintf("\nNAT Info: "); + mvOsPrintf("count=%u, flags=0x%x", rule->new_count, rule->flags); + mvOsPrintf(", newIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->newIp)); + mvOsPrintf(", newPort=%d", MV_16BIT_BE(rule->newPort)); + mvOsPrintf("\n"); +} + +/* Print NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbPrint(void) +{ + MV_U32 count, i = 0; + MV_FP_NAT_RULE *currRule; + + mvOsPrintf("\nPrinting NFP NAT Rule Database: \n"); + count = 0; + for (i=0; iflags != MV_FP_NULL_BINDING) || (currRule->new_count > 0) ) + { + mvOsPrintf("%03u: Rule=%p, Next=%p\n", count, currRule, currRule->next); + mvFpNatRulePrint(currRule); + } + currRule = currRule->next; + count++; + } + } + return MV_OK; +} + +/* Get the count value for a NAT rule */ +MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE *pNatRule; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)((dstPort << 16) | srcPort), + (MV_U32)((fp_ip_jhash_iv << 8) | proto)); + hash_tr = hash & (natRuleDbSize - 1); + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while(pNatRule) + { + /* look for a matching rule */ + if( (pNatRule->dstIp == dstIp) && + (pNatRule->srcIp == srcIp) && + (pNatRule->proto == proto) && + (pNatRule->dstPort == dstPort) && + (pNatRule->srcPort == srcPort) ) + { + return pNatRule->new_count; + } + pNatRule = pNatRule->next; + } + return 0; +} + diff --git a/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.c b/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.c new file mode 100644 index 0000000..0c3129b --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.c @@ -0,0 +1,655 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvFastPath.c - Marvell Network Fast Processing (Routing and NAT) +* +* DESCRIPTION: +* +* Supported Features: +* - OS independent. +* +*******************************************************************************/ + +/* includes */ +#include "mvOs.h" +#include "mvDebug.h" +#include "ethfp/fast_path/mvFastPath.h" +#include "ethfp/mvEth.h" + +MV_U32 ip_hash_depth[ETH_FP_MAX_HASH_DEPTH+1]; +MV_U32 nat_hash_depth[ETH_FP_MAX_HASH_DEPTH+1]; + + +static struct ruleHashBucket *ruleDb; +static MV_U32 ruleDbSize; + +static MV_U32 nfpRuleSetCount; +static MV_U32 nfpRuleUpdateCount; +static MV_U32 nfpRuleDeleteCount; + +MV_U32 fp_ip_jhash_iv = 0; + + +MV_STATUS mvFpInit(void) +{ + memset(nat_hash_depth, 0, (ETH_FP_MAX_HASH_DEPTH+1)*sizeof(MV_U32)); + memset(ip_hash_depth, 0, (ETH_FP_MAX_HASH_DEPTH+1)*sizeof(MV_U32)); + fp_ip_jhash_iv = mvOsRand(); + + return MV_OK; +} + + +/* Initialize NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbInit(MV_U32 dbSize) +{ + ruleDb = (struct ruleHashBucket *)mvOsMalloc(sizeof(struct ruleHashBucket)*dbSize); + if (ruleDb == NULL) { + mvOsPrintf("NFP Rule DB: Not Enough Memory\n"); + return MV_NO_RESOURCE; + } + ruleDbSize = dbSize; + memset(ruleDb, 0, sizeof(struct ruleHashBucket)*ruleDbSize); + nfpRuleSetCount = nfpRuleUpdateCount = nfpRuleDeleteCount = 0; + + mvOsPrintf("mvFpRuleDb (%p): %d entries, %d bytes\n", + ruleDb, ruleDbSize, sizeof(struct ruleHashBucket)*ruleDbSize); + + return MV_OK; +} + +/* Clear NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbClear(void) +{ + MV_U32 i = 0; + MV_FP_RULE *currRule; + MV_FP_RULE *tmpRule; + + if (ruleDb == NULL) + return MV_NOT_INITIALIZED; + + for (i = 0; i < ruleDbSize; i++) { + currRule = ruleDb[i].ruleChain; + while (currRule != NULL) { + tmpRule = currRule; + currRule = currRule->next; + mvOsFree(tmpRule); + } + ruleDb[i].ruleChain = NULL; + } + return MV_OK; +} + + +/* Free Rule Database memory */ +void mvFpRuleDbDestroy(void) +{ + if (ruleDb != NULL) + mvOsFree(ruleDb); +} + +/* Print rule action type. Assume rule is not NULL. */ +static void mvFpActionTypePrint(const MV_FP_RULE *rule) +{ + switch(rule->mgmtInfo.actionType) { + case MV_FP_ROUTE_CMD: + mvOsPrintf("A=Route, "); + break; + case MV_FP_DROP_CMD: + mvOsPrintf("A=Drop, "); + break; + case MV_FP_TO_STACK_CMD: + mvOsPrintf("A=Stack, "); + break; + default: + mvOsPrintf("A=Unknown (%d), ", rule->mgmtInfo.actionType); + break; + } +} + +/* Print rule type (static or dynamic). Assume rule is not NULL. */ +static void mvFpRuleTypePrint(const MV_FP_RULE *rule) +{ + switch(rule->mgmtInfo.ruleType) { + case MV_FP_STATIC_RULE: + mvOsPrintf("T=Static"); + break; + case MV_FP_DYNAMIC_RULE: + mvOsPrintf("T=Dynamic"); + break; + default: + mvOsPrintf("T=Unknown"); + break; + } +} + +/* Print a NFP Rule */ +void mvFpRulePrint(const MV_FP_RULE *rule) +{ + mvFpActionTypePrint(rule); + mvFpRuleTypePrint(rule); + mvOsPrintf(", SIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.srcIp)); + mvOsPrintf(", DIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.dstIp)); + mvOsPrintf(", GTW="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->routingInfo.defGtwIp)); + mvOsPrintf(", DA="); + mvDebugPrintMacAddr(rule->routingInfo.dstMac); + mvOsPrintf(", SA="); + mvDebugPrintMacAddr(rule->routingInfo.srcMac); + mvOsPrintf(", inIf=%d", rule->routingInfo.inIfIndex); + mvOsPrintf(", outIf=%d", rule->routingInfo.outIfIndex); + +#if defined(CONFIG_MV_GTW_HEADER_MODE) + mvOsPrintf(", mvHeader=0x%X", rule->routingInfo.pktHdr.mvHeader.header); +#elif defined (CONFIG_MV_GTW_DSA_TAG_MODE) + mvOsPrintf(", dsaTag=0x%X", rule->routingInfo.pktHdr.dsaTag); +#endif /* CONFIG_MV_GTW_HEADER_MODE || CONFIG_MV_GTW_EXT_DSA_TAG_MODE || CONFIG_MV_GTW_EXT_DSA_TAG_MODE */ + + mvOsPrintf(", count=%d, aware_flags=0x%X", rule->mgmtInfo.new_count, rule->routingInfo.aware_flags); + mvOsPrintf("\n"); +} + +/* Print NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbPrint(void) +{ + MV_U32 count, i; + MV_FP_RULE *currRule; + + mvOsPrintf("\nPrinting NFP Rule Database\n"); + count = 0; + + for(i=0; inext; + count++; + } + } + return MV_OK; +} + + +/* Copy all the information from src_rule to new_rule */ +/* Warning - doesn't perform any checks on memory, just copies */ +/* count is set to zero in new_rule */ +/* Note: the next pointer is not updated . */ +void mvFpRuleCopy(MV_FP_RULE *dstRule, const MV_FP_RULE *srcRule) +{ + dstRule->mgmtInfo.actionType = srcRule->mgmtInfo.actionType; + dstRule->mgmtInfo.new_count = srcRule->mgmtInfo.new_count; + dstRule->mgmtInfo.old_count = srcRule->mgmtInfo.old_count; + dstRule->mgmtInfo.ruleType = srcRule->mgmtInfo.ruleType; + dstRule->mgmtInfo.snat_aware_refcnt = srcRule->mgmtInfo.snat_aware_refcnt; + dstRule->mgmtInfo.dnat_aware_refcnt = srcRule->mgmtInfo.dnat_aware_refcnt; + + dstRule->routingInfo.aware_flags = srcRule->routingInfo.aware_flags; + dstRule->routingInfo.srcIp = srcRule->routingInfo.srcIp; + dstRule->routingInfo.dstIp = srcRule->routingInfo.dstIp; + dstRule->routingInfo.defGtwIp = srcRule->routingInfo.defGtwIp; + memcpy(dstRule->routingInfo.srcMac, srcRule->routingInfo.srcMac, MV_MAC_ADDR_SIZE); + memcpy(dstRule->routingInfo.dstMac, srcRule->routingInfo.dstMac, MV_MAC_ADDR_SIZE); + dstRule->routingInfo.inIfIndex = srcRule->routingInfo.inIfIndex; + dstRule->routingInfo.outIfIndex = srcRule->routingInfo.outIfIndex; +#ifdef CONFIG_MV_GATEWAY + dstRule->routingInfo.pktHdr = srcRule->routingInfo.pktHdr; +#endif /* CONFIG_MV_GATEWAY */ + +} + +/* Get the count value for a rule that matches the given SIP, DIP */ +MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *pRule; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + while(pRule) + { + /* look for a matching rule */ + if( (pRule->routingInfo.dstIp == dstIp) && + (pRule->routingInfo.srcIp == srcIp) ) + { + return pRule->mgmtInfo.new_count; + } + pRule = pRule->next; + } + return 0; +} + +MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *pRule; + + hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, + (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + while(pRule) + { + if( (pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp) && + (pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp) ) { + + + pRule->routingInfo.aware_flags = pSetRule->routingInfo.aware_flags; +#ifdef MV_FP_DEBUG + mvOsPrintf("Update FP aware: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash0x%x, flags=0x%x\n", + MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), + hash_tr, pSetRule->routingInfo.aware_flags); +#endif + return MV_OK; + } + pRule = pRule->next; + } +#ifdef MV_FP_DEBUG + mvOsPrintf("FP aware NOT found: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%x, flags=0x%x\n", + MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), + hash_tr, pSetRule->routingInfo.aware_flags); +#endif + return MV_NOT_FOUND; +} + +/* Set a Routing Rule: create a new rule or update an existing rule */ +/* in the Routing + ARP information table */ +MV_STATUS mvFpRuleSet(MV_FP_RULE *pSetRule) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *pRule, *pNewRule; + + hash = mv_jhash_3words(pSetRule->routingInfo.dstIp, pSetRule->routingInfo.srcIp, + (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + while(pRule) + { + if( (pRule->routingInfo.srcIp == pSetRule->routingInfo.srcIp && + pRule->routingInfo.dstIp == pSetRule->routingInfo.dstIp) ) { + + mvFpRuleCopy(pRule, pSetRule); + nfpRuleUpdateCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("UpdNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x\n", + nfpRuleUpdateCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), hash_tr); +#endif + return MV_OK; + } + pRule = pRule->next; + } + + /* Allocate new entry */ + pNewRule = mvOsMalloc(sizeof(MV_FP_RULE)); + if(pNewRule == NULL) + { + mvOsPrintf("mvFpRuleSet: Can't allocate new rule\n"); + return MV_FAIL; + } + + mvFpRuleCopy(pNewRule, pSetRule); + pNewRule->next = NULL; + + if(ruleDb[hash_tr].ruleChain == NULL) + ruleDb[hash_tr].ruleChain = pNewRule; + else { + pRule = ruleDb[hash_tr].ruleChain; + while (pRule->next != NULL) + pRule = pRule->next; + pRule->next = pNewRule; + } + nfpRuleSetCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("SetNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x, aware=0x%02x\n", + nfpRuleSetCount, MV_IP_QUAD(pSetRule->routingInfo.dstIp), + MV_IP_QUAD(pSetRule->routingInfo.srcIp), + hash_tr, pSetRule->routingInfo.aware_flags); +#endif + return MV_OK; +} + +/* Delete a specified rule from the Routing + ARP information table */ +MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE *currRule, *prevRule; + + nfpRuleDeleteCount++; + hash = mv_jhash_3words(rule->routingInfo.dstIp, rule->routingInfo.srcIp, + (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + prevRule = NULL; + for (currRule = ruleDb[hash_tr].ruleChain; + currRule != NULL; + prevRule = currRule, currRule = currRule->next) + { + if( (currRule->routingInfo.srcIp == rule->routingInfo.srcIp) && + (currRule->routingInfo.dstIp == rule->routingInfo.dstIp) ) + { + if (prevRule == NULL) + ruleDb[hash_tr].ruleChain = currRule->next; + else + prevRule->next = currRule->next; +#ifdef MV_FP_DEBUG + mvOsPrintf("DelNFP_%03u: DIP=%u.%u.%u.%u, SIP=%u.%u.%u.%u, hash=0x%04x\n", + nfpRuleDeleteCount, MV_IP_QUAD(currRule->routingInfo.dstIp), + MV_IP_QUAD(currRule->routingInfo.srcIp), hash_tr); +#endif + mvOsFree(currRule); + return MV_OK; + } + } + return MV_NOT_FOUND; +} + +/* Find and return the first matching rule in the Routing + ARP information table */ +static INLINE MV_FP_RULE* mvFpRuleFind(MV_U32 dstIp, MV_U32 srcIp) +{ + MV_U32 hash, hash_tr; + MV_FP_RULE* pRule; + int count = 0; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)0, fp_ip_jhash_iv); + hash_tr = hash & (ruleDbSize - 1); + + pRule = ruleDb[hash_tr].ruleChain; + + while(pRule) + { + /* look for a matching rule */ + if( (pRule->routingInfo.dstIp == dstIp) && + (pRule->routingInfo.srcIp == srcIp) ) + { + FASTPATH_STAT( ip_hash_depth[count]++); + pRule->mgmtInfo.new_count++; + return pRule; + } + pRule = pRule->next; + count++; + } + return NULL; +} + +int mvFpProcess(MV_U8* pData, MV_IP_HEADER* pIpHdr, MV_FP_STATS* pFpStats) +{ + MV_FP_RULE *pFpRoute; + MV_U32 dip, sip; +#ifdef CONFIG_MV_ETH_FP_NAT_SUPPORT + MV_U8 proto; + MV_U16 srcPort, dstPort; + MV_FP_NAT_RULE *pDnatRule, *pSnatRule; +#endif + MV_U8* pEthHeader = pData + ETH_MV_HEADER_SIZE; + + FASTPATH_STAT( pFpStats->process++ ); + + /* Check MAC address: + * WAN - non-promiscous mode. + * Unicast packets - NFP, + * Multicast, Broadcast - Linux + * LAN - Promiscous mode. + * LAN Unicast MAC - NFP, + * Multicast, Broadcast, Unknown Unicast - Linux + */ + if(pEthHeader[0] & 0x1) + { + /* Go to Linux IP stack */ + FASTPATH_STAT( pFpStats->multicast++); + return -1; + } + + /* Check TTL value */ + if(pIpHdr->ttl <= 1) + { + /* TTL expired */ + FASTPATH_STAT( pFpStats->ip_ttl_expired++ ); + return -1; + } + + dip = pIpHdr->dstIP; + sip = pIpHdr->srcIP; +#ifdef CONFIG_MV_ETH_FP_NAT_SUPPORT + proto = mvFpNatPortsGet(pIpHdr, &dstPort, &srcPort); + if(proto == MV_IP_PROTO_NULL) + { + /* NAT not supported for this protocol */ + FASTPATH_STAT( pFpStats->nat_bad_proto++ ); + pDnatRule = NULL; + } + else + { + /* Lookup NAT database accordingly with 5 tuple key */ + pDnatRule = mvFpNatRuleFind(dip, sip, proto, dstPort, srcPort); + } + if(pDnatRule != NULL) + { + if(pDnatRule->flags & MV_FP_DIP_CMD_MAP) + { + dip = pDnatRule->newIp; + } + if(pDnatRule->flags & MV_FP_DPORT_CMD_MAP) + { + dstPort = pDnatRule->newPort; + } + } + else + { + FASTPATH_STAT( pFpStats->dnat_not_found++ ); + } + +#endif /* CONFIG_MV_ETH_FP_NAT_SUPPORT */ + + pFpRoute = mvFpRuleFind(dip, sip); + if(pFpRoute == NULL) + { + /* IP Routing rule is not found: go to Linux IP stack */ + FASTPATH_STAT( pFpStats->ip_not_found++ ); + return -1; + } + FASTPATH_STAT(pFpStats->ip_found++); + +#ifdef CONFIG_MV_ETH_FP_NAT_SUPPORT + if( (pDnatRule != NULL) && (pDnatRule->flags & MV_FP_DNAT_CMD_MAP) ) + { + FASTPATH_STAT( pFpStats->dnat_found++ ); + pSnatRule = mvFpNatRuleFind(dip, sip, proto, dstPort, srcPort); + } + else + { + pSnatRule = pDnatRule; + } + + if( (pSnatRule != NULL) && (pSnatRule->flags & MV_FP_SNAT_CMD_MAP) ) + { + FASTPATH_STAT( pFpStats->snat_found++ ); + } + else + { + FASTPATH_STAT( pFpStats->snat_not_found++ ); + } + + /* Check IP awareness */ + if( (pFpRoute->routingInfo.aware_flags & MV_FP_DIP_CMD_MAP) && + (pDnatRule == NULL) ) + { + FASTPATH_STAT( pFpStats->dnat_aware++ ); + return -1; + } + + if( (pFpRoute->routingInfo.aware_flags & MV_FP_SIP_CMD_MAP) && + (pSnatRule == NULL) ) + { + FASTPATH_STAT( pFpStats->snat_aware++ ); + return -1; + } + + /* Update packet accordingly with NAT rules */ + if( (pDnatRule != NULL) || (pSnatRule != NULL) ) + { + mvFpNatPktUpdate(pIpHdr, pDnatRule, pSnatRule); + } +#endif /* CONFIG_MV_ETH_FP_NAT_SUPPORT */ + + if( (unsigned int)pEthHeader & 0x2) + { + *((MV_U16*)(pEthHeader)) = *(MV_U16*)(&pFpRoute->routingInfo.dstMac[0]); + *((MV_U32*)(pEthHeader + 2)) = *(MV_U32*)(&pFpRoute->routingInfo.dstMac[2]); + *((MV_U32*)(pEthHeader + 2 + 4)) = *(MV_U32*)(&pFpRoute->routingInfo.srcMac[0]); + *((MV_U16*)(pEthHeader + 2 + 4 + 4)) = *(MV_U16*)(&pFpRoute->routingInfo.srcMac[4]); + } + else + { + memcpy(pEthHeader, pFpRoute->routingInfo.dstMac, MV_MAC_ADDR_SIZE*2); + } + pIpHdr->ttl--; +#if defined(CONFIG_MV_GTW_HEADER_MODE) + memcpy(pData, &(pFpRoute->routingInfo.pktHdr.mvHeader.header), ETH_MV_HEADER_SIZE); +#endif + mvOsCacheLineFlushInv(pPortCtrl->osHandle, pData); + mvOsCacheLineFlushInv(pPortCtrl->osHandle, pData + CPU_D_CACHE_LINE_SIZE); + + return pFpRoute->routingInfo.outIfIndex; +} + +void mvFpStatsPrint(MV_FP_STATS *pFpStats) +{ +#ifdef MV_FP_STATISTICS + int i = 0; + + mvOsPrintf( "\n====================================================\n" ); + mvOsPrintf( "fast path statistics"); + mvOsPrintf( "\n-------------------------------\n" ); + + mvOsPrintf( "fast_path_parsing.............%10u\n", pFpStats->parsing ); + mvOsPrintf( "fast_path_process.............%10u\n", pFpStats->process ); + mvOsPrintf( "fast_path_multicast...........%10u\n", pFpStats->multicast ); + mvOsPrintf( "fast_path_non_ip..............%10u\n", pFpStats->non_ip ); + mvOsPrintf( "fast_path_vlan_tagged.........%10u\n", pFpStats->vlan_tagged ); + mvOsPrintf( "fast_path_ip_not_found........%10u\n", pFpStats->ip_not_found ); + mvOsPrintf( "fast_path_ttl_expired.........%10u\n", pFpStats->ip_ttl_expired ); + mvOsPrintf( "fast_path_ip_found............%10u\n", pFpStats->ip_found ); + +#ifdef CONFIG_MV_ETH_FP_NAT_SUPPORT + mvOsPrintf( "fp_nat_bad_proto..............%10u\n", pFpStats->nat_bad_proto); + mvOsPrintf( "fp_nat_dnat_found.............%10u\n", pFpStats->dnat_found); + mvOsPrintf( "fp_nat_snat_found.............%10u\n", pFpStats->snat_found); + mvOsPrintf( "fp_nat_dnat_not_found.........%10u\n", pFpStats->dnat_not_found); + mvOsPrintf( "fp_nat_snat_not_found.........%10u\n", pFpStats->snat_not_found); + mvOsPrintf( "fp_nat_dnat_aware.............%10u\n", pFpStats->dnat_aware); + mvOsPrintf( "fp_nat_snat_aware.............%10u\n", pFpStats->snat_aware); +#endif /* CONFIG_MV_ETH_FP_NAT_SUPPORT */ + + mvOsPrintf("\nHASH Depth IP stats\n"); + for(i=0; i<=ETH_FP_MAX_HASH_DEPTH; i++) + { + if(ip_hash_depth[i] != 0) + { + mvOsPrintf("%d depth - %u times\n", i, ip_hash_depth[i]); + ip_hash_depth[i] = 0; + } + } + +#ifdef CONFIG_MV_ETH_FP_NAT_SUPPORT + mvOsPrintf("\nHASH Depth NAT stats\n"); + for(i=0; i<=ETH_FP_MAX_HASH_DEPTH; i++) + { + if(nat_hash_depth[i] != 0) + { + mvOsPrintf("%d depth - %u times\n", i, nat_hash_depth[i]); + nat_hash_depth[i] = 0; + } + } +#endif /* CONFIG_MV_ETH_FP_NAT_SUPPORT */ + + memset(pFpStats, 0, sizeof(MV_FP_STATS)); +#endif /* MV_FP_STATISTICS */ + mvOsPrintf("\n"); + mvOsPrintf("nfpRuleSetCount=%u, nfpRuleUpdateCount=%u, nfpRuleDeleteCount=%u\n", + nfpRuleSetCount, nfpRuleUpdateCount, nfpRuleDeleteCount); + +#ifdef CONFIG_MV_ETH_FP_NAT_SUPPORT + mvOsPrintf("\n"); + mvOsPrintf("natRuleSetCount=%u, natRuleUpdateCount=%u, natRuleDeleteCount=%u\n", + natRuleSetCount, natRuleUpdateCount, natRuleDeleteCount); +#endif /* CONFIG_MV_ETH_FP_NAT_SUPPORT */ +} + diff --git a/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.h b/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.h new file mode 100644 index 0000000..6e47286 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFastPath.h @@ -0,0 +1,415 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvFastPath.h - Header File for Marvell NFP (Routing and NAT) +* +* DESCRIPTION: +* This header file contains macros, typedefs and function declarations +* specific to the Marvell Network Fast Processing (Routing and NAT). +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __mvFastPath_h__ +#define __mvFastPath_h__ + +/* includes */ +#include "mvTypes.h" +#include "mvCommon.h" +#include "mvStack.h" +#include "mv802_3.h" +#include "mvSysHwConfig.h" +#include "ethfp/mvEth.h" + +/* defines */ +#define ETH_FP_MAX_HASH_DEPTH 8 + +/* uncomment to open some debug prints on adding and updating Fast Path rules */ +/* #define MV_FP_DEBUG */ + +#ifdef MV_FP_STATISTICS +# define FASTPATH_STAT(CODE) CODE; +#else +# define FASTPATH_STAT(CODE) +#endif + +/* enumerations */ +typedef enum { + MV_FP_ROUTE_CMD, /* perform fast path routing */ + MV_FP_DROP_CMD, /* drop packet */ + MV_FP_TO_STACK_CMD, /* pass packet to linux stack */ + MV_FP_DIP_CMD, /* replace DIP */ + MV_FP_SIP_CMD, /* replace SIP */ + MV_FP_DPORT_CMD, /* replace DPORT */ + MV_FP_SPORT_CMD, /* replace SPORT */ + +} MV_FP_CMD_TYPE; + +#define MV_FP_NULL_BINDING 0 +#define MV_FP_NULL_BINDING_SET (1 << MV_FP_ROUTE_CMD) + +#define MV_FP_DIP_CMD_MAP (1 << MV_FP_DIP_CMD) +#define MV_FP_DPORT_CMD_MAP (1 << MV_FP_DPORT_CMD) +#define MV_FP_DNAT_CMD_MAP (MV_FP_DIP_CMD_MAP | MV_FP_DPORT_CMD_MAP) + +#define MV_FP_SIP_CMD_MAP (1 << MV_FP_SIP_CMD) +#define MV_FP_SPORT_CMD_MAP (1 << MV_FP_SPORT_CMD) +#define MV_FP_SNAT_CMD_MAP (MV_FP_SIP_CMD_MAP | MV_FP_SPORT_CMD_MAP) + +typedef enum { + MV_FP_STATIC_RULE, /* a static rule created by the user */ + MV_FP_DYNAMIC_RULE /* a dynamic rule */ + +} MV_FP_RULE_TYPE; + +/* structure definitions (used by the NFP Manager and the NFP Database)*/ +typedef struct { + MV_FP_CMD_TYPE actionType; + MV_U32 old_count; + int new_count; + MV_FP_RULE_TYPE ruleType; + int dnat_aware_refcnt; + int snat_aware_refcnt; + +} MV_FP_RULE_MGMT_INFO; + +typedef struct { + MV_U32 dstIp; + MV_U32 srcIp; + MV_U32 defGtwIp; + +#ifdef CONFIG_MV_GATEWAY + MV_ETH_PKT_HDR pktHdr; +#endif /* CONFIG_MV_GATEWAY */ + + MV_U8 reserved; + MV_U8 aware_flags; + /* dstMac should be 2 byte aligned */ + MV_U8 dstMac[MV_MAC_ADDR_SIZE]; + MV_U8 srcMac[MV_MAC_ADDR_SIZE]; + MV_U8 inIfIndex; /* Linux interface index */ + MV_U8 outIfIndex; /* Linux interface index */ + +} MV_FP_RULE_ROUTING_INFO; + +typedef struct _mv_fp_rule { + struct _mv_fp_rule *next; + + MV_FP_RULE_MGMT_INFO mgmtInfo; + MV_FP_RULE_ROUTING_INFO routingInfo; + +} MV_FP_RULE; + +struct ruleHashBucket { + MV_FP_RULE *ruleChain; /* This is an entry in the rule hash table. */ + + /* Add additional fields (such as a lock) here if required */ +}; + +#define MV_JHASH_MIX(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define MV_JHASH_GOLDEN_RATIO 0x9e3779b9 + +extern MV_U32 fp_ip_jhash_iv; +extern MV_U32 natRuleUpdateCount, natRuleSetCount, natRuleDeleteCount; + +static INLINE MV_U32 mv_jhash_3words(MV_U32 a, MV_U32 b, MV_U32 c, MV_U32 initval) +{ + a += MV_JHASH_GOLDEN_RATIO; + b += MV_JHASH_GOLDEN_RATIO; + c += initval; + MV_JHASH_MIX(a, b, c); + + return c; +} + +typedef struct _mv_fp_nat_rule { + struct _mv_fp_nat_rule *next; + MV_U32 old_count; + MV_U32 new_count; + + /* Original packet information */ + /* Fields will contain invalid values if they are irrelevant */ + MV_U32 srcIp; + MV_U32 dstIp; + MV_U16 srcPort; + MV_U16 dstPort; + MV_U8 proto; + + /* NAT information */ + MV_U8 flags; + MV_U32 newIp; + MV_U16 newPort; + +} MV_FP_NAT_RULE; + +struct natRuleHashBucket { + MV_FP_NAT_RULE *natRuleChain; /* This is an entry in the NAT rule hash table. */ + + /* Add additional fields (such as a lock) here if required */ +}; + +extern MV_U32 nat_hash_depth[]; + +extern struct natRuleHashBucket *natRuleDb; +extern MV_U32 natRuleDbSize; + +typedef struct +{ + MV_U32 parsing, process, multicast, non_ip, vlan_tagged; + MV_U32 ip_not_found, ip_ttl_expired, ip_found; + +#ifdef CONFIG_MV_ETH_FP_NAT_SUPPORT + MV_U32 nat_bad_proto; + MV_U32 dnat_aware; + MV_U32 snat_aware; + MV_U32 dnat_found; + MV_U32 snat_found; + MV_U32 dnat_not_found; + MV_U32 snat_not_found; +#endif + +} MV_FP_STATS; + +static INLINE MV_IP_HEADER* mvFpParsing(MV_PKT_INFO *pPktInfo, MV_FP_STATS* pFpStats) +{ + MV_U8 *pData; + MV_IP_HEADER *pIpHdr; + MV_U32 tx_status; + + pData = (MV_U8*)pPktInfo->pFrags[0].bufVirtPtr + ETH_MV_HEADER_SIZE; + + FASTPATH_STAT( pFpStats->parsing++ ); + + /* Check LLC/SNAP and IP header */ + if( ((pPktInfo->status & ETH_RX_NOT_LLC_SNAP_FORMAT_MASK) == 0) || + ((pPktInfo->status & ETH_RX_IP_HEADER_OK_MASK) == 0) || + (pPktInfo->fragIP) ) + { + /* Non IP packet: go to Linux IP stack */ + FASTPATH_STAT( pFpStats->non_ip++ ); + return NULL; + } + tx_status = ( ETH_TX_GENERATE_IP_CHKSUM_MASK + | ETH_TX_IP_NO_FRAG + | (5 << ETH_TX_IP_HEADER_LEN_OFFSET) ); + + /* Calculate start of IP header */ + if( (pPktInfo->status & ETH_RX_VLAN_TAGGED_FRAME_MASK) ) + { + FASTPATH_STAT(pFpStats->vlan_tagged++); + pIpHdr = (MV_IP_HEADER*)(pData + sizeof(MV_802_3_HEADER) + MV_VLAN_HLEN); + tx_status |= ETH_TX_VLAN_TAGGED_FRAME_MASK; + } + else + { + pIpHdr = (MV_IP_HEADER*)(pData + sizeof(MV_802_3_HEADER)); + } + + if( (pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_TCP_TYPE ) + { + tx_status |= (ETH_TX_L4_TCP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK); + } + else if( (pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_UDP_TYPE ) + { + tx_status |= (ETH_TX_L4_UDP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK); + } + + pPktInfo->status = tx_status; + + return pIpHdr; +} + +/* Find and return the first matching rule */ +static INLINE MV_FP_NAT_RULE* mvFpNatRuleFind(MV_U32 dstIp, MV_U32 srcIp, + MV_U8 proto, MV_U16 dport, MV_U16 sport) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE* pNatRule; + int count = 0; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)((dport << 16) | sport), + (MV_U32)((fp_ip_jhash_iv << 8) | proto)); + hash_tr = hash & (natRuleDbSize - 1); +/* + mvOsPrintf("mvFpNatRuleFind: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%08x (0x%x)\n", + dstIp, srcIp, proto, dport, sport, hash, hash_tr); +*/ + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while(pNatRule) + { + /* look for a matching rule */ + if( (pNatRule->dstIp == dstIp) && + (pNatRule->srcIp == srcIp) && + (pNatRule->proto == proto) && + (pNatRule->dstPort == dport) && + (pNatRule->srcPort == sport) ) + { + FASTPATH_STAT( nat_hash_depth[count]++); + pNatRule->new_count++; + return pNatRule; + } + pNatRule = pNatRule->next; + count++; + } + return NULL; +} + + +/* function headers: */ + +/* Initialize NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbInit(MV_U32 dbSize); + +/* Clear NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbClear(void); + +/* Free Rule Database memory */ +void mvFpRuleDbDestroy(void); + +/* Print NFP Rule Database (Routing + ARP information table) */ +MV_STATUS mvFpRuleDbPrint(void); + +/* Copy all the information from src_rule to new_rule */ +/* Warning - doesn't perform any checks on memory, just copies */ +/* count is set to zero in new_rule */ +/* Note: the next pointer is not updated . */ +void mvFpRuleCopy(MV_FP_RULE *newRule, const MV_FP_RULE *srcRule); + +/* Get the maximum count value for a rule with srcIp == given ip */ +MV_U32 mvFpMaxArpCountGet(MV_U32 ip); + +/* Get the count value for a rule that matches the given SIP, DIP */ +MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp); + +/* Set a Routing Rule: create a new rule or update an existing rule */ +/* in the Routing + ARP information table */ +MV_STATUS mvFpRuleSet(MV_FP_RULE *rule); + +/* Delete a specified rule from the Routing + ARP information table */ +MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule); + +/* Print a Rule */ +void mvFpRulePrint(const MV_FP_RULE *rule); + +/* Enable NFP */ +void mvFpEnable(void); + +/* Give all packets to Linux IP stack */ +void mvFpDisable(void); + +MV_STATUS mvFpInit(void); +int mvFpProcess(MV_U8* pData, MV_IP_HEADER* pIpHdr, MV_FP_STATS* pFpStats); +void mvFpStatsPrint(MV_FP_STATS *pFpStats); + +/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbInit(MV_U32 dbSize); + +/* Clear NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbClear(void); + +/* Free NAT Database memory */ +void mvFpNatDbDestroy(void); + +/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *natRule); + +MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule); + +/* Delete a specified NAT rule from the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule); + +/* Get the count value for a NAT rule */ +MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto); + +/* Print NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbPrint(void); + +/* Print a NAT Rule */ +void mvFpNatRulePrint(const MV_FP_NAT_RULE *rule); + +/* Extract dstPort and srcPort values from the packet */ +MV_U8 mvFpNatPortsGet(MV_IP_HEADER* pIpHdr, MV_U16* pDstPort, MV_U16* pSrcPort); + +int mvFpNatPktUpdate(MV_IP_HEADER* pIpHdr, MV_FP_NAT_RULE* pDnatRule, MV_FP_NAT_RULE* pSnatRule); + +#endif /* __mvFastPath_h__ */ + + diff --git a/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFpNat.c b/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFpNat.c new file mode 100644 index 0000000..d10ab4e --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/fast_path/mvFpNat.c @@ -0,0 +1,450 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "mvTypes.h" +#include "mvOs.h" +#include "mvStack.h" +#include "mvDebug.h" +#include "ethfp/fast_path/mvFastPath.h" +#include "ethfp/mvEth.h" + + +struct natRuleHashBucket *natRuleDb; +MV_U32 natRuleDbSize; + +MV_U32 natRuleUpdateCount = 0; +MV_U32 natRuleSetCount = 0; +MV_U32 natRuleDeleteCount = 0; + +/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbInit(MV_U32 dbSize) +{ + natRuleDb = (struct natRuleHashBucket *)mvOsMalloc(sizeof(struct natRuleHashBucket)*dbSize); + if (natRuleDb == NULL) { + mvOsPrintf("NFP NAT Rule DB: Not Enough Memory\n"); + return MV_NO_RESOURCE; + } + natRuleDbSize = dbSize; + memset(natRuleDb, 0, sizeof(struct natRuleHashBucket)*natRuleDbSize); + + natRuleSetCount = natRuleDeleteCount = natRuleUpdateCount = 0; + + mvOsPrintf("mvFpNatDb (%p): %d entries, %d bytes\n", + natRuleDb, natRuleDbSize, sizeof(struct natRuleHashBucket)*natRuleDbSize); + + return MV_OK; +} + +/* Clear NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbClear(void) +{ + MV_U32 i = 0; + MV_FP_NAT_RULE *currRule; + MV_FP_NAT_RULE *tmpRule; + + if (natRuleDb == NULL) + return MV_NOT_INITIALIZED; + + for (i = 0; i < natRuleDbSize; i++) { + currRule = natRuleDb[i].natRuleChain; + while (currRule != NULL) { + tmpRule = currRule; + currRule = currRule->next; + mvOsFree(tmpRule); + } + natRuleDb[i].natRuleChain = NULL; + } + return MV_OK; +} + +/* Free NAT Database memory */ +void mvFpNatDbDestroy(void) +{ + if (natRuleDb != NULL) + mvOsFree(natRuleDb); +} + +static void mvFpNatRuleUpdate(MV_FP_NAT_RULE *dstRule, const MV_FP_NAT_RULE *srcRule) +{ + dstRule->flags = srcRule->flags; + dstRule->newIp = srcRule->newIp; + dstRule->newPort = srcRule->newPort; + dstRule->new_count = srcRule->new_count; + dstRule->old_count = srcRule->old_count; +} + +/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *pSetRule) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE *pNatRule, *pNewRule; + + hash = mv_jhash_3words(pSetRule->dstIp, pSetRule->srcIp, + (MV_U32)((pSetRule->dstPort << 16) | pSetRule->srcPort), + (MV_U32)((fp_ip_jhash_iv << 8) | pSetRule->proto)); + hash_tr = hash & (natRuleDbSize - 1); + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while(pNatRule) + { + /* look for a matching rule */ + if( (pNatRule->dstIp == pSetRule->dstIp) && + (pNatRule->srcIp == pSetRule->srcIp) && + (pNatRule->proto == pSetRule->proto) && + (pNatRule->dstPort == pSetRule->dstPort) && + (pNatRule->srcPort == pSetRule->srcPort) ) + { + /* update rule */ + mvFpNatRuleUpdate(pNatRule, pSetRule); + natRuleUpdateCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("UpdNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n", + natRuleUpdateCount, pNatRule->dstIp, pNatRule->srcIp, pNatRule->proto, + MV_16BIT_BE(pNatRule->dstPort), MV_16BIT_BE(pNatRule->srcPort), hash_tr, pNatRule->flags); +#endif + return MV_OK; + } + pNatRule = pNatRule->next; + } + /* Allocate new entry */ + pNewRule = mvOsMalloc(sizeof(MV_FP_NAT_RULE)); + if(pNewRule == NULL) + { + mvOsPrintf("mvFpNatRuleSet: Can't allocate new rule\n"); + return MV_FAIL; + } + + memcpy(pNewRule, pSetRule, sizeof(*pNewRule)); + pNewRule->next = NULL; + + if(natRuleDb[hash_tr].natRuleChain == NULL) + { + natRuleDb[hash_tr].natRuleChain = pNewRule; + } + else + { + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while (pNatRule->next != NULL) + pNatRule = pNatRule->next; + + pNatRule->next = pNewRule; + } + natRuleSetCount++; + +#ifdef MV_FP_DEBUG + mvOsPrintf("SetNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x, flags=0x%02x\n", + natRuleSetCount, pNewRule->dstIp, pNewRule->srcIp, pNewRule->proto, + MV_16BIT_BE(pNewRule->dstPort), MV_16BIT_BE(pNewRule->srcPort), hash_tr, pNewRule->flags); +#endif + return MV_OK; +} + +/* Delete a specified NAT rule from the SNAT + DNAT table */ +MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE *currRule, *prevRule; + + natRuleDeleteCount++; + + hash = mv_jhash_3words(natRule->dstIp, natRule->srcIp, + (MV_U32)((natRule->dstPort << 16) | natRule->srcPort), + (MV_U32)((fp_ip_jhash_iv << 8) | natRule->proto)); + hash_tr = hash & (natRuleDbSize - 1); + + prevRule = NULL; + for (currRule = natRuleDb[hash_tr].natRuleChain; + currRule != NULL; + prevRule = currRule, currRule = currRule->next) + { + if (currRule->srcIp == natRule->srcIp && + currRule->dstIp == natRule->dstIp && + currRule->srcPort == natRule->srcPort && + currRule->dstPort == natRule->dstPort && + currRule->proto == natRule->proto ) + { + if (prevRule == NULL) + natRuleDb[hash_tr].natRuleChain = currRule->next; + else + prevRule->next = currRule->next; + +#ifdef MV_FP_DEBUG + mvOsPrintf("DelNAT_%03u: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%04x\n", + natRuleDeleteCount, currRule->dstIp, currRule->srcIp, currRule->proto, + MV_16BIT_BE(currRule->dstPort), MV_16BIT_BE(currRule->srcPort), hash_tr); +#endif + mvOsFree(currRule); + return MV_OK; + } + } + return MV_NOT_FOUND; +} + +/* Check that protocol supported for FP NAT and extract srcPort and dstPort + * (or their equivalents) from the packet. + */ +MV_U8 mvFpNatPortsGet(MV_IP_HEADER* pIpHdr, MV_U16* pDstPort, MV_U16* pSrcPort) +{ + MV_U8 proto = pIpHdr->protocol; + MV_UDP_HEADER *pUdpHdr; + MV_TCP_HEADER *pTcpHdr; + MV_ICMP_ECHO_HEADER *pIcmpHdr; + + switch(proto) + { + case MV_IP_PROTO_TCP: + pTcpHdr = (MV_TCP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + *pDstPort = pTcpHdr->dest; + *pSrcPort = pTcpHdr->source; + break; + + case MV_IP_PROTO_UDP: + pUdpHdr = (MV_UDP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + *pDstPort = pUdpHdr->dest; + *pSrcPort = pUdpHdr->source; + break; + + case MV_IP_PROTO_ICMP: + pIcmpHdr = (MV_ICMP_ECHO_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + if( (pIcmpHdr->type == MV_ICMP_ECHO) || (pIcmpHdr->type == MV_ICMP_ECHOREPLY) ) + { + *pDstPort = (pIcmpHdr->code << 8) | (pIcmpHdr->type); + *pSrcPort = pIcmpHdr->id; + } + else + { + /* Do NAT for IP + protocol only (without ports) */ + *pDstPort = 0; + *pSrcPort = 0; + } + break; + + case MV_IP_PROTO_ZERO_HOP: + /* Do NAT for IP + protocol only (without ports) */ + *pDstPort = 0; + *pSrcPort = 0; + break; + + /* Other protocols supporting NAT only without ports + * case ???????: + * case ???????: + * *pDstPort = 0; + * *pSrcPort = 0; + * break + * + */ + + default: + /* Skip NAT processing at all */ + proto = MV_IP_PROTO_NULL; + } + return proto; +} + +int mvFpNatPktUpdate(MV_IP_HEADER* pIpHdr, MV_FP_NAT_RULE* pDnatRule, MV_FP_NAT_RULE* pSnatRule) +{ + MV_UDP_HEADER *pUdpHdr; + MV_TCP_HEADER *pTcpHdr; + MV_ICMP_ECHO_HEADER *pIcmpHdr; + int hdr_size = 0; + MV_U16 *pDstPort=NULL, *pSrcPort=NULL; + + switch(pIpHdr->protocol) + { + case MV_IP_PROTO_TCP: + pTcpHdr = (MV_TCP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + pDstPort = &pTcpHdr->dest; + pSrcPort = &pTcpHdr->source; + hdr_size = sizeof(MV_TCP_HEADER); + break; + + case MV_IP_PROTO_UDP: + pUdpHdr = (MV_UDP_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + pDstPort = &pUdpHdr->dest; + pSrcPort = &pUdpHdr->source; + hdr_size = sizeof(MV_UDP_HEADER); + break; + + case MV_IP_PROTO_ICMP: + pIcmpHdr = (MV_ICMP_ECHO_HEADER*)((unsigned)pIpHdr + sizeof(MV_IP_HEADER)); + if( (pIcmpHdr->type == MV_ICMP_ECHO) || (pIcmpHdr->type == MV_ICMP_ECHOREPLY) ) + { + pDstPort = &pIcmpHdr->id; + pSrcPort = &pIcmpHdr->id; + hdr_size = sizeof(MV_ICMP_ECHO_HEADER); + } + else + { + mvOsPrintf("Wrong ICMP type: 0x%x\n", pIcmpHdr->type & 0xFF); + } + break; + + case MV_IP_PROTO_ZERO_HOP: + /* Do nothing - only IP addresses are updated for this protocol */ + break; + + default: + mvOsPrintf("Unexpected IP protocol: 0x%x\n", + pIpHdr->protocol); + } + if(pDnatRule != NULL) + { + if(pDnatRule->flags & MV_FP_DIP_CMD_MAP) + pIpHdr->dstIP = pDnatRule->newIp; + if( (pDnatRule->flags & MV_FP_DPORT_CMD_MAP) && + (pDstPort != NULL) ) + *pDstPort = pDnatRule->newPort; + } + + if(pSnatRule != NULL) + { + if(pSnatRule->flags & MV_FP_SIP_CMD_MAP) + pIpHdr->srcIP = pSnatRule->newIp; + + if( (pSnatRule->flags & MV_FP_SPORT_CMD_MAP) && + (pSrcPort != NULL) ) + *pSrcPort = pSnatRule->newPort; + } + return hdr_size; +} + +/* Print a NFP NAT Rule */ +void mvFpNatRulePrint(const MV_FP_NAT_RULE *rule) +{ + /* Note: some of the fields in the NAT rule may contain invalid values */ + mvOsPrintf("Original packet: "); + mvOsPrintf("SIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->srcIp)), + mvOsPrintf(", DIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->dstIp)), + mvOsPrintf(", SPort=%d", MV_16BIT_BE(rule->srcPort)); + mvOsPrintf(", DPort=%d", MV_16BIT_BE(rule->dstPort)); + mvOsPrintf("\nNAT Info: "); + mvOsPrintf("count=%u, flags=0x%x", rule->new_count, rule->flags); + mvOsPrintf(", newIP="); + mvDebugPrintIpAddr(MV_32BIT_BE(rule->newIp)); + mvOsPrintf(", newPort=%d", MV_16BIT_BE(rule->newPort)); + mvOsPrintf("\n"); +} + +/* Print NFP NAT Rule Database (SNAT + DNAT table) */ +MV_STATUS mvFpNatDbPrint(void) +{ + MV_U32 count, i = 0; + MV_FP_NAT_RULE *currRule; + + mvOsPrintf("\nPrinting NFP NAT Rule Database: \n"); + count = 0; + for (i=0; iflags != MV_FP_NULL_BINDING) || (currRule->new_count > 0) ) + { + mvOsPrintf("%03u: Rule=%p, Next=%p\n", count, currRule, currRule->next); + mvFpNatRulePrint(currRule); + } + currRule = currRule->next; + count++; + } + } + return MV_OK; +} + +/* Get the count value for a NAT rule */ +MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto) +{ + MV_U32 hash, hash_tr; + MV_FP_NAT_RULE *pNatRule; + + hash = mv_jhash_3words(dstIp, srcIp, (MV_U32)((dstPort << 16) | srcPort), + (MV_U32)((fp_ip_jhash_iv << 8) | proto)); + hash_tr = hash & (natRuleDbSize - 1); + pNatRule = natRuleDb[hash_tr].natRuleChain; + + while(pNatRule) + { + /* look for a matching rule */ + if( (pNatRule->dstIp == dstIp) && + (pNatRule->srcIp == srcIp) && + (pNatRule->proto == proto) && + (pNatRule->dstPort == dstPort) && + (pNatRule->srcPort == srcPort) ) + { + return pNatRule->new_count; + } + pNatRule = pNatRule->next; + } + return 0; +} + diff --git a/board/mv_feroceon/mv_hal/ethfp/gbe/mvEth.c b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEth.c new file mode 100644 index 0000000..c488ddc --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEth.c @@ -0,0 +1,2944 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEth.c - Marvell's Gigabit Ethernet controller low level driver +* +* DESCRIPTION: +* This file introduce OS independent APIs to Marvell's Gigabit Ethernet +* controller. This Gigabit Ethernet Controller driver API controls +* 1) Operations (i.e. port Init, Finish, Up, Down, PhyReset etc'). +* 2) Data flow (i.e. port Send, Receive etc'). +* 3) MAC Filtering functions (ethSetMcastAddr, ethSetRxFilterMode, etc.) +* 4) MIB counters support (ethReadMibCounter) +* 5) Debug functions (ethPortRegs, ethPortCounters, ethPortQueues, etc.) +* Each Gigabit Ethernet port is controlled via ETH_PORT_CTRL struct. +* This struct includes configuration information as well as driver +* internal data needed for its operations. +* +* Supported Features: +* - OS independent. All required OS services are implemented via external +* OS dependent components (like osLayer or ethOsg) +* - The user is free from Rx/Tx queue managing. +* - Simple Gigabit Ethernet port operation API. +* - Simple Gigabit Ethernet port data flow API. +* - Data flow and operation API support per queue functionality. +* - Support cached descriptors for better performance. +* - PHY access and control API. +* - Port Configuration API. +* - Full control over Special and Other Multicast MAC tables. +* +*******************************************************************************/ +/* includes */ +#include "mvTypes.h" +#include "mv802_3.h" +#include "mvDebug.h" +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "eth-phy/mvEthPhy.h" +#include "ethfp/mvEth.h" +#include "ethfp/gbe/mvEthGbe.h" +#include "cpu/mvCpu.h" + +#ifdef INCLUDE_SYNC_BARR +#include "sys/mvCpuIf.h" +#endif + +#ifdef MV_RT_DEBUG +# define ETH_DEBUG +#endif + + +/* locals */ +MV_BOOL ethDescInSram; +MV_BOOL ethDescSwCoher; + +/* This array holds the control structure of each port */ +ETH_PORT_CTRL* ethPortCtrl[MV_ETH_MAX_PORTS]; + +/* Ethernet Port Local routines */ + +static void ethInitRxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue); + +static void ethInitTxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue); + +static void ethSetUcastTable(int portNo, int queue); + +static MV_BOOL ethSetUcastAddr (int ethPortNum, MV_U8 lastNibble, int queue); +static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue); +static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue); + +static void ethFreeDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, MV_BUF_INFO* pDescBuf); +static MV_U8* ethAllocDescrMemory(ETH_PORT_CTRL* pEthPortCtrl, int size, + MV_ULONG* pPhysAddr, MV_U32 *memHandle); + +static MV_U32 mvEthMruGet(MV_U32 maxRxPktSize); +#if 0 +static void mvEthPortSgmiiConfig(int port); +#endif /* 0 */ + + +/******************************************************************************/ +/* EthDrv Initialization functions */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthInit - Initialize the Giga Ethernet unit +* +* DESCRIPTION: +* This function initialize the Giga Ethernet unit. +* 1) Configure Address decode windows of the unit +* 2) Set registers to HW default values. +* 3) Clear and Disable interrupts +* +* INPUT: NONE +* +* RETURN: NONE +* +* NOTE: this function is called once in the boot process. +*******************************************************************************/ +void mvEthHalInit(void) +{ + int port; + + /* Init static data structures */ + for (port=0; port 0) + { + isSram = MV_TRUE; + #if (INTEG_SRAM_COHER == MV_CACHE_COHER_SW) + isSwCoher = MV_TRUE; + #else + isSwCoher = MV_FALSE; + #endif + } +#endif /* ETH_DESCR_IN_SRAM */ + + if(pIsSram != NULL) + *pIsSram = isSram; + + if(pIsSwCoher != NULL) + *pIsSwCoher = isSwCoher; +} + + + +/******************************************************************************/ +/* Port Initialization functions */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthPortInit - Initialize the Ethernet port driver +* +* DESCRIPTION: +* This function initialize the ethernet port. +* 1) Allocate and initialize internal port Control structure. +* 2) Create RX and TX descriptor rings for default RX and TX queues +* 3) Disable RX and TX operations, clear cause registers and +* mask all interrupts. +* 4) Set all registers to default values and clean all MAC tables. +* +* INPUT: +* int portNo - Ethernet port number +* ETH_PORT_INIT *pEthPortInit - Ethernet port init structure +* +* RETURN: +* void* - ethernet port handler, that should be passed to the most other +* functions dealing with this port. +* +* NOTE: This function is called once per port when loading the eth module. +*******************************************************************************/ +void* mvEthPortInit(int portNo, MV_ETH_PORT_INIT *pEthPortInit) +{ + int queue, descSize; + ETH_PORT_CTRL* pPortCtrl; + + /* Check validity of parameters */ + if( (portNo >= (int)mvCtrlEthMaxPortGet()) || + (pEthPortInit->rxDefQ >= MV_ETH_RX_Q_NUM) || + (pEthPortInit->maxRxPktSize < 1518) ) + { + mvOsPrintf("EthPort #%d: Bad initialization parameters\n", portNo); + return NULL; + } + if( (pEthPortInit->rxDescrNum[pEthPortInit->rxDefQ]) == 0) + { + mvOsPrintf("EthPort #%d: rxDefQ (%d) must be created\n", + portNo, pEthPortInit->rxDefQ); + return NULL; + } + + pPortCtrl = (ETH_PORT_CTRL*)mvOsMalloc( sizeof(ETH_PORT_CTRL) ); + if(pPortCtrl == NULL) + { + mvOsPrintf("EthDrv: Can't allocate %dB for port #%d control structure!\n", + (int)sizeof(ETH_PORT_CTRL), portNo); + return NULL; + } + + memset(pPortCtrl, 0, sizeof(ETH_PORT_CTRL) ); + ethPortCtrl[portNo] = pPortCtrl; + + pPortCtrl->portState = MV_UNDEFINED_STATE; + + pPortCtrl->portNo = portNo; + + pPortCtrl->osHandle = pEthPortInit->osHandle; + + /* Copy Configuration parameters */ + pPortCtrl->portConfig.maxRxPktSize = pEthPortInit->maxRxPktSize; + pPortCtrl->portConfig.rxDefQ = pEthPortInit->rxDefQ; + pPortCtrl->portConfig.ejpMode = 0; + + for( queue=0; queuerxQueueConfig[queue].descrNum = pEthPortInit->rxDescrNum[queue]; + } + for( queue=0; queuetxQueueConfig[queue].descrNum = pEthPortInit->txDescrNum[queue]; + } + + mvEthPortDisable(pPortCtrl); + + /* Set the board information regarding PHY address */ + mvEthPhyAddrSet(pPortCtrl, mvBoardPhyAddrGet(portNo) ); + + /* Create all requested RX queues */ + for(queue=0; queuerxQueueConfig[queue].descrNum == 0) + continue; + + /* Allocate memory for RX descriptors */ + descSize = ((pPortCtrl->rxQueueConfig[queue].descrNum * ETH_RX_DESC_ALIGNED_SIZE) + + CPU_D_CACHE_LINE_SIZE); + + pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr = + ethAllocDescrMemory(pPortCtrl, descSize, + &pPortCtrl->rxQueue[queue].descBuf.bufPhysAddr, + &pPortCtrl->rxQueue[queue].descBuf.memHandle); + pPortCtrl->rxQueue[queue].descBuf.bufSize = descSize; + if(pPortCtrl->rxQueue[queue].descBuf.bufVirtPtr == NULL) + { + mvOsPrintf("EthPort #%d, rxQ=%d: Can't allocate %d bytes in %s for %d RX descr\n", + pPortCtrl->portNo, queue, descSize, + ethDescInSram ? "SRAM" : "DRAM", + pPortCtrl->rxQueueConfig[queue].descrNum); + return NULL; + } + + ethInitRxDescRing(pPortCtrl, queue); + } + /* Create TX queues */ + for(queue=0; queuetxQueueConfig[queue].descrNum == 0) + continue; + + /* Allocate memory for TX descriptors */ + descSize = ((pPortCtrl->txQueueConfig[queue].descrNum * ETH_TX_DESC_ALIGNED_SIZE) + + CPU_D_CACHE_LINE_SIZE); + + pPortCtrl->txQueue[queue].descBuf.bufVirtPtr = + ethAllocDescrMemory(pPortCtrl, descSize, + &pPortCtrl->txQueue[queue].descBuf.bufPhysAddr, + &pPortCtrl->txQueue[queue].descBuf.memHandle); + pPortCtrl->txQueue[queue].descBuf.bufSize = descSize; + if(pPortCtrl->txQueue[queue].descBuf.bufVirtPtr == NULL) + { + mvOsPrintf("EthPort #%d, txQ=%d: Can't allocate %d bytes in %s for %d TX descr\n", + pPortCtrl->portNo, queue, descSize, ethDescInSram ? "SRAM" : "DRAM", + pPortCtrl->txQueueConfig[queue].descrNum); + return NULL; + } + + ethInitTxDescRing(pPortCtrl, queue); + } + mvEthDefaultsSet(pPortCtrl); + + pPortCtrl->portState = MV_IDLE; + return pPortCtrl; +} + +/******************************************************************************* +* ethPortFinish - Finish the Ethernet port driver +* +* DESCRIPTION: +* This function finish the ethernet port. +* 1) Down ethernet port if needed. +* 2) Delete RX and TX descriptor rings for all created RX and TX queues +* 3) Free internal port Control structure. +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: NONE. +* +*******************************************************************************/ +void mvEthPortFinish(void* pPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + int queue, portNo = pPortCtrl->portNo; + + if(pPortCtrl->portState == MV_ACTIVE) + { + mvOsPrintf("ethPort #%d: Warning !!! Finish port in Active state\n", + portNo); + mvEthPortDisable(pPortHndl); + } + + /* Free all allocated RX queues */ + for(queue=0; queuerxQueue[queue].descBuf); + } + + /* Free all allocated TX queues */ + for(queue=0; queuetxQueue[queue].descBuf); + } + + /* Free port control structure */ + mvOsFree(pPortCtrl); + + ethPortCtrl[portNo] = NULL; +} + +/******************************************************************************* +* mvEthDefaultsSet - Set defaults to the ethernet port +* +* DESCRIPTION: +* This function set default values to the ethernet port. +* 1) Clear Cause registers and Mask all interrupts +* 2) Clear all MAC tables +* 3) Set defaults to all registers +* 4) Reset all created RX and TX descriptors ring +* 5) Reset PHY +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure +* NOTE: +* This function update all the port configuration except those set +* Initialy by the OsGlue by MV_ETH_PORT_INIT. +* This function can be called after portDown to return the port setting +* to defaults. +*******************************************************************************/ +MV_STATUS mvEthDefaultsSet(void* pPortHndl) +{ + int ethPortNo, queue; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + MV_U32 txPrio; + MV_U32 portCfgReg, portCfgExtReg, portSerialCtrlReg, portSerialCtrl1Reg, portSdmaCfgReg; + MV_BOARD_MAC_SPEED boardMacCfg; + + ethPortNo = pPortCtrl->portNo; + + /* Clear Cause registers */ + MV_REG_WRITE(ETH_INTR_CAUSE_REG(ethPortNo),0); + MV_REG_WRITE(ETH_INTR_CAUSE_EXT_REG(ethPortNo),0); + + /* Mask all interrupts */ + MV_REG_WRITE(ETH_INTR_MASK_REG(ethPortNo),0); + MV_REG_WRITE(ETH_INTR_MASK_EXT_REG(ethPortNo),0); + + portCfgReg = PORT_CONFIG_VALUE; + portCfgExtReg = PORT_CONFIG_EXTEND_VALUE; + + boardMacCfg = mvBoardMacSpeedGet(ethPortNo); + + if(boardMacCfg == BOARD_MAC_SPEED_100M) + { + portSerialCtrlReg = PORT_SERIAL_CONTROL_100MB_FORCE_VALUE; + } + else if(boardMacCfg == BOARD_MAC_SPEED_1000M) + { + portSerialCtrlReg = PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE; + } + else + { + portSerialCtrlReg = PORT_SERIAL_CONTROL_VALUE; + } + + /* build PORT_SDMA_CONFIG_REG */ + portSdmaCfgReg = ETH_TX_INTR_COAL_MASK(0); + portSdmaCfgReg |= ETH_TX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE); + +#if ( (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) || \ + (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) ) + /* some devices have restricted RX burst size when using HW coherency */ + portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_4_64BIT_VALUE); +#else + portSdmaCfgReg |= ETH_RX_BURST_SIZE_MASK(ETH_BURST_SIZE_16_64BIT_VALUE); +#endif + +#if defined(MV_CPU_BE) + /* big endian */ +# if defined(MV_ARM) + portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK | + ETH_TX_NO_DATA_SWAP_MASK | + ETH_DESC_SWAP_MASK); +# elif defined(MV_PPC) + portSdmaCfgReg |= (ETH_RX_DATA_SWAP_MASK | + ETH_TX_DATA_SWAP_MASK | + ETH_NO_DESC_SWAP_MASK); +# else +# error "Giga Ethernet Swap policy is not defined for the CPU_ARCH" +# endif /* MV_ARM / MV_PPC */ + +#else /* MV_CPU_LE */ + /* little endian */ + portSdmaCfgReg |= (ETH_RX_NO_DATA_SWAP_MASK | + ETH_TX_NO_DATA_SWAP_MASK | + ETH_NO_DESC_SWAP_MASK); +#endif /* MV_CPU_BE / MV_CPU_LE */ + + pPortCtrl->portRxQueueCmdReg = 0; + pPortCtrl->portTxQueueCmdReg = 0; + +#if (MV_ETH_VERSION >= 4) + if(pPortCtrl->portConfig.ejpMode == MV_FALSE) + pPortCtrl->portTxQueueCmdReg = MV_32BIT_LE_FAST(ETH_TX_LEGACY_WRR_MASK); +#endif /* (MV_ETH_VERSION >= 4) */ + + ethSetUcastTable(ethPortNo, -1); + mvEthSetSpecialMcastTable(ethPortNo, -1); + mvEthSetOtherMcastTable(ethPortNo, -1); + + portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK; + + portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize); + + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg); + + /* Update value of PortConfig register accordingly with all RxQueue types */ + pPortCtrl->portConfig.rxArpQ = pPortCtrl->portConfig.rxDefQ; + pPortCtrl->portConfig.rxBpduQ = pPortCtrl->portConfig.rxDefQ; + pPortCtrl->portConfig.rxTcpQ = pPortCtrl->portConfig.rxDefQ; + pPortCtrl->portConfig.rxUdpQ = pPortCtrl->portConfig.rxDefQ; + + portCfgReg &= ~ETH_DEF_RX_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_QUEUE_MASK(pPortCtrl->portConfig.rxDefQ); + + portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ); + + portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ); + + portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ); + + portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ); + + /* Assignment of Tx CTRP of given queue */ + txPrio = 0; + + for(queue=0; queuetxQueue[queue]; + + if(pQueueCtrl->pFirstDescr != NULL) + { + ethResetTxDescRing(pPortCtrl, queue); + + MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue), + 0x3fffffff); + MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue), + 0x03ffffff); + } + else + { + MV_REG_WRITE(ETH_TXQ_TOKEN_COUNT_REG(ethPortNo, queue), 0x0); + MV_REG_WRITE(ETH_TXQ_TOKEN_CFG_REG(ethPortNo, queue), 0x0); + } + } + + /* Assignment of Rx CRDP of given queue */ + for(queue=0; queueportNo; + + if( (pPortCtrl->portState != MV_ACTIVE) && + (pPortCtrl->portState != MV_PAUSED) ) + { + mvOsPrintf("ethDrv port%d: Unexpected port state %d\n", + ethPortNo, pPortCtrl->portState); + return MV_BAD_STATE; + } + + ethPortNo = pPortCtrl->portNo; + + /* Enable port RX. */ + MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNo), pPortCtrl->portRxQueueCmdReg); + + /* Enable port TX. */ + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(ethPortNo)) = pPortCtrl->portTxQueueCmdReg; + + pPortCtrl->portState = MV_ACTIVE; + + return MV_OK; +} + +/******************************************************************************* +* ethPortDown - Stop the Ethernet port activity. +* +* DESCRIPTION: +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure. +* +* NOTE : used for port link down. +*******************************************************************************/ +MV_STATUS mvEthPortDown(void* pEthPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + int ethPortNum = pPortCtrl->portNo; + unsigned int regData; + volatile int uDelay, mDelay; + + /* Stop Rx port activity. Check port Rx activity. */ + regData = (MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_RXQ_ENABLE_MASK; + if(regData != 0) + { + /* Issue stop command for active channels only */ + MV_REG_WRITE(ETH_RX_QUEUE_COMMAND_REG(ethPortNum), (regData << ETH_RXQ_DISABLE_OFFSET)); + } + + /* Stop Tx port activity. Check port Tx activity. */ + regData = (MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum))) & ETH_TXQ_ENABLE_MASK; + if(regData != 0) + { + MV_U32 val; + + /* Issue stop command for active channels only */ + val = (regData << ETH_TXQ_DISABLE_OFFSET); + +#if (MV_ETH_VERSION >= 4) + if(pPortCtrl->portConfig.ejpMode == MV_FALSE) + val |= ETH_TX_LEGACY_WRR_MASK; + else + val |= ETH_TX_EJP_ENABLE_MASK; +#endif /* MV_ETH_VERSION >= 4 */ + + MV_REG_WRITE(ETH_TX_QUEUE_COMMAND_REG(ethPortNum), val); + /* Writing 1 to Bit 19 is required for KW and OK for other SoCs */ + } + + /* Force link down */ +/* + regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum)); + regData &= ~(ETH_DO_NOT_FORCE_LINK_FAIL_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData); +*/ + /* Wait for all Rx activity to terminate. */ + mDelay = 0; + do + { + if(mDelay >= RX_DISABLE_TIMEOUT_MSEC) + { + mvOsPrintf("ethPort_%d: TIMEOUT for RX stopped !!! rxQueueCmd - 0x08%x\n", + ethPortNum, regData); + break; + } + mvOsDelay(1); + mDelay++; + + /* Check port RX Command register that all Rx queues are stopped */ + regData = MV_REG_READ(ETH_RX_QUEUE_COMMAND_REG(ethPortNum)); + } + while(regData & 0xFF); + + /* Wait for all Tx activity to terminate. */ + mDelay = 0; + do + { + if(mDelay >= TX_DISABLE_TIMEOUT_MSEC) + { + mvOsPrintf("ethPort_%d: TIMEOUT for TX stoped !!! txQueueCmd - 0x08%x\n", + ethPortNum, regData); + break; + } + mvOsDelay(1); + mDelay++; + + /* Check port TX Command register that all Tx queues are stopped */ + regData = MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(ethPortNum)); + } + while(regData & 0xFF); + + /* Double check to Verify that TX FIFO is Empty */ + mDelay = 0; + while(MV_TRUE) + { + do + { + if(mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC) + { + mvOsPrintf("\n ethPort_%d: TIMEOUT for TX FIFO empty !!! portStatus - 0x08%x\n", + ethPortNum, regData); + break; + } + mvOsDelay(1); + mDelay++; + + regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum)); + } + while( ((regData & ETH_TX_FIFO_EMPTY_MASK) == 0) || + ((regData & ETH_TX_IN_PROGRESS_MASK) != 0) ); + + if(mDelay >= TX_FIFO_EMPTY_TIMEOUT_MSEC) + break; + + /* Double check */ + regData = MV_REG_READ(ETH_PORT_STATUS_REG(ethPortNum)); + if( ((regData & ETH_TX_FIFO_EMPTY_MASK) != 0) && + ((regData & ETH_TX_IN_PROGRESS_MASK) == 0) ) + { + break; + } + else + mvOsPrintf("ethPort_%d: TX FIFO Empty double check failed. %d msec, portStatus=0x%x\n", + ethPortNum, mDelay, regData); + } + + /* Do NOT force link down */ +/* + regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum)); + regData |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData); +*/ + /* Wait about 2500 tclk cycles */ + uDelay = (PORT_DISABLE_WAIT_TCLOCKS/(mvBoardTclkGet()/1000000)); + mvOsUDelay(uDelay); + + pPortCtrl->portState = MV_PAUSED; + + return MV_OK; +} + + +/******************************************************************************* +* ethPortEnable - Enable the Ethernet port and Start RX and TX. +* +* DESCRIPTION: +* This routine enable the Ethernet port and Rx and Tx activity: +* +* Note: Each Rx and Tx queue descriptor's list must be initialized prior +* to calling this function (use etherInitTxDescRing for Tx queues and +* etherInitRxDescRing for Rx queues). +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure. +* +* NOTE: main usage is to enable the port after ifconfig up. +*******************************************************************************/ +MV_STATUS mvEthPortEnable(void* pEthPortHndl) +{ + int ethPortNo; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + MV_U32 portSerialCtrlReg; + + ethPortNo = pPortCtrl->portNo; + + /* Enable port */ + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNo)); + portSerialCtrlReg |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK | ETH_PORT_ENABLE_MASK); + + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg); + + mvEthMibCountersClear(pEthPortHndl); + + pPortCtrl->portState = MV_PAUSED; + + /* If Link is UP, Start RX and TX traffic */ + if( MV_REG_READ( ETH_PORT_STATUS_REG(ethPortNo) ) & ETH_LINK_UP_MASK) + return( mvEthPortUp(pEthPortHndl) ); + + return MV_NOT_READY; +} + + +/******************************************************************************* +* mvEthPortDisable - Stop RX and TX activities and Disable the Ethernet port. +* +* DESCRIPTION: +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler +* +* RETURN: MV_STATUS +* MV_OK - Success, Others - Failure. +* +* NOTE: main usage is to disable the port after ifconfig down. +*******************************************************************************/ +MV_STATUS mvEthPortDisable(void* pEthPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + int ethPortNum = pPortCtrl->portNo; + unsigned int regData; + volatile int mvDelay; + + if(pPortCtrl->portState == MV_ACTIVE) + { + /* Stop RX and TX activities */ + mvEthPortDown(pEthPortHndl); + } + + /* Reset the Enable bit in the Serial Control Register */ + regData = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNum)); + regData &= ~(ETH_PORT_ENABLE_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData); + + /* Wait about 2500 tclk cycles */ + mvDelay = (PORT_DISABLE_WAIT_TCLOCKS*(mvCpuPclkGet()/mvBoardTclkGet())); + for(mvDelay; mvDelay>0; mvDelay--); + + pPortCtrl->portState = MV_IDLE; + return MV_OK; +} + +/******************************************************************************* +* mvEthPortForceTxDone - Get next buffer from TX queue in spite of buffer ownership. +* +* DESCRIPTION: +* This routine used to free buffers attached to the Tx ring and should +* be called only when Giga Ethernet port is Down +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of TX queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to packet was sent. +* +* RETURN: +* MV_EMPTY - There is no more buffers in this queue. +* MV_OK - Buffer detached from the queue and pPktInfo structure +* filled with relevant information. +* +*******************************************************************************/ +MV_PKT_INFO* mvEthPortForceTxDone(void* pEthPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + MV_PKT_INFO* pPktInfo; + ETH_TX_DESC* pTxDesc; + int port = pPortCtrl->portNo; + + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + while( (pQueueCtrl->pUsedDescr != pQueueCtrl->pCurrentDescr) || + (pQueueCtrl->resource == 0) ) + { + /* Free next descriptor */ + pQueueCtrl->resource++; + pTxDesc = (ETH_TX_DESC*)pQueueCtrl->pUsedDescr; + pPktInfo = (MV_PKT_INFO*)pTxDesc->returnInfo; + pPktInfo->status = pTxDesc->cmdSts; + pTxDesc->cmdSts = 0x0; + pTxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc); + + pQueueCtrl->pUsedDescr = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl); + + if(pPktInfo->status & ETH_TX_LAST_DESC_MASK) + return pPktInfo; + } + MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(port, txQueue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + return NULL; +} + + + +/******************************************************************************* +* mvEthPortForceRx - Get next buffer from RX queue in spite of buffer ownership. +* +* DESCRIPTION: +* This routine used to free buffers attached to the Rx ring and should +* be called only when Giga Ethernet port is Down +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int rxQueue - Number of Rx queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to received packet. +* +* RETURN: +* MV_EMPTY - There is no more buffers in this queue. +* MV_OK - Buffer detached from the queue and pBufInfo structure +* filled with relevant information. +* +*******************************************************************************/ +MV_PKT_INFO* mvEthPortForceRx(void* pEthPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_RX_DESC* pRxDesc; + MV_PKT_INFO* pPktInfo; + int port = pPortCtrl->portNo; + + pQueueCtrl = &pPortCtrl->rxQueue[rxQueue]; + + if(pQueueCtrl->resource == 0) + { + MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(port, rxQueue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + + return NULL; + } + /* Free next descriptor */ + pQueueCtrl->resource--; + pRxDesc = (ETH_RX_DESC*)pQueueCtrl->pCurrentDescr; + pPktInfo = (MV_PKT_INFO*)pRxDesc->returnInfo; + + pPktInfo->status = pRxDesc->cmdSts; + pRxDesc->cmdSts = 0x0; + pRxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc); + + pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl); + return pPktInfo; +} + + +/******************************************************************************/ +/* Port Configuration functions */ +/******************************************************************************/ +/******************************************************************************* +* mvEthMruGet - Get MRU configuration for Max Rx packet size. +* +* INPUT: +* MV_U32 maxRxPktSize - max packet size. +* +* RETURN: MV_U32 - MRU configuration. +* +*******************************************************************************/ +static MV_U32 mvEthMruGet(MV_U32 maxRxPktSize) +{ + MV_U32 portSerialCtrlReg = 0; + + if(maxRxPktSize > 9192) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_9700BYTE; + else if(maxRxPktSize > 9022) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_9192BYTE; + else if(maxRxPktSize > 1552) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_9022BYTE; + else if(maxRxPktSize > 1522) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_1552BYTE; + else if(maxRxPktSize > 1518) + portSerialCtrlReg |= ETH_MAX_RX_PACKET_1522BYTE; + else + portSerialCtrlReg |= ETH_MAX_RX_PACKET_1518BYTE; + + return portSerialCtrlReg; +} + +/******************************************************************************* +* mvEthRxCoalSet - Sets coalescing interrupt mechanism on RX path +* +* DESCRIPTION: +* This routine sets the RX coalescing interrupt mechanism parameter. +* This parameter is a timeout counter, that counts in 64 tClk +* chunks, that when timeout event occurs a maskable interrupt occurs. +* The parameter is calculated using the tCLK frequency of the +* MV-64xxx chip, and the required number is in micro seconds. +* +* INPUT: +* void* pPortHndl - Ethernet Port handler. +* MV_U32 uSec - Number of micro seconds between +* RX interrupts +* +* RETURN: +* None. +* +* COMMENT: +* 1 sec - TCLK_RATE clocks +* 1 uSec - TCLK_RATE / 1,000,000 clocks +* +* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64) +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_U32 mvEthRxCoalSet (void* pPortHndl, MV_U32 uSec) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + MV_U32 coal = ((uSec * (mvBoardTclkGet() / 1000000)) / 64); + MV_U32 portSdmaCfgReg; + + portSdmaCfgReg = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo)); + portSdmaCfgReg &= ~ETH_RX_INTR_COAL_ALL_MASK; + + portSdmaCfgReg |= ETH_RX_INTR_COAL_MASK(coal); + +#if (MV_ETH_VERSION >= 2) + /* Set additional bit if needed ETH_RX_INTR_COAL_MSB_BIT (25) */ + if(ETH_RX_INTR_COAL_MASK(coal) > ETH_RX_INTR_COAL_ALL_MASK) + portSdmaCfgReg |= ETH_RX_INTR_COAL_MSB_MASK; +#endif /* MV_ETH_VERSION >= 2 */ + + MV_REG_WRITE (ETH_SDMA_CONFIG_REG(pPortCtrl->portNo), portSdmaCfgReg); + return coal; +} + +/******************************************************************************* +* mvEthTxCoalSet - Sets coalescing interrupt mechanism on TX path +* +* DESCRIPTION: +* This routine sets the TX coalescing interrupt mechanism parameter. +* This parameter is a timeout counter, that counts in 64 tClk +* chunks, that when timeout event occurs a maskable interrupt +* occurs. +* The parameter is calculated using the tCLK frequency of the +* MV-64xxx chip, and the required number is in micro seconds. +* +* INPUT: +* void* pPortHndl - Ethernet Port handler. +* MV_U32 uSec - Number of micro seconds between +* RX interrupts +* +* RETURN: +* None. +* +* COMMENT: +* 1 sec - TCLK_RATE clocks +* 1 uSec - TCLK_RATE / 1,000,000 clocks +* +* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64) +* +*******************************************************************************/ +MV_U32 mvEthTxCoalSet(void* pPortHndl, MV_U32 uSec) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + MV_U32 coal = ((uSec * (mvBoardTclkGet() / 1000000)) / 64); + MV_U32 regVal; + + regVal = MV_REG_READ(ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo)); + regVal &= ~ETH_TX_INTR_COAL_ALL_MASK; + regVal |= ETH_TX_INTR_COAL_MASK(coal); + + /* Set TX Coalescing mechanism */ + MV_REG_WRITE (ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo), regVal); + return coal; +} + +/******************************************************************************* +* mvEthCoalGet - Gets RX and TX coalescing values in micro seconds +* +* DESCRIPTION: +* This routine gets the RX and TX coalescing interrupt values. +* The parameter is calculated using the tCLK frequency of the +* MV-64xxx chip, and the returned numbers are in micro seconds. +* +* INPUTs: +* void* pPortHndl - Ethernet Port handler. +* +* OUTPUTs: +* MV_U32* pRxCoal - Number of micro seconds between RX interrupts +* MV_U32* pTxCoal - Number of micro seconds between TX interrupts +* +* RETURN: +* MV_STATUS MV_OK - success +* Others - failure. +* +* COMMENT: +* 1 sec - TCLK_RATE clocks +* 1 uSec - TCLK_RATE / 1,000,000 clocks +* +* Register Value for N micro seconds - ((N * ( (TCLK_RATE / 1,000,000)) / 64) +* +*******************************************************************************/ +MV_STATUS mvEthCoalGet(void* pPortHndl, MV_U32* pRxCoal, MV_U32* pTxCoal) +{ + MV_U32 regVal, coal, usec; + + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + /* get TX Coalescing */ + regVal = MV_REG_READ (ETH_TX_FIFO_URGENT_THRESH_REG(pPortCtrl->portNo)); + coal = ((regVal & ETH_TX_INTR_COAL_ALL_MASK) >> ETH_TX_INTR_COAL_OFFSET); + + usec = (coal * 64) / (mvBoardTclkGet() / 1000000); + if(pTxCoal != NULL) + *pTxCoal = usec; + + /* Get RX Coalescing */ + regVal = MV_REG_READ(ETH_SDMA_CONFIG_REG(pPortCtrl->portNo)); + coal = ((regVal & ETH_RX_INTR_COAL_ALL_MASK) >> ETH_RX_INTR_COAL_OFFSET); + +#if (MV_ETH_VERSION >= 2) + if(regVal & ETH_RX_INTR_COAL_MSB_MASK) + { + /* Add MSB */ + coal |= (ETH_RX_INTR_COAL_ALL_MASK + 1); + } +#endif /* MV_ETH_VERSION >= 2 */ + + usec = (coal * 64) / (mvBoardTclkGet() / 1000000); + if(pRxCoal != NULL) + *pRxCoal = usec; + + return MV_OK; +} + +/******************************************************************************* +* mvEthMaxRxSizeSet - +* +* DESCRIPTION: +* Change maximum receive size of the port. This configuration will take place +* after next call of ethPortSetDefaults() function. +* +* INPUT: +* +* RETURN: +*******************************************************************************/ +MV_STATUS mvEthMaxRxSizeSet(void* pPortHndl, int maxRxSize) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + MV_U32 portSerialCtrlReg; + + if((maxRxSize < 1518) || (maxRxSize & ~ETH_RX_BUFFER_MASK)) + return MV_BAD_PARAM; + + pPortCtrl->portConfig.maxRxPktSize = maxRxSize; + + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo)); + portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK; + portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo), portSerialCtrlReg); + + return MV_OK; +} + + +/******************************************************************************/ +/* MAC Filtering functions */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthRxFilterModeSet - Configure Fitering mode of Ethernet port +* +* DESCRIPTION: +* This routine used to free buffers attached to the Rx ring and should +* be called only when Giga Ethernet port is Down +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* MV_BOOL isPromisc - Promiscous mode +* MV_TRUE - accept all Broadcast, Multicast +* and Unicast packets +* MV_FALSE - accept all Broadcast, +* specially added Multicast and +* single Unicast packets +* +* RETURN: MV_STATUS MV_OK - Success, Other - Failure +* +*******************************************************************************/ +MV_STATUS mvEthRxFilterModeSet(void* pEthPortHndl, MV_BOOL isPromisc) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + int queue; + MV_U32 portCfgReg; + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + /* Set / Clear UPM bit in port configuration register */ + if(isPromisc) + { + /* Accept all multicast packets to RX default queue */ + queue = pPortCtrl->portConfig.rxDefQ; + portCfgReg |= ETH_UNICAST_PROMISCUOUS_MODE_MASK; + memset(pPortCtrl->mcastCount, 1, sizeof(pPortCtrl->mcastCount)); + MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo),0xFFFF); + MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo),0xFFFFFFFF); + } + else + { + /* Reject all Multicast addresses */ + queue = -1; + portCfgReg &= ~ETH_UNICAST_PROMISCUOUS_MODE_MASK; + /* Clear all mcastCount */ + memset(pPortCtrl->mcastCount, 0, sizeof(pPortCtrl->mcastCount)); + } + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + /* Set Special Multicast and Other Multicast tables */ + mvEthSetSpecialMcastTable(pPortCtrl->portNo, queue); + mvEthSetOtherMcastTable(pPortCtrl->portNo, queue); + ethSetUcastTable(pPortCtrl->portNo, queue); + + return MV_OK; +} + +/******************************************************************************* +* mvEthMacAddrSet - This function Set the port Unicast address. +* +* DESCRIPTION: +* This function Set the port Ethernet MAC address. This address +* will be used to send Pause frames if enabled. Packets with this +* address will be accepted and dispatched to default RX queue +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler. +* char* pAddr - Address to be set +* +* RETURN: MV_STATUS +* MV_OK - Success, Other - Faulure +* +*******************************************************************************/ +MV_STATUS mvEthMacAddrSet(void* pPortHndl, unsigned char *pAddr, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + unsigned int macH; + unsigned int macL; + + if(queue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", queue); + return MV_BAD_PARAM; + } + + if(queue != -1) + { + macL = (pAddr[4] << 8) | (pAddr[5]); + macH = (pAddr[0] << 24)| (pAddr[1] << 16) | + (pAddr[2] << 8) | (pAddr[3] << 0); + + MV_REG_WRITE(ETH_MAC_ADDR_LOW_REG(pPortCtrl->portNo), macL); + MV_REG_WRITE(ETH_MAC_ADDR_HIGH_REG(pPortCtrl->portNo), macH); + } + + /* Accept frames of this address */ + ethSetUcastAddr(pPortCtrl->portNo, pAddr[5], queue); + + return MV_OK; +} + +/******************************************************************************* +* mvEthMacAddrGet - This function returns the port Unicast address. +* +* DESCRIPTION: +* This function returns the port Ethernet MAC address. +* +* INPUT: +* int portNo - Ethernet port number. +* char* pAddr - Pointer where address will be written to +* +* RETURN: MV_STATUS +* MV_OK - Success, Other - Faulure +* +*******************************************************************************/ +MV_STATUS mvEthMacAddrGet(int portNo, unsigned char *pAddr) +{ + unsigned int macH; + unsigned int macL; + + if(pAddr == NULL) + { + mvOsPrintf("mvEthMacAddrGet: NULL pointer.\n"); + return MV_BAD_PARAM; + } + + macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(portNo)); + macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(portNo)); + pAddr[0] = (macH >> 24) & 0xff; + pAddr[1] = (macH >> 16) & 0xff; + pAddr[2] = (macH >> 8) & 0xff; + pAddr[3] = macH & 0xff; + pAddr[4] = (macL >> 8) & 0xff; + pAddr[5] = macL & 0xff; + + return MV_OK; +} + +/******************************************************************************* +* mvEthMcastCrc8Get - Calculate CRC8 of MAC address. +* +* DESCRIPTION: +* +* INPUT: +* MV_U8* pAddr - Address to calculate CRC-8 +* +* RETURN: MV_U8 - CRC-8 of this MAC address +* +*******************************************************************************/ +MV_U8 mvEthMcastCrc8Get(MV_U8* pAddr) +{ + unsigned int macH; + unsigned int macL; + int macArray[48]; + int crc[8]; + int i; + unsigned char crcResult = 0; + + /* Calculate CRC-8 out of the given address */ + macH = (pAddr[0] << 8) | (pAddr[1]); + macL = (pAddr[2] << 24)| (pAddr[3] << 16) | + (pAddr[4] << 8) | (pAddr[5] << 0); + + for(i=0; i<32; i++) + macArray[i] = (macL >> i) & 0x1; + + for(i=32; i<48; i++) + macArray[i] = (macH >> (i - 32)) & 0x1; + + crc[0] = macArray[45] ^ macArray[43] ^ macArray[40] ^ macArray[39] ^ + macArray[35] ^ macArray[34] ^ macArray[31] ^ macArray[30] ^ + macArray[28] ^ macArray[23] ^ macArray[21] ^ macArray[19] ^ + macArray[18] ^ macArray[16] ^ macArray[14] ^ macArray[12] ^ + macArray[8] ^ macArray[7] ^ macArray[6] ^ macArray[0]; + + crc[1] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^ + macArray[41] ^ macArray[39] ^ macArray[36] ^ macArray[34] ^ + macArray[32] ^ macArray[30] ^ macArray[29] ^ macArray[28] ^ + macArray[24] ^ macArray[23] ^ macArray[22] ^ macArray[21] ^ + macArray[20] ^ macArray[18] ^ macArray[17] ^ macArray[16] ^ + macArray[15] ^ macArray[14] ^ macArray[13] ^ macArray[12] ^ + macArray[9] ^ macArray[6] ^ macArray[1] ^ macArray[0]; + + crc[2] = macArray[47] ^ macArray[46] ^ macArray[44] ^ macArray[43] ^ + macArray[42] ^ macArray[39] ^ macArray[37] ^ macArray[34] ^ + macArray[33] ^ macArray[29] ^ macArray[28] ^ macArray[25] ^ + macArray[24] ^ macArray[22] ^ macArray[17] ^ macArray[15] ^ + macArray[13] ^ macArray[12] ^ macArray[10] ^ macArray[8] ^ + macArray[6] ^ macArray[2] ^ macArray[1] ^ macArray[0]; + + crc[3] = macArray[47] ^ macArray[45] ^ macArray[44] ^ macArray[43] ^ + macArray[40] ^ macArray[38] ^ macArray[35] ^ macArray[34] ^ + macArray[30] ^ macArray[29] ^ macArray[26] ^ macArray[25] ^ + macArray[23] ^ macArray[18] ^ macArray[16] ^ macArray[14] ^ + macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[7] ^ + macArray[3] ^ macArray[2] ^ macArray[1]; + + crc[4] = macArray[46] ^ macArray[45] ^ macArray[44] ^ macArray[41] ^ + macArray[39] ^ macArray[36] ^ macArray[35] ^ macArray[31] ^ + macArray[30] ^ macArray[27] ^ macArray[26] ^ macArray[24] ^ + macArray[19] ^ macArray[17] ^ macArray[15] ^ macArray[14] ^ + macArray[12] ^ macArray[10] ^ macArray[8] ^ macArray[4] ^ + macArray[3] ^ macArray[2]; + + crc[5] = macArray[47] ^ macArray[46] ^ macArray[45] ^ macArray[42] ^ + macArray[40] ^ macArray[37] ^ macArray[36] ^ macArray[32] ^ + macArray[31] ^ macArray[28] ^ macArray[27] ^ macArray[25] ^ + macArray[20] ^ macArray[18] ^ macArray[16] ^ macArray[15] ^ + macArray[13] ^ macArray[11] ^ macArray[9] ^ macArray[5] ^ + macArray[4] ^ macArray[3]; + + crc[6] = macArray[47] ^ macArray[46] ^ macArray[43] ^ macArray[41] ^ + macArray[38] ^ macArray[37] ^ macArray[33] ^ macArray[32] ^ + macArray[29] ^ macArray[28] ^ macArray[26] ^ macArray[21] ^ + macArray[19] ^ macArray[17] ^ macArray[16] ^ macArray[14] ^ + macArray[12] ^ macArray[10] ^ macArray[6] ^ macArray[5] ^ + macArray[4]; + + crc[7] = macArray[47] ^ macArray[44] ^ macArray[42] ^ macArray[39] ^ + macArray[38] ^ macArray[34] ^ macArray[33] ^ macArray[30] ^ + macArray[29] ^ macArray[27] ^ macArray[22] ^ macArray[20] ^ + macArray[18] ^ macArray[17] ^ macArray[15] ^ macArray[13] ^ + macArray[11] ^ macArray[7] ^ macArray[6] ^ macArray[5]; + + for(i=0; i<8; i++) + crcResult = crcResult | (crc[i] << i); + + return crcResult; +} +/******************************************************************************* +* mvEthMcastAddrSet - Multicast address settings. +* +* DESCRIPTION: +* This API controls the MV device MAC multicast support. +* The MV device supports multicast using two tables: +* 1) Special Multicast Table for MAC addresses of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* In this case, the function calls ethPortSmcAddr() routine to set the +* Special Multicast Table. +* 2) Other Multicast Table for multicast of another type. A CRC-8bit +* is used as an index to the Other Multicast Table entries in the +* DA-Filter table. +* In this case, the function calculates the CRC-8bit value and calls +* ethPortOmcAddr() routine to set the Other Multicast Table. +* +* INPUT: +* void* pEthPortHndl - Ethernet port handler. +* MV_U8* pAddr - Address to be set +* int queue - RX queue to capture all packets with this +* Multicast MAC address. +* -1 means delete this Multicast address. +* +* RETURN: MV_STATUS +* MV_TRUE - Success, Other - Failure +* +*******************************************************************************/ +MV_STATUS mvEthMcastAddrSet(void* pPortHndl, MV_U8 *pAddr, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + unsigned char crcResult = 0; + + if(queue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethPort %d: RX queue #%d is out of range\n", + pPortCtrl->portNo, queue); + return MV_BAD_PARAM; + } + + if((pAddr[0] == 0x01) && + (pAddr[1] == 0x00) && + (pAddr[2] == 0x5E) && + (pAddr[3] == 0x00) && + (pAddr[4] == 0x00)) + { + ethSetSpecialMcastAddr(pPortCtrl->portNo, pAddr[5], queue); + } + else + { + crcResult = mvEthMcastCrc8Get(pAddr); + + /* Check Add counter for this CRC value */ + if(queue == -1) + { + if(pPortCtrl->mcastCount[crcResult] == 0) + { + mvOsPrintf("ethPort #%d: No valid Mcast for crc8=0x%02x\n", + pPortCtrl->portNo, (unsigned)crcResult); + return MV_NO_SUCH; + } + + pPortCtrl->mcastCount[crcResult]--; + if(pPortCtrl->mcastCount[crcResult] != 0) + { + mvOsPrintf("ethPort #%d: After delete there are %d valid Mcast for crc8=0x%02x\n", + pPortCtrl->portNo, pPortCtrl->mcastCount[crcResult], + (unsigned)crcResult); + return MV_NO_CHANGE; + } + } + else + { + pPortCtrl->mcastCount[crcResult]++; + if(pPortCtrl->mcastCount[crcResult] > 1) + { + mvOsPrintf("ethPort #%d: Valid Mcast for crc8=0x%02x already exists\n", + pPortCtrl->portNo, (unsigned)crcResult); + return MV_NO_CHANGE; + } + } + ethSetOtherMcastAddr(pPortCtrl->portNo, crcResult, queue); + } + return MV_OK; +} + +/******************************************************************************* +* ethSetUcastTable - Unicast address settings. +* +* DESCRIPTION: +* Set all entries in the Unicast MAC Table queue==-1 means reject all +* INPUT: +* +* RETURN: +* +*******************************************************************************/ +static void ethSetUcastTable(int portNo, int queue) +{ + int offset; + MV_U32 regValue; + + if(queue == -1) + { + regValue = 0; + } + else + { + regValue = (((0x01 | (queue<<1)) << 0) | + ((0x01 | (queue<<1)) << 8) | + ((0x01 | (queue<<1)) << 16) | + ((0x01 | (queue<<1)) << 24)); + } + + for (offset=0; offset<=0xC; offset+=4) + MV_REG_WRITE((ETH_DA_FILTER_UCAST_BASE(portNo) + offset), regValue); +} + +/******************************************************************************* +* mvEthSetSpecialMcastTable - Special Multicast address settings. +* +* DESCRIPTION: +* Set all entries to the Special Multicast MAC Table. queue==-1 means reject all +* INPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvEthSetSpecialMcastTable(int portNo, int queue) +{ + int offset; + MV_U32 regValue; + + if(queue == -1) + { + regValue = 0; + } + else + { + regValue = (((0x01 | (queue<<1)) << 0) | + ((0x01 | (queue<<1)) << 8) | + ((0x01 | (queue<<1)) << 16) | + ((0x01 | (queue<<1)) << 24)); + } + + for (offset=0; offset<=0xFC; offset+=4) + { + MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(portNo) + + offset), regValue); + } +} + +/******************************************************************************* +* mvEthSetOtherMcastTable - Other Multicast address settings. +* +* DESCRIPTION: +* Set all entries to the Other Multicast MAC Table. queue==-1 means reject all +* INPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvEthSetOtherMcastTable(int portNo, int queue) +{ + int offset; + MV_U32 regValue; + + if(queue == -1) + { + regValue = 0; + } + else + { + regValue = (((0x01 | (queue<<1)) << 0) | + ((0x01 | (queue<<1)) << 8) | + ((0x01 | (queue<<1)) << 16) | + ((0x01 | (queue<<1)) << 24)); + } + + for (offset=0; offset<=0xFC; offset+=4) + { + MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(portNo) + + offset), regValue); + } +} + +/******************************************************************************* +* ethSetUcastAddr - This function Set the port unicast address table +* +* DESCRIPTION: +* This function locates the proper entry in the Unicast table for the +* specified MAC nibble and sets its properties according to function +* parameters. +* +* INPUT: +* int ethPortNum - Port number. +* MV_U8 lastNibble - Unicast MAC Address last nibble. +* int queue - Rx queue number for this MAC address. +* value "-1" means remove address +* +* OUTPUT: +* This function add/removes MAC addresses from the port unicast address +* table. +* +* RETURN: +* MV_TRUE is output succeeded. +* MV_FALSE if option parameter is invalid. +* +*******************************************************************************/ +static MV_BOOL ethSetUcastAddr(int portNo, MV_U8 lastNibble, int queue) +{ + unsigned int unicastReg; + unsigned int tblOffset; + unsigned int regOffset; + + /* Locate the Unicast table entry */ + lastNibble = (0xf & lastNibble); + tblOffset = (lastNibble / 4) * 4; /* Register offset from unicast table base*/ + regOffset = lastNibble % 4; /* Entry offset within the above register */ + + + unicastReg = MV_REG_READ( (ETH_DA_FILTER_UCAST_BASE(portNo) + + tblOffset)); + + + if(queue == -1) + { + /* Clear accepts frame bit at specified unicast DA table entry */ + unicastReg &= ~(0xFF << (8*regOffset)); + } + else + { + unicastReg &= ~(0xFF << (8*regOffset)); + unicastReg |= ((0x01 | (queue<<1)) << (8*regOffset)); + } + MV_REG_WRITE( (ETH_DA_FILTER_UCAST_BASE(portNo) + tblOffset), + unicastReg); + + return MV_TRUE; +} + +/******************************************************************************* +* ethSetSpecialMcastAddr - Special Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device special MAC multicast support. +* The Special Multicast Table for MAC addresses supports MAC of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0xFF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* This function set the Special Multicast Table appropriate entry +* according to the argument given. +* +* INPUT: +* int ethPortNum Port number. +* unsigned char mcByte Multicast addr last byte (MAC DA[7:0] bits). +* int queue Rx queue number for this MAC address. +* int option 0 = Add, 1 = remove address. +* +* OUTPUT: +* See description. +* +* RETURN: +* MV_TRUE is output succeeded. +* MV_FALSE if option parameter is invalid. +* +*******************************************************************************/ +static MV_BOOL ethSetSpecialMcastAddr(int ethPortNum, MV_U8 lastByte, int queue) +{ + unsigned int smcTableReg; + unsigned int tblOffset; + unsigned int regOffset; + + /* Locate the SMC table entry */ + tblOffset = (lastByte / 4); /* Register offset from SMC table base */ + regOffset = lastByte % 4; /* Entry offset within the above register */ + + smcTableReg = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) + tblOffset*4)); + + if(queue == -1) + { + /* Clear accepts frame bit at specified Special DA table entry */ + smcTableReg &= ~(0xFF << (8 * regOffset)); + } + else + { + smcTableReg &= ~(0xFF << (8 * regOffset)); + smcTableReg |= ((0x01 | (queue<<1)) << (8 * regOffset)); + } + MV_REG_WRITE((ETH_DA_FILTER_SPEC_MCAST_BASE(ethPortNum) + + tblOffset*4), smcTableReg); + + return MV_TRUE; +} + +/******************************************************************************* +* ethSetOtherMcastAddr - Multicast address settings. +* +* DESCRIPTION: +* This routine controls the MV device Other MAC multicast support. +* The Other Multicast Table is used for multicast of another type. +* A CRC-8bit is used as an index to the Other Multicast Table entries +* in the DA-Filter table. +* The function gets the CRC-8bit value from the calling routine and +* set the Other Multicast Table appropriate entry according to the +* CRC-8 argument given. +* +* INPUT: +* int ethPortNum Port number. +* MV_U8 crc8 A CRC-8bit (Polynomial: x^8+x^2+x^1+1). +* int queue Rx queue number for this MAC address. +* +* OUTPUT: +* See description. +* +* RETURN: +* MV_TRUE is output succeeded. +* MV_FALSE if option parameter is invalid. +* +*******************************************************************************/ +static MV_BOOL ethSetOtherMcastAddr(int ethPortNum, MV_U8 crc8, int queue) +{ + unsigned int omcTableReg; + unsigned int tblOffset; + unsigned int regOffset; + + /* Locate the OMC table entry */ + tblOffset = (crc8 / 4) * 4; /* Register offset from OMC table base */ + regOffset = crc8 % 4; /* Entry offset within the above register */ + + omcTableReg = MV_REG_READ( + (ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset)); + + if(queue == -1) + { + /* Clear accepts frame bit at specified Other DA table entry */ + omcTableReg &= ~(0xFF << (8 * regOffset)); + } + else + { + omcTableReg &= ~(0xFF << (8 * regOffset)); + omcTableReg |= ((0x01 | (queue<<1)) << (8 * regOffset)); + } + + MV_REG_WRITE((ETH_DA_FILTER_OTH_MCAST_BASE(ethPortNum) + tblOffset), + omcTableReg); + + return MV_TRUE; +} + + +/******************************************************************************/ +/* MIB Counters functions */ +/******************************************************************************/ + + +/******************************************************************************* +* mvEthMibCounterRead - Read a MIB counter +* +* DESCRIPTION: +* This function reads a MIB counter of a specific ethernet port. +* NOTE - Read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW or +* ETH_MIB_GOOD_OCTETS_SENT_LOW counters will return 64 bits value, +* so pHigh32 pointer should not be NULL in this case. +* +* INPUT: +* int ethPortNum - Ethernet Port number. +* unsigned int mibOffset - MIB counter offset. +* +* OUTPUT: +* MV_U32* pHigh32 - pointer to place where 32 most significant bits +* of the counter will be stored. +* +* RETURN: +* 32 low sgnificant bits of MIB counter value. +* +*******************************************************************************/ +MV_U32 mvEthMibCounterRead(void* pPortHandle, unsigned int mibOffset, + MV_U32* pHigh32) +{ + int portNo; + MV_U32 valLow32, valHigh32; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + + portNo = pPortCtrl->portNo; + + valLow32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset); + + /* Implement FEr ETH. Erroneous Value when Reading the Upper 32-bits */ + /* of a 64-bit MIB Counter. */ + if( (mibOffset == ETH_MIB_GOOD_OCTETS_RECEIVED_LOW) || + (mibOffset == ETH_MIB_GOOD_OCTETS_SENT_LOW) ) + { + valHigh32 = MV_REG_READ(ETH_MIB_COUNTERS_BASE(portNo) + mibOffset + 4); + if(pHigh32 != NULL) + *pHigh32 = valHigh32; + } + return valLow32; +} + +/******************************************************************************* +* mvEthMibCountersClear - Clear all MIB counters +* +* DESCRIPTION: +* This function clears all MIB counters +* +* INPUT: +* int ethPortNum - Ethernet Port number. +* +* +* RETURN: void +* +*******************************************************************************/ +void mvEthMibCountersClear(void* pPortHandle) +{ + int i, portNo; + unsigned int dummy; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + + portNo = pPortCtrl->portNo; + + /* Perform dummy reads from MIB counters */ + for(i=ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", vlanPrioQueue); + return MV_BAD_PARAM; + } + if(vlanPrio >= 8) + { + mvOsPrintf("ethDrv: vlanPrio=%d is out of range\n", vlanPrio); + return MV_BAD_PARAM; + } + + vlanPrioReg = MV_REG_READ(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo)); + vlanPrioReg &= ~(0x7 << (vlanPrio*3)); + vlanPrioReg |= (vlanPrioQueue << (vlanPrio*3)); + MV_REG_WRITE(ETH_VLAN_TAG_TO_PRIO_REG(pPortCtrl->portNo), vlanPrioReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthBpduRxQueue - Configure RX queue to capture BPDU packets. +* +* DESCRIPTION: +* This function defines processing of BPDU packets. +* BPDU packets can be accepted and captured to one of RX queues +* or can be processing as regular Multicast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int bpduQueue - Special queue to capture BPDU packets (DA is equal to +* 01-80-C2-00-00-00 through 01-80-C2-00-00-FF, +* except for the Flow-Control Pause packets). +* Negative value (-1) means no special processing for BPDU, +* packets so they will be processed as regular Multicast packets. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthBpduRxQueue(void* pPortHandle, int bpduQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + MV_U32 portCfgExtReg; + + if(bpduQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", bpduQueue); + return MV_BAD_PARAM; + } + + portCfgExtReg = MV_REG_READ(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo)); + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + if(bpduQueue >= 0) + { + pPortCtrl->portConfig.rxBpduQ = bpduQueue; + + portCfgReg &= ~ETH_DEF_RX_BPDU_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_BPDU_QUEUE_MASK(pPortCtrl->portConfig.rxBpduQ); + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + portCfgExtReg |= ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK; + } + else + { + pPortCtrl->portConfig.rxBpduQ = -1; + /* no special processing for BPDU packets */ + portCfgExtReg &= (~ETH_CAPTURE_SPAN_BPDU_ENABLE_MASK); + } + + MV_REG_WRITE(ETH_PORT_CONFIG_EXTEND_REG(pPortCtrl->portNo), portCfgExtReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthArpRxQueue - Configure RX queue to capture ARP packets. +* +* DESCRIPTION: +* This function defines processing of ARP (type=0x0806) packets. +* ARP packets can be accepted and captured to one of RX queues +* or can be processed as other Broadcast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int arpQueue - Special queue to capture ARP packets (type=0x806). +* Negative value (-1) means discard ARP packets +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthArpRxQueue(void* pPortHandle, int arpQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + + if(arpQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", arpQueue); + return MV_BAD_PARAM; + } + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + + if(arpQueue >= 0) + { + pPortCtrl->portConfig.rxArpQ = arpQueue; + portCfgReg &= ~ETH_DEF_RX_ARP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_ARP_QUEUE_MASK(pPortCtrl->portConfig.rxArpQ); + + portCfgReg &= (~ETH_REJECT_ARP_BCAST_MASK); + } + else + { + pPortCtrl->portConfig.rxArpQ = -1; + portCfgReg |= ETH_REJECT_ARP_BCAST_MASK; + } + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthTcpRxQueue - Configure RX queue to capture TCP packets. +* +* DESCRIPTION: +* This function defines processing of TCP packets. +* TCP packets can be accepted and captured to one of RX queues +* or can be processed as regular Unicast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int tcpQueue - Special queue to capture TCP packets. Value "-1" +* means no special processing for TCP packets, +* so they will be processed as regular +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthTcpRxQueue(void* pPortHandle, int tcpQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + + if(tcpQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", tcpQueue); + return MV_BAD_PARAM; + } + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + + if(tcpQueue >= 0) + { + pPortCtrl->portConfig.rxTcpQ = tcpQueue; + portCfgReg &= ~ETH_DEF_RX_TCP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_TCP_QUEUE_MASK(pPortCtrl->portConfig.rxTcpQ); + + portCfgReg |= ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK; + } + else + { + pPortCtrl->portConfig.rxTcpQ = -1; + portCfgReg &= (~ETH_CAPTURE_TCP_FRAMES_ENABLE_MASK); + } + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + return MV_OK; +} + + +/******************************************************************************* +* mvEthUdpRxQueue - Configure RX queue to capture UDP packets. +* +* DESCRIPTION: +* This function defines processing of UDP packets. +* TCP packets can be accepted and captured to one of RX queues +* or can be processed as regular Unicast packets. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int udpQueue - Special queue to capture UDP packets. Value "-1" +* means no special processing for UDP packets, +* so they will be processed as regular +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthUdpRxQueue(void* pPortHandle, int udpQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + MV_U32 portCfgReg; + + if(udpQueue >= MV_ETH_RX_Q_NUM) + { + mvOsPrintf("ethDrv: RX queue #%d is out of range\n", udpQueue); + return MV_BAD_PARAM; + } + + portCfgReg = MV_REG_READ(ETH_PORT_CONFIG_REG(pPortCtrl->portNo)); + + if(udpQueue >= 0) + { + pPortCtrl->portConfig.rxUdpQ = udpQueue; + portCfgReg &= ~ETH_DEF_RX_UDP_QUEUE_ALL_MASK; + portCfgReg |= ETH_DEF_RX_UDP_QUEUE_MASK(pPortCtrl->portConfig.rxUdpQ); + + portCfgReg |= ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK; + } + else + { + pPortCtrl->portConfig.rxUdpQ = -1; + portCfgReg &= ~ETH_CAPTURE_UDP_FRAMES_ENABLE_MASK; + } + + MV_REG_WRITE(ETH_PORT_CONFIG_REG(pPortCtrl->portNo), portCfgReg); + + return MV_OK; +} + + +/******************************************************************************/ +/* Speed, Duplex, FlowControl routines */ +/******************************************************************************/ + +/******************************************************************************* +* mvEthSpeedDuplexSet - Set Speed and Duplex of the port. +* +* DESCRIPTION: +* This function configure the port to work with desirable Duplex and Speed. +* Changing of these parameters are allowed only when port is disabled. +* This function disable the port if was enabled, change duplex and speed +* and, enable the port back if needed. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* ETH_PORT_SPEED speed - Speed of the port. +* ETH_PORT_SPEED duplex - Duplex of the port. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_OUT_OF_RANGE - Failed. Port is out of valid range +* MV_NOT_FOUND - Failed. Port is not initialized. +* MV_BAD_PARAM - Input parameters (speed/duplex) in conflict. +* MV_BAD_VALUE - Value of one of input parameters (speed, duplex) +* is not valid +* +*******************************************************************************/ +MV_STATUS mvEthSpeedDuplexSet(void* pPortHandle, MV_ETH_PORT_SPEED speed, + MV_ETH_PORT_DUPLEX duplex) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + MV_U32 portSerialCtrlReg; + + if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet()) ) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + /* Check validity */ + if( (speed == MV_ETH_SPEED_1000) && (duplex == MV_ETH_DUPLEX_HALF) ) + return MV_BAD_PARAM; + + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port)); + /* Set Speed */ + switch(speed) + { + case MV_ETH_SPEED_AN: + portSerialCtrlReg &= ~ETH_DISABLE_SPEED_AUTO_NEG_MASK; + break; + + case MV_ETH_SPEED_10: + portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK; + portSerialCtrlReg &= ~ETH_SET_MII_SPEED_100_MASK; + break; + + case MV_ETH_SPEED_100: + portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_GMII_SPEED_1000_MASK; + portSerialCtrlReg |= ETH_SET_MII_SPEED_100_MASK; + break; + + case MV_ETH_SPEED_1000: + portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_SET_GMII_SPEED_1000_MASK; + break; + + default: + mvOsPrintf("ethDrv: Unexpected Speed value %d\n", speed); + return MV_BAD_VALUE; + } + /* Set duplex */ + switch(duplex) + { + case MV_ETH_DUPLEX_AN: + portSerialCtrlReg &= ~ETH_DISABLE_DUPLEX_AUTO_NEG_MASK; + break; + + case MV_ETH_DUPLEX_HALF: + portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_FULL_DUPLEX_MASK; + break; + + case MV_ETH_DUPLEX_FULL: + portSerialCtrlReg |= ETH_DISABLE_DUPLEX_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_SET_FULL_DUPLEX_MASK; + break; + + default: + mvOsPrintf("ethDrv: Unexpected Duplex value %d\n", duplex); + return MV_BAD_VALUE; + } + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), portSerialCtrlReg); + + return MV_OK; +} + +/******************************************************************************* +* mvEthFlowCtrlSet - Set Flow Control of the port. +* +* DESCRIPTION: +* This function configure the port to work with desirable Duplex and +* Speed. Changing of these parameters are allowed only when port is +* disabled. This function disable the port if was enabled, change +* duplex and speed and, enable the port back if needed. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* MV_ETH_PORT_FC flowControl - Flow control of the port. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_OUT_OF_RANGE - Failed. Port is out of valid range +* MV_NOT_FOUND - Failed. Port is not initialized. +* MV_BAD_VALUE - Value flowControl parameters is not valid +* +*******************************************************************************/ +MV_STATUS mvEthFlowCtrlSet(void* pPortHandle, MV_ETH_PORT_FC flowControl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + MV_U32 portSerialCtrlReg; + + if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet() ) ) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port)); + switch(flowControl) + { + case MV_ETH_FC_AN_ADV_DIS: + portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_ADVERTISE_SYM_FC_MASK; + break; + + case MV_ETH_FC_AN_ADV_SYM: + portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_ADVERTISE_SYM_FC_MASK; + break; + + case MV_ETH_FC_DISABLE: + portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg &= ~ETH_SET_FLOW_CTRL_MASK; + break; + + case MV_ETH_FC_ENABLE: + portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK; + portSerialCtrlReg |= ETH_SET_FLOW_CTRL_MASK; + break; + + default: + mvOsPrintf("ethDrv: Unexpected FlowControl value %d\n", flowControl); + return MV_BAD_VALUE; + } + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), portSerialCtrlReg); + + return MV_OK; +} + +/******************************************************************************* +* mvEthHeaderModeSet - Set port header mode. +* +* DESCRIPTION: +* This function configures the port to work in Marvell-Header mode. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* MV_ETH_HEADER_MODE headerMode - The header mode to set the port in. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_NOT_SUPPORTED- Feature not supported. +* MV_OUT_OF_RANGE - Failed. Port is out of valid range +* MV_NOT_FOUND - Failed. Port is not initialized. +* MV_BAD_VALUE - Value of headerMode or numRxQueue parameter is not valid. +* +*******************************************************************************/ +MV_STATUS mvEthHeaderModeSet(void* pPortHandle, MV_ETH_HEADER_MODE headerMode) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + MV_U32 mvHeaderReg; + MV_U32 numRxQ = MV_ETH_RX_Q_NUM; + + if((port < 0) || (port >= mvCtrlEthMaxPortGet())) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + mvHeaderReg = MV_REG_READ(ETH_PORT_MARVELL_HEADER_REG(port)); + /* Disable header mode. */ + mvHeaderReg &= ~ETH_MVHDR_EN_MASK; + + if(headerMode != MV_ETH_DISABLE_HEADER_MODE) + { + /* Enable Header mode. */ + mvHeaderReg |= ETH_MVHDR_EN_MASK; + + /* Clear DA-Prefix & MHMask fields.*/ + mvHeaderReg &= ~(ETH_MVHDR_DAPREFIX_MASK | ETH_MVHDR_MHMASK_MASK); + + if(numRxQ > 1) + { + switch (headerMode) + { + case(MV_ETH_ENABLE_HEADER_MODE_PRI_2_1): + mvHeaderReg |= ETH_MVHDR_DAPREFIX_PRI_1_2; + break; + case(MV_ETH_ENABLE_HEADER_MODE_PRI_DBNUM): + mvHeaderReg |= ETH_MVHDR_DAPREFIX_DBNUM_PRI; + break; + case(MV_ETH_ENABLE_HEADER_MODE_PRI_SPID): + mvHeaderReg |= ETH_MVHDR_DAPREFIX_SPID_PRI; + break; + default: + break; + } + + switch (numRxQ) + { + case (4): + mvHeaderReg |= ETH_MVHDR_MHMASK_4_QUEUE; + break; + case (8): + mvHeaderReg |= ETH_MVHDR_MHMASK_8_QUEUE; + break; + default: + break; + } + } + } + + MV_REG_WRITE(ETH_PORT_MARVELL_HEADER_REG(port), mvHeaderReg); + + return MV_OK; +} + +#if (MV_ETH_VERSION >= 4) +/******************************************************************************* +* mvEthEjpModeSet - Enable / Disable EJP policy for TX. +* +* DESCRIPTION: +* This function +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* MV_BOOL TRUE - enable EJP mode +* FALSE - disable EJP mode +* +* OUTPUT: MV_STATUS +* MV_OK - Success +* Other - Failure +* +* RETURN: None. +* +*******************************************************************************/ +MV_STATUS mvEthEjpModeSet(void* pPortHandle, int mode) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + + if((port < 0) || (port >= mvCtrlEthMaxPortGet())) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + pPortCtrl->portConfig.ejpMode = mode; + if(mode) + { + /* EJP enabled - bit[18]=1, bit[19]=0 */ + pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(ETH_TX_EJP_ENABLE_MASK); + pPortCtrl->portTxQueueCmdReg &= ~MV_32BIT_LE_FAST(ETH_TX_LEGACY_WRR_MASK); + mvOsPrintf("EJP Enabled: portTxQueueCmdReg=0x%x\n", pPortCtrl->portTxQueueCmdReg); + } + else + { + /* EJP disabled - bit[18]=0, bit[19]=1 */ + pPortCtrl->portTxQueueCmdReg &= ~MV_32BIT_LE_FAST(ETH_TX_EJP_ENABLE_MASK); + pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(ETH_TX_LEGACY_WRR_MASK); + mvOsPrintf("EJP Disabled: portTxQueueCmdReg=0x%x\n", pPortCtrl->portTxQueueCmdReg); + } + + return MV_OK; +} +#endif /* MV_ETH_VERSION >= 4 */ + +/******************************************************************************* +* mvEthEjpModeSet - Enable / Disable EJP policy for TX. +* +* DESCRIPTION: +* This function +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* MV_BOOL TRUE - enable EJP mode +* FALSE - disable EJP mode +* +* OUTPUT: MV_STATUS +* MV_OK - Success +* Other - Failure +* +* RETURN: None. +* +*******************************************************************************/ +MV_STATUS mvEthEjpModeSet(void* pPortHandle, int mode) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + + if((port < 0) || (port >= mvCtrlEthMaxPortGet())) + return MV_OUT_OF_RANGE; + + pPortCtrl = ethPortCtrl[port]; + if(pPortCtrl == NULL) + return MV_NOT_FOUND; + + pPortCtrl->portConfig.ejpMode = mode; + if(mode) + { + /* EJP enabled - bit[18]=1, bit[19]=0 */ + pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(BIT18); + pPortCtrl->portTxQueueCmdReg &= ~MV_32BIT_LE_FAST(BIT19); + mvOsPrintf("EJP Enabled: portTxQueueCmdReg=0x%x\n", pPortCtrl->portTxQueueCmdReg); + } + else + { + /* EJP disabled - bit[18]=0, bit[19]=1 */ + pPortCtrl->portTxQueueCmdReg &= ~MV_32BIT_LE_FAST(BIT18); + pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(BIT19); + mvOsPrintf("EJP Disabled: portTxQueueCmdReg=0x%x\n", pPortCtrl->portTxQueueCmdReg); + } + + return MV_OK; +} + +/******************************************************************************* +* mvEthStatusGet - Get major properties of the port . +* +* DESCRIPTION: +* This function get major properties of the port (link, speed, duplex, +* flowControl, etc) and return them using the single structure. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* +* OUTPUT: +* MV_ETH_PORT_STATUS* pStatus - Pointer to structure, were port status +* will be placed. +* +* RETURN: None. +* +*******************************************************************************/ +void mvEthStatusGet(void* pPortHandle, MV_ETH_PORT_STATUS* pStatus) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + + MV_U32 regValue; + + regValue = MV_REG_READ( ETH_PORT_STATUS_REG(port) ); + + if(regValue & ETH_GMII_SPEED_1000_MASK) + pStatus->speed = MV_ETH_SPEED_1000; + else if(regValue & ETH_MII_SPEED_100_MASK) + pStatus->speed = MV_ETH_SPEED_100; + else + pStatus->speed = MV_ETH_SPEED_10; + + if(regValue & ETH_LINK_UP_MASK) + pStatus->isLinkUp = MV_TRUE; + else + pStatus->isLinkUp = MV_FALSE; + + if(regValue & ETH_FULL_DUPLEX_MASK) + pStatus->duplex = MV_ETH_DUPLEX_FULL; + else + pStatus->duplex = MV_ETH_DUPLEX_HALF; + + + if(regValue & ETH_ENABLE_RCV_FLOW_CTRL_MASK) + pStatus->flowControl = MV_ETH_FC_ENABLE; + else + pStatus->flowControl = MV_ETH_FC_DISABLE; +} + + +/******************************************************************************/ +/* PHY Control Functions */ +/******************************************************************************/ + + +/******************************************************************************* +* mvEthPhyAddrSet - Set the ethernet port PHY address. +* +* DESCRIPTION: +* This routine set the ethernet port PHY address according to given +* parameter. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* int phyAddr - PHY address +* +* RETURN: +* None. +* +*******************************************************************************/ +void mvEthPhyAddrSet(void* pPortHandle, int phyAddr) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + unsigned int regData; + + regData = MV_REG_READ(ETH_PHY_ADDR_REG(port)); + + regData &= ~ETH_PHY_ADDR_MASK; + regData |= phyAddr; + + MV_REG_WRITE(ETH_PHY_ADDR_REG(port), regData); + + return; +} + +/******************************************************************************* +* mvEthPhyAddrGet - Get the ethernet port PHY address. +* +* DESCRIPTION: +* This routine returns the given ethernet port PHY address. +* +* INPUT: +* void* pPortHandle - Pointer to port specific handler; +* +* +* RETURN: int - PHY address. +* +*******************************************************************************/ +int mvEthPhyAddrGet(void* pPortHandle) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHandle; + int port = pPortCtrl->portNo; + unsigned int regData; + + regData = MV_REG_READ(ETH_PHY_ADDR_REG(port)); + + return ((regData >> (5 * port)) & 0x1f); +} + +/******************************************************************************/ +/* Descriptor handling Functions */ +/******************************************************************************/ + +/******************************************************************************* +* etherInitRxDescRing - Curve a Rx chain desc list and buffer in memory. +* +* DESCRIPTION: +* This function prepares a Rx chained list of descriptors and packet +* buffers in a form of a ring. The routine must be called after port +* initialization routine and before port start routine. +* The Ethernet SDMA engine uses CPU bus addresses to access the various +* devices in the system (i.e. DRAM). This function uses the ethernet +* struct 'virtual to physical' routine (set by the user) to set the ring +* with physical addresses. +* +* INPUT: +* ETH_QUEUE_CTRL *pEthPortCtrl Ethernet Port Control srtuct. +* int rxQueue Number of Rx queue. +* int rxDescNum Number of Rx descriptors +* MV_U8* rxDescBaseAddr Rx descriptors memory area base addr. +* +* OUTPUT: +* The routine updates the Ethernet port control struct with information +* regarding the Rx descriptors and buffers. +* +* RETURN: None +* +*******************************************************************************/ +static void ethInitRxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue) +{ + ETH_RX_DESC *pRxDescBase, *pRxDesc, *pRxPrevDesc; + int ix, rxDescNum = pPortCtrl->rxQueueConfig[queue].descrNum; + ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->rxQueue[queue]; + + /* Make sure descriptor address is cache line size aligned */ + pRxDescBase = (ETH_RX_DESC*)MV_ALIGN_UP((MV_ULONG)pQueueCtrl->descBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + pRxDesc = (ETH_RX_DESC*)pRxDescBase; + pRxPrevDesc = pRxDesc; + + /* initialize the Rx descriptors ring */ + for (ix=0; ixbufSize = 0x0; + pRxDesc->byteCnt = 0x0; + pRxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pRxDesc->bufPtr = 0x0; + pRxDesc->returnInfo = 0x0; + pRxPrevDesc = pRxDesc; + if(ix == (rxDescNum-1)) + { + /* Closing Rx descriptors ring */ + pRxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pRxDescBase); + } + else + { + pRxDesc = (ETH_RX_DESC*)((MV_ULONG)pRxDesc + ETH_RX_DESC_ALIGNED_SIZE); + pRxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pRxDesc); + } + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxPrevDesc); + } + + pQueueCtrl->pCurrentDescr = pRxDescBase; + pQueueCtrl->pUsedDescr = pRxDescBase; + + pQueueCtrl->pFirstDescr = pRxDescBase; + pQueueCtrl->pLastDescr = pRxDesc; + pQueueCtrl->resource = 0; +} + +void ethResetRxDescRing(void* pPortHndl, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->rxQueue[queue]; + ETH_RX_DESC* pRxDesc = (ETH_RX_DESC*)pQueueCtrl->pFirstDescr; + + pQueueCtrl->resource = 0; + if(pQueueCtrl->pFirstDescr != NULL) + { + while(MV_TRUE) + { + pRxDesc->bufSize = 0x0; + pRxDesc->byteCnt = 0x0; + pRxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pRxDesc->bufPtr = 0x0; + pRxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc); + if( (void*)pRxDesc == pQueueCtrl->pLastDescr) + break; + pRxDesc = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl); + } + pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr; + pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr; + + /* Update RX Command register */ + pPortCtrl->portRxQueueCmdReg |= (1 << queue); + + /* update HW */ + MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + } + else + { + /* Update RX Command register */ + pPortCtrl->portRxQueueCmdReg &= ~(1 << queue); + + /* update HW */ + MV_REG_WRITE( ETH_RX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0); + } +} + +/******************************************************************************* +* etherInitTxDescRing - Curve a Tx chain desc list and buffer in memory. +* +* DESCRIPTION: +* This function prepares a Tx chained list of descriptors and packet +* buffers in a form of a ring. The routine must be called after port +* initialization routine and before port start routine. +* The Ethernet SDMA engine uses CPU bus addresses to access the various +* devices in the system (i.e. DRAM). This function uses the ethernet +* struct 'virtual to physical' routine (set by the user) to set the ring +* with physical addresses. +* +* INPUT: +* ETH_PORT_CTRL *pEthPortCtrl Ethernet Port Control srtuct. +* int txQueue Number of Tx queue. +* int txDescNum Number of Tx descriptors +* int txBuffSize Size of Tx buffer +* MV_U8* pTxDescBase Tx descriptors memory area base addr. +* +* OUTPUT: +* The routine updates the Ethernet port control struct with information +* regarding the Tx descriptors and buffers. +* +* RETURN: None. +* +*******************************************************************************/ +static void ethInitTxDescRing(ETH_PORT_CTRL* pPortCtrl, int queue) +{ + ETH_TX_DESC *pTxDescBase, *pTxDesc, *pTxPrevDesc; + int ix, txDescNum = pPortCtrl->txQueueConfig[queue].descrNum; + ETH_QUEUE_CTRL *pQueueCtrl = &pPortCtrl->txQueue[queue]; + + /* Make sure descriptor address is cache line size aligned */ + pTxDescBase = (ETH_TX_DESC*)MV_ALIGN_UP((MV_ULONG)pQueueCtrl->descBuf.bufVirtPtr, + CPU_D_CACHE_LINE_SIZE); + + pTxDesc = (ETH_TX_DESC*)pTxDescBase; + pTxPrevDesc = pTxDesc; + + /* initialize the Tx descriptors ring */ + for (ix=0; ixbyteCnt = 0x0000; + pTxDesc->L4iChk = 0x0000; + pTxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pTxDesc->bufPtr = 0x0; + pTxDesc->returnInfo = 0x0; + + pTxPrevDesc = pTxDesc; + + if(ix == (txDescNum-1)) + { + /* Closing Tx descriptors ring */ + pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDescBase); + } + else + { + pTxDesc = (ETH_TX_DESC*)((MV_ULONG)pTxDesc + ETH_TX_DESC_ALIGNED_SIZE); + pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDesc); + } + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxPrevDesc); + } + + pQueueCtrl->pCurrentDescr = pTxDescBase; + pQueueCtrl->pUsedDescr = pTxDescBase; + + pQueueCtrl->pFirstDescr = pTxDescBase; + pQueueCtrl->pLastDescr = pTxDesc; + /* Leave one TX descriptor out of use */ + pQueueCtrl->resource = txDescNum - 1; +} + +void ethResetTxDescRing(void* pPortHndl, int queue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->txQueue[queue]; + ETH_TX_DESC* pTxDesc = (ETH_TX_DESC*)pQueueCtrl->pFirstDescr; + + pQueueCtrl->resource = 0; + if(pQueueCtrl->pFirstDescr != NULL) + { + while(MV_TRUE) + { + pTxDesc->byteCnt = 0x0000; + pTxDesc->L4iChk = 0x0000; + pTxDesc->cmdSts = ETH_BUFFER_OWNED_BY_HOST; + pTxDesc->bufPtr = 0x0; + pTxDesc->returnInfo = 0x0; + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxDesc); + pQueueCtrl->resource++; + if( (void*)pTxDesc == pQueueCtrl->pLastDescr) + break; + pTxDesc = TX_NEXT_DESC_PTR(pTxDesc, pQueueCtrl); + } + /* Leave one TX descriptor out of use */ + pQueueCtrl->resource--; + pQueueCtrl->pCurrentDescr = pQueueCtrl->pFirstDescr; + pQueueCtrl->pUsedDescr = pQueueCtrl->pFirstDescr; + + /* Update TX Command register */ + pPortCtrl->portTxQueueCmdReg |= MV_32BIT_LE_FAST(1 << queue); + /* update HW */ + MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), + (MV_U32)ethDescVirtToPhy(pQueueCtrl, pQueueCtrl->pCurrentDescr) ); + } + else + { + /* Update TX Command register */ + pPortCtrl->portTxQueueCmdReg &= MV_32BIT_LE_FAST(~(1 << queue)); + /* update HW */ + MV_REG_WRITE( ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue), 0 ); + } +} + +/******************************************************************************* +* ethAllocDescrMemory - Free memory allocated for RX and TX descriptors. +* +* DESCRIPTION: +* This function allocates memory for RX and TX descriptors. +* - If ETH_DESCR_IN_SRAM defined, allocate memory from SRAM. +* - If ETH_DESCR_IN_SDRAM defined, allocate memory in SDRAM. +* +* INPUT: +* int size - size of memory should be allocated. +* +* RETURN: None +* +*******************************************************************************/ +static MV_U8* ethAllocDescrMemory(ETH_PORT_CTRL* pPortCtrl, int descSize, + MV_ULONG* pPhysAddr, MV_U32 *memHandle) +{ + MV_U8* pVirt; + +#if defined(ETH_DESCR_IN_SRAM) + if(ethDescInSram == MV_TRUE) + pVirt = (char*)mvSramMalloc(descSize, pPhysAddr); + else +#endif /* ETH_DESCR_IN_SRAM */ + { +#ifdef ETH_DESCR_UNCACHED + pVirt = (MV_U8*)mvOsIoUncachedMalloc(pPortCtrl->osHandle, descSize, + pPhysAddr,memHandle); +#else + pVirt = (MV_U8*)mvOsIoCachedMalloc(pPortCtrl->osHandle, descSize, + pPhysAddr, memHandle); +#endif /* ETH_DESCR_UNCACHED */ + } + memset(pVirt, 0, descSize); + + return pVirt; +} + +/******************************************************************************* +* ethFreeDescrMemory - Free memory allocated for RX and TX descriptors. +* +* DESCRIPTION: +* This function frees memory allocated for RX and TX descriptors. +* - If ETH_DESCR_IN_SRAM defined, free memory using gtSramFree() function. +* - If ETH_DESCR_IN_SDRAM defined, free memory using mvOsFree() function. +* +* INPUT: +* void* pVirtAddr - virtual pointer to memory allocated for RX and TX +* desriptors. +* +* RETURN: None +* +*******************************************************************************/ +void ethFreeDescrMemory(ETH_PORT_CTRL* pPortCtrl, MV_BUF_INFO* pDescBuf) +{ + if( (pDescBuf == NULL) || (pDescBuf->bufVirtPtr == NULL) ) + return; + +#if defined(ETH_DESCR_IN_SRAM) + if( ethDescInSram ) + { + mvSramFree(pDescBuf->bufSize, pDescBuf->bufPhysAddr, pDescBuf->bufVirtPtr); + return; + } +#endif /* ETH_DESCR_IN_SRAM */ + +#ifdef ETH_DESCR_UNCACHED + mvOsIoUncachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr, + pDescBuf->bufVirtPtr,pDescBuf->memHandle); +#else + mvOsIoCachedFree(pPortCtrl->osHandle, pDescBuf->bufSize, pDescBuf->bufPhysAddr, + pDescBuf->bufVirtPtr,pDescBuf->memHandle); +#endif /* ETH_DESCR_UNCACHED */ +} + +/******************************************************************************/ +/* Other Functions */ +/******************************************************************************/ + +void mvEthPortPowerUp(int port) +{ + MV_U32 regVal; + + if (mvBoardIsPortInSgmii(port)) + mvEthPortSgmiiConfig(port); + + /* Cancel Port Reset */ + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)); + regVal &= (~ETH_PORT_RESET_MASK); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal); + while( (MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) != 0); +} + +void mvEthPortPowerDown(int port) +{ +#if 0 + MV_U32 regVal; + + /* Port must be DISABLED */ + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port)); + if( (regVal & ETH_PORT_ENABLE_MASK) != 0) + { + mvOsPrintf("ethPort #%d: PowerDown - port must be Disabled (PSC=0x%x)\n", + port, regVal); + return; + } + + /* Port Reset (Read after write the register as a precaution) */ + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)); + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal | ETH_PORT_RESET_MASK); + while((MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) == 0); + + /* SERDES Reset (SERDES Config 0 Register bit0 ) */ + regVal = MV_REG_READ(ETH_SERDES_CFG_0_REG(port)); + MV_REG_WRITE(ETH_SERDES_CFG_0_REG(port), (regVal | ETH_SERDES_RST_MASK)); + /* (Wait several miliseconds as a precaution) */ + mvOsDelay(5); + + /* SERDESS Power Down (SERDES Config 0 Register bits 1-4) */ + regVal = MV_REG_READ(ETH_SERDES_CFG_0_REG(port)); + regVal &= ~(ETH_SERDES_TX_POWER_MASK | ETH_SERDES_RX_POWER_MASK | + ETH_SERDES_PLL_POWER_MASK | ETH_SERDES_IVREF_POWER_MASK); + MV_REG_WRITE(ETH_SERDES_CFG_0_REG(port), regVal); +#endif +} + +#if 0 +static void mvEthPortSgmiiConfig(int port) +{ + MV_U32 regVal; + + /* Enable working in INBAND_AUTO_NEG */ +/* if (mvCtrlModelGet() == MV_6082_DEV_ID) + { + regVal = MV_REG_READ(ETH_1MS_CLOCK_DIV_REG(port)); + regVal |= BIT31; + MV_REG_WRITE(ETH_1MS_CLOCK_DIV_REG(port), regVal); + } +*/ + regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)); + + regVal |= (ETH_SGMII_MODE_MASK /*| ETH_INBAND_AUTO_NEG_ENABLE_MASK */); + regVal &= (~ETH_INBAND_AUTO_NEG_BYPASS_MASK); + + MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal); +} + +#endif /* 0 */ diff --git a/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthDebug.c b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthDebug.c new file mode 100644 index 0000000..fa8165a --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthDebug.c @@ -0,0 +1,895 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEthDebug.c - Source file for user friendly debug functions +* +* DESCRIPTION: +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#include "mvOs.h" +#include "mvCommon.h" +#include "mvTypes.h" +#include "mv802_3.h" +#include "mvDebug.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "eth-phy/mvEthPhy.h" +#include "ethfp/mvEth.h" +#include "ethfp/mvEthPolicy.h" +#include "ethfp/mvEthDebug.h" + +/* #define mvOsPrintf printf */ + +void mvEthPortShow(void* pHndl); +void mvEthQueuesShow(void* pHndl, int rxQueue, int txQueue, int mode); +/******************************************************************************/ +/* Debug functions */ +/******************************************************************************/ +void ethRxCoal(int port, int usec) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthRxCoalSet(pHndl, usec); + } +} + +void ethTxCoal(int port, int usec) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthTxCoalSet(pHndl, usec); + } +} + +void ethEjpModeSet(int port, int mode) +{ +#if (MV_ETH_VERSION >= 4) + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthEjpModeSet(pHndl, mode); + } +#else + mvOsPrintf("Not supported\n"); +#endif /* (MV_ETH_VERSION >= 4) */ +} + +void ethBpduRxQ(int port, int bpduQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthBpduRxQueue(pHndl, bpduQueue); + } +} + +void ethArpRxQ(int port, int arpQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthArpRxQueue(pHndl, arpQueue); + } +} + +void ethTcpRxQ(int port, int tcpQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthTcpRxQueue(pHndl, tcpQueue); + } +} + +void ethUdpRxQ(int port, int udpQueue) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthUdpRxQueue(pHndl, udpQueue); + } +} + +#ifdef INCLUDE_MULTI_QUEUE +void ethRxPolMode(int port, MV_ETH_PRIO_MODE prioMode) +{ + void* pHndl; + + pHndl = mvEthRxPolicyHndlGet(port); + if(pHndl != NULL) + { + mvEthRxPolicyModeSet(pHndl, prioMode); + } +} + +void ethRxPolQ(int port, int queue, int quota) +{ + void* pHndl; + + pHndl = mvEthRxPolicyHndlGet(port); + if(pHndl != NULL) + { + mvEthRxPolicyQueueCfg(pHndl, queue, quota); + } +} + +void ethRxPolicy(int port) +{ + int queue; + ETH_RX_POLICY* pRxPolicy = (ETH_RX_POLICY*)mvEthRxPolicyHndlGet(port); + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)mvEthPortHndlGet(port); + + if( (pPortCtrl == NULL) || (pRxPolicy == NULL) ) + { + return; + } + + mvOsPrintf("rxDefQ=%d, arpQ=%d, bpduQ=%d, tcpQ=%d, udpQ=%d\n\n", + pPortCtrl->portConfig.rxDefQ, pPortCtrl->portConfig.rxArpQ, + pPortCtrl->portConfig.rxBpduQ, + pPortCtrl->portConfig.rxTcpQ, pPortCtrl->portConfig.rxUdpQ); + + mvOsPrintf("ethRxPolicy #%d: hndl=%p, mode=%s, curQ=%d, curQuota=%d\n", + pRxPolicy->port, pRxPolicy, + (pRxPolicy->rxPrioMode == MV_ETH_PRIO_FIXED) ? "FIXED" : "WRR", + pRxPolicy->rxCurQ, pRxPolicy->rxCurQuota); + + for(queue=0; queuerxQuota[queue]); + } +} + + +void ethTxPolDef(int port, int txQ, char* headerHexStr) +{ + void* pHndl; + MV_ETH_TX_POLICY_ENTRY polEntry; + + pHndl = mvEthTxPolicyHndlGet(port); + if(pHndl != NULL) + { + polEntry.txQ = txQ; + polEntry.pHeader = (MV_U8*)headerHexStr; + if(headerHexStr != NULL) + polEntry.headerSize = strlen(headerHexStr); + else + polEntry.headerSize = 0; + mvEthTxPolicyDef(pHndl, &polEntry); + } +} + + +#define MV_MAX_HEADER_LEN 64 +void ethTxPolDA(int port, char* macStr, int txQ, char* headerHexStr) +{ + void* pHndl; + MV_ETH_TX_POLICY_MACDA daPolicy; + MV_U8 header[MV_MAX_HEADER_LEN]; + + pHndl = mvEthTxPolicyHndlGet(port); + if(pHndl == NULL) + return; + + mvMacStrToHex(macStr, daPolicy.macDa); + if(txQ > 0) + { + daPolicy.policy.txQ = txQ; + if(headerHexStr != NULL) + { + /* each two char are one byte '55'-> 0x55 */ + daPolicy.policy.headerSize = strlen(headerHexStr)/2; + if(daPolicy.policy.headerSize > MV_MAX_HEADER_LEN) + return; + + mvAsciiToHex(headerHexStr, (char*)header); + daPolicy.policy.pHeader = header; + } + else + daPolicy.policy.headerSize = 0; + + mvEthTxPolicyAdd(pHndl, &daPolicy); + } + else + { + mvEthTxPolicyDel(pHndl, daPolicy.macDa); + } +} + +void ethTxPolicy(int port) +{ + ETH_TX_POLICY* pTxPolicy = (ETH_TX_POLICY*) mvEthTxPolicyHndlGet(port); + int idx, i, queue; + char macStr[MV_MAC_STR_SIZE]; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)mvEthPortHndlGet(port); + + if((pPortCtrl == NULL) || (pTxPolicy == NULL)) + { + return; + } + mvOsPrintf("Port #%d TX Policy: EJP=%d, TXQs: ", + port, pPortCtrl->portConfig.ejpMode); + + for(queue=0; queuetxQueueConfig[queue].descrNum > 0) + mvOsPrintf("%d, ", queue); + } + mvOsPrintf("\n"); + + mvOsPrintf("\n\t TX policy Port #%d configuration registers\n", port); + + mvOsPrintf("ETH_TX_FIXED_PRIO_CFG_REG : 0x%X = 0x%08x\n", + ETH_TX_FIXED_PRIO_CFG_REG(port), + MV_REG_READ( ETH_TX_FIXED_PRIO_CFG_REG(port) ) ); + + mvOsPrintf("ETH_TX_TOKEN_RATE_CFG_REG : 0x%X = 0x%08x\n", + ETH_TX_TOKEN_RATE_CFG_REG(port), + MV_REG_READ( ETH_TX_TOKEN_RATE_CFG_REG(port) ) ); + + mvOsPrintf("ETH_MAX_TRANSMIT_UNIT_REG : 0x%X = 0x%08x\n", + ETH_MAX_TRANSMIT_UNIT_REG(port), + MV_REG_READ( ETH_MAX_TRANSMIT_UNIT_REG(port) ) ); + + mvOsPrintf("ETH_TX_TOKEN_BUCKET_SIZE_REG : 0x%X = 0x%08x\n", + ETH_TX_TOKEN_BUCKET_SIZE_REG(port), + MV_REG_READ( ETH_TX_TOKEN_BUCKET_SIZE_REG(port) ) ); + + mvOsPrintf("ETH_TX_TOKEN_BUCKET_COUNT_REG : 0x%X = 0x%08x\n", + ETH_TX_TOKEN_BUCKET_COUNT_REG(port), + MV_REG_READ( ETH_TX_TOKEN_BUCKET_COUNT_REG(port) ) ); + + for(queue=0; queuetxQueueConfig[queue].prioMode == MV_ETH_PRIO_FIXED) ? "FIXED" : "WRR", + pPortCtrl->txQueueConfig[queue].quota ); + } + mvOsPrintf("\n"); + + mvOsPrintf("\nethDefTxPolicy : hndl=%p, defQ=%d, defHeader=%p, defSize=%d, maxDa=%d\n\n", + pTxPolicy, pTxPolicy->txPolDef.txQ, + pTxPolicy->txPolDef.pHeader, pTxPolicy->txPolDef.headerSize, + pTxPolicy->txPolMaxDa); + if(pTxPolicy->txPolDef.headerSize != 0) + { + for(i = 0; i < pTxPolicy->txPolDef.headerSize; i++) { + mvOsPrintf(" %02x",pTxPolicy->txPolDef.pHeader[i]); + if( (i & 0xf) == 0xf ) + mvOsPrintf("\n"); + } + mvOsPrintf("\n"); + } + + for(idx=0; idxtxPolMaxDa; idx++) + { + if(pTxPolicy->txPolDa[idx].policy.txQ == MV_INVALID) + continue; + + mvMacHexToStr(pTxPolicy->txPolDa[idx].macDa, macStr); + mvOsPrintf("%d. MAC = %s, txQ=%d, pHeader=%p, headerSize=%d\n", + idx, macStr, pTxPolicy->txPolDa[idx].policy.txQ, + pTxPolicy->txPolDa[idx].policy.pHeader, + pTxPolicy->txPolDa[idx].policy.headerSize); + if(pTxPolicy->txPolDa[idx].policy.headerSize != 0) + { + for(i = 0; i < pTxPolicy->txPolDa[idx].policy.headerSize; i++) + { + mvOsPrintf(" %02x",pTxPolicy->txPolDa[idx].policy.pHeader[i]); + if( (i & 0xf) == 0xf ) + mvOsPrintf("\n"); + } + mvOsPrintf("\n"); + } + } +} +#endif /* INCLUDE_MULTI_QUEUE */ + +/* Print important registers of Ethernet port */ +void ethPortRegs(int port) +{ + mvOsPrintf("\n\t ethGiga #%d port Registers:\n", port); + + mvOsPrintf("ETH_PORT_STATUS_REG : 0x%X = 0x%08x\n", + ETH_PORT_STATUS_REG(port), + MV_REG_READ( ETH_PORT_STATUS_REG(port) ) ); + + mvOsPrintf("ETH_PORT_SERIAL_CTRL_REG : 0x%X = 0x%08x\n", + ETH_PORT_SERIAL_CTRL_REG(port), + MV_REG_READ( ETH_PORT_SERIAL_CTRL_REG(port) ) ); + + mvOsPrintf("ETH_PORT_CONFIG_REG : 0x%X = 0x%08x\n", + ETH_PORT_CONFIG_REG(port), + MV_REG_READ( ETH_PORT_CONFIG_REG(port) ) ); + + mvOsPrintf("ETH_PORT_CONFIG_EXTEND_REG : 0x%X = 0x%08x\n", + ETH_PORT_CONFIG_EXTEND_REG(port), + MV_REG_READ( ETH_PORT_CONFIG_EXTEND_REG(port) ) ); + + mvOsPrintf("ETH_SDMA_CONFIG_REG : 0x%X = 0x%08x\n", + ETH_SDMA_CONFIG_REG(port), + MV_REG_READ( ETH_SDMA_CONFIG_REG(port) ) ); + + mvOsPrintf("ETH_TX_FIFO_URGENT_THRESH_REG : 0x%X = 0x%08x\n", + ETH_TX_FIFO_URGENT_THRESH_REG(port), + MV_REG_READ( ETH_TX_FIFO_URGENT_THRESH_REG(port) ) ); + + mvOsPrintf("ETH_RX_QUEUE_COMMAND_REG : 0x%X = 0x%08x\n", + ETH_RX_QUEUE_COMMAND_REG(port), + MV_REG_READ( ETH_RX_QUEUE_COMMAND_REG(port) ) ); + + mvOsPrintf("ETH_TX_QUEUE_COMMAND_REG : 0x%X = 0x%08x\n", + ETH_TX_QUEUE_COMMAND_REG(port), + MV_REG_READ( ETH_TX_QUEUE_COMMAND_REG(port) ) ); + + mvOsPrintf("ETH_INTR_CAUSE_REG : 0x%X = 0x%08x\n", + ETH_INTR_CAUSE_REG(port), + MV_REG_READ( ETH_INTR_CAUSE_REG(port) ) ); + + mvOsPrintf("ETH_INTR_EXTEND_CAUSE_REG : 0x%X = 0x%08x\n", + ETH_INTR_CAUSE_EXT_REG(port), + MV_REG_READ( ETH_INTR_CAUSE_EXT_REG(port) ) ); + + mvOsPrintf("ETH_INTR_MASK_REG : 0x%X = 0x%08x\n", + ETH_INTR_MASK_REG(port), + MV_REG_READ( ETH_INTR_MASK_REG(port) ) ); + + mvOsPrintf("ETH_INTR_EXTEND_MASK_REG : 0x%X = 0x%08x\n", + ETH_INTR_MASK_EXT_REG(port), + MV_REG_READ( ETH_INTR_MASK_EXT_REG(port) ) ); + + mvOsPrintf("ETH_RX_DESCR_STAT_CMD_REG : 0x%X = 0x%08x\n", + ETH_RX_DESCR_STAT_CMD_REG(port, 0), + MV_REG_READ( ETH_RX_DESCR_STAT_CMD_REG(port, 0) ) ); + + mvOsPrintf("ETH_RX_BYTE_COUNT_REG : 0x%X = 0x%08x\n", + ETH_RX_BYTE_COUNT_REG(port, 0), + MV_REG_READ( ETH_RX_BYTE_COUNT_REG(port, 0) ) ); + + mvOsPrintf("ETH_RX_BUF_PTR_REG : 0x%X = 0x%08x\n", + ETH_RX_BUF_PTR_REG(port, 0), + MV_REG_READ( ETH_RX_BUF_PTR_REG(port, 0) ) ); + + mvOsPrintf("ETH_RX_CUR_DESC_PTR_REG : 0x%X = 0x%08x\n", + ETH_RX_CUR_DESC_PTR_REG(port, 0), + MV_REG_READ( ETH_RX_CUR_DESC_PTR_REG(port, 0) ) ); +} + + +/* Print Giga Ethernet UNIT registers */ +void ethRegs(int port) +{ + mvOsPrintf("ETH_PHY_ADDR_REG : 0x%X = 0x%08x\n", + ETH_PHY_ADDR_REG(port), + MV_REG_READ(ETH_PHY_ADDR_REG(port)) ); + + mvOsPrintf("ETH_UNIT_INTR_CAUSE_REG : 0x%X = 0x%08x\n", + ETH_UNIT_INTR_CAUSE_REG(port), + MV_REG_READ( ETH_UNIT_INTR_CAUSE_REG(port)) ); + + mvOsPrintf("ETH_UNIT_INTR_MASK_REG : 0x%X = 0x%08x\n", + ETH_UNIT_INTR_MASK_REG(port), + MV_REG_READ( ETH_UNIT_INTR_MASK_REG(port)) ); + + mvOsPrintf("ETH_UNIT_ERROR_ADDR_REG : 0x%X = 0x%08x\n", + ETH_UNIT_ERROR_ADDR_REG(port), + MV_REG_READ(ETH_UNIT_ERROR_ADDR_REG(port)) ); + + mvOsPrintf("ETH_UNIT_INT_ADDR_ERROR_REG : 0x%X = 0x%08x\n", + ETH_UNIT_INT_ADDR_ERROR_REG(port), + MV_REG_READ(ETH_UNIT_INT_ADDR_ERROR_REG(port)) ); + +} + +/******************************************************************************/ +/* MIB Counters functions */ +/******************************************************************************/ + +/******************************************************************************* +* ethClearMibCounters - Clear all MIB counters +* +* DESCRIPTION: +* This function clears all MIB counters of a specific ethernet port. +* A read from the MIB counter will reset the counter. +* +* INPUT: +* int port - Ethernet Port number. +* +* RETURN: None +* +*******************************************************************************/ +void ethClearCounters(int port) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + mvEthMibCountersClear(pHndl); + + return; +} + + +/* Print counters of the Ethernet port */ +void ethPortCounters(int port) +{ + MV_U32 regValue, regValHigh; + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl == NULL) + return; + + mvOsPrintf("\n\t Port #%d MIB Counters\n\n", port); + + mvOsPrintf("GoodFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_FRAMES_RECEIVED, NULL)); + mvOsPrintf("BadFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_BAD_FRAMES_RECEIVED, NULL)); + mvOsPrintf("BroadcastFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_BROADCAST_FRAMES_RECEIVED, NULL)); + mvOsPrintf("MulticastFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_MULTICAST_FRAMES_RECEIVED, NULL)); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, + ®ValHigh); + mvOsPrintf("GoodOctetsReceived = 0x%08x%08x\n", + regValHigh, regValue); + + mvOsPrintf("\n"); + mvOsPrintf("GoodFramesSent = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_FRAMES_SENT, NULL)); + mvOsPrintf("BroadcastFramesSent = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_BROADCAST_FRAMES_SENT, NULL)); + mvOsPrintf("MulticastFramesSent = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_MULTICAST_FRAMES_SENT, NULL)); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_OCTETS_SENT_LOW, + ®ValHigh); + mvOsPrintf("GoodOctetsSent = 0x%08x%08x\n", regValHigh, regValue); + + + mvOsPrintf("\n\t FC Control Counters\n"); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_UNREC_MAC_CONTROL_RECEIVED, NULL); + mvOsPrintf("UnrecogMacControlReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_GOOD_FC_RECEIVED, NULL); + mvOsPrintf("GoodFCFramesReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_BAD_FC_RECEIVED, NULL); + mvOsPrintf("BadFCFramesReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_FC_SENT, NULL); + mvOsPrintf("FCFramesSent = %u\n", regValue); + + + mvOsPrintf("\n\t RX Errors\n"); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_BAD_OCTETS_RECEIVED, NULL); + mvOsPrintf("BadOctetsReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_UNDERSIZE_RECEIVED, NULL); + mvOsPrintf("UndersizeFramesReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_FRAGMENTS_RECEIVED, NULL); + mvOsPrintf("FragmentsReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_OVERSIZE_RECEIVED, NULL); + mvOsPrintf("OversizeFramesReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_JABBER_RECEIVED, NULL); + mvOsPrintf("JabbersReceived = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_MAC_RECEIVE_ERROR, NULL); + mvOsPrintf("MacReceiveErrors = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_BAD_CRC_EVENT, NULL); + mvOsPrintf("BadCrcReceived = %u\n", regValue); + + mvOsPrintf("\n\t TX Errors\n"); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR, NULL); + mvOsPrintf("TxMacErrors = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_EXCESSIVE_COLLISION, NULL); + mvOsPrintf("TxExcessiveCollisions = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_COLLISION, NULL); + mvOsPrintf("TxCollisions = %u\n", regValue); + + regValue = mvEthMibCounterRead(pHndl, ETH_MIB_LATE_COLLISION, NULL); + mvOsPrintf("TxLateCollisions = %u\n", regValue); + + + mvOsPrintf("\n"); + regValue = MV_REG_READ( ETH_RX_DISCARD_PKTS_CNTR_REG(port)); + mvOsPrintf("Rx Discard packets counter = %u\n", regValue); + + regValue = MV_REG_READ(ETH_RX_OVERRUN_PKTS_CNTR_REG(port)); + mvOsPrintf("Rx Overrun packets counter = %u\n", regValue); +} + +/* Print RMON counters of the Ethernet port */ +void ethPortRmonCounters(int port) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl == NULL) + return; + + mvOsPrintf("\n\t Port #%d RMON MIB Counters\n\n", port); + + mvOsPrintf("64 ByteFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_64_OCTETS, NULL)); + mvOsPrintf("65...127 ByteFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_65_TO_127_OCTETS, NULL)); + mvOsPrintf("128...255 ByteFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_128_TO_255_OCTETS, NULL)); + mvOsPrintf("256...511 ByteFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_256_TO_511_OCTETS, NULL)); + mvOsPrintf("512...1023 ByteFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_512_TO_1023_OCTETS, NULL)); + mvOsPrintf("1024...Max ByteFramesReceived = %u\n", + mvEthMibCounterRead(pHndl, ETH_MIB_FRAMES_1024_TO_MAX_OCTETS, NULL)); +} + +/* Print port information */ +void ethPortStatus(int port) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthPortShow(pHndl); + } +} + +/* Print port queues information */ +void ethPortQueues(int port, int rxQueue, int txQueue, int mode) +{ + void* pHndl; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvEthQueuesShow(pHndl, rxQueue, txQueue, mode); + } +} + +void ethUcastSet(int port, char* macStr, int queue) +{ + void* pHndl; + MV_U8 macAddr[MV_MAC_ADDR_SIZE]; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvMacStrToHex(macStr, macAddr); + mvEthMacAddrSet(pHndl, macAddr, queue); + } +} + + +void ethPortUcastShow(int port) +{ + MV_U32 unicastReg, macL, macH; + int i, j; + + macL = MV_REG_READ(ETH_MAC_ADDR_LOW_REG(port)); + macH = MV_REG_READ(ETH_MAC_ADDR_HIGH_REG(port)); + + mvOsPrintf("\n\t Port #%d Unicast MAC table: %02x:%02x:%02x:%02x:%02x:%02x\n\n", + port, ((macH >> 24) & 0xff), ((macH >> 16) & 0xff), + ((macH >> 8) & 0xff), (macH & 0xff), + ((macL >> 8) & 0xff), (macL & 0xff) ); + + for (i=0; i<4; i++) + { + unicastReg = MV_REG_READ( (ETH_DA_FILTER_UCAST_BASE(port) + i*4)); + for(j=0; j<4; j++) + { + MV_U8 macEntry = (unicastReg >> (8*j)) & 0xFF; + + mvOsPrintf("%X: %8s, Q = %d\n", i*4+j, + (macEntry & BIT0) ? "Accept" : "Reject", (macEntry >> 1) & 0x7); + } + } +} + +void ethMcastAdd(int port, char* macStr, int queue) +{ + void* pHndl; + MV_U8 macAddr[MV_MAC_ADDR_SIZE]; + + pHndl = mvEthPortHndlGet(port); + if(pHndl != NULL) + { + mvMacStrToHex(macStr, macAddr); + mvEthMcastAddrSet(pHndl, macAddr, queue); + } +} + +void ethPortMcast(int port) +{ + int tblIdx, regIdx; + MV_U32 regVal; + + mvOsPrintf("\n\t Port #%d Special (IP) Multicast table: 01:00:5E:00:00:XX\n\n", + port); + + for(tblIdx=0; tblIdx<(256/4); tblIdx++) + { + regVal = MV_REG_READ((ETH_DA_FILTER_SPEC_MCAST_BASE(port) + tblIdx*4)); + for(regIdx=0; regIdx<4; regIdx++) + { + if((regVal & (0x01 << (regIdx*8))) != 0) + { + mvOsPrintf("0x%02X: Accepted, rxQ = %d\n", + tblIdx*4+regIdx, ((regVal >> (regIdx*8+1)) & 0x07)); + } + } + } + mvOsPrintf("\n\t Port #%d Other Multicast table\n\n", port); + for(tblIdx=0; tblIdx<(256/4); tblIdx++) + { + regVal = MV_REG_READ((ETH_DA_FILTER_OTH_MCAST_BASE(port) + tblIdx*4)); + for(regIdx=0; regIdx<4; regIdx++) + { + if((regVal & (0x01 << (regIdx*8))) != 0) + { + mvOsPrintf("Crc8=0x%02X: Accepted, rxQ = %d\n", + tblIdx*4+regIdx, ((regVal >> (regIdx*8+1)) & 0x07)); + } + } + } +} + + +/* Print status of Ethernet port */ +void mvEthPortShow(void* pHndl) +{ + MV_U32 regValue, rxCoal, txCoal; + int speed, queue, port; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pHndl; + + port = pPortCtrl->portNo; + + regValue = MV_REG_READ( ETH_PORT_STATUS_REG(port) ); + + mvOsPrintf("\n\t ethGiga #%d port Status: 0x%04x = 0x%08x\n\n", + port, ETH_PORT_STATUS_REG(port), regValue); + + mvOsPrintf("descInSram=%d, descSwCoher=%d\n", + ethDescInSram, ethDescSwCoher); + + if(regValue & ETH_GMII_SPEED_1000_MASK) + speed = 1000; + else if(regValue & ETH_MII_SPEED_100_MASK) + speed = 100; + else + speed = 10; + + mvEthCoalGet(pPortCtrl, &rxCoal, &txCoal); + + /* Link, Speed, Duplex, FlowControl */ + mvOsPrintf("Link=%s, Speed=%d, Duplex=%s, RxFlowControl=%s", + (regValue & ETH_LINK_UP_MASK) ? "UP" : "DOWN", + speed, + (regValue & ETH_FULL_DUPLEX_MASK) ? "FULL" : "HALF", + (regValue & ETH_ENABLE_RCV_FLOW_CTRL_MASK) ? "ENABLE" : "DISABLE"); + + mvOsPrintf("\n"); + + mvOsPrintf("RxCoal = %d usec, TxCoal = %d usec\n", + rxCoal, txCoal); + + /* Print all RX and TX queues */ + for(queue=0; queuerxQueue[queue].pFirstDescr, + mvEthRxResourceGet(pPortCtrl, queue) ); + } + mvOsPrintf("\n"); + for(queue=0; queuetxQueue[queue].pFirstDescr, + mvEthTxResourceGet(pPortCtrl, queue) ); + } +} + +/* Print RX and TX queue of the Ethernet port */ +void mvEthQueuesShow(void* pHndl, int rxQueue, int txQueue, int mode) +{ + ETH_PORT_CTRL *pPortCtrl = (ETH_PORT_CTRL*)pHndl; + ETH_QUEUE_CTRL *pQueueCtrl; + MV_U32 regValue; + ETH_RX_DESC *pRxDescr; + ETH_TX_DESC *pTxDescr; + int i, port = pPortCtrl->portNo; + + if( (rxQueue >=0) && (rxQueue < MV_ETH_RX_Q_NUM) ) + { + pQueueCtrl = &(pPortCtrl->rxQueue[rxQueue]); + mvOsPrintf("Port #%d, RX Queue #%d\n\n", port, rxQueue); + + mvOsPrintf("CURR_RX_DESC_PTR : 0x%X = 0x%08x\n", + ETH_RX_CUR_DESC_PTR_REG(port, rxQueue), + MV_REG_READ( ETH_RX_CUR_DESC_PTR_REG(port, rxQueue))); + + + if(pQueueCtrl->pFirstDescr != NULL) + { + mvOsPrintf("pFirstDescr=0x%lx, pLastDescr=0x%lx, numOfResources=%d\n", + (MV_ULONG)pQueueCtrl->pFirstDescr, (MV_ULONG)pQueueCtrl->pLastDescr, + pQueueCtrl->resource); + mvOsPrintf("pCurrDescr: 0x%lx, pUsedDescr: 0x%lx\n", + (MV_ULONG)pQueueCtrl->pCurrentDescr, + (MV_ULONG)pQueueCtrl->pUsedDescr); + + if(mode == 1) + { + pRxDescr = (ETH_RX_DESC*)pQueueCtrl->pFirstDescr; + i = 0; + do + { + mvOsPrintf("%3d. desc=%08x (%08x), cmd=%08x, data=%4d, buf=%4d, buf=%08x, pkt=%lx, os=%lx\n", + i, (MV_U32)pRxDescr, (MV_U32)ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pRxDescr), + pRxDescr->cmdSts, pRxDescr->byteCnt, (MV_U32)pRxDescr->bufSize, + (unsigned int)pRxDescr->bufPtr, (MV_ULONG)pRxDescr->returnInfo, + ((MV_PKT_INFO*)pRxDescr->returnInfo)->osInfo); + + ETH_DESCR_INV(pPortCtrl, pRxDescr); + pRxDescr = RX_NEXT_DESC_PTR(pRxDescr, pQueueCtrl); + i++; + } while (pRxDescr != pQueueCtrl->pFirstDescr); + } + } + else + mvOsPrintf("RX Queue #%d is NOT CREATED\n", rxQueue); + } + + if( (txQueue >=0) && (txQueue < MV_ETH_TX_Q_NUM) ) + { + pQueueCtrl = &(pPortCtrl->txQueue[txQueue]); + mvOsPrintf("Port #%d, TX Queue #%d\n\n", port, txQueue); + + regValue = MV_REG_READ( ETH_TX_CUR_DESC_PTR_REG(port, txQueue)); + mvOsPrintf("CURR_TX_DESC_PTR : 0x%X = 0x%08x\n", + ETH_TX_CUR_DESC_PTR_REG(port, txQueue), regValue); + + if(pQueueCtrl->pFirstDescr != NULL) + { + mvOsPrintf("pFirstDescr=0x%lx, pLastDescr=0x%lx, numOfResources=%d\n", + (MV_ULONG)pQueueCtrl->pFirstDescr, + (MV_ULONG)pQueueCtrl->pLastDescr, + pQueueCtrl->resource); + mvOsPrintf("pCurrDescr: 0x%lx, pUsedDescr: 0x%lx\n", + (MV_ULONG)pQueueCtrl->pCurrentDescr, + (MV_ULONG)pQueueCtrl->pUsedDescr); + + if(mode == 1) + { + pTxDescr = (ETH_TX_DESC*)pQueueCtrl->pFirstDescr; + i = 0; + do + { + mvOsPrintf("%3d. desc=%08x (%08x), cmd=%08x, data=%4d, buf=%08x, pkt=%lx, os=%lx\n", + i, (MV_U32)pTxDescr, (MV_U32)ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pTxDescr), + pTxDescr->cmdSts, pTxDescr->byteCnt, + (MV_U32)pTxDescr->bufPtr, (MV_ULONG)pTxDescr->returnInfo, + pTxDescr->returnInfo ? (((MV_PKT_INFO*)pTxDescr->returnInfo)->osInfo) : 0x0); + + ETH_DESCR_INV(pPortCtrl, pTxDescr); + pTxDescr = TX_NEXT_DESC_PTR(pTxDescr, pQueueCtrl); + i++; + } while (pTxDescr != pQueueCtrl->pFirstDescr); + } + } + else + mvOsPrintf("TX Queue #%d is NOT CREATED\n", txQueue); + } +} diff --git a/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthGbe.h b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthGbe.h new file mode 100644 index 0000000..229245f --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthGbe.h @@ -0,0 +1,741 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEth.h - Header File for : Marvell Gigabit Ethernet Controller +* +* DESCRIPTION: +* This header file contains macros typedefs and function declaration specific to +* the Marvell Gigabit Ethernet Controller. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __mvEthGbe_h__ +#define __mvEthGbe_h__ + +extern MV_BOOL ethDescInSram; +extern MV_BOOL ethDescSwCoher; +extern ETH_PORT_CTRL* ethPortCtrl[]; + +static INLINE MV_ULONG ethDescVirtToPhy(ETH_QUEUE_CTRL* pQueueCtrl, MV_U8* pDesc) +{ +#if defined (ETH_DESCR_IN_SRAM) + if( ethDescInSram ) + return mvSramVirtToPhy(pDesc); + else +#endif /* ETH_DESCR_IN_SRAM */ + return (pQueueCtrl->descBuf.bufPhysAddr + (pDesc - pQueueCtrl->descBuf.bufVirtPtr)); +} +/* Return port handler */ +#define mvEthPortHndlGet(port) ethPortCtrl[port] + +/* Used as WA for HW/SW race on TX */ +static INLINE int mvEthPortTxEnable(void* pPortHndl, int queue, int max_deep) +{ + int deep = 0; + MV_U32 txCurrReg, txEnReg; + ETH_TX_DESC* pTxLastDesc; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + txEnReg = MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)); + if( (txEnReg & MV_32BIT_LE_FAST(ETH_TXQ_ENABLE_MASK)) == 0) + { + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg; + return 0; + } + + pQueueCtrl = &pPortCtrl->txQueue[queue]; + pTxLastDesc = pQueueCtrl->pCurrentDescr; + txCurrReg = MV_REG_READ(ETH_TX_CUR_DESC_PTR_REG(pPortCtrl->portNo, queue)); + if(ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pTxLastDesc) == txCurrReg) + { + /* All descriptors are processed, no chance for race */ + return 0; + } + + /* Check distance betwee HW and SW location: */ + /* If distance between HW and SW pointers is less than mvEthTxEnDeep descriptors */ + /* Race condition is possible, so wait end of TX and restart TXQ */ + while(deep < max_deep) + { + pTxLastDesc = TX_PREV_DESC_PTR(pTxLastDesc, pQueueCtrl); + if(ethDescVirtToPhy(pQueueCtrl, (MV_U8*)pTxLastDesc) == txCurrReg) + { + int count = 0; + + while( (txEnReg & MV_32BIT_LE_FAST(0x000000FF)) != 0) + { + count++; + if(count > 10000) + { + mvOsPrintf("mvEthPortTxEnable: timeout - TXQ_CMD=0x%08x\n", + MV_REG_READ(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) ); + break; + } + txEnReg = MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)); + } + + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg; + return count; + } + deep++; + } + /* Distance between HW and SW pointers is more than mvEthTxEnDeep descriptors, */ + /* So NO race condition - do nothing */ + return -1; +} + + +/* defines */ +#define ETH_CSUM_MIN_BYTE_COUNT 72 + +/* Tailgate and Kirwood have only 2K TX FIFO */ +#if (MV_ETH_VERSION == 2) || (MV_ETH_VERSION == 4) +#define ETH_CSUM_MAX_BYTE_COUNT 1600 +#else +#define ETH_CSUM_MAX_BYTE_COUNT 9*1024 +#endif /* MV_ETH_VERSION */ + +#define ETH_MV_HEADER_SIZE 2 +#define ETH_MV_TX_EN + +/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */ +#define MIN_TX_BUFF_LOAD 8 +#define TX_BUF_OFFSET_IN_DESC (ETH_TX_DESC_ALIGNED_SIZE - MIN_TX_BUFF_LOAD) + +/* Default port configuration value */ +#define PORT_CONFIG_VALUE \ + ETH_DEF_RX_QUEUE_MASK(0) | \ + ETH_DEF_RX_ARP_QUEUE_MASK(0) | \ + ETH_DEF_RX_TCP_QUEUE_MASK(0) | \ + ETH_DEF_RX_UDP_QUEUE_MASK(0) | \ + ETH_DEF_RX_BPDU_QUEUE_MASK(0) | \ + ETH_RX_CHECKSUM_WITH_PSEUDO_HDR + +/* Default port extend configuration value */ +#define PORT_CONFIG_EXTEND_VALUE 0 + +#define PORT_SERIAL_CONTROL_VALUE \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE | \ + ETH_SET_FULL_DUPLEX_MASK + +#define PORT_SERIAL_CONTROL_100MB_FORCE_VALUE \ + ETH_FORCE_LINK_PASS_MASK | \ + ETH_DISABLE_DUPLEX_AUTO_NEG_MASK | \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_DISABLE_SPEED_AUTO_NEG_MASK | \ + ETH_SET_FULL_DUPLEX_MASK | \ + ETH_SET_MII_SPEED_100_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE + + +#define PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE \ + ETH_FORCE_LINK_PASS_MASK | \ + ETH_DISABLE_DUPLEX_AUTO_NEG_MASK | \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_DISABLE_SPEED_AUTO_NEG_MASK | \ + ETH_SET_FULL_DUPLEX_MASK | \ + ETH_SET_GMII_SPEED_1000_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE + +#define PORT_SERIAL_CONTROL_SGMII_IBAN_VALUE \ + ETH_DISABLE_FC_AUTO_NEG_MASK | \ + BIT9 | \ + ETH_IN_BAND_AN_EN_MASK | \ + ETH_DO_NOT_FORCE_LINK_FAIL_MASK | \ + ETH_MAX_RX_PACKET_1552BYTE + +/* Function headers: */ +MV_VOID mvEthSetSpecialMcastTable(int portNo, int queue); +MV_STATUS mvEthArpRxQueue(void* pPortHandle, int arpQueue); +MV_STATUS mvEthUdpRxQueue(void* pPortHandle, int udpQueue); +MV_STATUS mvEthTcpRxQueue(void* pPortHandle, int tcpQueue); +MV_STATUS mvEthMacAddrGet(int portNo, unsigned char *pAddr); +MV_VOID mvEthSetOtherMcastTable(int portNo, int queue); +MV_STATUS mvEthHeaderModeSet(void* pPortHandle, MV_ETH_HEADER_MODE headerMode); +/* Interrupt Coalesting functions */ +MV_U32 mvEthRxCoalSet(void* pPortHndl, MV_U32 uSec); +MV_U32 mvEthTxCoalSet(void* pPortHndl, MV_U32 uSec); +MV_STATUS mvEthCoalGet(void* pPortHndl, MV_U32* pRxCoal, MV_U32* pTxCoal); + +/******************************************************************************/ +/* Data Flow functions */ +/******************************************************************************/ +static INLINE void mvEthPortTxRestart(void* pPortHndl) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(pPortCtrl->portNo)) = pPortCtrl->portTxQueueCmdReg; +} + +/* Get number of Free resources in specific TX queue */ +static INLINE int mvEthTxResourceGet(void* pPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + return (pPortCtrl->txQueue[txQueue].resource); +} + +/* Get number of Free resources in specific RX queue */ +static INLINE int mvEthRxResourceGet(void* pPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + return (pPortCtrl->rxQueue[rxQueue].resource); +} + +static INLINE int mvEthTxQueueIsFull(void* pPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + if(pPortCtrl->txQueue[txQueue].resource == 0) + return MV_TRUE; + + return MV_FALSE; +} + +/* Get number of Free resources in specific RX queue */ +static INLINE int mvEthRxQueueIsFull(void* pPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->rxQueue[rxQueue]; + + if( (pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && + (pQueueCtrl->resource != 0) ) + return MV_TRUE; + + return MV_FALSE; +} + +static INLINE int mvEthTxQueueIsEmpty(void* pPortHndl, int txQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + if( (pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && + (pQueueCtrl->resource != 0) ) + { + return MV_TRUE; + } + return MV_FALSE; +} + +/* Get number of Free resources in specific RX queue */ +static INLINE int mvEthRxQueueIsEmpty(void* pPortHndl, int rxQueue) +{ + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pPortHndl; + + if(pPortCtrl->rxQueue[rxQueue].resource == 0) + return MV_TRUE; + + return MV_FALSE; +} + +/******************************************************************************* +* mvEthPortTx - Send an Ethernet packet +* +* DESCRIPTION: +* This routine send a given packet described by pPktInfo parameter. +* Single buffer only. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of Tx queue. +* MV_PKT_INFO *pPktInfo - User packet to send. +* +* RETURN: +* MV_NO_RESOURCE - No enough resources to send this packet. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - Packet send successfully. +* +*******************************************************************************/ +static INLINE MV_STATUS mvEthPortTx(void* pEthPortHndl, int txQueue, MV_PKT_INFO* pPktInfo) +{ + ETH_TX_DESC* pTxCurrDesc; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + int portNo; + MV_BUF_INFO* pBufInfo = pPktInfo->pFrags; + +#ifdef ETH_DEBUG + if(pPortCtrl->portState != MV_ACTIVE) + return MV_BAD_STATE; +#endif /* ETH_DEBUG */ + + portNo = pPortCtrl->portNo; + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + /* Get the Tx Desc ring indexes */ + pTxCurrDesc = pQueueCtrl->pCurrentDescr; + + /* Check if there is enough resources to send the packet */ + if(pQueueCtrl->resource == 0) + return MV_NO_RESOURCE; + + pTxCurrDesc->bufPtr = pBufInfo->bufPhysAddr; + pTxCurrDesc->byteCnt = pBufInfo->dataSize; + + /* Flash Buffer */ + if(pPktInfo->pktSize != 0) + { + ETH_PACKET_CACHE_FLUSH(pBufInfo->bufVirtPtr, pPktInfo->pktSize); + pPktInfo->pktSize = 0; + } + + pTxCurrDesc->returnInfo = (MV_ULONG)pPktInfo; + + /* There is only one buffer in the packet */ + /* The OSG might set some bits for checksum offload, so add them to first descriptor */ + pTxCurrDesc->cmdSts = pPktInfo->status | + ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_GENERATE_CRC_MASK | + ETH_TX_ENABLE_INTERRUPT_MASK | + ETH_TX_ZERO_PADDING_MASK | + ETH_TX_FIRST_DESC_MASK | + ETH_TX_LAST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + + pQueueCtrl->resource--; + pQueueCtrl->pCurrentDescr = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl); + + /* Apply send command */ + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(portNo)) = pPortCtrl->portTxQueueCmdReg; + + return MV_OK; +} + + +/******************************************************************************* +* mvEthPortSgTx - Send an Ethernet packet +* +* DESCRIPTION: +* This routine send a given packet described by pBufInfo parameter. It +* supports transmitting of a packet spaned over multiple buffers. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of Tx queue. +* MV_PKT_INFO *pPktInfo - User packet to send. +* +* RETURN: +* MV_NO_RESOURCE - No enough resources to send this packet. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - Packet send successfully. +* +*******************************************************************************/ +static INLINE MV_STATUS mvEthPortSgTx(void* pEthPortHndl, int txQueue, MV_PKT_INFO* pPktInfo) +{ + ETH_TX_DESC* pTxFirstDesc; + ETH_TX_DESC* pTxCurrDesc; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + int portNo, bufCount; + MV_BUF_INFO* pBufInfo = pPktInfo->pFrags; + MV_U8* pTxBuf; + +#ifdef ETH_DEBUG + if(pPortCtrl->portState != MV_ACTIVE) + return MV_BAD_STATE; +#endif /* ETH_DEBUG */ + + portNo = pPortCtrl->portNo; + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + /* Get the Tx Desc ring indexes */ + pTxCurrDesc = pQueueCtrl->pCurrentDescr; + + /* Check if there is enough resources to send the packet */ + if(pQueueCtrl->resource < pPktInfo->numFrags) + return MV_NO_RESOURCE; + + /* Remember first desc */ + pTxFirstDesc = pTxCurrDesc; + + bufCount = 0; + while(MV_TRUE) + { + if(pBufInfo[bufCount].dataSize <= MIN_TX_BUFF_LOAD) + { + /* Buffers with a payload smaller than MIN_TX_BUFF_LOAD (8 bytes) must be aligned */ + /* to 64-bit boundary. Two options here: */ + /* 1) Usually, copy the payload to the reserved 8 bytes inside descriptor. */ + /* 2) In the Half duplex workaround, the reserved 8 bytes inside descriptor are used */ + /* as a pointer to the aligned buffer, copy the small payload to this buffer. */ + pTxBuf = ((MV_U8*)pTxCurrDesc)+TX_BUF_OFFSET_IN_DESC; + mvOsBCopy(pBufInfo[bufCount].bufVirtPtr, pTxBuf, pBufInfo[bufCount].dataSize); + pTxCurrDesc->bufPtr = ethDescVirtToPhy(pQueueCtrl, pTxBuf); + } + else + { + pTxCurrDesc->bufPtr = mvOsIoVirtToPhy(NULL, pBufInfo[bufCount].bufVirtPtr); + /* Flash Buffer */ + ETH_PACKET_CACHE_FLUSH(pBufInfo[bufCount].bufVirtPtr, pBufInfo[bufCount].dataSize); + } + + pTxCurrDesc->byteCnt = pBufInfo[bufCount].dataSize; + bufCount++; + + if(bufCount >= pPktInfo->numFrags) + break; + + if(bufCount > 1) + { + /* There is middle buffer of the packet Not First and Not Last */ + pTxCurrDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA; + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + } + /* Go to next descriptor and next buffer */ + pTxCurrDesc = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl); + } + /* Set last desc with DMA ownership and interrupt enable. */ + pTxCurrDesc->returnInfo = (MV_ULONG)pPktInfo; + if(bufCount == 1) + { + /* There is only one buffer in the packet */ + /* The OSG might set some bits for checksum offload, so add them to first descriptor */ + pTxCurrDesc->cmdSts = pPktInfo->status | + ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_GENERATE_CRC_MASK | + ETH_TX_ENABLE_INTERRUPT_MASK | + ETH_TX_ZERO_PADDING_MASK | + ETH_TX_FIRST_DESC_MASK | + ETH_TX_LAST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + } + else + { + /* Last but not First */ + pTxCurrDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_ENABLE_INTERRUPT_MASK | + ETH_TX_ZERO_PADDING_MASK | + ETH_TX_LAST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc); + + /* Update First when more than one buffer in the packet */ + /* The OSG might set some bits for checksum offload, so add them to first descriptor */ + pTxFirstDesc->cmdSts = pPktInfo->status | + ETH_BUFFER_OWNED_BY_DMA | + ETH_TX_GENERATE_CRC_MASK | + ETH_TX_FIRST_DESC_MASK; + + ETH_DESCR_FLUSH_INV(pPortCtrl, pTxFirstDesc); + } + /* Update txQueue state */ + pQueueCtrl->resource -= bufCount; + pQueueCtrl->pCurrentDescr = TX_NEXT_DESC_PTR(pTxCurrDesc, pQueueCtrl); + + /* Apply send command */ + MV_REG_VALUE(ETH_TX_QUEUE_COMMAND_REG(portNo)) = pPortCtrl->portTxQueueCmdReg; + + return MV_OK; +} + +/******************************************************************************* +* mvEthPortTxDone - Free all used Tx descriptors and mBlks. +* +* DESCRIPTION: +* This routine returns the transmitted packet information to the caller. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int txQueue - Number of Tx queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to packet was sent. +* +* RETURN: +* MV_NOT_FOUND - No transmitted packets to return. Transmit in progress. +* MV_EMPTY - No transmitted packets to return. TX Queue is empty. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - There is transmitted packet in the queue, +* 'pPktInfo' filled with relevant information. +* +*******************************************************************************/ +static INLINE MV_PKT_INFO* mvEthPortTxDone(void* pEthPortHndl, int txQueue) +{ + ETH_TX_DESC* pTxCurrDesc; + ETH_TX_DESC* pTxUsedDesc; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + MV_PKT_INFO* pPktInfo; + MV_U32 commandStatus; + + pQueueCtrl = &pPortCtrl->txQueue[txQueue]; + + pTxUsedDesc = pQueueCtrl->pUsedDescr; + pTxCurrDesc = pQueueCtrl->pCurrentDescr; + + while(MV_TRUE) + { + /* No more used descriptors */ + commandStatus = pTxUsedDesc->cmdSts; + if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) + { + ETH_DESCR_INV(pPortCtrl, pTxUsedDesc); + return NULL; + } + if( (pTxUsedDesc == pTxCurrDesc) && + (pQueueCtrl->resource != 0) ) + { + return NULL; + } + pQueueCtrl->resource++; + pQueueCtrl->pUsedDescr = TX_NEXT_DESC_PTR(pTxUsedDesc, pQueueCtrl); + if(commandStatus & (ETH_TX_LAST_DESC_MASK)) + { + pPktInfo = (MV_PKT_INFO*)pTxUsedDesc->returnInfo; + pPktInfo->status = commandStatus; + return pPktInfo; + } + pTxUsedDesc = pQueueCtrl->pUsedDescr; + } +} + +/******************************************************************************* +* mvEthPortRx - Get new received packets from Rx queue. +* +* DESCRIPTION: +* This routine returns the received data to the caller. There is no +* data copying during routine operation. All information is returned +* using pointer to packet information struct passed from the caller. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int rxQueue - Number of Rx queue. +* +* OUTPUT: +* MV_PKT_INFO *pPktInfo - Pointer to received packet. +* +* RETURN: +* MV_NO_RESOURCE - No free resources in RX queue. +* MV_ERROR - Unexpected Fatal error. +* MV_OK - New packet received and 'pBufInfo' structure filled +* with relevant information. +* +*******************************************************************************/ +static INLINE MV_PKT_INFO* mvEthPortRx(void* pEthPortHndl, int rxQueue) +{ + ETH_RX_DESC *pRxCurrDesc; + MV_U32 commandStatus; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + ETH_QUEUE_CTRL* pQueueCtrl; + MV_PKT_INFO* pPktInfo; + + pQueueCtrl = &(pPortCtrl->rxQueue[rxQueue]); + + /* Check resources */ + if(pQueueCtrl->resource == 0) + { + mvOsPrintf("ethPortRx: no more resources\n"); + return NULL; + } + while(MV_TRUE) + { + /* Get the Rx Desc ring 'curr and 'used' indexes */ + pRxCurrDesc = pQueueCtrl->pCurrentDescr; + + commandStatus = pRxCurrDesc->cmdSts; + if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) + { + /* Nothing to receive... */ + ETH_DESCR_INV(pPortCtrl, pRxCurrDesc); + return NULL; + } + + /* Valid RX only if FIRST and LAST bits are set */ + if( (commandStatus & (ETH_RX_LAST_DESC_MASK | ETH_RX_FIRST_DESC_MASK)) == + (ETH_RX_LAST_DESC_MASK | ETH_RX_FIRST_DESC_MASK) ) + { + pPktInfo = (MV_PKT_INFO*)pRxCurrDesc->returnInfo; + pPktInfo->pFrags->dataSize = pRxCurrDesc->byteCnt - 4; + pPktInfo->status = commandStatus; + pPktInfo->fragIP = pRxCurrDesc->bufSize & ETH_RX_IP_FRAGMENTED_FRAME_MASK; + + pQueueCtrl->resource--; + /* Update 'curr' in data structure */ + pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxCurrDesc, pQueueCtrl); + +#ifdef INCLUDE_SYNC_BARR + mvCpuIfSyncBarr(DRAM_TARGET); +#endif + return pPktInfo; + } + else + { + ETH_RX_DESC* pRxUsedDesc = pQueueCtrl->pUsedDescr; + +#ifdef ETH_DEBUG + mvOsPrintf("ethDrv: Unexpected Jumbo frame: " + "status=0x%08x, byteCnt=%d, pData=0x%x\n", + commandStatus, pRxCurrDesc->byteCnt, pRxCurrDesc->bufPtr); +#endif /* ETH_DEBUG */ + + /* move buffer from pCurrentDescr position to pUsedDescr position */ + pRxUsedDesc->bufPtr = pRxCurrDesc->bufPtr; + pRxUsedDesc->returnInfo = pRxCurrDesc->returnInfo; + pRxUsedDesc->bufSize = pRxCurrDesc->bufSize & ETH_RX_BUFFER_MASK; + + /* Return the descriptor to DMA ownership */ + pRxUsedDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA | + ETH_RX_ENABLE_INTERRUPT_MASK; + + /* Flush descriptor and CPU pipe */ + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxUsedDesc); + + /* Move the used descriptor pointer to the next descriptor */ + pQueueCtrl->pUsedDescr = RX_NEXT_DESC_PTR(pRxUsedDesc, pQueueCtrl); + pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxCurrDesc, pQueueCtrl); + } + } +} + +/******************************************************************************* +* mvEthPortRxDone - Returns a Rx buffer back to the Rx ring. +* +* DESCRIPTION: +* This routine returns a Rx buffer back to the Rx ring. +* +* INPUT: +* void* pEthPortHndl - Ethernet Port handler. +* int rxQueue - Number of Rx queue. +* MV_PKT_INFO *pPktInfo - Pointer to received packet. +* +* RETURN: +* MV_ERROR - Unexpected Fatal error. +* MV_OUT_OF_RANGE - RX queue is already FULL, so this buffer can't be +* returned to this queue. +* MV_FULL - Buffer returned successfully and RX queue became full. +* More buffers should not be returned at the time. +* MV_OK - Buffer returned successfully and there are more free +* places in the queue. +* +*******************************************************************************/ +static INLINE MV_STATUS mvEthPortRxDone(void* pEthPortHndl, int rxQueue, MV_PKT_INFO *pPktInfo) +{ + ETH_RX_DESC* pRxUsedDesc; + ETH_QUEUE_CTRL* pQueueCtrl; + ETH_PORT_CTRL* pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl; + + pQueueCtrl = &pPortCtrl->rxQueue[rxQueue]; + + /* Get 'used' Rx descriptor */ + pRxUsedDesc = pQueueCtrl->pUsedDescr; + + /* Check that ring is not FULL */ + if( (pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) && + (pQueueCtrl->resource != 0) ) + { + mvOsPrintf("%s %d: out of range Error resource=%d, curr=%p, used=%p\n", + __FUNCTION__, pPortCtrl->portNo, pQueueCtrl->resource, + pQueueCtrl->pCurrentDescr, pQueueCtrl->pUsedDescr); + return MV_OUT_OF_RANGE; + } + + pRxUsedDesc->bufPtr = pPktInfo->pFrags->bufPhysAddr; + pRxUsedDesc->returnInfo = (MV_ULONG)pPktInfo; + pRxUsedDesc->bufSize = pPktInfo->pFrags->bufSize & ETH_RX_BUFFER_MASK; + + /* Invalidate data buffer accordingly with pktSize */ + if(pPktInfo->pktSize != 0) + { + ETH_PACKET_CACHE_INVALIDATE(pPktInfo->pFrags->bufVirtPtr, pPktInfo->pktSize); + pPktInfo->pktSize = 0; + } + + /* Return the descriptor to DMA ownership */ + pRxUsedDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT_MASK; + + /* Flush descriptor and CPU pipe */ + ETH_DESCR_FLUSH_INV(pPortCtrl, pRxUsedDesc); + + pQueueCtrl->resource++; + + /* Move the used descriptor pointer to the next descriptor */ + pQueueCtrl->pUsedDescr = RX_NEXT_DESC_PTR(pRxUsedDesc, pQueueCtrl); + + /* If ring became Full return MV_FULL */ + if(pQueueCtrl->pUsedDescr == pQueueCtrl->pCurrentDescr) + return MV_FULL; + + return MV_OK; +} + + +#endif /* __mvEthGbe_h__ */ + + diff --git a/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthRegs.h b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthRegs.h new file mode 100644 index 0000000..5865fa6 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/gbe/mvEthRegs.h @@ -0,0 +1,695 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvEthRegsh +#define __INCmvEthRegsh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "ctrlEnv/mvCtrlEnvSpec.h" + +/****************************************/ +/* Ethernet Unit Registers */ +/****************************************/ +#define ETH_REG_BASE MV_ETH_REG_BASE + +#define ETH_PHY_ADDR_REG(port) (ETH_REG_BASE(port) + 0x000) +#define ETH_SMI_REG(port) (ETH_REG_BASE(port) + 0x004) +#define ETH_UNIT_DEF_ADDR_REG(port) (ETH_REG_BASE(port) + 0x008) +#define ETH_UNIT_DEF_ID_REG(port) (ETH_REG_BASE(port) + 0x00c) +#define ETH_UNIT_RESERVED(port) (ETH_REG_BASE(port) + 0x014) +#define ETH_UNIT_INTR_CAUSE_REG(port) (ETH_REG_BASE(port) + 0x080) +#define ETH_UNIT_INTR_MASK_REG(port) (ETH_REG_BASE(port) + 0x084) + + +#define ETH_UNIT_ERROR_ADDR_REG(port) (ETH_REG_BASE(port) + 0x094) +#define ETH_UNIT_INT_ADDR_ERROR_REG(port) (ETH_REG_BASE(port) + 0x098) +#define ETH_UNIT_CONTROL_REG(port) (ETH_REG_BASE(port) + 0x0B0) + +#define ETH_PORT_CONFIG_REG(port) (ETH_REG_BASE(port) + 0x400) +#define ETH_PORT_CONFIG_EXTEND_REG(port) (ETH_REG_BASE(port) + 0x404) +#define ETH_MII_SERIAL_PARAM_REG(port) (ETH_REG_BASE(port) + 0x408) +#define ETH_GMII_SERIAL_PARAM_REG(port) (ETH_REG_BASE(port) + 0x40c) +#define ETH_VLAN_ETHER_TYPE_REG(port) (ETH_REG_BASE(port) + 0x410) +#define ETH_MAC_ADDR_LOW_REG(port) (ETH_REG_BASE(port) + 0x414) +#define ETH_MAC_ADDR_HIGH_REG(port) (ETH_REG_BASE(port) + 0x418) +#define ETH_SDMA_CONFIG_REG(port) (ETH_REG_BASE(port) + 0x41c) +#define ETH_DIFF_SERV_PRIO_REG(port, code) (ETH_REG_BASE(port) + 0x420 + ((code)<<2)) +#define ETH_PORT_SERIAL_CTRL_REG(port) (ETH_REG_BASE(port) + 0x43c) +#define ETH_VLAN_TAG_TO_PRIO_REG(port) (ETH_REG_BASE(port) + 0x440) +#define ETH_PORT_STATUS_REG(port) (ETH_REG_BASE(port) + 0x444) + +#define ETH_RX_QUEUE_COMMAND_REG(port) (ETH_REG_BASE(port) + 0x680) +#define ETH_TX_QUEUE_COMMAND_REG(port) (ETH_REG_BASE(port) + 0x448) + +#define ETH_PORT_SERIAL_CTRL_1_REG(port) (ETH_REG_BASE(port) + 0x44c) +#define ETH_PORT_STATUS_1_REG(port) (ETH_REG_BASE(port) + 0x450) +#define ETH_PORT_MARVELL_HEADER_REG(port) (ETH_REG_BASE(port) + 0x454) +#define ETH_PORT_FIFO_PARAMS_REG(port) (ETH_REG_BASE(port) + 0x458) +#define ETH_MAX_TOKEN_BUCKET_SIZE_REG(port) (ETH_REG_BASE(port) + 0x45c) +#define ETH_INTR_CAUSE_REG(port) (ETH_REG_BASE(port) + 0x460) +#define ETH_INTR_CAUSE_EXT_REG(port) (ETH_REG_BASE(port) + 0x464) +#define ETH_INTR_MASK_REG(port) (ETH_REG_BASE(port) + 0x468) +#define ETH_INTR_MASK_EXT_REG(port) (ETH_REG_BASE(port) + 0x46c) +#define ETH_TX_FIFO_URGENT_THRESH_REG(port) (ETH_REG_BASE(port) + 0x474) +#define ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (ETH_REG_BASE(port) + 0x47c) +#define ETH_RX_DISCARD_PKTS_CNTR_REG(port) (ETH_REG_BASE(port) + 0x484) +#define ETH_RX_OVERRUN_PKTS_CNTR_REG(port) (ETH_REG_BASE(port) + 0x488) +#define ETH_INTERNAL_ADDR_ERROR_REG(port) (ETH_REG_BASE(port) + 0x494) +#define ETH_TX_FIXED_PRIO_CFG_REG(port) (ETH_REG_BASE(port) + 0x4dc) +#define ETH_TX_TOKEN_RATE_CFG_REG(port) (ETH_REG_BASE(port) + 0x4e0) +#define ETH_MAX_TRANSMIT_UNIT_REG(port) (ETH_REG_BASE(port) + 0x4e8) +#define ETH_TX_TOKEN_BUCKET_SIZE_REG(port) (ETH_REG_BASE(port) + 0x4ec) +#define ETH_TX_TOKEN_BUCKET_COUNT_REG(port) (ETH_REG_BASE(port) + 0x780) +#define ETH_RX_DESCR_STAT_CMD_REG(port, q) (ETH_REG_BASE(port) + 0x600 + ((q)<<4)) +#define ETH_RX_BYTE_COUNT_REG(port, q) (ETH_REG_BASE(port) + 0x604 + ((q)<<4)) +#define ETH_RX_BUF_PTR_REG(port, q) (ETH_REG_BASE(port) + 0x608 + ((q)<<4)) +#define ETH_RX_CUR_DESC_PTR_REG(port, q) (ETH_REG_BASE(port) + 0x60c + ((q)<<4)) +#define ETH_TX_CUR_DESC_PTR_REG(port, q) (ETH_REG_BASE(port) + 0x6c0 + ((q)<<2)) + +#define ETH_TXQ_TOKEN_COUNT_REG(port, q) (ETH_REG_BASE(port) + 0x700 + ((q)<<4)) +#define ETH_TXQ_TOKEN_CFG_REG(port, q) (ETH_REG_BASE(port) + 0x704 + ((q)<<4)) +#define ETH_TXQ_ARBITER_CFG_REG(port, q) (ETH_REG_BASE(port) + 0x708 + ((q)<<4)) + +#if (MV_ETH_VERSION >= 4) +#define ETH_EJP_TX_HI_IPG_REG(port) (ETH_REG_BASE(port) + 0x7A8) +#define ETH_EJP_TX_LO_IPG_REG(port) (ETH_REG_BASE(port) + 0x7B8) +#define ETH_EJP_HI_TKN_LO_PKT_REG(port) (ETH_REG_BASE(port) + 0x7C0) +#define ETH_EJP_HI_TKN_ASYNC_PKT_REG(port) (ETH_REG_BASE(port) + 0x7C4) +#define ETH_EJP_LO_TKN_ASYNC_PKT_REG(port) (ETH_REG_BASE(port) + 0x7C8) +#define ETH_EJP_TX_SPEED_REG(port) (ETH_REG_BASE(port) + 0x7D0) +#endif /* MV_ETH_VERSION >= 4 */ + +#define ETH_MIB_COUNTERS_BASE(port) (ETH_REG_BASE(port) + 0x1000) +#define ETH_DA_FILTER_SPEC_MCAST_BASE(port) (ETH_REG_BASE(port) + 0x1400) +#define ETH_DA_FILTER_OTH_MCAST_BASE(port) (ETH_REG_BASE(port) + 0x1500) +#define ETH_DA_FILTER_UCAST_BASE(port) (ETH_REG_BASE(port) + 0x1600) + +/* Phy address register definitions */ +#define ETH_PHY_ADDR_OFFS 0 +#define ETH_PHY_ADDR_MASK (0x1f <= 4) +#define ETH_TX_EJP_ENABLE_BIT 18 +#define ETH_TX_EJP_ENABLE_MASK (1 << ETH_TX_EJP_ENABLE_BIT) + +#define ETH_TX_LEGACY_WRR_BIT 19 +#define ETH_TX_LEGACY_WRR_MASK (1 << ETH_TX_LEGACY_WRR_BIT) +#endif /* (MV_ETH_VERSION >= 4) */ + +/***** BITs of Ethernet Port Status reg (PSR) *****/ +#define ETH_LINK_UP_BIT 1 +#define ETH_LINK_UP_MASK (1<pLastDescr) ? \ + (ETH_RX_DESC*)((pQueueCtrl)->pFirstDescr) : \ + (ETH_RX_DESC*)(((MV_ULONG)(pRxDescr)) + ETH_RX_DESC_ALIGNED_SIZE) + +#define TX_NEXT_DESC_PTR(pTxDescr, pQueueCtrl) \ + ((pTxDescr) == (pQueueCtrl)->pLastDescr) ? \ + (ETH_TX_DESC*)((pQueueCtrl)->pFirstDescr) : \ + (ETH_TX_DESC*)(((MV_ULONG)(pTxDescr)) + ETH_TX_DESC_ALIGNED_SIZE) + +#define RX_PREV_DESC_PTR(pRxDescr, pQueueCtrl) \ + ((pRxDescr) == (pQueueCtrl)->pFirstDescr) ? \ + (ETH_RX_DESC*)((pQueueCtrl)->pLastDescr) : \ + (ETH_RX_DESC*)(((MV_ULONG)(pRxDescr)) - ETH_RX_DESC_ALIGNED_SIZE) + +#define TX_PREV_DESC_PTR(pTxDescr, pQueueCtrl) \ + ((pTxDescr) == (pQueueCtrl)->pFirstDescr) ? \ + (ETH_TX_DESC*)((pQueueCtrl)->pLastDescr) : \ + (ETH_TX_DESC*)(((MV_ULONG)(pTxDescr)) - ETH_TX_DESC_ALIGNED_SIZE) + + +/* Queue specific information */ +typedef struct +{ + void* pFirstDescr; + void* pLastDescr; + void* pCurrentDescr; + void* pUsedDescr; + int resource; + MV_BUF_INFO descBuf; +} ETH_QUEUE_CTRL; + + +/* Ethernet port specific infomation */ +typedef struct _ethPortCtrl +{ + int portNo; + ETH_QUEUE_CTRL rxQueue[MV_ETH_RX_Q_NUM]; /* Rx ring resource */ + ETH_QUEUE_CTRL txQueue[MV_ETH_TX_Q_NUM]; /* Tx ring resource */ + + MV_ETH_PORT_CFG portConfig; + MV_ETH_RX_Q_CFG rxQueueConfig[MV_ETH_RX_Q_NUM]; + MV_ETH_TX_Q_CFG txQueueConfig[MV_ETH_TX_Q_NUM]; + + /* Register images - For DP */ + MV_U32 portTxQueueCmdReg; /* Port active Tx queues summary */ + MV_U32 portRxQueueCmdReg; /* Port active Rx queues summary */ + + MV_STATE portState; + + MV_U8 mcastCount[256]; + MV_U32* hashPtr; + void *osHandle; +} ETH_PORT_CTRL; + +/************** MACROs ****************/ + +/* MACROs to Flush / Invalidate TX / RX Buffers */ +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) && !defined(UNCACHED_TX_BUFFERS) +# define ETH_PACKET_CACHE_FLUSH(pAddr, size) \ + mvOsCacheClear(NULL, (pAddr), (size)); \ + /*CPU_PIPE_FLUSH;*/ +#else +# define ETH_PACKET_CACHE_FLUSH(pAddr, size) +#endif /* ETHER_DRAM_COHER == MV_CACHE_COHER_SW */ + +#if ( (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) && !defined(UNCACHED_RX_BUFFERS) ) +# define ETH_PACKET_CACHE_INVALIDATE(pAddr, size) \ + mvOsCacheInvalidate (NULL, (pAddr), (size)); \ + /*CPU_PIPE_FLUSH;*/ +#else +# define ETH_PACKET_CACHE_INVALIDATE(pAddr, size) +#endif /* ETHER_DRAM_COHER == MV_CACHE_COHER_SW && !UNCACHED_RX_BUFFERS */ + +#ifdef ETH_DESCR_UNCACHED + +#define ETH_DESCR_FLUSH_INV(pPortCtrl, pDescr) +#define ETH_DESCR_INV(pPortCtrl, pDescr) + +#else + +#define ETH_DESCR_FLUSH_INV(pPortCtrl, pDescr) \ + mvOsCacheLineFlushInv(pPortCtrl->osHandle, (MV_ULONG)(pDescr)) + +#define ETH_DESCR_INV(pPortCtrl, pDescr) \ + mvOsCacheLineInv(pPortCtrl->osHandle, (MV_ULONG)(pDescr)) + +#endif /* ETH_DESCR_UNCACHED */ + +#include "ethfp/gbe/mvEthGbe.h" + +#endif /* __mvEth_h__ */ + + diff --git a/board/mv_feroceon/mv_hal/ethfp/mvEthDebug.h b/board/mv_feroceon/mv_hal/ethfp/mvEthDebug.h new file mode 100644 index 0000000..f7b1ba1 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/mvEthDebug.h @@ -0,0 +1,113 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __MV_ETH_DEBUG_H__ +#define __MV_ETH_DEBUG_H__ + +/* + ** Externs + */ +void ethBpduRxQ(int port, int bpduQueue); +void ethArpRxQ(int port, int bpduQueue); +void ethTcpRxQ(int port, int bpduQueue); +void ethUdpRxQ(int port, int bpduQueue); +void ethMcastAdd(int port, char* macStr, int queue); + +#ifdef INCLUDE_MULTI_QUEUE +void ethRxPolicy( int port); +void ethTxPolicy( int port); +void ethTxPolDA(int port, char* macStr, int txQ, char* headerHexStr); +void ethRxPolMode(int port, MV_ETH_PRIO_MODE prioMode); +void ethRxPolQ(int port, int rxQueue, int rxQuota); +#endif /* INCLUDE_MULTI_QUEUE */ + +void print_egiga_stat(void *sc, unsigned int port); +void ethPortStatus (int port); +void ethPortQueues( int port, int rxQueue, int txQueue, int mode); +void ethPortMcast(int port); +void ethPortRegs(int port); +void ethPortCounters(int port); +void ethPortRmonCounters(int port); +void ethRxCoal(int port, int usec); +void ethTxCoal(int port, int usec); + +void ethRegs(int port); +void ethClearCounters(int port); +void ethUcastSet(int port, char* macStr, int queue); +void ethPortUcastShow(int port); + +#ifdef CONFIG_MV_ETH_HEADER +void run_com_header(const char *buffer); +#endif + +#ifdef INCLUDE_MULTI_QUEUE +void ethRxPolMode(int port, MV_ETH_PRIO_MODE prioMode); +void ethRxPolQ(int port, int queue, int quota); +void ethRxPolicy(int port); +void ethTxPolDef(int port, int txQ, char* headerHexStr); +void ethTxPolDA(int port, char* macStr, int txQ, char* headerHexStr); +void ethTxPolicy(int port); +#endif /* INCLUDE_MULTI_QUEUE */ + + +#endif diff --git a/board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.c b/board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.c new file mode 100644 index 0000000..18fa1ff --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.c @@ -0,0 +1,572 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEthPolicy.c - Source file for RX and TX policy of Giga Ethernet driver +* +* DESCRIPTION: +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + + +#include "mvEthPolicy.h" + +/*****************************************************************************/ +/**************************** RX Policy **************************************/ +/*****************************************************************************/ + +ETH_RX_POLICY* rxPolicy[MV_ETH_MAX_PORTS]; + + +/******************************************************************************* +* mvEthRxPolicyInit - Initialize RX policy component. +* +* DESCRIPTION: +* Create RX policy database for ethernet port, set to it to default +* (FIXED mode) and return port handle. +* +* INPUT: +* int port - Ethernet port number +* +* +* RETURN: +* void* pRxPolicyHndl - RX Policy component handler; +* +*******************************************************************************/ +void* mvEthRxPolicyInit(int port, int defQuota, MV_ETH_PRIO_MODE defMode) +{ + int queue; + + if( (port < 0) || (port >= mvCtrlEthMaxPortGet()) ) + { + mvOsPrintf("ethRxPolicy: port #%d is not exist\n", port); + return NULL; + } + rxPolicy[port] = mvOsMalloc(sizeof(ETH_RX_POLICY)); + if(rxPolicy[port] == NULL) + { + mvOsPrintf("ethRxPolicy: Port #%d, Can't allocate %lu bytes\n", + port, sizeof(ETH_RX_POLICY)); + return NULL; + } + /* Set defaults */ + memset(rxPolicy[port], 0, sizeof(ETH_RX_POLICY)); + + for(queue=0; queuerxQuota[queue] = defQuota; + } + rxPolicy[port]->port = port; + rxPolicy[port]->rxPrioMode = defMode; + rxPolicy[port]->rxCurQ = MV_ETH_RX_Q_NUM-1; + rxPolicy[port]->rxCurQuota = rxPolicy[port]->rxQuota[rxPolicy[port]->rxCurQ]; + + return rxPolicy[port]; +} + +/* Get RX policy handler for specific port */ +void* mvEthRxPolicyHndlGet(int port) +{ + return rxPolicy[port]; +} + +/******************************************************************************* +* mvEthRxPolicyModeSet - Set receive priority policy. +* +* DESCRIPTION: +* This function configures priority mode for processing received packets. +* +* INPUT: +* void* pRxPolHndl - RX Policy component handler +* MV_ETH_PRIO_MODE prioMode - RX priority mode (FIXED or WRR) +* +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthRxPolicyModeSet(void* pRxPolHndl, MV_ETH_PRIO_MODE prioMode) +{ + ETH_RX_POLICY* pRxPolicy = (ETH_RX_POLICY*)pRxPolHndl; + + pRxPolicy->rxPrioMode = prioMode; + + return MV_OK; +} + +/******************************************************************************* +* mvEthRxPolicyQueueCfg - Set quota for RX queue in WRR receive priority mode. +* +* DESCRIPTION: +* This function configures packet based quota for each RX queue, +* when WRR priority mode is chosen for processing received packets. +* +* INPUT: +* void* pRxPolHndl - RX Policy component handler +* int rxQueue - RX priority mode (FIXED or WRR) +* int rxQuota - packet based quota for RX queue (only in WRR mode) +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthRxPolicyQueueCfg(void* pRxPolHndl, int rxQueue, int rxQuota) +{ + ETH_RX_POLICY* pRxPolicy = (ETH_RX_POLICY*)pRxPolHndl; + + pRxPolicy->rxQuota[rxQueue] = rxQuota; + + return MV_OK; +} + +/******************************************************************************* +* mvEthRxPolicyGet - Get RX policy of ethernet port. +* +* DESCRIPTION: +* This function choose which RX queue will be processed next +* +* INPUT: +* void* pRxPolHndl - RX Policy component handler +* MV_U32 cause - value of cause register, indicating +* which RX queues received packets. +* +* RETURN: +* int rxQueue - The RX queue number that will be processed next. +* -1 means error +* +*******************************************************************************/ +int mvEthRxPolicyGet(void* pRxPolHndl, MV_U32 cause) +{ + int queue; + ETH_RX_POLICY* pRxPolicy = (ETH_RX_POLICY*)pRxPolHndl; + +#ifdef MV_RT_DEBUG + if(cause == 0) + { + mvOsPrintf("EthRxPolicy: port #%d, unexpected cause=0x%x\n", pRxPolicy->port, cause); + return MV_INVALID; + } +#endif /* MV_RT_DEBUG */ + + if(pRxPolicy->rxPrioMode == MV_ETH_PRIO_FIXED) + { + for(queue=(MV_ETH_RX_Q_NUM-1); queue>=0; queue--) + { + if(cause & (ETH_CAUSE_RX_READY_MASK(queue))) + return queue; + } + } + else + { + /* Check Current RX queue */ + if(cause & ETH_CAUSE_RX_READY_MASK(pRxPolicy->rxCurQ)) + { + if(pRxPolicy->rxCurQuota > 0) + { + pRxPolicy->rxCurQuota -= 1; + return pRxPolicy->rxCurQ; + } + } + /* Look for next RX Queue */ + while(MV_TRUE) + { + if(pRxPolicy->rxCurQ == 0) + pRxPolicy->rxCurQ = MV_ETH_RX_Q_NUM-1; + else + pRxPolicy->rxCurQ -= 1; + + if( ((cause & ETH_CAUSE_RX_READY_MASK(pRxPolicy->rxCurQ)) != 0) && + (pRxPolicy->rxQuota[pRxPolicy->rxCurQ] != 0) ) + { + pRxPolicy->rxCurQuota = pRxPolicy->rxQuota[pRxPolicy->rxCurQ]-1; + return pRxPolicy->rxCurQ; + } + } + } + return MV_INVALID; +} + +/*****************************************************************************/ +/**************************** TX Policy **************************************/ +/*****************************************************************************/ + + +ETH_TX_POLICY* txPolicy[MV_ETH_MAX_PORTS]; + +/******************************************************************************* +* mvEthTxPolicyInit - Initialize TX policy component. +* +* DESCRIPTION: +* Create TX policy database for ethernet port, set to it to default +* values and return port handle. +* +* INPUT: +* int port - Ethernet port number +* +* +* RETURN: +* void* pTxPolHndl - TX Policy component handler +* +*******************************************************************************/ +void* mvEthTxPolicyInit(int port, MV_ETH_TX_POLICY_ENTRY* pDefPolicy) +{ + int daIdx; + + if( (port < 0) || (port >= mvCtrlEthMaxPortGet()) ) + { + mvOsPrintf("ethTxPolicy: port #%d is not exist\n", port); + return NULL; + } + txPolicy[port] = mvOsMalloc(sizeof(ETH_TX_POLICY)); + if(txPolicy[port] == NULL) + { + mvOsPrintf("ethTxPolicy: Port #%d, Can't allocate %lu bytes\n", + port, sizeof(ETH_TX_POLICY)); + return NULL; + } + /* Set defaults */ + memset(txPolicy[port], 0, sizeof(ETH_TX_POLICY)); + txPolicy[port]->port = port; + mvEthTxPolicyDef(txPolicy[port],pDefPolicy); + + /* Invalidate all entries */ + txPolicy[port]->txPolMaxDa = 0; + for(daIdx=0; daIdxtxPolDa[daIdx].policy.txQ = MV_INVALID; + + return txPolicy[port]; +} + +/* Get TX policy handler for specific port */ +void* mvEthTxPolicyHndlGet(int port) +{ + return txPolicy[port]; +} + + +/******************************************************************************* +* mvEthTxPolicyDef - Set TX default policy. +* +* DESCRIPTION: +* This function configures TX default policy for packets that +* there is no information for them +* +* INPUT: +* void* pTxPolHndl - TX Policy component handler +* MV_ETH_TX_POLICY_ENTRY policy - Default TX policy +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthTxPolicyDef(void* pTxPolHndl, MV_ETH_TX_POLICY_ENTRY* pPolicy) +{ + ETH_TX_POLICY* pTxPolicy = (ETH_TX_POLICY*)pTxPolHndl; + + /* if Tx header exist */ + if(pPolicy->pHeader != NULL) + { + /* allocate memory for header */ + pTxPolicy->txPolDef.pHeader = mvOsMalloc(pPolicy->headerSize ); + if(pTxPolicy->txPolDef.pHeader == NULL) + { + mvOsPrintf("mvEthTxPolicyDef: Alloc failed \n"); + return MV_FAIL; + } + /* copy header */ + memcpy(pTxPolicy->txPolDef.pHeader, pPolicy->pHeader , pPolicy->headerSize ); + pTxPolicy->txPolDef.headerSize = pPolicy->headerSize; + } + else + { + pTxPolicy->txPolDef.pHeader = NULL; + pTxPolicy->txPolDef.headerSize = 0; + } + pTxPolicy->txPolDef.txQ = pPolicy->txQ; + + return MV_OK; +} + +/******************************************************************************* +* mvEthTxPolicyAdd - Add TX policy for packets with special MAC DA. +* +* DESCRIPTION: +* This function adds TX policy for outgoing packets with special MAC DAs. +* Support up to 16 entries. +* +* INPUT: +* void* pTxPolHndl - TX Policy component handler +* MV_ETH_TX_POLICY_MACDA daPolicy - TX policy for outgoing packets +* with specific MACDA +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthTxPolicyAdd(void* pTxPolHndl, MV_ETH_TX_POLICY_MACDA* pDaPolicy) +{ + int idx, firstEmptyIdx = MV_INVALID; + ETH_TX_POLICY* pTxPolicy = (ETH_TX_POLICY*)pTxPolHndl; + + for(idx=0; idxtxPolDa[idx].policy.txQ != MV_INVALID) && + ( memcmp(pTxPolicy->txPolDa[idx].macDa, pDaPolicy->macDa, + MV_MAC_ADDR_SIZE) == 0) ) + { + /* entry already exist - so replace */ + firstEmptyIdx = idx; + break; + } + if( (firstEmptyIdx == MV_INVALID) && + (pTxPolicy->txPolDa[idx].policy.txQ == MV_INVALID) ) + { + firstEmptyIdx = idx; + } + } + if(firstEmptyIdx != MV_INVALID) + { + memcpy(pTxPolicy->txPolDa[firstEmptyIdx].macDa, + pDaPolicy->macDa, MV_MAC_ADDR_SIZE); + + /* if Tx header exist */ + if(pDaPolicy->policy.pHeader != NULL) + { + /* allocate memory for header */ + pTxPolicy->txPolDa[firstEmptyIdx].policy.pHeader = mvOsMalloc(pDaPolicy->policy.headerSize ); + if(pTxPolicy->txPolDa[firstEmptyIdx].policy.pHeader == NULL) + { + mvOsPrintf("ethTxPolicy: Alloc failed \n"); + return MV_FAIL; + } + /* copy header */ + memcpy(pTxPolicy->txPolDa[firstEmptyIdx].policy.pHeader , + pDaPolicy->policy.pHeader , pDaPolicy->policy.headerSize ); + pTxPolicy->txPolDa[firstEmptyIdx].policy.headerSize = pDaPolicy->policy.headerSize; + } + else + { + pTxPolicy->txPolDa[firstEmptyIdx].policy.pHeader = NULL; + pTxPolicy->txPolDa[firstEmptyIdx].policy.headerSize = 0; + } + pTxPolicy->txPolDa[firstEmptyIdx].policy.txQ = pDaPolicy->policy.txQ; + if(firstEmptyIdx >= pTxPolicy->txPolMaxDa) + pTxPolicy->txPolMaxDa = firstEmptyIdx + 1; + + return MV_OK; + } + mvOsPrintf("ethTxPolicy: Can't add more MACDA entries\n"); + return MV_FULL; +} + +/******************************************************************************* +* mvEthTxPolicyDel - Delete TX policy for packets with special MACDA. +* +* DESCRIPTION: +* This function deletes existing TX policy for outgoing packets with +* special MAC DAs.. +* +* INPUT: +* void* pTxPolHndl - TX Policy component handler +* MV_U8* pMacAddr - Pointer to MACDA for the entry will be deleted. +* +* RETURN: MV_STATUS +* MV_OK - Success +* MV_FAIL - Failed. +* +*******************************************************************************/ +MV_STATUS mvEthTxPolicyDel(void* pTxPolHndl, MV_U8* pMacAddr) +{ + int idx; + ETH_TX_POLICY* pTxPolicy = (ETH_TX_POLICY*)pTxPolHndl; + + for(idx=0; idxtxPolMaxDa; idx++) + { + if( (pTxPolicy->txPolDa[idx].policy.txQ != MV_INVALID) && + (memcmp(pTxPolicy->txPolDa[idx].macDa, pMacAddr, + MV_MAC_ADDR_SIZE) == 0) ) + { + /* Entry found */ + pTxPolicy->txPolDa[idx].policy.txQ = MV_INVALID; + if(pTxPolicy->txPolDa[idx].policy.pHeader != NULL) + { + mvOsFree(pTxPolicy->txPolDa[idx].policy.pHeader); + pTxPolicy->txPolDa[idx].policy.pHeader = NULL; + pTxPolicy->txPolDa[idx].policy.headerSize = 0; + } + + if(idx == (pTxPolicy->txPolMaxDa - 1)) + pTxPolicy->txPolMaxDa--; + + /* Decrease table */ + while( (pTxPolicy->txPolMaxDa > 0) && + (pTxPolicy->txPolDa[pTxPolicy->txPolMaxDa-1].policy.txQ == MV_INVALID) ) + pTxPolicy->txPolMaxDa--; + + return MV_OK; + } + } + mvOsPrintf("ethTxPolicy: Can't delete the MACDA entry\n"); + return MV_NO_SUCH; +} + + + +/******************************************************************************* +* mvEthDATxPolicyGet - Get TX policy of ethernet port for the outgoing packet, +* base on the DA. +* +* DESCRIPTION: +* This function return an existing TX policy for specific MACs. +* +* INPUT: +* void* pPortHndl - Pointer to port specific handler +* MV_U8* MAC - Pointer to DA MAC. +* +* OUTPUT: +* MV_ETH_TX_POLICY_ENTRY* pTxPolEntry - pointer to TX policy entry for +* this packet +* +* RETURN: +* int txQ - TX queue to place the outgoing packet. +* +*******************************************************************************/ +static int mvEthDATxPolicyGet(void* pTxPolicyHndl, MV_U8* pDA, + MV_ETH_TX_POLICY_ENTRY* pTxPolicyEntry) +{ + int idx=0; + ETH_TX_POLICY* pTxPolicy = (ETH_TX_POLICY*)pTxPolicyHndl; + MV_ETH_TX_POLICY_ENTRY* pPolicy = &pTxPolicy->txPolDef; + + while(idx < pTxPolicy->txPolMaxDa) + { + if( (pTxPolicy->txPolDa[idx].policy.txQ != MV_INVALID) && + (memcmp(pDA, pTxPolicy->txPolDa[idx].macDa, + MV_MAC_ADDR_SIZE) == 0) ) + { + pPolicy = &pTxPolicy->txPolDa[idx].policy; + break; + } + idx++; + } + + /* if valid entry found */ + if(idx < pTxPolicy->txPolMaxDa) + { + if(pTxPolicyEntry != NULL) + { + pTxPolicyEntry->pHeader = pPolicy->pHeader; + pTxPolicyEntry->headerSize = pPolicy->headerSize; + pTxPolicyEntry->txQ = pPolicy->txQ; + } + return pPolicy->txQ; + } + else /* if no entry found - use defaults*/ + { + if(pTxPolicyEntry != NULL) + { + pTxPolicyEntry->pHeader = pTxPolicy->txPolDef.pHeader; + pTxPolicyEntry->headerSize = pTxPolicy->txPolDef.headerSize; + pTxPolicyEntry->txQ = pTxPolicy->txPolDef.txQ; + } + return pTxPolicy->txPolDef.txQ; + } + + return 0; +} + +/******************************************************************************* +* mvEthTxPolicyGet - Get TX policy of ethernet port for the outgoing packet. +* +* DESCRIPTION: +* This function gets existing TX policy for outgoing packets. +* +* INPUT: +* void* pPortHndl - Pointer to port specific handler +* MV_U8* pPktInfo - Pointer to outgoing packet +* +* OUTPUT: +* MV_ETH_TX_POLICY_ENTRY* pTxPolEntry - pointer to TX policy entry for +* this packet +* +* RETURN: +* int txQ - TX queue to place the outgoing packet. +* +*******************************************************************************/ +int mvEthTxPolicyGet(void* pTxPolicyHndl, MV_U8* pData, + MV_ETH_TX_POLICY_ENTRY* pTxPolicyEntry) +{ + /* extract the destination MAC address */ + return mvEthDATxPolicyGet(pTxPolicyHndl, pData, pTxPolicyEntry); +} + + + diff --git a/board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.h b/board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.h new file mode 100644 index 0000000..e1e2c41 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethfp/mvEthPolicy.h @@ -0,0 +1,139 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvEthPolicy.h - Header File for RX and TX policy of Giga Ethernet driver +* +* DESCRIPTION: +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __mvEthPolicy_h__ +#define __mvEthPolicy_h__ + +#include "mvOs.h" +#include "mvEth.h" + +#define MV_ETH_TX_POLICY_MAX_MACDA 16 + +typedef struct +{ + MV_U8* pHeader; + int headerSize; + int txQ; + +} MV_ETH_TX_POLICY_ENTRY; + +typedef struct +{ + MV_U8 macDa[MV_MAC_ADDR_SIZE]; + MV_ETH_TX_POLICY_ENTRY policy; +}MV_ETH_TX_POLICY_MACDA; + +/* Rx policy struct */ +typedef struct +{ + int port; + MV_ETH_PRIO_MODE rxPrioMode; + int rxQuota[MV_ETH_RX_Q_NUM]; + int rxCurQ; + int rxCurQuota; +}ETH_RX_POLICY; + +/* Tx policy struct */ +typedef struct +{ + int port; + MV_ETH_TX_POLICY_ENTRY txPolDef; + int txPolMaxDa; + MV_ETH_TX_POLICY_MACDA txPolDa[MV_ETH_TX_POLICY_MAX_MACDA]; +}ETH_TX_POLICY; + +/* RX Policy */ +void* mvEthRxPolicyInit(int port, int defQuota, MV_ETH_PRIO_MODE defMode); +void* mvEthRxPolicyHndlGet(int port); + +MV_STATUS mvEthRxPolicyModeSet(void* pPortHndl, MV_ETH_PRIO_MODE prioMode); +MV_STATUS mvEthRxPolicyQueueCfg(void* pPortHndl, int rxQueue, int rxQuota); +int mvEthRxPolicyGet(void* pPolicyHndl, MV_U32 cause); +void mvEthRxPolicyShow(void* pPolicyHndl); + +/* TX Policy */ +void* mvEthTxPolicyInit(int port, MV_ETH_TX_POLICY_ENTRY* pDefPolicy); +void* mvEthTxPolicyHndlGet(int port); + +MV_STATUS mvEthTxPolicyDef(void* pTxPolHndl, MV_ETH_TX_POLICY_ENTRY* pPolicy); +MV_STATUS mvEthTxPolicyAdd(void* pTxPolHndl, MV_ETH_TX_POLICY_MACDA* pDaPolicy); +MV_STATUS mvEthTxPolicyDel(void* pTxPolHndl, MV_U8* pMacAddr); + +int mvEthTxPolicyGet(void* pTxPolicyHndl, MV_U8* pData, + MV_ETH_TX_POLICY_ENTRY* pTxPolicyEntry); + +void mvEthTxPolicyShow(void* pPolicyHndl); + +#endif /* __mvEthPolicy_h__ */ + diff --git a/board/mv_feroceon/mv_hal/ethswitch/mvSwitch.c b/board/mv_feroceon/mv_hal/ethswitch/mvSwitch.c new file mode 100644 index 0000000..064bff1 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethswitch/mvSwitch.c @@ -0,0 +1,442 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvOs.h" +#include "mvSwitch.h" +#include "eth-phy/mvEthPhy.h" +#include "mvSwitchRegs.h" +#include "mvCtrlEnvLib.h" + + +static void switchVlanInit(MV_U32 ethPortNum, + MV_U32 switchCpuPort, + MV_U32 switchMaxPortsNum, + MV_U32 switchPortsOffset, + MV_U32 switchEnabledPortsMask); + +static void mvEthSwitchRegWrite(MV_U32 ethPortNum, MV_U32 phyAddr, + MV_U32 regOffs, MV_U16 data); + +static void mvEthSwitchRegRead(MV_U32 ethPortNum, MV_U32 phyAddr, + MV_U32 regOffs, MV_U16 *data); + +int switchMultiChipMode = 0xdeadbeef; + +/******************************************************************************* +* mvEthE6065_61PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6065_61SwitchBasicInit(MV_U32 ethPortNum) +{ + switchVlanInit(ethPortNum, + MV_E6065_CPU_PORT, + MV_E6065_MAX_PORTS_NUM, + MV_E6065_PORTS_OFFSET, + MV_E6065_ENABLED_PORTS); +} + +/******************************************************************************* +* mvEthE6063PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6063SwitchBasicInit(MV_U32 ethPortNum) +{ + switchVlanInit(ethPortNum, + MV_E6063_CPU_PORT, + MV_E6063_MAX_PORTS_NUM, + MV_E6063_PORTS_OFFSET, + MV_E6063_ENABLED_PORTS); +} + +/******************************************************************************* +* mvEthE6131PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6131SwitchBasicInit(MV_U32 ethPortNum) +{ + + MV_U16 reg; + + /*Enable Phy power up*/ + mvEthPhyRegWrite (0,0,0x9140); + mvEthPhyRegWrite (1,0,0x9140); + mvEthPhyRegWrite (2,0,0x9140); + + + /*Enable PPU*/ + mvEthPhyRegWrite (0x1b,4,0x4080); + + + /*Enable Phy detection*/ + mvEthPhyRegRead (0x13,0,®); + reg &= ~(1<<12); + mvEthPhyRegWrite (0x13,0,reg); + + mvOsDelay(100); + mvEthPhyRegWrite (0x13,1,0x33); + + + switchVlanInit(ethPortNum, + MV_E6131_CPU_PORT, + MV_E6131_MAX_PORTS_NUM, + MV_E6131_PORTS_OFFSET, + MV_E6131_ENABLED_PORTS); + +} + + +/******************************************************************************* +* mvEthE6161PhyBasicInit - +* +* DESCRIPTION: +* Do a basic Init to the Phy , including reset +* +* INPUT: +* ethPortNum - Ethernet port number +* +* OUTPUT: +* None. +* +* RETURN: None +* +*******************************************************************************/ +MV_VOID mvEthE6161SwitchBasicInit(MV_U32 ethPortNum) +{ + + MV_U32 prt; + MV_U16 reg; + volatile MV_U32 timeout; + + /* The 6161/5 needs a delay */ + mvOsDelay(1000); + + /* Init vlan */ + switchVlanInit(ethPortNum, + MV_E6161_CPU_PORT, + MV_E6161_MAX_PORTS_NUM, + MV_E6161_PORTS_OFFSET, + MV_E6161_ENABLED_PORTS); + + /* Enable RGMII delay on Tx and Rx for CPU port */ + mvEthSwitchRegWrite (ethPortNum, 0x14,0x1a,0x81e7); + mvEthSwitchRegRead (ethPortNum, 0x15,0x1a,®); + mvEthSwitchRegWrite (ethPortNum, 0x15,0x1a,0x18); + mvEthSwitchRegWrite (ethPortNum, 0x14,0x1a,0xc1e7); + + for(prt=0; prt < MV_E6161_MAX_PORTS_NUM; prt++) + { + if (prt != MV_E6161_CPU_PORT) + { + /*Enable Phy power up*/ + mvEthSwitchRegWrite (ethPortNum, MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_DATA, 0x3360); + mvEthSwitchRegWrite (ethPortNum, MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND, (0x9410 | (prt << 5))); + + /*Make sure SMIBusy bit cleared before another SMI operation can take place*/ + timeout = E6161_PHY_TIMEOUT; + do + { + mvEthSwitchRegRead(ethPortNum, MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND,®); + if(timeout-- == 0) + { + mvOsPrintf("mvEthPhyRegRead: SMI busy timeout\n"); + return; + } + }while (reg & E6161_PHY_SMI_BUSY_MASK); + + mvEthSwitchRegWrite (ethPortNum, MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_DATA,0x1140); + mvEthSwitchRegWrite (ethPortNum, MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND,(0x9400 | (prt << 5))); + + /*Make sure SMIBusy bit cleared before another SMI operation can take place*/ + timeout = E6161_PHY_TIMEOUT; + do + { + mvEthSwitchRegRead(ethPortNum, MV_E6161_GLOBAL_2_REG_DEV_ADDR, + MV_E6161_SMI_PHY_COMMAND,®); + if(timeout-- == 0) + { + mvOsPrintf("mvEthPhyRegRead: SMI busy timeout\n"); + return; + } + }while (reg & E6161_PHY_SMI_BUSY_MASK); + + } + + /*Enable port*/ + mvEthSwitchRegWrite (ethPortNum, MV_E6161_PORTS_OFFSET + prt, 4, 0x7f); + } + + /*Force CPU port to RGMII FDX 1000Base*/ + mvEthSwitchRegWrite (ethPortNum, MV_E6161_PORTS_OFFSET + MV_E6161_CPU_PORT, 1, 0x3e); +} + +static void switchVlanInit(MV_U32 ethPortNum, + MV_U32 switchCpuPort, + MV_U32 switchMaxPortsNum, + MV_U32 switchPortsOffset, + MV_U32 switchEnabledPortsMask) +{ + MV_U32 prt; + MV_U16 reg; + + /* be sure all ports are disabled */ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,®); + reg &= ~0x3; + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,reg); + + } + + /* Set CPU port VID to 0x1 */ + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VID_REG,®); + reg &= ~0xfff; + reg |= 0x1; + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VID_REG,reg); + + + /* Setting Port default priority for all ports to zero */ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,®); + reg &= ~0xc000; + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,reg); + } + + /* Setting VID and VID map for all ports except CPU port */ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + + /* only for enabled ports */ + if ((1 << prt)& switchEnabledPortsMask) + { + /* skip CPU port */ + if (prt== switchCpuPort) continue; + + /* + * set Ports VLAN Mapping. + * port prt <--> MV_SWITCH_CPU_PORT VLAN #prt+1. + */ + + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,®); + reg &= ~0x0fff; + reg |= (prt+1); + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VID_REG,reg); + + + /* Set Vlan map table for all ports to send only to MV_SWITCH_CPU_PORT */ + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VMAP_REG,®); + reg &= ~((1 << switchMaxPortsNum) - 1); + reg |= (1 << switchCpuPort); + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_VMAP_REG,reg); + } + + } + + + /* Set Vlan map table for MV_SWITCH_CPU_PORT to see all ports*/ + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VMAP_REG,®); + reg &= ~((1 << switchMaxPortsNum) - 1); + reg |= switchEnabledPortsMask & ~(1 << switchCpuPort); + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(switchCpuPort), + MV_SWITCH_PORT_VMAP_REG,reg); + + + /*enable only appropriate ports to forwarding mode - and disable the others*/ + for(prt=0; prt < switchMaxPortsNum; prt++) + { + + if ((1 << prt)& switchEnabledPortsMask) + { + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,®); + reg |= 0x3; + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,reg); + + } + else + { + /* Disable port */ + mvEthSwitchRegRead (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,®); + reg &= ~0x3; + mvEthSwitchRegWrite (ethPortNum, MV_SWITCH_PORT_OFFSET(prt), + MV_SWITCH_PORT_CONTROL_REG,reg); + } + } + return; +} + +static void mvEthSwitchRegWrite(MV_U32 ethPortNum, MV_U32 phyAddr, + MV_U32 regOffs, MV_U16 data) +{ + MV_U16 reg; + + if(switchMultiChipMode == 0xdeadbeef) + { + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum) ,0x2, ®); + if(reg == 0xffff) + switchMultiChipMode = mvBoardPhyAddrGet(ethPortNum); + else + switchMultiChipMode = 0xffffffff; + } + if(switchMultiChipMode == 0xffffffff) + mvEthPhyRegWrite(phyAddr, regOffs, data); + else //If Switch is in multichip mode, need to use indirect register access + { + do + { + mvEthPhyRegRead(switchMultiChipMode, 0x0, ®); + } while((reg & BIT15)); // Poll till SMIBusy bit is clear + mvEthPhyRegWrite(switchMultiChipMode, 0x1, data); // Write data to Switch indirect data register + mvEthPhyRegWrite(switchMultiChipMode, 0x0, regOffs | (phyAddr << 5) | + BIT10 | BIT12 | BIT15); // Write command to Switch indirect command register + } +} + +static void mvEthSwitchRegRead(MV_U32 ethPortNum, MV_U32 phyAddr, + MV_U32 regOffs, MV_U16 *data) +{ + MV_U16 reg; + + if(switchMultiChipMode == 0xdeadbeef) + { + mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),0x2, ®); + if(reg == 0xffff) + switchMultiChipMode = mvBoardPhyAddrGet(ethPortNum); + else + switchMultiChipMode = 0xffffffff; + } + if(switchMultiChipMode == 0xffffffff) + mvEthPhyRegRead(phyAddr, regOffs, &data); + else //If Switch is in multichip mode, need to use indirect register access + { + do + { + mvEthPhyRegRead(switchMultiChipMode, 0x0, ®); + } while((reg & BIT15)); // Poll till SMIBusy bit is clear + mvEthPhyRegWrite(switchMultiChipMode, 0x0, regOffs | (phyAddr << 5) | + BIT11 | BIT12 | BIT15); // Write command to Switch indirect command register + do + { + mvEthPhyRegRead(switchMultiChipMode, 0, ®); + } while((reg & BIT15)); // Poll till SMIBusy bit is clear + mvEthPhyRegRead(switchMultiChipMode, 0x1, &data); // Write data to Switch indirect data register + } +} + + + + + diff --git a/board/mv_feroceon/mv_hal/ethswitch/mvSwitch.h b/board/mv_feroceon/mv_hal/ethswitch/mvSwitch.h new file mode 100644 index 0000000..ea2da25 --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethswitch/mvSwitch.h @@ -0,0 +1,75 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCETHSWITCHH +#define __INCETHSWITCHH + +#include "mvTypes.h" + +MV_VOID mvEthE6063SwitchBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE6065_61SwitchBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE6131SwitchBasicInit(MV_U32 ethPortNum); +MV_VOID mvEthE6161SwitchBasicInit(MV_U32 ethPortNum); + +#endif /* #ifndef __INCETHSWITCHH */ diff --git a/board/mv_feroceon/mv_hal/ethswitch/mvSwitchRegs.h b/board/mv_feroceon/mv_hal/ethswitch/mvSwitchRegs.h new file mode 100644 index 0000000..dd8370e --- /dev/null +++ b/board/mv_feroceon/mv_hal/ethswitch/mvSwitchRegs.h @@ -0,0 +1,109 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCethswitchregsh +#define __INCethswitchregsh + +#define MV_SWITCH_PORT_CONTROL_REG 0x4 +#define MV_SWITCH_PORT_VMAP_REG 0x6 +#define MV_SWITCH_PORT_VID_REG 0x7 + + +#define MV_SWITCH_PORT_OFFSET(port) (switchPortsOffset+port) + +/* E6063 related */ +#define MV_E6063_CPU_PORT 5 +#define MV_E6063_PORTS_OFFSET 0x8 +#define MV_E6063_MAX_PORTS_NUM 7 +#define MV_E6063_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)| \ + (1 << 3)|(1 << 4)|(1 << 5)) + +/* E6065 related */ +#define MV_E6065_CPU_PORT 5 +#define MV_E6065_PORTS_OFFSET 0x8 +#define MV_E6065_MAX_PORTS_NUM 6 +#define MV_E6065_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)) + +/* E6063 related */ +#define MV_E6131_CPU_PORT 0x3 +#define MV_E6131_PORTS_OFFSET 0x10 +#define MV_E6131_MAX_PORTS_NUM 8 +#define MV_E6131_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)| \ + (1 << 3)|(1 << 5)|(1 << 7)) +/* E6161 related */ +#define MV_E6161_CPU_PORT 0x5 +#define MV_E6161_PORTS_OFFSET 0x10 +#define MV_E6161_SMI_PHY_COMMAND 0x18 +#define MV_E6161_SMI_PHY_DATA 0x19 +#define MV_E6161_GLOBAL_2_REG_DEV_ADDR 0x1C +#define MV_E6161_MAX_PORTS_NUM 6 +#define MV_E6161_ENABLED_PORTS ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)) +#define E6161_PHY_TIMEOUT 10000 +#define E6161_PHY_SMI_BUSY_BIT 15 /* Busy */ +#define E6161_PHY_SMI_BUSY_MASK (1 << ETH_PHY_SMI_BUSY_BIT) + + + + +#endif /* __INCethswitchregsh */ diff --git a/board/mv_feroceon/mv_hal/gpp/mvGpp.c b/board/mv_feroceon/mv_hal/gpp/mvGpp.c new file mode 100644 index 0000000..355cb47 --- /dev/null +++ b/board/mv_feroceon/mv_hal/gpp/mvGpp.c @@ -0,0 +1,395 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvGpp.h" + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +static MV_VOID gppRegSet(MV_U32 group, MV_U32 regOffs,MV_U32 mask,MV_U32 value); + +/* modify by QNAP for recovery button *****************************************/ +void QNAP_recovery_init() +{ + /* UART 1: PIC */ + gppRegSet(0, mvCtrlMppRegGet(1), 0x00f00000, 0x03 << 20); + mvGppTypeSet(0, MV_GPP13, MV_GPP13 & MV_GPP_IN); +//Patch by QNAP:Fix detect DRAM size + //MV_GPP36 for DRAM ID + gppRegSet(0,mvCtrlMppRegGet(4),0x000f0000,0); + mvGppTypeSet(1,MV_GPP4,MV_GPP4 & MV_GPP_IN); +/////////////////////////////////////// +#if defined(TS119) || defined(TS219) || defined(TS118) || defined(TS218) +//Patch by QNAP:Initial HDD error LED + gppRegSet(0, mvCtrlMppRegGet(4), 0x0000ff00, 0); + mvGppTypeSet(1, MV_GPP2 | MV_GPP3, (MV_GPP2 | MV_GPP3)& MV_GPP_OUT); + mvGppValueSet(1,MV_GPP2 | MV_GPP3,MV_GPP2 | MV_GPP3); +/////////////////////////////////////// +//Patch by QNAP:Fix detect Model:High for TS119/TS219;Low for TS119P/TS219P + //MV_GPP38 for Model detect + gppRegSet(0,mvCtrlMppRegGet(4),0x0f000000,0); + mvGppTypeSet(1,MV_GPP6,MV_GPP6 & MV_GPP_IN); +////////////////////////////////////// + /* Recovery Button */ + gppRegSet(0, mvCtrlMppRegGet(2), 0x0000000f, 0); + mvGppTypeSet(0, MV_GPP16, MV_GPP16 & MV_GPP_IN); +#elif defined(TS419) + //MV_GPP44 for Model detect:High for TS419;Low for TS419U + gppRegSet(0,mvCtrlMppRegGet(5),0x000f0000,0); + mvGppTypeSet(1,MV_GPP12,MV_GPP12 & MV_GPP_IN); + //MV_GPP45 for Console/LCM 0:LCM 1:Console + gppRegSet(0,mvCtrlMppRegGet(5),0x00f00000,0); + mvGppTypeSet(1,MV_GPP13,MV_GPP13 & MV_GPP_IN); + /* Recovery Button */ + gppRegSet(0, mvCtrlMppRegGet(4), 0x00f00000, 0); + mvGppTypeSet(1, MV_GPP5, MV_GPP5 & MV_GPP_IN); +#endif +} + +MV_BOOL QNAP_recovery_detect() +{ +#if defined(TS119) || defined(TS219) || defined(TS118) || defined(TS218) + return !mvGppValueGet(0,MV_GPP16); +#elif defined(TS419) + return !mvGppValueGet(1,MV_GPP5); +#endif +} +/******************************************************************************/ + +/******************************************************************************* +* mvGppTypeSet - Enable a GPP (OUT) pin +* +* DESCRIPTION: +* +* INPUT: +* group - GPP group number +* mask - 32bit mask value. Each set bit in the mask means that the type +* of corresponding GPP will be set. Other GPPs are ignored. +* value - 32bit value that describes GPP type per pin. +* +* OUTPUT: +* None. +* +* EXAMPLE: +* Set GPP8 to input and GPP15 to output. +* mvGppTypeSet(0, (GPP8 | GPP15), +* ((MV_GPP_IN & GPP8) | (MV_GPP_OUT & GPP15)) ); +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvGppTypeSet(MV_U32 group, MV_U32 mask, MV_U32 value) +{ + if (group >= MV_GPP_MAX_GROUP) + { + DB(mvOsPrintf("mvGppTypeSet: ERR. invalid group number \n")); + return MV_BAD_PARAM; + } + + gppRegSet(group, GPP_DATA_OUT_EN_REG(group), mask, value); + + return MV_OK; + +} + +/******************************************************************************* +* mvGppBlinkEn - Set a GPP (IN) Pin list to blink every ~100ms +* +* DESCRIPTION: +* +* INPUT: +* group - GPP group number +* mask - 32bit mask value. Each set bit in the mask means that the type +* of corresponding GPP will be set. Other GPPs are ignored. +* value - 32bit value that describes GPP blink per pin. +* +* OUTPUT: +* None. +* +* EXAMPLE: +* Set GPP8 to be static and GPP15 to be blinking. +* mvGppBlinkEn(0, (GPP8 | GPP15), +* ((MV_GPP_OUT_STATIC & GPP8) | (MV_GPP_OUT_BLINK & GPP15)) ); +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvGppBlinkEn(MV_U32 group, MV_U32 mask, MV_U32 value) +{ + if (group >= MV_GPP_MAX_GROUP) + { + DB(mvOsPrintf("mvGppBlinkEn: ERR. invalid group number \n")); + return MV_BAD_PARAM; + } + + gppRegSet(group, GPP_BLINK_EN_REG(group), mask, value); + + return MV_OK; + +} +/******************************************************************************* +* mvGppPolaritySet - Set a GPP (IN) Pin list Polarity mode +* +* DESCRIPTION: +* +* INPUT: +* group - GPP group number +* mask - 32bit mask value. Each set bit in the mask means that the type +* of corresponding GPP will be set. Other GPPs are ignored. +* value - 32bit value that describes GPP polarity per pin. +* +* OUTPUT: +* None. +* +* EXAMPLE: +* Set GPP8 to the actual pin value and GPP15 to be inverted. +* mvGppPolaritySet(0, (GPP8 | GPP15), +* ((MV_GPP_IN_ORIGIN & GPP8) | (MV_GPP_IN_INVERT & GPP15)) ); +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvGppPolaritySet(MV_U32 group, MV_U32 mask, MV_U32 value) +{ + if (group >= MV_GPP_MAX_GROUP) + { + DB(mvOsPrintf("mvGppPolaritySet: ERR. invalid group number \n")); + return MV_BAD_PARAM; + } + + gppRegSet(group, GPP_DATA_IN_POL_REG(group), mask, value); + + return MV_OK; + +} + +/******************************************************************************* +* mvGppPolarityGet - Get a value of relevant bits from GPP Polarity register. +* +* DESCRIPTION: +* +* INPUT: +* group - GPP group number +* mask - 32bit mask value. Each set bit in the mask means that the +* returned value is valid for it. +* +* OUTPUT: +* None. +* +* EXAMPLE: +* Get GPP8 and GPP15 value. +* mvGppPolarityGet(0, (GPP8 | GPP15)); +* +* RETURN: +* 32bit value that describes GPP polatity mode per pin. +* +*******************************************************************************/ +MV_U32 mvGppPolarityGet(MV_U32 group, MV_U32 mask) +{ + MV_U32 regVal; + + if (group >= MV_GPP_MAX_GROUP) + { + DB(mvOsPrintf("mvGppActiveSet: Error invalid group number \n")); + return MV_ERROR; + } + regVal = MV_REG_READ(GPP_DATA_IN_POL_REG(group)); + + return (regVal & mask); +} + +/******************************************************************************* +* mvGppValueGet - Get a GPP Pin list value. +* +* DESCRIPTION: +* This function get GPP value. +* +* INPUT: +* group - GPP group number +* mask - 32bit mask value. Each set bit in the mask means that the +* returned value is valid for it. +* +* OUTPUT: +* None. +* +* EXAMPLE: +* Get GPP8 and GPP15 value. +* mvGppValueGet(0, (GPP8 | GPP15)); +* +* RETURN: +* 32bit value that describes GPP activity mode per pin. +* +*******************************************************************************/ +MV_U32 mvGppValueGet(MV_U32 group, MV_U32 mask) +{ + MV_U32 gppData; + + gppData = MV_REG_READ(GPP_DATA_IN_REG(group)); + + gppData &= mask; + + return gppData; + +} + +/******************************************************************************* +* mvGppValueSet - Set a GPP Pin list value. +* +* DESCRIPTION: +* This function set value for given GPP pin list. +* +* INPUT: +* group - GPP group number +* mask - 32bit mask value. Each set bit in the mask means that the +* value of corresponding GPP will be set accordingly. Other GPP +* are not affected. +* value - 32bit value that describes GPP value per pin. +* +* OUTPUT: +* None. +* +* EXAMPLE: +* Set GPP8 value of '0' and GPP15 value of '1'. +* mvGppActiveSet(0, (GPP8 | GPP15), ((0 & GPP8) | (GPP15)) ); +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvGppValueSet (MV_U32 group, MV_U32 mask, MV_U32 value) +{ + MV_U32 outEnable; + MV_U32 i; + + if (group >= MV_GPP_MAX_GROUP) + { + DB(mvOsPrintf("mvGppValueSet: Error invalid group number \n")); + return MV_BAD_PARAM; + } + + /* verify that the gpp pin is configured as output */ + /* Note that in the register out enabled -> bit = '0'. */ + outEnable = ~MV_REG_READ(GPP_DATA_OUT_EN_REG(group)); + + for (i = 0 ; i < 32 ;i++) + { + if (((mask & (1 << i)) & (outEnable & (1 << i))) != (mask & (1 << i))) + { + mvOsPrintf("mvGppValueSet: Err. An attempt to set output "\ + "value to GPP %d in input mode.\n", i); + return MV_ERROR; + } + } + + gppRegSet(group, GPP_DATA_OUT_REG(group), mask, value); + + return MV_OK; + +} +/******************************************************************************* +* gppRegSet - Set a specific GPP pin on a specific GPP register +* +* DESCRIPTION: +* This function set a specific GPP pin on a specific GPP register +* +* INPUT: +* regOffs - GPP Register offset +* group - GPP group number +* mask - 32bit mask value. Each set bit in the mask means that the +* value of corresponding GPP will be set accordingly. Other GPP +* are not affected. +* value - 32bit value that describes GPP value per pin. +* +* OUTPUT: +* None. +* +* EXAMPLE: +* Set GPP8 value of '0' and GPP15 value of '1'. +* mvGppActiveSet(0, (GPP8 | GPP15), ((0 & GPP8) | (1 & GPP15)) ); +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID gppRegSet (MV_U32 group, MV_U32 regOffs,MV_U32 mask,MV_U32 value) +{ + MV_U32 gppData; + + gppData = MV_REG_READ(regOffs); + + gppData &= ~mask; + + gppData |= (value & mask); + + MV_REG_WRITE(regOffs, gppData); +} + + diff --git a/board/mv_feroceon/mv_hal/gpp/mvGpp.h b/board/mv_feroceon/mv_hal/gpp/mvGpp.h new file mode 100644 index 0000000..526d324 --- /dev/null +++ b/board/mv_feroceon/mv_hal/gpp/mvGpp.h @@ -0,0 +1,118 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvGppH +#define __INCmvGppH + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "gpp/mvGppRegs.h" + +/* These macros describes the GPP type. Each of the GPPs pins can */ +/* be assigned to act as a general purpose input or output pin. */ +#define MV_GPP_IN 0xFFFFFFFF /* GPP input */ +#define MV_GPP_OUT 0 /* GPP output */ + + +/* These macros describes the GPP Out Enable. */ +#define MV_GPP_OUT_DIS 0xFFFFFFFF /* Out pin disabled*/ +#define MV_GPP_OUT_EN 0 /* Out pin enabled*/ + +/* These macros describes the GPP Out Blinking. */ +/* When set and the corresponding bit in GPIO Data Out Enable Control */ +/* Register is enabled, the GPIO pin blinks every ~100 ms (a period of */ +/* 2^24 TCLK clocks). */ +#define MV_GPP_OUT_BLINK 0xFFFFFFFF /* Out pin blinking*/ +#define MV_GPP_OUT_STATIC 0 /* Out pin static*/ + + +/* These macros describes the GPP Polarity. */ +/* When set to 1 GPIO Data In Register reflects the inverted value of the */ +/* corresponding pin. */ + +#define MV_GPP_IN_INVERT 0xFFFFFFFF /* Inverted value is got*/ +#define MV_GPP_IN_ORIGIN 0 /* original value is got*/ + +/* mvGppTypeSet - Set PP pin mode (IN or OUT) */ +MV_STATUS mvGppTypeSet(MV_U32 group, MV_U32 mask, MV_U32 value); + +/* mvGppBlinkEn - Set a GPP (IN) Pin list to blink every ~100ms */ +MV_STATUS mvGppBlinkEn(MV_U32 group, MV_U32 mask, MV_U32 value); + +/* mvGppPolaritySet - Set a GPP (IN) Pin list Polarity mode. */ +MV_STATUS mvGppPolaritySet(MV_U32 group, MV_U32 mask, MV_U32 value); + +/* mvGppPolarityGet - Get the Polarity of a GPP Pin */ +MV_U32 mvGppPolarityGet(MV_U32 group, MV_U32 mask); + +/* mvGppValueGet - Get a GPP Pin list value.*/ +MV_U32 mvGppValueGet(MV_U32 group, MV_U32 mask); + + +/* mvGppValueSet - Set a GPP Pin list value. */ +MV_STATUS mvGppValueSet (MV_U32 group, MV_U32 mask, MV_U32 value); + +#endif /* #ifndef __INCmvGppH */ + diff --git a/board/mv_feroceon/mv_hal/gpp/mvGppRegs.h b/board/mv_feroceon/mv_hal/gpp/mvGppRegs.h new file mode 100644 index 0000000..b6fec34 --- /dev/null +++ b/board/mv_feroceon/mv_hal/gpp/mvGppRegs.h @@ -0,0 +1,116 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvGppRegsH +#define __INCmvGppRegsH + +#define MV_GPP0 BIT0 +#define MV_GPP1 BIT1 +#define MV_GPP2 BIT2 +#define MV_GPP3 BIT3 +#define MV_GPP4 BIT4 +#define MV_GPP5 BIT5 +#define MV_GPP6 BIT6 +#define MV_GPP7 BIT7 +#define MV_GPP8 BIT8 +#define MV_GPP9 BIT9 +#define MV_GPP10 BIT10 +#define MV_GPP11 BIT11 +#define MV_GPP12 BIT12 +#define MV_GPP13 BIT13 +#define MV_GPP14 BIT14 +#define MV_GPP15 BIT15 +#define MV_GPP16 BIT16 +#define MV_GPP17 BIT17 +#define MV_GPP18 BIT18 +#define MV_GPP19 BIT19 +#define MV_GPP20 BIT20 +#define MV_GPP21 BIT21 +#define MV_GPP22 BIT22 +#define MV_GPP23 BIT23 +#define MV_GPP24 BIT24 +#define MV_GPP25 BIT25 +#define MV_GPP26 BIT26 +#define MV_GPP27 BIT27 +#define MV_GPP28 BIT28 +#define MV_GPP29 BIT29 +#define MV_GPP30 BIT30 +#define MV_GPP31 BIT31 + + +/* registers offsets */ + +#define GPP_DATA_OUT_REG(grp) ((grp == 0) ? 0x10100 : 0x10140) +#define GPP_DATA_OUT_EN_REG(grp) ((grp == 0) ? 0x10104 : 0x10144) +#define GPP_BLINK_EN_REG(grp) ((grp == 0) ? 0x10108 : 0x10148) +#define GPP_DATA_IN_POL_REG(grp) ((grp == 0) ? 0x1010C : 0x1014c) +#define GPP_DATA_IN_REG(grp) ((grp == 0) ? 0x10110 : 0x10150) +#define GPP_INT_CAUSE_REG(grp) ((grp == 0) ? 0x10114 : 0x10154) +#define GPP_INT_MASK_REG(grp) ((grp == 0) ? 0x10118 : 0x10158) +#define GPP_INT_LVL_REG(grp) ((grp == 0) ? 0x1011c : 0x1015c) + +#define GPP_DATA_OUT_SET_REG 0x10120 +#define GPP_DATA_OUT_CLEAR_REG 0x10124 + +#endif /* #ifndef __INCmvGppRegsH */ diff --git a/board/mv_feroceon/mv_hal/norflash/mvAmdFlash.c b/board/mv_feroceon/mv_hal/norflash/mvAmdFlash.c new file mode 100644 index 0000000..9666b4d --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvAmdFlash.c @@ -0,0 +1,279 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvFlash.h" + +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +static MV_BOOL amdFlashStsIsRdy(MV_FLASH_INFO *pFlash, MV_U32 offset, + MV_U32 excepted); +static MV_VOID amdFlashUnlock(MV_FLASH_INFO *pFlash); + +/******************************************************************************* +* reset the flash +*******************************************************************************/ +MV_VOID amdFlashReset(MV_FLASH_INFO *pFlash) +{ + flashCmdSet(pFlash, 0, 0, AMD_CHIP_CMD_RST); + return; +} + +/******************************************************************************* +* amdFlashSecErase - Erase a sector. +* +* DESCRIPTION: +* Erase a Flash sector. +* +* INPUT: +* secNum - sector Number. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* MV_OK if program completed successfully, +* MV_TIMEOUT if timeout reached, +* MV_FAIL otherwise. +* +*******************************************************************************/ +MV_STATUS amdFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum) +{ + MV_U32 i; + + DB(mvOsPrintf("Flash: amdFlashSecErase\n")); + + /* erase sequence */ + amdFlashUnlock(pFlash); + + switch (pFlash->flashSpec.flashVen) + { + case AMD_MANUF: + case STM_MANUF: + flashCmdSet(pFlash, AMD_CHIP_ADDR_ERASE1, 0, AMD_CHIP_CMD_ERASE1); + flashCmdSet(pFlash, AMD_CHIP_ADDR_ERASE2, 0, AMD_CHIP_CMD_ERASE2); + flashCmdSet(pFlash, AMD_CHIP_ADDR_ERASE3, 0, AMD_CHIP_CMD_ERASE3); + flashCmdSet(pFlash, 0, secNum, AMD_CHIP_CMD_ERASE4); + break; + case SST_MANUF: + flashCmdSet(pFlash, SST_CHIP_ADDR_ERASE1, 0, AMD_CHIP_CMD_ERASE1); + flashCmdSet(pFlash, SST_CHIP_ADDR_ERASE2, 0, AMD_CHIP_CMD_ERASE2); + flashCmdSet(pFlash, SST_CHIP_ADDR_ERASE3, 0, AMD_CHIP_CMD_ERASE3); + flashCmdSet(pFlash, 0, secNum, AMD_CHIP_CMD_ERASE4); + break; + + } + + + + /* wait for erase to complete */ + for(i = 0; i < AMD_EARASE_MILI_TIMEOUT; i++) + { + mvOsDelay(1); + if(MV_TRUE == amdFlashStsIsRdy(pFlash, mvFlashSecOffsGet(pFlash,secNum) + + mvFlashBaseAddrGet(pFlash), AMD_CHIP_STAT_DQ7_MASK)) + { + DB(mvOsPrintf("Flash: amdFlashSecErase erase PASS !!\n")); + return MV_OK; + } + } + mvOsPrintf("Flash: ERROR amdFlashSecErase timeout \n"); + + return MV_TIMEOUT; +} + + +/******************************************************************************* +* amdFlashProg - Prog busWidth Bits into the address offest in the flash. +* +* DESCRIPTION: +* This function writes busWidth data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* data - 32bit data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if program completed successfully, +* MV_TIMEOUT otherwise. +* +*******************************************************************************/ +MV_STATUS amdFlashProg(MV_FLASH_INFO *pFlash,MV_U32 offset, MV_U32 data) +{ + MV_U32 i; + MV_U32 statusExpectedData; + + DB(mvOsPrintf("Flash: amdFlashProg offset %x data %x\n",offset,data)); + + /* write sequence */ + amdFlashUnlock(pFlash); + + switch (pFlash->flashSpec.flashVen) + { + case AMD_MANUF: + case STM_MANUF: + flashCmdSet(pFlash, AMD_CHIP_ADDR_PROG, 0, AMD_CHIP_CMD_PROG); + break; + case SST_MANUF: + flashCmdSet(pFlash, SST_CHIP_ADDR_PROG, 0, AMD_CHIP_CMD_PROG); + break; + + } + flashBusWidthDataWr(pFlash, offset + mvFlashBaseAddrGet(pFlash), data); + + /* To check status we need to be sure that the data is in the same endianess + of the status, the status is always little endian and the data is big endian + , so we will convert the data to little endian before calling the amdFlashStsIsRdy + function*/ + + switch(pFlash->busWidth) + { + case 1: + statusExpectedData = data; + break; + case 2: + statusExpectedData = MV_16BIT_LE(data); + break; + case 4: + statusExpectedData = MV_32BIT_LE(data); + break; + default: + mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", + __FUNCTION__, pFlash->busWidth); + return MV_TIMEOUT; + } + + + /* wait for write to complete */ + for(i = 0; i < AMD_PROG_TIMEOUT; i++) + { + if(MV_TRUE == amdFlashStsIsRdy(pFlash,offset + + mvFlashBaseAddrGet(pFlash), + statusExpectedData)) + { + DB(mvOsPrintf("Flash: amdFlashProg prog PASS !!\n")); + return MV_OK; + } + } + + mvOsPrintf("Flash: ERROR amdFlashSecErase timeout \n"); + + return MV_TIMEOUT; +} + +/******************************************************************************* +* There are few ways to check if the AMD flash is busy or not: +* 1) by checking DQ7 [and 5 - optional ] +* 2) by checking toggle bit DQ7 (linux implementation) +* here we used the first option: +* after write/erase the flash push not(DQ7) until the opertion is completed. +*******************************************************************************/ +static MV_BOOL amdFlashStsIsRdy(MV_FLASH_INFO *pFlash, MV_U32 addr, + MV_U32 expected) +{ + MV_U32 status; + + status = flashBusWidthRd(pFlash, addr); + /* if DQ7 == Datum 7 */ + if((status & flashDataExt(pFlash, AMD_CHIP_STAT_DQ7_MASK )) == + (flashDataExt(pFlash,expected) & + flashDataExt(pFlash, AMD_CHIP_STAT_DQ7_MASK))) + { + DB(mvOsPrintf("Flash: amdFlashStatusChk value is ready \n")); + return MV_TRUE; + } + DB(mvOsPrintf("Flash: amdFlashStatusChk staus not ready \n")); + return MV_FALSE; +} + +/******************************************************************************* +* Sequence for Unlocking the flash before accessing the flash. +*******************************************************************************/ +static MV_VOID amdFlashUnlock(MV_FLASH_INFO *pFlash) +{ + switch (pFlash->flashSpec.flashVen) + { + case AMD_MANUF: + case STM_MANUF: + flashCmdSet(pFlash, AMD_CHIP_UNLOCK_ADDR1, 0, AMD_CHIP_UNLOCK_CMD1); + flashCmdSet(pFlash, AMD_CHIP_UNLOCK_ADDR2, 0, AMD_CHIP_UNLOCK_CMD2); + break; + case SST_MANUF: + flashCmdSet(pFlash, SST_CHIP_UNLOCK_ADDR1, 0, AMD_CHIP_UNLOCK_CMD1); + flashCmdSet(pFlash, SST_CHIP_UNLOCK_ADDR2, 0, AMD_CHIP_UNLOCK_CMD2); + break; + } + return; +} + + + diff --git a/board/mv_feroceon/mv_hal/norflash/mvAmdFlash.h b/board/mv_feroceon/mv_hal/norflash/mvAmdFlash.h new file mode 100644 index 0000000..791db1b --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvAmdFlash.h @@ -0,0 +1,168 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvAmdFlashH +#define __INCmvAmdFlashH + +#include "mvFlashCom.h" + + +/* AMD Flash IDs */ +#define AMD_FID_LV040B 0x4F /* 29LV040B ID */ + /* 4 Mbit, 512K x 8, */ + /* 8 64K x 8 uniform sectors */ + +#define AMD_FID_F040B 0xA4 /* 29F040B ID */ + /* 4 Mbit, 512K x 8, */ + /* 8 64K x 8 uniform sectors */ +#define STM_FID_M29W040B 0xE3 /* M29W040B ID */ + /* 4 Mbit, 512K x 8, */ + /* 8 64K x 8 uniform sectors */ +#define AMD_FID_F080B 0xD5 /* 29F080 ID ( 1 M) */ + /* 8 Mbit, 512K x 16, */ + /* 8 64K x 16 uniform sectors */ +#define AMD_FID_F016D 0xAD /* 29F016 ID ( 2 M x 8) */ +#define AMD_FID_F032B 0x41 /* 29F032 ID ( 4 M x 8) */ +#define AMD_FID_LV116DT 0xC7 /* 29LV116DT ( 2 M x 8, top boot sect)*/ +#define AMD_FID_LV016B 0xc8 /* 29LV016 ID ( 2 M x 8) */ + +#define AMD_FID_LV400T 0x22B9 /* 29LV400T ID ( 4 M, top boot sector) */ +#define AMD_FID_LV400B 0x22BA /* 29LV400B ID ( 4 M, bottom boot sect) */ + +#define AMD_FID_LV033C 0xA3 /* 29LV033C ID ( 4 M x 8) */ +#define AMD_FID_LV065D 0x93 /* 29LV065D ID ( 8 M x 8) */ + +#define AMD_FID_LV800T 0x22DA /* 29LV800T ID ( 8 M, top boot sector) */ +#define AMD_FID_LV800B 0x225B /* 29LV800B ID ( 8 M, bottom boot sect) */ + +#define AMD_FID_LV160T 0x22C4 /* 29LV160T ID (16 M, top boot sector) */ +#define AMD_FID_LV160B 0x2249 /* 29LV160B ID (16 M, bottom boot sect) */ + +#define AMD_FID_LV320T 0x22F6 /* 29LV320T ID (32 M, top boot sector) */ +#define AMD_FID_LV320B 0x22F9 /* 29LV320B ID (32 M, bottom boot sect) */ + +#define AMD_FID_DL322T 0x2255 /* 29DL322T ID (32 M, top boot sector) */ +#define AMD_FID_DL322B 0x2256 /* 29DL322B ID (32 M, bottom boot sect) */ +#define AMD_FID_DL323T 0x2250 /* 29DL323T ID (32 M, top boot sector) */ +#define AMD_FID_DL323B 0x2253 /* 29DL323B ID (32 M, bottom boot sect) */ +#define AMD_FID_DL324T 0x225C /* 29DL324T ID (32 M, top boot sector) */ +#define AMD_FID_DL324B 0x225F /* 29DL324B ID (32 M, bottom boot sect) */ + +#define AMD_S29GL128N 0x227E /* S29GL128N spansion 128Mbit flash */ +#define AMD_FID_DL640 0x227E /* 29DL640D ID (64 M, dual boot sectors)*/ +#define AMD_FID_MIRROR 0x227E /* 1st ID word for MirrorBit family */ +#define AMD_FID_LV640U_2 0x220C /* 2d ID word for AM29LV640M at 0x38 */ +#define AMD_FID_LV640U_3 0x2201 /* 3d ID word for AM29LV640M at 0x3c */ +#define AMD_FID_LV128U_2 0x2212 /* 2d ID word for AM29LV128M at 0x38 */ +#define AMD_FID_LV128U_3 0x2200 /* 3d ID word for AM29LV128M at 0x3c */ + +#define AMD_FID_LV640U 0x22D7 /* 29LV640U ID (64 M, uniform sectors) */ + +#define STM_FID_29W040B 0xE3 /* M29W040B ID (4M = 512K x 8) */ + +/* SST Flash IDs */ +#define SST_39VF_020 0xD6 /* SST39VF020 (256KB = 4K * 64) */ + + +/* Amd Flash APIs */ +#define AMD_EARASE_MILI_TIMEOUT 8000 /* mili seconds */ +#define AMD_PROG_TIMEOUT 0xA0000 /* number of loops */ + +/* Commands */ +#define AMD_CHIP_CMD_RST 0xF0 /* reset flash */ +#define AMD_CHIP_UNLOCK_CMD1 0xAA /* 1st data for unlock */ +#define AMD_CHIP_UNLOCK_ADDR1 0x555 /* 1st addr for unlock */ +#define SST_CHIP_UNLOCK_ADDR1 0x5555 /* 1st addr for unlock */ +#define AMD_CHIP_UNLOCK_CMD2 0x55 /* 2nd data for unlock */ +#define AMD_CHIP_UNLOCK_ADDR2 0x2AA /* 2nd addr for unlock */ +#define SST_CHIP_UNLOCK_ADDR2 0x2AAA /* 2nd addr for unlock */ +#define AMD_CHIP_CMD_PROG 0xA0 /* 1st data for program command */ +#define AMD_CHIP_ADDR_PROG 0x555 /* 1st addr for program command */ +#define SST_CHIP_ADDR_PROG 0x5555 /* 1st addr for program command */ +#define AMD_CHIP_CMD_ERASE1 0x80 /* 1st data for erase command */ +#define AMD_CHIP_ADDR_ERASE1 0x555 /* 1st addr for erase command */ +#define SST_CHIP_ADDR_ERASE1 0x5555 /* 1st addr for erase command */ +#define AMD_CHIP_CMD_ERASE2 0xAA /* 2nd data for erase command */ +#define AMD_CHIP_ADDR_ERASE2 0x555 /* 2nd addr for erase command */ +#define SST_CHIP_ADDR_ERASE2 0x5555 /* 2nd addr for erase command */ +#define AMD_CHIP_CMD_ERASE3 0x55 /* 3rd data for erase command */ +#define AMD_CHIP_ADDR_ERASE3 0x2AA /* 3rd addr for erase command */ +#define SST_CHIP_ADDR_ERASE3 0x2AAA /* 3rd addr for erase command */ +#define AMD_CHIP_CMD_ERASE4 0x30 /* 4rd data for erase command */ + +/* there are few ways to check if the AMD flash is busy or not: */ +/* 1) by checking DQ7 [and 5 - optional ] */ +/* 2) by checking toggle bit DQ7 (linux) */ +/* here we used the first option. */ +/* status register bits */ +#define AMD_CHIP_STAT_DQ7_MASK 0x80 /* Device is ready */ + +/* ID and Lock Configuration */ +#define AMD_CHIP_RD_ID_MAN 0x01 /* Manufacturer code = 0x89 */ + +MV_STATUS amdFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum); +MV_VOID amdFlashReset(MV_FLASH_INFO *pFlash); +MV_STATUS amdFlashProg(MV_FLASH_INFO *pFlash,MV_U32 offset, MV_U32 data); + +#endif /* __INCmvAmdFlashH */ diff --git a/board/mv_feroceon/mv_hal/norflash/mvFlash.c b/board/mv_feroceon/mv_hal/norflash/mvFlash.c new file mode 100644 index 0000000..4eae4e8 --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvFlash.c @@ -0,0 +1,1409 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvFlash.h" + + +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +#define LAST_FLASH 0xFFFFFFFF +/* When inserting a bottom/top flash number of sectors should be the number */ +/* of all sector including the "fragmented" sectors. */ +/* */ +/* Size of the flash must be as spesified in Spec, in case there are 2 dev */ +/* in a row the driver will recognize it according to bus and dev width. */ +/* */ +/* In case of using Bottom flash it should look like this: */ +/* MV_U32 IntelSecFrag[]= {_8K, _8K, _8K, _8K, _8K, _8K, _8K, _8K}; */ +/* FLASH_STRUCT supFlashAry[]= */ +/* { */ +/* { */ +/* INTEL_MANUF, flash Vendor */ +/* INTEL_FID_28F640J3A, flash ID */ +/* _4M, flash size */ +/* 71, flash secotor number */ +/* BOTTOM, flash sector structure (top, bottom, regular) */ +/* 8, Number of sector fragments */ +/* IntelSecFrag, pointer to sector size fragment list */ +/* MV_FALSE Support of HW protection */ +/* }, */ +/* ....... */ +/* } */ +/* */ +FLASH_STRUCT supFlashAry[]= +{ +/* flashVen flashId size #sec secType #Frag pFragList HWprot HwWrBuff */ +{INTEL_MANUF, INTEL_FID_28F640J3A, _8M, 64, REGULAR, 0, NULL, MV_TRUE, 32 }, +{INTEL_MANUF, INTEL_FID_28F128J3A, _16M, 128, REGULAR, 0, NULL, MV_TRUE, 32 }, +{SST_MANUF, SST_39VF_020, _256K, 64, REGULAR, 0, NULL, MV_FALSE, 0 }, +{AMD_MANUF, AMD_FID_LV040B, _512K, 8, REGULAR, 0, NULL, MV_FALSE, 0 }, +{STM_MANUF, STM_FID_29W040B, _512K, 8, REGULAR, 0, NULL, MV_FALSE, 0 }, +{AMD_MANUF, AMD_S29GL128N, _16M, 128, REGULAR, 0, NULL, MV_FALSE}, +{MX_MANUF, AMD_FID_MIRROR, _16M, 256, REGULAR, 0, NULL, MV_FALSE}, +{STM_MANUF, AMD_FID_MIRROR, _16M, 256, REGULAR, 0, NULL, MV_FALSE}, +{LAST_FLASH, LAST_FLASH, 0, 0, REGULAR, 0, NULL, MV_FALSE, 0 } +}; + +static MV_STATUS flashReset(MV_FLASH_INFO *pFlash); +static MV_STATUS flashStructGet(MV_FLASH_INFO *pFlash, MV_U32 manu, MV_U32 id); +static MV_STATUS flashSecsInit(MV_FLASH_INFO *pFlash); +static MV_BOOL flashSecLockGet(MV_FLASH_INFO *pBlock,MV_U32 secNum); +static MV_STATUS mvFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data); +static MV_U32 flashGetHwBuffSize(MV_FLASH_INFO *pFlash); +static MV_STATUS flashHwBufferProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 byteCount, + MV_U8 *pData); + +/******************************************************************************* +* mvFlashInit - Initialize a flash descriptor structure. +* +* DESCRIPTION: +* This function intialize flash info struct with specified flash +* parameters. This structure is used to identify the target flash the +* function refers to. This allow the use of the same API for multiple +* flash devices. +* +* +* INPUT: +* pFlash->baseAddr - Flash base address. +* pFlash->busWidth - Flash bus width (8, 16, 32 bit). +* pFlash->devWidth - Flash device width (8 or 16 bit). +* +* OUTPUT: +* pFlash - Flash identifier structure. +* +* RETURN: +* 32bit describing flash size. +* In case of any error, it returns 0. +* +*******************************************************************************/ +MV_U32 mvFlashInit(MV_FLASH_INFO *pFlash) +{ + MV_U32 manu = 0, id = 0; + + if(NULL == pFlash) + return 0; + + DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n", + pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth)); + + /* must init first sector base, before calling flashCmdSet */ + pFlash->sector[0].baseOffs = 0; + /* reset flash 0xf0(AMD) 0xff (Intel) */ + flashCmdSet(pFlash, 0, 0, 0xf0); + flashCmdSet(pFlash, 0, 0, 0xff); + + /* Write auto select command: read Manufacturer ID */ + /* AMD seq is: 0x555 0xAA -> 0x2AA 0x55 -> 0x555 0x90 */ + /* INTEL seq is dc 0x90 */ + flashCmdSet(pFlash, 0x555, 0, 0xAA); + flashCmdSet(pFlash, 0x2AA, 0, 0x55); + flashCmdSet(pFlash, 0x555, 0, 0x90); + + + /* Write auto select command: read Manufacturer ID */ + /* SST seq is: 0x5555 0xAA -> 0x2AAA 0x55 -> 0x5555 0x90 */ + flashCmdSet(pFlash, 0x5555, 0, 0xAA); + flashCmdSet(pFlash, 0x2AAA, 0, 0x55); + flashCmdSet(pFlash, 0x5555, 0, 0x90); + + DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n", + pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth)); + + + /* get flash Manufactor and Id */ + manu = flashBusWidthRd(pFlash, mvFlashBaseAddrGet(pFlash)); + DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n", + pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth)); + + + /* Some Micron flashes don't use A0 address for Identifier and + Lock information, so in order to read Identifier and lock information + properly we will do the following workarround: + If our device width is 1 (x8) then if address 0 equal to address 1 + and address 2 equal to address 3 ,then we have this case (A0 is not used) + and then we will issue the address without A0 to read the Identifier and + lock information properly*/ + DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n", + pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth)); + + + if ((pFlash->devWidth == 1) && + ((flashBusWidthRd(pFlash, flashAddrExt(pFlash, 0, 0)) == + flashBusWidthRd(pFlash, flashAddrExt(pFlash, 1, 0)))&& + (flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, 0)) == + flashBusWidthRd(pFlash, flashAddrExt(pFlash, 3, 0))))) + { + id = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, 0)); + + } else id = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 1, 0)); + + + /* check if this flash is Supported, and Init the pFlash flash feild */ + if( MV_OK != flashStructGet(pFlash, manu, id ) ) + { + mvOsPrintf("%s: Flash ISN'T supported: manufactor-0x%x, id-0x%x\n", + __FUNCTION__, manu, id); + return 0; + } + DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n", + pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth)); + + + /* Init pFlash sectors */ + if(MV_OK != flashSecsInit(pFlash)) + { + mvOsPrintf("Flash: ERROR mvFlashInit flashSecsInit failed \n"); + return 0; + } + + DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n", + pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth)); + + + /* print all flash information */ + DB(flashPrint(pFlash)); + + /* reset the Flash */ + flashReset(pFlash); + DB(mvOsOutput("Flash: mvFlashInit base 0x%x devW %d busW %d\n", + pFlash->baseAddr, pFlash->devWidth, pFlash->busWidth)); + + + return mvFlashSizeGet(pFlash); +} + + +/* erase */ +/******************************************************************************* +* mvFlashErase - Completly Erase a flash. +* +* DESCRIPTION: +* This function completly erase the given flash, by erasing all the +* flash sectors one by one (Currently there is no support for HW +* flash erase). +* +* INPUT: +* pFlash - Flash identifier structure. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if pFlash is NULL, +* MV_OK if erased completed successfully, +* MV_FAIL otherwise. +* +*******************************************************************************/ +MV_STATUS mvFlashErase(MV_FLASH_INFO *pFlash) +{ + MV_U32 i; + + if(NULL == pFlash) + return MV_BAD_PARAM; + + DB(mvOsPrintf("Flash: mvFlashErase \n")); + /* erase all sectors in the flash one by one */ + for(i = 0; i < mvFlashNumOfSecsGet(pFlash); i++) + { + if( MV_OK != mvFlashSecErase(pFlash,i) ) + return MV_FAIL; + } + + return MV_OK; +} + +/******************************************************************************* +* flashIsSecErased - Check if a given Sector is erased. +* +* DESCRIPTION: +* Go over the sector and check if its entire data is 0xFF. +* INPUT: +* secNum - sector Number. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* MV_BAD_PARAM if one of the inputs values is illegal, +* MV_TRUE if sector is already erased, +* MV_FALSE otherwise. +* +*******************************************************************************/ +MV_BOOL flashIsSecErased(MV_FLASH_INFO *pFlash, MV_U32 secNum) +{ + MV_U32 i; + + DB(mvOsPrintf("Flash: flashIsSecErased. \n")); + if((NULL == pFlash) || (secNum >= mvFlashNumOfSecsGet(pFlash)) ) + return MV_BAD_PARAM; + + /* reset the flash */ + flashReset(pFlash); + + /* go over the sector */ + for(i = mvFlashSecOffsGet(pFlash,secNum); + i < mvFlashSecOffsGet(pFlash,secNum) + mvFlashSecSizeGet(pFlash,secNum); + i+= 4) + { + if(mvFlash32Rd(pFlash,i) != FLASH_WR_ERASED ) + { + DB(mvOsPrintf("Flash: Not erased addr %x is %x \n", + i ,mvFlash32Rd(pFlash,i))); + return MV_FALSE; + } + } + return MV_TRUE; +} + + +/******************************************************************************* +* mvFlashSecErase - Erase a flash sector. +* +* DESCRIPTION: +* This function checks if the sector isn't protected and if the sector +* isn't already erased. +* +* INPUT: +* pFlash - Flash identifier structure. +* sectorNum - secrot number to erase. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if one of the inputs values is illegal, +* MV_OK if erased completed successfully, +* MV_FAIL otherwise (e.g. sector protected). +* +*******************************************************************************/ +MV_STATUS mvFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 sectorNum) +{ + MV_U32 status; + DB(mvOsPrintf("Flash: mvFlashSecErase \n")); + + /* check parametrs values */ + if((NULL == pFlash) || (sectorNum >= mvFlashNumOfSecsGet(pFlash)) ) { + return MV_BAD_PARAM; + } + + /* check if sector is locked */ + if(MV_TRUE == mvFlashSecLockGet(pFlash, sectorNum)) + { + mvOsPrintf("Flash: ERROR mvFlashSecErase protected sector.\n"); + return MV_FAIL; + } + /* check if already erased */ + if(MV_TRUE == flashIsSecErased(pFlash,sectorNum)) + { + DB(mvOsPrintf("Flash: FlashSecErase sector already erased \n")); + return MV_OK; + } + + /* erase sector using the Flash Ven Alg. */ + switch(mvFlashVenIdGet(pFlash)) + { + case INTEL_MANUF: /* INTEL/MT */ + status = intelFlashSecErase(pFlash,sectorNum); + break; + case AMD_MANUF: + case STM_MANUF: + case SST_MANUF: + case MX_MANUF: + status = amdFlashSecErase(pFlash,sectorNum); + break; + default: + mvOsPrintf("Flash: ERROR mvFlashErase. unsupported flash vendor\n"); + return MV_FAIL; + } + /* reset the flash */ + flashReset(pFlash); + + return status; +} + +/* write */ +/******************************************************************************* +* mvFlash32Wr - Write 32bit (word) to flash. +* +* DESCRIPTION: +* This function writes 32bit data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* data - 32bit data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if one of the inputs values is illegal, +* MV_OK if write completed successfully, +* MV_FAIL otherwise (e.g. sector protected). +* +*******************************************************************************/ +MV_STATUS mvFlash32Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data) +{ + MV_U32 i, status = MV_OK, temp,secNum; + + DB(mvOsPrintf("Flash: mvFlash32Wr offset %x data %x \n",offset,data)); + + /* check that the offset is aligned to 32 bit */ + if((NULL == pFlash) || (offset % 4)) + return MV_BAD_PARAM; + + secNum = mvFlashInWhichSec(pFlash,offset); + + DB(mvOsPrintf("Flash: mvFlashProg \n")); + /* check if offset is in flash range */ + if( secNum >= mvFlashNumOfSecsGet(pFlash)) + { + DB(mvOsPrintf("Flash: mvFlashProg offset out of flash range \n")); + return MV_BAD_PARAM; + } + + /* check if sector is locked */ + if(MV_TRUE == mvFlashSecLockGet(pFlash, secNum) ) + { + mvOsPrintf("Flash: ERROR mvFlashProg protected sector.\n"); + return MV_FAIL; + } + + /* check if offset is erased enough */ + if((mvFlash32Rd(pFlash, offset) & data) != data ) + { + mvOsPrintf("%s ERROR: offset 0x%x (sector %d) isn't erased !!!.\n", + __FUNCTION__, offset, secNum); + return MV_FAIL; + } + + + /* bus width is 32 bit */ + if(mvFlashBusWidthGet(pFlash) == 4) + { + data = MV_32BIT_BE(data); + status = mvFlashProg(pFlash, offset,data); + if (status != MV_OK ) + { + mvOsPrintf("%s ERROR: mvFlashProg() status %x \n", + __FUNCTION__, status); + } + } + + /* bus width is 16 bit */ + else if(mvFlashBusWidthGet(pFlash) == 2) + { + for(i = 0; i < 2; i++) + { + /* 0x44556677 -> [44][55][66][77] */ + temp = MV_16BIT_BE(((data >> (16*(1-i))) & FLASH_MASK_16BIT)); + if(MV_OK != mvFlashProg(pFlash, offset + (i*2), temp) ) + { + status = MV_FAIL; + break; + } + } + } + /* bus width is 8 bit */ + else if(mvFlashBusWidthGet(pFlash) == 1) + { + for(i = 0; i < 4; i++) + { + /* 0x44556677 -> [44][55][66][77] */ + temp = ((data >> (8*(3-i))) & FLASH_MASK_8BIT); + if(MV_OK != mvFlashProg(pFlash, offset + i, temp )) + { + status = MV_FAIL; + } + } + } + /* bus width isn't 8/16/32 */ + else + { + DB(mvOsPrintf("Flash: mvFlashWordWr no support for for bus width %d \n", + mvFlashBusWidthGet(pFlash) )); + status = MV_FAIL; + } + /* reset the flash */ + flashReset(pFlash); + + if (status != MV_OK ) + { + mvOsPrintf("mvFlash32Wr: ERROR #### status %x \n", status ); + } + + return status; +} + +/******************************************************************************* +* mvFlash16Wr - Write 16bit (short) to flash. +* +* DESCRIPTION: +* This function writes 16bit data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* sdata - 16bit data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if one of the inputs values is illegal, +* MV_OK if write completed successfully, +* MV_FAIL otherwise (e.g. sector protected). +* +*******************************************************************************/ +MV_STATUS mvFlash16Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U16 sdata) +{ + MV_U32 temp,shiftSdata; + + DB(mvOsPrintf("Flash: mvFlash16Wr\n")); + + /* check that the offset is aligned to 16 bit */ + if((NULL == pFlash) || (offset % 2)) + return MV_BAD_PARAM; + + /* sdata shift in 32 bit aligned. i.e. */ + /* wr 0x9922 to 0xf4000002 -> 0xf4000000: qqqq9999 */ + shiftSdata = (1 - ((offset & 0x2)>>1) ) * 16; + /* read 32 bit aligned */ + temp = mvFlash32Rd(pFlash, MV_ALIGN_DOWN(offset,4)); /* aligned to 32 bit */ + /* write 16 bit sdata into 32 bit */ + temp &= temp & ~(0xffff << shiftSdata); + temp |= sdata << shiftSdata; + + /* write 32 bit */ + return mvFlash32Wr(pFlash,MV_ALIGN_DOWN(offset,4),temp); +} + +/******************************************************************************* +* mvFlash8Wr - Write 8bit (char) to flash. +* +* DESCRIPTION: +* This function writes 8bit data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* cdata - 8bit data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if one of the inputs values is illegal, +* MV_OK if write completed successfully, +* MV_FAIL otherwise (e.g. sector protected). +* +*******************************************************************************/ +MV_STATUS mvFlash8Wr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U8 cdata) +{ + MV_U32 temp, shiftCdata; + + DB(mvOsPrintf("Flash: mvFlash8Wr\n")); + /* check that the offset is aligned to 16 bit */ + if(NULL == pFlash) + return MV_BAD_PARAM; + + /* cdata shift in 32 bit aligned. i.e. */ + /* wr 0x99 to 0xf4000003 -> 0xf4000000: qqqqqq99 */ + shiftCdata = (3 - (offset & 0x3)) * 8; + /* read 32 bit aligned */ + temp = mvFlash32Rd(pFlash, MV_ALIGN_DOWN(offset,4)); /* aligned to 32 bit */ + /* write 16 bit sdata into 32 bit */ + temp &= temp & ~(0xff << shiftCdata); + temp |= cdata << shiftCdata; + /* write 32 bit */ + return mvFlash32Wr(pFlash,MV_ALIGN_DOWN(offset,4),temp); +} + +/******************************************************************************* +* mvFlashBlockUnbufWr - Write a block to flash. Unbuffered +* +* DESCRIPTION: +* This function writes a block of data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* blockSize - Size of block in bytes. +* pBlock - Pointer to data block to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* The number of bytes written to flash. +* +*******************************************************************************/ +MV_U32 mvFlashBlockUnbufWr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, + MV_U8 *pBlock) +{ + MV_U32 i, j, temp = 0; + + DB(mvOsPrintf("Flash: mvFlashBlockWr\n")); + if(NULL == pFlash) + return 0; + +#ifndef CONFIG_MARVELL + if(NULL == pBlock) + return 0; +#endif + + for(i = 0; i < blockSize; ) + { + if( ((offset + i) % 4) || ((blockSize - i) < 4) )/* unaligned to 32 bit*/ + { + DB(mvOsPrintf("Flash: mvFlashBlockWr not aligned\n")); + if(MV_OK != mvFlash8Wr(pFlash, offset + i, pBlock[i]) ) + { + DB(mvOsPrintf("Flash: mvFlashBlockWr failed in writing char\n")); + return i; + } + i++; + } + else /* aligned to 32 bit */ + { + temp = 0; + /* to make sure we don't write to un aligned address */ + for(j = 0; j < 4; j++) + { + /* [44][55][66][77] -> 0x44556677 */ + temp |= (pBlock[i+j] & FLASH_MASK_8BIT ) << (8*(3-j)) ; + } + if( MV_OK != mvFlash32Wr(pFlash, offset + i, temp)) + { + DB(mvOsPrintf("Flash: mvFlashBlockWr failed in writing word\n")); + return i; + } + i += 4; + } + } + + return i; +} + + +/******************************************************************************* +* mvFlashBlockWr - Write a block to flash. +* +* DESCRIPTION: +* This function writes a block of data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* blockSize - Size of block in bytes. +* pBlock - Pointer to data block to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* The number of bytes written to flash. +* +*******************************************************************************/ +MV_U32 mvFlashBlockWr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, + MV_U8 *pBlock) +{ + MV_U32 numOfBytesWritten = 0; + MV_U32 secNum; /* lastOffset;*/ + MV_U32 i; + MV_U32 hwBuffSize, sizeToWrite; + MV_U32 unBufWritten= 0; + MV_U8 *pTmpBlock = NULL; + + DB(mvOsPrintf("Flash: mvFlashBlockWr\n")); + if(NULL == pFlash) + return 0; + +#ifndef CONFIG_MARVELL + if(NULL == pBlock) + return 0; +#endif + + /* check if any of the dest sectors is protected */ + /*lastOffset = ((MV_U32)pBlock) + blockSize;*/ + secNum = mvFlashInWhichSec(pFlash,offset); + do + { + if( MV_TRUE == mvFlashSecLockGet(pFlash, secNum) ) + { + mvOsPrintf("Flash: ERROR mvFlashProg protected sector.\n"); + return 0; + } + + /* next sec base offset */ + i = mvFlashSecOffsGet(pFlash, secNum) + + mvFlashSecSizeGet(pFlash, secNum); + secNum++; + + } while (i < blockSize); + + hwBuffSize = flashGetHwBuffSize(pFlash); + + /* if no HW buffer support, then call unbuffer routine*/ + if (hwBuffSize == 0) + { + return mvFlashBlockUnbufWr(pFlash, offset, blockSize, + pBlock); + + } + + flashReset(pFlash); + + + /* now write unbuffered the unaligned data*/ + while (((offset % hwBuffSize) || (blockSize < hwBuffSize))&&(blockSize)) + { + DB(mvOsPrintf("if I: offset = 0x%x, blockSize= 0x%x\n", + offset,blockSize)); + + if ((blockSize < hwBuffSize)|| + ((offset + blockSize) < (offset + (2*hwBuffSize + (offset / hwBuffSize))))) + { + sizeToWrite = blockSize; + } + else sizeToWrite = hwBuffSize - (offset % hwBuffSize); + + + unBufWritten = mvFlashBlockUnbufWr(pFlash, offset, sizeToWrite, + pBlock); + + flashReset(pFlash); + + blockSize -= unBufWritten; + offset += unBufWritten; + pBlock += unBufWritten; + numOfBytesWritten += unBufWritten; + + if (unBufWritten != sizeToWrite) return numOfBytesWritten; + + + } + + if (blockSize) + { + /* now write buffered the aligned data*/ + sizeToWrite = blockSize - (blockSize % hwBuffSize); + + /* Check source addr, in case source is in the FLASH */ + /* First copy the data to a temporary container in the SDRAM */ + /* and only then copy the data from the SDRAM to the FLASH */ + if (((MV_U32)pBlock >= mvFlashBaseAddrGet(pFlash)) && + ((MV_U32)pBlock < (mvFlashBaseAddrGet(pFlash) + mvFlashSizeGet(pFlash)))) + { + /* Malloc memory */ + if (NULL == (pTmpBlock=mvOsMalloc(sizeToWrite))) + { + DB(mvOsPrintf("mvFlashBlockWr: Malloc temporary container failed\n")); + flashReset(pFlash); + return numOfBytesWritten; + } + /* Copy data to SDRAM */ + memcpy(pTmpBlock, pBlock, sizeToWrite); + /* Change source pointer to SDRAM */ + } + else + /* Source address is not in flash */ + pTmpBlock = pBlock; + + /* Write data to flash */ + if ( MV_OK != flashHwBufferProg(pFlash, offset, + sizeToWrite, pTmpBlock) ) + { + DB(mvOsPrintf("mvFlashBlockWr: flashHwBufferProg failed\n")); + flashReset(pFlash); + return numOfBytesWritten; + } + /* Free memory only if used SDRAM container */ + if (pTmpBlock != pBlock) + mvOsFree(pTmpBlock); + + flashReset(pFlash); + + blockSize -= sizeToWrite; + offset += sizeToWrite; + pBlock += sizeToWrite; + numOfBytesWritten += sizeToWrite; + + } + + + /* now write unbuffered the rest*/ + if (blockSize) + { + unBufWritten = mvFlashBlockUnbufWr(pFlash, offset, blockSize, + pBlock); + + flashReset(pFlash); + + blockSize -= unBufWritten; + offset += unBufWritten; + pBlock += unBufWritten; + numOfBytesWritten += unBufWritten; + + } + + + return numOfBytesWritten; +} + + +/* read */ +/******************************************************************************* +* mvFlash32Rd - Read a 32bit (word) from flash. +* +* DESCRIPTION: +* This function reads 32bit (word) data from a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit data read from flash. +* +*******************************************************************************/ +MV_U32 mvFlash32Rd(MV_FLASH_INFO *pFlash, MV_U32 offset) +{ + MV_U32 val; + + DB(mvOsPrintf("Flash: mvFlashWordRd %x\n",offset)); + if(NULL == pFlash) + return 0; + + val = MV_FL_32_DATA_READ(offset + mvFlashBaseAddrGet(pFlash)); + + return MV_32BIT_BE(val); +} + +/******************************************************************************* +* mvFlash16Rd - Read a 16bit (short) from flash. +* +* DESCRIPTION: +* This function reads 16bit (short) data from a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit data read from flash. +* +*******************************************************************************/ +MV_U16 mvFlash16Rd (MV_FLASH_INFO *pFlash,MV_U32 offset) +{ + MV_U32 val; + + if(NULL == pFlash) + return 0; + + val = MV_FL_16_DATA_READ(offset + mvFlashBaseAddrGet(pFlash)); + + return MV_16BIT_BE(val); +} + +/******************************************************************************* +* mvFlash8Rd - Read a 8bit (char) from flash. +* +* DESCRIPTION: +* This function reads 8bit (char) data from a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* +* OUTPUT: +* None. +* +* RETURN: +* 8bit data read from flash. +* 0 if pflash is NULL. +* +*******************************************************************************/ +MV_U8 mvFlash8Rd (MV_FLASH_INFO *pFlash, MV_U32 offset) +{ + if(NULL == pFlash) + return 0; + + return MV_FL_8_DATA_READ(offset + mvFlashBaseAddrGet(pFlash)); +} + +/******************************************************************************* +* mvFlashBlockRd - Read a block of data from flash. +* +* DESCRIPTION: +* This function reads a block of data from given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* blockSize - Size of block in bytes. +* +* OUTPUT: +* pBlock - Pointer to data block to be read from flash. +* +* RETURN: +* The number of bytes read from flash. +* +*******************************************************************************/ +MV_U32 mvFlashBlockRd (MV_FLASH_INFO *pFlash, MV_U32 offset,MV_U32 blockSize, + MV_U8 *pBlock) +{ + MV_U32 i, j, temp; + + if((NULL == pFlash) || (NULL == pBlock)) + return 0; + + for(i = 0; i < blockSize; ) + { + if( ((offset + i) % 4) || ((blockSize - i) < 4) )/* unaligned to 32 bit*/ + { + DB(mvOsPrintf("Flash: mvFlashBlockRd not aligned\n")); + pBlock[i] = mvFlash8Rd(pFlash, offset + i); + i++; + } + else /* aligned to 32 bit */ + { + temp = mvFlash32Rd(pFlash, offset + i); + /* to make sure we don't write to un aligned address */ + for(j = 0; j < 4; j++) + { + /* 0x44556677 -> [44][55][66][77] */ + pBlock[i+j] = (MV_U8)((temp >> (8*(3-j))) & FLASH_MASK_8BIT); + } + i += 4; + } + } + + return i; +} + +/******************************************************************************* +* mvFlashSecLockSet - Lock/Unlock a Sector in the flash for Writing. +* +* DESCRIPTION: +* Lock/Unlock a Sector in the flash for Writing. +* +* INPUT: +* pFlash - Flash identifier structure. +* secNum - Sector Number. +* enable - MV_TRUE for Lock MV_FALSE for un-lock. +* +* OUTPUT: +* None +* +* RETURN: +* MV_BAD_PARAM if pFlash is NULL, +* MV_OK if operation completed successfully, +* MV_FAIL otherwise +* +*******************************************************************************/ +MV_STATUS mvFlashSecLockSet(MV_FLASH_INFO *pFlash, MV_U32 secNum, MV_BOOL enable) +{ + MV_U32 status = MV_FAIL; + + DB(mvOsPrintf("Flash: mvFlashSecLockSet\n")); + if( (NULL == pFlash) || (secNum > mvFlashNumOfSecsGet(pFlash)) ) + return MV_BAD_PARAM; + + /* check if sector is locked */ + if(enable == mvFlashSecLockGet(pFlash, secNum) ) + { + DB(mvOsPrintf("already un/locked\n")); + return MV_OK; + } + + /* SW Lock */ + if( mvFlashIsHwLock(pFlash) == MV_FALSE) + { + pFlash->sector[secNum].protect = enable; + status = MV_OK; + } + else /* HW Lock */ + { + switch(mvFlashVenIdGet(pFlash)) + { + case INTEL_MANUF: /* INTEL / MT */ + status = intelFlashSecLock(pFlash,secNum,enable); + break; + default: + mvOsPrintf("%s ERROR: No support for flash vendor id=0x%x\n", + __FUNCTION__, mvFlashVenIdGet(pFlash)); + return MV_FAIL; + } + /* if completed successfully, updated SW structure */ + if( MV_OK == status ) + { + pFlash->sector[secNum].protect = enable; + } + + /* reset the flash */ + flashReset(pFlash); + } + + return status; +} + +/********************** statics APIs *******************************************/ +/******************************************************************************* +* flashReset - Reset the Flash. +* DESCRIPTION: +* Reset the flash (Inset it into read mode). +* +* INPUT: +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* MV_FAIL - if flash Vendor isn't supported MV_OK otherwise. +* +*******************************************************************************/ +static MV_STATUS flashReset(MV_FLASH_INFO *pFlash) +{ + switch(mvFlashVenIdGet(pFlash)) + { + case INTEL_MANUF: /* INTEL/MT */ + intelFlashReset(pFlash); + break; + case AMD_MANUF: + case STM_MANUF: + case SST_MANUF: + amdFlashReset(pFlash); + break; + default: + mvOsPrintf("Flash: ERROR mvFlashErase unsupported flash vendor\n"); + return MV_FAIL; + } + return MV_OK; +} + +/******************************************************************************* +* flashStructGet - return flash structure information. +* +* DESCRIPTION: +* This function goes over the supported flash list and look for a flash +* with manufactor code = manu and id code = id if found it return the flash +* structure. +* +* INPUT: +* manu - Flash Manufactor. +* id - Flash ID. +* +* OUTPUT: +* pFlash - Flash structure. +* +* RETURN: +* MV_BAD_PARAM if pFlash is NULL, +* MV_OK if manufactor and id were found, +* MV_FAIL otherwise +* +*******************************************************************************/ +static MV_STATUS flashStructGet(MV_FLASH_INFO *pFlash, MV_U32 manu, MV_U32 id) +{ + MV_U32 i= 0; + + if(NULL == pFlash) + return MV_BAD_PARAM; + + DB(mvOsPrintf("Flash: flashStructGet manu 0x%x id 0x%x \n",manu,id)); + /* while its not the last supported flash */ + while((supFlashAry[i].flashVen != LAST_FLASH) || + (supFlashAry[i].flashId != LAST_FLASH)) + { + /* if supported flash manufactor and Id equal to manu and id break */ + if( (flashDataExt(pFlash, supFlashAry[i].flashVen) == manu) && + (flashDataExt(pFlash, supFlashAry[i].flashId) == id) ) + { + DB(mvOsPrintf("Flash: flashStructGet flash is supported.\n")); + pFlash->flashSpec = supFlashAry[i]; + return MV_OK; + } + i++; + } + + /* manu and id are not supported! */ + DB(mvOsPrintf("Flash: flashStructGet flash is not supported.\n")); + return MV_FAIL; +} + + +/******************************************************************************* +* flashSecsInit - Init the flash sector array in pFlash. +* +* DESCRIPTION: +* Init the sector array based on the sector type. +* +* INPUT: +* +* OUTPUT: +* pFlash - Flash sectors information. +* +* RETURN: +* MV_BAD_PARAM if pFlash or frag sector struct(if needed) are NULL, +* MV_OK otherwise +* +*******************************************************************************/ +static MV_STATUS flashSecsInit(MV_FLASH_INFO *pFlash) +{ + MV_U32 i, temp, base = 0; + MV_U32 restSecSize, initSize = 0; + MV_U32 *pSecFrag, numSecFrag, firstSec, lastSec , flashDevNum; + + if(NULL == pFlash) + return MV_BAD_PARAM; + + /* first Init the bottom or top sectors */ + if( mvFlashSecTypeGet(pFlash) != REGULAR ) /* BOTTOM or TOP */ + { + /* init sectors fragments parameters */ + numSecFrag = pFlash->flashSpec.secFragNum; + pSecFrag = pFlash->flashSpec.pSecSizeFragList; + if(NULL == pSecFrag) + { + mvOsPrintf("Flash: flashSecsInit missing frag sector list.\n"); + return MV_BAD_PARAM; + } + + /* In case we got more then one flash in parallel then each */ + /* fragment size will be "duplicated" */ + flashDevNum = mvFlashNumOfDevGet(pFlash); + + /* caculate the size of each sector in the rest of the flash sector */ + temp = 0; + for(i = 0; i < numSecFrag; i++) + { + temp += pSecFrag[i] * flashDevNum; + } + restSecSize = (mvFlashSizeGet(pFlash) - temp) / + (mvFlashNumOfSecsGet(pFlash) - numSecFrag); + + + if(mvFlashSecTypeGet(pFlash) == TOP) /* TOP */ + { + /* if TOP sec type the the last sector is fragmented */ + DB(mvOsPrintf("FLASH: initFlashSecs TOP Sector Type \n")); + base = mvFlashSizeGet(pFlash) - restSecSize; + temp = mvFlashNumOfSecsGet(pFlash) - numSecFrag; + + for(i = 0; i < numSecFrag; i++) + { + pFlash->sector[temp + i].baseOffs = base; + pFlash->sector[temp + i].size = + pSecFrag[(numSecFrag - 1)- i] * flashDevNum; + /* Init Protect feild */ + if(pFlash->flashSpec.HwProtect == MV_FALSE) /* SW Protect */ + { + pFlash->sector[i].protect = MV_FALSE; + } + else/* HW protect */ + { + pFlash->sector[i].protect=flashSecLockGet(pFlash, temp + i); + } + /*increment base and size of initialized sectors */ + base += pSecFrag[(numSecFrag - 1) - i] * flashDevNum; + initSize += pSecFrag[(numSecFrag - 1) - i] * flashDevNum; + } + /* prepare for rest of sector init */ + firstSec = 0; + lastSec = mvFlashNumOfSecsGet(pFlash) - numSecFrag; + base = 0; + + } + else if(mvFlashSecTypeGet(pFlash) == BOTTOM)/* BOTTOM */ + { + /* if BOTTOM sec type the the first sector is fragmented */ + DB(mvOsPrintf("FLASH: initFlashSecs BOTTOM Sector Type \n")); + + for(i = 0; i < numSecFrag; i++) + { + pFlash->sector[i].baseOffs = base; + pFlash->sector[i].size = pSecFrag[i] * flashDevNum; + /* Init Protect feild */ + if(pFlash->flashSpec.HwProtect == MV_FALSE) /* SW Protect */ + { + pFlash->sector[i].protect = MV_FALSE; + } + else/* HW protect */ + { + pFlash->sector[i].protect = flashSecLockGet(pFlash, i); + } + /*increment base and size of initialized sectors */ + base += pSecFrag[i] * flashDevNum; + initSize += pSecFrag[i] * flashDevNum; + } + /* prepare for rest of sector init */ + firstSec = numSecFrag; + lastSec = mvFlashNumOfSecsGet(pFlash); + } + else /* unknown Type */ + { + mvOsPrintf("FLASH: initFlashSecs Sector Type %d is unsupported\n.", + pFlash->flashSpec.secType); + return MV_BAD_PARAM; + } + + } + else /* REGULAR */ + { + DB(mvOsPrintf("FLASH: initFlashSecs REGULAR Sector Type \n")); + restSecSize = mvFlashSizeGet(pFlash) / mvFlashNumOfSecsGet(pFlash); + firstSec = 0; + lastSec = mvFlashNumOfSecsGet(pFlash); + } + + /* init the rest of the sectors */ + DB(mvOsPrintf("Flash: flashSecsInit main sector loop %d - %d \n", + firstSec,lastSec)); + for(i = firstSec; i < lastSec; i++) + { + pFlash->sector[i].baseOffs = base; + pFlash->sector[i].size = restSecSize; + /* Init Protect feild */ + if(pFlash->flashSpec.HwProtect == MV_FALSE) /* SW Protect */ + { + pFlash->sector[i].protect = MV_FALSE; + } + else/* HW protect */ + { + pFlash->sector[i].protect = flashSecLockGet(pFlash, i); + } + /*increment base */ + base += restSecSize; + } + + return MV_OK; +} + +/******************************************************************************* +* flashSecLockGet - Return a sector Lock Bit status. +* +* DESCRIPTION: +* Return a sector Lock Bit status. +* +* +* INPUT: +* pFlash - Flash structure. +* secNum - Sector Number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if lock is set +* MV_FALSE if lock isn't set +* +*******************************************************************************/ +static MV_BOOL flashSecLockGet(MV_FLASH_INFO *pFlash, MV_U32 secNum) +{ + MV_U32 status; + + /* check if sector is locked */ + if( ( NULL == pFlash) || (secNum >= mvFlashNumOfSecsGet(pFlash)) ) + return MV_BAD_PARAM; + + switch(mvFlashVenIdGet(pFlash)) + { + case INTEL_MANUF: /* INTEL / MT */ + status = intelFlashSecLockGet(pFlash,secNum); + break; + default: + mvOsPrintf("Flash: ERROR flashSecLockGet unsupported vendor\n"); + return MV_FAIL; + } + /* reset the flash */ + flashReset(pFlash); + + return status; + +} + +/******************************************************************************* +* mvFlashProg - Prog busWidth Bits into the address offest in the flash. +* +* DESCRIPTION: +* This function writes busWidth data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* data - 32bit data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if one of the inputs values is illegal, +* MV_OK if program completed successfully, +* MV_FAIL otherwise (e.g. sector protected). +* +*******************************************************************************/ +static MV_STATUS mvFlashProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data) +{ + MV_U32 status; + + + switch(mvFlashVenIdGet(pFlash)) + { + case INTEL_MANUF: /* INTEL / MT */ + status = intelFlashProg(pFlash,offset,data); + break; + case AMD_MANUF: + case STM_MANUF: + case SST_MANUF: + status = amdFlashProg(pFlash,offset,data); + break; + default: + mvOsPrintf("Flash: ERROR mvFlashProg unsupported flash vendor\n"); + return MV_FAIL; + } + + return status; + +} + + +/******************************************************************************* +* flashHwBufferProg - Prog flash via hw flash hw buffer +* +* DESCRIPTION: +* This function writes to a given flash offset using flash hw buffer. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* data - 32bit data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if one of the inputs values is illegal, +* MV_OK if program completed successfully, +* MV_FAIL otherwise (e.g. sector protected). +* +*******************************************************************************/ +static MV_STATUS flashHwBufferProg(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 byteCount, + MV_U8 *pData) +{ + MV_U32 status; + + + switch(mvFlashVenIdGet(pFlash)) + { + case INTEL_MANUF: /* INTEL / MT */ + status = intelFlashHwBufferProg(pFlash, offset, byteCount, pData); + break; + default: + mvOsPrintf("Flash: ERROR flashHwBufferProg unsupported flash vendor\n"); + return MV_FAIL; + } + + return status; +} + + +/******************************************************************************* +* flashGetHwBuffSize - get supported flash write buffer size. +* DESCRIPTION: +* Returns supported flash write buffer size. +* +* INPUT: +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* MV_U32 - supported buffer size +* +*******************************************************************************/ +static MV_U32 flashGetHwBuffSize(MV_FLASH_INFO *pFlash) +{ + + switch(mvFlashVenIdGet(pFlash)) + { + case INTEL_MANUF: /* INTEL / MT */ + return intelFlashGetHwBuffSize(pFlash); + break; + default: + return 0; + } +} diff --git a/board/mv_feroceon/mv_hal/norflash/mvFlash.h b/board/mv_feroceon/mv_hal/norflash/mvFlash.h new file mode 100644 index 0000000..c09768f --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvFlash.h @@ -0,0 +1,96 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvFlashH +#define __INCmvFlashH + +#include "mvFlashCom.h" +#include "mvIntelFlash.h" +#include "mvAmdFlash.h" + +/** APIs **/ +/* Init */ +MV_U32 mvFlashInit (MV_FLASH_INFO *pFlash); +/* Erase */ +MV_STATUS mvFlashErase (MV_FLASH_INFO *pFlash); +MV_BOOL flashIsSecErased(MV_FLASH_INFO *pFlash, MV_U32 secNum); +MV_STATUS mvFlashSecErase (MV_FLASH_INFO *pFlash, MV_U32 sectorNum); +/* write */ +MV_STATUS mvFlash32Wr (MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 data); +MV_STATUS mvFlash16Wr (MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U16 sdata); +MV_STATUS mvFlash8Wr (MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U8 cdata); +MV_U32 mvFlashBlockWr (MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock); +MV_U32 mvFlashBlockUnbufWr(MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock); +/* read */ +MV_U32 mvFlash32Rd (MV_FLASH_INFO *pFlash, MV_U32 offset); +MV_U16 mvFlash16Rd (MV_FLASH_INFO *pFlash, MV_U32 offset); +MV_U8 mvFlash8Rd (MV_FLASH_INFO *pFlash, MV_U32 offset); +MV_U32 mvFlashBlockRd (MV_FLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, + MV_U8 *pBlock); +/* protection */ +MV_STATUS mvFlashSecLockSet(MV_FLASH_INFO *pFlash, MV_U32 secNum, + MV_BOOL enable); + + +#endif /* __INCmvFlashH */ diff --git a/board/mv_feroceon/mv_hal/norflash/mvFlashCom.c b/board/mv_feroceon/mv_hal/norflash/mvFlashCom.c new file mode 100644 index 0000000..f1142f7 --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvFlashCom.c @@ -0,0 +1,650 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvFlashCom.h" +#include "mvIntelFlash.h" +#include "mvAmdFlash.h" + +#undef MV_DEBUG + +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + + +static MV_VOID sizePrint (MV_U32 size, MV_U8 *s); + +/******************************************************************************* +* mvFlashInWhichSec - Return which Sector rap the offset address. +* +* DESCRIPTION: +* +* INPUT: +* pFlash - Flash identifier structure. +* offset - offset address. +* +* OUTPUT: +* None +* +* RETURN: +* MV_U32 - The Sector Number that the offset sits in. +* BAD_SEC_NUM if not found. +* +*******************************************************************************/ +MV_U32 mvFlashInWhichSec(MV_FLASH_INFO *pFlash, MV_U32 offset) +{ + MV_U32 secNum; + if(NULL == pFlash) + return 0; + + for( secNum = 0; secNum < mvFlashNumOfSecsGet(pFlash); secNum++){ + if((offset >= mvFlashSecOffsGet(pFlash, secNum)) && + (offset < mvFlashSecOffsGet(pFlash, secNum) + + mvFlashSecSizeGet(pFlash, secNum)) ) + { + return secNum; + } + } + /* return illegal sector Number */ + return FLASH_BAD_SEC_NUM; +} + + +/**************************************************/ +/* get information from the MV_FLASH_INFO struct */ +/**************************************************/ +/* get the Number of Device which sits in parallel on the bus */ +MV_U32 mvFlashNumOfDevGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + if(mvFlashBusWidthGet(pFlash) >= mvFlashDevWidthGet(pFlash)) + return mvFlashBusWidthGet(pFlash) / mvFlashDevWidthGet(pFlash); + return 1; +} +/* get the Flash Lock type HW/SW */ +MV_BOOL mvFlashIsHwLock(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return MV_FALSE; + + return pFlash->flashSpec.HwProtect; +} +/* get the lock status of a sector in the flash */ +MV_BOOL mvFlashSecLockGet(MV_FLASH_INFO *pFlash, MV_U32 secNum) +{ + if((NULL == pFlash)|| (secNum > mvFlashNumOfSecsGet(pFlash)) ) + return MV_FALSE; + + return pFlash->sector[secNum].protect; +} +/* get the size of a sector in the flash */ +MV_U32 mvFlashSecSizeGet(MV_FLASH_INFO *pFlash, MV_U32 secNum) +{ + if((NULL == pFlash) || (secNum > mvFlashNumOfSecsGet(pFlash))) + return 0; + + return pFlash->sector[secNum].size; +} +/* get the num of sectors in the flash */ +MV_U32 mvFlashNumOfSecsGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->flashSpec.sectorNum; +} +/* get the flash size */ +MV_U32 mvFlashSizeGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->flashSpec.size * mvFlashNumOfDevGet(pFlash); +} +/* get the sector offset */ +MV_U32 mvFlashSecOffsGet(MV_FLASH_INFO *pFlash, MV_U32 secNum) +{ + if((NULL == pFlash)|| (secNum > mvFlashNumOfSecsGet(pFlash))) + return 0; + + return pFlash->sector[secNum].baseOffs; +} +/* get the sector types TOP/BOT/REG */ +FLASH_SEC_TYPE mvFlashSecTypeGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->flashSpec.secType; +} +/* get the flash Vendor ID */ +MV_U32 mvFlashVenIdGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->flashSpec.flashVen; +} +/* get the flash device id */ +MV_U32 mvFlashDevIdGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->flashSpec.flashId; +} +/* get the flash base address */ +MV_U32 mvFlashBaseAddrGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->baseAddr; +} +/* get the flash bus width */ +MV_U32 mvFlashBusWidthGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->busWidth; +} +/* get the flash device width */ +MV_U32 mvFlashDevWidthGet(MV_FLASH_INFO *pFlash) +{ + if(NULL == pFlash) + return 0; + + return pFlash->devWidth; +} + + +/******************************************************************************* +* flashDataExt - Extend Data. +* DESCRIPTION: +* Should be used only for FLASH CFI command sequence. +* +* Prepare the Data according to the Flash Width and Bus Width. +* If flash width = 2 and bus width = 1 data = 0x55 -> data = 0x55 +* If flash width = 2 and bus width = 4 data = 0x55 -> data = 0x550055 +* If flash width = 1 and bus width = 4 data = 0x55 -> data = 0x55555555 +* +* INPUT: +* data - Data to be expended. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* MV_U32 - Data after extension. +* OxFFFFFFFF if pFlash is Null +* +*******************************************************************************/ +MV_U32 flashDataExt( MV_FLASH_INFO *pFlash, MV_U32 data) +{ + MV_U32 i; + if(NULL == pFlash) + return 0xFFFFFFFF; + + for(i = 0; i < pFlash->busWidth ; i+= pFlash->devWidth) + { + data |= data << 8*i; + } + return data; +} +/****************************************************************************** +* flashAddrExt - Extend Addr. +* DESCRIPTION: +* Should be used only for FLASH CFI command sequence. +* +* Prepare the Addr according to the Flash width and the bus width, +* and add the sector offset. +* If flash width = 2 and bus width = 1 then it means we are using 16 Bit +* flash in 8 Bit mode, we should make sure that we shift the addr in 1 bit +* since in 16 Bit flash A0 isn't connected. and A1 of the MV dev address will +* go to A1 of the Flash. +* If flash width = 2 and bus width = 4 then it means we are using 2 16 Bit +* flash, (for the 16 Bit flash A0 isn't connected) and since when we refer to +* address 0x4 we actually want to refer to 0x2 of each device, then we will +* connect A2 of the MV Dev addres to A1 of the flash. +* +* INPUT: +* addr - Addr to be expended. +* pFlash - flash information. +* secNum - Sector Number. +* +* OUTPUT: +* None +* +* RETURN: +* MV_U32 - Data after extension. +* 0 if pFlash is Null. +* +*******************************************************************************/ +MV_U32 flashAddrExt(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 secNum ) +{ + MV_U32 shift; + if(NULL == pFlash) + return 0; + + shift = (pFlash->busWidth > pFlash->devWidth ) ? + pFlash->busWidth : pFlash->devWidth; + addr = addr * shift; + + /* Add flash sector Offset.*/ + addr += (mvFlashSecOffsGet(pFlash,secNum) + mvFlashBaseAddrGet(pFlash)); + + return addr; +} + +/******************************************************************************* +* flashCmdSet - Write converted data to the flash converted address+sector base. +* +* DESCRIPTION: +* Convert data based on the bus width and the flash device width +* and write it to secoffset + converted address. +* Should be used only for FLASH command sequence. +* +* INPUT: +* addr - Address offset. +* secNum - In which sector the address is sitting. +* data - Data to be written. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID flashCmdSet(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 secNum, + MV_U32 data) +{ + if(NULL == pFlash) + return; + + /* prepare the Data according to the Flash Width and Bus Width. */ + data = flashDataExt(pFlash, data); + addr = flashAddrExt(pFlash, addr, secNum); + + flashBusWidthWr(pFlash,addr,data); + + return; +} + +/******************************************************************************* +* flashBusWidthRd - read BusWidth Bits from address. +* +* DESCRIPTION: +* read BusWidth Bits from address. Note that access to Flash registers +* is always in LE mode as the Flash registers are in LE mode. +* +* INPUT: +* addr - Address offset. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* MV_U32 - contain the Bus Width Bits read from the address. +* +*******************************************************************************/ +MV_U32 flashBusWidthRd(MV_FLASH_INFO *pFlash, MV_U32 addr) +{ + MV_U32 val; + + switch(pFlash->busWidth) + { + case 1: + val = (MV_U32)MV_FL_8_READ(addr); + break; + case 2: + val = (MV_U32)MV_FL_16_READ(addr); + break; + case 4: + val = MV_FL_32_READ(addr); + break; + default: + mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", + __FUNCTION__, pFlash->busWidth); + return 0; + } + /* mvOsPrintf("Addr = 0x%x, val = 0x%x, width %d\n", addr, val, pFlash->busWidth); */ + + return val; +} + +/******************************************************************************* +* flashBusWidthWr - write BusWidth Bits from address. +* +* DESCRIPTION: +* write BusWidth Bits to address. Note that access to Flash registers +* is always in LE mode as the Flash registers are in LE mode. +* +* INPUT: +* addr - Address offset. +* data - data to be written. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID flashBusWidthWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data) +{ + /* mvOsPrintf("Addr = 0x%x, data = 0x%x, width %d\n", addr, data, pFlash->busWidth); */ + switch(pFlash->busWidth) + { + case 1: + MV_FL_8_WRITE(addr,(MV_U8)data); + break; + case 2: + MV_FL_16_WRITE(addr,(MV_U16)data); + break; + case 4: + MV_FL_32_WRITE(addr,data); + break; + default: + mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", + __FUNCTION__, pFlash->busWidth); + return; + } + + return ; +} + +/******************************************************************************* +* flashBusWidthDataWr - write BusWidth Bits of data from address. +* +* DESCRIPTION: +* This function is used to perform data write to Flash, not like +* flashBusWidthWr which is used for commands. +* +* INPUT: +* addr - Address offset. +* data - data to be written. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID flashBusWidthDataWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data) +{ + /*mvOsPrintf("Addr = 0x%x, data = 0x%x, width %d\n", addr, data, pFlash->busWidth);*/ + switch(pFlash->busWidth) + { + case 1: + MV_FL_8_DATA_WRITE(addr,(MV_U8)data); + break; + case 2: + MV_FL_16_DATA_WRITE(addr,(MV_U16)data); + break; + case 4: + MV_FL_32_DATA_WRITE(addr,data); + break; + default: + mvOsPrintf("%s ERROR: Bus Width %d Bytes isn't supported.\n", + __FUNCTION__, pFlash->busWidth); + return; + } + + return ; +} + + +/******************************************************************************* +* flashPrint - Print flash information structure. +* +* DESCRIPTION: +* Prints all the feilds in the flash info structure. +* +* INPUT: +* pFlash - Flash information. +* +* OUTPUT: +* None +* +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID flashPrint(MV_FLASH_INFO *pFlash) +{ + MV_U32 i; + + + if ((NULL == pFlash) || (mvFlashVenIdGet(pFlash) == 0)) + { + mvOsOutput ("missing or unknown FLASH type\n"); + return; + } + + switch (mvFlashVenIdGet(pFlash)) { + case STM_MANUF: + mvOsOutput ("STM "); + break; + case AMD_MANUF: + mvOsOutput ("AMD "); + break; + case FUJ_MANUF: + mvOsOutput ("FUJITSU "); + break; + case INTEL_MANUF: + mvOsOutput ("INTEL "); + break; + case SST_MANUF: + mvOsOutput ("SST "); + break; + case MX_MANUF: + mvOsOutput ("MX "); + break; + default: + mvOsOutput ("Unknown Vendor 0x%x",mvFlashVenIdGet(pFlash)); + break; + } + + switch (mvFlashDevIdGet(pFlash)) { + case AMD_FID_LV040B: + mvOsOutput ("AM29LV040B (4 Mbit, bottom boot sect)"); + break; + case AMD_FID_LV400B: + mvOsOutput ("AM29LV400B (4 Mbit, bottom boot sect)"); + break; + case AMD_FID_LV400T: + mvOsOutput ("AM29LV400T (4 Mbit, top boot sector)"); + break; + case AMD_FID_LV800B: + mvOsOutput ("AM29LV800B (8 Mbit, bottom boot sect)"); + break; + case AMD_FID_LV800T: + mvOsOutput ("AM29LV800T (8 Mbit, top boot sector)"); + break; + case AMD_FID_LV160B: + mvOsOutput ("AM29LV160B (16 Mbit, bottom boot sect)"); + break; + case AMD_FID_LV160T: + mvOsOutput ("AM29LV160T (16 Mbit, top boot sector)"); + break; + case AMD_FID_LV320B: + mvOsOutput ("AM29LV320B (32 Mbit, bottom boot sect)"); + break; + case AMD_FID_LV320T: + mvOsOutput ("AM29LV320T (32 Mbit, top boot sector)"); + break; + case AMD_S29GL128N: + mvOsOutput ("SPANSION S29GL128N (128 Mbit) - AMD MirrorBit-compat"); + break; + case STM_FID_29W040B: + mvOsOutput ("M29W040B (4Mbit = 512K x 8) "); + break; + case INTEL_FID_28F320J3A: + mvOsOutput ("28F320J3A (32 Mbit)"); + break; + case INTEL_FID_28F640J3A: + mvOsOutput ("28F640J3A (64 Mbit)"); + break; + case INTEL_FID_28F128J3A: + mvOsOutput ("28F128J3A (128 Mbit)"); + break; + case INTEL_FID_28F128P30T: + mvOsOutput ("28F128P30 TOP (128 Mbit)"); + break; + case INTEL_FID_28F128P30B: + mvOsOutput ("28F128P30 BOTTOM (128 Mbit)"); + break; + case INTEL_FID_28F256P30T: + mvOsOutput ("28F256P30 TOP (256 Mbit)"); + break; +#if defined (DB_88F1281) + case INTEL_FID_28F256P30B: + mvOsOutput ("28F256P30 BOTTOM (128 Mbit)"); + break; +#else + case INTEL_FID_28F256P30B: + mvOsOutput ("28F256P30 BOTTOM (256 Mbit)"); + break; +#endif + case SST_39VF_020: + mvOsOutput ("SST39VF020 (2 Mbit)"); + break; + default: + mvOsOutput ("Unknown Chip Type id 0x%x",mvFlashDevIdGet(pFlash)); + break; + } + if(mvFlashNumOfDevGet(pFlash) > 1) + mvOsOutput(" X %d",mvFlashNumOfDevGet(pFlash)); + + mvOsOutput("\nSize: "); + sizePrint(mvFlashSizeGet(pFlash),(MV_U8*)" in "); + mvOsOutput("%d Sectors\n",mvFlashNumOfSecsGet(pFlash)); + mvOsOutput("Bus Width: %dbit, device Width: %dbit, type: ", + (8 * mvFlashBusWidthGet(pFlash)), (8 * mvFlashDevWidthGet(pFlash))); + + switch (mvFlashSecTypeGet(pFlash)) { + case TOP: mvOsOutput ("TOP"); break; + case BOTTOM: mvOsOutput ("BOTTOM"); break; + case REGULAR: mvOsOutput ("REGULAR"); break; + default: mvOsOutput ("Unknown Type"); break; + } + mvOsOutput(".\n"); + + + mvOsOutput (" Sector Start Addresses:"); + for (i=0; i= 10) { + m -= 10; + n += 1; + } + + mvOsOutput ("%2d", n); + if (m) { + mvOsOutput (".%d", m); + } + mvOsOutput (" %cB%s", c, s); +} + diff --git a/board/mv_feroceon/mv_hal/norflash/mvFlashCom.h b/board/mv_feroceon/mv_hal/norflash/mvFlashCom.h new file mode 100644 index 0000000..e6b7de7 --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvFlashCom.h @@ -0,0 +1,164 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvFlashComH +#define __INCmvFlashComH + +#include "mvCtrlEnvLib.h" + + +/* Vendor Ids */ +#define AMD_MANUF 0x01 /* AMD manuf. ID in D23..D16, D7..D0 */ +#define FUJ_MANUF 0x04 /* FUJITSU manuf. ID in D23..D16, D7..D0 */ +#define ATM_MANUF 0x1F /* ATMEL */ +#define STM_MANUF 0x20 /* STM (Thomson) manuf. ID in D23.. -"- */ +#define SST_MANUF 0xBF /* SST manuf. ID in D23..D16, D7..D0 */ +#define MT_MANUF 0x89 /* MT manuf. ID in D23..D16, D7..D0 */ +#define INTEL_MANUF 0x89 /* INTEL manuf. ID in D23..D16, D7..D0 */ +#define INTEL_ALT_MANUF 0xB0 /* alternate INTEL namufacturer ID */ +#define MX_MANUF 0xC2 /* MXIC manuf. ID in D23..D16, D7..D0 */ +#define TOSH_MANUF 0x98 /* TOSHIBA manuf. ID in D23..D16, D7..D0 */ + + +#define MAX_SECTOR_NUM 300 + +#define FLASH_BAD_SEC_NUM 0xFFFFFFFF +#define FLASH_WR_ERASED 0xFFFFFFFF +#define FLASH_MASK_16BIT 0xFFFF +#define FLASH_MASK_8BIT 0xFF +/* typedefs */ + +/* This structure describes a flash sector */ +typedef struct _mvFlashSector +{ + MV_U32 baseOffs; /* Sector base offset related to flash base. */ + MV_U32 size; /* sector size in bytes */ + MV_BOOL protect; /* Sector write protect indicator */ +}MV_FLASH_SECTOR; + +/* This structures describes a flash Sectors structure type */ +typedef enum flashSecType +{ + REGULAR, + BOTTOM, + TOP +}FLASH_SEC_TYPE; + +typedef struct flashStruct +{ + MV_U32 flashVen; /* AMD/Intel/... */ + MV_U32 flashId; /* Combined device & vendor ID */ + MV_U32 size; /* Total Flash size in bytes */ + MV_U32 sectorNum; /* Flash total sector number */ + FLASH_SEC_TYPE secType; /* Sector structure type */ + MV_U32 secFragNum; /* In case B/T flash then this is the Number */ + /* of Sector defined in the Frag list. */ + MV_U32 *pSecSizeFragList; /* a list of the sectors' sizes in the */ + /* B/T sector part. */ + MV_BOOL HwProtect; /* HW protection is supported */ + MV_U32 HwBuffLen; /* support for hw buffering (0 - not, */ + /* > 0 - hw buff length). */ +}FLASH_STRUCT; + +/* This struct describes a Flash device */ +typedef struct _mvFlashInfo +{ + FLASH_STRUCT flashSpec; + MV_U32 baseAddr; /* Flash base address */ + MV_FLASH_SECTOR sector[MAX_SECTOR_NUM]; /* Flash sector list */ + MV_U32 busWidth; /* Width of the Flash bus */ + MV_U32 devWidth; /* Width of single Flash device */ + +} MV_FLASH_INFO; + + + + +/* get info */ +MV_U32 mvFlashNumOfDevGet (MV_FLASH_INFO *pFlash); +MV_BOOL mvFlashIsHwLock (MV_FLASH_INFO *pFlash); +MV_BOOL mvFlashSecLockGet (MV_FLASH_INFO *pFlash, MV_U32 secNum); +MV_U32 mvFlashInWhichSec (MV_FLASH_INFO *pFlash, MV_U32 offset); +MV_U32 mvFlashSecSizeGet (MV_FLASH_INFO *pFlash, MV_U32 sectorNumber); +MV_U32 mvFlashNumOfSecsGet (MV_FLASH_INFO *pFlash); +MV_U32 mvFlashSizeGet (MV_FLASH_INFO *pFlash); +MV_U32 mvFlashSecOffsGet (MV_FLASH_INFO *pFlash, MV_U32 sectorNum); +MV_U32 mvFlashVenIdGet (MV_FLASH_INFO *pFlash); +MV_U32 mvFlashDevIdGet (MV_FLASH_INFO *pFlash); +MV_U32 mvFlashBaseAddrGet (MV_FLASH_INFO *pFlash); +MV_U32 mvFlashBusWidthGet (MV_FLASH_INFO *pFlash); +MV_U32 mvFlashDevWidthGet (MV_FLASH_INFO *pFlash); +FLASH_SEC_TYPE mvFlashSecTypeGet(MV_FLASH_INFO *pFlash); + +/* flash Utils */ +MV_U32 flashDataExt(MV_FLASH_INFO *pFlash, MV_U32 data); +MV_U32 flashAddrExt(MV_FLASH_INFO *pFlash, MV_U32 data, MV_U32 secNum); +MV_VOID flashCmdSet (MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 secNum, + MV_U32 data); +MV_VOID flashPrint (MV_FLASH_INFO *pFlash); +MV_VOID flashBusWidthWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data); +MV_VOID flashBusWidthDataWr(MV_FLASH_INFO *pFlash, MV_U32 addr, MV_U32 data); +MV_U32 flashBusWidthRd(MV_FLASH_INFO *pFlash, MV_U32 addr); + +#endif /* __INCmvFlashComH */ diff --git a/board/mv_feroceon/mv_hal/norflash/mvIntelFlash.c b/board/mv_feroceon/mv_hal/norflash/mvIntelFlash.c new file mode 100644 index 0000000..0b48bcb --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvIntelFlash.c @@ -0,0 +1,518 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvFlash.h" + +#undef MV_DEBUG + +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +static MV_STATUS intelFlashStsGet(MV_FLASH_INFO *pFlash, MV_U32 sec, + MV_BOOL enableReadCommand, MV_U32* flashStatus); +static MV_VOID intelFlashStatusClr(MV_FLASH_INFO *pFlash); + +/******************************************************************************* +* reset the flash +*******************************************************************************/ +MV_VOID intelFlashReset(MV_FLASH_INFO *pFlash) +{ + flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_RST); + return; +} + +/******************************************************************************* +* intelFlashSecErase - Erase a sector. +* +* DESCRIPTION: +* Erase a Flash sector. +* +* INPUT: +* secNum - sector Number. +* pFlash - flash information. +* +* OUTPUT: +* None +* +* RETURN: +* MV_OK if program completed successfully, +* MV_TIMEOUT if timeout reached, +* MV_FAIL otherwise. +* +*******************************************************************************/ +MV_STATUS intelFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum) +{ + MV_U32 i, status, flashStatus; + + DB(mvOsPrintf("Flash: intelFlashSecErase\n")); + + /* clear status */ + intelFlashStatusClr(pFlash); + + /* erase sequence */ + flashCmdSet(pFlash, 0, secNum, INTEL_CHIP_CMD_ERASE1); + flashCmdSet(pFlash, 0, secNum, INTEL_CHIP_CMD_ERASE2); + + /* wait for erase to complete */ + for(i = 0; i < INTEL_EARASE_MILI_TIMEOUT; i++) + { + mvOsDelay(1); + status = intelFlashStsGet(pFlash, 0, MV_TRUE, &flashStatus); + if( MV_NOT_READY != status ) + return status; + } + mvOsPrintf("Flash: ERROR intelFlashSecErase timeout \n"); + + return MV_TIMEOUT; +} + +/******************************************************************************* +* intelFlashProg - Prog busWidth Bits into the address offest in the flash. +* +* DESCRIPTION: +* This function writes busWidth data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* data - 32bit data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if program completed successfully, +* MV_TIMEOUT if timeout reached, +* MV_FAIL otherwise. +* +*******************************************************************************/ +MV_STATUS intelFlashProg(MV_FLASH_INFO *pFlash,MV_U32 offset, MV_U32 data) +{ + MV_U32 i, status, flashStatus; + + DB(mvOsPrintf("Flash: mvIntelFlashWr\n")); + + /* clear status */ + intelFlashStatusClr(pFlash); + + /* write sequence */ + flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_PROG); + flashBusWidthDataWr(pFlash, offset + mvFlashBaseAddrGet(pFlash), data); + + /* wait for write to complete */ + for(i = 0; i < INTEL_PROG_TIMEOUT; i++) + { + status = intelFlashStsGet(pFlash, 0, MV_TRUE, &flashStatus); + if( MV_NOT_READY != status ) + return status; + } + mvOsPrintf("Flash: ERROR intelFlashSecErase timeout \n"); + + return MV_TIMEOUT; +} + + +MV_U32 intelFlashGetHwBuffSize(MV_FLASH_INFO *pFlash) +{ + MV_U32 buffSize; + + buffSize = mvFlashNumOfDevGet(pFlash) * pFlash->flashSpec.HwBuffLen ; + return buffSize; +} + +/******************************************************************************* +* intelFlashBufferProg - Prog hw buff into the address offest in the flash. +* +* DESCRIPTION: +* This function writes busWidth data to a given flash offset. +* +* INPUT: +* pFlash - Flash identifier structure (flash cockie). +* offset - Offset from flash base address. +* pData - buffer (32 byte) data to be written to flash. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if program completed successfully, +* MV_BAD_PARAM illegal param +* MV_TIMEOUT if timeout reached, +* MV_FAIL otherwise. +* +*******************************************************************************/ +MV_STATUS intelFlashHwBufferProg(MV_FLASH_INFO *pFlash,MV_U32 offset, + MV_U32 byteCount, MV_U8* pData) +{ + MV_U32 i, status, flashStatus; + MV_U32 buffSize, sec, wordCount, busWidth; + MV_U32 offInBuff, absOffInFlash; + MV_U32 data, j; + + DB(mvOsPrintf("Flash: intelFlashBufferProg\n")); + + if ((buffSize = (intelFlashGetHwBuffSize(pFlash) )) == 0) + { + return MV_BAD_PARAM; + } + + if (0 != (byteCount % buffSize)) + { + return MV_BAD_PARAM; + } + + + + /* has to be aligned */ + if ((offset % buffSize) != 0) + { + return MV_BAD_PARAM; + } + +#ifndef CONFIG_MARVELL + if (pData == NULL) + { + return MV_BAD_PARAM; + } +#endif + + busWidth = mvFlashBusWidthGet(pFlash); + wordCount = (pFlash->flashSpec.HwBuffLen / mvFlashDevWidthGet(pFlash)); + absOffInFlash = mvFlashBaseAddrGet(pFlash) + offset; + offInBuff = 0; + + /* clear status */ + intelFlashStatusClr(pFlash); + + do + { + + /* Start the 'write to buffer' sequence */ + sec = mvFlashInWhichSec(pFlash,offset); + + i=0; + do + { + flashCmdSet(pFlash, 0, sec, INTEL_CHIP_CMD_WR_BUF); + + status = intelFlashStsGet(pFlash, sec, MV_FALSE, &flashStatus); + + if((i++ > INTEL_PROG_TIMEOUT)&&(status != MV_OK)) + { + DB(printf("intelFlashHwBufferProg1: Timeout:offset = 0x%x flashStatus =0x%x\n", + offset,flashStatus)); + return status; + } + + }while (status != MV_OK); + + + /* write num of words to write minus 1 */ + flashCmdSet(pFlash, 0, sec, wordCount - 1); + + for (i = 0; i < wordCount * mvFlashNumOfDevGet(pFlash); i += mvFlashNumOfDevGet(pFlash)) + { + data = 0; + switch (busWidth) + { + case 4: + for(j = 0; j < 4; j++) + { + /* [44][55][66][77] -> 0x44556677 */ + data |= (pData[offInBuff+j] & FLASH_MASK_8BIT ) << (8*(3-j)) ; + } + data = MV_32BIT_BE(data); + break; + case 2: + for(j = 0; j < 2; j++) + { + /* [44][55] -> 0x4455 */ + data |= (pData[offInBuff+j] & FLASH_MASK_8BIT ) << (8*(1-j)) ; + } + data = MV_16BIT_BE(data); + break; + case 1: + data = *(MV_U8*)(((MV_U32)pData) + offInBuff); + break; + } + flashBusWidthDataWr(pFlash, absOffInFlash, data); + + offInBuff += busWidth; + absOffInFlash += busWidth; + } + + flashCmdSet(pFlash, 0, sec, INTEL_CHIP_CMD_CONFIRM_BUF); + + /* check status */ + for(i = 0; i < INTEL_PROG_TIMEOUT; i++) + { + status = intelFlashStsGet(pFlash, sec, MV_FALSE, &flashStatus); + if ( status == MV_OK ) + break; + } + + if ( status != MV_OK ) break; + + byteCount -= buffSize; + }while(byteCount); + + + if ( status != MV_OK ) + { + + DB(printf("intelFlashHwBufferProg2: Timeout:offset = 0x%x flashStatus =0x%x\n", + offset,flashStatus)); + + return status; + } + + + return MV_OK; +} + + +/******************************************************************************* +* intelSecLockGet - Return a sector Lock Bit status. +* +* DESCRIPTION: +* Return a sector Lock Bit status. +* +* +* INPUT: +* pFlash - Flash structure. +* secNum - Sector Number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if lock is set +* MV_FALSE if lock isn't set +* +*******************************************************************************/ +MV_BOOL intelFlashSecLockGet(MV_FLASH_INFO *pFlash,MV_U32 secNum) +{ + MV_U32 status; + + DB(mvOsPrintf("Flash: intelSecLockGet sector %d\n",secNum)); + + /* clear status */ + intelFlashStatusClr(pFlash); + + /* Some Micron flashes don't use A0 address for Identifier and + Lock information, so in order to read Identifier and lock information + properly we will do the following workarround: + If our device width is 1 (x8) then if address 0 equal to address 1 + and address 2 equal to address 3 ,then we have this case (A0 is not used) + and then we will issue the address without A0 to read the Identifier and + lock information properly*/ + + /* read Query sequence */ + flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_RD_QUERY); + + if ((pFlash->devWidth == 1) && + ((flashBusWidthRd(pFlash, flashAddrExt(pFlash, 0, 0)) == + flashBusWidthRd(pFlash, flashAddrExt(pFlash, 1, 0)))&& + (flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, 0)) == + flashBusWidthRd(pFlash, flashAddrExt(pFlash, 3, 0))))) + { + status = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 4, secNum)); + + } else status = flashBusWidthRd(pFlash, flashAddrExt(pFlash, 2, secNum)); + + + if((status & flashDataExt(pFlash,INTEL_CHIP_RD_ID_LOCK)) != 0) + { + DB(mvOsPrintf("Flash: intelSecLockGet sector %d is locked \n",secNum)); + return MV_TRUE; + } + + return MV_FALSE; +} +/******************************************************************************* +* intelSecLock - Lock/Unlock a Sector in the flash for Writing. +* +* DESCRIPTION: +* Lock/Unlock a Sector in the flash for Writing. +* +* INPUT: +* pFlash - Flash identifier structure. +* secNum - Sector Number. +* enable - MV_TRUE for Lock MV_FALSE for un-lock. +* +* OUTPUT: +* None +* +* RETURN: +* MV_OK if program completed successfully, +* MV_TIMEOUT if timeout reached, +* MV_FAIL otherwise. +* +*******************************************************************************/ +MV_STATUS intelFlashSecLock(MV_FLASH_INFO *pFlash, MV_U32 secNum, MV_BOOL enable) +{ + MV_U32 status, intelLockEna, i, flashStatus; + + status = MV_ERROR; + + DB(mvOsPrintf("Flash: intelSecLock")); + + /* lock */ + if(enable == MV_TRUE) + { + DB(mvOsPrintf("Flash: intelSecLock Lock sector %d \n", secNum)); + intelLockEna = INTEL_CHIP_CMD_SET_LOCK_BLK; + } + else{ /* unlock */ + DB(mvOsPrintf("Flash: intelSecLock Unlock sector %d \n", secNum)); + intelLockEna = INTEL_CHIP_CMD_CLR_LOCK_BLK; + } + + /* clear status */ + intelFlashStatusClr(pFlash); + + /* Un/lock sequence */ + flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_LOCK); + flashCmdSet(pFlash, 0, secNum, intelLockEna); + + /* wait for write to complete */ + for(i = 0; i < INTEL_LOCK_MILI_TIMEOUT; i++) + { + mvOsDelay(1); + status = intelFlashStsGet(pFlash, 0, MV_TRUE, &flashStatus); + if(status != MV_NOT_READY) + break; + } + /* if timeout */ + if(i >= INTEL_LOCK_MILI_TIMEOUT) + { + mvOsPrintf("Flash: ERROR intelSecLock timeout \n"); + return MV_TIMEOUT; + } + /* if completed successfully */ + if( MV_OK == status ) + { + /* Unprotect one sector, which means unprotect all flash + * and reprotect the other protected sectors. + */ + if(enable == MV_FALSE) + { + for(i = 0; i < mvFlashNumOfSecsGet(pFlash); i++) + if((i != secNum) && (MV_TRUE == mvFlashSecLockGet(pFlash,i))) + if(MV_OK != intelFlashSecLock(pFlash,i,MV_TRUE)) + return MV_FAIL; + } + return MV_OK; + } + /* otherwise FAIL */ + return MV_FAIL; +} + +/******************************************************************************* +* Check the Flash Status and return: +* MV_OK if status is ready and there isn't any error. +* MV_FAIL if status is ready and there is an error. +* MV_NOT_READY if status isn't ready. +*******************************************************************************/ +static MV_STATUS intelFlashStsGet(MV_FLASH_INFO *pFlash ,MV_U32 sec, + MV_BOOL enableReadCommand, MV_U32* flashStatus) +{ + MV_U32 status; + + if ( enableReadCommand ) + flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_RD_STAT); + status = flashBusWidthRd(pFlash, pFlash->baseAddr + mvFlashSecOffsGet(pFlash,sec)); + + *flashStatus = status; + + if((status & flashDataExt(pFlash,INTEL_CHIP_STAT_RDY)) == + flashDataExt(pFlash,INTEL_CHIP_STAT_RDY)) + { + DB(mvOsPrintf("Flash: intelFlashStatusChk value is ready \n")); + if( (status & flashDataExt(pFlash,INTEL_CHIP_STAT_ERR)) != 0) + { + mvOsPrintf("Flash: intelFlashStatusChk value has ERROR %x \n", + status); + return MV_FAIL; + } + return MV_OK; + } + + DB(mvOsPrintf("Flash: intelFlashStatusChk staus is %x and should %x \n", + status,flashDataExt(pFlash,INTEL_CHIP_STAT_RDY))); + return MV_NOT_READY; +} + +/******************************************************************************* +* Clear the Flash Status. +*******************************************************************************/ +static MV_VOID intelFlashStatusClr(MV_FLASH_INFO *pFlash) +{ + flashCmdSet(pFlash, 0, 0, INTEL_CHIP_CMD_CLR_STAT); + return; +} + diff --git a/board/mv_feroceon/mv_hal/norflash/mvIntelFlash.h b/board/mv_feroceon/mv_hal/norflash/mvIntelFlash.h new file mode 100644 index 0000000..dbd413e --- /dev/null +++ b/board/mv_feroceon/mv_hal/norflash/mvIntelFlash.h @@ -0,0 +1,165 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvIntelFlashH +#define __INCmvIntelFlashH + +#include "mvFlashCom.h" + + +/* Mt Flash IDs */ +#define MT_FID_28F400_T 0x4470 /* 28F400B3 ID ( 4 M, top boot sector) */ +#define MT_FID_28F400_B 0x4471 /* 28F400B3 ID ( 4 M, bottom boot sect) */ + + +/* Intel Flash IDs */ +#define INTEL_FID_28F016S 0x66a0 /* 28F016S[VS] ID (16M = 512k x 16) */ +#define INTEL_FID_28F800B3T 0x8892 /* 8M = 512K x 16 top boot sector */ +#define INTEL_FID_28F800B3B 0x8893 /* 8M = 512K x 16 bottom boot sector */ +#define INTEL_FID_28F160B3T 0x8890 /* 16M = 1M x 16 top boot sector */ +#define INTEL_FID_28F160B3B 0x8891 /* 16M = 1M x 16 bottom boot sector */ +#define INTEL_FID_28F320B3T 0x8896 /* 32M = 2M x 16 top boot sector */ +#define INTEL_FID_28F320B3B 0x8897 /* 32M = 2M x 16 bottom boot sector */ +#define INTEL_FID_28F640B3T 0x8898 /* 64M = 4M x 16 top boot sector */ +#define INTEL_FID_28F640B3B 0x8899 /* 64M = 4M x 16 bottom boot sector */ +#define INTEL_FID_28F160F3B 0x88F4 /* 16M = 1M x 16 bottom boot sector */ + +#define INTEL_FID_28F800C3T 0x88C0 /* 8M = 512K x 16 top boot sector */ +#define INTEL_FID_28F800C3B 0x88C1 /* 8M = 512K x 16 bottom boot sector */ +#define INTEL_FID_28F160C3T 0x88C2 /* 16M = 1M x 16 top boot sector */ +#define INTEL_FID_28F160C3B 0x88C3 /* 16M = 1M x 16 bottom boot sector */ +#define INTEL_FID_28F320C3T 0x88C4 /* 32M = 2M x 16 top boot sector */ +#define INTEL_FID_28F320C3B 0x88C5 /* 32M = 2M x 16 bottom boot sector */ +#define INTEL_FID_28F640C3T 0x88CC /* 64M = 4M x 16 top boot sector */ +#define INTEL_FID_28F640C3B 0x88CD /* 64M = 4M x 16 bottom boot sector */ + +#define INTEL_FID_28F128J3 0x8918 /* 16M = 8M x 16 x 128 */ +#define INTEL_FID_28F320J5 0x0014 /* 32M = 128K x 32 */ +#define INTEL_FID_28F640J5 0x0015 /* 64M = 128K x 64 */ +#define INTEL_FID_28F320J3A 0x0016 /* 32M = 128K x 32 */ +#define INTEL_FID_28F640J3A 0x0017 /* 64M = 128K x 64 */ +#define INTEL_FID_28F128J3A 0x0018 /* 128M = 128K x 128 */ +#define INTEL_FID_28F256L18T 0x880D /* 256M = 128K x 255 + 32k x 4 */ + +#define INTEL_FID_28F160S3 0x00D0 /* 16M = 512K x 32 (64kB x 32) */ +#define INTEL_FID_28F320S3 0x00D4 /* 32M = 512K x 64 (64kB x 64) */ +#define INTEL_FID_28F128P30T 0x8818 /* 16M = 128K x 127 (32kB x 4) top boot sector */ +#define INTEL_FID_28F128P30B 0x881B /* 16M = 128K x 127 (32kB x 4) bottom boot sector */ +#define INTEL_FID_28F256P30T 0x8919 /* 32M = 128K x 255 (32kB x 4) top boot sector */ +#if defined (DB_88F1281) +#define INTEL_FID_28F256P30B 0x1C /* 16M = 64K x 255 (16kB x 4) bottom boot sector */ +#else +#define INTEL_FID_28F256P30B 0x891C /* 32M = 128K x 255 (32kB x 4) bottom boot sector */ +#endif + + +/* Intel Flash APIs timeouts*/ +#define INTEL_EARASE_MILI_TIMEOUT (8000*10) /* mili Sec */ +#define INTEL_PROG_TIMEOUT (0xA0000*10) /* number of loops */ +#define INTEL_LOCK_MILI_TIMEOUT (8000*10) /* mili Sec */ + +/* Commands */ +#define INTEL_CHIP_CMD_RST 0xFF /* reset flash */ +#define INTEL_CHIP_CMD_RD_ID 0x90 /* read the id and lock bits */ +#define INTEL_CHIP_CMD_RD_QUERY 0x98 /* read device capabilities */ +#define INTEL_CHIP_CMD_RD_STAT 0x70 /* read the status register */ +#define INTEL_CHIP_CMD_CLR_STAT 0x50 /* clear the staus register */ +#define INTEL_CHIP_CMD_WR_BUF 0xE8 /* write buffer command */ +#define INTEL_CHIP_CMD_CONFIRM_BUF 0xD0 /* write buffer command */ +#define INTEL_CHIP_CMD_PROG 0x40 /* program word command */ +#define INTEL_CHIP_CMD_ERASE1 0x20 /* 1st word for block erase */ +#define INTEL_CHIP_CMD_ERASE2 0xD0 /* 2nd word for block erase */ +#define INTEL_CHIP_CMD_ERASE_SUSP 0xB0 /* suspend block erase */ +#define INTEL_CHIP_CMD_LOCK 0x60 /* 1st word for all lock cmds */ +#define INTEL_CHIP_CMD_SET_LOCK_BLK 0x01 /* 2nd wrd set block lock bit */ +#define INTEL_CHIP_CMD_SET_LOCK_MSTR 0xF1 /* 2nd wrd set master lck bit */ +#define INTEL_CHIP_CMD_CLR_LOCK_BLK 0xD0 /* 2nd wrd clear blk lck bit */ + + + +/* status register bits */ +#define INTEL_CHIP_STAT_DPS 0x02 /* Device Protect Status */ +#define INTEL_CHIP_STAT_VPPS 0x08 /* VPP Status */ +#define INTEL_CHIP_STAT_PSLBS 0x10 /* Program+Set Lock Bit Stat */ +#define INTEL_CHIP_STAT_ECLBS 0x20 /* Erase+Clr Lock Bit Stat */ +#define INTEL_CHIP_STAT_ESS 0x40 /* Erase Suspend Status */ +#define INTEL_CHIP_STAT_RDY 0x80 /* WSM Mach Status, 1=rdy */ + +#define INTEL_CHIP_STAT_ERR (INTEL_CHIP_STAT_VPPS | INTEL_CHIP_STAT_DPS | \ + INTEL_CHIP_STAT_ECLBS | INTEL_CHIP_STAT_PSLBS) + +/* Lock Configuration */ +#define INTEL_CHIP_RD_ID_LOCK 0x01 /* Bit 0 of each byte */ + +MV_STATUS intelFlashSecErase(MV_FLASH_INFO *pFlash, MV_U32 secNum); +MV_VOID intelFlashReset(MV_FLASH_INFO *pFlash); +MV_STATUS intelFlashProg(MV_FLASH_INFO *pFlash,MV_U32 offset, MV_U32 data); +MV_BOOL intelFlashSecLockGet(MV_FLASH_INFO *pFlash,MV_U32 secNum); +MV_STATUS intelFlashSecLock(MV_FLASH_INFO *pFlash, MV_U32 secNum, + MV_BOOL enable); +MV_U32 intelFlashGetHwBuffSize(MV_FLASH_INFO *pFlash); +MV_STATUS intelFlashHwBufferProg(MV_FLASH_INFO *pFlash,MV_U32 offset, MV_U32 byteCount, + MV_U8* pData); + +#endif /* __INCmvIntelFlashH */ diff --git a/board/mv_feroceon/mv_hal/pci-if/mvPciIf.c b/board/mv_feroceon/mv_hal/pci-if/mvPciIf.c new file mode 100644 index 0000000..672d3e3 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pci-if/mvPciIf.c @@ -0,0 +1,669 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvPciIf.h" +#include "ctrlEnv/sys/mvSysPex.h" + +#if defined(MV_INCLUDE_PCI) +#include "ctrlEnv/sys/mvSysPci.h" +#endif + + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + + +/******************************************************************************* +* mvPciInit - Initialize PCI interfaces +* +* DESCRIPTION: +* +* INPUT: +* +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM +* +*******************************************************************************/ + + +MV_STATUS mvPciIfInit(MV_U32 pciIf, PCI_IF_MODE pciIfmode) +{ + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + + MV_PCI_MOD pciMod; + + if (PCI_IF_MODE_HOST == pciIfmode) + { + pciMod = MV_PCI_MOD_HOST; + } + else if (PCI_IF_MODE_DEVICE == pciIfmode) + { + pciMod = MV_PCI_MOD_DEVICE; + } + else + { + mvOsPrintf("%s: ERROR!!! Bus %d mode %d neither host nor device!\n", + __FUNCTION__, pciIf, pciIfmode); + return MV_FAIL; + } + + return mvPciInit(pciIf - MV_PCI_START_IF, pciMod); + #else + return MV_OK; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + + MV_PEX_TYPE pexType; + + if (PCI_IF_MODE_HOST == pciIfmode) + { + pexType = MV_PEX_ROOT_COMPLEX; + } + else if (PCI_IF_MODE_DEVICE == pciIfmode) + { + pexType = MV_PEX_END_POINT; + } + else + { + mvOsPrintf("%s: ERROR!!! Bus %d type %d neither root complex nor" \ + " end point\n", __FUNCTION__, pciIf, pciIfmode); + return MV_FAIL; + } + return mvPexInit(pciIf - MV_PEX_START_IF, pexType); + + #else + return MV_OK; + #endif + + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return MV_FAIL; + +} + +/* PCI configuration space read write */ + +/******************************************************************************* +* mvPciConfigRead - Read from configuration space +* +* DESCRIPTION: +* This function performs a 32 bit read from PCI configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to read from local bus segment, use +* bus number retrieved from mvPciLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pciIf - PCI interface number. +* bus - PCI segment bus number. +* dev - PCI device number. +* func - Function number. +* regOffs - Register offset. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit register data, 0xffffffff on error +* +*******************************************************************************/ +MV_U32 mvPciIfConfigRead (MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, + MV_U32 regOff) +{ + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciConfigRead(pciIf - MV_PCI_START_IF, + bus, + dev, + func, + regOff); + #else + return 0xffffffff; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexConfigRead(pciIf - MV_PEX_START_IF, + bus, + dev, + func, + regOff); + #else + return 0xffffffff; + #endif + + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return 0; + +} + +/******************************************************************************* +* mvPciConfigWrite - Write to configuration space +* +* DESCRIPTION: +* This function performs a 32 bit write to PCI configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to write to local bus segment, use +* bus number retrieved from mvPciLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pciIf - PCI interface number. +* bus - PCI segment bus number. +* dev - PCI device number. +* func - Function number. +* regOffs - Register offset. +* data - 32bit data. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciIfConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data) +{ + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciConfigWrite(pciIf - MV_PCI_START_IF, + bus, + dev, + func, + regOff, + data); + #else + return MV_OK; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexConfigWrite(pciIf - MV_PEX_START_IF, + bus, + dev, + func, + regOff, + data); + #else + return MV_OK; + #endif + + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return MV_FAIL; + +} + +/******************************************************************************* +* mvPciMasterEnable - Enable/disale PCI interface master transactions. +* +* DESCRIPTION: +* This function performs read modified write to PCI command status +* (offset 0x4) to set/reset bit 2. After this bit is set, the PCI +* master is allowed to gain ownership on the bus, otherwise it is +* incapable to do so. +* +* INPUT: +* pciIf - PCI interface number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciIfMasterEnable(MV_U32 pciIf, MV_BOOL enable) +{ + + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciMasterEnable(pciIf - MV_PCI_START_IF, + enable); + #else + return MV_OK; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexMasterEnable(pciIf - MV_PEX_START_IF, + enable); + #else + return MV_OK; + #endif + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return MV_FAIL; + +} + + +/******************************************************************************* +* mvPciSlaveEnable - Enable/disale PCI interface slave transactions. +* +* DESCRIPTION: +* This function performs read modified write to PCI command status +* (offset 0x4) to set/reset bit 0 and 1. After those bits are set, +* the PCI slave is allowed to respond to PCI IO space access (bit 0) +* and PCI memory space access (bit 1). +* +* INPUT: +* pciIf - PCI interface number. +* dev - PCI device number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciIfSlaveEnable(MV_U32 pciIf,MV_U32 bus, MV_U32 dev, MV_BOOL enable) +{ + + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciSlaveEnable(pciIf - MV_PCI_START_IF,bus,dev, + enable); + #else + return MV_OK; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexSlaveEnable(pciIf - MV_PEX_START_IF,bus,dev, + enable); + #else + return MV_OK; + #endif + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return MV_FAIL; + +} + +/******************************************************************************* +* mvPciLocalBusNumSet - Set PCI interface local bus number. +* +* DESCRIPTION: +* This function sets given PCI interface its local bus number. +* Note: In case the PCI interface is PCI-X, the information is read-only. +* +* INPUT: +* pciIf - PCI interface number. +* busNum - Bus number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_NOT_ALLOWED in case PCI interface is PCI-X. +* MV_BAD_PARAM on bad parameters , +* otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciIfLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum) +{ + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciLocalBusNumSet(pciIf - MV_PCI_START_IF, + busNum); + #else + return MV_OK; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexLocalBusNumSet(pciIf - MV_PEX_START_IF, + busNum); + #else + return MV_OK; + #endif + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return MV_FAIL; + +} + +/******************************************************************************* +* mvPciLocalBusNumGet - Get PCI interface local bus number. +* +* DESCRIPTION: +* This function gets the local bus number of a given PCI interface. +* +* INPUT: +* pciIf - PCI interface number. +* +* OUTPUT: +* None. +* +* RETURN: +* Local bus number.0xffffffff on Error +* +*******************************************************************************/ +MV_U32 mvPciIfLocalBusNumGet(MV_U32 pciIf) +{ + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciLocalBusNumGet(pciIf - MV_PCI_START_IF); + #else + return 0xFFFFFFFF; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexLocalBusNumGet(pciIf - MV_PEX_START_IF); + #else + return 0xFFFFFFFF; + #endif + + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n",__FUNCTION__, pciIf); + } + + return 0; + +} + + +/******************************************************************************* +* mvPciLocalDevNumSet - Set PCI interface local device number. +* +* DESCRIPTION: +* This function sets given PCI interface its local device number. +* Note: In case the PCI interface is PCI-X, the information is read-only. +* +* INPUT: +* pciIf - PCI interface number. +* devNum - Device number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_NOT_ALLOWED in case PCI interface is PCI-X. MV_BAD_PARAM on bad parameters , +* otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciIfLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum) +{ + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciLocalDevNumSet(pciIf - MV_PCI_START_IF, + devNum); + #else + return MV_OK; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexLocalDevNumSet(pciIf - MV_PEX_START_IF, + devNum); + #else + return MV_OK; + #endif + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return MV_FAIL; + +} + +/******************************************************************************* +* mvPciLocalDevNumGet - Get PCI interface local device number. +* +* DESCRIPTION: +* This function gets the local device number of a given PCI interface. +* +* INPUT: +* pciIf - PCI interface number. +* +* OUTPUT: +* None. +* +* RETURN: +* Local device number. 0xffffffff on Error +* +*******************************************************************************/ +MV_U32 mvPciIfLocalDevNumGet(MV_U32 pciIf) +{ + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + #if defined(MV_INCLUDE_PCI) + return mvPciLocalDevNumGet(pciIf - MV_PCI_START_IF); + #else + return 0xFFFFFFFF; + #endif + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + #if defined(MV_INCLUDE_PEX) + return mvPexLocalDevNumGet(pciIf - MV_PEX_START_IF); + #else + return 0xFFFFFFFF; + #endif + + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return 0; + +} + +/******************************************************************************* +* mvPciIfTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ + +PCI_IF_TYPE mvPciIfTypeGet(MV_U32 pciIf) +{ + + if ((pciIf >= MV_PCI_START_IF)&&(pciIf < MV_PCI_MAX_IF + MV_PCI_START_IF)) + { + return PCI_IF_TYPE_CONVEN_PCIX; + } + else if ((pciIf >= MV_PEX_START_IF) && + (pciIf < MV_PEX_MAX_IF + MV_PEX_START_IF)) + { + return PCI_IF_TYPE_PEX; + + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return 0xffffffff; + +} + +/******************************************************************************* +* mvPciIfTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ + +MV_U32 mvPciRealIfNumGet(MV_U32 pciIf) +{ + + PCI_IF_TYPE pciIfType = mvPciIfTypeGet(pciIf); + + if (PCI_IF_TYPE_CONVEN_PCIX == pciIfType) + { + return (pciIf - MV_PCI_START_IF); + } + else if (PCI_IF_TYPE_PEX == pciIfType) + { + return (pciIf - MV_PEX_START_IF); + + } + else + { + mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, pciIf); + } + + return 0xffffffff; + +} + + + diff --git a/board/mv_feroceon/mv_hal/pci-if/mvPciIf.h b/board/mv_feroceon/mv_hal/pci-if/mvPciIf.h new file mode 100644 index 0000000..9c2d160 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pci-if/mvPciIf.h @@ -0,0 +1,134 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCPCIIFH +#define __INCPCIIFH + +#include "mvSysHwConfig.h" +#include "pci-if/mvPciIfRegs.h" +#if defined(MV_INCLUDE_PEX) +#include "pex/mvPex.h" +#endif +#if defined(MV_INCLUDE_PCI) +#include "pci/mvPci.h" +#endif +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +typedef enum _mvPCIIfType +{ + PCI_IF_TYPE_CONVEN_PCIX, + PCI_IF_TYPE_PEX + +}PCI_IF_TYPE; + +typedef enum _mvPCIIfMode +{ + PCI_IF_MODE_HOST, + PCI_IF_MODE_DEVICE +}PCI_IF_MODE; + + +/* Global Functions prototypes */ + +/* mvPciIfInit - Initialize PCI interfaces*/ +MV_STATUS mvPciIfInit(MV_U32 pciIf, PCI_IF_MODE pciIfmode); + +/* mvPciIfConfigRead - Read from configuration space */ +MV_U32 mvPciIfConfigRead (MV_U32 pciIf, MV_U32 bus, MV_U32 dev, + MV_U32 func,MV_U32 regOff); + +/* mvPciIfConfigWrite - Write to configuration space */ +MV_STATUS mvPciIfConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data); + +/* mvPciIfMasterEnable - Enable/disale PCI interface master transactions.*/ +MV_STATUS mvPciIfMasterEnable(MV_U32 pciIf, MV_BOOL enable); + +/* mvPciIfSlaveEnable - Enable/disale PCI interface slave transactions.*/ +MV_STATUS mvPciIfSlaveEnable(MV_U32 pciIf,MV_U32 bus, MV_U32 dev, + MV_BOOL enable); + +/* mvPciIfLocalBusNumSet - Set PCI interface local bus number.*/ +MV_STATUS mvPciIfLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum); + +/* mvPciIfLocalBusNumGet - Get PCI interface local bus number.*/ +MV_U32 mvPciIfLocalBusNumGet(MV_U32 pciIf); + +/* mvPciIfLocalDevNumSet - Set PCI interface local device number.*/ +MV_STATUS mvPciIfLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum); + +/* mvPciIfLocalDevNumGet - Get PCI interface local device number.*/ +MV_U32 mvPciIfLocalDevNumGet(MV_U32 pciIf); + +/* mvPciIfTypeGet - Get PCI If type*/ +PCI_IF_TYPE mvPciIfTypeGet(MV_U32 pciIf); + +MV_U32 mvPciRealIfNumGet(MV_U32 pciIf); + +/* mvPciIfAddrDecShow - Display address decode windows attributes */ +MV_VOID mvPciIfAddrDecShow(MV_VOID); + +#endif /* #ifndef __INCPCIIFH */ + diff --git a/board/mv_feroceon/mv_hal/pci-if/mvPciIfRegs.h b/board/mv_feroceon/mv_hal/pci-if/mvPciIfRegs.h new file mode 100644 index 0000000..08d4d2d --- /dev/null +++ b/board/mv_feroceon/mv_hal/pci-if/mvPciIfRegs.h @@ -0,0 +1,245 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCPCIIFREGSH +#define __INCPCIIFREGSH + + +/* defines */ +#define MAX_PCI_DEVICES 32 +#define MAX_PCI_FUNCS 8 +#define MAX_PCI_BUSSES 128 + +/***************************************/ +/* PCI Configuration registers */ +/***************************************/ + +/*********************************************/ +/* PCI Configuration, Function 0, Registers */ +/*********************************************/ + + +/* Standard registers */ +#define PCI_DEVICE_AND_VENDOR_ID 0x000 +#define PCI_STATUS_AND_COMMAND 0x004 +#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE 0x00C +#define PCI_MEMORY_BAR_BASE_ADDR(barNum) (0x010 + ((barNum) << 2)) +#define PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID 0x02C +#define PCI_EXPANSION_ROM_BASE_ADDR_REG 0x030 +#define PCI_CAPABILTY_LIST_POINTER 0x034 +#define PCI_INTERRUPT_PIN_AND_LINE 0x03C + + +/* PCI Device and Vendor ID Register (PDVIR) */ +#define PDVIR_VEN_ID_OFFS 0 /* Vendor ID */ +#define PDVIR_VEN_ID_MASK (0xffff << PDVIR_VEN_ID_OFFS) + +#define PDVIR_DEV_ID_OFFS 16 /* Device ID */ +#define PDVIR_DEV_ID_MASK (0xffff << PDVIR_DEV_ID_OFFS) + +/* PCI Status and Command Register (PSCR) */ +#define PSCR_IO_EN BIT0 /* IO Enable */ +#define PSCR_MEM_EN BIT1 /* Memory Enable */ +#define PSCR_MASTER_EN BIT2 /* Master Enable */ +#define PSCR_SPECIAL_EN BIT3 /* Special Cycle Enable */ +#define PSCR_MEM_WRI_INV BIT4 /* Memory Write and Invalidate Enable */ +#define PSCR_VGA BIT5 /* VGA Palette Snoops */ +#define PSCR_PERR_EN BIT6 /* Parity Errors Respond Enable */ +#define PSCR_ADDR_STEP BIT7 /* Address Stepping Enable (Wait Cycle En)*/ +#define PSCR_SERR_EN BIT8 /* Ability to assert SERR# line */ +#define PSCR_FAST_BTB_EN BIT9 /* generate fast back-to-back transactions*/ +#define PSCR_CAP_LIST BIT20 /* Capability List Support */ +#define PSCR_66MHZ_EN BIT21 /* 66 MHz Capable */ +#define PSCR_UDF_EN BIT22 /* User definable features */ +#define PSCR_TAR_FAST_BB BIT23 /* fast back-to-back transactions capable */ +#define PSCR_DATA_PERR BIT24 /* Data Parity reported */ + +#define PSCR_DEVSEL_TIM_OFFS 25 /* DEVSEL timing */ +#define PSCR_DEVSEL_TIM_MASK (0x3 << PSCR_DEVSEL_TIM_OFFS) +#define PSCR_DEVSEL_TIM_FAST (0x0 << PSCR_DEVSEL_TIM_OFFS) +#define PSCR_DEVSEL_TIM_MED (0x1 << PSCR_DEVSEL_TIM_OFFS) +#define PSCR_DEVSEL_TIM_SLOW (0x2 << PSCR_DEVSEL_TIM_OFFS) + +#define PSCR_SLAVE_TABORT BIT27 /* Signalled Target Abort */ +#define PSCR_MASTER_TABORT BIT28 /* Recieved Target Abort */ +#define PSCR_MABORT BIT29 /* Recieved Master Abort */ +#define PSCR_SYSERR BIT30 /* Signalled system error */ +#define PSCR_DET_PARERR BIT31 /* Detect Parity Error */ + +/* PCI configuration register offset=0x08 fields + (PCI_CLASS_CODE_AND_REVISION_ID)(PCCRI) */ + +#define PCCRIR_REVID_OFFS 0 /* Revision ID */ +#define PCCRIR_REVID_MASK (0xff << PCCRIR_REVID_OFFS) + +#define PCCRIR_FULL_CLASS_OFFS 8 /* Full Class Code */ +#define PCCRIR_FULL_CLASS_MASK (0xffffff << PCCRIR_FULL_CLASS_OFFS) + +#define PCCRIR_PROGIF_OFFS 8 /* Prog .I/F*/ +#define PCCRIR_PROGIF_MASK (0xff << PCCRIR_PROGIF_OFFS) + +#define PCCRIR_SUB_CLASS_OFFS 16 /* Sub Class*/ +#define PCCRIR_SUB_CLASS_MASK (0xff << PCCRIR_SUB_CLASS_OFFS) + +#define PCCRIR_BASE_CLASS_OFFS 24 /* Base Class*/ +#define PCCRIR_BASE_CLASS_MASK (0xff << PCCRIR_BASE_CLASS_OFFS) + +/* PCI configuration register offset=0x0C fields + (PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE)(PBHTLTCL) */ + +#define PBHTLTCLR_CACHELINE_OFFS 0 /* Specifies the cache line size */ +#define PBHTLTCLR_CACHELINE_MASK (0xff << PBHTLTCLR_CACHELINE_OFFS) + +#define PBHTLTCLR_LATTIMER_OFFS 8 /* latency timer */ +#define PBHTLTCLR_LATTIMER_MASK (0xff << PBHTLTCLR_LATTIMER_OFFS) + +#define PBHTLTCLR_HEADTYPE_FULL_OFFS 16 /* Full Header Type */ +#define PBHTLTCLR_HEADTYPE_FULL_MASK (0xff << PBHTLTCLR_HEADTYPE_FULL_OFFS) + +#define PBHTLTCLR_MULTI_FUNC BIT23 /* Multi/Single function */ + +#define PBHTLTCLR_HEADER_OFFS 16 /* Header type */ +#define PBHTLTCLR_HEADER_MASK (0x7f << PBHTLTCLR_HEADER_OFFS) +#define PBHTLTCLR_HEADER_STANDARD (0x0 << PBHTLTCLR_HEADER_OFFS) +#define PBHTLTCLR_HEADER_PCI2PCI_BRIDGE (0x1 << PBHTLTCLR_HEADER_OFFS) + + +#define PBHTLTCLR_BISTCOMP_OFFS 24 /* BIST Completion Code */ +#define PBHTLTCLR_BISTCOMP_MASK (0xf << PBHTLTCLR_BISTCOMP_OFFS) + +#define PBHTLTCLR_BISTACT BIT30 /* BIST Activate bit */ +#define PBHTLTCLR_BISTCAP BIT31 /* BIST Capable Bit */ + + +/* PCI Bar Base Low Register (PBBLR) */ +#define PBBLR_IOSPACE BIT0 /* Memory Space Indicator */ + +#define PBBLR_TYPE_OFFS 1 /* BAR Type/Init Val. */ +#define PBBLR_TYPE_MASK (0x3 << PBBLR_TYPE_OFFS) +#define PBBLR_TYPE_32BIT_ADDR (0x0 << PBBLR_TYPE_OFFS) +#define PBBLR_TYPE_64BIT_ADDR (0x2 << PBBLR_TYPE_OFFS) + +#define PBBLR_PREFETCH_EN BIT3 /* Prefetch Enable */ + + +#define PBBLR_MEM_BASE_OFFS 4 /* Memory Bar Base address. Corresponds to + address bits [31:4] */ +#define PBBLR_MEM_BASE_MASK (0xfffffff << PBBLR_MEM_BASE_OFFS) + +#define PBBLR_IO_BASE_OFFS 2 /* IO Bar Base address. Corresponds to + address bits [31:2] */ +#define PBBLR_IO_BASE_MASK (0x3fffffff << PBBLR_IO_BASE_OFFS) + + +#define PBBLR_BASE_OFFS 12 /* Base address. Address bits [31:12] */ +#define PBBLR_BASE_MASK (0xfffff << PBBLR_BASE_OFFS) +#define PBBLR_BASE_ALIGNMET (1 << PBBLR_BASE_OFFS) + + +/* PCI Bar Base High Fegister (PBBHR) */ +#define PBBHR_BASE_OFFS 0 /* Base address. Address bits [31:12] */ +#define PBBHR_BASE_MASK (0xffffffff << PBBHR_BASE_OFFS) + + +/* PCI configuration register offset=0x2C fields + (PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID)(PSISVI) */ + +#define PSISVIR_VENID_OFFS 0 /* Subsystem Manufacturer Vendor ID Number */ +#define PSISVIR_VENID_MASK (0xffff << PSISVIR_VENID_OFFS) + +#define PSISVIR_DEVID_OFFS 16 /* Subsystem Device ID Number */ +#define PSISVIR_DEVID_MASK (0xffff << PSISVIR_DEVID_OFFS) + +/* PCI configuration register offset=0x30 fields + (PCI_EXPANSION_ROM_BASE_ADDR_REG)(PERBA) */ + +#define PERBAR_EXPROMEN BIT0 /* Expansion ROM Enable */ + +#define PERBAR_BASE_OFFS 12 /* Expansion ROM Base Address */ +#define PERBAR_BASE_MASK (0xfffff << PERBAR_BASE_OFFS) + +/* PCI configuration register offset=0x34 fields + (PCI_CAPABILTY_LIST_POINTER)(PCLP) */ + +#define PCLPR_CAPPTR_OFFS 0 /* Capability List Pointer */ +#define PCLPR_CAPPTR_MASK (0xff << PCLPR_CAPPTR_OFFS) + +/* PCI configuration register offset=0x3C fields + (PCI_INTERRUPT_PIN_AND_LINE)(PIPL) */ + +#define PIPLR_INTLINE_OFFS 0 /* Interrupt line (IRQ) */ +#define PIPLR_INTLINE_MASK (0xff << PIPLR_INTLINE_OFFS) + +#define PIPLR_INTPIN_OFFS 8 /* interrupt pin (A,B,C,D) */ +#define PIPLR_INTPIN_MASK (0xff << PIPLR_INTPIN_OFFS) + +#define PIPLR_MINGRANT_OFFS 16 /* Minimum Grant on 250 nano seconds units */ +#define PIPLR_MINGRANT_MASK (0xff << PIPLR_MINGRANT_OFFS) + +#define PIPLR_MAXLATEN_OFFS 24 /* Maximum latency on 250 nano seconds units */ +#define PIPLR_MAXLATEN_MASK (0xff << PIPLR_MAXLATEN_OFFS) + +#endif /* #ifndef __INCPCIIFREGSH */ + diff --git a/board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.c b/board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.c new file mode 100644 index 0000000..ae0c943 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.c @@ -0,0 +1,1006 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/* includes */ +#include "mvPciUtils.h" + +#include "mvCtrlEnvLib.h" + +/* #define MV_DEBUG */ +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x + #define mvOsPrintf printf +#else + #define DB(x) +#endif + +/* +This module only support scanning of Header type 00h of pci devices +There is no suppotr for Header type 01h of pci devices ( PCI bridges ) +*/ + + +static MV_STATUS pciDetectDevice(MV_U32 pciIf, + MV_U32 bus, + MV_U32 dev, + MV_U32 func, + MV_PCI_DEVICE *pPciAgent); + +static MV_U32 pciDetectDeviceBars(MV_U32 pciIf, + MV_U32 bus, + MV_U32 dev, + MV_U32 func, + MV_PCI_DEVICE *pPciAgent); + + + + + + +/******************************************************************************* +* mvPciScan - Scan a PCI interface bus +* +* DESCRIPTION: +* Performs a full scan on a PCI interface and returns all possible details +* on the agents found on the bus. +* +* INPUT: +* pciIf - PCI Interface +* pPciAgents - Pointer to an Array of the pci agents to be detected +* pPciAgentsNum - pPciAgents array maximum number of elements +* +* OUTPUT: +* pPciAgents - Array of the pci agents detected on the bus +* pPciAgentsNum - Number of pci agents detected on the bus +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ + +MV_STATUS mvPciScan(MV_U32 pciIf, + MV_PCI_DEVICE *pPciAgents, + MV_U32 *pPciAgentsNum) +{ + + MV_U32 devIndex,funcIndex=0,busIndex=0,detectedDevNum=0; + MV_U32 localBus=mvPciIfLocalBusNumGet(pciIf); + MV_PCI_DEVICE *pPciDevice; + MV_PCI_DEVICE *pMainDevice; + + DB(mvOsPrintf("mvPciScan: PCI interface num %d\n", pciIf)); + /* Parameter checking */ + if (pciIf >= mvCtrlPciIfMaxIfGet()) + { + DB(mvOsPrintf("mvPciScan: ERR. Invalid PCI interface num %d\n", pciIf)); + return MV_BAD_PARAM; + } + if (NULL == pPciAgents) + { + DB(mvOsPrintf("mvPciScan: ERR. pPciAgents=NULL \n")); + return MV_BAD_PARAM; + } + if (NULL == pPciAgentsNum) + { + DB(mvOsPrintf("mvPciScan: ERR. pPciAgentsNum=NULL \n")); + return MV_BAD_PARAM; + } + + + DB(mvOsPrintf("mvPciScan: PCI interface num %d mvPciMasterEnable\n", pciIf)); + /* Master enable the MV PCI master */ + if (MV_OK != mvPciIfMasterEnable(pciIf,MV_TRUE)) + { + DB(mvOsPrintf("mvPciScan: ERR. mvPciMasterEnable failed \n")); + return MV_ERROR; + + } + + DB(mvOsPrintf("mvPciScan: PCI interface num scan%d\n", pciIf)); + + /* go through all busses */ + for (busIndex=localBus ; busIndex < MAX_PCI_BUSSES ; busIndex++) + { + /* go through all possible devices on the local bus */ + for (devIndex=0 ; devIndex < MAX_PCI_DEVICES ; devIndex++) + { + /* always start with function equal to zero */ + funcIndex=0; + + pPciDevice=&pPciAgents[detectedDevNum]; + DB(mvOsPrintf("mvPciScan: PCI interface num scan%d:%d\n", busIndex, devIndex)); + + if (MV_ERROR == pciDetectDevice(pciIf, + busIndex, + devIndex, + funcIndex, + pPciDevice)) + { + /* no device detected , try the next address */ + continue; + } + + /* We are here ! means we have detected a device*/ + /* always we start with only one function per device */ + pMainDevice = pPciDevice; + pPciDevice->funtionsNum = 1; + + + /* move on */ + detectedDevNum++; + + + /* check if we have no more room for a new device */ + if (detectedDevNum == *pPciAgentsNum) + { + DB(mvOsPrintf("mvPciScan: ERR. array passed too small \n")); + return MV_ERROR; + } + + /* check the detected device if it is a multi functional device then + scan all device functions*/ + if (pPciDevice->isMultiFunction == MV_TRUE) + { + /* start with function number 1 because we have already detected + function 0 */ + for (funcIndex=1; funcIndexfuntionsNum++; + detectedDevNum++; + + /* check if we have no more room for a new device */ + if (detectedDevNum == *pPciAgentsNum) + { + DB(mvOsPrintf("mvPciScan: ERR. Array too small\n")); + return MV_ERROR; + } + + + } + } + + } + + } + + /* return the number of devices actually detected on the bus ! */ + *pPciAgentsNum = detectedDevNum; + + return MV_OK; + +} + + +/******************************************************************************* +* pciDetectDevice - Detect a pci device parameters +* +* DESCRIPTION: +* This function detect if a pci agent exist on certain address ! +* and if exists then it fills all possible information on the +* agent +* +* INPUT: +* pciIf - PCI Interface +* bus - Bus number +* dev - Device number +* func - Function number +* +* +* +* OUTPUT: +* pPciAgent - pointer to the pci agent filled with its information +* +* RETURN: +* MV_ERROR if no device , MV_OK otherwise +* +*******************************************************************************/ + +static MV_STATUS pciDetectDevice(MV_U32 pciIf, + MV_U32 bus, + MV_U32 dev, + MV_U32 func, + MV_PCI_DEVICE *pPciAgent) +{ + MV_U32 pciData; + + /* no Parameters checking ! because it is static function and it is assumed + that all parameters were checked in the calling function */ + + + /* Try read the PCI Vendor ID and Device ID */ + + /* We will scan only ourselves and the PCI slots that exist on the + board, because we may have a case that we have one slot that has + a Cardbus connector, and because CardBus answers all IDsels we want + to scan only this slot and ourseleves. + + */ + #if defined(MV_INCLUDE_PCI) + if ((PCI_IF_TYPE_CONVEN_PCIX == mvPciIfTypeGet(pciIf)) && + (DB_88F5181_DDR1_PRPMC != mvBoardIdGet()) && + (DB_88F5181_DDR1_PEXPCI != mvBoardIdGet()) && + (DB_88F5181_DDR1_MNG != mvBoardIdGet())) + { + + if (mvBoardIsOurPciSlot(bus, dev) == MV_FALSE) + { + return MV_ERROR; + } + } + #endif /* defined(MV_INCLUDE_PCI) */ + + pciData = mvPciIfConfigRead(pciIf, bus,dev,func, PCI_DEVICE_AND_VENDOR_ID); + + if (PCI_ERROR_CODE == pciData) + { + /* no device exist */ + return MV_ERROR; + } + + /* we are here ! means a device is detected */ + + /* fill basic information */ + pPciAgent->busNumber=bus; + pPciAgent->deviceNum=dev; + pPciAgent->function=func; + + /* Fill the PCI Vendor ID and Device ID */ + + pPciAgent->venID = (pciData & PDVIR_VEN_ID_MASK) >> PDVIR_VEN_ID_OFFS; + pPciAgent->deviceID = (pciData & PDVIR_DEV_ID_MASK) >> PDVIR_DEV_ID_OFFS; + + /* Read Status and command */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_STATUS_AND_COMMAND); + + + /* Fill related Status and Command information*/ + + if (pciData & PSCR_TAR_FAST_BB) + { + pPciAgent->isFastB2BCapable = MV_TRUE; + } + else + { + pPciAgent->isFastB2BCapable = MV_FALSE; + } + + if (pciData & PSCR_CAP_LIST) + { + pPciAgent->isCapListSupport=MV_TRUE; + } + else + { + pPciAgent->isCapListSupport=MV_FALSE; + } + + if (pciData & PSCR_66MHZ_EN) + { + pPciAgent->is66MHZCapable=MV_TRUE; + } + else + { + pPciAgent->is66MHZCapable=MV_FALSE; + } + + /* Read Class Code and Revision */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_CLASS_CODE_AND_REVISION_ID); + + + pPciAgent->baseClassCode = + (pciData & PCCRIR_BASE_CLASS_MASK) >> PCCRIR_BASE_CLASS_OFFS; + + pPciAgent->subClassCode = + (pciData & PCCRIR_SUB_CLASS_MASK) >> PCCRIR_SUB_CLASS_OFFS; + + pPciAgent->progIf = + (pciData & PCCRIR_PROGIF_MASK) >> PCCRIR_PROGIF_OFFS; + + pPciAgent->revisionID = + (pciData & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS; + + /* Read PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE); + + + + pPciAgent->pciCacheLine= + (pciData & PBHTLTCLR_CACHELINE_MASK ) >> PBHTLTCLR_CACHELINE_OFFS; + pPciAgent->pciLatencyTimer= + (pciData & PBHTLTCLR_LATTIMER_MASK) >> PBHTLTCLR_LATTIMER_OFFS; + + switch (pciData & PBHTLTCLR_HEADER_MASK) + { + case PBHTLTCLR_HEADER_STANDARD: + + pPciAgent->pciHeader=MV_PCI_STANDARD; + break; + case PBHTLTCLR_HEADER_PCI2PCI_BRIDGE: + + pPciAgent->pciHeader=MV_PCI_PCI2PCI_BRIDGE; + break; + + } + + if (pciData & PBHTLTCLR_MULTI_FUNC) + { + pPciAgent->isMultiFunction=MV_TRUE; + } + else + { + pPciAgent->isMultiFunction=MV_FALSE; + } + + if (pciData & PBHTLTCLR_BISTCAP) + { + pPciAgent->isBISTCapable=MV_TRUE; + } + else + { + pPciAgent->isBISTCapable=MV_FALSE; + } + + + /* read this device pci bars */ + + pciDetectDeviceBars(pciIf, + bus,dev,func, + pPciAgent); + + + /* check if we are bridge*/ + if ((pPciAgent->baseClassCode == PCI_BRIDGE_CLASS)&& + (pPciAgent->subClassCode == P2P_BRIDGE_SUB_CLASS_CODE)) + { + + /* Read P2P_BUSSES_NUM */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + P2P_BUSSES_NUM); + + pPciAgent->p2pPrimBusNum = + (pciData & PBM_PRIME_BUS_NUM_MASK) >> PBM_PRIME_BUS_NUM_OFFS; + + pPciAgent->p2pSecBusNum = + (pciData & PBM_SEC_BUS_NUM_MASK) >> PBM_SEC_BUS_NUM_OFFS; + + pPciAgent->p2pSubBusNum = + (pciData & PBM_SUB_BUS_NUM_MASK) >> PBM_SUB_BUS_NUM_OFFS; + + pPciAgent->p2pSecLatencyTimer = + (pciData & PBM_SEC_LAT_TMR_MASK) >> PBM_SEC_LAT_TMR_OFFS; + + /* Read P2P_IO_BASE_LIMIT_SEC_STATUS */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + P2P_IO_BASE_LIMIT_SEC_STATUS); + + pPciAgent->p2pSecStatus = + (pciData & PIBLSS_SEC_STATUS_MASK) >> PIBLSS_SEC_STATUS_OFFS; + + + pPciAgent->p2pIObase = + (pciData & PIBLSS_IO_BASE_MASK) << PIBLSS_IO_LIMIT_OFFS; + + /* clear low address (should be zero)*/ + pPciAgent->p2pIObase &= PIBLSS_HIGH_ADDR_MASK; + + pPciAgent->p2pIOLimit = + (pciData & PIBLSS_IO_LIMIT_MASK); + + /* fill low address with 0xfff */ + pPciAgent->p2pIOLimit |= PIBLSS_LOW_ADDR_MASK; + + + switch ((pciData & PIBLSS_ADD_CAP_MASK) >> PIBLSS_ADD_CAP_OFFS) + { + case PIBLSS_ADD_CAP_16BIT: + + pPciAgent->bIO32 = MV_FALSE; + + break; + case PIBLSS_ADD_CAP_32BIT: + + pPciAgent->bIO32 = MV_TRUE; + + /* Read P2P_IO_BASE_LIMIT_UPPER_16 */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + P2P_IO_BASE_LIMIT_UPPER_16); + + pPciAgent->p2pIObase |= + (pciData & PRBU_IO_UPP_BASE_MASK) << PRBU_IO_UPP_LIMIT_OFFS; + + + pPciAgent->p2pIOLimit |= + (pciData & PRBU_IO_UPP_LIMIT_MASK); + + break; + + } + + + /* Read P2P_MEM_BASE_LIMIT */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + P2P_MEM_BASE_LIMIT); + + pPciAgent->p2pMemBase = + (pciData & PMBL_MEM_BASE_MASK) << PMBL_MEM_LIMIT_OFFS; + + /* clear low address */ + pPciAgent->p2pMemBase &= PMBL_HIGH_ADDR_MASK; + + pPciAgent->p2pMemLimit = + (pciData & PMBL_MEM_LIMIT_MASK); + + /* add 0xfffff */ + pPciAgent->p2pMemLimit |= PMBL_LOW_ADDR_MASK; + + + /* Read P2P_PREF_MEM_BASE_LIMIT */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + P2P_PREF_MEM_BASE_LIMIT); + + + pPciAgent->p2pPrefMemBase = + (pciData & PRMBL_PREF_MEM_BASE_MASK) << PRMBL_PREF_MEM_LIMIT_OFFS; + + /* get high address only */ + pPciAgent->p2pPrefMemBase &= PRMBL_HIGH_ADDR_MASK; + + + + pPciAgent->p2pPrefMemLimit = + (pciData & PRMBL_PREF_MEM_LIMIT_MASK); + + /* add 0xfffff */ + pPciAgent->p2pPrefMemLimit |= PRMBL_LOW_ADDR_MASK; + + switch (pciData & PRMBL_ADD_CAP_MASK) + { + case PRMBL_ADD_CAP_32BIT: + + pPciAgent->bPrefMem64 = MV_FALSE; + + /* Read P2P_PREF_BASE_UPPER_32 */ + pPciAgent->p2pPrefBaseUpper32Bits = 0; + + /* Read P2P_PREF_LIMIT_UPPER_32 */ + pPciAgent->p2pPrefLimitUpper32Bits = 0; + + break; + case PRMBL_ADD_CAP_64BIT: + + pPciAgent->bPrefMem64 = MV_TRUE; + + /* Read P2P_PREF_BASE_UPPER_32 */ + pPciAgent->p2pPrefBaseUpper32Bits = mvPciIfConfigRead(pciIf, + bus,dev,func, + P2P_PREF_BASE_UPPER_32); + + /* Read P2P_PREF_LIMIT_UPPER_32 */ + pPciAgent->p2pPrefLimitUpper32Bits = mvPciIfConfigRead(pciIf, + bus,dev,func, + P2P_PREF_LIMIT_UPPER_32); + + break; + + } + + } + else /* no bridge */ + { + /* Read PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID); + + + pPciAgent->subSysVenID = + (pciData & PSISVIR_VENID_MASK) >> PSISVIR_VENID_OFFS; + pPciAgent->subSysID = + (pciData & PSISVIR_DEVID_MASK) >> PSISVIR_DEVID_OFFS; + + + /* Read PCI_EXPANSION_ROM_BASE_ADDR_REG */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_EXPANSION_ROM_BASE_ADDR_REG); + + + if (pciData & PERBAR_EXPROMEN) + { + pPciAgent->isExpRom = MV_TRUE; + } + else + { + pPciAgent->isExpRom = MV_FALSE; + } + + pPciAgent->expRomAddr = + (pciData & PERBAR_BASE_MASK) >> PERBAR_BASE_OFFS; + + } + + + if (MV_TRUE == pPciAgent->isCapListSupport) + { + /* Read PCI_CAPABILTY_LIST_POINTER */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_CAPABILTY_LIST_POINTER); + + pPciAgent->capListPointer = + (pciData & PCLPR_CAPPTR_MASK) >> PCLPR_CAPPTR_OFFS; + + } + + /* Read PCI_INTERRUPT_PIN_AND_LINE */ + pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_INTERRUPT_PIN_AND_LINE); + + + pPciAgent->irqLine= + (pciData & PIPLR_INTLINE_MASK) >> PIPLR_INTLINE_OFFS; + + pPciAgent->intPin= + (MV_PCI_INT_PIN)(pciData & PIPLR_INTPIN_MASK) >> PIPLR_INTPIN_OFFS; + + pPciAgent->minGrant= + (pciData & PIPLR_MINGRANT_MASK) >> PIPLR_MINGRANT_OFFS; + pPciAgent->maxLatency= + (pciData & PIPLR_MAXLATEN_MASK) >> PIPLR_MAXLATEN_OFFS; + + mvPciClassNameGet(pPciAgent->baseClassCode, + (MV_8 *)pPciAgent->type); + + return MV_OK; + + +} + +/******************************************************************************* +* pciDetectDeviceBars - Detect a pci device bars +* +* DESCRIPTION: +* This function detects all pci agent bars +* +* INPUT: +* pciIf - PCI Interface +* bus - Bus number +* dev - Device number +* func - Function number +* +* +* +* OUTPUT: +* pPciAgent - pointer to the pci agent filled with its information +* +* RETURN: +* detected bars number +* +*******************************************************************************/ +static MV_U32 pciDetectDeviceBars(MV_U32 pciIf, + MV_U32 bus, + MV_U32 dev, + MV_U32 func, + MV_PCI_DEVICE *pPciAgent) +{ + MV_U32 pciData,barIndex,detectedBar=0; + MV_U32 tmpBaseHigh=0,tmpBaseLow=0; + MV_U32 pciMaxBars=0; + + pPciAgent->barsNum=0; + + /* check if we are bridge*/ + if ((pPciAgent->baseClassCode == PCI_BRIDGE_CLASS)&& + (pPciAgent->subClassCode == P2P_BRIDGE_SUB_CLASS_CODE)) + { + pciMaxBars = 2; + } + else /* no bridge */ + { + pciMaxBars = 6; + } + + /* read this device pci bars */ + for (barIndex = 0 ; barIndex < pciMaxBars ; barIndex++ ) + { + /* Read PCI_MEMORY_BAR_BASE_ADDR */ + tmpBaseLow = pciData = mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex)); + + pPciAgent->pciBar[detectedBar].barOffset = + PCI_MEMORY_BAR_BASE_ADDR(barIndex); + + /* check if the bar is 32bit or 64bit bar */ + switch (pciData & PBBLR_TYPE_MASK) + { + case PBBLR_TYPE_32BIT_ADDR: + pPciAgent->pciBar[detectedBar].barType = PCI_32BIT_BAR; + break; + case PBBLR_TYPE_64BIT_ADDR: + pPciAgent->pciBar[detectedBar].barType = PCI_64BIT_BAR; + break; + + } + + /* check if it is memory or IO bar */ + if (pciData & PBBLR_IOSPACE) + { + pPciAgent->pciBar[detectedBar].barMapping=PCI_IO_BAR; + } + else + { + pPciAgent->pciBar[detectedBar].barMapping=PCI_MEMORY_BAR; + } + + /* if it is memory bar then check if it is prefetchable */ + if (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping) + { + if (pciData & PBBLR_PREFETCH_EN) + { + pPciAgent->pciBar[detectedBar].isPrefetchable = MV_TRUE; + } + else + { + pPciAgent->pciBar[detectedBar].isPrefetchable = MV_FALSE; + } + + pPciAgent->pciBar[detectedBar].barBaseLow = + pciData & PBBLR_MEM_BASE_MASK; + + + } + else /* IO Bar */ + { + pPciAgent->pciBar[detectedBar].barBaseLow = + pciData & PBBLR_IO_BASE_MASK; + + } + + pPciAgent->pciBar[detectedBar].barBaseHigh=0; + + if (PCI_64BIT_BAR == pPciAgent->pciBar[detectedBar].barType) + { + barIndex++; + + tmpBaseHigh = pPciAgent->pciBar[detectedBar].barBaseHigh = + mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex)); + + + } + + /* calculating full base address (64bit) */ + pPciAgent->pciBar[detectedBar].barBaseAddr = + (MV_U64)pPciAgent->pciBar[detectedBar].barBaseHigh; + + pPciAgent->pciBar[detectedBar].barBaseAddr <<= 32; + + pPciAgent->pciBar[detectedBar].barBaseAddr |= + (MV_U64)pPciAgent->pciBar[detectedBar].barBaseLow; + + + + /* get the sizes of the the bar */ + + pPciAgent->pciBar[detectedBar].barSizeHigh=0; + + if ((PCI_64BIT_BAR == pPciAgent->pciBar[detectedBar].barType) && + (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping)) + + { + /* write oxffffffff to the bar to get the size */ + /* start with sizelow ( original value was saved in tmpBaseLow ) */ + mvPciIfConfigWrite(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex-1), + 0xffffffff); + + /* read size */ + pPciAgent->pciBar[detectedBar].barSizeLow = + mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex-1)); + + + + /* restore original value */ + mvPciIfConfigWrite(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex-1), + tmpBaseLow); + + + /* now do the same for BaseHigh */ + + /* write oxffffffff to the bar to get the size */ + mvPciIfConfigWrite(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex), + 0xffffffff); + + /* read size */ + pPciAgent->pciBar[detectedBar].barSizeHigh = + mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex)); + + /* restore original value */ + mvPciIfConfigWrite(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex), + tmpBaseHigh); + + if ((0 == pPciAgent->pciBar[detectedBar].barSizeLow)&& + (0 == pPciAgent->pciBar[detectedBar].barSizeHigh)) + { + /* this bar is not applicable for this device, + ignore all previous settings and check the next bar*/ + + /* we though this was a 64bit bar , and it seems this + was wrong ! so decrement barIndex */ + barIndex--; + continue; + } + + /* calculate the full 64 bit size */ + + if (0 != pPciAgent->pciBar[detectedBar].barSizeHigh) + { + pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK; + + pPciAgent->pciBar[detectedBar].barSizeLow = + ~pPciAgent->pciBar[detectedBar].barSizeLow + 1; + + pPciAgent->pciBar[detectedBar].barSizeHigh = 0; + + } + else + { + + pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK; + + pPciAgent->pciBar[detectedBar].barSizeLow = + ~pPciAgent->pciBar[detectedBar].barSizeLow + 1; + + pPciAgent->pciBar[detectedBar].barSizeHigh = 0; + + } + + + + } + else /* 32bit bar */ + { + /* write oxffffffff to the bar to get the size */ + mvPciIfConfigWrite(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex), + 0xffffffff); + + /* read size */ + pPciAgent->pciBar[detectedBar].barSizeLow = + mvPciIfConfigRead(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex)); + + if (0 == pPciAgent->pciBar[detectedBar].barSizeLow) + { + /* this bar is not applicable for this device, + ignore all previous settings and check the next bar*/ + continue; + } + + + /* restore original value */ + mvPciIfConfigWrite(pciIf, + bus,dev,func, + PCI_MEMORY_BAR_BASE_ADDR(barIndex), + tmpBaseLow); + + /* calculate size low */ + + if (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping) + { + pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK; + } + else + { + pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_IO_BASE_MASK; + } + + pPciAgent->pciBar[detectedBar].barSizeLow = + ~pPciAgent->pciBar[detectedBar].barSizeLow + 1; + + pPciAgent->pciBar[detectedBar].barSizeHigh = 0; + pPciAgent->pciBar[detectedBar].barSize = + (MV_U64)pPciAgent->pciBar[detectedBar].barSizeLow; + + + } + + /* we are here ! this means we have already detected a bar for + this device , now move on */ + + detectedBar++; + pPciAgent->barsNum++; + } + + return detectedBar; +} + + +/******************************************************************************* +* mvPciClassNameGet - get PCI class name +* +* DESCRIPTION: +* This function returns the PCI class name +* +* INPUT: +* baseClassCode - Base Class Code. +* +* OUTPUT: +* pType - the class name +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciClassNameGet(MV_U32 baseClassCode, MV_8 *pType) +{ + + switch(baseClassCode) + { + case 0x0: + strcpy(pType,"Old generation device"); + break; + case 0x1: + strcpy(pType,"Mass storage controller"); + break; + case 0x2: + strcpy(pType,"Network controller"); + break; + case 0x3: + strcpy(pType,"Display controller"); + break; + case 0x4: + strcpy(pType,"Multimedia device"); + break; + case 0x5: + strcpy(pType,"Memory controller"); + break; + case 0x6: + strcpy(pType,"Bridge Device"); + break; + case 0x7: + strcpy(pType,"Simple Communication controllers"); + break; + case 0x8: + strcpy(pType,"Base system peripherals"); + break; + case 0x9: + strcpy(pType,"Input Devices"); + break; + case 0xa: + strcpy(pType,"Docking stations"); + break; + case 0xb: + strcpy(pType,"Processors"); + break; + case 0xc: + strcpy(pType,"Serial bus controllers"); + break; + case 0xd: + strcpy(pType,"Wireless controllers"); + break; + case 0xe: + strcpy(pType,"Intelligent I/O controllers"); + break; + case 0xf: + strcpy(pType,"Satellite communication controllers"); + break; + case 0x10: + strcpy(pType,"Encryption/Decryption controllers"); + break; + case 0x11: + strcpy(pType,"Data acquisition and signal processing controllers"); + break; + default: + strcpy(pType,"Unknown device"); + break; + } + + return MV_OK; + +} + + + diff --git a/board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.h b/board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.h new file mode 100644 index 0000000..2ee0b17 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pci-if/pci_util/mvPciUtils.h @@ -0,0 +1,323 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvPciUtilsh +#define __INCmvPciUtilsh + +/* +This module only support scanning of Header type 00h of pci devices +There is no suppotr for Header type 01h of pci devices ( PCI bridges ) +*/ + +/* includes */ +#include "mvSysHwConfig.h" +#include "pci-if/mvPciIf.h" +#include "pci/mvPciRegs.h" + + + +/* PCI base address low bar mask */ +#define PCI_ERROR_CODE 0xffffffff + +#define PCI_BRIDGE_CLASS 0x6 +#define P2P_BRIDGE_SUB_CLASS_CODE 0x4 + + +#define P2P_BUSSES_NUM 0x18 +#define P2P_IO_BASE_LIMIT_SEC_STATUS 0x1C +#define P2P_MEM_BASE_LIMIT 0x20 +#define P2P_PREF_MEM_BASE_LIMIT 0x24 +#define P2P_PREF_BASE_UPPER_32 0x28 +#define P2P_PREF_LIMIT_UPPER_32 0x2C +#define P2P_IO_BASE_LIMIT_UPPER_16 0x30 +#define P2P_EXP_ROM 0x38 + +/* P2P_BUSSES_NUM (PBM) */ + +#define PBM_PRIME_BUS_NUM_OFFS 0 +#define PBM_PRIME_BUS_NUM_MASK (0xff << PBM_PRIME_BUS_NUM_OFFS) + +#define PBM_SEC_BUS_NUM_OFFS 8 +#define PBM_SEC_BUS_NUM_MASK (0xff << PBM_SEC_BUS_NUM_OFFS) + +#define PBM_SUB_BUS_NUM_OFFS 16 +#define PBM_SUB_BUS_NUM_MASK (0xff << PBM_SUB_BUS_NUM_OFFS) + +#define PBM_SEC_LAT_TMR_OFFS 24 +#define PBM_SEC_LAT_TMR_MASK (0xff << PBM_SEC_LAT_TMR_OFFS) + +/* P2P_IO_BASE_LIMIT_SEC_STATUS (PIBLSS) */ + +#define PIBLSS_IO_BASE_OFFS 0 +#define PIBLSS_IO_BASE_MASK (0xff << PIBLSS_IO_BASE_OFFS) + +#define PIBLSS_ADD_CAP_OFFS 0 +#define PIBLSS_ADD_CAP_MASK (0x3 << PIBLSS_ADD_CAP_OFFS) +#define PIBLSS_ADD_CAP_16BIT (0x0 << PIBLSS_ADD_CAP_OFFS) +#define PIBLSS_ADD_CAP_32BIT (0x1 << PIBLSS_ADD_CAP_OFFS) + +#define PIBLSS_LOW_ADDR_OFFS 0 +#define PIBLSS_LOW_ADDR_MASK (0xFFF << PIBLSS_LOW_ADDR_OFFS) + +#define PIBLSS_HIGH_ADDR_OFFS 12 +#define PIBLSS_HIGH_ADDR_MASK (0xF << PIBLSS_HIGH_ADDR_OFFS) + +#define PIBLSS_IO_LIMIT_OFFS 8 +#define PIBLSS_IO_LIMIT_MASK (0xff << PIBLSS_IO_LIMIT_OFFS) + +#define PIBLSS_SEC_STATUS_OFFS 16 +#define PIBLSS_SEC_STATUS_MASK (0xffff << PIBLSS_SEC_STATUS_OFFS) + + +/* P2P_MEM_BASE_LIMIT (PMBL)*/ + +#define PMBL_MEM_BASE_OFFS 0 +#define PMBL_MEM_BASE_MASK (0xffff << PMBL_MEM_BASE_OFFS) + +#define PMBL_MEM_LIMIT_OFFS 16 +#define PMBL_MEM_LIMIT_MASK (0xffff << PMBL_MEM_LIMIT_OFFS) + + +#define PMBL_LOW_ADDR_OFFS 0 +#define PMBL_LOW_ADDR_MASK (0xFFFFF << PMBL_LOW_ADDR_OFFS) + +#define PMBL_HIGH_ADDR_OFFS 20 +#define PMBL_HIGH_ADDR_MASK (0xFFF << PMBL_HIGH_ADDR_OFFS) + + +/* P2P_PREF_MEM_BASE_LIMIT (PRMBL) */ + +#define PRMBL_PREF_MEM_BASE_OFFS 0 +#define PRMBL_PREF_MEM_BASE_MASK (0xffff << PRMBL_PREF_MEM_BASE_OFFS) + +#define PRMBL_PREF_MEM_LIMIT_OFFS 16 +#define PRMBL_PREF_MEM_LIMIT_MASK (0xffff<= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciCommandSet: ERR. Invalid PCI IF num %d\n", pciIf); + return MV_BAD_PARAM; + } + + /* Set command register */ + MV_REG_WRITE(PCI_CMD_REG(pciIf), command); + + /* Upodate device max outstanding split tarnsaction */ + if ((command & PCR_CPU_TO_PCI_ORDER_EN) && + (command & PCR_PCI_TO_CPU_ORDER_EN)) + { + /* Read PCI-X command register */ + regVal = mvPciConfigRead (pciIf, locBusNum, locDevNum, 0, PCIX_COMMAND); + + /* clear bits 22:20 */ + regVal &= 0xff8fffff; + + /* set reset value */ + regVal |= (0x3 << 20); + + /* Write back the value */ + mvPciConfigWrite (pciIf, locBusNum, locDevNum, 0, PCIX_COMMAND, regVal); + } + + return MV_OK; + + +} + + +/******************************************************************************* +* mvPciModeGet - Get PCI interface mode. +* +* DESCRIPTION: +* This function returns the given PCI interface mode. +* +* INPUT: +* pciIf - PCI interface number. +* +* OUTPUT: +* pPciMode - Pointer to PCI mode structure. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciModeGet(MV_U32 pciIf, MV_PCI_MODE *pPciMode) +{ + MV_U32 pciMode; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciModeGet: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + if (NULL == pPciMode) + { + mvOsPrintf("mvPciModeGet: ERR. pPciMode = NULL \n"); + return MV_BAD_PARAM; + } + + /* Read pci mode register */ + pciMode = MV_REG_READ(PCI_MODE_REG(pciIf)); + + switch (pciMode & PMR_PCI_MODE_MASK) + { + case PMR_PCI_MODE_CONV: + pPciMode->pciType = MV_PCI_CONV; + + if (MV_REG_READ(PCI_DLL_CTRL_REG(pciIf)) & PDC_DLL_EN) + { + pPciMode->pciSpeed = 66000000; /* 66MHZ */ + } + else + { + pPciMode->pciSpeed = 33000000; /* 33MHZ */ + } + + break; + + case PMR_PCI_MODE_PCIX_66MHZ: + pPciMode->pciType = MV_PCIX; + pPciMode->pciSpeed = 66000000; /* 66MHZ */ + break; + + case PMR_PCI_MODE_PCIX_100MHZ: + pPciMode->pciType = MV_PCIX; + pPciMode->pciSpeed = 100000000; /* 100MHZ */ + break; + + case PMR_PCI_MODE_PCIX_133MHZ: + pPciMode->pciType = MV_PCIX; + pPciMode->pciSpeed = 133000000; /* 133MHZ */ + break; + + default: + { + mvOsPrintf("mvPciModeGet: ERR. Non existing mode !!\n"); + return MV_ERROR; + } + } + + switch (pciMode & PMR_PCI_64_MASK) + { + case PMR_PCI_64_64BIT: + pPciMode->pciWidth = MV_PCI_64; + break; + + case PMR_PCI_64_32BIT: + pPciMode->pciWidth = MV_PCI_32; + break; + + default: + { + mvOsPrintf("mvPciModeGet: ERR. Non existing mode !!\n"); + return MV_ERROR; + } + } + + return MV_OK; +} + +/******************************************************************************* +* mvPciRetrySet - Set PCI retry counters +* +* DESCRIPTION: +* This function specifies the number of times the PCI controller +* retries a transaction before it quits. +* Applies to the PCI Master when acting as a requester. +* Applies to the PCI slave when acting as a completer (PCI-X mode). +* A 0x00 value means a "retry forever". +* +* INPUT: +* pciIf - PCI interface number. +* counter - Number of times PCI controller retry. Use counter value +* up to PRR_RETRY_CNTR_MAX. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciRetrySet(MV_U32 pciIf, MV_U32 counter) +{ + MV_U32 pciRetry; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciRetrySet: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + + if (counter >= PRR_RETRY_CNTR_MAX) + { + mvOsPrintf("mvPciRetrySet: ERR. Invalid counter: %d\n", counter); + return MV_BAD_PARAM; + + } + + /* Reading PCI retry register */ + pciRetry = MV_REG_READ(PCI_RETRY_REG(pciIf)); + + pciRetry &= ~PRR_RETRY_CNTR_MASK; + + pciRetry |= (counter << PRR_RETRY_CNTR_OFFS); + + /* write new value */ + MV_REG_WRITE(PCI_RETRY_REG(pciIf), pciRetry); + + return MV_OK; +} + + +/******************************************************************************* +* mvPciDiscardTimerSet - Set PCI discard timer +* +* DESCRIPTION: +* This function set PCI discard timer. +* In conventional PCI mode: +* Specifies the number of PCLK cycles the PCI slave keeps a non-accessed +* read buffers (non-completed delayed read) before invalidate the buffer. +* Set to '0' to disable the timer. The PCI slave waits for delayed +* read completion forever. +* In PCI-X mode: +* Specifies the number of PCLK cycles the PCI master waits for split +* completion transaction, before it invalidates the pre-allocated read +* buffer. +* Set to '0' to disable the timer. The PCI master waits for split +* completion forever. +* NOTE: Must be set to a number greater than MV_PCI_MAX_DISCARD_CLK, +* unless using the "wait for ever" setting 0x0. +* NOTE: Must not be updated while there are pending read requests. +* +* INPUT: +* pciIf - PCI interface number. +* pClkCycles - Number of PCI clock cycles. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciDiscardTimerSet(MV_U32 pciIf, MV_U32 pClkCycles) +{ + MV_U32 pciDiscardTimer; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciDiscardTimerSet: ERR. Invalid PCI interface %d\n", + pciIf); + return MV_BAD_PARAM; + } + + if (pClkCycles >= PDTR_TIMER_MIN) + { + mvOsPrintf("mvPciDiscardTimerSet: ERR. Invalid Clk value: %d\n", + pClkCycles); + return MV_BAD_PARAM; + + } + + /* Read PCI Discard Timer */ + pciDiscardTimer = MV_REG_READ(PCI_DISCARD_TIMER_REG(pciIf)); + + pciDiscardTimer &= ~PDTR_TIMER_MASK; + + pciDiscardTimer |= (pClkCycles << PDTR_TIMER_OFFS); + + /* Write new value */ + MV_REG_WRITE(PCI_DISCARD_TIMER_REG(pciIf), pciDiscardTimer); + + return MV_OK; + +} + +/* PCI Arbiter routines */ + +/******************************************************************************* +* mvPciArbEnable - PCI arbiter enable/disable +* +* DESCRIPTION: +* This fuction enable/disables a given PCI interface arbiter. +* NOTE: Arbiter setting can not be changed while in work. It should only +* be set once. +* INPUT: +* pciIf - PCI interface number. +* enable - Enable/disable parameter. If enable = MV_TRUE then enable. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvPciArbEnable(MV_U32 pciIf, MV_BOOL enable) +{ + MV_U32 regVal; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciArbEnable: ERR. Invalid PCI interface %d\n", pciIf); + return MV_ERROR; + } + + /* Set PCI Arbiter Control register according to default configuration */ + regVal = MV_REG_READ(PCI_ARBITER_CTRL_REG(pciIf)); + + /* Make sure arbiter disabled before changing its values */ + MV_REG_BIT_RESET(PCI_ARBITER_CTRL_REG(pciIf), PACR_ARB_ENABLE); + + regVal &= ~PCI_ARBITER_CTRL_DEFAULT_MASK; + + regVal |= PCI_ARBITER_CTRL_DEFAULT; /* Set default configuration */ + + if (MV_TRUE == enable) + { + regVal |= PACR_ARB_ENABLE; + } + else + { + regVal &= ~PACR_ARB_ENABLE; + } + + /* Write to register */ + MV_REG_WRITE(PCI_ARBITER_CTRL_REG(pciIf), regVal); + + return MV_OK; +} + + +/******************************************************************************* +* mvPciArbParkDis - Disable arbiter parking on agent +* +* DESCRIPTION: +* This function disables the PCI arbiter from parking on the given agent +* list. +* +* INPUT: +* pciIf - PCI interface number. +* pciAgentMask - When a bit in the mask is set to '1', parking on +* the associated PCI master is disabled. Mask bit +* refers to bit 0 - 6. For example disable parking on PCI +* agent 3 set pciAgentMask 0x4 (bit 3 is set). +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvPciArbParkDis(MV_U32 pciIf, MV_U32 pciAgentMask) +{ + MV_U32 pciArbiterCtrl; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciArbParkDis: ERR. Invalid PCI interface %d\n", pciIf); + return MV_ERROR; + } + + /* Reading Arbiter Control register */ + pciArbiterCtrl = MV_REG_READ(PCI_ARBITER_CTRL_REG(pciIf)); + + /* Arbiter must be disabled before changing parking */ + MV_REG_BIT_RESET(PCI_ARBITER_CTRL_REG(pciIf), PACR_ARB_ENABLE); + + /* do the change */ + pciArbiterCtrl &= ~PACR_PARK_DIS_MASK; + pciArbiterCtrl |= (pciAgentMask << PACR_PARK_DIS_OFFS); + + /* writing new value ( if th earbiter was enabled before the change */ + /* here it will be reenabled */ + MV_REG_WRITE(PCI_ARBITER_CTRL_REG(pciIf), pciArbiterCtrl); + + return MV_OK; +} + + +/******************************************************************************* +* mvPciArbBrokDetectSet - Set PCI arbiter broken detection +* +* DESCRIPTION: +* This function sets the maximum number of cycles that the arbiter +* waits for a PCI master to respond to its grant assertion. If a +* PCI agent fails to respond within this time, the PCI arbiter aborts +* the transaction and performs a new arbitration cycle. +* NOTE: Value must be greater than '1' for conventional PCI and +* greater than '5' for PCI-X. +* +* INPUT: +* pciIf - PCI interface number. +* pClkCycles - Number of PCI clock cycles. If equal to '0' the broken +* master detection is disabled. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciArbBrokDetectSet(MV_U32 pciIf, MV_U32 pClkCycles) +{ + MV_U32 pciArbiterCtrl; + MV_U32 pciMode; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciArbBrokDetectSet: ERR. Invalid PCI interface %d\n", + pciIf); + return MV_BAD_PARAM; + } + + /* Checking PCI mode and if pClkCycles is legal value */ + pciMode = MV_REG_READ(PCI_MODE_REG(pciIf)); + pciMode &= PMR_PCI_MODE_MASK; + + if (PMR_PCI_MODE_CONV == pciMode) + { + if (pClkCycles < PACR_BROKEN_VAL_CONV_MIN) + return MV_ERROR; + } + else + { + if (pClkCycles < PACR_BROKEN_VAL_PCIX_MIN) + return MV_ERROR; + } + + pClkCycles <<= PACR_BROKEN_VAL_OFFS; + + /* Reading Arbiter Control register */ + pciArbiterCtrl = MV_REG_READ(PCI_ARBITER_CTRL_REG(pciIf)); + pciArbiterCtrl &= ~PACR_BROKEN_VAL_MASK; + pciArbiterCtrl |= pClkCycles; + + /* Arbiter must be disabled before changing broken detection */ + MV_REG_BIT_RESET(PCI_ARBITER_CTRL_REG(pciIf), PACR_ARB_ENABLE); + + /* writing new value ( if th earbiter was enabled before the change */ + /* here it will be reenabled */ + + MV_REG_WRITE(PCI_ARBITER_CTRL_REG(pciIf), pciArbiterCtrl); + + return MV_OK; +} + +/* PCI configuration space read write */ + +/******************************************************************************* +* mvPciConfigRead - Read from configuration space +* +* DESCRIPTION: +* This function performs a 32 bit read from PCI configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to read from local bus segment, use +* bus number retrieved from mvPciLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pciIf - PCI interface number. +* bus - PCI segment bus number. +* dev - PCI device number. +* func - Function number. +* regOffs - Register offset. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit register data, 0xffffffff on error +* +*******************************************************************************/ +MV_U32 mvPciConfigRead (MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func, + MV_U32 regOff) +{ + MV_U32 pciData = 0; + + /* Parameter checking */ + if (PCI_DEFAULT_IF != pciIf) + { + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciConfigRead: ERR. Invalid PCI interface %d\n",pciIf); + return 0xFFFFFFFF; + } + } + + if (dev >= MAX_PCI_DEVICES) + { + DB(mvOsPrintf("mvPciConfigRead: ERR. device number illigal %d\n", dev)); + return 0xFFFFFFFF; + } + + if (func >= MAX_PCI_FUNCS) + { + DB(mvOsPrintf("mvPciConfigRead: ERR. function number illigal %d\n", func)); + return 0xFFFFFFFF; + } + + if (bus >= MAX_PCI_BUSSES) + { + DB(mvOsPrintf("mvPciConfigRead: ERR. bus number illigal %d\n", bus)); + return MV_ERROR; + } + + + /* Creating PCI address to be passed */ + pciData |= (bus << PCAR_BUS_NUM_OFFS); + pciData |= (dev << PCAR_DEVICE_NUM_OFFS); + pciData |= (func << PCAR_FUNC_NUM_OFFS); + pciData |= (regOff & PCAR_REG_NUM_MASK); + + pciData |= PCAR_CONFIG_EN; + + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE(PCI_CONFIG_ADDR_REG(pciIf), pciData); + + /* In order to let the PCI controller absorbed the address of the read */ + /* transaction we perform a validity check that the address was written */ + if(pciData != MV_REG_READ(PCI_CONFIG_ADDR_REG(pciIf))) + { + return MV_ERROR; + } + /* Read the Data returned in the PCI Data register */ + pciData = MV_REG_READ(PCI_CONFIG_DATA_REG(pciIf)); + + return pciData; +} + +/******************************************************************************* +* mvPciConfigWrite - Write to configuration space +* +* DESCRIPTION: +* This function performs a 32 bit write to PCI configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to write to local bus segment, use +* bus number retrieved from mvPciLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pciIf - PCI interface number. +* bus - PCI segment bus number. +* dev - PCI device number. +* func - Function number. +* regOffs - Register offset. +* data - 32bit data. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data) +{ + MV_U32 pciData = 0; + + /* Parameter checking */ + if (PCI_DEFAULT_IF != pciIf) + { + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciConfigWrite: ERR. Invalid PCI interface %d\n", + pciIf); + return 0xFFFFFFFF; + } + } + + if (dev >= MAX_PCI_DEVICES) + { + mvOsPrintf("mvPciConfigWrite: ERR. device number illigal %d\n",dev); + return MV_BAD_PARAM; + } + + if (func >= MAX_PCI_FUNCS) + { + mvOsPrintf("mvPciConfigWrite: ERR. function number illigal %d\n", func); + return MV_ERROR; + } + + if (bus >= MAX_PCI_BUSSES) + { + mvOsPrintf("mvPciConfigWrite: ERR. bus number illigal %d\n", bus); + return MV_ERROR; + } + + /* Creating PCI address to be passed */ + pciData |= (bus << PCAR_BUS_NUM_OFFS); + pciData |= (dev << PCAR_DEVICE_NUM_OFFS); + pciData |= (func << PCAR_FUNC_NUM_OFFS); + pciData |= (regOff & PCAR_REG_NUM_MASK); + + pciData |= PCAR_CONFIG_EN; + + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE(PCI_CONFIG_ADDR_REG(pciIf), pciData); + + /* In order to let the PCI controller absorbed the address of the read */ + /* transaction we perform a validity check that the address was written */ + if(pciData != MV_REG_READ(PCI_CONFIG_ADDR_REG(pciIf))) + { + return MV_ERROR; + } + + /* Write the Data passed to the PCI Data register */ + MV_REG_WRITE(PCI_CONFIG_DATA_REG(pciIf), data); + + return MV_OK; +} + +/******************************************************************************* +* mvPciMasterEnable - Enable/disale PCI interface master transactions. +* +* DESCRIPTION: +* This function performs read modified write to PCI command status +* (offset 0x4) to set/reset bit 2. After this bit is set, the PCI +* master is allowed to gain ownership on the bus, otherwise it is +* incapable to do so. +* +* INPUT: +* pciIf - PCI interface number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciMasterEnable(MV_U32 pciIf, MV_BOOL enable) +{ + MV_U32 pciCommandStatus; + MV_U32 RegOffs; + MV_U32 localBus; + MV_U32 localDev; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciMasterEnable: ERR. Invalid PCI interface %d\n", pciIf); + return MV_ERROR; + } + + localBus = mvPciLocalBusNumGet(pciIf); + localDev = mvPciLocalDevNumGet(pciIf); + + RegOffs = PCI_STATUS_AND_COMMAND; + + pciCommandStatus = mvPciConfigRead(pciIf, localBus, localDev, 0, RegOffs); + + if (MV_TRUE == enable) + { + pciCommandStatus |= PSCR_MASTER_EN; + } + else + { + pciCommandStatus &= ~PSCR_MASTER_EN; + } + + mvPciConfigWrite(pciIf, localBus, localDev, 0, RegOffs, pciCommandStatus); + + return MV_OK; +} + + +/******************************************************************************* +* mvPciSlaveEnable - Enable/disale PCI interface slave transactions. +* +* DESCRIPTION: +* This function performs read modified write to PCI command status +* (offset 0x4) to set/reset bit 0 and 1. After those bits are set, +* the PCI slave is allowed to respond to PCI IO space access (bit 0) +* and PCI memory space access (bit 1). +* +* INPUT: +* pciIf - PCI interface number. +* dev - PCI device number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciSlaveEnable(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_BOOL enable) +{ + MV_U32 pciCommandStatus; + MV_U32 RegOffs; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciSlaveEnable: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + if (dev >= MAX_PCI_DEVICES) + { + mvOsPrintf("mvPciLocalDevNumSet: ERR. device number illigal %d\n", dev); + return MV_BAD_PARAM; + + } + + RegOffs = PCI_STATUS_AND_COMMAND; + + pciCommandStatus=mvPciConfigRead(pciIf, bus, dev, 0, RegOffs); + + if (MV_TRUE == enable) + { + pciCommandStatus |= (PSCR_IO_EN | PSCR_MEM_EN); + } + else + { + pciCommandStatus &= ~(PSCR_IO_EN | PSCR_MEM_EN); + } + + mvPciConfigWrite(pciIf, bus, dev, 0, RegOffs, pciCommandStatus); + + return MV_OK; +} + +/******************************************************************************* +* mvPciLocalBusNumSet - Set PCI interface local bus number. +* +* DESCRIPTION: +* This function sets given PCI interface its local bus number. +* Note: In case the PCI interface is PCI-X, the information is read-only. +* +* INPUT: +* pciIf - PCI interface number. +* busNum - Bus number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_NOT_ALLOWED in case PCI interface is PCI-X. +* MV_BAD_PARAM on bad parameters , +* otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum) +{ + MV_U32 pciP2PConfig; + MV_PCI_MODE pciMode; + MV_U32 localBus; + MV_U32 localDev; + + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciLocalBusNumSet: ERR. Invalid PCI interface %d\n",pciIf); + return MV_BAD_PARAM; + } + if (busNum >= MAX_PCI_BUSSES) + { + mvOsPrintf("mvPciLocalBusNumSet: ERR. bus number illigal %d\n", busNum); + return MV_ERROR; + + } + + localBus = mvPciLocalBusNumGet(pciIf); + localDev = mvPciLocalDevNumGet(pciIf); + + + /* PCI interface mode */ + mvPciModeGet(pciIf, &pciMode); + + /* if PCI type is PCI-X then it is not allowed to change the dev number */ + if (MV_PCIX == pciMode.pciType) + { + pciP2PConfig = mvPciConfigRead(pciIf, localBus, localDev, 0, PCIX_STATUS ); + + pciP2PConfig &= ~PXS_BN_MASK; + + pciP2PConfig |= (busNum << PXS_BN_OFFS) & PXS_BN_MASK; + + mvPciConfigWrite(pciIf, localBus, localDev, 0, PCIX_STATUS,pciP2PConfig ); + + } + else + { + pciP2PConfig = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf)); + + pciP2PConfig &= ~PPCR_BUS_NUM_MASK; + + pciP2PConfig |= (busNum << PPCR_BUS_NUM_OFFS) & PPCR_BUS_NUM_MASK; + + MV_REG_WRITE(PCI_P2P_CONFIG_REG(pciIf), pciP2PConfig); + + } + + + return MV_OK; +} + + +/******************************************************************************* +* mvPciLocalBusNumGet - Get PCI interface local bus number. +* +* DESCRIPTION: +* This function gets the local bus number of a given PCI interface. +* +* INPUT: +* pciIf - PCI interface number. +* +* OUTPUT: +* None. +* +* RETURN: +* Local bus number.0xffffffff on Error +* +*******************************************************************************/ +MV_U32 mvPciLocalBusNumGet(MV_U32 pciIf) +{ + MV_U32 pciP2PConfig; + + /* Parameter checking */ + if (PCI_DEFAULT_IF != pciIf) + { + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciLocalBusNumGet: ERR. Invalid PCI interface %d\n", + pciIf); + return 0xFFFFFFFF; + } + } + + pciP2PConfig = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf)); + pciP2PConfig &= PPCR_BUS_NUM_MASK; + return (pciP2PConfig >> PPCR_BUS_NUM_OFFS); +} + + +/******************************************************************************* +* mvPciLocalDevNumSet - Set PCI interface local device number. +* +* DESCRIPTION: +* This function sets given PCI interface its local device number. +* Note: In case the PCI interface is PCI-X, the information is read-only. +* +* INPUT: +* pciIf - PCI interface number. +* devNum - Device number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_NOT_ALLOWED in case PCI interface is PCI-X. MV_BAD_PARAM on bad parameters , +* otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum) +{ + MV_U32 pciP2PConfig; + MV_PCI_MODE pciMode; + MV_U32 localBus; + MV_U32 localDev; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciLocalDevNumSet: ERR. Invalid PCI interface %d\n",pciIf); + return MV_BAD_PARAM; + } + if (devNum >= MAX_PCI_DEVICES) + { + mvOsPrintf("mvPciLocalDevNumSet: ERR. device number illigal %d\n", + devNum); + return MV_BAD_PARAM; + + } + + localBus = mvPciLocalBusNumGet(pciIf); + localDev = mvPciLocalDevNumGet(pciIf); + + /* PCI interface mode */ + mvPciModeGet(pciIf, &pciMode); + + /* if PCI type is PCIX then it is not allowed to change the dev number */ + if (MV_PCIX == pciMode.pciType) + { + pciP2PConfig = mvPciConfigRead(pciIf, localBus, localDev, 0, PCIX_STATUS ); + + pciP2PConfig &= ~PXS_DN_MASK; + + pciP2PConfig |= (devNum << PXS_DN_OFFS) & PXS_DN_MASK; + + mvPciConfigWrite(pciIf,localBus, localDev, 0, PCIX_STATUS,pciP2PConfig ); + } + else + { + pciP2PConfig = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf)); + + pciP2PConfig &= ~PPCR_DEV_NUM_MASK; + + pciP2PConfig |= (devNum << PPCR_DEV_NUM_OFFS) & PPCR_DEV_NUM_MASK; + + MV_REG_WRITE(PCI_P2P_CONFIG_REG(pciIf), pciP2PConfig); + } + + return MV_OK; +} + +/******************************************************************************* +* mvPciLocalDevNumGet - Get PCI interface local device number. +* +* DESCRIPTION: +* This function gets the local device number of a given PCI interface. +* +* INPUT: +* pciIf - PCI interface number. +* +* OUTPUT: +* None. +* +* RETURN: +* Local device number. 0xffffffff on Error +* +*******************************************************************************/ +MV_U32 mvPciLocalDevNumGet(MV_U32 pciIf) +{ + MV_U32 pciP2PConfig; + + /* Parameter checking */ + + if (PCI_DEFAULT_IF != pciIf) + { + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciLocalDevNumGet: ERR. Invalid PCI interface %d\n", + pciIf); + return 0xFFFFFFFF; + } + } + + pciP2PConfig = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf)); + + pciP2PConfig &= PPCR_DEV_NUM_MASK; + + return (pciP2PConfig >> PPCR_DEV_NUM_OFFS); +} + + + + diff --git a/board/mv_feroceon/mv_hal/pci/mvPci.h b/board/mv_feroceon/mv_hal/pci/mvPci.h new file mode 100644 index 0000000..4746336 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pci/mvPci.h @@ -0,0 +1,185 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCPCIH +#define __INCPCIH + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "pci/mvPciRegs.h" + + +/* NOTE not supported in this driver: + + Built In Self Test (BIST) + Vital Product Data (VPD) + Message Signaled Interrupt (MSI) + Power Management + Compact PCI Hot Swap + Header retarget + +Registers not supported: +1) PCI DLL Status and Control (PCI0 0x1D20, PCI1 0x1DA0) +2) PCI/MPP Pads Calibration (CI0/MPP[31:16] 0x1D1C, PCI1/MPP[15:0] 0X1D9C) +*/ + +/* defines */ +/* The number of supported PCI interfaces depend on Marvell controller */ +/* device number. This device number ID is located on the PCI unit */ +/* configuration header. This creates a loop where calling PCI */ +/* configuration read/write routine results a call to get PCI configuration */ +/* information etc. This macro defines a default PCI interface. This PCI */ +/* interface is sure to exist. */ +#define PCI_DEFAULT_IF 0 + + +/* typedefs */ +/* The Marvell controller supports both conventional PCI and PCI-X. */ +/* This enumeration describes the PCI type. */ +typedef enum _mvPciType +{ + MV_PCI_CONV, /* Conventional PCI */ + MV_PCIX /* PCI-X */ +}MV_PCI_TYPE; + +typedef enum _mvPciMod +{ + MV_PCI_MOD_HOST, + MV_PCI_MOD_DEVICE +}MV_PCI_MOD; + + +/* The Marvell controller supports both PCI width of 32 and 64 bit. */ +/* This enumerator describes PCI width */ +typedef enum _mvPciWidth +{ + MV_PCI_32, /* PCI width 32bit */ + MV_PCI_64 /* PCI width 64bit */ +}MV_PCI_WIDTH; + +/* This structure describes the PCI unit configured type, speed and width. */ +typedef struct _mvPciMode +{ + MV_PCI_TYPE pciType; /* PCI type */ + MV_U32 pciSpeed; /* Assuming PCI base clock on board is 33MHz */ + MV_PCI_WIDTH pciWidth; /* PCI bus width */ +}MV_PCI_MODE; + +/* mvPciInit - Initialize PCI interfaces*/ +MV_VOID mvPciHalInit(MV_U32 pciIf, MV_PCI_MOD pciIfmod); + +/* mvPciCommandSet - Set PCI comman register value.*/ +MV_STATUS mvPciCommandSet(MV_U32 pciIf, MV_U32 command); + +/* mvPciModeGet - Get PCI interface mode.*/ +MV_STATUS mvPciModeGet(MV_U32 pciIf, MV_PCI_MODE *pPciMode); + +/* mvPciRetrySet - Set PCI retry counters*/ +MV_STATUS mvPciRetrySet(MV_U32 pciIf, MV_U32 counter); + +/* mvPciDiscardTimerSet - Set PCI discard timer*/ +MV_STATUS mvPciDiscardTimerSet(MV_U32 pciIf, MV_U32 pClkCycles); + +/* mvPciArbEnable - PCI arbiter enable/disable*/ +MV_STATUS mvPciArbEnable(MV_U32 pciIf, MV_BOOL enable); + +/* mvPciArbParkDis - Disable arbiter parking on agent */ +MV_STATUS mvPciArbParkDis(MV_U32 pciIf, MV_U32 pciAgentMask); + +/* mvPciArbBrokDetectSet - Set PCI arbiter broken detection */ +MV_STATUS mvPciArbBrokDetectSet(MV_U32 pciIf, MV_U32 pClkCycles); + +/* mvPciConfigRead - Read from configuration space */ +MV_U32 mvPciConfigRead (MV_U32 pciIf, MV_U32 bus, MV_U32 dev, + MV_U32 func,MV_U32 regOff); + +/* mvPciConfigWrite - Write to configuration space */ +MV_STATUS mvPciConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data); + +/* mvPciMasterEnable - Enable/disale PCI interface master transactions.*/ +MV_STATUS mvPciMasterEnable(MV_U32 pciIf, MV_BOOL enable); + +/* mvPciSlaveEnable - Enable/disale PCI interface slave transactions.*/ +MV_STATUS mvPciSlaveEnable(MV_U32 pciIf, MV_U32 bus, MV_U32 dev,MV_BOOL enable); + +/* mvPciLocalBusNumSet - Set PCI interface local bus number.*/ +MV_STATUS mvPciLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum); + +/* mvPciLocalBusNumGet - Get PCI interface local bus number.*/ +MV_U32 mvPciLocalBusNumGet(MV_U32 pciIf); + +/* mvPciLocalDevNumSet - Set PCI interface local device number.*/ +MV_STATUS mvPciLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum); + +/* mvPciLocalDevNumGet - Get PCI interface local device number.*/ +MV_U32 mvPciLocalDevNumGet(MV_U32 pciIf); + + +#endif /* #ifndef __INCPCIH */ + + + diff --git a/board/mv_feroceon/mv_hal/pci/mvPciRegs.h b/board/mv_feroceon/mv_hal/pci/mvPciRegs.h new file mode 100644 index 0000000..89d0ef1 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pci/mvPciRegs.h @@ -0,0 +1,411 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCPCIREGSH +#define __INCPCIREGSH + + +#include "pci-if/mvPciIfRegs.h" +/* defines */ +#define MAX_PCI_DEVICES 32 +#define MAX_PCI_FUNCS 8 +#define MAX_PCI_BUSSES 128 + +/* enumerators */ + +/* This enumerator described the possible PCI slave targets. */ +/* PCI slave targets are designated memory/IO address spaces that the */ +/* PCI slave targets can access. They are also refered as "targets" */ +/* this enumeratoe order is determined by the content of : + PCI_BASE_ADDR_ENABLE_REG */ + + +/* registers offsetes defines */ + + + +/*************************/ +/* PCI control registers */ +/*************************/ +/* maen : should add new registers */ +#define PCI_CMD_REG(pciIf) (0x30c00 + ((pciIf) * 0x80)) +#define PCI_MODE_REG(pciIf) (0x30d00 + ((pciIf) * 0x80)) +#define PCI_RETRY_REG(pciIf) (0x30c04 + ((pciIf) * 0x80)) +#define PCI_DISCARD_TIMER_REG(pciIf) (0x30d04 + ((pciIf) * 0x80)) +#define PCI_ARBITER_CTRL_REG(pciIf) (0x31d00 + ((pciIf) * 0x80)) +#define PCI_P2P_CONFIG_REG(pciIf) (0x31d14 + ((pciIf) * 0x80)) +#define PCI_ACCESS_CTRL_BASEL_REG(pciIf, targetWin) \ + (0x31e00 + ((pciIf) * 0x80) + ((targetWin) * 0x10)) +#define PCI_ACCESS_CTRL_BASEH_REG(pciIf, targetWin) \ + (0x31e04 + ((pciIf) * 0x80) + ((targetWin) * 0x10)) +#define PCI_ACCESS_CTRL_SIZE_REG(pciIf, targetWin) \ + (0x31e08 + ((pciIf) * 0x80) + ((targetWin) * 0x10)) + +#define PCI_DLL_CTRL_REG(pciIf) (0x31d20 + ((pciIf) * 0x80)) + +/* PCI Dll Control (PDC)*/ +#define PDC_DLL_EN BIT0 + + +/* PCI Command Register (PCR) */ +#define PCR_MASTER_BYTE_SWAP_EN BIT0 +#define PCR_MASTER_WR_COMBINE_EN BIT4 +#define PCR_MASTER_RD_COMBINE_EN BIT5 +#define PCR_MASTER_WR_TRIG_WHOLE BIT6 +#define PCR_MASTER_RD_TRIG_WHOLE BIT7 +#define PCR_MASTER_MEM_RD_LINE_EN BIT8 +#define PCR_MASTER_MEM_RD_MULT_EN BIT9 +#define PCR_MASTER_WORD_SWAP_EN BIT10 +#define PCR_SLAVE_WORD_SWAP_EN BIT11 +#define PCR_NS_ACCORDING_RCV_TRANS BIT14 +#define PCR_MASTER_PCIX_REQ64N_EN BIT15 +#define PCR_SLAVE_BYTE_SWAP_EN BIT16 +#define PCR_MASTER_DAC_EN BIT17 +#define PCR_MASTER_M64_ALLIGN BIT18 +#define PCR_ERRORS_PROPAGATION_EN BIT19 +#define PCR_SLAVE_SWAP_ENABLE BIT20 +#define PCR_MASTER_SWAP_ENABLE BIT21 +#define PCR_MASTER_INT_SWAP_EN BIT22 +#define PCR_LOOP_BACK_ENABLE BIT23 +#define PCR_SLAVE_INTREG_SWAP_OFFS 24 +#define PCR_SLAVE_INTREG_SWAP_MASK 0x3 +#define PCR_SLAVE_INTREG_BYTE_SWAP \ + (MV_BYTE_SWAP << PCR_SLAVE_INT_REG_SWAP_MASK) +#define PCR_SLAVE_INTREG_NO_SWAP \ + (MV_NO_SWAP << PCR_SLAVE_INT_REG_SWAP_MASK) +#define PCR_SLAVE_INTREG_BYTE_WORD \ + (MV_BYTE_WORD_SWAP << PCR_SLAVE_INT_REG_SWAP_MASK) +#define PCR_SLAVE_INTREG_WORD_SWAP \ + (MV_WORD_SWAP << PCR_SLAVE_INT_REG_SWAP_MASK) +#define PCR_RESET_REASSERTION_EN BIT26 +#define PCR_PCI_TO_CPU_REG_ORDER_EN BIT28 +#define PCR_CPU_TO_PCI_ORDER_EN BIT29 +#define PCR_PCI_TO_CPU_ORDER_EN BIT30 + +/* PCI Mode Register (PMR) */ +#define PMR_PCI_ID_OFFS 0 /* PCI Interface ID */ +#define PMR_PCI_ID_MASK (0x1 << PMR_PCI_ID_OFFS) +#define PMR_PCI_ID_PCI(pciNum) ((pciNum) << PCI_MODE_PCIID_OFFS) + +#define PMR_PCI_64_OFFS 2 /* 64-bit PCI Interface */ +#define PMR_PCI_64_MASK (0x1 << PMR_PCI_64_OFFS) +#define PMR_PCI_64_64BIT (0x1 << PMR_PCI_64_OFFS) +#define PMR_PCI_64_32BIT (0x0 << PMR_PCI_64_OFFS) + +#define PMR_PCI_MODE_OFFS 4 /* PCI interface mode of operation */ +#define PMR_PCI_MODE_MASK (0x3 << PMR_PCI_MODE_OFFS) +#define PMR_PCI_MODE_CONV (0x0 << PMR_PCI_MODE_OFFS) +#define PMR_PCI_MODE_PCIX_66MHZ (0x1 << PMR_PCI_MODE_OFFS) +#define PMR_PCI_MODE_PCIX_100MHZ (0x2 << PMR_PCI_MODE_OFFS) +#define PMR_PCI_MODE_PCIX_133MHZ (0x3 << PMR_PCI_MODE_OFFS) + +#define PMR_EXP_ROM_SUPPORT BIT8 /* Expansion ROM Active */ + +#define PMR_PCI_RESET_OFFS 31 /* PCI Interface Reset Indication */ +#define PMR_PCI_RESET_MASK (0x1 << PMR_PCI_RESET_OFFS) +#define PMR_PCI_RESET_PCIXRST (0x0 << PMR_PCI_RESET_OFFS) + + +/* PCI Retry Register (PRR) */ +#define PRR_RETRY_CNTR_OFFS 16 /* Retry Counter */ +#define PRR_RETRY_CNTR_MAX 0xff +#define PRR_RETRY_CNTR_MASK (PRR_RETRY_CNTR_MAX << PRR_RETRY_CNTR_OFFS) + + +/* PCI Discard Timer Register (PDTR) */ +#define PDTR_TIMER_OFFS 0 /* Timer */ +#define PDTR_TIMER_MAX 0xffff +#define PDTR_TIMER_MIN 0x7F +#define PDTR_TIMER_MASK (PDTR_TIMER_MAX << PDTR_TIMER_OFFS) + + +/* PCI Arbiter Control Register (PACR) */ +#define PACR_BROKEN_DETECT_EN BIT1 /* Broken Detection Enable */ + +#define PACR_BROKEN_VAL_OFFS 3 /* Broken Value */ +#define PACR_BROKEN_VAL_MASK (0xf << PACR_BROKEN_VAL_OFFS) +#define PACR_BROKEN_VAL_CONV_MIN 0x2 +#define PACR_BROKEN_VAL_PCIX_MIN 0x6 + +#define PACR_PARK_DIS_OFFS 14 /* Parking Disable */ +#define PACR_PARK_DIS_MAX_AGENT 0x3f +#define PACR_PARK_DIS_MASK (PACR_PARK_DIS_MAX_AGENT<= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexModeGet: ERR. Invalid PEX interface %d\n",pexIf); + return MV_ERROR; + } + } + + pexData = MV_REG_READ(PEX_CTRL_REG(pexIf)); + + switch (pexData & PXCR_DEV_TYPE_CTRL_MASK) + { + case PXCR_DEV_TYPE_CTRL_CMPLX: + pexMode->pexType = MV_PEX_ROOT_COMPLEX; + break; + case PXCR_DEV_TYPE_CTRL_POINT: + pexMode->pexType = MV_PEX_END_POINT; + break; + + } + + /* Check if we have link */ + if (MV_REG_READ(PEX_STATUS_REG(pexIf)) & PXSR_DL_DOWN) + { + pexMode->pexLinkUp = MV_FALSE; + + /* If there is no link, the auto negotiation data is worthless */ + pexMode->pexWidth = MV_PEX_WITDH_INVALID; + } + else + { + pexMode->pexLinkUp = MV_TRUE; + + /* We have link. The link width is now valid */ + pexData = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, PEX_LINK_CTRL_STAT_REG)); + pexMode->pexWidth = ((pexData & PXLCSR_NEG_LNK_WDTH_MASK) >> + PXLCSR_NEG_LNK_WDTH_OFFS); + } + + return MV_OK; +} + + +/* PEX configuration space read write */ + +/******************************************************************************* +* mvPexConfigRead - Read from configuration space +* +* DESCRIPTION: +* This function performs a 32 bit read from PEX configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to read from local bus segment, use +* bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pexIf - PEX interface number. +* bus - PEX segment bus number. +* dev - PEX device number. +* func - Function number. +* regOffs - Register offset. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit register data, 0xffffffff on error +* +*******************************************************************************/ +MV_U32 mvPexConfigRead (MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, + MV_U32 regOff) +{ +#if defined(VIRTUAL_BRIDGE_SUPPORT) + return mvPexVrtBrgConfigRead (pexIf, bus, dev, func, regOff); +#else + MV_U32 pexData = 0; + MV_U32 localDev,localBus; + + /* Parameter checking */ + if (PEX_DEFAULT_IF != pexIf) + { + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexConfigRead: ERR. Invalid PEX interface %d\n",pexIf); + return 0xFFFFFFFF; + } + } + + if (dev >= MAX_PEX_DEVICES) + { + mvOsPrintf("mvPexConfigRead: ERR. device number illigal %d\n", dev); + return 0xFFFFFFFF; + } + + if (func >= MAX_PEX_FUNCS) + { + mvOsPrintf("mvPexConfigRead: ERR. function num illigal %d\n", func); + return 0xFFFFFFFF; + } + + if (bus >= MAX_PEX_BUSSES) + { + mvOsPrintf("mvPexConfigRead: ERR. bus number illigal %d\n", bus); + return MV_ERROR; + } + + DB(mvOsPrintf("mvPexConfigRead: pexIf %d, bus %d, dev %d, func %d, regOff 0x%x\n", + pexIf, bus, dev, func, regOff)); + + localDev = mvPexLocalDevNumGet(pexIf); + localBus = mvPexLocalBusNumGet(pexIf); + + /* Speed up the process. In case on no link, return MV_ERROR */ + if ((dev != localDev) || (bus != localBus)) + { + pexData = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + if ((pexData & PXSR_DL_DOWN)) + { + return MV_ERROR; + } + } + + /* in PCI Express we have only one device number */ + /* and this number is the first number we encounter + else that the localDev*/ + /* spec pex define return on config read/write on any device */ + if (bus == localBus) + { + if (localDev == 0) + { + /* if local dev is 0 then the first number we encounter + after 0 is 1 */ + if ((dev != 1)&&(dev != localDev)) + { + return MV_ERROR; + } + } + else + { + /* if local dev is not 0 then the first number we encounter + is 0 */ + + if ((dev != 0)&&(dev != localDev)) + { + return MV_ERROR; + } + } + if(func != 0 ) /* i.e bridge */ + { + return MV_ERROR; + } + } + + + /* Creating PEX address to be passed */ + pexData = (bus << PXCAR_BUS_NUM_OFFS); + pexData |= (dev << PXCAR_DEVICE_NUM_OFFS); + pexData |= (func << PXCAR_FUNC_NUM_OFFS); + pexData |= (regOff & PXCAR_REG_NUM_MASK); /* lgacy register space */ + /* extended register space */ + pexData |=(((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >> + PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS); + + pexData |= PXCAR_CONFIG_EN; + + /* Write the address to the PEX configuration address register */ + MV_REG_WRITE(PEX_CFG_ADDR_REG(pexIf), pexData); + + DB(mvOsPrintf("mvPexConfigRead:address pexData=%x ",pexData)); + + + /* In order to let the PEX controller absorbed the address of the read */ + /* transaction we perform a validity check that the address was written */ + if(pexData != MV_REG_READ(PEX_CFG_ADDR_REG(pexIf))) + { + return MV_ERROR; + } + + /* cleaning Master Abort */ + MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_STATUS_AND_COMMAND), + PXSAC_MABORT); +#if 0 + /* Guideline (GL# PCI Express-1) Erroneous Read Data on Configuration */ + /* This guideline is relevant for all devices except of the following devices: + 88F5281-BO and above, 88F5181L-A0 and above, 88F1281 A0 and above + 88F6183 A0 and above, 88F6183L */ + if ( ( (dev != localDev) || (bus != localBus) ) && + ( + !(MV_5281_DEV_ID == mvCtrlModelGet())&& + !((MV_5181_DEV_ID == mvCtrlModelGet())&& (mvCtrlRevGet() >= MV_5181L_A0_REV))&& + !(MV_1281_DEV_ID == mvCtrlModelGet())&& + !(MV_6183_DEV_ID == mvCtrlModelGet())&& + !(MV_6183L_DEV_ID == mvCtrlModelGet())&& + !(MV_6281_DEV_ID == mvCtrlModelGet())&& + !(MV_6192_DEV_ID == mvCtrlModelGet())&& + !(MV_6190_DEV_ID == mvCtrlModelGet())&& + !(MV_6180_DEV_ID == mvCtrlModelGet())&& + !(MV_78XX0_DEV_ID == mvCtrlModelGet()) + )) + { + + /* PCI-Express configuration read work-around */ + + /* we will use one of the Punit (AHBToMbus) windows to access the xbar + and read the data from there */ + /* + Need to configure the 2 free Punit (AHB to MBus bridge) + address decoding windows: + Configure the flash Window to handle Configuration space requests + for PEX0/1: + 1. write 0x7931/0x7941 to the flash window and the size, + 79-xbar attr (pci cfg), 3/4-xbar target (pex0/1), 1-WinEn + 2. write base to flash window + + Configuration transactions from the CPU should write/read the data + to/from address of the form: + addr[31:28] = 0x5 (for PEX0) or 0x6 (for PEX1) + addr[27:24] = extended register number + addr[23:16] = bus number + addr[15:11] = device number + addr[10:8] = function number + addr[7:0] = register number + */ + + #include "ctrlEnv/sys/mvAhbToMbus.h" + { + MV_U32 winNum; + MV_AHB_TO_MBUS_DEC_WIN originWin; + MV_U32 pciAddr=0; + MV_U32 remapLow=0,remapHigh=0; + + /* + We will use DEV_CS2\Flash window for this workarround + */ + + winNum = mvAhbToMbusWinTargetGet(PEX_CONFIG_RW_WA_TARGET); + + /* save remap values if exist */ + if ((1 == winNum)||(0 == winNum)) + { + remapLow = MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum)); + remapHigh = MV_REG_READ(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum)); + + } + + + /* save the original window values */ + mvAhbToMbusWinGet(winNum,&originWin); + + if (PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES) + { + /* set the window as xbar window */ + if (pexIf) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), + (0x7931 | (((originWin.addrWin.size >> 16)-1) ) << 16)); + } + else + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), + (0x7941 | (((originWin.addrWin.size >> 16)-1) ) << 16)); + } + + MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), + originWin.addrWin.baseLow); + + /*pciAddr = originWin.addrWin.baseLow;*/ + pciAddr = (MV_U32)CPU_MEMIO_UNCACHED_ADDR( + (MV_U32)originWin.addrWin.baseLow); + + } + else + { + /* set the window as xbar window */ + if (pexIf) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), + (0x7931 | (((PEX_CONFIG_RW_WA_SIZE >> 16)-1) ) << 16)); + } + else + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), + (0x7941 | (((PEX_CONFIG_RW_WA_SIZE >> 16)-1) ) << 16)); + } + + MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), + PEX_CONFIG_RW_WA_BASE); + + pciAddr = (MV_U32)CPU_MEMIO_UNCACHED_ADDR(PEX_CONFIG_RW_WA_BASE); + } + + + /* remap should be as base */ + if ((1 == winNum)||(0 == winNum)) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum),pciAddr); + MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum),0); + + } + + /* extended register space */ + pciAddr |= (bus << 16); + pciAddr |= (dev << 11); + pciAddr |= (func << 8); + pciAddr |= (regOff & PXCAR_REG_NUM_MASK); /* lgacy register space */ + + pexData = *(MV_U32*)pciAddr; + pexData = MV_32BIT_LE(pexData); /* Data always in LE */ + + /* restore the original window values */ + mvAhbToMbusWinSet(winNum,&originWin); + + /* restore original remap values*/ + if ((1 == winNum)||(0 == winNum)) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum),remapLow); + MV_REG_WRITE(AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum),remapHigh); + + } + } + } + else +#endif + { + /* Read the Data returned in the PEX Data register */ + pexData = MV_REG_READ(PEX_CFG_DATA_REG(pexIf)); + + } + + DB(mvOsPrintf("mvPexConfigRead: got : %x \n",pexData)); + + return pexData; +#endif +} + +/******************************************************************************* +* mvPexConfigWrite - Write to configuration space +* +* DESCRIPTION: +* This function performs a 32 bit write to PEX configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to write to local bus segment, use +* bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pexIf - PEX interface number. +* bus - PEX segment bus number. +* dev - PEX device number. +* func - Function number. +* regOffs - Register offset. +* data - 32bit data. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data) +{ +#if defined(VIRTUAL_BRIDGE_SUPPORT) + return mvPexVrtBrgConfigWrite (pexIf, bus, dev, func, regOff, data); +#else + MV_U32 pexData = 0; + MV_U32 localDev,localBus; + + /* Parameter checking */ + if (PEX_DEFAULT_IF != pexIf) + { + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexConfigWrite: ERR. Invalid PEX interface %d\n", + pexIf); + return MV_ERROR; + } + } + + if (dev >= MAX_PEX_DEVICES) + { + mvOsPrintf("mvPexConfigWrite: ERR. device number illigal %d\n",dev); + return MV_BAD_PARAM; + } + + if (func >= MAX_PEX_FUNCS) + { + mvOsPrintf("mvPexConfigWrite: ERR. function number illigal %d\n", func); + return MV_ERROR; + } + + if (bus >= MAX_PEX_BUSSES) + { + mvOsPrintf("mvPexConfigWrite: ERR. bus number illigal %d\n", bus); + return MV_ERROR; + } + + + + localDev = mvPexLocalDevNumGet(pexIf); + localBus = mvPexLocalBusNumGet(pexIf); + + + /* in PCI Express we have only one device number other than ourselves*/ + /* and this number is the first number we encounter + else than the localDev that can be any valid dev number*/ + /* pex spec define return on config read/write on any device */ + if (bus == localBus) + { + + if (localDev == 0) + { + /* if local dev is 0 then the first number we encounter + after 0 is 1 */ + if ((dev != 1)&&(dev != localDev)) + { + return MV_ERROR; + } + + } + else + { + /* if local dev is not 0 then the first number we encounter + is 0 */ + + if ((dev != 0)&&(dev != localDev)) + { + return MV_ERROR; + } + } + + + } + + /* if we are not accessing ourselves , then check the link */ + if ((dev != localDev) || (bus != localBus) ) + { + /* workarround */ + /* when no link return MV_ERROR */ + + pexData = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + if ((pexData & PXSR_DL_DOWN)) + { + return MV_ERROR; + } + + } + + pexData =0; + + /* Creating PEX address to be passed */ + pexData |= (bus << PXCAR_BUS_NUM_OFFS); + pexData |= (dev << PXCAR_DEVICE_NUM_OFFS); + pexData |= (func << PXCAR_FUNC_NUM_OFFS); + pexData |= (regOff & PXCAR_REG_NUM_MASK); /* lgacy register space */ + /* extended register space */ + pexData |=(((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >> + PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS); + pexData |= PXCAR_CONFIG_EN; + + DB(mvOsPrintf("mvPexConfigWrite: If=%x bus=%x func=%x dev=%x regOff=%x data=%x \n", + pexIf,bus,func,dev,regOff,data,pexData) ); + + /* Write the address to the PEX configuration address register */ + MV_REG_WRITE(PEX_CFG_ADDR_REG(pexIf), pexData); + + /* Clear CPU pipe. Important where CPU can perform OOO execution */ + CPU_PIPE_FLUSH; + + /* In order to let the PEX controller absorbed the address of the read */ + /* transaction we perform a validity check that the address was written */ + if(pexData != MV_REG_READ(PEX_CFG_ADDR_REG(pexIf))) + { + return MV_ERROR; + } + + /* Write the Data passed to the PEX Data register */ + MV_REG_WRITE(PEX_CFG_DATA_REG(pexIf), data); + + return MV_OK; +#endif +} + +/******************************************************************************* +* mvPexMasterEnable - Enable/disale PEX interface master transactions. +* +* DESCRIPTION: +* This function performs read modified write to PEX command status +* (offset 0x4) to set/reset bit 2. After this bit is set, the PEX +* master is allowed to gain ownership on the bus, otherwise it is +* incapable to do so. +* +* INPUT: +* pexIf - PEX interface number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexMasterEnable(MV_U32 pexIf, MV_BOOL enable) +{ + MV_U32 pexCommandStatus; + MV_U32 localBus; + MV_U32 localDev; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexMasterEnable: ERR. Invalid PEX interface %d\n", pexIf); + return MV_ERROR; + } + + localBus = mvPexLocalBusNumGet(pexIf); + localDev = mvPexLocalDevNumGet(pexIf); + + pexCommandStatus = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, + PEX_STATUS_AND_COMMAND)); + + + if (MV_TRUE == enable) + { + pexCommandStatus |= PXSAC_MASTER_EN; + } + else + { + pexCommandStatus &= ~PXSAC_MASTER_EN; + } + + + MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_STATUS_AND_COMMAND), + pexCommandStatus); + + return MV_OK; +} + + +/******************************************************************************* +* mvPexSlaveEnable - Enable/disale PEX interface slave transactions. +* +* DESCRIPTION: +* This function performs read modified write to PEX command status +* (offset 0x4) to set/reset bit 0 and 1. After those bits are set, +* the PEX slave is allowed to respond to PEX IO space access (bit 0) +* and PEX memory space access (bit 1). +* +* INPUT: +* pexIf - PEX interface number. +* dev - PEX device number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexSlaveEnable(MV_U32 pexIf, MV_U32 bus,MV_U32 dev, MV_BOOL enable) +{ + MV_U32 pexCommandStatus; + MV_U32 RegOffs; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexSlaveEnable: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + if (dev >= MAX_PEX_DEVICES) + { + mvOsPrintf("mvPexLocalDevNumSet: ERR. device number illigal %d\n", dev); + return MV_BAD_PARAM; + + } + + + RegOffs = PEX_STATUS_AND_COMMAND; + + pexCommandStatus = mvPexConfigRead(pexIf, bus, dev, 0, RegOffs); + + if (MV_TRUE == enable) + { + pexCommandStatus |= (PXSAC_IO_EN | PXSAC_MEM_EN); + } + else + { + pexCommandStatus &= ~(PXSAC_IO_EN | PXSAC_MEM_EN); + } + + mvPexConfigWrite(pexIf, bus, dev, 0, RegOffs, pexCommandStatus); + + return MV_OK; + +} + +/******************************************************************************* +* mvPexLocalBusNumSet - Set PEX interface local bus number. +* +* DESCRIPTION: +* This function sets given PEX interface its local bus number. +* Note: In case the PEX interface is PEX-X, the information is read-only. +* +* INPUT: +* pexIf - PEX interface number. +* busNum - Bus number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_NOT_ALLOWED in case PEX interface is PEX-X. +* MV_BAD_PARAM on bad parameters , +* otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexLocalBusNumSet(MV_U32 pexIf, MV_U32 busNum) +{ + MV_U32 pexStatus; + MV_U32 localBus; + MV_U32 localDev; + + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexLocalBusNumSet: ERR. Invalid PEX interface %d\n",pexIf); + return MV_BAD_PARAM; + } + if (busNum >= MAX_PEX_BUSSES) + { + mvOsPrintf("mvPexLocalBusNumSet: ERR. bus number illigal %d\n", busNum); + return MV_ERROR; + + } + + localBus = mvPexLocalBusNumGet(pexIf); + localDev = mvPexLocalDevNumGet(pexIf); + + + + pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + pexStatus &= ~PXSR_PEX_BUS_NUM_MASK; + + pexStatus |= (busNum << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK; + + MV_REG_WRITE(PEX_STATUS_REG(pexIf), pexStatus); + + + return MV_OK; +} + + +/******************************************************************************* +* mvPexLocalBusNumGet - Get PEX interface local bus number. +* +* DESCRIPTION: +* This function gets the local bus number of a given PEX interface. +* +* INPUT: +* pexIf - PEX interface number. +* +* OUTPUT: +* None. +* +* RETURN: +* Local bus number.0xffffffff on Error +* +*******************************************************************************/ +MV_U32 mvPexLocalBusNumGet(MV_U32 pexIf) +{ + MV_U32 pexStatus; + + /* Parameter checking */ + if (PEX_DEFAULT_IF != pexIf) + { + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexLocalBusNumGet: ERR. Invalid PEX interface %d\n",pexIf); + return 0xFFFFFFFF; + } + } + + + pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + pexStatus &= PXSR_PEX_BUS_NUM_MASK; + + return (pexStatus >> PXSR_PEX_BUS_NUM_OFFS); + +} + + +/******************************************************************************* +* mvPexLocalDevNumSet - Set PEX interface local device number. +* +* DESCRIPTION: +* This function sets given PEX interface its local device number. +* Note: In case the PEX interface is PEX-X, the information is read-only. +* +* INPUT: +* pexIf - PEX interface number. +* devNum - Device number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_NOT_ALLOWED in case PEX interface is PEX-X. +* MV_BAD_PARAM on bad parameters , +* otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexLocalDevNumSet(MV_U32 pexIf, MV_U32 devNum) +{ + MV_U32 pexStatus; + MV_U32 localBus; + MV_U32 localDev; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexLocalDevNumSet: ERR. Invalid PEX interface %d\n",pexIf); + return MV_BAD_PARAM; + } + if (devNum >= MAX_PEX_DEVICES) + { + mvOsPrintf("mvPexLocalDevNumSet: ERR. device number illigal %d\n", + devNum); + return MV_BAD_PARAM; + + } + + localBus = mvPexLocalBusNumGet(pexIf); + localDev = mvPexLocalDevNumGet(pexIf); + + + pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + pexStatus &= ~PXSR_PEX_DEV_NUM_MASK; + + pexStatus |= (devNum << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK; + + MV_REG_WRITE(PEX_STATUS_REG(pexIf), pexStatus); + + + return MV_OK; +} + +/******************************************************************************* +* mvPexLocalDevNumGet - Get PEX interface local device number. +* +* DESCRIPTION: +* This function gets the local device number of a given PEX interface. +* +* INPUT: +* pexIf - PEX interface number. +* +* OUTPUT: +* None. +* +* RETURN: +* Local device number. 0xffffffff on Error +* +*******************************************************************************/ +MV_U32 mvPexLocalDevNumGet(MV_U32 pexIf) +{ + MV_U32 pexStatus; + + /* Parameter checking */ + + if (PEX_DEFAULT_IF != pexIf) + { + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexLocalDevNumGet: ERR. Invalid PEX interface %d\n", + pexIf); + return 0xFFFFFFFF; + } + } + + pexStatus = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + pexStatus &= PXSR_PEX_DEV_NUM_MASK; + + return (pexStatus >> PXSR_PEX_DEV_NUM_OFFS); +} + +MV_VOID mvPexPhyRegRead(MV_U32 pexIf, MV_U32 regOffset, MV_U16 *value) +{ + + MV_U32 regAddr; + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexPhyRegRead: ERR. Invalid PEX interface %d\n", pexIf); + return; + } + regAddr = (BIT31 | ((regOffset & 0x3fff) << 16)); + MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regAddr); + *value = MV_REG_READ(PEX_PHY_ACCESS_REG(pexIf)); +} + + +MV_VOID mvPexPhyRegWrite(MV_U32 pexIf, MV_U32 regOffset, MV_U16 value) +{ + + MV_U32 regAddr; + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexPhyRegWrite: ERR. Invalid PEX interface %d\n", pexIf); + return; + } + regAddr = (((regOffset & 0x3fff) << 16) | value); + MV_REG_WRITE(PEX_PHY_ACCESS_REG(pexIf), regAddr); +} + + +/******************************************************************************* +* mvPexForceX1 +* +* DESCRIPTION: +* shut down lanes 1-3 if recognize that attached to an x1 end-point +* INPUT: +* pexIf - PEX interface number. +* +* OUTPUT: +* None +* +* RETURN: +* MV_OK on success , MV_ERROR otherwise +* +*******************************************************************************/ +MV_U32 mvPexForceX1(MV_U32 pexIf) +{ + MV_U32 regData = 0; + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexForceX1: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + regData = MV_REG_READ(PEX_CTRL_REG(pexIf)) & ~(PXCR_CONF_LINK_MASK) ; + regData |= PXCR_CONF_LINK_X1; + + MV_REG_WRITE(PEX_CTRL_REG(pexIf), regData); + return MV_OK; +} + +MV_BOOL mvPexIsPowerUp(MV_U32 pexIf) +{ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexIsPowerUp: ERR. Invalid PEX interface %d\n", pexIf); + return MV_FALSE; + } + return mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf); +} + + +MV_VOID mvPexPowerDown(MV_U32 pexIf) +{ + if ( (mvCtrlModelGet() == MV_78XX0_DEV_ID) || + (mvCtrlModelGet() == MV_78100_DEV_ID) || + (mvCtrlModelGet() == MV_78200_DEV_ID) ) + { + mvCtrlPwrClckSet(PEX_UNIT_ID, pexIf, MV_FALSE); + } + else + { + MV_REG_WRITE((0x41B00 -(pexIf)*0x10000), 0x20800087); + } +} + + + diff --git a/board/mv_feroceon/mv_hal/pex/mvPex.h b/board/mv_feroceon/mv_hal/pex/mvPex.h new file mode 100644 index 0000000..c3ac827 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pex/mvPex.h @@ -0,0 +1,163 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCPEXH +#define __INCPEXH + +#include "mvCommon.h" +#include "mvOs.h" +#include "pex/mvPexRegs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + + + +/* NOTE not supported in this driver:*/ + + +/* defines */ +/* The number of supported PEX interfaces depend on Marvell controller */ +/* device number. This device number ID is located on the PEX unit */ +/* configuration header. This creates a loop where calling PEX */ +/* configuration read/write routine results a call to get PEX configuration */ +/* information etc. This macro defines a default PEX interface. This PEX */ +/* interface is sure to exist. */ +#define PEX_DEFAULT_IF 0 + + +/* typedefs */ +/* The Marvell controller supports both root complex and end point devices */ +/* This enumeration describes the PEX type. */ +typedef enum _mvPexType +{ + MV_PEX_ROOT_COMPLEX, /* root complex device */ + MV_PEX_END_POINT /* end point device */ +}MV_PEX_TYPE; + +typedef enum _mvPexWidth +{ + MV_PEX_WITDH_X1 = 1, + MV_PEX_WITDH_X2, + MV_PEX_WITDH_X3, + MV_PEX_WITDH_X4, + MV_PEX_WITDH_INVALID +}MV_PEX_WIDTH; + +/* PEX Bar attributes */ +typedef struct _mvPexMode +{ + MV_PEX_TYPE pexType; + MV_PEX_WIDTH pexWidth; + MV_BOOL pexLinkUp; +}MV_PEX_MODE; + + + +/* Global Functions prototypes */ +/* mvPexInit - Initialize PEX interfaces*/ +MV_STATUS mvPexHalInit(MV_U32 pexIf, MV_PEX_TYPE pexType); + +/* mvPexModeGet - Get Pex If mode */ +MV_U32 mvPexModeGet(MV_U32 pexIf,MV_PEX_MODE *pexMode); + +/* mvPexConfigRead - Read from configuration space */ +MV_U32 mvPexConfigRead (MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func,MV_U32 regOff); + +/* mvPexConfigWrite - Write to configuration space */ +MV_STATUS mvPexConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data); + +/* mvPexMasterEnable - Enable/disale PEX interface master transactions.*/ +MV_STATUS mvPexMasterEnable(MV_U32 pexIf, MV_BOOL enable); + +/* mvPexSlaveEnable - Enable/disale PEX interface slave transactions.*/ +MV_STATUS mvPexSlaveEnable(MV_U32 pexIf, MV_U32 bus,MV_U32 dev, MV_BOOL enable); + +/* mvPexLocalBusNumSet - Set PEX interface local bus number.*/ +MV_STATUS mvPexLocalBusNumSet(MV_U32 pexIf, MV_U32 busNum); + +/* mvPexLocalBusNumGet - Get PEX interface local bus number.*/ +MV_U32 mvPexLocalBusNumGet(MV_U32 pexIf); + +/* mvPexLocalDevNumSet - Set PEX interface local device number.*/ +MV_STATUS mvPexLocalDevNumSet(MV_U32 pexIf, MV_U32 devNum); + +/* mvPexLocalDevNumGet - Get PEX interface local device number.*/ +MV_U32 mvPexLocalDevNumGet(MV_U32 pexIf); + +/* mvPexIsPowerUp - Is PEX interface Power up? */ +MV_BOOL mvPexIsPowerUp(MV_U32 pexIf); + +/* mvPexPowerDown - Power Down */ +MV_VOID mvPexPowerDown(MV_U32 pexIf); + +/* mvPexPowerUp - Power Up */ +MV_VOID mvPexPowerUp(MV_U32 pexIf); + +/* mvPexPhyRegRead - Pex phy read */ +MV_VOID mvPexPhyRegRead(MV_U32 pexIf, MV_U32 regOffset, MV_U16 *value); + +/* mvPexPhyRegWrite - Pex phy write */ +MV_VOID mvPexPhyRegWrite(MV_U32 pexIf, MV_U32 regOffset, MV_U16 value); +#endif /* #ifndef __INCPEXH */ diff --git a/board/mv_feroceon/mv_hal/pex/mvPexRegs.h b/board/mv_feroceon/mv_hal/pex/mvPexRegs.h new file mode 100644 index 0000000..e48cad8 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pex/mvPexRegs.h @@ -0,0 +1,743 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCPEXREGSH +#define __INCPEXREGSH + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines */ +#define MAX_PEX_DEVICES 32 +#define MAX_PEX_FUNCS 8 +#define MAX_PEX_BUSSES 256 + + + +/*********************************************************/ +/* PCI Express Configuration Cycles Generation Registers */ +/*********************************************************/ + +#define PEX_CFG_ADDR_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x18F8) +#define PEX_CFG_DATA_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x18FC) +#define PEX_PHY_ACCESS_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1B00) +/* PCI Express Configuration Address Register */ +/* PEX_CFG_ADDR_REG (PXCAR)*/ + +#define PXCAR_REG_NUM_OFFS 2 +#define PXCAR_REG_NUM_MAX 0x3F +#define PXCAR_REG_NUM_MASK (PXCAR_REG_NUM_MAX << PXCAR_REG_NUM_OFFS) +#define PXCAR_FUNC_NUM_OFFS 8 +#define PXCAR_FUNC_NUM_MAX 0x7 +#define PXCAR_FUNC_NUM_MASK (PXCAR_FUNC_NUM_MAX << PXCAR_FUNC_NUM_OFFS) +#define PXCAR_DEVICE_NUM_OFFS 11 +#define PXCAR_DEVICE_NUM_MAX 0x1F +#define PXCAR_DEVICE_NUM_MASK (PXCAR_DEVICE_NUM_MAX << PXCAR_DEVICE_NUM_OFFS) +#define PXCAR_BUS_NUM_OFFS 16 +#define PXCAR_BUS_NUM_MAX 0xFF +#define PXCAR_BUS_NUM_MASK (PXCAR_BUS_NUM_MAX << PXCAR_BUS_NUM_OFFS) +#define PXCAR_EXT_REG_NUM_OFFS 24 +#define PXCAR_EXT_REG_NUM_MAX 0xF + +/* in pci express register address is now the legacy register address (8 bits) +with the new extended register address (more 4 bits) , below is the mask of +the upper 4 bits of the full register address */ + +#define PXCAR_REAL_EXT_REG_NUM_OFFS 8 +#define PXCAR_EXT_REG_NUM_MASK (PXCAR_EXT_REG_NUM_MAX << PXCAR_EXT_REG_NUM_OFFS) +#define PXCAR_CONFIG_EN BIT31 + +#define PXCAR_REAL_EXT_REG_NUM_OFFS 8 +#define PXCAR_REAL_EXT_REG_NUM_MASK (0xF << PXCAR_REAL_EXT_REG_NUM_OFFS) + +/* The traditional PCI spec defined 6-bit field to describe register offset.*/ +/* The new PCI Express extend the register offset by an extra 4-bits. */ +/* The below macro assign 10-bit register offset into the apprpreate */ +/* fields in the CFG_ADDR_REG */ +#define PXCAR_REG_OFFS_SET(regOffs) \ + ( (regOff & PXCAR_REG_NUM_MASK) | \ + ( ((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >> PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS) ) + +/***********************************/ +/* PCI Express Interrupt registers */ +/***********************************/ +#define PEX_CAUSE_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1900) +#define PEX_MASK_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1910) + +#define PXICR_TX_REQ_IN_DLDOWN_ERR BIT0 /* Transmit request while field */ + /* of the PCI Express */ +/* PCI Express Interrupt Cause */ +/* PEX_INT_CAUSE_REG (PXICR)*/ +/* PEX_INT_MASK_REG*/ +/* +NOTE:All bits except bits[27:24] are Read/Write Clear only. A cause bit sets +upon an error event occurrence. A write of 0 clears the bit. A write of 1 has +no affect. Bits[24:27} are set and cleared upon reception of interrupt +emulation messages. + +Mask bit per cause bit. If a bit is set to 1, the corresponding event is +enabled. Mask does not affect setting of the Interrupt Cause register bits; +it only affects the assertion of the interrupt .*/ + + +#define PXICR_MDIS_CAUSE BIT1 /* Attempt to generate PCI transaction + while master is disabled */ +#define PXICR_ERR_WRTO_REG_CAUSE BIT3 /* Erroneous write attempt to + PCI Express internal register*/ +#define PXICR_HIT_DFLT_WIN_ERR BIT4 /* Hit Default Window Error */ +#define PXICR_RX_RAM_PAR_ERR BIT6 /* Rx RAM Parity Error */ +#define PXICR_TX_RAM_PAR_ERR BIT7 /* Tx RAM Parity Error */ +#define PXICR_COR_ERR_DET BIT8 /* Correctable Error Detected*/ +#define PXICR_NF_ERR_DET BIT9 /* Non-Fatal Error Detected*/ +#define PXICR_FERR_DET BIT10 /* Fatal Error Detected*/ +#define PXICR_DSTATE_CHANGE BIT11 /* Dstate Change Indication*/ +#define PXICR_BIST BIT12 /* PCI-Express BIST activated*/ +#define PXICR_FLW_CTRL_PROT BIT14 /* Flow Control Protocol Error */ + +#define PXICR_RCV_UR_CA_ERR BIT15 /* Received UR or CA status. */ +#define PXICR_RCV_ERR_FATAL BIT16 /* Received ERR_FATAL message.*/ +#define PXICR_RCV_ERR_NON_FATAL BIT17 /* Received ERR_NONFATAL message*/ +#define PXICR_RCV_ERR_COR BIT18 /* Received ERR_COR message.*/ +#define PXICR_RCV_CRS BIT19 /* Received CRS completion status*/ +#define PXICR_SLV_HOT_RESET BIT20 /* Received Hot Reset Indication*/ +#define PXICR_SLV_DIS_LINK BIT21 /* Slave Disable Link Indication*/ +#define PXICR_SLV_LB BIT22 /* Slave Loopback Indication*/ +#define PXICR_LINK_FAIL BIT23 /* Link Failure indication.*/ +#define PXICR_RCV_INTA BIT24 /* IntA status.*/ +#define PXICR_RCV_INTB BIT25 /* IntB status.*/ +#define PXICR_RCV_INTC BIT26 /* IntC status.*/ +#define PXICR_RCV_INTD BIT27 /* IntD status.*/ +#define PXICR_RCV_PM_PME BIT28 /* Received PM_PME message. */ + + +/********************************************/ +/* PCI Express Control and Status Registers */ +/********************************************/ +#define PEX_CTRL_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1A00) +#define PEX_STATUS_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1A04) +#define PEX_COMPLT_TMEOUT_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1A10) +#define PEX_FLOW_CTRL_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1A20) +#define PEX_ACK_TMR_4X_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1A30) +#define PEX_ACK_TMR_1X_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1A40) +#define PEX_TL_CTRL_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1AB0) + + +#define PEX_RAM_PARITY_CTRL_REG(pexIf) ((PEX_IF_BASE(pexIf)) + 0x1A50) +/* PCI Express Control Register */ +/* PEX_CTRL_REG (PXCR) */ + +#define PXCR_CONF_LINK_OFFS 0 +#define PXCR_CONF_LINK_MASK (1 << PXCR_CONF_LINK_OFFS) +#define PXCR_CONF_LINK_X4 (0 << PXCR_CONF_LINK_OFFS) +#define PXCR_CONF_LINK_X1 (1 << PXCR_CONF_LINK_OFFS) +#define PXCR_DEV_TYPE_CTRL_OFFS 1 /*PCI ExpressDevice Type Control*/ +#define PXCR_DEV_TYPE_CTRL_MASK BIT1 +#define PXCR_DEV_TYPE_CTRL_CMPLX (1 << PXCR_DEV_TYPE_CTRL_OFFS) +#define PXCR_DEV_TYPE_CTRL_POINT (0 << PXCR_DEV_TYPE_CTRL_OFFS) +#define PXCR_CFG_MAP_TO_MEM_EN BIT2 /* Configuration Header Mapping + to Memory Space Enable */ + +#define PXCR_CFG_MAP_TO_MEM_EN BIT2 /* Configuration Header Mapping + to Memory Space Enable*/ + +#define PXCR_RSRV1_OFFS 5 +#define PXCR_RSRV1_MASK (0x7 << PXCR_RSRV1_OFFS) +#define PXCR_RSRV1_VAL (0x0 << PXCR_RSRV1_OFFS) + +#define PXCR_CONF_MAX_OUTSTND_OFFS 8 /*Maximum outstanding NP requests as a master*/ +#define PXCR_CONF_MAX_OUTSTND_MASK (0x3 << PXCR_CONF_MAX_OUTSTND_OFFS) + + +#define PXCR_CONF_NFTS_OFFS 16 /*number of FTS Ordered-Sets*/ +#define PXCR_CONF_NFTS_MASK (0xff << PXCR_CONF_NFTS_OFFS) + +#define PXCR_CONF_MSTR_HOT_RESET BIT24 /*Master Hot-Reset.*/ +#define PXCR_CONF_MSTR_LB BIT26 /* Master Loopback */ +#define PXCR_CONF_MSTR_DIS_SCRMB BIT27 /* Master Disable Scrambling*/ +#define PXCR_CONF_DIRECT_DIS_SCRMB BIT28 /* Direct Disable Scrambling*/ + +/* PCI Express Status Register */ +/* PEX_STATUS_REG (PXSR) */ + +#define PXSR_DL_DOWN BIT0 /* DL_Down indication.*/ + +#define PXSR_PEX_BUS_NUM_OFFS 8 /* Bus Number Indication */ +#define PXSR_PEX_BUS_NUM_MASK (0xff << PXSR_PEX_BUS_NUM_OFFS) + +#define PXSR_PEX_DEV_NUM_OFFS 16 /* Device Number Indication */ +#define PXSR_PEX_DEV_NUM_MASK (0x1f << PXSR_PEX_DEV_NUM_OFFS) + +#define PXSR_PEX_SLV_HOT_RESET BIT24 /* Slave Hot Reset Indication*/ +#define PXSR_PEX_SLV_DIS_LINK BIT25 /* Slave Disable Link Indication*/ +#define PXSR_PEX_SLV_LB BIT26 /* Slave Loopback Indication*/ +#define PXSR_PEX_SLV_DIS_SCRMB BIT27 /* Slave Disable Scrambling Indication*/ + + +/* PCI Express Completion Timeout Register */ +/* PEX_COMPLT_TMEOUT_REG (PXCTR)*/ + +#define PXCTR_CMP_TO_THRSHLD_OFFS 0 /* Completion Timeout Threshold */ +#define PXCTR_CMP_TO_THRSHLD_MASK (0xffff << PXCTR_CMP_TO_THRSHLD_OFFS) + +/* PCI Express Flow Control Register */ +/* PEX_FLOW_CTRL_REG (PXFCR)*/ + +#define PXFCR_PH_INIT_FC_OFFS 0 /*Posted Headers Flow Control Credit + Initial Value.*/ +#define PXFCR_PH_INIT_FC_MASK (0xff << PXFCR_PH_INIT_FC_OFFS) + + +#define PXFCR_NPH_INIT_FC_OFFS 8 /* Classified Non-Posted Headers + Flow Control Credit Initial Value*/ +#define PXFCR_NPH_INIT_FC_MASK (0xff << PXFCR_NPH_INIT_FC_OFFS) + +#define PXFCR_CH_INIT_FC_OFFS 16 /* Completion Headers Flow Control + Credit Initial Value Infinite*/ + +#define PXFCR_CH_INIT_FC_MASK (0xff << PXFCR_CH_INIT_FC_OFFS) + +#define PXFCR_FC_UPDATE_TO_OFFS 24 /* Flow Control Update Timeout */ +#define PXFCR_FC_UPDATE_TO_MASK (0xff << PXFCR_FC_UPDATE_TO_OFFS) + +/* PCI Express Acknowledge Timers (4X) Register */ +/* PEX_ACK_TMR_4X_REG (PXAT4R) */ +#define PXAT1R_ACK_LAT_TOX4_OFFS 0 /* Ack Latency Timer Timeout Value */ +#define PXAT1R_ACK_LAT_TOX4_MASK (0xffff << PXAT4R_ACK_LAT_TOX1_OFFS) +#define PXAT1R_ACK_RPLY_TOX4_OFFS 16 /* Ack Replay Timer Timeout Value */ +#define PXAT1R_ACK_RPLY_TOX4_MASK (0xffff << PXAT1R_ACK_RPLY_TOX1_OFFS) + +/* PCI Express Acknowledge Timers (1X) Register */ +/* PEX_ACK_TMR_1X_REG (PXAT1R) */ + +#define PXAT1R_ACK_LAT_TOX1_OFFS 0 /* Acknowledge Latency Timer Timeout + Value for 1X Link*/ +#define PXAT1R_ACK_LAT_TOX1_MASK (0xffff << PXAT1R_ACK_LAT_TOX1_OFFS) + +#define PXAT1R_ACK_RPLY_TOX1_OFFS 16 /* Acknowledge Replay Timer Timeout + Value for 1X*/ +#define PXAT1R_ACK_RPLY_TOX1_MASK (0xffff << PXAT1R_ACK_RPLY_TOX1_OFFS) + + +/* PCI Express TL Control Register */ +/* PEX_TL_CTRL_REG (PXTCR) */ + +#define PXTCR_TX_CMP_BUFF_NO_OFFS 8 /*Number of completion buffers in Tx*/ +#define PXTCR_TX_CMP_BUFF_NO_MASK (0xf << PXTCR_TX_CMP_BUFF_NO_OFFS) + +/* PCI Express Debug MAC Control Register */ +/* PEX_DEBUG_MAC_CTRL_REG (PXDMCR) */ + +#define PXDMCR_LINKUP BIT4 + + + +/**********************************************/ +/* PCI Express Configuration Header Registers */ +/**********************************************/ +#define PEX_CFG_DIRECT_ACCESS(pexIf,cfgReg) ((PEX_IF_BASE(pexIf)) + (cfgReg)) + +#define PEX_DEVICE_AND_VENDOR_ID 0x000 +#define PEX_STATUS_AND_COMMAND 0x004 +#define PEX_CLASS_CODE_AND_REVISION_ID 0x008 +#define PEX_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE 0x00C +#define PEX_MEMORY_BAR_BASE_ADDR(barNum) (0x010 + ((barNum) << 2)) +#define PEX_MV_BAR_BASE(barNum) (0x010 + (barNum) * 8) +#define PEX_MV_BAR_BASE_HIGH(barNum) (0x014 + (barNum) * 8) +#define PEX_BAR0_INTER_REG 0x010 +#define PEX_BAR0_INTER_REG_HIGH 0x014 +#define PEX_BAR1_REG 0x018 +#define PEX_BAR1_REG_HIGH 0x01C +#define PEX_BAR2_REG 0x020 +#define PEX_BAR2_REG_HIGH 0x024 + +#define PEX_SUBSYS_ID_AND_SUBSYS_VENDOR_ID 0x02C +#define PEX_EXPANSION_ROM_BASE_ADDR_REG 0x030 +#define PEX_CAPABILTY_LIST_POINTER 0x034 +#define PEX_INTERRUPT_PIN_AND_LINE 0x03C + +/* capability list */ +#define PEX_POWER_MNG_CAPABILITY 0x040 +#define PEX_POWER_MNG_STATUS_CONTROL 0x044 + +#define PEX_MSI_MESSAGE_CONTROL 0x050 +#define PEX_MSI_MESSAGE_ADDR 0x054 +#define PEX_MSI_MESSAGE_HIGH_ADDR 0x058 +#define PEX_MSI_MESSAGE_DATA 0x05C + +#define PEX_CAPABILITY_REG 0x60 +#define PEX_DEV_CAPABILITY_REG 0x64 +#define PEX_DEV_CTRL_STAT_REG 0x68 +#define PEX_LINK_CAPABILITY_REG 0x6C +#define PEX_LINK_CTRL_STAT_REG 0x70 + +#define PEX_ADV_ERR_RPRT_HDR_TRGT_REG 0x100 +#define PEX_UNCORRECT_ERR_STAT_REG 0x104 +#define PEX_UNCORRECT_ERR_MASK_REG 0x108 +#define PEX_UNCORRECT_ERR_SERVITY_REG 0x10C +#define PEX_CORRECT_ERR_STAT_REG 0x110 +#define PEX_CORRECT_ERR_MASK_REG 0x114 +#define PEX_ADV_ERR_CAPABILITY_CTRL_REG 0x118 +#define PEX_HDR_LOG_FIRST_DWORD_REG 0x11C +#define PEX_HDR_LOG_SECOND_DWORD_REG 0x120 +#define PEX_HDR_LOG_THIRD_DWORD_REG 0x124 +#define PEX_HDR_LOG_FOURTH_DWORD_REG 0x128 + + + +/* PCI Express Device and Vendor ID Register*/ +/*PEX_DEVICE_AND_VENDOR_ID (PXDAVI)*/ + +#define PXDAVI_VEN_ID_OFFS 0 /* Vendor ID */ +#define PXDAVI_VEN_ID_MASK (0xffff << PXDAVI_VEN_ID_OFFS) + +#define PXDAVI_DEV_ID_OFFS 16 /* Device ID */ +#define PXDAVI_DEV_ID_MASK (0xffff << PXDAVI_DEV_ID_OFFS) + + +/* PCI Express Command and Status Register*/ +/*PEX_STATUS_AND_COMMAND (PXSAC)*/ + +#define PXSAC_IO_EN BIT0 /* IO Enable */ +#define PXSAC_MEM_EN BIT1 /* Memory Enable */ +#define PXSAC_MASTER_EN BIT2 /* Master Enable */ +#define PXSAC_PERR_EN BIT6 /* Parity Errors Respond Enable */ +#define PXSAC_SERR_EN BIT8 /* Ability to assert SERR# line */ +#define PXSAC_INT_DIS BIT10 /* Interrupt Disable */ +#define PXSAC_INT_STAT BIT19 /* Interrupt Status */ +#define PXSAC_CAP_LIST BIT20 /* Capability List Support */ +#define PXSAC_MAS_DATA_PERR BIT24 /* Master Data Parity Error */ +#define PXSAC_SLAVE_TABORT BIT27 /* Signalled Target Abort */ +#define PXSAC_RT_ABORT BIT28 /* Recieved Target Abort */ +#define PXSAC_MABORT BIT29 /* Recieved Master Abort */ +#define PXSAC_SYSERR BIT30 /* Signalled system error */ +#define PXSAC_DET_PARERR BIT31 /* Detect Parity Error */ + + +/* PCI Express Class Code and Revision ID Register*/ +/*PEX_CLASS_CODE_AND_REVISION_ID (PXCCARI)*/ + +#define PXCCARI_REVID_OFFS 0 /* Revision ID */ +#define PXCCARI_REVID_MASK (0xff << PXCCARI_REVID_OFFS) + +#define PXCCARI_FULL_CLASS_OFFS 8 /* Full Class Code */ +#define PXCCARI_FULL_CLASS_MASK (0xffffff << PXCCARI_FULL_CLASS_OFFS) + +#define PXCCARI_PROGIF_OFFS 8 /* Prog .I/F*/ +#define PXCCARI_PROGIF_MASK (0xff << PXCCARI_PROGIF_OFFS) + +#define PXCCARI_SUB_CLASS_OFFS 16 /* Sub Class*/ +#define PXCCARI_SUB_CLASS_MASK (0xff << PXCCARI_SUB_CLASS_OFFS) + +#define PXCCARI_BASE_CLASS_OFFS 24 /* Base Class*/ +#define PXCCARI_BASE_CLASS_MASK (0xff << PXCCARI_BASE_CLASS_OFFS) + + +/* PCI Express BIST, Header Type and Cache Line Size Register*/ +/*PEX_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE (PXBHTLTCL)*/ + +#define PXBHTLTCL_CACHELINE_OFFS 0 /* Specifies the cache line size */ +#define PXBHTLTCL_CACHELINE_MASK (0xff << PXBHTLTCL_CACHELINE_OFFS) + +#define PXBHTLTCL_HEADTYPE_FULL_OFFS 16 /* Full Header Type */ +#define PXBHTLTCL_HEADTYPE_FULL_MASK (0xff << PXBHTLTCL_HEADTYPE_FULL_OFFS) + +#define PXBHTLTCL_MULTI_FUNC BIT23 /* Multi/Single function */ + +#define PXBHTLTCL_HEADER_OFFS 16 /* Header type */ +#define PXBHTLTCL_HEADER_MASK (0x7f << PXBHTLTCL_HEADER_OFFS) +#define PXBHTLTCL_HEADER_STANDARD (0x0 << PXBHTLTCL_HEADER_OFFS) +#define PXBHTLTCL_HEADER_PCI2PCI_BRIDGE (0x1 << PXBHTLTCL_HEADER_OFFS) + + +#define PXBHTLTCL_BISTCOMP_OFFS 24 /* BIST Completion Code */ +#define PXBHTLTCL_BISTCOMP_MASK (0xf << PXBHTLTCL_BISTCOMP_OFFS) + +#define PXBHTLTCL_BISTACT BIT30 /* BIST Activate bit */ +#define PXBHTLTCL_BISTCAP BIT31 /* BIST Capable Bit */ +#define PXBHTLTCL_BISTCAP_OFFS 31 +#define PXBHTLTCL_BISTCAP_MASK BIT31 +#define PXBHTLTCL_BISTCAP_VAL 0 + + +/* PCI Express Subsystem Device and Vendor ID */ +/*PEX_SUBSYS_ID_AND_SUBSYS_VENDOR_ID (PXSIASVI)*/ + +#define PXSIASVI_VENID_OFFS 0 /* Subsystem Manufacturer Vendor ID Number */ +#define PXSIASVI_VENID_MASK (0xffff << PXSIASVI_VENID_OFFS) + +#define PXSIASVI_DEVID_OFFS 16 /* Subsystem Device ID Number */ +#define PXSIASVI_DEVID_MASK (0xffff << PXSIASVI_DEVID_OFFS) + + +/* PCI Express Capability List Pointer Register*/ +/*PEX_CAPABILTY_LIST_POINTER (PXCLP)*/ + +#define PXCLP_CAPPTR_OFFS 0 /* Capability List Pointer */ +#define PXCLP_CAPPTR_MASK (0xff << PXCLP_CAPPTR_OFFS) + +/* PCI Express Interrupt Pin and Line Register */ +/*PEX_INTERRUPT_PIN_AND_LINE (PXIPAL)*/ + +#define PXIPAL_INTLINE_OFFS 0 /* Interrupt line (IRQ) */ +#define PXIPAL_INTLINE_MASK (0xff << PXIPAL_INTLINE_OFFS) + +#define PXIPAL_INTPIN_OFFS 8 /* interrupt pin (A,B,C,D) */ +#define PXIPAL_INTPIN_MASK (0xff << PXIPAL_INTPIN_OFFS) + + +/* PCI Express Power Management Capability Header Register*/ +/*PEX_POWER_MNG_CAPABILITY (PXPMC)*/ + +#define PXPMC_CAP_ID_OFFS 0 /* Capability ID */ +#define PXPMC_CAP_ID_MASK (0xff << PXPMC_CAP_ID_OFFS) + +#define PXPMC_NEXT_PTR_OFFS 8 /* Next Item Pointer */ +#define PXPMC_NEXT_PTR_MASK (0xff << PXPMC_NEXT_PTR_OFFS) + +#define PXPMC_PMC_VER_OFFS 16 /* PCI Power Management Capability Version*/ +#define PXPMC_PMC_VER_MASK (0x7 << PXPMC_PMC_VER_OFFS) + +#define PXPMC_DSI BIT21/* Device Specific Initialization */ + +#define PXPMC_AUX_CUR_OFFS 22 /* Auxiliary Current Requirements */ +#define PXPMC_AUX_CUR_MASK (0x7 << PXPMC_AUX_CUR_OFFS) + +#define PXPMC_D1_SUP BIT25 /* D1 Power Management support*/ + +#define PXPMC_D2_SUP BIT26 /* D2 Power Management support*/ + +#define PXPMC_PME_SUP_OFFS 27 /* PM Event generation support*/ +#define PXPMC_PME_SUP_MASK (0x1f << PXPMC_PME_SUP_OFFS) + +/* PCI Express Power Management Control and Status Register*/ +/*PEX_POWER_MNG_STATUS_CONTROL (PXPMSC)*/ + +#define PXPMSC_PM_STATE_OFFS 0 /* Power State */ +#define PXPMSC_PM_STATE_MASK (0x3 << PXPMSC_PM_STATE_OFFS) +#define PXPMSC_PM_STATE_D0 (0x0 << PXPMSC_PM_STATE_OFFS) +#define PXPMSC_PM_STATE_D1 (0x1 << PXPMSC_PM_STATE_OFFS) +#define PXPMSC_PM_STATE_D2 (0x2 << PXPMSC_PM_STATE_OFFS) +#define PXPMSC_PM_STATE_D3 (0x3 << PXPMSC_PM_STATE_OFFS) + +#define PXPMSC_PME_EN BIT8/* PM_PME Message Generation Enable */ + +#define PXPMSC_PM_DATA_SEL_OFFS 9 /* Data Select*/ +#define PXPMSC_PM_DATA_SEL_MASK (0xf << PXPMSC_PM_DATA_SEL_OFFS) + +#define PXPMSC_PM_DATA_SCALE_OFFS 13 /* Data Scale */ +#define PXPMSC_PM_DATA_SCALE_MASK (0x3 << PXPMSC_PM_DATA_SCALE_OFFS) + +#define PXPMSC_PME_STAT BIT15/* PME Status */ + +#define PXPMSC_PM_DATA_OFFS 24 /* State Data */ +#define PXPMSC_PM_DATA_MASK (0xff << PXPMSC_PM_DATA_OFFS) + + +/* PCI Express MSI Message Control Register*/ +/*PEX_MSI_MESSAGE_CONTROL (PXMMC)*/ + +#define PXMMC_CAP_ID_OFFS 0 /* Capability ID */ +#define PXMMC_CAP_ID_MASK (0xff << PXMMC_CAP_ID_OFFS) + +#define PXMMC_NEXT_PTR_OFFS 8 /* Next Item Pointer */ +#define PXMMC_NEXT_PTR_MASK (0xff << PXMMC_NEXT_PTR_OFFS) + +#define PXMMC_MSI_EN BIT18 /* MSI Enable */ + +#define PXMMC_MULTI_CAP_OFFS 17 /* Multiple Message Capable */ +#define PXMMC_MULTI_CAP_MASK (0x7 << PXMMC_MULTI_CAP_OFFS) + +#define PXMMC_MULTI_EN_OFFS 20 /* Multiple Messages Enable */ +#define PXMMC_MULTI_EN_MASK (0x7 << PXMMC_MULTI_EN_OFFS) + +#define PXMMC_ADDR64 BIT23 /* 64-bit Addressing Capable */ + + +/* PCI Express MSI Message Address Register*/ +/*PEX_MSI_MESSAGE_ADDR (PXMMA)*/ + +#define PXMMA_MSI_ADDR_OFFS 2 /* Message Address corresponds to + Address[31:2] of the MSI MWr TLP*/ +#define PXMMA_MSI_ADDR_MASK (0x3fffffff << PXMMA_MSI_ADDR_OFFS) + + +/* PCI Express MSI Message Address (High) Register */ +/*PEX_MSI_MESSAGE_HIGH_ADDR (PXMMHA)*/ + +#define PXMMA_MSI_ADDR_H_OFFS 0 /* Message Upper Address corresponds to + Address[63:32] of the MSI MWr TLP*/ +#define PXMMA_MSI_ADDR_H_MASK (0xffffffff << PXMMA_MSI_ADDR_H_OFFS ) + + +/* PCI Express MSI Message Data Register*/ +/*PEX_MSI_MESSAGE_DATA (PXMMD)*/ + +#define PXMMD_MSI_DATA_OFFS 0 /* Message Data */ +#define PXMMD_MSI_DATA_MASK (0xffff << PXMMD_MSI_DATA_OFFS ) + + +/* PCI Express Capability Register*/ +/*PEX_CAPABILITY_REG (PXCR)*/ + +#define PXCR_CAP_ID_OFFS 0 /* Capability ID*/ +#define PXCR_CAP_ID_MASK (0xff << PXCR_CAP_ID_OFFS) + +#define PXCR_NEXT_PTR_OFFS 8 /* Next Item Pointer*/ +#define PXCR_NEXT_PTR_MASK (0xff << PXCR_NEXT_PTR_OFFS) + +#define PXCR_CAP_VER_OFFS 16 /* Capability Version*/ +#define PXCR_CAP_VER_MASK (0xf << PXCR_CAP_VER_OFFS) + +#define PXCR_DEV_TYPE_OFFS 20 /* Device/Port Type*/ +#define PXCR_DEV_TYPE_MASK (0xf << PXCR_DEV_TYPE_OFFS) + +#define PXCR_SLOT_IMP BIT24 /* Slot Implemented*/ + +#define PXCR_INT_MSG_NUM_OFFS 25 /* Interrupt Message Number*/ +#define PXCR_INT_MSG_NUM_MASK (0x1f << PXCR_INT_MSG_NUM_OFFS) + + +/* PCI Express Device Capabilities Register */ +/*PEX_DEV_CAPABILITY_REG (PXDCR)*/ + +#define PXDCR_MAX_PLD_SIZE_SUP_OFFS 0 /* Maximum Payload Size Supported*/ +#define PXDCR_MAX_PLD_SIZE_SUP_MASK (0x7 << PXDCR_MAX_PLD_SIZE_SUP_OFFS) + +#define PXDCR_EP_L0S_ACC_LAT_OFFS 6/* Endpoint L0s Acceptable Latency*/ +#define PXDCR_EP_L0S_ACC_LAT_MASK (0x7 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_64NS_LESS (0x0 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_64NS_128NS (0x1 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_128NS_256NS (0x2 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_256NS_512NS (0x3 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_512NS_1US (0x4 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_1US_2US (0x5 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_2US_4US (0x6 << PXDCR_EP_L0S_ACC_LAT_OFFS) +#define PXDCR_EP_L0S_ACC_LAT_4US_MORE (0x7 << PXDCR_EP_L0S_ACC_LAT_OFFS) + +#define PXDCR_EP_L1_ACC_LAT_OFFS 9 /* Endpoint L1 Acceptable Latency*/ +#define PXDCR_EP_L1_ACC_LAT_MASK (0x7 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_64NS_LESS (0x0 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_64NS_128NS (0x1 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_128NS_256NS (0x2 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_256NS_512NS (0x3 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_512NS_1US (0x4 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_1US_2US (0x5 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_2US_4US (0x6 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXDCR_EP_L1_ACC_LAT_4US_MORE (0x7 << PXDCR_EP_L1_ACC_LAT_OFFS) + + +#define PXDCR_ATT_BUT_PRS_OFFS 12 /* Attention Button Present*/ +#define PXDCR_ATT_BUT_PRS_MASK BIT12 +#define PXDCR_ATT_BUT_PRS_IMPLEMENTED BIT12 + +#define PXDCR_ATT_IND_PRS_OFFS 13 /* Attention Indicator Present*/ +#define PXDCR_ATT_IND_PRS_MASK BIT13 +#define PXDCR_ATT_IND_PRS_IMPLEMENTED BIT13 + +#define PXDCR_PWR_IND_PRS_OFFS 14/* Power Indicator Present*/ +#define PXDCR_PWR_IND_PRS_MASK BIT14 +#define PXDCR_PWR_IND_PRS_IMPLEMENTED BIT14 + +#define PXDCR_CAP_SPL_VAL_OFFS 18 /*Captured Slot Power Limit + Value*/ +#define PXDCR_CAP_SPL_VAL_MASK (0xff << PXDCR_CAP_SPL_VAL_OFFS) + +#define PXDCR_CAP_SP_LSCL_OFFS 26 /* Captured Slot Power Limit + Scale */ +#define PXDCR_CAP_SP_LSCL_MASK (0x3 << PXDCR_CAP_SP_LSCL_OFFS) + +/* PCI Express Device Control Status Register */ +/*PEX_DEV_CTRL_STAT_REG (PXDCSR)*/ + +#define PXDCSR_COR_ERR_REP_EN BIT0 /* Correctable Error Reporting Enable*/ +#define PXDCSR_NF_ERR_REP_EN BIT1 /* Non-Fatal Error Reporting Enable*/ +#define PXDCSR_F_ERR_REP_EN BIT2 /* Fatal Error Reporting Enable*/ +#define PXDCSR_UR_REP_EN BIT3 /* Unsupported Request (UR) + Reporting Enable*/ +#define PXDCSR_EN_RO BIT4 /* Enable Relaxed Ordering*/ + +#define PXDCSR_MAX_PLD_SZ_OFFS 5 /* Maximum Payload Size*/ +#define PXDCSR_MAX_PLD_SZ_MASK (0x7 << PXDCSR_MAX_PLD_SZ_OFFS) +#define PXDCSR_MAX_PLD_SZ_128B (0x0 << PXDCSR_MAX_PLD_SZ_OFFS) +#define PXDCSR_EN_NS BIT11 /* Enable No Snoop*/ + +#define PXDCSR_MAX_RD_RQ_SZ_OFFS 12 /* Maximum Read Request Size*/ +#define PXDCSR_MAX_RD_RQ_SZ_MASK (0x7 << PXDCSR_MAX_RD_RQ_SZ_OFFS) +#define PXDCSR_MAX_RD_RQ_SZ_128B (0x0 << PXDCSR_MAX_RD_RQ_SZ_OFFS) +#define PXDCSR_MAX_RD_RQ_SZ_256B (0x1 << PXDCSR_MAX_RD_RQ_SZ_OFFS) +#define PXDCSR_MAX_RD_RQ_SZ_512B (0x2 << PXDCSR_MAX_RD_RQ_SZ_OFFS) +#define PXDCSR_MAX_RD_RQ_SZ_1KB (0x3 << PXDCSR_MAX_RD_RQ_SZ_OFFS) +#define PXDCSR_MAX_RD_RQ_SZ_2KB (0x4 << PXDCSR_MAX_RD_RQ_SZ_OFFS) +#define PXDCSR_MAX_RD_RQ_SZ_4KB (0x5 << PXDCSR_MAX_RD_RQ_SZ_OFFS) + +#define PXDCSR_COR_ERR_DET BIT16 /* Correctable Error Detected*/ +#define PXDCSR_NF_ERR_DET BIT17 /* Non-Fatal Error Detected.*/ +#define PXDCSR_F_ERR_DET BIT18 /* Fatal Error Detected.*/ +#define PXDCSR_UR_DET BIT19 /* Unsupported Request Detected */ +#define PXDCSR_AUX_PWR_DET BIT20 /* Reserved*/ + +#define PXDCSR_TRANS_PEND_OFFS 21 /* Transactions Pending*/ +#define PXDCSR_TRANS_PEND_MASK BIT21 +#define PXDCSR_TRANS_PEND_NOT_COMPLETED (0x1 << PXDCSR_TRANS_PEND_OFFS) + + +/* PCI Express Link Capabilities Register*/ +/*PEX_LINK_CAPABILITY_REG (PXLCR)*/ + +#define PXLCR_MAX_LINK_SPD_OFFS 0 /* Maximum Link Speed*/ +#define PXLCR_MAX_LINK_SPD_MASK (0xf << PXLCR_MAX_LINK_SPD_OFFS) + +#define PXLCR_MAX_LNK_WDTH_OFFS 3 /* Maximum Link Width*/ +#define PXLCR_MAX_LNK_WDTH_MASK (0x3f << PXLCR_MAX_LNK_WDTH_OFFS) + +#define PXLCR_ASPM_SUP_OFFS 10 /* Active State Link PM Support*/ +#define PXLCR_ASPM_SUP_MASK (0x3 << PXLCR_ASPM_SUP_OFFS) + +#define PXLCR_L0S_EXT_LAT_OFFS 12 /* L0s Exit Latency*/ +#define PXLCR_L0S_EXT_LAT_MASK (0x7 << PXLCR_L0S_EXT_LAT_OFFS) +#define PXLCR_L0S_EXT_LAT_64NS_LESS (0x0 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXLCR_L0S_EXT_LAT_64NS_128NS (0x1 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXLCR_L0S_EXT_LAT_128NS_256NS (0x2 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXLCR_L0S_EXT_LAT_256NS_512NS (0x3 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXLCR_L0S_EXT_LAT_512NS_1US (0x4 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXLCR_L0S_EXT_LAT_1US_2US (0x5 << PXDCR_EP_L1_ACC_LAT_OFFS) +#define PXLCR_L0S_EXT_LAT_2US_4US (0x6 << PXDCR_EP_L1_ACC_LAT_OFFS) + +#define PXLCR_POR_TNUM_OFFS 24 /* Port Number */ +#define PXLCR_POR_TNUM_MASK (0xff << PXLCR_POR_TNUM_OFFS) + +/* PCI Express Link Control Status Register */ +/*PEX_LINK_CTRL_STAT_REG (PXLCSR)*/ + +#define PXLCSR_ASPM_CNT_OFFS 0 /* Active State Link PM Control */ +#define PXLCSR_ASPM_CNT_MASK (0x3 << PXLCSR_ASPM_CNT_OFFS) +#define PXLCSR_ASPM_CNT_DISABLED (0x0 << PXLCSR_ASPM_CNT_OFFS) +#define PXLCSR_ASPM_CNT_L0S_ENT_SUPP (0x1 << PXLCSR_ASPM_CNT_OFFS) +#define PXLCSR_ASPM_CNT_L0S_L1S_ENT_SUPP (0x3 << PXLCSR_ASPM_CNT_OFFS) + +#define PXLCSR_RCB_OFFS 3 /* Read Completion Boundary */ +#define PXLCSR_RCB_MASK BIT3 +#define PXLCSR_RCB_64B (0 << PXLCSR_RCB_OFFS) +#define PXLCSR_RCB_128B (1 << PXLCSR_RCB_OFFS) + +#define PXLCSR_LNK_DIS BIT4 /* Link Disable */ +#define PXLCSR_RETRN_LNK BIT5 /* Retrain Link */ +#define PXLCSR_CMN_CLK_CFG BIT6 /* Common Clock Configuration */ +#define PXLCSR_EXTD_SNC BIT7 /* Extended Sync */ + +#define PXLCSR_LNK_SPD_OFFS 16 /* Link Speed */ +#define PXLCSR_LNK_SPD_MASK (0xf << PXLCSR_LNK_SPD_OFFS) + +#define PXLCSR_NEG_LNK_WDTH_OFFS 20 /* Negotiated Link Width */ +#define PXLCSR_NEG_LNK_WDTH_MASK (0x3f << PXLCSR_NEG_LNK_WDTH_OFFS) +#define PXLCSR_NEG_LNK_WDTH_X1 (0x1 << PXLCSR_NEG_LNK_WDTH_OFFS) + +#define PXLCSR_LNK_TRN BIT27 /* Link Training */ + +#define PXLCSR_SLT_CLK_CFG_OFFS 28 /* Slot Clock Configuration */ +#define PXLCSR_SLT_CLK_CFG_MASK BIT28 +#define PXLCSR_SLT_CLK_CFG_INDPNT (0x0 << PXLCSR_SLT_CLK_CFG_OFFS) +#define PXLCSR_SLT_CLK_CFG_REF (0x1 << PXLCSR_SLT_CLK_CFG_OFFS) + +/* PCI Express Advanced Error Report Header Register */ +/*PEX_ADV_ERR_RPRT_HDR_TRGT_REG (PXAERHTR)*/ + +/* PCI Express Uncorrectable Error Status Register*/ +/*PEX_UNCORRECT_ERR_STAT_REG (PXUESR)*/ + +/* PCI Express Uncorrectable Error Mask Register */ +/*PEX_UNCORRECT_ERR_MASK_REG (PXUEMR)*/ + +/* PCI Express Uncorrectable Error Severity Register */ +/*PEX_UNCORRECT_ERR_SERVITY_REG (PXUESR)*/ + +/* PCI Express Correctable Error Status Register */ +/*PEX_CORRECT_ERR_STAT_REG (PXCESR)*/ + +/* PCI Express Correctable Error Mask Register */ +/*PEX_CORRECT_ERR_MASK_REG (PXCEMR)*/ + +/* PCI Express Advanced Error Capability and Control Register*/ +/*PEX_ADV_ERR_CAPABILITY_CTRL_REG (PXAECCR)*/ + +/* PCI Express Header Log First DWORD Register*/ +/*PEX_HDR_LOG_FIRST_DWORD_REG (PXHLFDR)*/ + +/* PCI Express Header Log Second DWORD Register*/ +/*PEX_HDR_LOG_SECOND_DWORD_REG (PXHLSDR)*/ + +/* PCI Express Header Log Third DWORD Register*/ +/*PEX_HDR_LOG_THIRD_DWORD_REG (PXHLTDR)*/ + +/* PCI Express Header Log Fourth DWORD Register*/ +/*PEX_HDR_LOG_FOURTH_DWORD_REG (PXHLFDR)*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* #ifndef __INCPEXREGSH */ + + diff --git a/board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.c b/board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.c new file mode 100644 index 0000000..2989245 --- /dev/null +++ b/board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.c @@ -0,0 +1,580 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvPex.h" + +//#define MV_DEBUG +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* locals */ +typedef struct +{ + MV_U32 data; + MV_U32 mask; +}PEX_HEADER_DATA; + +/* local function forwad decleration */ +MV_U32 mvPexHwConfigRead (MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, + MV_U32 regOff); +MV_STATUS mvPexHwConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data); +void resetPexConfig(MV_U32 pexIf, MV_U32 bus, MV_U32 dev); + + +PEX_HEADER_DATA configHdr[16] = +{ +{0x888811ab, 0x00000000}, /*[device ID, vendor ID] */ +{0x00100007, 0x0000ffff}, /*[status register, command register] */ +{0x0604000e, 0x00000000}, /*[programming interface, sub class code, class code, revision ID] */ +{0x00010008, 0x00000000}, /*[BIST, header type, latency time, cache line] */ +{0x00000000, 0x00000000}, /*[base address 0] */ +{0x00000000, 0x00000000}, /*[base address 1] */ +{0x00000000, 0x00ffffff}, /*[secondary latency timersubordinate bus number, secondary bus number, primary bus number] */ +{0x0000f101, 0x00000000}, /*[secondary status ,IO limit, IO base] */ +{0x9ff0a000, 0x00000000}, /*[memory limit, memory base] */ +{0x0001fff1, 0x00000000}, /*[prefetch memory limit, prefetch memory base] */ +{0xffffffff, 0x00000000}, /*[prefetch memory base upper] */ +{0x00000000, 0x00000000}, /*[prefetch memory limit upper] */ +{0xeffff000, 0x00000000}, /*[IO limit upper 16 bits, IO base upper 16 bits] */ +{0x00000000, 0x00000000}, /*[reserved, capability pointer] */ +{0x00000000, 0x00000000}, /*[expansion ROM base address] */ +{0x00000000, 0x000000FF}, /*[bridge control, interrupt pin, interrupt line] */ +}; + + +#define HEADER_WRITE(data, offset) configHdr[offset/4].data = ((configHdr[offset/4].data & ~configHdr[offset/4].mask) | \ + (data & configHdr[offset/4].mask)) +#define HEADER_READ(offset) configHdr[offset/4].data + +/******************************************************************************* +* mvVrtBrgPexInit - Initialize PEX interfaces +* +* DESCRIPTION: +* +* This function is responsible of intialization of the Pex Interface , It +* configure the Pex Bars and Windows in the following manner: +* +* Assumptions : +* Bar0 is always internal registers bar +* Bar1 is always the DRAM bar +* Bar2 is always the Device bar +* +* 1) Sets the Internal registers bar base by obtaining the base from +* the CPU Interface +* 2) Sets the DRAM bar base and size by getting the base and size from +* the CPU Interface when the size is the sum of all enabled DRAM +* chip selects and the base is the base of CS0 . +* 3) Sets the Device bar base and size by getting these values from the +* CPU Interface when the base is the base of the lowest base of the +* Device chip selects, and the +* +* +* INPUT: +* +* pexIf - PEX interface number. +* +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM +* +*******************************************************************************/ +MV_STATUS mvPexVrtBrgInit(MV_U32 pexIf) +{ + /* reset PEX tree to recover previous U-boot/Boot configurations */ + MV_U32 localBus = mvPexLocalBusNumGet(pexIf); + + + resetPexConfig(pexIf, localBus, 1); + return MV_OK; +} + + +MV_U32 mvPexVrtBrgConfigRead (MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, + MV_U32 regOff) +{ + + MV_U32 localBus = mvPexLocalBusNumGet(pexIf); + MV_U32 localDev = mvPexLocalDevNumGet(pexIf); + + if(bus == localBus) + { + if(dev > 1) + { +/* on the local device allow only device #0 & #1 */ + return 0xffffffff; + } + else + if (dev == localDev) + { + /* read the memory controller registers */ + return mvPexHwConfigRead (pexIf, bus, dev, func, regOff); + } + else + { + /* access the virtual brg header */ + return HEADER_READ(regOff); + } + } + else + if(bus == (localBus + 1)) + { + /* access the device behind the virtual bridge */ + if((dev == localDev) || (dev > 1)) + { + return 0xffffffff; + } + else + { + /* access the device behind the virtual bridge, in this case + * change the bus number to the local bus number in order to + * generate type 0 config cycle + */ + return mvPexHwConfigRead (pexIf, localBus, dev, func, regOff); + } + } + /* for all other devices use the HW function to get the + * requested registers + */ + return mvPexHwConfigRead (pexIf, bus, dev, func, regOff); + +} + + +MV_STATUS mvPexVrtBrgConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data) +{ + MV_U32 localBus = mvPexLocalBusNumGet(pexIf); + MV_U32 localDev = mvPexLocalDevNumGet(pexIf); + + if(bus == localBus) + { + if(dev > 1) + { + /* on the local device allow only device #0 & #1 */ + return MV_ERROR; + } + else + if (dev == localDev) + { + /* read the memory controller registers */ + return mvPexHwConfigWrite (pexIf, bus, dev, func, regOff, data); + + } + else + { + /* access the virtual brg header */ + HEADER_WRITE(data, regOff); + return MV_OK; + } + } + else + if(bus == (localBus + 1)) + { + /* access the device behind the virtual bridge */ + if((dev == localDev) || (dev > 1)) + { + return MV_ERROR; + } + else + { + /* access the device behind the virtual bridge, in this case + * change the bus number to the local bus number in order to + * generate type 0 config cycle + */ + return mvPexHwConfigWrite (pexIf, localBus, dev, func, regOff, data); + } + } + /* for all other devices use the HW function to get the + * requested registers + */ + return mvPexHwConfigWrite (pexIf, bus, dev, func, regOff, data); + +} + + +/******************************************************************************* +* mvPexConfigRead - Read from configuration space +* +* DESCRIPTION: +* This function performs a 32 bit read from PEX configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to read from local bus segment, use +* bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pexIf - PEX interface number. +* bus - PEX segment bus number. +* dev - PEX device number. +* func - Function number. +* regOffs - Register offset. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit register data, 0xffffffff on error +* +*******************************************************************************/ +MV_U32 mvPexHwConfigRead (MV_U32 pexIf, MV_U32 bus, MV_U32 dev, MV_U32 func, + MV_U32 regOff) +{ + MV_U32 pexData = 0; + MV_U32 localDev,localBus; + + /* Parameter checking */ + if (PEX_DEFAULT_IF != pexIf) + { + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexConfigRead: ERR. Invalid PEX interface %d\n",pexIf); + return 0xFFFFFFFF; + } + } + + if (dev >= MAX_PEX_DEVICES) + { + DB(mvOsPrintf("mvPexConfigRead: ERR. device number illigal %d\n", dev)); + return 0xFFFFFFFF; + } + + if (func >= MAX_PEX_FUNCS) + { + DB(mvOsPrintf("mvPexConfigRead: ERR. function num illigal %d\n", func)); + return 0xFFFFFFFF; + } + + if (bus >= MAX_PEX_BUSSES) + { + DB(mvOsPrintf("mvPexConfigRead: ERR. bus number illigal %d\n", bus)); + return MV_ERROR; + } + + DB(mvOsPrintf("pexIf %d, bus %d, dev %d, func %d, regOff 0x%x\n", + pexIf, bus, dev, func, regOff)); + + localDev = mvPexLocalDevNumGet(pexIf); + localBus = mvPexLocalBusNumGet(pexIf); + + /* Speed up the process. In case on no link, return MV_ERROR */ + if ((dev != localDev) || (bus != localBus)) + { + pexData = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + if ((pexData & PXSR_DL_DOWN)) + { + return MV_ERROR; + } + } + + /* in PCI Express we have only one device number */ + /* and this number is the first number we encounter + else that the localDev*/ + /* spec pex define return on config read/write on any device */ + if (bus == localBus) + { + if (localDev == 0) + { + /* if local dev is 0 then the first number we encounter + after 0 is 1 */ + if ((dev != 1)&&(dev != localDev)) + { + return MV_ERROR; + } + } + else + { + /* if local dev is not 0 then the first number we encounter + is 0 */ + + if ((dev != 0)&&(dev != localDev)) + { + return MV_ERROR; + } + } + if(func != 0 ) /* i.e bridge */ + { + return MV_ERROR; + } + } + + /* Creating PEX address to be passed */ + pexData = 0; /* ofir */ + pexData |= (bus << PXCAR_BUS_NUM_OFFS); + pexData |= (dev << PXCAR_DEVICE_NUM_OFFS); + pexData |= (func << PXCAR_FUNC_NUM_OFFS); + pexData |= (regOff & PXCAR_REG_NUM_MASK); /* lgacy register space */ + /* extended register space */ + pexData |=(((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >> + PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS); + + pexData |= PXCAR_CONFIG_EN; + + /* Write the address to the PEX configuration address register */ + MV_REG_WRITE(PEX_CFG_ADDR_REG(pexIf), pexData); + + + /* In order to let the PEX controller absorbed the address of the read */ + /* transaction we perform a validity check that the address was written */ + if(pexData != MV_REG_READ(PEX_CFG_ADDR_REG(pexIf))) + { + return MV_ERROR; + } + + /* cleaning Master Abort */ + MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_STATUS_AND_COMMAND), + PXSAC_MABORT); + + /* Clear CPU pipe. Important where CPU can perform OOO execution */ + CPU_PIPE_FLUSH; + + + /* Read the Data returned in the PEX Data register */ + pexData = MV_REG_READ(PEX_CFG_DATA_REG(pexIf)); + + + DB(mvOsPrintf(" got : %x \n",pexData)); + + return pexData; +} + +/******************************************************************************* +* mvPexConfigWrite - Write to configuration space +* +* DESCRIPTION: +* This function performs a 32 bit write to PEX configuration space. +* It supports both type 0 and type 1 of Configuration Transactions +* (local and over bridge). In order to write to local bus segment, use +* bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers +* will result configuration transaction of type 1 (over bridge). +* +* INPUT: +* pexIf - PEX interface number. +* bus - PEX segment bus number. +* dev - PEX device number. +* func - Function number. +* regOffs - Register offset. +* data - 32bit data. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexHwConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data) +{ + MV_U32 pexData = 0; + MV_U32 localDev,localBus; + + /* Parameter checking */ + if (PEX_DEFAULT_IF != pexIf) + { + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexConfigWrite: ERR. Invalid PEX interface %d\n", pexIf); + return MV_ERROR; + } + } + + if (dev >= MAX_PEX_DEVICES) + { + mvOsPrintf("mvPexConfigWrite: ERR. device number illigal %d\n",dev); + return MV_BAD_PARAM; + } + + if (func >= MAX_PEX_FUNCS) + { + mvOsPrintf("mvPexConfigWrite: ERR. function number illigal %d\n", func); + return MV_ERROR; + } + + if (bus >= MAX_PEX_BUSSES) + { + mvOsPrintf("mvPexConfigWrite: ERR. bus number illigal %d\n", bus); + return MV_ERROR; + } + + + + localDev = mvPexLocalDevNumGet(pexIf); + localBus = mvPexLocalBusNumGet(pexIf); + + /* in PCI Express we have only one device number other than ourselves*/ + /* and this number is the first number we encounter + else than the localDev that can be any valid dev number*/ + /* pex spec define return on config read/write on any device */ + if (bus == localBus) + { + + if (localDev == 0) + { + /* if local dev is 0 then the first number we encounter + after 0 is 1 */ + if ((dev != 1)&&(dev != localDev)) + { + return MV_ERROR; + } + + } + else + { + /* if local dev is not 0 then the first number we encounter + is 0 */ + + if ((dev != 0)&&(dev != localDev)) + { + return MV_ERROR; + } + } + + + } + + /* if we are not accessing ourselves , then check the link */ + if ((dev != localDev) || (bus != localBus) ) + { + /* workarround */ + /* when no link return MV_ERROR */ + + pexData = MV_REG_READ(PEX_STATUS_REG(pexIf)); + + if ((pexData & PXSR_DL_DOWN)) + { + return MV_ERROR; + } + + } + + pexData =0; + + /* Creating PEX address to be passed */ + pexData |= (bus << PXCAR_BUS_NUM_OFFS); + pexData |= (dev << PXCAR_DEVICE_NUM_OFFS); + pexData |= (func << PXCAR_FUNC_NUM_OFFS); + pexData |= (regOff & PXCAR_REG_NUM_MASK); /* lgacy register space */ + /* extended register space */ + pexData |=(((regOff & PXCAR_REAL_EXT_REG_NUM_MASK) >> + PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS); + pexData |= PXCAR_CONFIG_EN; + + DB(mvOsPrintf(" CfWr:If=%x bus=%x func=%x dev=%x regOff=%x data=%x \n", + pexIf,bus,func,dev,regOff,data,pexData) ); + + /* Write the address to the PEX configuration address register */ + MV_REG_WRITE(PEX_CFG_ADDR_REG(pexIf), pexData); + + /* Clear CPU pipe. Important where CPU can perform OOO execution */ + CPU_PIPE_FLUSH; + + + /* Write the Data passed to the PEX Data register */ + MV_REG_WRITE(PEX_CFG_DATA_REG(pexIf), data); + + return MV_OK; +} + + + +void resetPexConfig(MV_U32 pexIf, MV_U32 bus, MV_U32 dev) +{ + MV_U32 tData; + MV_U32 i; + + /* restore the PEX configuration to initialization state */ + /* in case PEX P2P call recursive and reset config */ + tData = mvPexHwConfigRead (pexIf, bus, dev, 0x0, 0x0); + if(tData != 0xffffffff) + { + /* agent had been found - check whether P2P */ + tData = mvPexHwConfigRead (pexIf, bus, dev, 0x0, 0x8); + if((tData & 0xffff0000) == 0x06040000) + {/* P2P */ + /* get the sec bus and the subordinate */ + MV_U32 secBus; + tData = mvPexHwConfigRead (pexIf, bus, dev, 0x0, 0x18); + secBus = ((tData >> 8) & 0xff); + /* now scan on sec bus */ + for(i = 0;i < 0xff;i++) + { + resetPexConfig(pexIf, secBus, i); + } + /* now reset this device */ + DB(mvOsPrintf("Reset bus %d dev %d\n", bus, dev)); + mvPexHwConfigWrite(pexIf, bus, dev, 0x0, 0x18, 0x0); + } + } +} + + diff --git a/board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.h b/board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.h new file mode 100644 index 0000000..82eb72d --- /dev/null +++ b/board/mv_feroceon/mv_hal/pex/mvVrtBrgPex.h @@ -0,0 +1,82 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCVRTBRGPEXH +#define __INCVRTBRGPEXH + + +/* Global Functions prototypes */ +/* mvPexInit - Initialize PEX interfaces*/ +MV_STATUS mvPexVrtBrgInit(MV_U32 pexIf); + +/* mvPexConfigRead - Read from configuration space */ +MV_U32 mvPexVrtBrgConfigRead (MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func,MV_U32 regOff); + +/* mvPexConfigWrite - Write to configuration space */ +MV_STATUS mvPexVrtBrgConfigWrite(MV_U32 pexIf, MV_U32 bus, MV_U32 dev, + MV_U32 func, MV_U32 regOff, MV_U32 data); + + +#endif /* #ifndef __INCPEXH */ diff --git a/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c new file mode 100644 index 0000000..cb08bc5 --- /dev/null +++ b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.c @@ -0,0 +1,321 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "rtc/ext_rtc/mvDS1339.h" +#include "rtc/ext_rtc/mvDS1339Reg.h" + +static MV_VOID mvRtcCharWrite(MV_U32 offset, MV_U8 data); +static MV_VOID mvRtcCharRead(MV_U32 offset, MV_U8 *data); + + +/******************************************************************************* +* mvRtcDS1339TimeSet - Set the Alarm of the Real time clock +* +* DESCRIPTION: +* +* INPUT: +* time - A pointer to a structure RTC_TIME (defined in mvDS1339.h). +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcDS1339AlarmSet(MV_RTC_TIME* mvTime) +{ + return; +} +/******************************************************************************* +* mvRtcDS1339TimeSet - Update the Real Time Clock. +* +* DESCRIPTION: +* This function sets a new time and date to the RTC from the given +* structure RTC_TIME . All fields within the structure must be assigned +* with a value prior to the use of this function. +* +* INPUT: +* time - A pointer to a structure RTC_TIME (defined in mvDS1339.h). +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcDS1339TimeSet(MV_RTC_TIME* mvTime) +{ + MV_U8 tempValue; + MV_U8 tens; + MV_U8 single; + + /* seconds */ + tens = mvTime->seconds / 10; + single = mvTime->seconds % 10; + tempValue = ((tens << RTC_CLOCK_10SECONDS_SHF )& RTC_CLOCK_10SECONDS_MSK )| + (( single << RTC_CLOCK_SECONDS_SHF)&RTC_CLOCK_SECONDS_MSK) ; + mvRtcCharWrite(RTC_CLOCK_SECONDS,tempValue); + + /* minutes */ + tens = mvTime->minutes / 10; + single = mvTime->minutes % 10; + tempValue = ((tens << RTC_CLOCK_10MINUTES_SHF )& RTC_CLOCK_10MINUTES_MSK )| + (( single << RTC_CLOCK_MINUTES_SHF)& RTC_CLOCK_MINUTES_MSK) ; + mvRtcCharWrite(RTC_CLOCK_MINUTES,tempValue); + + /* hours (24) */ + tens = mvTime->hours / 10; + single = mvTime->hours % 10; + tempValue = ((tens << RTC_CLOCK_10HOURS_SHF) & RTC_CLOCK_10HOURS_MSK2 )| + (( single << RTC_CLOCK_HOURS_SHF ) & RTC_CLOCK_HOURS_MSK); + mvRtcCharWrite(RTC_CLOCK_HOUR,tempValue); + + /* day */ + single = mvTime->day; + tempValue = ((single << RTC_CLOCK_DAY_SHF ) & RTC_CLOCK_DAY_MSK) ; + mvRtcCharWrite(RTC_CLOCK_DAY,tempValue); + + /* date */ + tens = mvTime->date / 10; + single = mvTime->date % 10; + tempValue = ((tens << RTC_CLOCK_10DATE_SHF ) & RTC_CLOCK_10DATE_MSK )| + ((single << RTC_CLOCK_DATE_SHF )& RTC_CLOCK_DATE_MSK) ; + + /* month */ + mvRtcCharWrite( RTC_CLOCK_DATE,tempValue); + tens = mvTime->month / 10; + single = mvTime->month % 10; + tempValue = ((tens << RTC_CLOCK_10MONTH_SHF ) & RTC_CLOCK_10MONTH_MSK )| + ((single << RTC_CLOCK_MONTH_SHF)& RTC_CLOCK_MONTH_MSK); + mvRtcCharWrite( RTC_CLOCK_MONTH_CENTURY,tempValue); + + /* year */ + tens = mvTime->year / 10; + single = mvTime->year % 10; + tempValue = ((tens << RTC_CLOCK_10YEAR_SHF) & RTC_CLOCK_10YEAR_MSK )| + ((single << RTC_CLOCK_YEAR_SHF) & RTC_CLOCK_YEAR_MSK); + mvRtcCharWrite(RTC_CLOCK_YEAR,tempValue); + + return; +} + +/******************************************************************************* +* mvRtcDS1339TimeGet - Read the time from the RTC. +* +* DESCRIPTION: +* This function reads the current time and date from the RTC into the +* structure RTC_TIME (defined in mvDS1339.h). +* +* INPUT: +* time - A pointer to a structure TIME (defined in mvDS1339.h). +* +* OUTPUT: +* The structure RTC_TIME is updated with the time read from the RTC. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcDS1339TimeGet(MV_RTC_TIME* mvTime) +{ + MV_U8 tempValue; + MV_U32 tens; + MV_U32 single; + + /* seconds */ + mvRtcCharRead(RTC_CLOCK_SECONDS,&tempValue); + tens = ( tempValue & RTC_CLOCK_10SECONDS_MSK) >> RTC_CLOCK_10SECONDS_SHF; + single = (tempValue & RTC_CLOCK_SECONDS_MSK) >> RTC_CLOCK_SECONDS_SHF ; + mvTime->seconds = 10*tens + single; + + /* minutes */ + mvRtcCharRead(RTC_CLOCK_MINUTES,&tempValue); + tens = (tempValue & RTC_CLOCK_10MINUTES_MSK) >> RTC_CLOCK_10MINUTES_SHF; + single = (tempValue & RTC_CLOCK_MINUTES_MSK) >> RTC_CLOCK_MINUTES_SHF; + mvTime->minutes = 10*tens + single; + + /* hours */ + mvRtcCharRead(RTC_CLOCK_HOUR,&tempValue); + tens = (tempValue & RTC_CLOCK_10HOURS_MSK2) >> RTC_CLOCK_10HOURS_SHF; + single = (tempValue & RTC_CLOCK_HOURS_MSK) >> RTC_CLOCK_HOURS_SHF; + mvTime->hours = 10*tens + single; + + /* day */ + mvRtcCharRead(RTC_CLOCK_DAY,&tempValue); + mvTime->day = (tempValue & RTC_CLOCK_DAY_MSK) >> RTC_CLOCK_DAY_SHF ; + + /* date */ + mvRtcCharRead(RTC_CLOCK_DATE,&tempValue); + tens = (tempValue & RTC_CLOCK_10DATE_MSK) >> RTC_CLOCK_10DATE_SHF; + single = (tempValue & RTC_CLOCK_DATE_MSK) >> RTC_CLOCK_DATE_SHF; + mvTime->date = 10*tens + single; + + /* century/ month */ + mvRtcCharRead(RTC_CLOCK_MONTH_CENTURY,&tempValue); + tens = (tempValue & RTC_CLOCK_10MONTH_MSK) >> RTC_CLOCK_10MONTH_SHF; + single = (tempValue & RTC_CLOCK_MONTH_MSK) >> RTC_CLOCK_MONTH_SHF; + mvTime->month = 10*tens + single; + mvTime->century = (tempValue & RTC_CLOCK_CENTURY_MSK)>>RTC_CLOCK_CENTURY_SHF; + + /* year */ + mvRtcCharRead(RTC_CLOCK_YEAR,&tempValue); + tens = (tempValue & RTC_CLOCK_10YEAR_MSK) >> RTC_CLOCK_10YEAR_SHF; + single = (tempValue & RTC_CLOCK_YEAR_MSK) >> RTC_CLOCK_YEAR_SHF; + mvTime->year = 10*tens + single; + + return; +} + +/******************************************************************************* +* mvRtcDS1339Init - Initialize the clock. +* +* DESCRIPTION: +* This function initialize the clock registers and read\write functions +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcDS1339Init(MV_VOID) +{ + MV_U8 ucTemp; + + /* We will disable interrupts as default .*/ + mvRtcCharRead(RTC_CONTROL,&ucTemp); + ucTemp|=RTC_CONTROL_INTCN_BIT; + mvRtcCharWrite(RTC_CONTROL,ucTemp); + + /* disable trickle */ + mvRtcCharWrite(RTC_TRICKLE_CHARGE,0); + + return; +} + + +/* assumption twsi is initialized !!! */ +/******************************************************************************* +* mvRtcCharRead - Read a char from the RTC. +* +* DESCRIPTION: +* This function reads a char from the RTC offset. +* +* INPUT: +* offset - offset +* +* OUTPUT: +* data - char read from offset offset. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID mvRtcCharRead(MV_U32 offset, MV_U8 *data) +{ + MV_TWSI_SLAVE twsiSlave; + + twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet(); + twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet(); + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = offset; + twsiSlave.moreThen256 = MV_FALSE; + mvTwsiRead (MV_BOARD_RTC_I2C_CHANNEL, &twsiSlave, data, 1); + return; +} + +/******************************************************************************* +* mvRtcCharWrite - Write a char from the RTC. +* +* DESCRIPTION: +* This function writes a char to the RTC offset. +* +* INPUT: +* offset - offset +* +* OUTPUT: +* data - char write to addr address. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID mvRtcCharWrite(MV_U32 offset, MV_U8 data) +{ + MV_TWSI_SLAVE twsiSlave; + + twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet(); + twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet(); + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = offset; + twsiSlave.moreThen256 = MV_FALSE; + mvTwsiWrite (MV_BOARD_RTC_I2C_CHANNEL, &twsiSlave, &data, 1); + return; +} diff --git a/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h new file mode 100644 index 0000000..e2f9761 --- /dev/null +++ b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339.h @@ -0,0 +1,96 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDS1339h +#define __INCmvDS1339h + +#include "mvTypes.h" +#include "twsi/mvTwsi.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "boardEnv/mvBoardEnvSpec.h" + +typedef struct time +{ + MV_U8 seconds; + MV_U8 minutes; + MV_U8 hours; + MV_U8 day; + MV_U8 date; + MV_U8 month; + MV_U8 century; + MV_U8 year; +} MV_RTC_TIME; + +MV_VOID mvRtcDS1339Init(MV_VOID); + +MV_VOID mvRtcDS1339TimeSet(MV_RTC_TIME* time); + +MV_VOID mvRtcDS1339TimeGet(MV_RTC_TIME* time); + +MV_VOID mvRtcDS1339AlarmSet(MV_RTC_TIME* time); + + +#endif /* __INCmvDS1511h */ + diff --git a/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339Reg.h b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339Reg.h new file mode 100644 index 0000000..a9975a3 --- /dev/null +++ b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS1339Reg.h @@ -0,0 +1,368 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDS1339Regh +#define __INCmvDS1339Regh + +#ifndef MSK +#define MSK(n) ((1 << (n)) - 1) +#endif + +#define RTC_CLOCK_SECONDS 0x0 +#define RTC_CLOCK_MINUTES 0x1 +#define RTC_CLOCK_HOUR 0x2 +#define RTC_CLOCK_DAY 0x3 +#define RTC_CLOCK_DATE 0x4 +#define RTC_CLOCK_MONTH_CENTURY 0x5 +#define RTC_CLOCK_YEAR 0x6 +#define RTC_ALARM_SECONDS 0x7 +#define RTC_ALARM_MINUTES 0x8 +#define RTC_ALARM_HOUR 0x9 +#define RTC_ALARM_DAY_DATE 0xa +#define RTC_ALARM2_MINUTES 0xb +#define RTC_ALARM2_HOUR 0xc +#define RTC_ALARM2_DAY_DATE 0xd +#define RTC_CONTROL 0xe +#define RTC_STATUS 0xf +#define RTC_TRICKLE_CHARGE 0x10 + +#define FIRST_REG_OFF RTC_CLOCK_SECONDS +#define LAST_REG_OFF RTC_TRICKLE_CHARGE + + +/* RTC_CLOCK_SECONDS 0x0*/ + +#define RTC_CLOCK_SECONDS_SHF 0 +#define RTC_CLOCK_SECONDS_MSK (MSK(4)<seconds / 10; + single = time->seconds % 10; + tempValue = ((tens << RTC_CLOCK_10SECONDS_SHF )& RTC_CLOCK_10SECONDS_MSK )| + (( single << RTC_CLOCK_SECONDS_SHF)&RTC_CLOCK_SECONDS_MSK) ; + mvRtcCharWrite(RTC_CLOCK_SECONDS,tempValue); + + /* minutes */ + tens = time->minutes / 10; + single = time->minutes % 10; + tempValue = ((tens << RTC_CLOCK_10MINUTES_SHF )& RTC_CLOCK_10MINUTES_MSK )| + (( single << RTC_CLOCK_MINUTES_SHF)& RTC_CLOCK_MINUTES_MSK) ; + mvRtcCharWrite(RTC_CLOCK_MINUTES,tempValue); + + /* hours (24) */ + tens = time->hours / 10; + single = time->hours % 10; + tempValue = ((tens << RTC_CLOCK_10HOURS_SHF) & RTC_CLOCK_10HOURS_MSK2 )| + (( single << RTC_CLOCK_HOURS_SHF ) & RTC_CLOCK_HOURS_MSK); + mvRtcCharWrite(RTC_CLOCK_HOUR,tempValue); + + /* day */ + single = ++(time->day); + tempValue = ((single << RTC_CLOCK_DAY_SHF ) & RTC_CLOCK_DAY_MSK) ; + mvRtcCharWrite(RTC_CLOCK_DAY,tempValue); + + /* date */ + tens = time->date / 10; + single = time->date % 10; + tempValue = ((tens << RTC_CLOCK_10DATE_SHF ) & RTC_CLOCK_10DATE_MSK )| + ((single << RTC_CLOCK_DATE_SHF )& RTC_CLOCK_DATE_MSK) ; + + /* month */ + mvRtcCharWrite( RTC_CLOCK_DATE,tempValue); + tens = time->month / 10; + single = time->month % 10; + tempValue = ((tens << RTC_CLOCK_10MONTH_SHF ) & RTC_CLOCK_10MONTH_MSK )| + ((single << RTC_CLOCK_MONTH_SHF)& RTC_CLOCK_MONTH_MSK); + mvRtcCharWrite( RTC_CLOCK_MONTH_CENTURY,tempValue); + + /* year */ + tens = time->year / 10; + single = time->year % 10; + tempValue = ((tens << RTC_CLOCK_10YEAR_SHF) & RTC_CLOCK_10YEAR_MSK )| + ((single << RTC_CLOCK_YEAR_SHF) & RTC_CLOCK_YEAR_MSK); + mvRtcCharWrite(RTC_CLOCK_YEAR,tempValue); + + return; +} + +/******************************************************************************* +* mvRtcDS133xTimeGet - Read the time from the RTC. +* +* DESCRIPTION: +* This function reads the current time and date from the RTC into the +* structure RTC_TIME (defined in mvDS133x.h). +* +* INPUT: +* time - A pointer to a structure TIME (defined in mvDS133x.h). +* +* OUTPUT: +* The structure RTC_TIME is updated with the time read from the RTC. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcDS133xTimeGet(MV_RTC_TIME* time) +{ + MV_U8 tempValue; + MV_U32 tens; + MV_U32 single; + + /* seconds */ + mvRtcCharRead(RTC_CLOCK_SECONDS,&tempValue); + tens = ( tempValue & RTC_CLOCK_10SECONDS_MSK) >> RTC_CLOCK_10SECONDS_SHF; + single = (tempValue & RTC_CLOCK_SECONDS_MSK) >> RTC_CLOCK_SECONDS_SHF ; + time->seconds = 10*tens + single; + + /* minutes */ + mvRtcCharRead(RTC_CLOCK_MINUTES,&tempValue); + tens = (tempValue & RTC_CLOCK_10MINUTES_MSK) >> RTC_CLOCK_10MINUTES_SHF; + single = (tempValue & RTC_CLOCK_MINUTES_MSK) >> RTC_CLOCK_MINUTES_SHF; + time->minutes = 10*tens + single; + + /* hours */ + mvRtcCharRead(RTC_CLOCK_HOUR,&tempValue); + tens = (tempValue & RTC_CLOCK_10HOURS_MSK2) >> RTC_CLOCK_10HOURS_SHF; + single = (tempValue & RTC_CLOCK_HOURS_MSK) >> RTC_CLOCK_HOURS_SHF; + time->hours = 10*tens + single; + + /* day */ + mvRtcCharRead(RTC_CLOCK_DAY,&tempValue); + time->day = (tempValue & RTC_CLOCK_DAY_MSK) >> RTC_CLOCK_DAY_SHF ; + time->day--; + + /* date */ + mvRtcCharRead(RTC_CLOCK_DATE,&tempValue); + tens = (tempValue & RTC_CLOCK_10DATE_MSK) >> RTC_CLOCK_10DATE_SHF; + single = (tempValue & RTC_CLOCK_DATE_MSK) >> RTC_CLOCK_DATE_SHF; + time->date = 10*tens + single; + + /* century/ month */ + mvRtcCharRead(RTC_CLOCK_MONTH_CENTURY,&tempValue); + tens = (tempValue & RTC_CLOCK_10MONTH_MSK) >> RTC_CLOCK_10MONTH_SHF; + single = (tempValue & RTC_CLOCK_MONTH_MSK) >> RTC_CLOCK_MONTH_SHF; + time->month = 10*tens + single; + time->century = (tempValue & RTC_CLOCK_CENTURY_MSK)>>RTC_CLOCK_CENTURY_SHF; + + /* year */ + mvRtcCharRead(RTC_CLOCK_YEAR,&tempValue); + tens = (tempValue & RTC_CLOCK_10YEAR_MSK) >> RTC_CLOCK_10YEAR_SHF; + single = (tempValue & RTC_CLOCK_YEAR_MSK) >> RTC_CLOCK_YEAR_SHF; + time->year = 10*tens + single; + + return; +} + +/******************************************************************************* +* mvRtcDS1339Init - Initialize the clock. +* +* DESCRIPTION: +* This function initialize the clock registers and read\write functions +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcDS1339Init(MV_VOID) +{ + MV_U8 ucTemp; + + /* We will disable interrupts as default .*/ + mvRtcCharRead(RTC1339_CONTROL,&ucTemp); + ucTemp|=RTC_CONTROL_INTCN_BIT; + mvRtcCharWrite(RTC1339_CONTROL,ucTemp); + + /* disable trickle */ + mvRtcCharWrite(RTC_TRICKLE_CHARGE,0); + + return; +} + + +/******************************************************************************* +* mvRtcDS1338Init - Initialize the clock. +* +* DESCRIPTION: +* This function initialize the clock registers and read\write functions +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcDS1338Init(MV_VOID) +{ + MV_U8 ucTemp; + + /* We will enable OSC .*/ + mvRtcCharRead(RTC_CLOCK_SECONDS,&ucTemp); + ucTemp &=~RTC_CONTROL_EOSC_MSK; + mvRtcCharWrite(RTC_CLOCK_SECONDS,ucTemp); + + return; +} + +/* assumption twsi is initialized !!! */ +/******************************************************************************* +* mvRtcCharRead - Read a char from the RTC. +* +* DESCRIPTION: +* This function reads a char from the RTC offset. +* +* INPUT: +* offset - offset +* +* OUTPUT: +* data - char read from offset offset. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID mvRtcCharRead(MV_U32 offset, MV_U8 *data) +{ + MV_TWSI_SLAVE twsiSlave; + + twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet(); + twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet(); + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = offset; + twsiSlave.moreThen256 = MV_FALSE; + mvTwsiRead (RTC_I2C_CH, &twsiSlave, data, 1); + + return; +} + +/******************************************************************************* +* mvRtcCharWrite - Write a char from the RTC. +* +* DESCRIPTION: +* This function writes a char to the RTC offset. +* +* INPUT: +* offset - offset +* +* OUTPUT: +* data - char write to addr address. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID mvRtcCharWrite(MV_U32 offset, MV_U8 data) +{ + MV_TWSI_SLAVE twsiSlave; + + twsiSlave.slaveAddr.type = mvBoardRtcTwsiAddrTypeGet(); + twsiSlave.slaveAddr.address = mvBoardRtcTwsiAddrGet(); + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = offset; + twsiSlave.moreThen256 = MV_FALSE; + mvTwsiWrite (RTC_I2C_CH, &twsiSlave, &data, 1); + + return; +} diff --git a/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h new file mode 100644 index 0000000..e73f310 --- /dev/null +++ b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133x.h @@ -0,0 +1,100 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDS133xh +#define __INCmvDS133xh + +#include "mvTypes.h" +#include "twsi/mvTwsi.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "boardEnv/mvBoardEnvSpec.h" + +/*******************************************************************************/ +/* Support: DS1338 and DS1339 */ +/*******************************************************************************/ +typedef struct time +{ + MV_U8 seconds; + MV_U8 minutes; + MV_U8 hours; + MV_U8 day; + MV_U8 date; + MV_U8 month; + MV_U8 century; + MV_U8 year; +} MV_RTC_TIME; + +MV_VOID mvRtcDS1339Init(MV_VOID); +MV_VOID mvRtcDS1338Init(MV_VOID); + +MV_VOID mvRtcDS133xTimeSet(MV_RTC_TIME* time); + +MV_VOID mvRtcDS133xTimeGet(MV_RTC_TIME* time); + +MV_VOID mvRtcDS133xAlarmSet(MV_RTC_TIME* time); + + +#endif /* __INCmvDS133xh */ + diff --git a/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133xReg.h b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133xReg.h new file mode 100644 index 0000000..59b6251 --- /dev/null +++ b/board/mv_feroceon/mv_hal/rtc/ext_rtc/mvDS133xReg.h @@ -0,0 +1,369 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvDS133xRegh +#define __INCmvDS133xRegh + +#ifndef MSK +#define MSK(n) ((1 << (n)) - 1) +#endif + +#define RTC_CLOCK_SECONDS 0x0 +#define RTC_CLOCK_MINUTES 0x1 +#define RTC_CLOCK_HOUR 0x2 +#define RTC_CLOCK_DAY 0x3 +#define RTC_CLOCK_DATE 0x4 +#define RTC_CLOCK_MONTH_CENTURY 0x5 +#define RTC_CLOCK_YEAR 0x6 +#define RTC_ALARM_SECONDS 0x7 +#define RTC_ALARM_MINUTES 0x8 +#define RTC_ALARM_HOUR 0x9 +#define RTC_ALARM_DAY_DATE 0xa +#define RTC_ALARM2_MINUTES 0xb +#define RTC_ALARM2_HOUR 0xc +#define RTC_ALARM2_DAY_DATE 0xd +#define RTC1339_CONTROL 0xe +#define RTC1338_CONTROL 0x7 +#define RTC_STATUS 0xf +#define RTC_TRICKLE_CHARGE 0x10 + +#define FIRST_REG_OFF RTC_CLOCK_SECONDS +#define LAST_REG_OFF RTC_TRICKLE_CHARGE + + +/* RTC_CLOCK_SECONDS 0x0*/ + +#define RTC_CLOCK_SECONDS_SHF 0 +#define RTC_CLOCK_SECONDS_MSK (MSK(4)<seconds / 10; + single = mvTime->seconds % 10; + timeVal |= ((tens << RTC_TIME_10SECONDS_SHF) & RTC_TIME_10SECONDS_MSK) | + (( single << RTC_TIME_SECONDS_SHF) & RTC_TIME_SECONDS_MSK); + + /* minutes */ + tens = mvTime->minutes / 10; + single = mvTime->minutes % 10; + timeVal |= ((tens << RTC_TIME_10MINUTES_SHF) & RTC_TIME_10MINUTES_MSK) | + (( single << RTC_TIME_MINUTES_SHF) & RTC_TIME_MINUTES_MSK); + + /* hours (24) */ + tens = mvTime->hours / 10; + single = mvTime->hours % 10; + timeVal |= ((tens << RTC_TIME_10HOUR_SHF) & RTC_TIME_10HOUR_MSK) | + (( single << RTC_TIME_HOUR_SHF) & RTC_TIME_HOUR_MSK); + + /* day */ + single = ++(mvTime->day); + timeVal |= ((single << RTC_TIME_DAY_SHF ) & RTC_TIME_DAY_MSK); + + /* Update RTC Time Register */ + MV_REG_WRITE(RTC_TIME_REG, timeVal); + + /* date */ + tens = mvTime->date / 10; + single = mvTime->date % 10; + dateVal = ((tens << RTC_DATE_10DAY_SHF) & RTC_DATE_10DAY_MSK) | + (( single << RTC_DATE_DAY_SHF) & RTC_DATE_DAY_MSK); + + /* month */ + tens = mvTime->month / 10; + single = mvTime->month % 10; + dateVal |= ((tens << RTC_DATE_10MONTH_SHF) & RTC_DATE_10MONTH_MSK) | + (( single << RTC_DATE_MONTH_SHF) & RTC_DATE_MONTH_MSK); + + /* year */ + tens = mvTime->year / 10; + single = mvTime->year % 10; + dateVal |= ((tens << RTC_DATE_10YEAR_SHF) & RTC_DATE_10YEAR_MSK) | + (( single << RTC_DATE_YEAR_SHF) & RTC_DATE_YEAR_MSK); + + /* Update RTC Date Register */ + MV_REG_WRITE(RTC_DATE_REG, dateVal); + + + return; +} + +/******************************************************************************* +* mvRtcTimeGet - Read the time from the RTC. +* +* DESCRIPTION: +* This function reads the current time and date from the RTC into the +* structure RTC_TIME (defined in mv.h). +* +* INPUT: +* time - A pointer to a structure TIME (defined in mv.h). +* +* OUTPUT: +* The structure RTC_TIME is updated with the time read from the RTC. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcTimeGet(MV_RTC_TIME* mvTime) +{ + MV_U32 timeVal; + MV_U32 dateVal; + MV_U8 tens; + MV_U8 single; + + /* read Time register */ + timeVal = MV_REG_READ(RTC_TIME_REG); + + /* seconds */ + tens = ((timeVal & RTC_TIME_10SECONDS_MSK) >> RTC_TIME_10SECONDS_SHF); + single = ((timeVal & RTC_TIME_SECONDS_MSK) >> RTC_TIME_SECONDS_SHF); + mvTime->seconds = 10*tens + single; + + /* minutes */ + tens = ((timeVal & RTC_TIME_10MINUTES_MSK) >> RTC_TIME_10MINUTES_SHF); + single = ((timeVal & RTC_TIME_MINUTES_MSK) >> RTC_TIME_MINUTES_SHF); + mvTime->minutes = 10*tens + single; + + /* hours */ + tens = ((timeVal & RTC_TIME_10HOUR_MSK) >> RTC_TIME_10HOUR_SHF); + single = ((timeVal & RTC_TIME_HOUR_MSK) >> RTC_TIME_HOUR_SHF); + mvTime->hours = 10*tens + single; + + /* day */ + mvTime->day = ((timeVal & RTC_TIME_DAY_MSK) >> RTC_TIME_DAY_SHF); + mvTime->day--; + + /* read Date register */ + dateVal = MV_REG_READ(RTC_DATE_REG); + + /* day */ + tens = ((dateVal & RTC_DATE_10DAY_MSK) >> RTC_DATE_10DAY_SHF); + single = ((dateVal & RTC_DATE_DAY_MSK) >> RTC_DATE_DAY_SHF); + mvTime->date = 10*tens + single; + + /* month */ + tens = ((dateVal & RTC_DATE_10MONTH_MSK) >> RTC_DATE_10MONTH_SHF); + single = ((dateVal & RTC_DATE_MONTH_MSK) >> RTC_DATE_MONTH_SHF); + mvTime->month = 10*tens + single; + + /* year */ + tens = ((dateVal & RTC_DATE_10YEAR_MSK) >> RTC_DATE_10YEAR_SHF); + single = ((dateVal & RTC_DATE_YEAR_MSK) >> RTC_DATE_YEAR_SHF); + mvTime->year = 10*tens + single; + + return; +} + +/******************************************************************************* +* mvRtcInit - Initialize the clock. +* +* DESCRIPTION: +* This function initialize the RTC integrated unit. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvRtcInit(MV_VOID) +{ + return; +} diff --git a/board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtc.h b/board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtc.h new file mode 100644 index 0000000..44201aa --- /dev/null +++ b/board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtc.h @@ -0,0 +1,93 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvRtch +#define __INCmvRtch + +#include "mvTypes.h" +#include "ctrlEnv/mvCtrlEnvLib.h" + +typedef struct time +{ + MV_U8 seconds; + MV_U8 minutes; + MV_U8 hours; + MV_U8 day; + MV_U8 date; + MV_U8 month; + MV_U8 century; + MV_U8 year; +} MV_RTC_TIME; + +MV_VOID mvRtcInit(MV_VOID); + +MV_VOID mvRtcTimeSet(MV_RTC_TIME* time); + +MV_VOID mvRtcTimeGet(MV_RTC_TIME* time); + +MV_VOID mvRtcAlarmSet(MV_RTC_TIME* time); + +#endif /* __INCmvRtch */ + diff --git a/board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtcReg.h b/board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtcReg.h new file mode 100644 index 0000000..9d4800e --- /dev/null +++ b/board/mv_feroceon/mv_hal/rtc/integ_rtc/mvRtcReg.h @@ -0,0 +1,118 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvRtcRegh +#define __INCmvRtcRegh + + +/* RTC Time Register */ +#define RTC_TIME_REG 0x10300 + +/* RTC Date Register */ +#define RTC_DATE_REG 0x10304 + + +/* RTC Time Bit Definitions */ +#define RTC_TIME_SECONDS_SHF 0 +#define RTC_TIME_SECONDS_MSK (0xF << RTC_TIME_SECONDS_SHF) +#define RTC_TIME_10SECONDS_SHF 4 +#define RTC_TIME_10SECONDS_MSK (0x7 << RTC_TIME_10SECONDS_SHF) + +#define RTC_TIME_MINUTES_SHF 8 +#define RTC_TIME_MINUTES_MSK (0xF << RTC_TIME_MINUTES_SHF) +#define RTC_TIME_10MINUTES_SHF 12 +#define RTC_TIME_10MINUTES_MSK (0x7 << RTC_TIME_10MINUTES_SHF) + +#define RTC_TIME_HOUR_SHF 16 +#define RTC_TIME_HOUR_MSK (0xF << RTC_TIME_HOUR_SHF) +#define RTC_TIME_10HOUR_SHF 20 +#define RTC_TIME_10HOUR_MSK (0x3 << RTC_TIME_10HOUR_SHF) + + +#define RTC_TIME_HOUR_FORMAT_SHF 22 +#define RTC_TIME_HOUR_FORMAT_12_MSK (1 << RTC_TIME_HOUR_FORMAT_SHF) +#define RTC_TIME_HOUR_FORMAT_24_MSK (0 << RTC_TIME_HOUR_FORMAT_SHF) + +#define RTC_TIME_DAY_SHF 24 +#define RTC_TIME_DAY_MSK (0x7 << RTC_TIME_DAY_SHF) + +/* RTC Date Bit Definitions */ +#define RTC_DATE_DAY_SHF 0 +#define RTC_DATE_DAY_MSK (0xF << RTC_DATE_DAY_SHF) +#define RTC_DATE_10DAY_SHF 4 +#define RTC_DATE_10DAY_MSK (0x3 << RTC_DATE_10DAY_SHF) + +#define RTC_DATE_MONTH_SHF 8 +#define RTC_DATE_MONTH_MSK (0xF << RTC_DATE_MONTH_SHF) +#define RTC_DATE_10MONTH_SHF 12 +#define RTC_DATE_10MONTH_MSK (0x1 << RTC_DATE_10MONTH_SHF) + +#define RTC_DATE_YEAR_SHF 16 +#define RTC_DATE_YEAR_MSK (0xF << RTC_DATE_YEAR_SHF) +#define RTC_DATE_10YEAR_SHF 20 +#define RTC_DATE_10YEAR_MSK (0xF << RTC_DATE_10YEAR_SHF) + +#endif /* __INCmvRtcRegh */ + diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.c b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.c new file mode 100644 index 0000000..8c9db03 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.c @@ -0,0 +1,194 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvLog - C File for implementation of the core driver logger +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* +*******************************************************************************/ +#include "mvOsS.h" + + +#if defined (MV_LOG_DEBUG) || defined (MV_LOG_ERROR) + +const char* mvLogMsgType[MV_MAX_MESSAGE_TYPE] = { + " (FATAL_ERROR) ", + " (ERROR) ", + " (DEBUG INIT) ", + " (DEBUG INTERRUPTS) ", + " (DEBUG SATA LINK) ", + " (DEBUG UDMA COMMAND) ", + " (DEBUG NON UDMA COMMAND) ", + " (DEBUG PM) ", + " (DEBUG) ", + " (INFO) ", +}; + +static MV_LOG_FILTER_HEADER mvLogInstance[MV_MAX_LOG_MODULES] = +{ + {MV_FALSE, 0, NULL}, + {MV_FALSE, 0, NULL}, + {MV_FALSE, 0, NULL}, + {MV_FALSE, 0, NULL}, + {MV_FALSE, 0, NULL}, + {MV_FALSE, 0, NULL}, + {MV_FALSE, 0, NULL}, + {MV_FALSE, 0, NULL}, +}; + +static char szMessageBuffer[1024]; + + +MV_BOOLEAN mvLogRegisterModule(MV_U8 moduleId, MV_U32 filterMask, const char* name) +{ + if (moduleId >= MV_MAX_LOG_MODULES) + { + return MV_FALSE; + } + if (mvLogInstance[moduleId].used == MV_TRUE) + { + return MV_FALSE; + } + if (name == NULL) + { + return MV_FALSE; + } + mvLogInstance[moduleId].filterMask = filterMask; + mvLogInstance[moduleId].name = name; + mvLogInstance[moduleId].used = MV_TRUE; + return MV_TRUE; +} + +MV_BOOLEAN mvLogSetModuleFilter(MV_U8 moduleId, MV_U32 filterMask) +{ + if (moduleId >= MV_MAX_LOG_MODULES) + { + return MV_FALSE; + } + if (mvLogInstance[moduleId].used == MV_FALSE) + { + return MV_FALSE; + } + mvLogInstance[moduleId].filterMask = filterMask; + return MV_TRUE; +} + + +MV_U32 mvLogGetModuleFilter(MV_U8 moduleId) +{ + if (moduleId >= MV_MAX_LOG_MODULES) + { + return 0; + } + if (mvLogInstance[moduleId].used == MV_FALSE) + { + return 0; + } + return mvLogInstance[moduleId].filterMask; +} + +void mvLogMsg(MV_U8 moduleId, MV_U32 type, const char* format, ...) +{ + int len; + va_list args; + + if (moduleId >= MV_MAX_LOG_MODULES) + { + return; + } + if ((moduleId != MV_RAW_MSG_ID) && + ((mvLogInstance[moduleId].used == MV_FALSE) || + ((mvLogInstance[moduleId].filterMask & type) == 0))) + { + return; + } + if ((moduleId != MV_RAW_MSG_ID) && (type & 0x1ff)) + { + MV_U8 msgType = 0; + /* find least significant 1*/ + while (msgType < MV_MAX_MESSAGE_TYPE) + { + if (type & ( 1 << msgType)) + { + break; + } + msgType++; + } + len = sprintf(szMessageBuffer, "%s%s", + mvLogInstance[moduleId].name, mvLogMsgType[msgType]); + } + else + { + len = 0; + } + va_start(args, format); + vsprintf(&szMessageBuffer[len], format, args); + va_end(args); + MV_LOG_PRINT("%s", szMessageBuffer); +} +#endif diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.h b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.h new file mode 100644 index 0000000..e94806d --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvLog.h @@ -0,0 +1,187 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvLog.h - Header File for CORE driver logger +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* +*******************************************************************************/ +#ifndef __INCmvLogh +#define __INCmvLogh + +#ifdef __cplusplus +extern "C" /*{*/ +#endif /* __cplusplus */ + +#include "mvOsS.h" + +/*-------------H file-----------------------------*/ +#define MV_DEBUG_FATAL_ERROR 0x01 +#define MV_DEBUG_ERROR 0x02 +#define MV_DEBUG_INIT 0x04 +#define MV_DEBUG_INTERRUPTS 0x08 +#define MV_DEBUG_SATA_LINK 0x10 +#define MV_DEBUG_UDMA_COMMAND 0x20 +#define MV_DEBUG_NON_UDMA_COMMAND 0x40 +#define MV_DEBUG_PM 0x80 +#define MV_DEBUG 0x100 +#define MV_DEBUG_INFO 0x200 + +#define MV_DEBUG_ENABLE_ALL 0x3FF + +#define MV_MAX_LOG_MODULES 16 +#define MV_MAX_MESSAGE_TYPE 10 +#define MV_RAW_MSG_ID 0xF + +typedef struct +{ + MV_BOOLEAN used; + MV_U32 filterMask; + const char *name; + char *filters; +} MV_LOG_FILTER_HEADER; + + +#if defined (MV_LOG_DEBUG) || defined (MV_LOG_ERROR) + #define MV_LOGGER 1 + #if defined (WIN32) +ULONG +_cdecl +DbgPrint( + PCH Format, + ... + ); + #define MV_LOG_PRINT DbgPrint + #elif defined (LINUX) + #define MV_LOG_PRINT printk + #elif defined __DOS__ + #define MV_LOG_PRINT printf + #elif defined __UBOOT__ + #define MV_LOG_PRINT printf + #else + #define MV_LOG_PRINT printf + #endif + + +MV_BOOLEAN mvLogRegisterModule(MV_U8 moduleId, MV_U32 filterMask, const char* name); +MV_BOOLEAN mvLogSetModuleFilter(MV_U8 moduleId, MV_U32 filterMask); +MV_U32 mvLogGetModuleFilter(MV_U8 moduleId); +void mvLogMsg(MV_U8 moduleId, MV_U32 type, const char* format, ...); + +#else /*defined (MV_LOG_DEBUG) || defined (MV_LOG_ERROR)*/ + + #undef MV_LOGGER + + #if defined (WIN32) + #define MV_LOG_PRINT + #define mvLogRegisterModule + #define mvLogGetModuleFilter + #define mvLogRegisterAllModules + #define mvLogMsg + + #elif defined (MV_LINUX) + #define MV_LOG_PRINT(x...) + #define mvLogRegisterModule(x...) + #define mvLogSetModuleFilter(x...) + #define mvLogGetModuleFilter(x...) + #define mvLogRegisterAllModules(x...) + #define mvLogMsg(x...) + + #elif defined (MV_UBOOT) + #define MV_LOG_PRINT(x...) + #define mvLogRegisterModule(x...) + #define mvLogSetModuleFilter(x...) + #define mvLogGetModuleFilter(x...) + #define mvLogRegisterAllModules(x...) + #define mvLogMsg(x...) + + #elif defined (__DOS__) + #define MV_LOG_PRINT() + #define mvLogRegisterModule() + #define mvLogSetModuleFilter() + #define mvLogGetModuleFilter() + #define mvLogRegisterAllModules() + #define mvLogMsg() + + #else + #define MV_LOG_PRINT + #define mvLogRegisterModule + #define mvLogSetModuleFilter + #define mvLogGetModuleFilter + #define mvLogRegisterAllModules + #define mvLogMsg + #endif + +#endif /*!defined (MV_LOG_DEBUG) && !defined (MV_LOG_ERROR)*/ + +#ifdef __cplusplus + +/*}*/ +#endif /* __cplusplus */ + +#endif + diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvOsS.h b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvOsS.h new file mode 100644 index 0000000..faa8963 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvOsS.h @@ -0,0 +1,90 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvOsSh +#define __INCmvOsSh + +#include "mvSysHwConfig.h" +/* Includes */ +#include "mvOs.h" + +#if defined(MV_LINUX) + +#include "mvOsSata.h" + +#elif defined(MV_UBOOT) + +#include "mvOsSata.h" + +#elif defined(MV_VXWORKS) + +#include "mvOsSVxw.h" + +#elif defined(MV_NETBSD) + +#include "mvOsSata.h" + +#endif + +#endif /* __INCmvOsSh */ diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvRegs.h b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvRegs.h new file mode 100644 index 0000000..8103666 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvRegs.h @@ -0,0 +1,416 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvRegs.h - Header file that includes the regs addresses +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmvRegs +#define __INCmvRegs +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* General Definitions */ +#define MV_BIT0 0x00000001 +#define MV_BIT1 0x00000002 +#define MV_BIT2 0x00000004 +#define MV_BIT3 0x00000008 +#define MV_BIT4 0x00000010 +#define MV_BIT5 0x00000020 +#define MV_BIT6 0x00000040 +#define MV_BIT7 0x00000080 +#define MV_BIT8 0x00000100 +#define MV_BIT9 0x00000200 +#define MV_BIT10 0x00000400 +#define MV_BIT11 0x00000800 +#define MV_BIT12 0x00001000 +#define MV_BIT13 0x00002000 +#define MV_BIT14 0x00004000 +#define MV_BIT15 0x00008000 +#define MV_BIT16 0x00010000 +#define MV_BIT17 0x00020000 +#define MV_BIT18 0x00040000 +#define MV_BIT19 0x00080000 +#define MV_BIT20 0x00100000 +#define MV_BIT21 0x00200000 +#define MV_BIT22 0x00400000 +#define MV_BIT23 0x00800000 +#define MV_BIT24 0x01000000 +#define MV_BIT25 0x02000000 +#define MV_BIT26 0x04000000 +#define MV_BIT27 0x08000000 +#define MV_BIT28 0x10000000 +#define MV_BIT29 0x20000000 +#define MV_BIT30 0x40000000 +#define MV_BIT31 0x80000000 + + +#define MV_PCI_REGS_OFFSET 0x0 + +/* PCI registers */ + +#define MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET 0x1d60 + +#define MV_MAIN_INTERRUPT_MASK_REG_OFFSET 0x1d64 +#define MV_MAIN_INTERRUPT_MASK_REG_ALL_BITS 0x7ffff +#define MV_MAIN_INTERRUPT_MASK_REG_PCIERR_BIT MV_BIT18 +#define MV_MAIN_INTERRUPT_HOST_SELF_INT_BIT MV_BIT23 + +#define MV_PCI_CONTROL_REG_OFFSET 0x1d68 +#define MV_PCI_CONTROL_REG_H2H_INT_BIT MV_BIT1 + +/* enable ports error, coalescing done and pci error*/ +#define MV_MAIN_INTERRUPT_MASK_ENABLE_ALL 0x6ab55 + +#define MV_PCI_DLL_STATUS_CONTROL_REG_OFFSET 0x1d20 +#define MV_PCI_COMMAND_REG_OFFSET 0xc00 +#define MV_PCI_COMMAND_REG_DEFAULT 0x0107E371 +#define MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY \ + (MV_BIT5|MV_BIT6|MV_BIT7|MV_BIT8|MV_BIT9|MV_BIT31) +#define MV_PCI_MWRITE_COMBINE_BIT MV_BIT4 +#define MV_PCI_MREAD_COMBINE_BIT MV_BIT5 + +#define MV_PCI_MODE_REG_OFFSET 0xd00 +#define MV_PCI_MODE_MASK 0x30 +#define MV_PCI_MODE_OFFSET 4 + +#define MV_PCI_DISCARD_TIMER_REG_OFFSET 0xd04 + +#define MV_PCI_MSI_TRIGGER_REG_OFFSET 0xc38 + +#define MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET 0xd2c + +#define MV_PCI_XBAR_IF_TIMEOUT_REG_OFFSET 0x1d04 + +#define MV_PCI_SERR_MASK_REG_OFFSET 0xc28 +#define MV_PCI_SERR_MASK_REG_ENABLE_ALL 0xd77fe6 + +#define MV_PCI_INTERRUPT_CAUSE_REG_OFFSET 0x1d58 + +#define MV_PCI_INTERRUPT_MASK_REG_OFFSET 0x1d5c + +#define MV_PCI_INTERRUPT_MASK_REG_ENABLE_ALL MV_PCI_SERR_MASK_REG_ENABLE_ALL + +#define MV_PCI_ERROR_LOW_ADDRESS_REG_OFFSET 0x1d40 + +#define MV_PCI_ERROR_HIGH_ADDRESS_REG_OFFSET 0x1d44 + +#define MV_PCI_ERROR_ATTRIBUTE_REG_OFFSET 0x1d48 + +#define MV_PCI_ERROR_COMMAND_REG_OFFSET 0x1d50 + +#define MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET 0xd30 /*Relevant for 60x1 only*/ +#define MV_PCI_MAIN_COMMAND_DIS_CORE_CLK_MASK MV_BIT0 +#define MV_PCI_MAIN_COMMAND_DIS_SHC1_CLK_MASK MV_BIT0 +#define MV_PCI_MAIN_COMMAND_STOP_MASTER_MASK MV_BIT2 +#define MV_PCI_MAIN_COMMAND_MASTER_EMPTY_MASK MV_BIT3 +#define MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK MV_BIT4 + +/*PEX (PCI-Express registers*/ +#define MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET 0x1900 +#define MV_PCI_E_INTERRUPT_MASK_REG_OFFSET 0x1910 +#define MV_PCI_E_ERROR_MASK_VALUE (MV_BIT10|MV_BIT9|MV_BIT8|MV_BIT3|MV_BIT1) +/* Flash interface registers */ +#define MV_FLASH_PARAMS_REG_OFFSET 0x1046c + +#define MV_FLASH_GPIO_PORT_CONTROL_OFFSET 0x104f0 + +#define MV_RESET_CONFIG_REG_OFFSET 0x180d8 +#define MV_RESET_CONFIG_TWSI_INIT_MASK MV_BIT0 +#define MV_SATA_II_ALL_PORTS_INT_COAL_CMND_THR_REG_OFFSET 0x180cc + +#define MV_SATA_II_ALL_PORTS_INT_COAL_TIME_THR_REG_OFFSET 0x180d0 + +#define MV_SATA_II_ALL_PORTS_INT_CAUSE_REG_OFFSET 0x18008 + +/* SATAHC registers*/ +#define MV_SATAHC_0_REGS_BASE_OFFSET 0x20000 /* 128KByte offset */ + +#define MV_SATAHC_1_REGS_BASE_OFFSET 0x30000 /* 192KByte offset */ + +#define MV_SATAHC_REGS_BASE_OFFSET(unit) ((unit)?(MV_SATAHC_1_REGS_BASE_OFFSET):(MV_SATAHC_0_REGS_BASE_OFFSET)) + +#define MV_SATAHC_XBAR_CONF_REG_OFFSET 0x000 + +#define MV_SATAHC_RESPONSE_Q_IN_POINTER_OFFSET 0x008 + +#define MV_SATAHC_INT_COAL_THRE_REG_OFFSET 0x00c + +#define MV_SATAHC_INT_TIME_THRE_REG_OFFSET 0x010 + +#define MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET 0x014 + +//Patch by QNAP:Fix OnBoard SATA LED and Ethernet LED +#define MV_SATAHC_LED_CONF_REG_OFFSET 0x02c +///////////////////////////////////////////////// +#define MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET 0x018 +#define MV_SATA_I_TEST_CONTROL_PATTERN_MASK 0x7 +#define MV_SATA_I_TEST_CONTROL_PATTERN_OFFSET 10 +#define MV_SATA_I_TEST_CONTROL_PORT_MASK 0x3 +#define MV_SATA_I_TEST_CONTROL_PORT_OFFSET 13 +#define MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port) ((MV_U32)1 << (24 + (port))) + +#define MV_SATA_I_HC_BRIDGES_TEST_STATUS_REG_OFFSET 0x01c +#define MV_SATA_I_TEST_STATUS_LOOPBACK_PASS_BIT MV_BIT8 + +#define MV_SATA_I_HC_BRIDGES_PINS_CONFIG_REG_OFFSET 0x020 + +#define MV_SATA_I_HC_R00_STATUS_BRIDGE_PORT_OFFSET(port) \ + (0x100 + (port)*0x100) + +#define MV_SATA_I_HC_R00_STATUS_BRIDGE_DET_OFFSET 0x0 +#define MV_SATA_I_HC_R00_STATUS_BRIDGE_DET_MASK 0xf + +#define MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port) \ + (0x108 + (port)*0x100) + +#define MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port) \ + (0x10C + (port)*0x100) + +#define MV_SATA_I_HC_R04_STATUS_BRIDGE_PORT_OFFSET(port) \ + (0x110 + (port)*0x100) +#define MV_SATA_I_HC_R05_STATUS_BRIDGE_PORT_OFFSET(port) \ + (0x114 + (port)*0x100) +#define MV_SATA_I_HC_R06_STATUS_BRIDGE_PORT_OFFSET(port) \ + (0x118 + (port)*0x100) +#define MV_SATA_I_HC_R0F_STATUS_BRIDGE_PORT_OFFSET(port) \ + (0x13c + (port)*0x100) +#define MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port) \ + (0x130 + ((port) * 0x100)) +#define MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port) \ + (0x174 + ((port) * 0x100)) +#define MV_SATA_I_PHY_MODE_AMP_MASK 0xe0 +#define MV_SATA_I_PHY_MODE_AMP_OFFSET 5 +#define MV_SATA_I_PHY_MODE_PRE_MASK 0x1800 +#define MV_SATA_I_PHY_MODE_PRE_OFFSET 11 + +#define MV_SATA_II_PHY_MODE_1_REG_OFFSET 0x32c + +#define MV_SATA_II_PHY_MODE_2_REG_OFFSET 0x330 +#define MV_SATA_II_PHY_MODE_2_AMP_MASK 0x700 +#define MV_SATA_II_PHY_MODE_2_AMP_OFFSET 8 +#define MV_SATA_II_PHY_MODE_2_PRE_MASK 0xe0 +#define MV_SATA_II_PHY_MODE_2_PRE_OFFSET 5 + +#define MV_SATA_II_PHY_MODE_3_REG_OFFSET 0x310 + +#define MV_SATA_II_PHY_MODE_4_REG_OFFSET 0x314 + +#define MV_SATA_II_IF_CONTROL_REG_OFFSET 0x344 +#define MV_SATA_II_IF_CONTROL_PMTX_OFFSET 0 +#define MV_SATA_II_IF_CONTROL_PMTX_MASK 0xf + +#define MV_SATA_II_IF_TEST_CTRL_REG_OFFSET 0x348 + +#define MV_SATA_II_IF_STATUS_REG_OFFSET 0x34c +#define MV_SATA_II_IF_STATUS_VUQ_DONE_MASK MV_BIT12 +#define MV_SATA_II_IF_STATUS_VUQ_ERR_MASK MV_BIT13 +#define MV_SATA_II_IF_STATUS_FSM_STATUS_MASK 0x3f000000 + + +#define MV_SATA_II_VENDOR_UQ_REG_OFFSET 0x35c + +#define MV_SATA_II_S_STATUS_REG_OFFSET 0x300 + +#define MV_SATA_II_S_ERROR_REG_OFFSET 0x304 + +#define MV_SATA_II_S_CONTROL_REG_OFFSET 0x308 + +#define MV_SATA_II_SATA_CONFIG_REG_OFFSET 0x50 + +#define MV_SATA_II_PHY_MODE_9_GEN1_REG_OFFSET 0x39c +#define MV_SATA_II_PHY_MODE_9_GEN2_REG_OFFSET 0x398 +/* EDMA registers */ + +#define MV_EDMA_PORT_BASE_OFFSET(port) ( 0x2000UL * ((port) + 1)) + +#define MV_EDMA_CONFIG_REG_OFFSET 0x000 +#define MV_EDMA_CONFIG_Q_DEPTH_MASK 0x1f +#define MV_EDMA_CONFIG_NATIVE_QUEUING_MASK MV_BIT5 /* Relevant for 60x1 */ +#define MV_EDMA_CONFIG_BURST_SIZE_MASK MV_BIT8 +#define MV_EDMA_CONFIG_EQUEUE_ENABLED_MASK MV_BIT9 +#define MV_EDMA_CONFIG_STOP_ON_ERROR_MASK MV_BIT10 +#define MV_EDMA_CONFIG_BURST_SIZE_EXT_MASK MV_BIT11 +#define MV_EDMA_CONFIG_CONONDEVERR_MASK MV_BIT14 + +#define MV_EDMA_TIMER_REG_OFFSET 0x004 + +#define MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET 0x008 + +#define MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET 0x00c + +/* unrecoverable EDMA errors*/ +#define MV_EDMA_GEN_I_UNRECOVERABLE_EDMA_ERROR 0x00001E6B +#define MV_EDMA_GEN_I_RECOVERABLE_EDMA_ERROR 0x00000000 +#define MV_EDMA_GEN_I_ERROR_MASK 0x00001118 + +#define MV_EDMA_GEN_II_UNRECOVERABLE_EDMA_ERROR 0xFC1E9E0B +#define MV_EDMA_GEN_II_RECOVERABLE_EDMA_ERROR 0x03E16020 +#define MV_EDMA_GEN_II_NORMAL_RCVRBL_EDMA_ERROR 0x02200000 + +/*don't enable rcvrbl errors that occur too often*/ +#define MV_EDMA_GEN_II_ERROR_MASK 0xFDDFF198 + + +#define MV_EDMA_REQUEST_Q_BAH_REG_OFFSET 0x010 + +#define MV_EDMA_REQUEST_Q_INP_REG_OFFSET 0x014 +#define MV_EDMA_REQUEST_Q_INP_MASK 0x000003e0 +#define MV_EDMA_REQUEST_Q_INP_OFFSET 5 +#define MV_EDMA_REQUEST_Q_BA_MASK 0xfffffc00 + +#define MV_EDMA_GEN2E_REQUEST_Q_INP_MASK 0x00000fe0 +#define MV_EDMA_GEN2E_REQUEST_Q_BA_MASK 0xfffff000 + +#define MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET 0x018 +#define MV_EDMA_REQUEST_Q_OUTP_MASK 0x000003e0 + +#define MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET 0x01c + +#define MV_EDMA_RESPONSE_Q_INP_REG_OFFSET 0x020 +#define MV_EDMA_RESPONSE_Q_INP_MASK 0x000000f8 + +#define MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET 0x024 +#define MV_EDMA_RESPONSE_Q_OUTP_MASK 0x000000f8 +#define MV_EDMA_RESPONSE_Q_OUTP_OFFSET 3 + +#define MV_EDMA_RESPONSE_Q_BA_MASK 0xffffff00 + + +#define MV_EDMA_COMMAND_REG_OFFSET 0x028 +#define MV_EDMA_COMMAND_ENABLE_MASK MV_BIT0 +#define MV_EDMA_COMMAND_DISABLE_MASK MV_BIT1 +#define MV_EDMA_COMMAND_HARD_RST_MASK MV_BIT2 + +#define MV_EDMA_TEST_CONTROL_REG_OFFSET 0x02c +#define MV_EDMA_LOOPBACK_MODE_BIT MV_BIT1 + +#define MV_EDMA_STATUS_REG_OFFSET 0x030 +#define MV_EDMA_STATUS_TAG_MASK 0x1f +#define MV_EDMA_STATUS_TAG_OFFSET 0 +#define MV_EDMA_STATUS_ECACHE_EMPTY_BIT MV_BIT6 +#define MV_EDMA_STATUS_EDMA_IDLE_BIT MV_BIT7 + + +#define MV_EDMA_IORDY_TIMEOUT_REG_OFFSET 0x034 + +#define MV_EDMA_ARBITER_CNFG_REG_OFFSET 0x038 +#define MV_EDMA_NO_SNOOP_BIT MV_BIT6 + +#define MV_EDMA_CMD_DELAY_THRE_REG_OFFSET 0x040 + +#define MV_EDMA_HALT_CONDITIONS_REG_OFFSET 0x060 + +#define MV_EDMA_TCQ_STATUS_REG_OFFSET 0x08c + +#define MV_EDMA_NCQTCQ0_OUTSTANDING_REG_OFFSET 0x094 +#define MV_EDMA_NCQTCQ1_OUTSTANDING_REG_OFFSET 0x098 +#define MV_EDMA_NCQTCQ2_OUTSTANDING_REG_OFFSET 0x09c +#define MV_EDMA_NCQTCQ3_OUTSTANDING_REG_OFFSET 0x0a0 + +#define MV_EDMA_FIS_CONFIGURATION_REG_OFFSET 0x360 +#define MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET 0x364 +#define MV_EDMA_FIS_INTERRUPT_MASK_REG_OFFSET 0x368 +/* C2C */ +/* BM DMA */ +#define MV_BMDMA_COMMAND_OFFSET 0x224 +#define MV_BMDMA_STATUS_OFFSET 0x228 +#define MV_BMDMA_PRD_TABLE_LOW_ADDRESS_OFFSET 0x22c +#define MV_BMDMA_PRD_TABLE_HIGH_ADDRESS_OFFSET 0x230 + +/* storage device registers*/ + +#define MV_ATA_DEVICE_PIO_DATA_REG_OFFSET 0x100 +#define MV_ATA_DEVICE_FEATURES_REG_OFFSET 0x104 +#define MV_ATA_DEVICE_ERROR_REG_OFFSET MV_ATA_DEVICE_FEATURES_REG_OFFSET +#define MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET 0x108 +#define MV_ATA_DEVICE_LBA_LOW_REG_OFFSET 0x10c +#define MV_ATA_DEVICE_LBA_MID_REG_OFFSET 0x110 +#define MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET 0x114 +#define MV_ATA_DEVICE_HEAD_REG_OFFSET 0x118 +#define MV_ATA_DEVICE_COMMAND_REG_OFFSET 0x11c +#define MV_ATA_DEVICE_STATUS_REG_OFFSET MV_ATA_DEVICE_COMMAND_REG_OFFSET +#define MV_ATA_DEVICE_CONTROL_REG_OFFSET 0x120 +#define MV_ATA_DEVICE_ALTERNATE_REG_OFFSET MV_ATA_DEVICE_CONTROL_REG_OFFSET + +#define MV_IOG_TRANS_LOW_BIT (MV_BIT19) +#define MV_IOG_TRANS_HIGH_BIT (MV_BIT20) +#define MV_IOG_TRANS_INT_MASK (MV_IOG_TRANS_LOW_BIT | MV_IOG_TRANS_HIGH_BIT) +#define MV_IOG_TRANS_LOW_REG_OFFSET 0x18088 +#define MV_IOG_TRANS_HIGH_REG_OFFSET 0x1808C +#define MV_IOG_TRANS_CTRL_REG_OFFSET 0x18048 + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvRegs */ diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.c b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.c new file mode 100644 index 0000000..3df4ab4 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.c @@ -0,0 +1,10135 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvSata - C File for implementation of the core driver for Marvell's Sata +* Adapters. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* mvOs.h +* mvSata.h. +* mvStorageDev.h +* mvRegs.h +* +*******************************************************************************/ +#include "mvOsS.h" +#include "mvSata.h" +#include "mvStorageDev.h" +#include "mvRegs.h" + +/* Defines */ +#define MV_SATA_PORT_PER_UNIT 4 + +#define MV_PHY_DET_STATE_NO_DEVICE 0 +#define MV_PHY_DET_STATE_DEVICE_NO_PHY_COM 1 +#define MV_PHY_DET_STATE_DEVICE_AND_PHY_COM 3 +#define MV_PHY_DET_STATE_PHY_OFFLINE 4 +#define MV_PHY_DET_CONTROL_START_NEGOTIATION 1 +#define MV_PHY_DET_CONTROL_SHUTDOWN 4 +#define MV_NEAR_END_LOOPBACK_TEST_WAIT_TIME 100 /* 100 uSec */ +#define MV_FAR_END_LOOPBACK_TEST_WAIT_TIME 5 /* 5 uSec */ +#define MV_PHY_COM_SETUP_WAIT 5000 /* 5 mili seconds */ +#define MV_HARD_RESET_WAIT_ASSERT 25 /* 25 uSec */ +#define MV_HARD_RESET_WAIT_NEGATE 1000 /* 1 mSec*/ +#define MV_HARD_RESET_WAIT_READY 2000 /* ms to wait after HR*/ +/* before disk access */ +#define MV_HARD_RESET_WAIT_FOR_BUSY_LOOPS 10000 +#define MV_HARD_RESET_WAIT_FOR_BUSY_LOOP_DELAY 1000 + +/* for the command result */ +#define MV_EDMA_REQUEST_COMMANDS_NUM 11 + + +/* Fix the watermark to the following default value */ +#define MV_WATER_MARK_FIX 29 /* write 5'b11101 to bits 12:8*/ + +extern MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER *pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delay); + +extern void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_BOOLEAN isEXT, + MV_STORAGE_DEVICE_REGISTERS *pRegisters); + +extern MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel); + +MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel); + +extern MV_BOOLEAN executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_NON_UDMA_PROTOCOL protocolType, + MV_BOOLEAN isEXT, + MV_U16_PTR bufPtr, MV_U32 count, + MV_U16 features, + MV_U16 sectorCount, + MV_U16 lbaLow, MV_U16 lbaMid, + MV_U16 lbaHigh, MV_U8 device, + MV_U8 command); + +extern MV_BOOLEAN waitForDRQ(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delay); + +static void _setRegBits(MV_BUS_ADDR_T ioBaseAddr, MV_U32 offset, + MV_U32 bits) +{ + MV_U32 regVal = MV_REG_READ_DWORD(ioBaseAddr, offset); + regVal |= bits; + MV_REG_WRITE_DWORD(ioBaseAddr, offset, regVal); +} + +static void _clearRegBits(MV_BUS_ADDR_T ioBaseAddr, MV_U32 offset, + MV_U32 bits) +{ + MV_U32 regVal = MV_REG_READ_DWORD(ioBaseAddr, offset); + regVal &= ~bits; + MV_REG_WRITE_DWORD(ioBaseAddr, offset, regVal); +} + +static MV_U32 getRegField(MV_U32 regVal, MV_U32 fieldOff, MV_U32 bitsNum); + +static MV_BOOLEAN _checkSStatusAfterHReset(MV_SATA_ADAPTER* pAdapter, + MV_U8 channelIndex); +#ifdef MV_LOGGER + +void _dumpPCIRegs(MV_SATA_ADAPTER *pAdapter); +void _dumpEDMARegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); +void _dumpChannelQueues(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); +void _dumpSataRegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); +void _printATARegs(MV_STORAGE_DEVICE_REGISTERS *pDeviceRegs); + +#else + + #define _dumpPCIRegs(p) + #define _dumpEDMARegs(p,i) + #define _dumpChannelQueues(p,i) + #define _dumpSataRegs(p,i) + #define _printATARegs(p) + +#endif + +/* write ATA command register entry in a request entry */ +#define WRITE_ATA_COMMAND_REG(addr, data, reg, isLast) \ +do{ \ + *(addr) = MV_CPU_TO_LE16((((MV_U8)(data)) & 0xff) | ((reg) << 8) | (isLast)); \ +} while(0) + +#define MV_CHANNEL_INDEX(unit, port) (((unit) << 2) | (port)) + + +/* Typedefs */ + +typedef struct mvDmaRequestQueueEntry +{ + /* Fields set by CORE driver */ + volatile MV_U32 prdLowAddr; + volatile MV_U32 prdHighAddr; + volatile MV_U16 controlFlags; + volatile MV_U16 command[MV_EDMA_REQUEST_COMMANDS_NUM]; + +} MV_DMA_REQUEST_QUEUE_ENTRY; + +/*CRQP Data structure of the fourth generation devices*/ +typedef struct mvGen2EEdmaRequestQueueEntry +{ + /* Fields set by CORE driver */ + volatile MV_U32 prdLowAddr; + volatile MV_U32 prdHighAddr; + volatile MV_U32 controlFlags; + volatile MV_U16 dataRegionByteCount; + volatile MV_U16 reserved[2]; + volatile MV_U8 ATACommand; + volatile MV_U8 ATAFeatures; + volatile MV_U8 ATALBALow; + volatile MV_U8 ATALBAMid; + volatile MV_U8 ATALBAHigh; + volatile MV_U8 ATADevice; + volatile MV_U8 ATALBALowExp; + volatile MV_U8 ATALBAMidExp; + volatile MV_U8 ATALBAHighExp; + volatile MV_U8 ATAFeaturesExp; + volatile MV_U8 ATASectorCount; + volatile MV_U8 ATASectorCountExp; + volatile MV_U16 reserved2; +} MV_GEN2E_EDMA_REQUEST_QUEUE_ENTRY; + +typedef struct mvDmaResponseQueueEntry +{ + /* Fields set by hardware */ + volatile MV_U16 id; + volatile MV_U16 responseFlags; + volatile MV_U32 timeStamp; +} MV_DMA_RESPONSE_QUEUE_ENTRY; + + +/* local functions */ + +/*static*/ MV_BOOLEAN waitForBusyAfterHReset(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +static void unmaskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void maskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void setupEdmaDeviceErrorHandlingConfiguration(MV_SATA_CHANNEL *pSataChannel); + +static void writeEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry, + MV_SATA_CHANNEL *mvSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_UDMA_COMMAND_PARAMS *pUdmaParams); + +static void writeGen2EEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry, + MV_SATA_CHANNEL *mvSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_UDMA_COMMAND_PARAMS *pUdmaParams); + +static void handleEdmaFailedCommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_U16 eDmaErrorCause); + +static void handleEdmaResponse(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_DMA_RESPONSE_QUEUE_ENTRY *eDmaResponse); + +#ifdef MV_SATA_C2C_COMM +static void handleBmDMAInterrupt(MV_SATA_ADAPTER *pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_SATA_CHANNEL *pSataChannel, + MV_U8 channelIndex, + MV_U32 edmaError); +#endif + +static void handleEdmaInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, + MV_U8 port, MV_U8 rspInPtr,MV_U32 responseDone, + MV_U32 edmaError, MV_U32 unitCause); + +static void handleDeviceInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, + MV_U8 port); + +static void handleEdmaError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static MV_VOID handleDisconnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static MV_VOID handleConnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static MV_BOOLEAN handleUnrecoverableError(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause); + +static MV_BOOLEAN handleRecoverableError(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause); + +static MV_BOOLEAN handleAsyncNotify(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause); + +static MV_BOOLEAN handleSelfDisable(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause); + +static MV_BOOLEAN handleDevErr(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause); + +#ifdef MV_SATA_C2C_COMM +static void handleC2CInterrupt(MV_SATA_CHANNEL *pSataChannel); +#endif +static MV_BOOLEAN sendVendorUniqueFIS(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 *vendorUniqueBuffer, + MV_U8 numOfDWords); + +static void handlePIOInterrupt(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry); + +static MV_BOOLEAN transferPIOData(MV_SATA_CHANNEL *pSataChannel, + MV_NONE_UDMA_COMMAND_PARAMS *pNoneUdmaCommandParams); + +#ifdef MV_SUPPORT_ATAPI +static MV_BOOLEAN transferPacketData(MV_SATA_CHANNEL *pSataChannel, + MV_PACKET_COMMAND_PARAMS *pPacketCommandParams, + MV_U16 byteCount); + +static void completePacketCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_BOOLEAN failed); +#endif +static void completePIOCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_BOOLEAN failed); + +static MV_BOOLEAN _resetEdmaQPointers(MV_SATA_CHANNEL *pSataChannel); + +static MV_BOOLEAN resetEdmaChannel(MV_SATA_CHANNEL *pSataChannel); + +static void flushDmaQueue(MV_SATA_CHANNEL *pSataChannel, + MV_FLUSH_TYPE flushType, MV_COMPLETION_TYPE, MV_U16); + +static void _fixPhyParams(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelIndex); + +static void _channelHardReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void _establishSataComm(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void _establishSataCommAll(MV_SATA_ADAPTER *pAdapter); + +void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort); + +static void revertSataHCRegs (MV_SATA_ADAPTER *pAdapter); + +static void revertFlashInterfaceRegs (MV_SATA_ADAPTER *pAdapter); + +static void revertPCIInterfaceRegs (MV_SATA_ADAPTER *pAdapter); + +static void revertPEXInterfaceRegs (MV_SATA_ADAPTER *pAdapter); + +static void commandsQueueAddTail(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry); + +static void commandsQueueRemove(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry); + +static void addCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_QUEUE_COMMAND_INFO *pCommandInfo); + +static void removeCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry); + +static void enableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +void disableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void _checkATAStatus(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void activateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void deactivateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +static void EdmaReqQueueInsert(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_UDMA_COMMAND_PARAMS *pUdmaParams); + +static MV_BOOLEAN sendNoneUdmaCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry); + +static MV_BOOLEAN isGoodCompletionsExpected(MV_SATA_CHANNEL *pSataChannel); + +static MV_VOID updatePortsWithErrors(MV_SATA_CHANNEL *pSataChannel); + +static MV_VOID setAbortedCommands(MV_SATA_CHANNEL *pSataChannel); + +static MV_VOID enterRequestSenseState(MV_SATA_CHANNEL *pSataChannel); + +static MV_BOOLEAN _getHostTagByDeviceTag(MV_SATA_CHANNEL *pSataChannel, + MV_U8 deviceTag, + MV_U8 PMPort, + MV_U8 *pHostTag); + +static MV_BOOLEAN parseReadLogExtOutPut(MV_SATA_CHANNEL *pSataChannel); + +static MV_BOOLEAN +ReadLogExtCompletionCB(MV_SATA_ADAPTER *pSataAdapter, + MV_U8 channelNum, + MV_COMPLETION_TYPE comp_type, + MV_VOID_PTR commandId, + MV_U16 responseFlags, + MV_U32 timeStamp, + MV_STORAGE_DEVICE_REGISTERS *registerStruct); + +static MV_VOID setReadLogExtCmndPointers(MV_SATA_CHANNEL *pSataChannel); + +static MV_VOID insertReadLogExtCmnd(MV_SATA_CHANNEL *pSataChannel); + +static MV_VOID handlePortError(MV_SATA_CHANNEL *pSataChannel); + +static MV_VOID softResetErringPorts(MV_SATA_CHANNEL *pSataChannel); + +static MV_VOID _insertQCommandsIntoEdma(MV_SATA_CHANNEL *pSataChannel); + +static MV_BOOLEAN _doDevErrorRecovery(MV_SATA_CHANNEL *pSataChannel); + +#if defined (MV_SUPPORT_ATAPI) || defined (MV_SATA_C2C_COMM) +static void activateBMDmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_U32 prdTableHi, MV_U32 prdTableLow, + MV_UDMA_TYPE dmaType); +#endif +static void _resetBmDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +#ifdef MV_SATA_C2C_COMM + +/* Channel 2 Channel */ +static MV_BOOLEAN sendVendorUniqueFIS(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 *vendorUniqueBuffer, + MV_U8 numOfDWords); + +#endif + +#ifdef MV_SATA_IO_GRANULARITY + +static void setIoGranularityCount(MV_SATA_ADAPTER *pAdapter, + MV_U8 transId, + MV_U8 counter); +static MV_U8 readIoGranularityCount(MV_SATA_ADAPTER *pAdapter, + MV_U8 transId); +static void iogInterrupt(MV_SATA_ADAPTER *pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 mainCause); +static void checkIogCompletion(MV_SATA_ADAPTER *pAdapter, + MV_U32 iogCause, MV_U8 offset); +static void checkIogBit(MV_SATA_ADAPTER *pAdapter, + MV_U8 bitOffset, + MV_U8 value); + +static MV_BOOLEAN iogReset(MV_SATA_ADAPTER *pAdapter); +#endif + + +/* Calculate the base address of the registers for a SATA channel */ +MV_U32 edmaRegOffst[MV_SATA_CHANNELS_NUM] = {0x22000, 0x24000, 0x26000, 0x28000, +0x32000, 0x34000, 0x36000, 0x38000}; + +#define getEdmaRegOffset(x) edmaRegOffst[(x)] + + + + +MV_BOOLEAN waitForBusyAfterHReset(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_U32 i; + MV_U8 ATAstatus; + mvMicroSecondsDelay(pAdapter, MV_HARD_RESET_WAIT_READY); + for (i = MV_HARD_RESET_WAIT_READY; i < 5000000; i+= 10000) + { + ATAstatus = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) + { + return MV_TRUE; + } + mvMicroSecondsDelay(pAdapter, 10000); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: in Channel " + "Hard Reset wait for busy, ATA STATUS=0x%02x\n", + pAdapter->adapterId, + channelIndex, ATAstatus); + return MV_FALSE; +} + +static void unmaskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + + + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /*clear SError */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_S_ERROR_REG_OFFSET, 0xFFFFFFFF); + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { + /* clear FIS Interrupt cause register*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, 0); + } + } + + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, + 0); + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + /* Unmask EDMA self disable (bit 8), mask errors that cause self disable */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, + MV_EDMA_GEN_I_ERROR_MASK); + } + else + { + /* Unmask EDMA self disable (bit 7), mask errors that cause self disable */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, + MV_EDMA_GEN_II_ERROR_MASK); + } +} + +static void maskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, + 0); +} + +/******************************************************************************* +* writeEdmaRequestEntry - Write a CRQB (COMMAND REQUEST QUEUE BLOCK) +* +* DESCRIPTION: +* write one CRQB for an EDMA request queue. +* +* INPUT: +* pReqEntry - pointer to the CRQB area on the system memory +* (HW reqeust Queue). +* mvSataChannel - pointer to the channel data structure +* pCommandEntry - pointer to the command entry data structure +* (SW request Queue). +* +* RETURN: +* None +* +* COMMENTS: +* None. +* +*******************************************************************************/ +static void writeEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry, + MV_SATA_CHANNEL *mvSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_UDMA_COMMAND_PARAMS *pUdmaParams) +{ + MV_U16 ControlFlags = 0; + volatile MV_U16 *pCommand = &pReqEntry->command[0]; + MV_U8 ATACommand = 0; + + pReqEntry->prdLowAddr = MV_CPU_TO_LE32(pUdmaParams->prdLowAddr); + pReqEntry->prdHighAddr = MV_CPU_TO_LE32(pUdmaParams->prdHighAddr); + + /* Set the direction of the transaction (read/write) */ + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ControlFlags |= 0x1; /* Device to system memory */ + } + ControlFlags |= (pCommandEntry->hostTag << 1); /* the tag will be used also */ +#ifdef MV_SATA_IO_GRANULARITY + + /*If valid IO Granularity transaction Id*/ + if (pUdmaParams->iogCurrentTransId < MV_IOG_INVALID_COMMAND_ID) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND, "%d %d: " + "Edma request with IO granularity Id = 0x%x\n", + mvSataChannel->mvSataAdapter->adapterId, + mvSataChannel->channelNumber, pUdmaParams->iogCurrentTransId); + ControlFlags |= (((MV_U16)pUdmaParams->iogCurrentTransId) << 6); + } +#endif + /* in Non-queue EDMA mode */ + ControlFlags |= (pCommandEntry->pCommandInfo->PMPort << 12); + + pReqEntry->controlFlags = MV_CPU_TO_LE16(ControlFlags); + + if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) || + (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)) + { + if (pUdmaParams->isEXT == MV_TRUE) /* Read/Write DMA QUEUED EXT */ + { + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->numOfSectors & 0xFF00) >> 8, + MV_EDMA_ATA_FEATURES_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->numOfSectors) & 0xFF, + MV_EDMA_ATA_FEATURES_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pCommandEntry->deviceTag << 3) & 0xF8, + MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF000000) + >> 24, MV_EDMA_ATA_LBA_LOW_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress) & 0xFF, + MV_EDMA_ATA_LBA_LOW_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++,(pUdmaParams->highLBAAddress & + 0xFF), + MV_EDMA_ATA_LBA_MID_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, + MV_EDMA_ATA_LBA_MID_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->highLBAAddress & 0xFF00) >> 8, + MV_EDMA_ATA_LBA_HIGH_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF0000) >> + 16, MV_EDMA_ATA_LBA_HIGH_ADDR, 0); + + if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) && + (pUdmaParams->FUA == MV_TRUE)) + { + WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT7 | MV_BIT6 , + MV_EDMA_ATA_DEVICE_ADDR,0); + } + else + { + WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6 , + MV_EDMA_ATA_DEVICE_ADDR,0); + } + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + ATACommand = MV_ATA_COMMAND_READ_FPDMA_QUEUED_EXT; + } + else + { + ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED_EXT; + } + } + else + { + if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + ATACommand = MV_ATA_COMMAND_WRITE_FPDMA_QUEUED_EXT; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED_EXT; + } + } + } + else /* Read/Write DMA QUEUED */ + { + WRITE_ATA_COMMAND_REG(pCommand++, (pUdmaParams->numOfSectors) & + 0xFF, MV_EDMA_ATA_FEATURES_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pCommandEntry->deviceTag << 3) & 0xF8, + MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress) & 0xFF, + MV_EDMA_ATA_LBA_LOW_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, + MV_EDMA_ATA_LBA_MID_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF0000) + >> 16, MV_EDMA_ATA_LBA_HIGH_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6 | + (MV_U8)((pUdmaParams->lowLBAAddress & 0xF000000) + >> 24), MV_EDMA_ATA_DEVICE_ADDR, 0); + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED; + } + } + } + else + { + if (pUdmaParams->isEXT == MV_TRUE) + { /* READ/WRITE DMA EXT */ + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->numOfSectors & 0xFF00) >> 8, + MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->numOfSectors) & 0xFF, + MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF000000) + >> 24, + MV_EDMA_ATA_LBA_LOW_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress) &0xFF, + MV_EDMA_ATA_LBA_LOW_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->highLBAAddress & 0xFF), + MV_EDMA_ATA_LBA_MID_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, + MV_EDMA_ATA_LBA_MID_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->highLBAAddress & 0xFF00) >> 8, + MV_EDMA_ATA_LBA_HIGH_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF0000) + >> 16, + MV_EDMA_ATA_LBA_HIGH_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6, MV_EDMA_ATA_DEVICE_ADDR, + 0); + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ATACommand = MV_ATA_COMMAND_READ_DMA_EXT; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA_EXT; + } + } + else /* READ/WRITE DMA */ + { + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->numOfSectors) & 0xFF, + MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress) & 0xFF, + MV_EDMA_ATA_LBA_LOW_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF00) >> 8, + MV_EDMA_ATA_LBA_MID_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + (pUdmaParams->lowLBAAddress & 0xFF0000) + >> 16, + MV_EDMA_ATA_LBA_HIGH_ADDR, 0); + + WRITE_ATA_COMMAND_REG(pCommand++, + MV_BIT6 | (MV_U8)((pUdmaParams->lowLBAAddress & + 0xF000000) >> 24), + MV_EDMA_ATA_DEVICE_ADDR, 0); + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ATACommand = MV_ATA_COMMAND_READ_DMA; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA; + } + } + } + WRITE_ATA_COMMAND_REG(pCommand++, ATACommand, MV_EDMA_ATA_COMMAND_ADDR, + MV_BIT15); +} +/******************************************************************************* +* writeGen2EEdmaRequestEntry - Write a Gen2E CRQB (COMMAND REQUEST QUEUE BLOCK) +* +* DESCRIPTION: +* write one CRQB for an EDMA request queue. +* +* INPUT: +* pReqEntry - pointer to the CRQB area on the system memory +* (HW reqeust Queue). +* mvSataChannel - pointer to the channel data structure +* pCommandEntry - pointer to the command entry data structure +* (SW request Queue). +* pUdmaParams - pointer to the UDMA command parameters data structure. +* +* RETURN: +* None +* +* COMMENTS: +* None. +* +*******************************************************************************/ +static void writeGen2EEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry, + MV_SATA_CHANNEL *mvSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_UDMA_COMMAND_PARAMS *pUdmaParams) +{ + MV_GEN2E_EDMA_REQUEST_QUEUE_ENTRY *pGen2EReqEntry = (MV_GEN2E_EDMA_REQUEST_QUEUE_ENTRY *)pReqEntry; + MV_U32 ControlFlags = 0; + MV_U8 ATACommand = 0; + + pGen2EReqEntry->prdLowAddr = MV_CPU_TO_LE32(pUdmaParams->prdLowAddr); + pGen2EReqEntry->prdHighAddr = MV_CPU_TO_LE32(pUdmaParams->prdHighAddr); + + /* Set the direction of the transaction (read/write) */ + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ControlFlags |= 0x1; /* Device to system memory */ + } +#ifdef MV_SATA_IO_GRANULARITY + + /*If valid IO Granularity transaction Id*/ + if (pUdmaParams->iogCurrentTransId < MV_IOG_INVALID_COMMAND_ID) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND, "%d %d: " + "Edma request with IO granularity Id = 0x%x\n", + mvSataChannel->mvSataAdapter->adapterId, + mvSataChannel->channelNumber, pUdmaParams->iogCurrentTransId); + ControlFlags |= (((MV_U16)pUdmaParams->iogCurrentTransId) << 6); + } +#endif + /* the tag will be used also in Non-queue EDMA mode */ + ControlFlags |= (pCommandEntry->deviceTag << 1); + ControlFlags |= (pCommandEntry->pCommandInfo->PMPort << 12); + ControlFlags |= (pCommandEntry->hostTag << 17); +#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION + if (pUdmaParams->singleDataRegion == MV_TRUE) + { + ControlFlags |= MV_BIT16; + pGen2EReqEntry->dataRegionByteCount = MV_CPU_TO_LE16(pUdmaParams->byteCount); + } +#endif + + pGen2EReqEntry->controlFlags = MV_CPU_TO_LE32(ControlFlags); + if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) || + (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING)) + { + if (pUdmaParams->isEXT == MV_TRUE) /* Read/Write DMA QUEUED EXT */ + { + pGen2EReqEntry->ATAFeaturesExp = (MV_U8)((pUdmaParams->numOfSectors & 0xFF00) >> 8); + pGen2EReqEntry->ATAFeatures = (MV_U8)((pUdmaParams->numOfSectors) & 0xFF); + pGen2EReqEntry->ATASectorCount = (MV_U8)((pCommandEntry->deviceTag << 3) & 0xF8); + pGen2EReqEntry->ATALBALowExp = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF000000) >> 24); + pGen2EReqEntry->ATALBALow = (MV_U8)((pUdmaParams->lowLBAAddress) & 0xFF); + pGen2EReqEntry->ATALBAMidExp = (MV_U8)(pUdmaParams->highLBAAddress & 0xFF); + pGen2EReqEntry->ATALBAMid = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF00) >> 8); + pGen2EReqEntry->ATALBAHighExp = (MV_U8)((pUdmaParams->highLBAAddress & 0xFF00) >> 8); + pGen2EReqEntry->ATALBAHigh = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16); + if ((mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) && + (pUdmaParams->FUA == MV_TRUE)) + { + pGen2EReqEntry->ATADevice = MV_BIT7 | MV_BIT6; + + } + else + { + pGen2EReqEntry->ATADevice = MV_BIT6; + + } + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + ATACommand = MV_ATA_COMMAND_READ_FPDMA_QUEUED_EXT; + } + else + { + ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED_EXT; + } + } + else + { + if (mvSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + ATACommand = MV_ATA_COMMAND_WRITE_FPDMA_QUEUED_EXT; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED_EXT; + } + } + } + else /* Read/Write DMA QUEUED */ + { + pGen2EReqEntry->ATAFeatures = (MV_U8)((pUdmaParams->numOfSectors) & 0xFF); + pGen2EReqEntry->ATASectorCount = (MV_U8)((pCommandEntry->deviceTag << 3) & 0xF8); + pGen2EReqEntry->ATALBALow = (MV_U8)((pUdmaParams->lowLBAAddress) & 0xFF); + pGen2EReqEntry->ATALBAMid = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF00) >> 8); + pGen2EReqEntry->ATALBAHigh = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16); + pGen2EReqEntry->ATADevice = MV_BIT6 | + (MV_U8)((pUdmaParams->lowLBAAddress & 0xF000000) >> 24); + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ATACommand = MV_ATA_COMMAND_READ_DMA_QUEUED; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA_QUEUED; + } + } + } + else + { + if (pUdmaParams->isEXT == MV_TRUE) + { /* READ/WRITE DMA EXT */ + pGen2EReqEntry->ATASectorCountExp = (MV_U8)((pUdmaParams->numOfSectors & 0xFF00) >> 8); + pGen2EReqEntry->ATASectorCount = (MV_U8)((pUdmaParams->numOfSectors) & 0xFF); + pGen2EReqEntry->ATALBALowExp = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF000000) >> 24); + pGen2EReqEntry->ATALBALow = (MV_U8)((pUdmaParams->lowLBAAddress) & 0xFF); + pGen2EReqEntry->ATALBAMidExp = (MV_U8)(pUdmaParams->highLBAAddress & 0xFF); + pGen2EReqEntry->ATALBAMid = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF00) >> 8); + pGen2EReqEntry->ATALBAHighExp = (MV_U8)((pUdmaParams->highLBAAddress & 0xFF00) >> 8); + pGen2EReqEntry->ATALBAHigh = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16); + pGen2EReqEntry->ATADevice = MV_BIT6; + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ATACommand = MV_ATA_COMMAND_READ_DMA_EXT; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA_EXT; + } + } + else /* READ/WRITE DMA */ + { + pGen2EReqEntry->ATASectorCount = (MV_U8)((pUdmaParams->numOfSectors) & 0xFF); + pGen2EReqEntry->ATALBALow = (MV_U8)((pUdmaParams->lowLBAAddress) & 0xFF); + pGen2EReqEntry->ATALBAMid = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF00) >> 8); + pGen2EReqEntry->ATALBAHigh = (MV_U8)((pUdmaParams->lowLBAAddress & 0xFF0000) >> 16); + pGen2EReqEntry->ATADevice = MV_BIT6 | + (MV_U8)((pUdmaParams->lowLBAAddress & 0xF000000) >> 24); + + if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ) + { + ATACommand = MV_ATA_COMMAND_READ_DMA; + } + else + { + ATACommand = MV_ATA_COMMAND_WRITE_DMA; + } + } + } + pGen2EReqEntry->ATACommand = ATACommand; +} + +/******************************************************************************* +* handleEdmaFailedCommand - Handle failed EDMA command which didn't commpleted. +* +* DESCRIPTION: +* This function handles the completion of failed EDMA command when no +* response received for that command. +* +* INPUT: +* pAdapter - Pointer to the MV88SX50XX adapter data structure. +* channelIndex - The index of the channel where the response received. +* eDmaErrorCause - the value of the channel EDMA error cause register. +* +* RETURN: +* None +* +* COMMENTS: +* This function assumes that the channel semaphore is locked. +* +*******************************************************************************/ +static void handleEdmaFailedCommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_U16 eDmaErrorCause) +{ + MV_QUEUED_COMMAND_ENTRY *pCommandEntry; + MV_UDMA_COMMAND_PARAMS *pUdmaCommandParams; + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_STORAGE_DEVICE_REGISTERS deviceRegs; + MV_U32 eDmaStatus; + MV_U8 deviceTag = 0xFF; + MV_U8 hostTag; + MV_U8 PMPort = 0; + + if (pSataChannel->PMSupported == MV_TRUE) + { + MV_U32 regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_STATUS_REG_OFFSET); + PMPort = (MV_U8)getRegField(regVal, 8, 4); + } + eDmaStatus = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_STATUS_REG_OFFSET); + + switch (pSataChannel->queuedDMA) + { + case MV_EDMA_MODE_QUEUED: + /* if only one command is queued*/ + if (pSataChannel->portQueuedCommands[PMPort] == 1) + { + MV_QUEUED_COMMAND_ENTRY *pEntry = pSataChannel->commandsQueueHead; + while (pEntry != NULL) + { + if (pEntry->isCommandInEdma == MV_TRUE) + { + if (pEntry->pCommandInfo->PMPort == PMPort) + { + deviceTag = pEntry->deviceTag; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d %d: handleEdmaFailedCommand, found " + "single erring command in TCQ mode " + "deviceTag(0x%02x)\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + PMPort, + deviceTag); + break; + } + } + else + { + /* stop once reached a command that has not been inserted into the + EDMA since the next commands also must be outside the EDMA + */ + break; + } + pEntry = pEntry->next; + } + if (deviceTag == 0xFF) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + "%d %d %d: handleEdmaFailedCommand, failed to find " + "device tag of single erring command in TCQ mode\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + PMPort); + return; + } + } + else + { + /*multiple commands are queued, take the tag from the disk*/ + deviceTag = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET); + deviceTag >>= 3; + deviceTag &= 0x1F; + } + break; + case MV_EDMA_MODE_NOT_QUEUED: + deviceTag = (MV_U8)getRegField(eDmaStatus, 0, 5); + break; + default: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: " + "handleEdmaFailedCommand: called with wrong mode %d\n", + pAdapter->adapterId, + channelIndex, + pSataChannel->queuedDMA); + return; + } + + if (_getHostTagByDeviceTag(pSataChannel, + deviceTag, + PMPort, + &hostTag) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: " + "handleEdmaFailedCommand: " + "Error - None Valid device tag (0x%02x)\n", + pAdapter->adapterId, + channelIndex, + PMPort, + deviceTag); + return; + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Handle failed command," + "host tag 0x%02x, error cause 0x%02x (eStatus Tag 0x%02x)\n", + pAdapter->adapterId, channelIndex, hostTag, + eDmaErrorCause, (eDmaStatus & MV_EDMA_STATUS_TAG_MASK) >> + MV_EDMA_STATUS_TAG_OFFSET); + /* this function called only if FBS mode disable, then device tag equals to*/ + /* host tag*/ + pCommandEntry = &(pSataChannel->commandsQueue[hostTag]); + if (pCommandEntry->isFreeEntry == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d %d:" + " Received response on a non-valid tag (0x%x)," + " device Tag (0x%x)\n", + pAdapter->adapterId, + channelIndex, + PMPort, + hostTag, + deviceTag); + + _dumpSataRegs(pAdapter,channelIndex); + dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_TRUE, &deviceRegs); + _printATARegs(&deviceRegs); + return; + } + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, pCommandEntry->pCommandInfo->PMPort); + } + pUdmaCommandParams = &pCommandEntry->pCommandInfo->commandParams.udmaCommand; + dumpAtaDeviceRegisters(pAdapter, channelIndex, pUdmaCommandParams->isEXT, + &deviceRegs); + + pSataChannel->EdmaQueuedCommands--; + pUdmaCommandParams->callBack(pSataChannel->mvSataAdapter, channelIndex, + MV_COMPLETION_TYPE_ERROR, + pUdmaCommandParams->commandId, eDmaErrorCause, + 0, &deviceRegs); + removeCommand(pSataChannel,pCommandEntry); +} + +/******************************************************************************* +* handleEdmaResponse - Handle an EDMA response queue entry. +* +* DESCRIPTION: +* This function handles the completion of EDMA command when a response +* entry is received. +* +* INPUT: +* pAdapter - Pointer to the MV88SX50XX adapter data structure. +* channelIndex - The index of the channel where the response received. +* response - Pointer to the received EDMA response block structure. +* +* RETURN: +* None +* +* COMMENTS: +* This function assumes that the channel semaphore is locked. +* +*******************************************************************************/ +static void handleEdmaResponse(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_DMA_RESPONSE_QUEUE_ENTRY *eDmaResponse) +{ + MV_QUEUED_COMMAND_ENTRY *pCommandEntry; + MV_UDMA_COMMAND_PARAMS *pUdmaCommandParams; + MV_STORAGE_DEVICE_REGISTERS deviceRegs; + MV_COMPLETION_TYPE compType = MV_COMPLETION_TYPE_NORMAL; + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_DMA_RESPONSE_QUEUE_ENTRY response; + MV_U16 eDmaCause = 0; + + response.id = MV_LE16_TO_CPU(eDmaResponse->id); + response.responseFlags = MV_LE16_TO_CPU(eDmaResponse->responseFlags); + response.timeStamp = MV_LE32_TO_CPU(eDmaResponse->timeStamp); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: New Response Received. ptr %p, " + "id 0x%02x, flags 0x%x ts 0x%08x\n", pAdapter->adapterId, + channelIndex, eDmaResponse, response.id, + response.responseFlags, response.timeStamp); + + eDmaCause = (response.responseFlags & 0xff); + pCommandEntry = &(pSataChannel->commandsQueue[response.id & pSataChannel->EDMAQueuePtrMask]); + if (response.responseFlags & 0xFF) + { + MV_BOOLEAN ignoreErrorInFlags = MV_FALSE; + + /* response with errors, ignore SErrors since they are recoverable*/ + if ((pAdapter->sataAdapterGeneration != MV_SATA_GEN_I) && + (response.responseFlags & MV_BIT5) && + ((response.responseFlags & 0xDF) == 0)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Ignore Serror in response flags\n", + pAdapter->adapterId, channelIndex); + ignoreErrorInFlags = MV_TRUE; + /* SError in EDMA error cause is masked. so we need to handle it here*/ + pSataChannel->recoveredErrorsCounter = 0; + handleRecoverableError(pAdapter, channelIndex, MV_BIT5); + /* clear SError bit in EDMA error cause*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, + ~MV_BIT5); + + } + /* in NCQ mode, Device error doesn't halt the EDMA operation. since the*/ + /* response flags are a snapshot of the EDMA error cause, then this */ + /* error (Device error) is ignored */ + if ((pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) && + (response.responseFlags & MV_BIT2) && + ((response.responseFlags & 0xDB) == 0)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Ignore Device Error in response flags.\n", + pAdapter->adapterId, channelIndex); + ignoreErrorInFlags = MV_TRUE; + } + + if ((pSataChannel->queuedDMA != MV_EDMA_MODE_NATIVE_QUEUING) && + (pSataChannel->FBSEnabled == MV_TRUE) && + (response.responseFlags & MV_BIT2) && + ((response.responseFlags & 0xDB) == 0)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Device Error in response flags in FBS none NCQ mode." + "outstanding commands %d \n", + pAdapter->adapterId, channelIndex, + pSataChannel->outstandingCommands); + ignoreErrorInFlags = MV_TRUE; + compType = MV_COMPLETION_TYPE_ERROR; + } + + if (ignoreErrorInFlags == MV_FALSE) + { + pSataChannel->queueCommandsEnabled = MV_FALSE; + pSataChannel->EdmaActive = MV_FALSE; + compType = MV_COMPLETION_TYPE_ERROR; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Response with Error. outstanding commands %d, " + "response flags 0x%x\n", + pAdapter->adapterId, channelIndex, + pSataChannel->outstandingCommands, response.responseFlags); + + /* + * link & phy layers unrecoverable errors may be the reason for a + * device errors, so we first check if any unrecoverable errors occured, + * except PCI/internal parity, if yes then we don't count this response + * the PCI/internal parity errors excluded since we want to complete + * the commands with error indication so higher layers can receive it + */ + { + MV_U32 edmaErrorCause = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET); + MV_U32 unrecoverableErrorMask; + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + unrecoverableErrorMask = MV_EDMA_GEN_I_UNRECOVERABLE_EDMA_ERROR; + } + else + { + unrecoverableErrorMask = MV_EDMA_GEN_II_UNRECOVERABLE_EDMA_ERROR; + } + unrecoverableErrorMask &= ~(MV_BIT1|MV_BIT0); + if (edmaErrorCause & unrecoverableErrorMask) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Response ignored due to unrecoverable error," + " EDMA Error Cause: 0x%08x\n", + pAdapter->adapterId, channelIndex, + edmaErrorCause); + return; + } + } + + /* + * responseFlags will hold the low 8 bit of the EDMA error cause + * regiter. For 88SX50XX set bit 8 sence each error causes to + * eDmaSelfDisable. + */ + eDmaCause = (response.responseFlags & 0xff); + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + eDmaCause |= MV_BIT8; + } + else + { + eDmaCause |= MV_BIT7; + } + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, pCommandEntry->pCommandInfo->PMPort); + } + } + } + pUdmaCommandParams = &pCommandEntry->pCommandInfo->commandParams.udmaCommand; + if (response.responseFlags & MV_BIT2) /*device error */ + { + if (pSataChannel->queuedDMA != MV_EDMA_MODE_NATIVE_QUEUING) + { + dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_TRUE, &deviceRegs); + + if (pSataChannel->FBSEnabled == MV_TRUE) + { + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED) + { + if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: First error\n", pAdapter->adapterId, + channelIndex); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS; + } + /*let transport layer resume*/ + setAbortedCommands(pSataChannel); + } + else + { + /*in TCQ/FBS mode, ignore responses with device error*/ + return; + } + + } + } + } + + if (pCommandEntry->isFreeEntry == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + "%d %d: Received response on a non-valid tag (%x), ts 0x%08x," + " address %p\n", pAdapter->adapterId, channelIndex, + response.id, response.timeStamp, eDmaResponse); + _dumpEDMARegs(pAdapter, channelIndex); + _dumpChannelQueues(pAdapter, channelIndex); + } + else + { + pSataChannel->EdmaQueuedCommands--; + + pUdmaCommandParams->callBack(pSataChannel->mvSataAdapter, channelIndex, + compType, pUdmaCommandParams->commandId, + eDmaCause, response.timeStamp, &deviceRegs); + removeCommand(pSataChannel,pCommandEntry); + + if (pSataChannel->queueCommandsEnabled == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND, + "%d %d: Commands queuing is disabled\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return; + } + + if (pSataChannel->ErrorHandlingInfo.state != MV_ERROR_HANDLING_STATE_IDLE) + { + if (compType == MV_COMPLETION_TYPE_NORMAL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Commands with Tag 0x%x completed successfly\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, response.id & 0x1f); + } + if (pSataChannel->ErrorHandlingInfo.state == + MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS) + { + if (isGoodCompletionsExpected(pSataChannel) == MV_FALSE) + { + enterRequestSenseState(pSataChannel); + return; + } + } + } + if (pSataChannel->commandsQueueHead == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND, + "%d %d: Commands queue is empty\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return; + } + if (pSataChannel->commandsQueueHead->pCommandInfo->type != + MV_QUEUED_COMMAND_TYPE_UDMA) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND, + "%d %d: Next Command isn't DMA\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + deactivateEdma(pAdapter,channelIndex); + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, + pSataChannel->commandsQueueHead->pCommandInfo->PMPort); + } + if (sendNoneUdmaCommand(pSataChannel, + pSataChannel->commandsQueueHead) == MV_FALSE) + { + completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead, + MV_TRUE); + } + + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND, + "%d %d: Next Command is UDMA nothing to do\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + + } + } +} + + +#ifdef MV_SATA_C2C_COMM +/******************************************************************************* +* handleBmDmaInterrupt - handle DMA interrupt received for a given channel +* +* DESCRIPTION: +* This function is called when response interrupt is issued when C2C DMA +* completion event occurs. +* +* INPUT: +* pAdapter - pointer to the MV88SX50XX adapter data structure +* ioBaseAddr - adapter rbase address +* pSataChannel - SATA channel structure +* channelIndex - SATA channel index +* edmaError - if != zero then EDMA error happened. +* +* RETURN: +* None. +* +* COMMENTS: +* None +* +*******************************************************************************/ + +static void handleBmDMAInterrupt(MV_SATA_ADAPTER *pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_SATA_CHANNEL *pSataChannel, + MV_U8 channelIndex, + MV_U32 edmaError) +{ + MV_U32 val; + MV_U32 eDmaErrorCause = 0; + mvOsSemTake(&pSataChannel->semaphore); + /*Reset BM dma*/ + _clearRegBits(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_BMDMA_COMMAND_OFFSET, MV_BIT0); + + MV_REG_WRITE_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_IF_CONTROL_REG_OFFSET, + 0); + if (edmaError) + { + eDmaErrorCause = (MV_U16)MV_REG_READ_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET); + } + mvOsSemRelease(&pSataChannel->semaphore); + if (pSataChannel->C2CCallback) + { + if (!edmaError) + { + pSataChannel->C2CCallback(pAdapter, + pSataChannel, + MV_C2C_BM_DMA_DONE, + 0, + NULL); + } + else + { + if (eDmaErrorCause & (MV_BIT17 | MV_BIT26)) + { + pSataChannel->C2CCallback(pAdapter, + pSataChannel, + MV_C2C_BM_DMA_ERROR, + 0, + NULL); + } + if (eDmaErrorCause & (MV_BIT13 | MV_BIT21)) + { + pSataChannel->C2CCallback(pAdapter, + pSataChannel, + MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_ERROR, + 0, + NULL); + } + } + } +} +#endif + + +/******************************************************************************* +* handleEdmaInterrupt - handle EDMA interrupt receivd for a given channel +* +* DESCRIPTION: +* this function called when response interrupt issuesed for a channel and it +* handles all EDMA responses. +* +* INPUT: +* *pAdapter - pointer to the MV88SX50XX adapter data structure +* sataUnit - the SATAHC unit this channel belongs to +* port - the port number of the channel +* rspInPtr - the value of eRPQIP of the channel +* responseDone - if != zero then responses received on this channel +* edmaError - if != zero then EDMA error happened. +* +* RETURN: +* None. +* +* COMMENTS: +* None. +* +*******************************************************************************/ +static void handleEdmaInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, + MV_U8 port,MV_U8 rspInPtr, MV_U32 responseDone, + MV_U32 edmaError, MV_U32 unitCause) +{ + MV_U8 rspOutPtr; + MV_U8 channelIndex; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset; + MV_SATA_CHANNEL *pSataChannel; + MV_BOOLEAN responseWithErr = MV_FALSE; + + channelIndex = MV_CHANNEL_INDEX(sataUnit, port); + pSataChannel = pAdapter->sataChannel[channelIndex]; + + if (responseDone && (pSataChannel != NULL))/* port Done*/ + { + mvOsSemTake(&pSataChannel->semaphore); + pSataChannel->recoveredErrorsCounter = 0; +#ifdef MV_SATA_C2C_COMM + if (MV_FALSE == pSataChannel->C2CmodeEnabled) + { +#endif +#ifdef MV_SUPPORT_ATAPI + if ((pSataChannel->commandsQueueHead) && (pSataChannel->commandsQueueHead->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "%d %d: Basic DMA Interrupt\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + " BMDMA status 0x%08x\n", + MV_REG_READ_DWORD (ioBaseAddr, + getEdmaRegOffset(pSataChannel->channelNumber) + + MV_BMDMA_STATUS_OFFSET)); + if( pSataChannel->waitForBMDMA == MV_TRUE) + { + completePacketCommand(pSataChannel, pSataChannel->commandsQueueHead, MV_FALSE); + } + } + else + { +#endif + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + rspOutPtr = pSataChannel->rspOutPtr; + rspInPtr &= pSataChannel->EDMAQueuePtrMask; + /* here we should update the response out pointer though we didn't*/ + /* handled the new responses, these response entries will not be */ + /* accessed again by the EDMA sinse the number of queued commands */ + /* (outstandingCommands) will be updated only after we handle each*/ + /* response entry */ + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET, + pSataChannel->responseQueuePciLowAddress | + (rspInPtr << MV_EDMA_RESPONSE_Q_OUTP_OFFSET)); + + while (rspOutPtr != rspInPtr) + { + /*handleEdmaResponse may change the channel rspOutPtr due to */ + /*device error in NCQ mode or FBS*/ + pSataChannel->rspOutPtr = (rspOutPtr + 1) & pSataChannel->EDMAQueuePtrMask; + handleEdmaResponse(pAdapter, channelIndex, + &(pSataChannel->responseQueue[rspOutPtr])); + rspOutPtr++; + rspOutPtr &= pSataChannel->EDMAQueuePtrMask; + } +#ifdef MV_SUPPORT_ATAPI + } +#endif + /* + * Check if queueCommandsEnabled flag is disabled. + * If so, then an error has occured and auto flush must be triggered. + * Basically it is enough to trigger auto flush upon edmaError flag, + * but since edmaError is set before handleEdmaResponse is called + * there could be a racing condition between the time edmaError is checked + * and the response queue is checked. + * The racing condition is that an error does not occur when setting + * edmaError to MV_FALSE, but in handlEdmaResponse, the hardware + * has completed a command with error. + * The racing condition will complete the error command (through callback) + * but will prevent the auto flush of all outstanding commands. + */ + if (pSataChannel->queueCommandsEnabled == MV_FALSE) + { + responseWithErr = MV_TRUE; + } + mvOsSemRelease(&pSataChannel->semaphore); +#ifdef MV_SATA_C2C_COMM + } + else + { + mvOsSemRelease(&pSataChannel->semaphore); + handleBmDMAInterrupt(pAdapter, + ioBaseAddr, + pSataChannel, + channelIndex, + edmaError); + } +#endif + } + + if ((edmaError) || (responseWithErr == MV_TRUE)) /* EDMA error interrupt*/ + { + handleEdmaError(pAdapter,channelIndex ); + } +} + +static void handleEdmaError(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_U32 eDmaErrorCause = 0; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + + pSataChannel = pAdapter->sataChannel[channelIndex]; + + eDmaErrorCause = MV_REG_READ_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Edma Error Reg 0x%x\n", pAdapter->adapterId, + channelIndex, MV_REG_READ_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET)); + /* clear the channel's error cause register */ + MV_REG_WRITE_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, + ~eDmaErrorCause); + /*if PM connected, connect/disconnect interrupts storm could happen*/ + if (MV_REG_READ_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET) & + (MV_BIT3 & MV_BIT4)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Edma Error Reg 0x%x still set!!!!!!!!\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET)); + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /*wait 20ms till diconnect/connect interrupts finish*/ + mvMicroSecondsDelay(pAdapter, 20000); + eDmaErrorCause |= MV_REG_READ_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET); + MV_REG_WRITE_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, + ~eDmaErrorCause); + } + } + /* dump in case any kind of parity error*/ + if (eDmaErrorCause & (MV_BIT11 | MV_BIT10 | MV_BIT9 | MV_BIT1 | MV_BIT0)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR," PARITY ERROR Detected\n"); + _dumpPCIRegs(pAdapter); + _dumpEDMARegs(pAdapter,channelIndex); + _dumpChannelQueues(pAdapter,channelIndex); + } + if (eDmaErrorCause & MV_BIT3) /*device disconneted*/ + { + handleDisconnect(pAdapter, channelIndex); + if (mvSataIsStorageDeviceConnected(pAdapter,channelIndex, NULL) == MV_FALSE) + { + pAdapter->mvSataEventNotify(pAdapter, + MV_EVENT_TYPE_SATA_CABLE, + MV_SATA_CABLE_EVENT_DISCONNECT, + channelIndex); + return; + } + } + if (eDmaErrorCause & MV_BIT4) /*device conneted*/ + { + handleConnect(pAdapter, channelIndex); + return; + } + /* unrecoverable error*/ + if (handleUnrecoverableError(pAdapter,channelIndex ,eDmaErrorCause ) == MV_TRUE) + { + return; + } + + /*PM hot plug*/ + if (handleAsyncNotify(pAdapter,channelIndex ,eDmaErrorCause ) == MV_TRUE) + { + return; + } + /* device errors in none NCQ mode generate self disable interrupt*/ + if (handleSelfDisable(pAdapter,channelIndex ,eDmaErrorCause ) == MV_TRUE) + { + return; + } + /* Neither device error without completion nor self disable must be in NCQ + * mode and Port multiplier connected + */ + if (handleDevErr(pAdapter,channelIndex ,eDmaErrorCause ) == MV_TRUE) + { + return; + } + /* recoverable error*/ + if (handleRecoverableError(pAdapter,channelIndex ,eDmaErrorCause) == MV_TRUE) + { + return; + } +} +static MV_VOID handleDisconnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + + if (pSataChannel) + { + mvOsSemTake(&pSataChannel->semaphore); + pSataChannel->queueCommandsEnabled = MV_FALSE; + pSataChannel->EdmaActive = MV_FALSE; + } + /* If disk is disconnected, then disable the activity LED */ + if (pAdapter->chipIs50XXB2 == MV_TRUE) + { + MV_U32 regVal1, regVal2; + /* First enable flash controller clocks*/ + regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET); + + regVal1 |= (MV_BIT0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, + regVal1); + regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET); + /* Disable activity LEDs */ + regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET); + regVal2 |= (MV_BIT8 << channelIndex); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, + regVal2); + regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET); + /* Disable flash controller clocks */ + regVal1 &= ~(MV_BIT0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, + regVal1); + } + /* Fix for 88SX50XX FEr SATA#2 */ + if ((pAdapter->chipIs50XXB0 == MV_TRUE)|| + (pAdapter->chipIs50XXB2 == MV_TRUE)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, + "%d %d: Before Hard RESET Main Cause %x\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainCauseOffset)); + /* Hard Reset the channel so we can do re-connect*/ + _channelHardReset(pAdapter, channelIndex); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, + "%d %d: After Hard RESET Main Cause %x\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainCauseOffset)); + } + else + { + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + +#ifdef MV_SATA_C2C_COMM + if (pSataChannel->C2CmodeEnabled == MV_FALSE) + { +#endif + _channelHardReset(pAdapter, channelIndex); + _establishSataComm(pAdapter, channelIndex); +#ifdef MV_SATA_C2C_COMM + } +#endif + } + } + /* after calling mvSataNotify we can not be sure that the channel*/ + /* data structure is still available so first we release the */ + /* semaphore, after notifying the upper-layer with the disconnect*/ + /* event, nothing else is done with that channel */ + if (pSataChannel) + { + mvOsSemRelease(&pSataChannel->semaphore); + } + +} +static MV_VOID handleConnect(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + /* Fix for 88SX50xx FEr SATA#2 */ + if ((pAdapter->chipIs50XXB0 == MV_TRUE) || + (pAdapter->chipIs50XXB2 == MV_TRUE)) + { + _fixPhyParams(pAdapter, channelIndex);/*TBD*/ + /* The following link re-establishment is due to non */ + /* Marvell driven hard drives */ + _establishSataComm(pAdapter, channelIndex); + _establishSataComm(pAdapter, channelIndex); + } + + /* If disk is connected, then enable the activity LED */ + if (pAdapter->chipIs50XXB2 == MV_TRUE) + { + MV_U32 regVal1, regVal2; + /* First enable flash controller clocks*/ + regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET); + + regVal1 |= (MV_BIT0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, + regVal1); + regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET); + /* Enable activity LEDs */ + regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET); + regVal2 &= ~(MV_BIT8 << channelIndex); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, + regVal2); + regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET); + /* Disable flash controller clocks */ + regVal1 &= ~(MV_BIT0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, + regVal1); + } + if (mvSataIsStorageDeviceConnected(pAdapter,channelIndex, NULL) == MV_TRUE) + { + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE, + MV_SATA_CABLE_EVENT_CONNECT, + channelIndex); + } +} +static MV_BOOLEAN handleUnrecoverableError(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + + if (((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) && + (eDmaErrorCause & MV_EDMA_GEN_I_UNRECOVERABLE_EDMA_ERROR)) || + ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (eDmaErrorCause & MV_EDMA_GEN_II_UNRECOVERABLE_EDMA_ERROR))) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Unrecoverable" + " HW error detected.\n", pAdapter->adapterId, channelIndex); +#ifdef MV_LOGGER + if (eDmaErrorCause & MV_BIT0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtDataErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT1) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtPRDErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT3) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: eDevDis" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT9) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtCRQBErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT10) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtCRPBErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT11) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: ePrtIntErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT12) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: eIORdyErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT15) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkCtlRxErr[2]" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & (MV_BIT17 | MV_BIT18 | MV_BIT19 | MV_BIT20)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkDataRxErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & (MV_BIT26 | MV_BIT27 | MV_BIT28 | MV_BIT29 | MV_BIT30)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkDataTxErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & MV_BIT31) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: TransProtErr" + "UnrecoverableHW error detected.\n", pAdapter->adapterId, channelIndex); + } +#endif + if (pSataChannel) + { + mvOsSemTake(&pSataChannel->semaphore); + pSataChannel->queueCommandsEnabled = MV_FALSE; + pSataChannel->EdmaActive = MV_FALSE; + deactivateEdma(pAdapter, channelIndex); + disableSaDevInterrupts(pAdapter, channelIndex); + flushDmaQueue (pSataChannel, MV_FLUSH_TYPE_CALLBACK, + MV_COMPLETION_TYPE_ABORT, (MV_U16)eDmaErrorCause); + resetEdmaChannel(pSataChannel); + mvOsSemRelease(&pSataChannel->semaphore); + } + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) || + (eDmaErrorCause & MV_BIT12) == 0) + { + _dumpSataRegs(pAdapter, channelIndex); + } + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, + MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR, + channelIndex); + return MV_TRUE; + } + return MV_FALSE; +} +static MV_BOOLEAN handleRecoverableError(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + + if (((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) && + (eDmaErrorCause & MV_EDMA_GEN_I_RECOVERABLE_EDMA_ERROR)) || + ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (eDmaErrorCause & MV_EDMA_GEN_II_RECOVERABLE_EDMA_ERROR))) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Recoverable" + " HW error detected.\n", pAdapter->adapterId, channelIndex); +#ifdef MV_LOGGER + if (eDmaErrorCause & MV_BIT5) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: SerrInt" + "Recoverable error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & (MV_BIT13 | MV_BIT14 | MV_BIT16)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkCtlRxErr" + "Recoverable error detected.\n", pAdapter->adapterId, channelIndex); + } + if (eDmaErrorCause & (MV_BIT21 | MV_BIT22 | MV_BIT23 | MV_BIT24 | MV_BIT25)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: LinkCtlTxErr" + "Recoverable error detected.\n", pAdapter->adapterId, channelIndex); + } +#endif + _dumpSataRegs(pAdapter, channelIndex); + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (eDmaErrorCause & MV_BIT5)) + { + MV_U32 regVal; + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_S_ERROR_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Clear " + " Serror register(0x%02x).\n", pAdapter->adapterId, + channelIndex, regVal); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_S_ERROR_REG_OFFSET, regVal); + /* clear the channel's error cause register */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, + ~MV_BIT5); + } + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, + MV_SATA_RECOVERABLE_COMMUNICATION_ERROR, + channelIndex); + if (pSataChannel) + { + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->recoveredErrorsCounter++ > 10) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Reached %d Recoverable errors " + "notify unrecoverable error\n", + pAdapter->adapterId, channelIndex, + pSataChannel->recoveredErrorsCounter); + pSataChannel->queueCommandsEnabled = MV_FALSE; + pSataChannel->EdmaActive = MV_FALSE; + deactivateEdma(pAdapter, channelIndex); + disableSaDevInterrupts(pAdapter, channelIndex); + flushDmaQueue (pSataChannel, MV_FLUSH_TYPE_CALLBACK, + MV_COMPLETION_TYPE_ABORT, (MV_U16)eDmaErrorCause); + resetEdmaChannel(pSataChannel); + mvOsSemRelease(&pSataChannel->semaphore); + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, + MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR, + channelIndex); + } + else + { + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; + } + } + return MV_TRUE; + } + return MV_FALSE; +} + +static MV_BOOLEAN handleAsyncNotify(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (eDmaErrorCause & MV_BIT8)) + { + MV_U32 regVal1; + if (pSataChannel != NULL) + { + mvOsSemTake(&pSataChannel->semaphore); + } + regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_IF_STATUS_REG_OFFSET); + /*Clear status*/ + if (regVal1 & (MV_BIT31 | MV_BIT30)) + { + MV_U32 regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_IF_CONTROL_REG_OFFSET); + regVal2 |= MV_BIT24; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_IF_CONTROL_REG_OFFSET, regVal2); + } + if (pSataChannel != NULL) + { + mvOsSemRelease(&pSataChannel->semaphore); + } + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: PM asynchronous notification interrupt. FIS Cause %x\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET)); + + /* clear FIS Interrupt cause register*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, + ~0xA00); + /* clear the channel's error cause register */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, + ~MV_BIT8); + } + if (((regVal1 & MV_BIT30) == 0) && + ((regVal1 & MV_BIT31) == MV_BIT31)) + { + + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, + "%d %d: PM asynchronous notification interrupt.\n", + pAdapter->adapterId, channelIndex); + + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE, + MV_SATA_CABLE_EVENT_PM_HOT_PLUG, + channelIndex); + } + return MV_TRUE; + } + return MV_FALSE; +} + +static MV_BOOLEAN handleSelfDisable(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + + if ((((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) && (eDmaErrorCause & MV_BIT8)) || + ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && (eDmaErrorCause & MV_BIT7))) + && + (pSataChannel != NULL)) /* edma self disable */ + { + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->EdmaActive == MV_TRUE) + { + pSataChannel->queueCommandsEnabled = MV_FALSE; + pSataChannel->EdmaActive = MV_FALSE; + + if (eDmaErrorCause & MV_BIT2) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Edma Self disabled due to device error" + " without completion\n", pAdapter->adapterId, + channelIndex); + switch (pSataChannel->queuedDMA) + { + case MV_EDMA_MODE_NOT_QUEUED: + case MV_EDMA_MODE_QUEUED: + handleEdmaFailedCommand(pAdapter, channelIndex, + (MV_U16)eDmaErrorCause); + break; + case MV_EDMA_MODE_NATIVE_QUEUING: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + "%d %d: Edma Self disabled due to device " + "error in NCQ mode!!!!\n", + pAdapter->adapterId, channelIndex); + + break; + default: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + "%d %d: Unknown EDMA mode (%d)\n", + pAdapter->adapterId, channelIndex, + pSataChannel->queuedDMA); + break; + + } + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS, + "%d %d: Edma Self disable received without reason!!!\n", + pAdapter->adapterId, channelIndex); + + } + } + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, + MV_SATA_DEVICE_ERROR, channelIndex); + if (_doDevErrorRecovery(pSataChannel) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS, + "%d %d: Error Recovery Fails!!!\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; + } + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; + } + return MV_FALSE; +} +static MV_BOOLEAN handleDevErr(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 eDmaErrorCause) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (eDmaErrorCause & MV_BIT2) && (pSataChannel != NULL)) + { + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->EdmaActive == MV_TRUE) + { + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: EDMA device error in NCQ mode\n", + pAdapter->adapterId, channelIndex); + if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: First error\n", pAdapter->adapterId, + channelIndex); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS; + } + + updatePortsWithErrors(pSataChannel); + setAbortedCommands(pSataChannel); + if (isGoodCompletionsExpected(pSataChannel) == MV_FALSE) + { + enterRequestSenseState(pSataChannel); + } + + } + else if (pSataChannel->FBSEnabled == MV_TRUE) + { + if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) + { + if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: First error\n", pAdapter->adapterId, + channelIndex); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS; + } + /*get the Device tag from the EDMA's internal memory then*/ + /*complete the failed command*/ + handleEdmaFailedCommand(pAdapter, channelIndex, MV_BIT2); + updatePortsWithErrors(pSataChannel); + setAbortedCommands(pSataChannel); + if (isGoodCompletionsExpected(pSataChannel) == MV_FALSE) + { + enterRequestSenseState(pSataChannel); + } + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: EDMA device error in FBS none NCQ mode\n", + pAdapter->adapterId, channelIndex); + } + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS, + "%d %d: EDMA device error must be handled" + "previously!!!\n", pAdapter->adapterId, + channelIndex); + } + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS, + "%d %d: EDMA device error while EDMA not active!!!\n", + pAdapter->adapterId, channelIndex); + } + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, + MV_SATA_DEVICE_ERROR, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; + } + return MV_FALSE; +} +static MV_VOID handlePCIErrorInterrupt(MV_SATA_ADAPTER *pAdapter) +{ + MV_U32 errorCause = 0; + if (pAdapter->hostInterface == MV_HOST_IF_PEX) + { + errorCause = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET); + } + else if (pAdapter->hostInterface == MV_HOST_IF_PCI) + { + errorCause = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_INTERRUPT_CAUSE_REG_OFFSET); + _dumpPCIRegs(pAdapter); + } + + + { + MV_U8 i; + + for (i = 0; i < pAdapter->numberOfChannels;i++) + { + _dumpEDMARegs(pAdapter, i); + _dumpChannelQueues(pAdapter, i); + } + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_INTERRUPTS, + " %d : PCI error, pci interrupt cause register=%08x\n", + pAdapter->adapterId, errorCause); + /* clear cause register */ + if (pAdapter->hostInterface == MV_HOST_IF_PEX) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET, + ~errorCause); + } + else if (pAdapter->hostInterface == MV_HOST_IF_PCI) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_INTERRUPT_CAUSE_REG_OFFSET, + ~errorCause); + } + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_ADAPTER_ERROR, + errorCause, 0); +} +#ifdef MV_SATA_C2C_COMM +/******************************************************************************* +* handleC2CInterrupt - channel 2 channel interrupt handler +* +* +* DESCRIPTION: +* Handles channel 2 channel interrupt (register device 2 host FIS) and +* convert ATA registers values to user specific 10 bytes message +* +* INPUT: +* pSataChannel - pointer to the Sata channel data structure +* +* RETURN: +* None +* +* COMMENTS: +* None +* +*******************************************************************************/ +static void handleC2CInterrupt(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr = + pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2; + MV_U8 ATAstatus; + MV_STORAGE_DEVICE_REGISTERS deviceRegs; + + mvOsSemTake(&pSataChannel->semaphore); + + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET); + + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + /* clear DevInterrupt*/ + MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port)); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: C2C Interrupt: status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + + dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, + MV_TRUE, + &deviceRegs); + mvOsSemRelease(&pSataChannel->semaphore); + if (pSataChannel->C2CCallback) + { + MV_U8 msg[MV_C2C_MESSAGE_SIZE]; + msg[0] = deviceRegs.errorRegister; + msg[1] = deviceRegs.lbaLowRegister & 0xFF; + msg[2] = deviceRegs.lbaMidRegister & 0xFF; + msg[3] = deviceRegs.lbaHighRegister & 0xFF; + msg[4] = deviceRegs.deviceRegister; + msg[5] = deviceRegs.lbaLowRegister >> 8; + msg[6] = deviceRegs.lbaMidRegister >> 8; + msg[7] = deviceRegs.lbaHighRegister >> 8; + msg[8] = deviceRegs.sectorCountRegister & 0xFF; + msg[9] = deviceRegs.sectorCountRegister >> 8; + pSataChannel->C2CCallback(pSataChannel->mvSataAdapter, + pSataChannel, + MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_DONE, + MV_C2C_MESSAGE_SIZE, + msg); + } +} +#endif + + + +static void handleDeviceInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, + MV_U8 port) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_QUEUED_COMMAND_ENTRY *pCommandEntry; + MV_U8 channelIndex; + + channelIndex = MV_CHANNEL_INDEX(sataUnit, port); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: SaDevInterrupt Received\n", pAdapter->adapterId, + channelIndex); + + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: SaDevInterrupt Received for disconnected channel\n", + pAdapter->adapterId, channelIndex); + /* disable SaDevInterrupts from this channel */ + disableSaDevInterrupts(pAdapter,channelIndex); + return; + } +#ifdef MV_SATA_C2C_COMM + /*handle channel 2 channel communication mode*/ + if (pSataChannel->C2CmodeEnabled == MV_TRUE) + { + handleC2CInterrupt(pSataChannel); + return; + } +#endif + + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_WAIT_FOR_BUSY) + { + MV_U8 ATAstatus; + + ATAstatus = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + /* clear DevInterrupt*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, + ~(MV_BIT8 << port)); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: enter NCQ error handling request sense state\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_REQUEST_SENSE; + pSataChannel->ErrorHandlingInfo.CurrPort = 0; + setReadLogExtCmndPointers(pSataChannel); + handlePortError(pSataChannel); + mvOsSemRelease(&pSataChannel->semaphore); + return; + } + + /* clear interrupt */ + + pCommandEntry = pSataChannel->commandsQueueHead; + if (pCommandEntry == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: SaDevInterrupt: No command is running!!!\n", + pAdapter->adapterId, channelIndex); + _dumpSataRegs(pAdapter, channelIndex); + /* disable SaDevInterrupts from this channel */ + disableSaDevInterrupts(pAdapter,channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return; + } + if ((pCommandEntry->isFreeEntry == MV_TRUE) || + (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA)) + { + if (pCommandEntry->isFreeEntry == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: SaDevInterrupt: current command is free ???\n", + pAdapter->adapterId, channelIndex); + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: SaDevInterrupt: current command is Not PIO ???\n", + pAdapter->adapterId, channelIndex); + } + /* disable SaDevInterrupts from this channel */ + disableSaDevInterrupts(pAdapter,channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return; + } + handlePIOInterrupt(pSataChannel, pCommandEntry); + mvOsSemRelease(&pSataChannel->semaphore); +} + +static void handlePIOInterrupt(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry) +{ + MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2; + MV_U8 ATAstatus; + MV_NON_UDMA_PROTOCOL protocolType; + + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET); + + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + /* clear DevInterrupt*/ + MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port)); + + if(pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET) + { + protocolType = pCommandEntry->pCommandInfo->commandParams.packetCommand.protocolType; + } + else + { + protocolType = pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.protocolType; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: PIO Interrupt: cmd 0x%02X, type %d. status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.command, + protocolType, + ATAstatus); + if (ATAstatus & MV_ATA_BUSY_STATUS) + { + if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: " + "PIO Interrupt: drive is BUSY!!!! status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + } + return; + } + if (ATAstatus & MV_ATA_ERROR_STATUS) + { + if (pSataChannel->FBSEnabled == MV_TRUE) + { + /*clear interrupt cause to resume the transport layer operation*/ + MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, + ~MV_BIT8); + } + if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA) + { + completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE); + return; + } + } + switch (protocolType) + { + case MV_NON_UDMA_PROTOCOL_NON_DATA: + /* command is successfully completed*/ + completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE); + break; + case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN: + if (ATAstatus & MV_ATA_READY_STATUS) + { + if (transferPIOData(pSataChannel, + &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand) == MV_TRUE) + { + if (pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.count == 0) + { + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if (ATAstatus & MV_ATA_DATA_REQUEST_STATUS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: PIO Interrupt: DRQ still set. ATA status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + return; + } + completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE); + return; + } +#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG + + /* for Read long only*/ + if (pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.count == 4) + { + if (transferPIOData(pSataChannel, + &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand) == MV_TRUE) + { + completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE); + } + else + { + completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE); + } + } +#endif /*MV_SATA_SUPPORT_READ_WRITE_LONG*/ + + } + else + { + completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE); + } + } + else /* when BUSY and DRQ cleared to zero then the device has*/ + { + /* completed the command with error */ + completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE); + return; + } + break; + case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT: + if ((ATAstatus & MV_ATA_READY_STATUS) && + !(ATAstatus & MV_ATA_DEVICE_FAULT_STATUS)) + { + if (pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand.count == 0) + { + completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE); + } + else + { + if (transferPIOData(pSataChannel, + &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand) == MV_FALSE) + { + completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE); + } + } + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Interrupt: PIO" + " Data Out command failed status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE); + } + break; +#ifdef MV_SUPPORT_ATAPI + case MV_NON_UDMA_PROTOCOL_PACKET_PIO_NON_DATA: + completePacketCommand(pSataChannel, pCommandEntry, MV_FALSE); + break; + case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN: + case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT: + { + MV_U8 ATASectorCount = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET); + + if ((ATAstatus & MV_ATA_ERROR_STATUS) || (ATAstatus & MV_ATA_DEVICE_FAULT_STATUS)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Packet Interrupt: Command completed with error: ATA status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE); + return; + } + if ((ATAstatus & MV_ATA_DATA_REQUEST_STATUS) == 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "%d %d: Packet Interrupt: Command completed ATA status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + completePacketCommand(pSataChannel, pCommandEntry, MV_FALSE); + return; + } + if (((ATAstatus & MV_ATA_READY_STATUS) != MV_ATA_READY_STATUS) || + (((ATASectorCount & 0x3) != MV_BIT1) && (protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN)) || + (((ATASectorCount & 0x3) != 0) && (protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT)) + ) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Packet Interrupt: unexpected ATA regs: ATA status 0x%02x," + " ATA SectorCount 0x%02x protocol %d\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus, ATASectorCount, + protocolType); + + /* completed the command with error */ + completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE); + return; + } + else + { + MV_U8 LBAMid = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET); + MV_U8 LBAHigh = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET); + MV_U16 byteCount = (LBAHigh << 8) | LBAMid; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " Packet with Data: LBA Mid %x, LBA High %x\n", + LBAMid, LBAHigh); + if (transferPacketData(pSataChannel, + &pCommandEntry->pCommandInfo->commandParams.packetCommand, + byteCount) != MV_TRUE) + { + completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE); + } + } + } + break; + case MV_NON_UDMA_PROTOCOL_PACKET_DMA: + { + MV_U32 BMDMA_status = MV_REG_READ_DWORD (ioBaseAddr, + getEdmaRegOffset(pSataChannel->channelNumber) + + MV_BMDMA_STATUS_OFFSET); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "%d %d: Packet Interrupt: in ATAPI DMA command ATA status 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "Packet Interrupt: BMDMA status 0x%08x\n", BMDMA_status); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + " Packet Interrupt: EDMA Error cause 0x%08x\n", + MV_REG_READ_DWORD (ioBaseAddr, + getEdmaRegOffset(pSataChannel->channelNumber) + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET)); + if(ATAstatus & MV_ATA_ERROR_STATUS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "Packet Interrupt: DMA command completed with error BMDMA " + "status 0x%08x, ATA status 0x%02x\n", BMDMA_status, ATAstatus); + _resetBmDma(pSataChannel->mvSataAdapter, pSataChannel->channelNumber); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + ": BMDMA status(2) 0x%08x\n", + MV_REG_READ_DWORD (ioBaseAddr, + getEdmaRegOffset(pSataChannel->channelNumber) +MV_BMDMA_STATUS_OFFSET)); + + pCommandEntry->pCommandInfo->commandParams.packetCommand.transfered_data = 0; + } + else + { + pCommandEntry->pCommandInfo->commandParams.packetCommand.transfered_data = + pCommandEntry->pCommandInfo->commandParams.packetCommand.buffer_len; + +#if 0 + /* chech if the BMDMA still active*/ + if (BMDMA_status & MV_BIT0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "Packet Interrupt: BMDMA not finished yet. " + "status 0x%08x, ATA status 0x%02x\n", BMDMA_status, ATAstatus); + /* wait for BMDMA done interrrupt*/ + pSataChannel->waitForBMDMA = MV_TRUE; + return; + } +#endif + /* if BMDMA finished, call _resetBmDma to clear the Done interrupt*/ + _resetBmDma(pSataChannel->mvSataAdapter, pSataChannel->channelNumber); + /* chech if the BMDMA completed with errors*/ + if (BMDMA_status & MV_BIT1) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "Packet Interrupt: BMDMA completed with error. " + "status 0x%08x, ATA status 0x%02x\n", BMDMA_status, ATAstatus); + completePacketCommand(pSataChannel, pCommandEntry, MV_TRUE); + return; + } + } + completePacketCommand(pSataChannel, pCommandEntry, MV_FALSE); + return; + } + break; +#endif + default: /* never reached */ + break; + } +} +static MV_BOOLEAN transferPIOData(MV_SATA_CHANNEL *pSataChannel, + MV_NONE_UDMA_COMMAND_PARAMS *pNoneUdmaCommandParams) +{ + MV_U32 i; + MV_U32 dataBlockWords = pSataChannel->DRQDataBlockSize * ATA_SECTOR_SIZE_IN_WORDS; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: xfer data for PIO Data command.count %d\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pNoneUdmaCommandParams->count); + + switch (pNoneUdmaCommandParams->protocolType) + { + case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT: + for (i = 0; i < dataBlockWords; i++) + { + if (pNoneUdmaCommandParams->count == 0) + { + return MV_TRUE; + } + pNoneUdmaCommandParams->count--; + MV_REG_WRITE_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, + *pNoneUdmaCommandParams->bufPtr++); + } + break; + case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN: + for (i = 0; i < dataBlockWords; i++) + { + if (pNoneUdmaCommandParams->count == 0) + { + return MV_TRUE; + } + pNoneUdmaCommandParams->count--; + *pNoneUdmaCommandParams->bufPtr++ = + MV_REG_READ_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET); + } + break; + default: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: in xfer data " + "PIO: command protocol is not Data in/out\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_FALSE; + } + return MV_TRUE; +} +#ifdef MV_SUPPORT_ATAPI +static MV_BOOLEAN transferPacketData(MV_SATA_CHANNEL *pSataChannel, + MV_PACKET_COMMAND_PARAMS *pPacketCommandParams, + MV_U16 byteCount) +{ + MV_U32 i; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: xfer data for Packet command.count %d\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, byteCount); + byteCount >>= 1; + switch (pPacketCommandParams->protocolType) + { + case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN: + for (i = 0; i < byteCount; i++) + { + MV_U16 data; + if (pPacketCommandParams->transfered_data == pPacketCommandParams->buffer_len) + { + return MV_TRUE; + } + pPacketCommandParams->transfered_data += 2; + data = MV_REG_READ_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET); + *pPacketCommandParams->bufPtr++ = MV_CPU_TO_LE16(data); + } + break; + case MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT: + for (i = 0; i < byteCount; i++) + { + if (pPacketCommandParams->transfered_data == pPacketCommandParams->buffer_len) + { + return MV_TRUE; + } + pPacketCommandParams->transfered_data += 2; + MV_REG_WRITE_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_CPU_TO_LE16(MV_ATA_DEVICE_PIO_DATA_REG_OFFSET), + *pPacketCommandParams->bufPtr++); + } + break; + default: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: in xfer data " + "Packet command: non valid protocol type (%d)\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber,pPacketCommandParams->protocolType ); + return MV_FALSE; + } + return MV_TRUE; +} +#endif + +static void completePIOCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_BOOLEAN failed) +{ + MV_COMPLETION_TYPE compType = MV_COMPLETION_TYPE_NORMAL; + MV_STORAGE_DEVICE_REGISTERS deviceRegs; + MV_U8 hostTag; + MV_NONE_UDMA_COMMAND_PARAMS *pParams = + &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand; + + if (pCommandEntry->pCommandInfo->type != MV_QUEUED_COMMAND_TYPE_NONE_UDMA) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d %d: completePIOCommand called for" + " wrong command\n",pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber ); + } + dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, pParams->isEXT, + &deviceRegs); + if (failed == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Command completed " + "with error\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + + compType = MV_COMPLETION_TYPE_ERROR; + pSataChannel->queueCommandsEnabled = MV_FALSE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: PIO Command completed successfully\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + pSataChannel->recoveredErrorsCounter = 0; + } + /* pCommandEntry is invalid after calling the callback function + so we cache the tag to be used later*/ + + hostTag = pCommandEntry->hostTag; + if (hostTag == 0xFF)/*NCQ Error handling ReadLogExt command*/ + { + /*sanity check*/ + if (pCommandEntry != pSataChannel->ErrorHandlingInfo.pReadLogExtEntry) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + "%d %d: in completePIOCommand, command is ReadLogExt" + ", pointers mismatch \n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + } + commandsQueueRemove(pSataChannel,pCommandEntry); + } + else + { + removeCommand(pSataChannel,pCommandEntry); + } + + pParams->callBack(pSataChannel->mvSataAdapter, pSataChannel->channelNumber, + compType, pParams->commandId, 0, 0, &deviceRegs); + + if (hostTag != 0xFF)/*if not NCQ Error handling ReadLogExt command*/ + { + if (failed == MV_TRUE) + { + _doDevErrorRecovery(pSataChannel); + } + else + { + _insertQCommandsIntoEdma(pSataChannel); + } + } +} +#ifdef MV_SUPPORT_ATAPI +static void completePacketCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_BOOLEAN failed) +{ + MV_COMPLETION_TYPE compType = MV_COMPLETION_TYPE_NORMAL; + MV_STORAGE_DEVICE_REGISTERS deviceRegs; + MV_PACKET_COMMAND_PARAMS *pParams = + &pCommandEntry->pCommandInfo->commandParams.packetCommand; + MV_U32 transfered_data = pParams->transfered_data; + + dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, MV_FALSE, + &deviceRegs); + if (failed == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Packet Command completed " + "with error\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: Packet Command completed successfully\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + } + pSataChannel->recoveredErrorsCounter = 0; + + + removeCommand(pSataChannel,pCommandEntry); + + pParams->callBack(pSataChannel->mvSataAdapter, pSataChannel->channelNumber, + compType, pParams->commandId, 0, transfered_data, &deviceRegs); + + _insertQCommandsIntoEdma(pSataChannel); +} +#endif +static MV_VOID initTagsStack(struct _mvTagsStack *pTagsStack, + MV_U8 *pTagsArray, MV_U8 size); + +static MV_U8 popTag(struct _mvTagsStack *pTagsStack); + +static MV_VOID pushTag(struct _mvTagsStack *pTagsStack, MV_U8 tag); + +static MV_BOOLEAN isEmpty(struct _mvTagsStack *pTagsStack); + +static MV_VOID initChannelTags(MV_SATA_CHANNEL *pSataChannel); +static MV_BOOLEAN getTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, + MV_U8 *pHostTag,MV_U8 *pDeviceTag); +static MV_VOID releaseTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, + MV_U8 hostTag,MV_U8 deviceTag); + +static MV_VOID initTagsStack(struct _mvTagsStack *pTagsStack, + MV_U8 *pTagsArray, MV_U8 size) +{ + MV_U8 i; + pTagsStack->pTagsArray = pTagsArray; + pTagsStack->top = size; + for (i = 0; i < size; i++) + { + pTagsStack->pTagsArray[i] = size - 1 - i; + } +} + +static MV_U8 popTag(struct _mvTagsStack *pTagsStack) +{ + return pTagsStack->pTagsArray[--pTagsStack->top]; +} + +static MV_VOID pushTag(struct _mvTagsStack *pTagsStack, MV_U8 tag) +{ + pTagsStack->pTagsArray[pTagsStack->top++] = tag; +} + +static MV_BOOLEAN isEmpty(struct _mvTagsStack *pTagsStack) +{ + if (pTagsStack->top == 0) + { + return MV_TRUE; + } + return MV_FALSE; +} + +static MV_VOID initChannelTags(MV_SATA_CHANNEL *pSataChannel) +{ + MV_U8 i; + for (i = 0; i < MV_SATA_GEN2E_TAG_POOLS_NUM; i++) + { + initTagsStack(&pSataChannel->Tags.DeviceTagsPool[i], + pSataChannel->Tags.DeviceTags[i], + MV_SATA_TAGS_PER_POOL); + } + if (pSataChannel->use128Entries == MV_TRUE) + { + initTagsStack(&pSataChannel->Tags.HostTagsPool, + pSataChannel->Tags.HostTags, + MV_SATA_GEN2E_SW_QUEUE_SIZE); + } + else + { + initTagsStack(&pSataChannel->Tags.HostTagsPool, + pSataChannel->Tags.HostTags, + MV_SATA_SW_QUEUE_SIZE); + } +} +static MV_BOOLEAN getTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, + MV_U8 *pHostTag,MV_U8 *pDeviceTag) +{ + MV_U8 pool = 0;/*for Gen1-2 devices host tag must be equal to device tag*/ + if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) + { + pool = PMPort & MV_SATA_GEN2E_TAG_PMPORT_MASK; + } + if ((MV_TRUE == isEmpty(&pSataChannel->Tags.HostTagsPool)) || + (MV_TRUE == isEmpty(&pSataChannel->Tags.DeviceTagsPool[pool]))) + { + return MV_FALSE; + } + *pHostTag = popTag(&pSataChannel->Tags.HostTagsPool); + *pDeviceTag = popTag(&pSataChannel->Tags.DeviceTagsPool[pool]); + return MV_TRUE; +} +static MV_VOID releaseTag(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort, + MV_U8 hostTag,MV_U8 deviceTag) +{ + MV_U8 pool = 0;/*for Gen1-2 devices host tag must be equal to device tag*/ + if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) + { + pool = PMPort & MV_SATA_GEN2E_TAG_PMPORT_MASK; + } + pushTag(&pSataChannel->Tags.HostTagsPool, hostTag); + pushTag(&pSataChannel->Tags.DeviceTagsPool[pool], deviceTag); +} + +/******************************************************************************* +* _resetEdmaQPointers - resets EDMA's Queues Pointers +* +* +* DESCRIPTION: +* +* INPUT: +* *pSataChannel - pointer to the Sata channel data structure +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* +* COMMENTS: +* this function assumes that the channel semaphore is locked +* +*******************************************************************************/ +static MV_BOOLEAN _resetEdmaQPointers(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr = + pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: _resetEdmaQPointers\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + + pSataChannel->EdmaQueuedCommands = 0; + pSataChannel->reqInPtr = 0; + pSataChannel->rspOutPtr = 0; + + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_REQUEST_Q_BAH_REG_OFFSET, + pSataChannel->requestQueuePciHiAddress); + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_REQUEST_Q_INP_REG_OFFSET, + pSataChannel->requestQueuePciLowAddress & + MV_EDMA_REQUEST_Q_BA_MASK); + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET, 0); + + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET, + pSataChannel->responseQueuePciHiAddress); + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET, + pSataChannel->responseQueuePciLowAddress); + + return MV_TRUE; +} +static void setupEdmaDeviceErrorHandlingConfiguration(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress; + + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2); + + if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_HALT_CONDITIONS_REG_OFFSET, MV_BIT2); + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT10 | MV_BIT8); + } + else + { + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_CONFIG_REG_OFFSET, MV_EDMA_CONFIG_CONONDEVERR_MASK); + /* Fix for 88SX60x1 FEr SATA#25 */ + _setRegBits(ioBaseAddr, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, MV_BIT22); + } + } + else + { + + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_CONFIG_REG_OFFSET, MV_EDMA_CONFIG_CONONDEVERR_MASK); + if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_II) + { + _clearRegBits(ioBaseAddr, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, MV_BIT22); + } + + if (pSataChannel->FBSEnabled == MV_TRUE) + { + if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) + { + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2); + } + else + { + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2); + } + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_HALT_CONDITIONS_REG_OFFSET, MV_BIT2); + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT8); + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT10); + + } + else + { + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, MV_BIT2); + if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_HALT_CONDITIONS_REG_OFFSET, MV_BIT2); + _clearRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT10 | MV_BIT8); + } + } + } +} + +/******************************************************************************* +* resetEdmaChannel - resets the channel data stucture and EDMA registers +* +* +* DESCRIPTION: +* this function resets the low level EDMA fields of Sata channel data +* structure and initialize the EDMA register accourdingly +* +* INPUT: +* *pSataChannel - pointer to the Sata channel data structure +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* +* COMMENTS: +* this function assumes that the channel semaphore is locked +* +*******************************************************************************/ +static MV_BOOLEAN resetEdmaChannel(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr = + pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + int i; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: resetEdmaChannel\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + + if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_COMMAND_REG_OFFSET) & + MV_EDMA_COMMAND_HARD_RST_MASK) + { + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_COMMAND_REG_OFFSET, + MV_EDMA_COMMAND_DISABLE_MASK); + + MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_COMMAND_REG_OFFSET); + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, + MV_HARD_RESET_WAIT_NEGATE); + _fixPhyParams(pSataChannel->mvSataAdapter, pSataChannel->channelNumber); + } + else + { + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_COMMAND_REG_OFFSET, + MV_EDMA_COMMAND_DISABLE_MASK); + } + + pSataChannel->outstandingCommands = 0; + for (i = 0; i <= MV_SATA_PM_MAX_PORTS; i++) + { + pSataChannel->portQueuedCommands[i] = 0; + } + pSataChannel->noneUdmaOutstandingCommands = 0; +#ifdef MV_SUPPORT_ATAPI + pSataChannel->packetOutstandingCommands = 0; +#endif + pSataChannel->EdmaActive = MV_FALSE; + + /* init free entries stack*/ + initChannelTags(pSataChannel); + for (i = 0; i < pSataChannel->commandsQueueSize; i++) + { + pSataChannel->commandsQueue[i].isFreeEntry = MV_TRUE; + } + + pSataChannel->commandsQueueHead = NULL; + pSataChannel->commandsQueueTail = NULL; + pSataChannel->queueCommandsEnabled = MV_FALSE; +#ifdef MV_SATA_C2C_COMM + + /* C2C */ + pSataChannel->C2CmodeEnabled = MV_FALSE; +#endif + pSataChannel->ErrorHandlingInfo.CurrPort = 0; + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE; + pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0; + pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA = MV_FALSE; + pSataChannel->recoveredErrorsCounter = 0; + _resetEdmaQPointers(pSataChannel); + return MV_TRUE; +} + +static void flushDmaQueue(MV_SATA_CHANNEL *pSataChannel,MV_FLUSH_TYPE flushType, + MV_COMPLETION_TYPE completionType, MV_U16 eDmaCause) +{ + mvSataCommandCompletionCallBack_t callBackFunc; + int i; + + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Flush DMA, type=%s, commands" + " %d (on EDMA %d)\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + (flushType==MV_FLUSH_TYPE_CALLBACK)?"CALLBACK":"NONE", + pSataChannel->outstandingCommands,pSataChannel->EdmaQueuedCommands); + + if (flushType == MV_FLUSH_TYPE_CALLBACK) + { + for (i = 0; i < pSataChannel->commandsQueueSize; i++) + { + if (pSataChannel->commandsQueue[i].isFreeEntry == MV_FALSE) + { + MV_STORAGE_DEVICE_REGISTERS deviceRegisters; + MV_BOOLEAN isEXT; + MV_VOID_PTR commandId; + switch (pSataChannel->commandsQueue[i].pCommandInfo->type) + { + case MV_QUEUED_COMMAND_TYPE_NONE_UDMA: + isEXT = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.NoneUdmaCommand.isEXT; + commandId = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.NoneUdmaCommand.commandId; + callBackFunc = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.NoneUdmaCommand.callBack; + break; + case MV_QUEUED_COMMAND_TYPE_UDMA: + isEXT = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.udmaCommand.isEXT; + commandId = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.udmaCommand.commandId; + callBackFunc = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.udmaCommand.callBack; + break; + default: + /* MV_QUEUED_COMMAND_TYPE_PACKET:*/ + isEXT = MV_FALSE; + commandId = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.packetCommand.commandId; + callBackFunc = pSataChannel->commandsQueue[i].pCommandInfo->commandParams.packetCommand.callBack; + break; + } + + dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, isEXT, + &deviceRegisters); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Calling callBackFunc - host tag 0x%x (device tag 0x%x) at %p," + " next %p, prev %p, PMPort 0x%x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + i, + pSataChannel->commandsQueue[i].deviceTag, + &pSataChannel->commandsQueue[i], + pSataChannel->commandsQueue[i].next, + pSataChannel->commandsQueue[i].prev, + pSataChannel->commandsQueue[i].pCommandInfo->PMPort); + callBackFunc(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, completionType, + commandId, eDmaCause, 0, &deviceRegisters); + } + } + } +} + +static void _fixPhyParams(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + /* Set unit 0 or 1 */ + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + /* Set port 0-3 */ + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U32 regVal; + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + + if (pAdapter->chipIs50XXB0 == MV_TRUE) + { + /* Fix for 88SX50xx FEr SATA#12 */ + /* Disable auto-power management*/ + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port)); + regVal |= MV_BIT19; /* disbale auto-power management*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port), + regVal); + /* 88SX50xx FEr SATA#9*/ + /*Fix squelch threshold*/ + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port)); + + regVal &= ~0x3; + regVal |= 0x1; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port), + regVal); + } + /* Revert values of pre-emphasis and signal amps to the saved ones */ + { + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port)); + regVal &= ~MV_SATA_I_PHY_MODE_AMP_MASK; + regVal |= (pAdapter->signalAmps[channelIndex] << MV_SATA_I_PHY_MODE_AMP_OFFSET) & + MV_SATA_I_PHY_MODE_AMP_MASK; + regVal &= ~MV_SATA_I_PHY_MODE_PRE_MASK; + regVal |= (pAdapter->pre[channelIndex] << MV_SATA_I_PHY_MODE_PRE_OFFSET) & + MV_SATA_I_PHY_MODE_PRE_MASK; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port), + regVal); + } + } + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (pAdapter->chipIs62X1Z0 == MV_FALSE)) + { + MV_U32 phyMode2Offset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_PHY_MODE_2_REG_OFFSET; + if ((pAdapter->chipIs60X1B2 == MV_TRUE) || + (pAdapter->chipIs60X1C0 == MV_TRUE)) + { + /* Fix for 88SX60X1 FEr SATA #23 */ + /* 88SX6042/88SX7042 FEr SATA #23 */ + /* 88F5182 FEr #SATA-S13 */ + /* 88F5082 FEr #SATA-S13 */ + MV_U32 regVal2; + regVal2 = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_2_REG_OFFSET); + regVal2 |= MV_BIT31; + regVal2 &= ~MV_BIT16; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_2_REG_OFFSET, + regVal2); + mvMicroSecondsDelay (pAdapter, 200); /* Wait 200uSec */ + regVal2 = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_2_REG_OFFSET); + regVal2 &= ~MV_BIT31; + regVal2 &= ~MV_BIT16; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_2_REG_OFFSET, + regVal2); + mvMicroSecondsDelay (pAdapter, 200); /* Wait 200uSec */ + } + /* Fix values in phyMode 3 register.*/ + { + MV_U32 regVal2 = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_3_REG_OFFSET); + regVal2 &= ~0x7F900000; + regVal2 |= 0x2A800000; + + /* Implement Guidline 88F5182, 88F5082, 88F6082 (GL# SATA-S11) */ + if((pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_5182) || + (pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_5082) || + (pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_6082)) + { + regVal2 &= ~0x1C; + } + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_3_REG_OFFSET, + regVal2); + } + /* Fix values in phyMode 4 register.*/ + /* 88SX60x1 FEr SATA#10 */ + /* 88F5182 GL #SATA-S10 */ + /* 88F5082 GL #SATA-S10 */ + if ((pAdapter->chipIs60X1B2 == MV_TRUE) || + (pAdapter->chipIs60X1C0 == MV_TRUE)) + { + MV_U32 phyMode4Value; + MV_U32 tempRegOffset, tempRegValue = 0; + MV_U32 phyMode4Offset = getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_4_REG_OFFSET; + tempRegOffset = getEdmaRegOffset (channelIndex) + 0x310; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_SATA_LINK, + "%d %d: PHY mode4 reg value before fix is %x\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + phyMode4Offset)); + phyMode4Value = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + phyMode4Offset); + /* 88SX60x1 FEr SATA #13 */ + if (pAdapter->chipIs60X1B2 == MV_TRUE) + { + tempRegValue = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + tempRegOffset); + } + + phyMode4Value |= MV_BIT0; + phyMode4Value &= ~MV_BIT1; + /* phy mode 4 register of Gen IIE devices has some restriction */ + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) + { + phyMode4Value &= ~0x5DE3FFFC; + phyMode4Value |= MV_BIT2; + + } + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + phyMode4Offset, phyMode4Value); + /* 88SX60x1 FEr SATA #13 */ + if (pAdapter->chipIs60X1B2 == MV_TRUE) + { + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + tempRegOffset, tempRegValue); + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_SATA_LINK, + "%d %d: PHY mode4 reg value after fix is %x\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + phyMode4Offset)); + } + + /* Revert values of pre-emphasis and signal amps to the saved ones */ + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + phyMode2Offset); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: PHY mode2 " + "reg = %x (Before AMP/PRE modification)\n", + pAdapter->adapterId, channelIndex, regVal); + + regVal &= ~MV_SATA_II_PHY_MODE_2_AMP_MASK; + regVal |= (pAdapter->signalAmps[channelIndex] << MV_SATA_II_PHY_MODE_2_AMP_OFFSET) & + MV_SATA_II_PHY_MODE_2_AMP_MASK; + regVal &= ~MV_SATA_II_PHY_MODE_2_PRE_MASK; + regVal |= (pAdapter->pre[channelIndex] << MV_SATA_II_PHY_MODE_2_PRE_OFFSET) & + MV_SATA_II_PHY_MODE_2_PRE_MASK; + regVal &= ~MV_BIT16; /* Should always write 0 to bit 16 in phymode 2 */ + + /*some reserved fields must be written with fixed values */ + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) + { + regVal &= ~0xC30FF01F; + regVal |= 0x0000900F; + } + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + phyMode2Offset, regVal); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: PHY mode2 " + "reg = %x (After AMP/PRE modification)\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + phyMode2Offset)); + } + if(pAdapter->chipIs62X1Z0 == MV_TRUE) + { + + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_3_REG_OFFSET); + + regVal &= ~0x78000000; + regVal |= 0x28000000; + + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_3_REG_OFFSET, + regVal); + + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_4_REG_OFFSET); + regVal &= ~0x1; + regVal |= MV_BIT16; /* must write 1 to this bit */ + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_4_REG_OFFSET, + regVal); + + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_9_GEN2_REG_OFFSET); + regVal &= ~0x400F; + regVal |= 0x00008; + + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_9_GEN2_REG_OFFSET, + regVal); + + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_9_GEN1_REG_OFFSET); + regVal &= ~0x400F; + regVal |= 0x00008; + + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_PHY_MODE_9_GEN1_REG_OFFSET, + regVal); + } +} + +static void _channelHardReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_U32 EdmaCommandOffset = getEdmaRegOffset(channelIndex) + + MV_EDMA_COMMAND_REG_OFFSET; + + maskEdmaInterrupts(pAdapter, channelIndex); + /* 1. Set ATA reset bit*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset, + MV_EDMA_COMMAND_HARD_RST_MASK); + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset); + + /* 2. Wait 25uSeconds*/ + mvMicroSecondsDelay(pAdapter, MV_HARD_RESET_WAIT_ASSERT); + + + /* 3. Clear ATA reset bit*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset, 0); + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, EdmaCommandOffset); + + /* 4. Change phy params (watermark + squelch) */ + _fixPhyParams(pAdapter, channelIndex); + /* For Gen 1 devices, time delay is needed after resetingt the SATA bridge*/ + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + mvMicroSecondsDelay(pAdapter, MV_HARD_RESET_WAIT_NEGATE); + } + unmaskEdmaInterrupts(pAdapter, channelIndex); + +} +static void _establishSataComm(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_U32 SControlOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_CONTROL_REG_OFFSET; + MV_U32 SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + MV_U32 SStatus; + MV_U8 retryCount, commRetryCount = 5, retryWithGen1 = 0; + + maskEdmaInterrupts(pAdapter, channelIndex); + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + /* Set DET field in SControl register to 1 */ + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + SControlOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port); + SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + } + + while (1) + { + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset, 0x301); + MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset); + MV_CPU_WRITE_BUFFER_FLUSH(); + mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_DELAY); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset, 0x300); + MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset); + MV_CPU_WRITE_BUFFER_FLUSH(); + mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_WAIT_DELAY); + unmaskEdmaInterrupts(pAdapter, channelIndex); + /*Wait 200 msec for PHY to become ready*/ + for (retryCount = 0; retryCount < 200; retryCount++) + { + if (_checkSStatusAfterHReset(pAdapter, channelIndex) == MV_FALSE) + { + mvMicroSecondsDelay(pAdapter, 1000); + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_SATA_LINK, "%d %d: SATA PHY ready " + "after %d msec\n", pAdapter->adapterId, channelIndex, + retryCount); + + break; + } + } + if (retryCount == 200) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_SATA_LINK, + "%d %d: SATA PHY not ready after 200 msec\n", + pAdapter->adapterId, channelIndex); + } + SStatus = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + SStatusOffset); + /* Fix for 88SX60X1 FEr #10 - retry SATA communication if failed 5 times */ + /* this workaround applied for all devices for simplicity and robustness */ + if ((SStatus == 0x0) || (SStatus == 0x113) || (SStatus == 0x123)) + { + break; + } + commRetryCount --; + if (commRetryCount == 0) + { + MV_U32 regVal; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_FATAL_ERROR, + "%d %d: Failed OOB sequence 5 times !!!\n", + pAdapter->adapterId, channelIndex); + if ((SStatus != 0x121) || (retryWithGen1 == 1) || (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)) + { + break; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_FATAL_ERROR, + "%d %d: SStatus is 0x121, Retry OOB sequence with Gen1 \n", + pAdapter->adapterId, channelIndex); + retryWithGen1 = 1; + commRetryCount = 5; + /* set the phy in offline mode */ + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset, 0x304); + + /* force Sata speed to Gen1*/ + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + /* Fix for 88SX60x1 FEr SATA#8*/ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + regVal &= ~MV_BIT7; /* Disable GEn II */ + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, + regVal); + + _channelHardReset(pAdapter, channelIndex); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d: Retrying OOB sequnce",pAdapter->adapterId, + channelIndex); + } +} + +static void _establishSataCommAll(MV_SATA_ADAPTER *pAdapter) +{ + MV_U8 channelIndex; + MV_U32 SControlOffset; + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + for (channelIndex = 0 ; channelIndex < pAdapter->numberOfChannels ; + channelIndex ++) + { + maskEdmaInterrupts(pAdapter, channelIndex); + SControlOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_CONTROL_REG_OFFSET; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset, + 0x301); + + } + /* Wait for 1mSecond for COMRESET for all drives */ + mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_DELAY); + for (channelIndex = 0 ; channelIndex < pAdapter->numberOfChannels ; + channelIndex ++) + { + SControlOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_CONTROL_REG_OFFSET; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset, + 0x300); + } + mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_WAIT_DELAY); + for (channelIndex = 0 ; channelIndex < pAdapter->numberOfChannels ; + channelIndex ++) + { + unmaskEdmaInterrupts(pAdapter, channelIndex); + } + } +} + + + + + +void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort) +{ + MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + MV_U32 regVal; + + if (pSataChannel->PMSupported == MV_FALSE) + { + return; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_PM, "%d %d: Set TX PM" + " Port to %x\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, PMPort); + + regVal = MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET); + + regVal &= ~MV_SATA_II_IF_CONTROL_PMTX_MASK; + regVal |= (PMPort << MV_SATA_II_IF_CONTROL_PMTX_OFFSET) & + MV_SATA_II_IF_CONTROL_PMTX_MASK; + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET, regVal); + MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET); + +} +static void revertSataHCRegs (MV_SATA_ADAPTER *pAdapter) +{ + MV_U8 channelIndex; + MV_U8 temp; + MV_U32 edmaRegsOffset; + MV_U32 sataHcRegsOffset; + MV_U32 regTemp; + MV_U8 sataUnit; + + if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) || + (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED)) + { + for (sataUnit = 0 ; sataUnit < pAdapter->numberOfUnits ; sataUnit ++) + { + for (temp = 0 ; temp < pAdapter->portsPerUnit ; temp ++) + { + channelIndex = temp + sataUnit * pAdapter->portsPerUnit; + edmaRegsOffset = getEdmaRegOffset(channelIndex); + + /* Disable EDMA */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET, + MV_EDMA_COMMAND_DISABLE_MASK); + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET); + + /* Reset SATA bridge */ + _channelHardReset(pAdapter, channelIndex); + + /* Zero EDMA registersr */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET, 0); + + if(pAdapter->hostInterface == MV_HOST_IF_INTEGRATED) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, 0x101f); + } + else + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, 0x11f); + } + + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_TIMER_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_REQUEST_Q_BAH_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_REQUEST_Q_INP_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET,0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_TEST_CONTROL_REG_OFFSET, 0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegsOffset + MV_EDMA_IORDY_TIMEOUT_REG_OFFSET, 0xbc); + } + + /* Revert values of SATA HC regs (few registers are READ-ONLY ) */ + if(pAdapter->hostInterface != MV_HOST_IF_INTEGRATED) + { + sataHcRegsOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + sataHcRegsOffset + MV_SATAHC_INT_COAL_THRE_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + sataHcRegsOffset + MV_SATAHC_INT_TIME_THRE_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + sataHcRegsOffset + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + sataHcRegsOffset + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, 0); + regTemp = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + sataHcRegsOffset + + MV_SATA_I_HC_BRIDGES_PINS_CONFIG_REG_OFFSET); + /* Keep the SS during power on and the reference clock bits (reset sample )*/ + regTemp &= 0x1c1c1c1c; + regTemp |= 0x03030303; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + sataHcRegsOffset + MV_SATA_I_HC_BRIDGES_PINS_CONFIG_REG_OFFSET, + regTemp); + } + } + } + + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) + { + MV_U32 timeout; + /* Use global reset feature */ + /* Empty PCI master */ + + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET, + MV_PCI_MAIN_COMMAND_STOP_MASTER_MASK); + MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET); + timeout = 1000; + while (timeout) + { + if (MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET) & + MV_PCI_MAIN_COMMAND_MASTER_EMPTY_MASK) + { + break; + } + + mvMicroSecondsDelay (pAdapter, 1); + timeout --; + } + if (timeout == 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: Global reset timeout when" + " trying to flush PCI master - discarding the master flush" + , pAdapter->adapterId); + } + /* Issue global reset - this will reset both SATAHC */ + regTemp = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET); + regTemp |= MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET, regTemp); + regTemp = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET); + if (!(regTemp & MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: Global reset error while " + "writing '1' to the global reset bit",pAdapter->adapterId); + } + mvMicroSecondsDelay (pAdapter, 5); + regTemp &= ~(MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK | MV_PCI_MAIN_COMMAND_STOP_MASTER_MASK); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET, regTemp); + regTemp = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MAIN_COMMAND_STATUS_REG_OFFSET); + if (regTemp & MV_PCI_MAIN_COMMAND_GLOBAL_RESET_MASK) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: Global reset error while " + "writing '1' to the global reset bit",pAdapter->adapterId); + } + mvMicroSecondsDelay (pAdapter, 5); + } +} + +static void revertFlashInterfaceRegs (MV_SATA_ADAPTER *pAdapter) +{ + MV_U32 regTemp; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_FLASH_PARAMS_REG_OFFSET, 0x0fcfffff); + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + regTemp = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET); + regTemp &= 0x3; + regTemp |= (MV_BIT5 | MV_BIT6); + + + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, regTemp); + } +} + +static void revertPCIInterfaceRegs (MV_SATA_ADAPTER *pAdapter) +{ + MV_U32 regTemp; + if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)) + { + if (!((pAdapter->pciConfigDeviceId == MV_SATA_DEVICE_ID_5080) && + (pAdapter->pciConfigRevisionId == 0x0))) + { + regTemp = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET); + regTemp |= MV_BIT0; + + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, regTemp); + } + } + + regTemp = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MODE_REG_OFFSET); + regTemp &= 0xff00ffff; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MODE_REG_OFFSET, regTemp); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_DISCARD_TIMER_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_MSI_TRIGGER_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_XBAR_IF_TIMEOUT_REG_OFFSET, 0x000100ff); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_SERR_MASK_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_INTERRUPT_CAUSE_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_INTERRUPT_MASK_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_ERROR_LOW_ADDRESS_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_ERROR_HIGH_ADDRESS_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_ERROR_ATTRIBUTE_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_ERROR_COMMAND_REG_OFFSET, 0); +} + +static void revertPEXInterfaceRegs (MV_SATA_ADAPTER *pAdapter) +{ + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_E_INTERRUPT_CAUSE_REG_OFFSET, 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_PCI_E_INTERRUPT_MASK_REG_OFFSET, 0); +} +static void commandsQueueAddTail(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry) +{ + pCommandEntry->next = NULL; + pCommandEntry->prev = pSataChannel->commandsQueueTail; + if (pSataChannel->commandsQueueTail != NULL) + { + pSataChannel->commandsQueueTail->next = pCommandEntry; + } + pSataChannel->commandsQueueTail = pCommandEntry; + + if (pSataChannel->commandsQueueHead == NULL) + { + pSataChannel->commandsQueueHead = pCommandEntry; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: command queued. Head:%p Tail:%p " + "command :%p\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pSataChannel->commandsQueueHead, + pSataChannel->commandsQueueTail, pCommandEntry); +} + +static void commandsQueueAddHead(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry) +{ + pCommandEntry->next = pSataChannel->commandsQueueHead; + pCommandEntry->prev = NULL; + if (pSataChannel->commandsQueueHead != NULL) + { + pSataChannel->commandsQueueHead->prev = pCommandEntry; + } + pSataChannel->commandsQueueHead = pCommandEntry; + + if (pSataChannel->commandsQueueTail == NULL) + { + pSataChannel->commandsQueueTail = pCommandEntry; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: command queued. Head:%p Tail:%p " + "command :%p\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pSataChannel->commandsQueueHead, + pSataChannel->commandsQueueTail, pCommandEntry); +} + +static void commandsQueueRemove(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry) +{ + if (pCommandEntry->next == NULL) /* last */ + { + pSataChannel->commandsQueueTail = pCommandEntry->prev; + if (pSataChannel->commandsQueueTail != NULL) + { + pSataChannel->commandsQueueTail->next = NULL; + } + } + else + { + pCommandEntry->next->prev = pCommandEntry->prev; + } + + if (pCommandEntry->prev == NULL) /* head*/ + { + pSataChannel->commandsQueueHead = pCommandEntry->next; + if (pSataChannel->commandsQueueHead != NULL) + { + pSataChannel->commandsQueueHead->prev = NULL; + } + } + else + { + pCommandEntry->prev->next = pCommandEntry->next; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: command removed. Head:%p Tail:%p " + "command :%p\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pSataChannel->commandsQueueHead, + pSataChannel->commandsQueueTail, pCommandEntry); + pCommandEntry->next = NULL; + pCommandEntry->prev = NULL; +} +static void addCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_QUEUE_COMMAND_INFO *pCommandInfo) +{ +#ifndef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK + pCommandEntry->pCommandInfo = &pCommandEntry->commandInfo; + switch (pCommandInfo->type) + { + case MV_QUEUED_COMMAND_TYPE_UDMA: + memcpy(&pCommandEntry->pCommandInfo->commandParams.udmaCommand, + &pCommandInfo->commandParams.udmaCommand, + sizeof(MV_UDMA_COMMAND_PARAMS)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: queue Udma command.\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + break; + case MV_QUEUED_COMMAND_TYPE_NONE_UDMA: + memcpy(&pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand, + &pCommandInfo->commandParams.NoneUdmaCommand, + sizeof(MV_NONE_UDMA_COMMAND_PARAMS)); + pSataChannel->noneUdmaOutstandingCommands++; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: queue Non Udma command.[%d]\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->noneUdmaOutstandingCommands); + break; +#ifdef MV_SUPPORT_ATAPI + case MV_QUEUED_COMMAND_TYPE_PACKET: + memcpy(&pCommandEntry->pCommandInfo->commandParams.packetCommand, + &pCommandInfo->commandParams.packetCommand, + sizeof(MV_PACKET_COMMAND_PARAMS)); + pSataChannel->packetOutstandingCommands++; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: queue Packet command.[%d]\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->packetOutstandingCommands); + break; +#endif + default: + break; + } + pCommandEntry->pCommandInfo->type = pCommandInfo->type; + pCommandEntry->pCommandInfo->PMPort = pCommandInfo->PMPort; +#else + if (pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA) + { + pSataChannel->noneUdmaOutstandingCommands++; + } + else if (pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET) + { + pSataChannel->packetOutstandingCommands++; + } + + pCommandEntry->pCommandInfo = pCommandInfo; +#endif + commandsQueueAddTail(pSataChannel, pCommandEntry); + /* pCommandEntry->commandTag = ?*/ + pCommandEntry->isFreeEntry = MV_FALSE; + pSataChannel->outstandingCommands++; + pSataChannel->portQueuedCommands[pCommandInfo->PMPort]++; +} + +static void removeCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry) +{ + if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: remove Udma command.\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + } + else if (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: remove Non Udma command.[%d]\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->noneUdmaOutstandingCommands); + + pSataChannel->noneUdmaOutstandingCommands--; + } +#ifdef MV_SUPPORT_ATAPI + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: remove Packet command.[%d]\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->packetOutstandingCommands); + + pSataChannel->packetOutstandingCommands--; + } +#endif + commandsQueueRemove(pSataChannel,pCommandEntry); + releaseTag(pSataChannel, pCommandEntry->pCommandInfo->PMPort, + pCommandEntry->hostTag,pCommandEntry->deviceTag); + pCommandEntry->isFreeEntry = MV_TRUE; + pSataChannel->outstandingCommands--; + pSataChannel->portQueuedCommands[pCommandEntry->pCommandInfo->PMPort]--; +} + +static MV_U32 SaDevInterrutpBit(MV_U8 channelIndex) +{ + MV_U32 maskBit = 0; + + if (channelIndex >= MV_SATA_PORT_PER_UNIT) + { + maskBit = (1 << ((channelIndex << 1) + 2)); + } + else + { + maskBit = (1 << ((channelIndex << 1) + 1)); + } + return maskBit; +} +static void enableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_U32 maskBit = 0; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: enable SaDevInterrupts.\n", + pAdapter->adapterId, channelIndex); + maskBit = SaDevInterrutpBit(channelIndex); + mvOsSemTake(&pAdapter->interruptsMaskSem); + + pAdapter->mainMask |= maskBit; + + /*clear disk interrupt */ + MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + /* clear DevInterrupt*/ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET((channelIndex & MV_BIT2) >> 2) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, + ~(MV_BIT8 << (channelIndex & (MV_BIT0 | MV_BIT1)))); + + /* unmask*/ + if (pAdapter->interruptsAreMasked == MV_FALSE) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset); + + } + mvOsSemRelease(&pAdapter->interruptsMaskSem); +} + +void disableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_U32 maskBit = 0; + + + maskBit = SaDevInterrutpBit(channelIndex); + mvOsSemTake(&pAdapter->interruptsMaskSem); + pAdapter->mainMask &= ~maskBit; + if (pAdapter->interruptsAreMasked == MV_FALSE) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset); + + } + mvOsSemRelease(&pAdapter->interruptsMaskSem); +} +static void _checkATAStatus(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_U8 ATAstatus = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + if ((ATAstatus & (MV_ATA_BUSY_STATUS|MV_ATA_DATA_REQUEST_STATUS| + MV_ATA_READY_STATUS|MV_ATA_DEVICE_FAULT_STATUS| + MV_ATA_ERROR_STATUS)) == MV_ATA_READY_STATUS) + { + return; + } + } + else + { + if ((ATAstatus & (MV_ATA_BUSY_STATUS|MV_ATA_DATA_REQUEST_STATUS| + MV_ATA_READY_STATUS)) == MV_ATA_READY_STATUS) + { + return; + } + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: _checkATAStatus " + "EDMA can't be enabled with ATA status (0x%02x), do SW reset\n", + pAdapter->adapterId, channelIndex, ATAstatus); + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, MV_SATA_PM_CONTROL_PORT); + } + _doSoftReset(pSataChannel); +} +static void activateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 eDmaRegsOffset; + MV_U8 sataUnit; + MV_U8 port; + + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: activateEdma\n", pAdapter->adapterId, + channelIndex); + pSataChannel->EdmaActive = MV_TRUE; + sataUnit = (channelIndex & MV_BIT2) >> 2; + port = channelIndex & (MV_BIT0 | MV_BIT1); + /* clear Device interrupt */ + MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, + ~((MV_BIT8 | MV_BIT0) << port)); + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + MV_REG_WRITE_DWORD(ioBaseAddr, + pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0); + } + else + { + MV_REG_WRITE_DWORD(ioBaseAddr, + pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, MV_BIT8); + } + + /* disable sata device interrupts */ + disableSaDevInterrupts(pAdapter, channelIndex); + + MV_CPU_WRITE_BUFFER_FLUSH(); + + _checkATAStatus(pAdapter, channelIndex); + + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET, + MV_EDMA_COMMAND_ENABLE_MASK); +} + +static void deactivateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 eDmaRegsOffset; + MV_U32 counter = 0; + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: deactivateEdma\n", pAdapter->adapterId, + channelIndex); + pSataChannel->EdmaActive = MV_FALSE; + + MV_CPU_WRITE_BUFFER_FLUSH(); + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET, + MV_EDMA_COMMAND_DISABLE_MASK); + while (counter < 1000) + { + if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_COMMAND_REG_OFFSET) & MV_BIT0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: deactivateEdma: " + "Edma still active. elapsed time %d us\n", pAdapter->adapterId, + channelIndex, counter * 1000); + mvMicroSecondsDelay(pAdapter, 1000); + } + else + { + break; + } + counter++; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: deactivateEdma: " + "Edma status reg 0x%08x\n", pAdapter->adapterId, + channelIndex, MV_REG_READ_DWORD(ioBaseAddr, + eDmaRegsOffset + + MV_EDMA_STATUS_REG_OFFSET)); + if (counter >= 1000) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + " %d %d: deactivateEdma: Edma Failed (EDMA status = %x)\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD(ioBaseAddr, + eDmaRegsOffset + MV_EDMA_STATUS_REG_OFFSET)); + pSataChannel->queueCommandsEnabled = MV_FALSE; + flushDmaQueue (pSataChannel, MV_FLUSH_TYPE_CALLBACK, + MV_COMPLETION_TYPE_ABORT, 0); + resetEdmaChannel(pSataChannel); + mvOsSemRelease(&pSataChannel->semaphore); + pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_ERROR, + MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR, + channelIndex); + mvOsSemTake(&pSataChannel->semaphore); + } + + /*_dumpSataRegs(pAdapter, channelIndex);*/ + enableSaDevInterrupts(pAdapter, channelIndex); +} + +static void EdmaReqQueueInsert(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry, + MV_UDMA_COMMAND_PARAMS *pUdmaParams) +{ + MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress; + + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND, " %d %d: Insert Edma " + "Request. PMPort %x host tag = 0x%x device tag = 0x%x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pCommandEntry->pCommandInfo->PMPort, + pCommandEntry->hostTag, pCommandEntry->deviceTag); + + /* insert the last commmand into the Edma queue */ + if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { + writeGen2EEdmaRequestEntry (&pSataChannel->requestQueue[pSataChannel->reqInPtr], + pSataChannel, pCommandEntry, pUdmaParams); + } + else + { + writeEdmaRequestEntry (&pSataChannel->requestQueue[pSataChannel->reqInPtr], + pSataChannel, pCommandEntry, pUdmaParams); + } + pSataChannel->reqInPtr++; + pSataChannel->reqInPtr &= pSataChannel->EDMAQueuePtrMask; + pSataChannel->EdmaQueuedCommands++; + pCommandEntry->isCommandInEdma = MV_TRUE; + pCommandEntry->commandAborted = MV_FALSE; + + MV_CPU_WRITE_BUFFER_FLUSH(); + MV_REG_WRITE_DWORD(ioBaseAddr, + pSataChannel->eDmaRegsOffset + + MV_EDMA_REQUEST_Q_INP_REG_OFFSET, + pSataChannel->requestQueuePciLowAddress | + ((pSataChannel->reqInPtr << MV_EDMA_REQUEST_Q_INP_OFFSET) + & pSataChannel->EDMARequestInpMask)); +} + +static MV_VOID _insertQCommandsIntoEdma(MV_SATA_CHANNEL *pSataChannel) +{ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: _insert" + "QCommandsIntoEdma\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + + if (pSataChannel->commandsQueueHead == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: Commands queue is empty\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return; + } + if (pSataChannel->commandsQueueHead->pCommandInfo->type == + MV_QUEUED_COMMAND_TYPE_NONE_UDMA) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: Next Command is PIO\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, + pSataChannel->commandsQueueHead->pCommandInfo->PMPort); + } + if (sendNoneUdmaCommand(pSataChannel, + pSataChannel->commandsQueueHead) == MV_FALSE) + { + completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead, + MV_TRUE); + } + + } +#ifdef MV_SUPPORT_ATAPI + + else if (pSataChannel->commandsQueueHead->pCommandInfo->type == + MV_QUEUED_COMMAND_TYPE_PACKET) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: Next Command is Packet\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, + pSataChannel->commandsQueueHead->pCommandInfo->PMPort); + } + if (sendNoneUdmaCommand(pSataChannel, + pSataChannel->commandsQueueHead) == MV_FALSE) + { + completePacketCommand(pSataChannel, pSataChannel->commandsQueueHead, + MV_TRUE); + } + + } +#endif /* MV_SUPPORT_ATAPI */ + else + { + MV_QUEUED_COMMAND_ENTRY *pEntry; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "%d %d: Next Command is UDMA\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + activateEdma(pSataChannel->mvSataAdapter,pSataChannel->channelNumber); + pEntry = pSataChannel->commandsQueueHead; + while ((pEntry != NULL) && + (pEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA)) + { + EdmaReqQueueInsert(pSataChannel, pEntry, + &pEntry->pCommandInfo->commandParams.udmaCommand); + pEntry = pEntry->next; + } + + } + +} +/* do device error recovery for PIO, DMA and QUEUED DMA commands (not NCQ)*/ +static MV_BOOLEAN _doDevErrorRecovery(MV_SATA_CHANNEL *pSataChannel) +{ + if ((pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I) || + (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED)) + { + if (_doSoftReset(pSataChannel) == MV_FALSE) + { + return MV_FALSE; + } + } + pSataChannel->queueCommandsEnabled = MV_TRUE; + /* Enable the storage device interrupts */ + enableSaDevInterrupts(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber); + _resetEdmaQPointers(pSataChannel); + _insertQCommandsIntoEdma(pSataChannel); + return MV_TRUE; +} +/* this function used for NCQ error handling or FBS mode, it cheks if further commands + expected to be completed successfully (from drives without errors in PM)*/ +static MV_BOOLEAN isGoodCompletionsExpected(MV_SATA_CHANNEL *pSataChannel) +{ + MV_QUEUED_COMMAND_ENTRY *pEntry; + + pEntry = pSataChannel->commandsQueueHead; + while (pEntry != NULL) + { + if (pEntry->isCommandInEdma == MV_TRUE) + { + if (pEntry->commandAborted == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: isGoodCompletionsExpected: command (host tag 0x%02x)" + "(device tag 0x%02x) expected with good completion from port 0x%02x. " + "PortsWithErros= 0x%04x \n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pEntry->hostTag, + pEntry->deviceTag, + pEntry->pCommandInfo->PMPort, + pSataChannel->ErrorHandlingInfo.PortsWithErrors); + return MV_TRUE; + } + } + else + { + /* stop once reached a command that has not been inserted into the + EDMA since the next commands also must be outside the EDMA + */ + break; + } + pEntry = pEntry->next; + } + + if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + MV_U32 EDMAStatus = MV_REG_READ_DWORD( + pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_STATUS_REG_OFFSET); + + /*wait for internal commands cache to be empty */ + if ((EDMAStatus & MV_EDMA_STATUS_ECACHE_EMPTY_BIT) == 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: isGoodCompletionsExpected: eCache not empty," + " wait for completions with errors\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_TRUE; + } + if ((EDMAStatus & MV_EDMA_STATUS_EDMA_IDLE_BIT) == 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: isGoodCompletionsExpected: EDMA is not Idle\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_TRUE; + } + } + } + /* check for responses*/ + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + MV_U32 rspInReg = MV_REG_READ_DWORD( + pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET); + MV_U32 rspInPtr = 0; + if (pSataChannel->use128Entries == MV_TRUE) + { + rspInPtr = getRegField(rspInReg, 3, 7); + } + else + { + rspInPtr = getRegField(rspInReg, 3, 5); + } + + + if (pSataChannel->rspOutPtr != rspInPtr) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: isGoodCompletionsExpected: More responses need to be " + "handled, Response In Ptr 0x%x, SW Response Out Ptr 0x%x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + rspInPtr, pSataChannel->rspOutPtr); + return MV_TRUE; + } + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: isGoodCompletionsExpected: No commands expected to be " + "completed. PortrNumDevError 0x%04x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->ErrorHandlingInfo.PortsWithErrors); + return MV_FALSE; +} +/* this function used for NCQ error handling, this function called wheb DevErr + interrupt receivedm it checks which PM ports repored device error and updates + PortsWithErrors varibles +*/ + +static MV_VOID updatePortsWithErrors(MV_SATA_CHANNEL *pSataChannel) +{ + MV_U32 testCtrlReg = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_TEST_CTRL_REG_OFFSET); + testCtrlReg &= 0xFFFF0000; + testCtrlReg = testCtrlReg >> 16; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: updatePortsWithErrors: old val 0x%04x, new 0x%04x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->ErrorHandlingInfo.PortsWithErrors, + pSataChannel->ErrorHandlingInfo.PortsWithErrors | testCtrlReg); + + pSataChannel->ErrorHandlingInfo.PortsWithErrors |= (MV_U16)testCtrlReg; +} +/* this function called when Device Error occures in NCQ mode or FBS mode*/ +/* is detects which outstanding commands (command in the EDMA) are aborted by*/ +/* the drive due to the error, also it resumes the transport layer*/ +static MV_VOID setAbortedCommands(MV_SATA_CHANNEL *pSataChannel) +{ + MV_QUEUED_COMMAND_ENTRY *pEntry; + MV_U32 TCQOutStandingStatus[4] = {0,0,0,0}; + MV_U8 TCQPortWithError = 0; + /*sanity checks*/ + if ((pSataChannel == NULL) || (pSataChannel->EdmaActive == MV_FALSE)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID,MV_DEBUG_FATAL_ERROR, + "setAbortedCommands called in wrong context\n"); + return; + } + if (pSataChannel->FBSEnabled == MV_TRUE) + { + MV_U32 TCQStatus = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_TCQ_STATUS_REG_OFFSET); + + TCQOutStandingStatus[0] = MV_REG_READ_DWORD( + pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_NCQTCQ0_OUTSTANDING_REG_OFFSET); + TCQOutStandingStatus[1] = MV_REG_READ_DWORD( + pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_NCQTCQ1_OUTSTANDING_REG_OFFSET); + TCQOutStandingStatus[2] = MV_REG_READ_DWORD( + pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_NCQTCQ2_OUTSTANDING_REG_OFFSET); + TCQOutStandingStatus[3] = MV_REG_READ_DWORD( + pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_NCQTCQ3_OUTSTANDING_REG_OFFSET); + + { + MV_U32 regVal = MV_REG_READ_DWORD( + pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_STATUS_REG_OFFSET); + + TCQPortWithError = (MV_U8)getRegField(regVal, 8, 4); + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: setAbortedCommands: \n" + "TCQPortWithError = 0x%04x \n" + "TCQStatus = 0x%04x \n" + "TCQ0OutStandingStatus = 0x%04x \n" + "TCQ1OutStandingStatus = 0x%04x \n" + "TCQ2OutStandingStatus = 0x%04x \n" + "TCQ3OutStandingStatus = 0x%04x \n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + TCQPortWithError, + TCQStatus, + TCQOutStandingStatus[0], + TCQOutStandingStatus[1], + TCQOutStandingStatus[2], + TCQOutStandingStatus[3]); + /* clear DRQ bit */ + if (TCQStatus & (MV_BIT0 << TCQPortWithError)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: setAbortedCommands Clear TCQ DRQ\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + TCQStatus &= ~(MV_BIT0 << TCQPortWithError); + MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_TCQ_STATUS_REG_OFFSET, TCQStatus); + } + /* clear SERVICE bit */ + if (TCQStatus & (MV_BIT16 << TCQPortWithError)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: setAbortedCommands Clear TCQ Service\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + TCQStatus &= ~(MV_BIT16 << TCQPortWithError); + MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_TCQ_STATUS_REG_OFFSET, TCQStatus); + } + /* clear Device errors in EDMA error cause register */ + MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,~MV_BIT2); + + /*clear interrupt cause to resume the transport layer operation*/ + MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_FIS_INTERRUPT_CAUSE_REG_OFFSET, + ~MV_BIT8); + } + pEntry = pSataChannel->commandsQueueHead; + while (pEntry != NULL) + { + if (pEntry->isCommandInEdma == MV_TRUE) + { + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + if ((((MV_U16)(1 << pEntry->pCommandInfo->PMPort)) & + pSataChannel->ErrorHandlingInfo.PortsWithErrors) != 0) + { + pEntry->commandAborted = MV_TRUE; + } + } + else /*FBS*/ + { + if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED) + { + if (pEntry->pCommandInfo->PMPort == TCQPortWithError) + { + MV_U32 bitmap = (1 << ((MV_U32)pEntry->hostTag)); + MV_U8 reg = (pEntry->hostTag >> 5) & 0x3; + if ((bitmap & TCQOutStandingStatus[reg]) != 0) + { + pEntry->commandAborted = MV_TRUE; + } + } + } + } + if (pEntry->commandAborted == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: command (host tag 0x%02x)" + "(device tag 0x%02x) not expected, port 0x%02x. \n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pEntry->hostTag, + pEntry->deviceTag, + pEntry->pCommandInfo->PMPort); + } + } + else + { + /* stop once reached a command that has not been inserted into the + EDMA since the next commands also must be outside the EDMA + */ + break; + } + pEntry = pEntry->next; + } +} +/* this function used for NCQ error handling, called when device error received + and no further good complitions expected. it stops the EDMA and starts the + process if sending ReadLogExt commands to the drives that reported device + errors +*/ +static MV_VOID enterRequestSenseState(MV_SATA_CHANNEL *pSataChannel) +{ + MV_U8 ATAstatus; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: enterRequestSenseState: PortsWithErrors 0x%04x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->ErrorHandlingInfo.PortsWithErrors); + /* Fix for 88SX60x1 FEr SATA#25 */ + { + pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA = MV_FALSE; + if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_II) + { + MV_U32 EDMAStatus = MV_REG_READ_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_STATUS_REG_OFFSET); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: EDMA state is %x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, EDMAStatus); + + if (getRegField(EDMAStatus, 8, 8) == 0x70) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: EDMA state is 0x70 do WA\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA = MV_TRUE; + } + } + } + deactivateEdma(pSataChannel->mvSataAdapter, pSataChannel->channelNumber); + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED) + { + if (pSataChannel->FBSEnabled != MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID,MV_DEBUG_FATAL_ERROR, + "enterRequestSenseState called in wrong context\n"); + return; + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: enterRequestSenseState: Finished All erring ports\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE; + pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0; + _resetEdmaQPointers(pSataChannel); + _insertQCommandsIntoEdma(pSataChannel); + return; + } + + /* clear Device errors in EDMA error cause register due to the aborted + commands*/ + MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,~MV_BIT2); + /* the EDMA may be disabled after FPDMA commands issued and before */ + /* receiving response from the drive (D2H Fis), in this case the ATA */ + /* busy bit will be set, so we wait for this bit to be cleared by the */ + /* drive when is sends D2H registers Fis and SaDevInterrupt will be issued*/ + + /* clear SaDevInterrupt if already received*/ + { + MV_U8 port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2; + + MV_REG_WRITE_DWORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port)); + } + + ATAstatus = MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + + if (ATAstatus & MV_ATA_BUSY_STATUS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ATA Busy" + "bit is set after disabling EDMA, wait for SaDevInterrupt\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_WAIT_FOR_BUSY; + return; + } + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_REQUEST_SENSE; + pSataChannel->ErrorHandlingInfo.CurrPort = 0; + if (pSataChannel->queuedDMA == MV_EDMA_MODE_QUEUED)/*TCQ*/ + { + softResetErringPorts(pSataChannel); + } + else + { + setReadLogExtCmndPointers(pSataChannel); + handlePortError(pSataChannel); + } +} + + + +/* this function used for NCQ error handling, called from the ReadLogExt command + callback function, it makes sanity checks for the command output and + completes the erring command with the ATA registers values, finally it calls + handlePortError to handle NCQ errors from the next drive if any*/ +static MV_BOOLEAN parseReadLogExtOutPut(MV_SATA_CHANNEL *pSataChannel) +{ + MV_U32 count; + MV_U8 tag; + MV_STORAGE_DEVICE_REGISTERS registerStruct; + MV_QUEUED_COMMAND_ENTRY *pCommandEntry; + + MV_U8_PTR ReadLogExtBuffer = (MV_U8_PTR)pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer; + /* chack CRC*/ + { + MV_U8 crc = 0; + for (count = 0 ; count < ATA_SECTOR_SIZE ; count ++) + { + crc += ReadLogExtBuffer[count]; + } + if (crc != 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut " + "ATA Command failed due to wrong CRC checksum (%02x)\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber,crc); + return MV_FALSE; + } + } + /* Swap to little endianess */ + for (count = 0 ; count < ATA_SECTOR_SIZE_IN_WORDS; count++) + { + /* CPU to little*/ + pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer[count] = + MV_LE16_TO_CPU(pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer[count]); + } + + for (count = 0; count < 3; count++) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " ReadLogExt: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + ReadLogExtBuffer[(count * 6) + 0], + ReadLogExtBuffer[(count * 6) + 1], + ReadLogExtBuffer[(count * 6) + 2], + ReadLogExtBuffer[(count * 6) + 3], + ReadLogExtBuffer[(count * 6) + 4], + ReadLogExtBuffer[(count * 6) + 5]); + } + /* check NQ bit*/ + if (ReadLogExtBuffer[0] & MV_BIT7) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: " + "Error - NQ is set\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_FALSE; + } + + if (_getHostTagByDeviceTag(pSataChannel, + 0x1F & ReadLogExtBuffer[0], + pSataChannel->ErrorHandlingInfo.CurrPort, + &tag) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: " + "parseReadLogExtOutPut: " + "Error - None Valid device tag (0x%02x)\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->ErrorHandlingInfo.CurrPort, + 0x1F & ReadLogExtBuffer[0]); + return MV_FALSE; + } + pCommandEntry = &pSataChannel->commandsQueue[tag]; + if (pCommandEntry->isFreeEntry == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: " + "Error - No command with tag (0x%02x) has been issued\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, tag); + return MV_FALSE; + } + if (pCommandEntry->pCommandInfo->PMPort != pSataChannel->ErrorHandlingInfo.CurrPort) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: " + "Error - command PM Port (0x%02x) and CurrPort (0x%02x) doesn't match\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pCommandEntry->pCommandInfo->PMPort, + pSataChannel->ErrorHandlingInfo.CurrPort); + return MV_FALSE; + } + if (pCommandEntry->pCommandInfo->type != MV_QUEUED_COMMAND_TYPE_UDMA) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: parseReadLogExtOutPut: " + "Error - command with tag (0x%02x) isn't UDMA command\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, tag); + return MV_FALSE; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: parseReadLogExtOutPut: " + " command tag (0x%02x)\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, tag); + registerStruct.statusRegister = ReadLogExtBuffer[2]; + registerStruct.deviceRegister = ReadLogExtBuffer[7]; + registerStruct.errorRegister = ReadLogExtBuffer[3]; + registerStruct.lbaLowRegister = (ReadLogExtBuffer[8] << 8) | ReadLogExtBuffer[4]; + registerStruct.lbaMidRegister = (ReadLogExtBuffer[9] << 8) | ReadLogExtBuffer[5]; + registerStruct.lbaHighRegister = (ReadLogExtBuffer[10] << 8) | ReadLogExtBuffer[6]; + registerStruct.sectorCountRegister = (ReadLogExtBuffer[13] << 8) | ReadLogExtBuffer[12]; + + _printATARegs(®isterStruct); + + pSataChannel->EdmaQueuedCommands--; + pCommandEntry->pCommandInfo->commandParams.udmaCommand.callBack(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, + MV_COMPLETION_TYPE_ERROR, + pCommandEntry->pCommandInfo->commandParams.udmaCommand.commandId, + 0x04, + 0, ®isterStruct); + removeCommand(pSataChannel,pCommandEntry); + return MV_TRUE; +} +static MV_BOOLEAN _getHostTagByDeviceTag(MV_SATA_CHANNEL *pSataChannel, + MV_U8 deviceTag, + MV_U8 PMPort, + MV_U8 *pHostTag) +{ + MV_QUEUED_COMMAND_ENTRY *pEntry = pSataChannel->commandsQueueHead; + while (pEntry != NULL) + { + if (pEntry->isCommandInEdma == MV_TRUE) + { + if ((pEntry->deviceTag == deviceTag) && + (pEntry->pCommandInfo->PMPort == PMPort)) + { + *pHostTag = pEntry->hostTag; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%d %d %d: _getHostTagByDeviceTag, command entry found, " + "host tag = 0x%02x, deviceTag(0x%02x)\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + PMPort, + *pHostTag, + deviceTag); + return MV_TRUE; + } + } + else + { + /* stop once reached a command that has not been inserted into the + EDMA since the next commands also must be outside the EDMA + */ + break; + } + pEntry = pEntry->next; + } + return MV_FALSE; +} +/* this function used for NCQ error handling, it's the callback function of the + ReadLogExt command with issued by adding command entry to the channel's + commands queue */ +static MV_BOOLEAN +ReadLogExtCompletionCB(MV_SATA_ADAPTER *pSataAdapter, + MV_U8 channelNum, + MV_COMPLETION_TYPE comp_type, + MV_VOID_PTR commandId, + MV_U16 responseFlags, + MV_U32 timeStamp, + MV_STORAGE_DEVICE_REGISTERS *registerStruct) +{ + MV_SATA_CHANNEL *pSataChannel = pSataAdapter->sataChannel[channelNum]; + + switch (comp_type) + { + case MV_COMPLETION_TYPE_NORMAL: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: ReadLogExtCompletionCB: Normal completion. Port 0x%02x\n", + pSataAdapter->adapterId, channelNum, + pSataChannel->ErrorHandlingInfo.CurrPort); + if (parseReadLogExtOutPut(pSataChannel) == MV_TRUE) + { + /* Fix for 88SX60x1 FEr SATA#25 */ + { + if (pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA == MV_TRUE) + { + MV_U32 i; + MV_U8 ATAstatus; + _doSoftReset(pSataChannel); + for (i = 0;i < 31000; i++) + { + ATAstatus = MV_REG_READ_BYTE(pSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) + { + break; + } + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 1000); + } + } + } + pSataChannel->ErrorHandlingInfo.CurrPort++; + handlePortError(pSataChannel); + } + break; + default: + /* when ReadLogExt fails or parseReaDLogExtOutPut fails do nothing*/ + /* the higher layers will not have the queued commands completed so it*/ + /* should recover this situation by it's timeout error recovery*/ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: ReadLogExtCompletionCB: Bad completion. Port 0x%02x\n", + pSataAdapter->adapterId, channelNum, + pSataChannel->ErrorHandlingInfo.CurrPort); + _printATARegs(registerStruct); + _dumpSataRegs(pSataAdapter, channelNum); + break; + } + return MV_TRUE; +} +/* this function used for NCQ error handling, it "allocates" command entry of the + ReadLogExt command and data buffer used for that command from the EDMA + requests queue which is not used meanwhile since the EDMA disabled*/ +static MV_VOID setReadLogExtCmndPointers(MV_SATA_CHANNEL *pSataChannel) +{ + struct ReadLogExtBuffers + { + MV_QUEUED_COMMAND_ENTRY entry; +#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK + MV_QUEUE_COMMAND_INFO commandInfo; +#endif + MV_U16 pioBuffer[ATA_SECTOR_SIZE_IN_WORDS]; + }; + /* EDMA is not active, so we use the request queue buffer for Read Log Ext + command data */ + struct ReadLogExtBuffers *pReadLogExtBuffers = + (struct ReadLogExtBuffers *)pSataChannel->requestQueue; + pSataChannel->ErrorHandlingInfo.pReadLogExtEntry = &pReadLogExtBuffers->entry; + pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer = pReadLogExtBuffers->pioBuffer; + +#ifdef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK + pSataChannel->ErrorHandlingInfo.pReadLogExtEntry->pCommandInfo = + &pReadLogExtBuffers->commandInfo; +#else + pSataChannel->ErrorHandlingInfo.pReadLogExtEntry->pCommandInfo = + &pReadLogExtBuffers->entry.commandInfo; +#endif +} +/* this function used for NCQ error handling, it sets the ReadLogExt command + entry, then issues the command to the CuttPort*/ +static MV_VOID insertReadLogExtCmnd(MV_SATA_CHANNEL *pSataChannel) +{ + MV_QUEUED_COMMAND_ENTRY *pEntry = pSataChannel->ErrorHandlingInfo.pReadLogExtEntry; + MV_NONE_UDMA_COMMAND_PARAMS *pReadLogExtPIOParams = + &pEntry->pCommandInfo->commandParams.NoneUdmaCommand; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: insertReadLogExtCmnd: Port 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->ErrorHandlingInfo.CurrPort); + + pReadLogExtPIOParams->bufPtr = pSataChannel->ErrorHandlingInfo.ReadLogExtBuffer; + pReadLogExtPIOParams->callBack = ReadLogExtCompletionCB; + pReadLogExtPIOParams->command = MV_ATA_COMMAND_READ_LOG_EXT; + pReadLogExtPIOParams->commandId = NULL; + pReadLogExtPIOParams->count = ATA_SECTOR_SIZE_IN_WORDS; + pReadLogExtPIOParams->device = 0; + pReadLogExtPIOParams->features = 0; + pReadLogExtPIOParams->isEXT = MV_TRUE; + pReadLogExtPIOParams->lbaHigh = 0; + pReadLogExtPIOParams->lbaLow = 0x10; + pReadLogExtPIOParams->lbaMid = 0; + pReadLogExtPIOParams->protocolType = MV_NON_UDMA_PROTOCOL_PIO_DATA_IN; + pReadLogExtPIOParams->sectorCount = 1; + pEntry->pCommandInfo->type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA; + pEntry->pCommandInfo->PMPort = pSataChannel->ErrorHandlingInfo.CurrPort; + pEntry->isCommandInEdma = MV_FALSE; + pEntry->commandAborted = MV_FALSE; + pEntry->isFreeEntry = MV_FALSE; + pEntry->hostTag = 0xFF; + pEntry->deviceTag = 0xFF; + commandsQueueAddHead(pSataChannel, pEntry); + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, pEntry->pCommandInfo->PMPort); + + } + /* Fix for 88SX60x1 FEr SATA#25 */ + if (pSataChannel->ErrorHandlingInfo.useVendorUniqGen2WA == MV_TRUE) + { + MV_U32 FISBuffer[5]; + FISBuffer[0] = ((MV_ATA_COMMAND_READ_LOG_EXT << 16)& 0xFF0000) | + MV_BIT15 | 0x27; + FISBuffer[1] = 0x10; + FISBuffer[2] = 0; + FISBuffer[3] = 1; + FISBuffer[4] = 0; + + sendVendorUniqueFIS(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, + FISBuffer, 5); + + return; + } + + if (sendNoneUdmaCommand(pSataChannel, pEntry) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Failed to " + "Issue ReadLogExt PIO command\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead, + MV_TRUE); + } +} +/* this function used for NCQ error handling, it checks the comming port + that experienced NCQ device error starting from CurrPort, if no port found, + it sets the NCQ error handling state to the Idle state and re-queues the + outstanding commands*/ +static MV_VOID handlePortError(MV_SATA_CHANNEL *pSataChannel) +{ + while (pSataChannel->ErrorHandlingInfo.CurrPort <= MV_SATA_PM_MAX_PORTS) + { + if (((MV_U16)( 1 << pSataChannel->ErrorHandlingInfo.CurrPort)) & pSataChannel->ErrorHandlingInfo.PortsWithErrors) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: handlePortError: Device Error found on Port " + "0x%02x\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->ErrorHandlingInfo.CurrPort); + break; + } + pSataChannel->ErrorHandlingInfo.CurrPort++; + } + if (pSataChannel->ErrorHandlingInfo.CurrPort > MV_SATA_PM_MAX_PORTS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: handlePortError: Finished All erring ports\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE; + pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0; + _resetEdmaQPointers(pSataChannel); + _insertQCommandsIntoEdma(pSataChannel); + return; + } + insertReadLogExtCmnd(pSataChannel); +} +static MV_VOID softResetErringPorts(MV_SATA_CHANNEL *pSataChannel) +{ + while (pSataChannel->ErrorHandlingInfo.CurrPort <= MV_SATA_PM_MAX_PORTS) + { + if (((MV_U16)( 1 << pSataChannel->ErrorHandlingInfo.CurrPort)) & pSataChannel->ErrorHandlingInfo.PortsWithErrors) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: softResetErringPorts: Device Error found on Port " + "0x%02x\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + pSataChannel->ErrorHandlingInfo.CurrPort); + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, + pSataChannel->ErrorHandlingInfo.CurrPort); + + } + _doSoftReset(pSataChannel); + } + pSataChannel->ErrorHandlingInfo.CurrPort++; + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: softResetErringPorts: Finished All erring ports\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + pSataChannel->ErrorHandlingInfo.state = MV_ERROR_HANDLING_STATE_IDLE; + pSataChannel->ErrorHandlingInfo.PortsWithErrors = 0; + _resetEdmaQPointers(pSataChannel); + _insertQCommandsIntoEdma(pSataChannel); + return; +} +static MV_BOOLEAN sendNoneUdmaCommand(MV_SATA_CHANNEL *pSataChannel, + MV_QUEUED_COMMAND_ENTRY *pCommandEntry) +{ + MV_NONE_UDMA_COMMAND_PARAMS *pParams = + &pCommandEntry->pCommandInfo->commandParams.NoneUdmaCommand; + MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset; + MV_U8 ATAstatus; + unsigned int i; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + " %d %d Issue NON UDMA command: protocol(%d) buff %p , words %x ," + " features %x , sector count %x , lba %x.%x.%x device %x " + "command=%x\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pParams->protocolType, + pParams->bufPtr, pParams->count, + pParams->features, pParams->sectorCount, + pParams->lbaLow, pParams->lbaMid, + pParams->lbaHigh, pParams->device, + pParams->command); + + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & (MV_ATA_READY_STATUS | MV_ATA_BUSY_STATUS)) != + MV_ATA_READY_STATUS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: storage drive is not" + " ready, ATA STATUS=0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + return MV_FALSE; + } + + if(pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET) + { + if(pParams->protocolType == MV_NON_UDMA_PROTOCOL_PACKET_DMA) + { + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_FEATURES_REG_OFFSET, MV_BIT0); + } + else + { + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_FEATURES_REG_OFFSET, 0); + } + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, 0); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, 0); + + /* set byte count limit to 8KB (0x2000)*/ + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, 0x00); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, 0x20); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_HEAD_REG_OFFSET, 0); + MV_CPU_WRITE_BUFFER_FLUSH(); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_COMMAND_REG_OFFSET,MV_ATA_COMMAND_PACKET ); + + } + else + { + if (pParams->isEXT == MV_TRUE) + { + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_FEATURES_REG_OFFSET, + (pParams->features & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, + (pParams->sectorCount & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, + (pParams->lbaLow & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, + (pParams->lbaMid & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, + (pParams->lbaHigh & 0xff00) >> 8); + } + else + { + if ((pParams->features & 0xff00) || + (pParams->sectorCount & 0xff00) || + (pParams->lbaLow & 0xff00) || + (pParams->lbaMid & 0xff00) || + (pParams->lbaHigh & 0xff00)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR | MV_DEBUG_NON_UDMA_COMMAND, + " %d %d :in Issue NON UDMA command:" + " bits[15:8] of register values should be reserved" + " Features 0x%02x, SectorCount 0x%02x, LBA Low 0x%02x," + " LBA Mid 0x%02x, LBA High 0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, pParams->features, + pParams->sectorCount, pParams->lbaLow, + pParams->lbaMid, pParams->lbaHigh); + return MV_FALSE; + } + } + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_FEATURES_REG_OFFSET, pParams->features & 0xff); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, pParams->sectorCount & 0xff); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, pParams->lbaLow & 0xff); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, pParams->lbaMid & 0xff); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, pParams->lbaHigh & 0xff); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_HEAD_REG_OFFSET, pParams->device); + + MV_CPU_WRITE_BUFFER_FLUSH(); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_COMMAND_REG_OFFSET, pParams->command); + } + if ((pParams->protocolType == MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT) || + (pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET)) + { + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET); + + /* Wait for the command to complete */ + if (waitWhileStorageDevIsBusy(pSataChannel->mvSataAdapter, + ioBaseAddr, eDmaRegsOffset, 10, 100) == + MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: in Issue PIO " + "DATA-OUT command: disk not ready.\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_FALSE; + } + + if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + + if (waitForDRQ(pSataChannel->mvSataAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000) + == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: DRQ bit in ATA STATUS" + " register is not set\n", pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber); + return MV_FALSE; + } + } + /* Check the status register on DATA request commands */ + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & (MV_ATA_DATA_REQUEST_STATUS | MV_ATA_BUSY_STATUS | MV_ATA_ERROR_STATUS)) != + MV_ATA_DATA_REQUEST_STATUS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: in Issue PIO " + "DATA-OUT command: Bad ATA STATUS:0x%02x.\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + return MV_FALSE; + } + + if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /* Perform a dummy read */ + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + mvMicroSecondsDelay (pSataChannel->mvSataAdapter, 1); + } +#ifdef MV_SUPPORT_ATAPI + if(pCommandEntry->pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_PACKET) + { + MV_PACKET_COMMAND_PARAMS *pParams = + &pCommandEntry->pCommandInfo->commandParams.packetCommand; + for (i = 0; i < pParams->cdb_len ; i++) + { + MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, + MV_CPU_TO_LE16(pParams->cdb_buffer[i])); + } + for(; i < 6; i++) + { + MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, + 0); + + } + MV_CPU_WRITE_BUFFER_FLUSH(); + pSataChannel->waitForBMDMA = MV_FALSE; + if(pParams->protocolType == MV_NON_UDMA_PROTOCOL_PACKET_DMA) + { + activateBMDmaMode(pSataChannel->mvSataAdapter, + pSataChannel->channelNumber, + pParams->prdHighAddr, + pParams->prdLowAddr, + (pParams->flags & MV_BIT0) ? MV_UDMA_TYPE_WRITE: MV_UDMA_TYPE_READ); + + } + return MV_TRUE; + } +#endif + for (i = 0; i < ATA_SECTOR_SIZE_IN_WORDS; i++) + { + MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, + *pParams->bufPtr++); + MV_CPU_WRITE_BUFFER_FLUSH(); + } + pParams->count -= ATA_SECTOR_SIZE_IN_WORDS; +#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG + + /* for Write long only*/ + if (pParams->count == 4) + { + if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /* Perform a dummy read */ + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + mvMicroSecondsDelay (pSataChannel->mvSataAdapter, 1); + } + if (waitWhileStorageDevIsBusy(pSataChannel->mvSataAdapter, + ioBaseAddr, eDmaRegsOffset, + 50000, 100) == MV_FALSE) + { + return MV_FALSE; + } + if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + if (waitForDRQ(pSataChannel->mvSataAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100) + == MV_FALSE) + { + return MV_FALSE; + } + } + for (i = 0; i < 4; i++) + { + MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, + *pParams->bufPtr++); + MV_CPU_WRITE_BUFFER_FLUSH(); + + + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Write Long ECC data" + " xfered. ATA STATUS:0x%02x.\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + } + pParams->count -= 4; + } +#endif /*MV_SATA_SUPPORT_READ_WRITE_LONG*/ + } + return MV_TRUE; +} + +/* SATA Core API functions */ + +/******************************************************************************* +* mvSataInitAdapter - initialize MV88SX50XX adapter +* +* DESCRIPTION: +* this function initializes glabal registers that concerns PCI access +* and Interrupts. +* +* INPUT: +* *pAdapter - pointer to the adapter data structure. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* +* COMMENTS: +* The adapter will not be able yet to generate interrupts +* +*******************************************************************************/ +MV_BOOLEAN mvSataInitAdapter (MV_SATA_ADAPTER *pAdapter) +{ + MV_U8 sataUnit; + MV_U8 channelIndex; + MV_U32 regVal; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " : mvSataInitAdapter" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + + if (mvOsSemInit(&pAdapter->semaphore) == MV_FALSE) + { + return MV_FALSE; + } + + if (mvOsSemInit(&pAdapter->interruptsMaskSem) == MV_FALSE) + { + return MV_FALSE; + } +#ifdef MV_SATA_IO_GRANULARITY + if (mvOsSemInit(&pAdapter->iogSemaphore) == MV_FALSE) + { + return MV_FALSE; + } +#endif + + if (pAdapter->mvSataEventNotify == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d : Bad pointer for " + "mvSataEventNotify function\n", pAdapter->adapterId); + return MV_FALSE; + } + + /* Initialize the hardware workarounds to false, and to 8 channels */ + pAdapter->chipIs50XXB0 = MV_FALSE; + pAdapter->chipIs50XXB2 = MV_FALSE; + pAdapter->chipIs60X1B2 = MV_FALSE; + pAdapter->chipIs60X1C0 = MV_FALSE; + pAdapter->chipIs62X1Z0 = MV_FALSE; + pAdapter->numberOfChannels = MV_SATA_CHANNELS_NUM; + pAdapter->numberOfUnits = MV_SATA_UNITS_NUM; + pAdapter->portsPerUnit = MV_SATA_PORT_PER_UNIT; + pAdapter->hostInterface = MV_HOST_IF_PCI; + pAdapter->mainMaskOffset = MV_MAIN_INTERRUPT_MASK_REG_OFFSET; + pAdapter->mainCauseOffset = MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET; + switch (pAdapter->pciConfigDeviceId) + { + case MV_SATA_DEVICE_ID_5080 : + pAdapter->sataAdapterGeneration = MV_SATA_GEN_I; + switch (pAdapter->pciConfigRevisionId) + { + case 0x1: + pAdapter->chipIs50XXB0 = MV_TRUE; + break; + case 0x3: + pAdapter->chipIs50XXB2 = MV_TRUE; + break; + default: + if (pAdapter->pciConfigRevisionId > 0x3) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d : Warning: Future revision ID %02x for Device " + "ID %02x. Implementing latest workarounds\n", + pAdapter->adapterId, pAdapter->pciConfigRevisionId, + pAdapter->pciConfigDeviceId); + pAdapter->chipIs50XXB2 = MV_TRUE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d : Bad revision ID %02x for Device ID %02x\n", + pAdapter->adapterId, pAdapter->pciConfigRevisionId, + pAdapter->pciConfigDeviceId); + return MV_FALSE; + } + } + break; + case MV_SATA_DEVICE_ID_5041 : + case MV_SATA_DEVICE_ID_5040 : + pAdapter->numberOfChannels = MV_SATA_PORT_PER_UNIT; + pAdapter->numberOfUnits = 1; + case MV_SATA_DEVICE_ID_5081 : + pAdapter->sataAdapterGeneration = MV_SATA_GEN_I; + switch (pAdapter->pciConfigRevisionId) + { + case 0x0: + pAdapter->chipIs50XXB0 = MV_TRUE; + break; + case 0x3: + pAdapter->chipIs50XXB2 = MV_TRUE; + break; + default: + if (pAdapter->pciConfigRevisionId > 0x3) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Warning: Future revis" + "ion ID %02x. Implementing latest workarounds\n", + pAdapter->adapterId, pAdapter->pciConfigRevisionId); + pAdapter->chipIs50XXB2 = MV_TRUE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Bad revisi" + "on ID %02x\n", pAdapter->adapterId, + pAdapter->pciConfigRevisionId); + return MV_FALSE; + } + } + break; + case MV_SATA_DEVICE_ID_6041 : + pAdapter->numberOfChannels = MV_SATA_PORT_PER_UNIT; + pAdapter->numberOfUnits = 1; + case MV_SATA_DEVICE_ID_6081 : + pAdapter->sataAdapterGeneration = MV_SATA_GEN_II; + switch (pAdapter->pciConfigRevisionId) + { + case 0x7:/*B2*/ + pAdapter->chipIs60X1B2 = MV_TRUE; + break; + case 0x9:/*C0*/ + pAdapter->chipIs60X1C0 = MV_TRUE; + break; + default: + if (pAdapter->pciConfigRevisionId > 0x9) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Warning:" + " Future revision ID %02x. Implementing latest " + "workarounds\n", pAdapter->adapterId, + pAdapter->pciConfigRevisionId); + pAdapter->chipIs60X1C0 = MV_TRUE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d : Device %02x Bad revision ID %02x\n", + pAdapter->adapterId, + pAdapter->pciConfigDeviceId, + pAdapter->pciConfigRevisionId); + return MV_FALSE; + } + } + break; + case MV_SATA_DEVICE_ID_7042 : + pAdapter->hostInterface = MV_HOST_IF_PEX; + case MV_SATA_DEVICE_ID_6042 : + pAdapter->numberOfChannels = MV_SATA_PORT_PER_UNIT; + pAdapter->numberOfUnits = 1; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + switch (pAdapter->pciConfigRevisionId) + { + case 0x2:/*B0*/ + pAdapter->chipIs60X1C0 = MV_TRUE; + break; + default: + if (pAdapter->pciConfigRevisionId > 0x2) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Warning:" + " Future revision ID %02x for Device %02x." + " Implementing latest workarounds\n", + pAdapter->adapterId, + pAdapter->pciConfigRevisionId, + pAdapter->pciConfigDeviceId); + pAdapter->chipIs60X1C0 = MV_TRUE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d : Device %02x Bad revision ID %02x\n", + pAdapter->adapterId, + pAdapter->pciConfigDeviceId, + pAdapter->pciConfigRevisionId); + return MV_FALSE; + } + } + break; + + case MV_SATA_DEVICE_ID_5182: + pAdapter->numberOfChannels = MV_SATA_5182_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_5182_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->chipIs60X1C0 = MV_TRUE; + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; /*the iobaseaddress is 0x60000*/ + pAdapter->mainCauseOffset = 0x20020; + break; + + case MV_SATA_DEVICE_ID_5082: + pAdapter->numberOfChannels = MV_SATA_5082_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_5082_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->chipIs60X1C0 = MV_TRUE; + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; /*the iobaseaddress is 0x60000*/ + pAdapter->mainCauseOffset = 0x20020; + mvSataChannelPhyShutdown(pAdapter, 1); + break; + + case MV_SATA_DEVICE_ID_6082: + pAdapter->numberOfChannels = MV_SATA_6082_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_6082_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->chipIs60X1C0 = MV_TRUE; + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; /*the iobaseaddress is 0x40000*/ + pAdapter->mainCauseOffset = 0x20020; + break; + + case MV_SATA_DEVICE_ID_6490: + pAdapter->numberOfChannels = MV_SATA_6490_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_6490_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->chipIs60X1C0 = MV_TRUE; + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; + pAdapter->mainCauseOffset = 0x20020; + + /* enable swap DMA Data, EDMA descriptors and PRD tables to keep the data layout + * as in the PCI adapters + */ + _clearRegBits(pAdapter->adapterIoBaseAddress, + MV_SATAHC_0_REGS_BASE_OFFSET, + MV_BIT10 | MV_BIT9 | MV_BIT8); + + break; + case MV_SATA_DEVICE_ID_78XX0: + case MV_SATA_DEVICE_ID_78100: + case MV_SATA_DEVICE_ID_78200: + pAdapter->numberOfChannels = MV_SATA_78XX0_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_78XX0_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; + pAdapter->mainCauseOffset = 0x20020; + pAdapter->chipIs62X1Z0 = MV_TRUE; + break; + case MV_SATA_DEVICE_ID_6281: + pAdapter->numberOfChannels = MV_SATA_6281_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_6281_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; + pAdapter->mainCauseOffset = 0x20020; + pAdapter->chipIs62X1Z0 = MV_TRUE; + break; + case MV_SATA_DEVICE_ID_6192: + pAdapter->numberOfChannels = MV_SATA_6192_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_6192_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; + pAdapter->mainCauseOffset = 0x20020; + pAdapter->chipIs62X1Z0 = MV_TRUE; + break; + case MV_SATA_DEVICE_ID_6190: + pAdapter->numberOfChannels = MV_SATA_6190_PORT_NUM; + pAdapter->numberOfUnits = 1; + pAdapter->portsPerUnit = MV_SATA_6190_PORT_NUM; + pAdapter->sataAdapterGeneration = MV_SATA_GEN_IIE; + /*The integrated sata core chip based on 60x1 C0*/ + pAdapter->hostInterface = MV_HOST_IF_INTEGRATED; + pAdapter->mainMaskOffset = 0x20024; + pAdapter->mainCauseOffset = 0x20020; + pAdapter->chipIs62X1Z0 = MV_TRUE; + break; + + default: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : Bad device ID" + " 0x%04x\n", pAdapter->adapterId, + pAdapter->pciConfigDeviceId); + return MV_FALSE; + } + + /* Clear main mask register to prevent adapter from generating interrupts */ + pAdapter->mainMask = 0; + pAdapter->interruptsAreMasked = MV_TRUE; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, pAdapter->mainMask); + + /* + * Save the PRE and AMP in the adapter. Also set staggared spin up to be + * disabled on default (60x1 only). + */ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d : Saving PRE and AMP values\n", + pAdapter->adapterId); + for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) + { + MV_U32 PHYModeRegister; + pAdapter->staggaredSpinup[channelIndex] = MV_FALSE; + pAdapter->ifSpeed[channelIndex] = MV_SATA_IF_SPEED_NO_LIMIT; + pAdapter->ifPowerState[channelIndex] = MV_SATA_IF_POWER_PHY_READY; + pAdapter->limitInterfaceSpeed[channelIndex] = MV_FALSE; + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + PHYModeRegister = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET((channelIndex & MV_BIT2) >> 2) + + MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(channelIndex & (MV_BIT0 | MV_BIT1))); + pAdapter->signalAmps[channelIndex] = (MV_U8)((PHYModeRegister & MV_SATA_I_PHY_MODE_AMP_MASK) >> MV_SATA_I_PHY_MODE_AMP_OFFSET); + pAdapter->pre[channelIndex] = (MV_U8)((PHYModeRegister & MV_SATA_I_PHY_MODE_PRE_MASK) >> MV_SATA_I_PHY_MODE_PRE_OFFSET); + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /* + * Check if TWSI serial ROM initialization was triggered. + * If so, then PRE/AMP configuration probably are set after + * reset by serial ROM. If not then override the PRE/AMP + * values. + */ + if ((pAdapter->hostInterface != MV_HOST_IF_INTEGRATED) && + ((MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, MV_RESET_CONFIG_REG_OFFSET)) + & MV_RESET_CONFIG_TWSI_INIT_MASK)) + { + + MV_U32 phyMode2Offset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_PHY_MODE_2_REG_OFFSET; + /* Make sure EDMA is off */ + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_EDMA_COMMAND_REG_OFFSET, + MV_EDMA_COMMAND_DISABLE_MASK); + MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_EDMA_COMMAND_REG_OFFSET); + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + phyMode2Offset); + pAdapter->signalAmps[channelIndex] = + (MV_U8)((regVal & MV_SATA_II_PHY_MODE_2_AMP_MASK) >> + MV_SATA_II_PHY_MODE_2_AMP_OFFSET); + pAdapter->pre[channelIndex] = + (MV_U8)((regVal & MV_SATA_II_PHY_MODE_2_PRE_MASK) >> + MV_SATA_II_PHY_MODE_2_PRE_OFFSET); + } + else + { + pAdapter->signalAmps[channelIndex] = 0x7; + pAdapter->pre[channelIndex] = 0x1; + } + } + } +#ifndef MV_NO_SW_RESET_FOR_THE_ADAPTER + /* Revert the registers to it's default value (software reset) */ + revertSataHCRegs (pAdapter); + + if (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED) + { + revertFlashInterfaceRegs (pAdapter); + } + + if (pAdapter->hostInterface == MV_HOST_IF_PEX) + { + revertPEXInterfaceRegs(pAdapter); + } + else if (pAdapter->hostInterface == MV_HOST_IF_PCI) + { + revertPCIInterfaceRegs(pAdapter); + } +#endif + + /* Enable the SATA LEDs if the silicon revision is B0 */ + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d : Enabling SATA LEDS\n", + pAdapter->adapterId); + /* Enable the SATA leds */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, 0x0); + if (pAdapter->chipIs50XXB2 == MV_TRUE) + { + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET); + for (channelIndex = 0 ; channelIndex < pAdapter->numberOfChannels ; + channelIndex ++) + { + if (mvSataIsStorageDeviceConnected (pAdapter,channelIndex, NULL) == MV_FALSE) + { + regVal |= (MV_BIT8 << channelIndex); + } + } + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, + regVal); + } + /* disable Flash controller clock*/ + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET); + + regVal &= ~(MV_BIT0); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET, + regVal); + } + + /* Enable the SATA LEDs for 88SX60X1 devices */ + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) + + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d : Enabling SATA LEDS\n", + pAdapter->adapterId); + /* Enable the SATA leds */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_FLASH_GPIO_PORT_CONTROL_OFFSET, 0x00000060); + + } + + /* Check if working in PCI-X mode, then disable all conventional PCI */ + /* features */ + if (pAdapter->hostInterface == MV_HOST_IF_PCI) + { + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_MODE_REG_OFFSET); + if (((regVal & MV_PCI_MODE_MASK) >> MV_PCI_MODE_OFFSET) != 0) /* PCI-X */ + { + if (pAdapter->pciCommand & MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : disable pci conventio" + "nal features when working in PCI-X. pciCommand origin" + "al value:0x%08x. new value: 0x%08x.\n", + pAdapter->adapterId, + pAdapter->pciCommand, pAdapter->pciCommand & + (~MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY)); + pAdapter->pciCommand &= ~MV_PCI_COMMAND_PCI_CONVENTIONAL_ONLY; + } + if ((pAdapter->chipIs50XXB0 == MV_TRUE) || + (pAdapter->chipIs50XXB2 == MV_TRUE) || + (pAdapter->chipIs60X1B2 == MV_TRUE)) + { + /* Fix for 88SX50xx FEr PCI#1*/ + /* Fix for 88SX60x1 FEr PCI#7*/ + if (pAdapter->pciCommand & MV_PCI_MWRITE_COMBINE_BIT) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : PCI-X Master" + " Write combine enable rejected\n", + pAdapter->adapterId); + pAdapter->pciCommand &= ~MV_PCI_MWRITE_COMBINE_BIT; + } + } + } + else + { + if ((pAdapter->chipIs50XXB0 == MV_TRUE) || + (pAdapter->chipIs50XXB2 == MV_TRUE)) + { + /* Fix for 88SX50xx FEr PCI#2*/ + if (pAdapter->pciCommand & MV_PCI_MWRITE_COMBINE_BIT) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : PCI Master" + " Write combine enable rejected\n", + pAdapter->adapterId); + pAdapter->pciCommand &= ~MV_PCI_MWRITE_COMBINE_BIT; + } + if (pAdapter->pciCommand & MV_PCI_MREAD_COMBINE_BIT) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d : PCI Master" + " Read combine enable rejected\n", + pAdapter->adapterId); + pAdapter->pciCommand &= ~MV_PCI_MREAD_COMBINE_BIT; + } + } + } + } +#if 0 + /* Fix for 88SX60x1 FEr SATA#8*/ + for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) + { + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* Fix for 88SX60x1 FEr SATA#8*/ + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, + regVal); + /* _channelHardReset(pAdapter, channelIndex);*/ + } + + _fixPhyParams(pAdapter, channelIndex); + } +#endif + if (pAdapter->hostInterface == MV_HOST_IF_PCI) + { + + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_COMMAND_REG_OFFSET, + pAdapter->pciCommand); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_SERR_MASK_REG_OFFSET, + pAdapter->pciSerrMask); + + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_INTERRUPT_MASK_REG_OFFSET, + pAdapter->pciInterruptMask); + } + else if (pAdapter->hostInterface == MV_HOST_IF_PEX) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + MV_PCI_E_INTERRUPT_MASK_REG_OFFSET, + MV_PCI_E_ERROR_MASK_VALUE); + } + for (sataUnit = 0; sataUnit < pAdapter->numberOfUnits; sataUnit++) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INT_COAL_THRE_REG_OFFSET, + pAdapter->intCoalThre[sataUnit]); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INT_TIME_THRE_REG_OFFSET, + pAdapter->intTimeThre[sataUnit]); + + } +//Patch by QNAP:Fix OnBoard SATA LED and Ethernet LED + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,MV_SATAHC_REGS_BASE_OFFSET(0) + MV_SATAHC_LED_CONF_REG_OFFSET, 0x0c); +////////////////////////////////////////////////////////////////// + if (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED) + { + pAdapter->mainMask = MV_BIT8|MV_BIT2|MV_BIT0; + } + else + { + pAdapter->mainMask = MV_MAIN_INTERRUPT_MASK_ENABLE_ALL; + } + pAdapter->interruptsScheme = MV_SATA_INTERRUPT_HANDLING_IN_ISR; + + for (channelIndex = 0; channelIndex < pAdapter->numberOfChannels; channelIndex++) + { + unmaskEdmaInterrupts(pAdapter, channelIndex); + } + return MV_TRUE; +} + +/******************************************************************************* +* mvSataShutDownAdapter - Shuts down adapter. +* +* DESCRIPTION: Shuts down a specific 88SX50xx adapter. +* +* INPUT: +* *pAdapter - pointer to the adapter data structure. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE on success, MV_FALSE on failure +* +* COMMENTS: +* None. +* +*******************************************************************************/ + +MV_BOOLEAN mvSataShutdownAdapter(MV_SATA_ADAPTER *pAdapter) +{ + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataShutdownAdapter Failed, Bad adapter data structure " + "pointer\n"); + return MV_FALSE; + } + pAdapter->interruptsAreMasked = MV_TRUE; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, 0); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataReadReg - return the value of register. +* +* DESCRIPTION: +* return the value of a register, which have the offset regOffset, in a +* MV88SX50XX adapter. +* Note that if reading from storage device's internal registers and EDMA +* is enabled, then the read transaction will never complete and possibly +* cause system hang. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* regOffset - offset of the register +* +* RETURN: +* the register value in 32 bit. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_U32 mvSataReadReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset) +{ + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataReadReg Failed," + " Bad adapter data structure pointer\n"); + return 0; + } + + return MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, regOffset); +} + +/******************************************************************************* +* mvSataWriteReg - return the value of register. +* +* DESCRIPTION: +* write the regValue to a register, which have the offset regOffset, in a +* MV88SX50XX adapter. +* Note that if writing to storage device's internal registers and EDMA +* is enabled, then the write transaction will never complete and possibly +* cause system hang. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* regOffset - offset of the register +* regValue - the value to write to the register +* +* RETURN: +* None. +* COMMENTS: +* for 8 or 16 bit registers the low bits of the regValue should hold the +* requested value to be written. +* +*******************************************************************************/ +MV_VOID mvSataWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset, + MV_U32 regValue) +{ + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataWriteReg Failed," + " Bad adapter data structure pointer\n"); + return; + } + + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, regOffset, regValue); +} +/******************************************************************************* +* mvSataConfigureChannel - configure Sata channel +* +* +* DESCRIPTION: +* this function configures SATA channel by resetting the low level fields +* of the channel data structure and configures EDMA regs accourdingly +* +* INPUT: +* pAdapter - pointer to the MV88SX50XX adapter data structure +* channelIndex - the index of the channel where the response received +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* +* COMMENTS: +* None. +* +*******************************************************************************/ +MV_BOOLEAN mvSataConfigureChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BOOLEAN result; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataConfigureChannel" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataConfigureChann" + "el Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + if (pAdapter->numberOfChannels <= channelIndex) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataConfigureChann" + "el Failed - requsted to configure a non-valid channel\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + pSataChannel->eDmaRegsOffset = getEdmaRegOffset(channelIndex); + pSataChannel->mvSataAdapter = pAdapter; + + if (mvOsSemInit(&pSataChannel->semaphore)==MV_FALSE) + { + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + + /* Sets the request and response queues base addresses */ + pSataChannel->queueCommandsEnabled = MV_FALSE; + pSataChannel->EdmaActive = MV_FALSE; + pSataChannel->deviceType = MV_SATA_DEVICE_TYPE_UNKNOWN; + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + pSataChannel->PMSupported = MV_TRUE; + } + else + { + pSataChannel->PMSupported = MV_FALSE; + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_IIE) + { + pSataChannel->commandsQueue = pAdapter->adapterCommands + + (MV_SATA_GEN2E_SW_QUEUE_SIZE * channelIndex); + pSataChannel->commandsQueueSize = MV_SATA_GEN2E_SW_QUEUE_SIZE; + } + else + { + pSataChannel->commandsQueue = pAdapter->adapterCommands + + (MV_SATA_SW_QUEUE_SIZE * channelIndex); + pSataChannel->commandsQueueSize = MV_SATA_SW_QUEUE_SIZE; + } + pSataChannel->DRQDataBlockSize = 1; + pSataChannel->FBSEnabled = MV_FALSE; + pSataChannel->use128Entries = MV_FALSE; + pSataChannel->EDMAQueuePtrMask = MV_EDMA_QUEUE_MASK; + pSataChannel->EDMARequestInpMask = MV_EDMA_REQUEST_Q_INP_MASK; + result = resetEdmaChannel(pSataChannel); + disableSaDevInterrupts(pAdapter, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return result; +} + +/******************************************************************************* +* mvSataRemoveChannel - +* +* DESCRIPTION: Removes data structures and other parameters used for the +* specific SATA channel that is indicated by pAdapter and channelIndex. +* +* INPUT: +* pAdapter - A pointer to an MV_SATA_ADAPTER data structure that holds +* information to access the 88SX50xx device. +* channelIndex - An index to a specific 88SX50xx channel. +* OUTPUT: +* None. +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataRemoveChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataRemoveChannel" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + mvOsSemTake(&pAdapter->semaphore); + pSataChannel = pAdapter->sataChannel[channelIndex]; + + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataRemoveChannel" + " Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pAdapter->semaphore); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataRemoveChannel " + "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + mvOsSemRelease(&pAdapter->semaphore); + return MV_FALSE; + } + mvOsSemRelease(&pSataChannel->semaphore); + mvOsSemRelease(&pAdapter->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataIsStorageDeviceConnected - Check if storage device is connected to a +* SATA channel. +* +* DESCRIPTION: +* This function reads the DET field from the R00 status bridge register +* of the corresponding channel. +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* OUTPU: +* SStatus - Pointer to SATA status reg value +* +* RETURN: +* MV_TRUE when storage device is connected, MV_FALSE otherwise( also when +* loopback mode is used). +* +* COMMENTS: +* None +* +*******************************************************************************/ +MV_BOOLEAN mvSataIsStorageDeviceConnected(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 *SStatus) +{ + MV_U32 SStatusOffset = 0; + MV_U32 det; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," : " + "mvSataIsStorageDeviceConnected Failed, Bad adapter data" + " structure pointer\n"); + return MV_FALSE; + } + + if (pAdapter->numberOfChannels <= channelIndex) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "mvSataIsStorageDeviceConnected Failed, Bad channelIndex " + " input on a 0x%x adapterstructure pointer\n", + pAdapter->adapterId,channelIndex,pAdapter->pciConfigDeviceId); + return MV_FALSE; + } + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + SStatusOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R00_STATUS_BRIDGE_PORT_OFFSET(port); + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + if (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE) + { + return MV_FALSE; + } + } + + det = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + SStatusOffset) & 0xf; + + switch (det) + { + case MV_PHY_DET_STATE_NO_DEVICE: + break; + case MV_PHY_DET_STATE_DEVICE_NO_PHY_COM: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: Detection value is 1\n", pAdapter->adapterId, + channelIndex); + + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + SStatusOffset); + mvMicroSecondsDelay(pAdapter, MV_PHY_COM_SETUP_WAIT); + det = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + SStatusOffset) & 0xf; + if (det != MV_PHY_DET_STATE_DEVICE_AND_PHY_COM) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Failed to" + " establish SATA PHY communication\n", + pAdapter->adapterId, channelIndex); + break; + } + case MV_PHY_DET_STATE_DEVICE_AND_PHY_COM: + return MV_TRUE; + case MV_PHY_DET_STATE_PHY_OFFLINE: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: WARNING: SATA PHY is " + "offline\n", pAdapter->adapterId, channelIndex); + break; + default: + return MV_FALSE; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: unknow value for\ + R00 Status Bridge reg bits[3:0] (0x%02x)\n", + pAdapter->adapterId, channelIndex, det); + } + return MV_FALSE; +} + +static MV_BOOLEAN _checkSStatusAfterHReset(MV_SATA_ADAPTER* pAdapter, + MV_U8 channelIndex) +{ + MV_U32 SStatusOffset; + MV_U32 SStatus; + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + /* Get DET field in SControl register to 1 */ + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + SStatusOffset = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R00_STATUS_BRIDGE_PORT_OFFSET(port); + } + else + { + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + } + else + { + return MV_TRUE; + } + } + SStatus = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + SStatusOffset); + SStatus &= (MV_BIT0 | MV_BIT1); + if ((SStatus == (MV_BIT0 | MV_BIT1)) || (SStatus == 0)) + { + return MV_TRUE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard " + "Reset SATA communication not established.\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } +} + + +/******************************************************************************* +* mvSataChannelHardReset - issue channel SATA HARD reset. +* +* DESCRIPTION: +* perform HARDWARE RESET to the connected device by asserting the RESET +* signal, this is done by setting the hardware reset bit of the EDMA +* command register +* +* INPUT: +* pAdapter - pointer to the device data structure. +* channelIndex - index of the required channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvSataChannelHardReset(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 count = 0; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataChannelHardReset" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + ioBaseAddr = pAdapter->adapterIoBaseAddress; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: " + "mvSataChannelHardReset Failed, channel data structure not " + "allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + if(pSataChannel) + mvOsSemTake(&pSataChannel->semaphore); + + if (pSataChannel && pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Error:\ + mvSataIChannelHardReset called while EDMA is active\n", + pAdapter->adapterId,channelIndex); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Issue HRST\n", pAdapter->adapterId, + channelIndex); + + + _channelHardReset(pAdapter, channelIndex); + _resetBmDma(pAdapter, channelIndex); + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE)) + { + if(pSataChannel) + mvOsSemRelease( &pSataChannel->semaphore); + return MV_TRUE; + } + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + while (1) + { + _establishSataComm(pAdapter, channelIndex); + + /* try the DET fix 3 times */ + if (_checkSStatusAfterHReset(pAdapter, channelIndex) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard " + "Reset storage drive is not ready, try fix #%d\n", + pAdapter->adapterId, channelIndex, count); + + count++; + if (count == 3) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel H" + "ard Reset storage drive is not ready after 3 tries\n", + pAdapter->adapterId, channelIndex); + if(pSataChannel) + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: Disk is Ready After" + " Hard Reset\n", pAdapter->adapterId, channelIndex); + break; + } + } + } + + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + _establishSataComm(pAdapter, channelIndex); + } + if(pSataChannel) + mvOsSemRelease( &pSataChannel->semaphore); + return MV_TRUE; +} +/******************************************************************************* +* mvSataSetFBSMode - set FIS based switching mode. +* +* DESCRIPTION: +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* enableFBS - if true then enable FBS mode. +* useQueueLen128 - if true then enable the 128 EDMA queue length. +* +* RETURN: +* MV_FALSE if +* 1. the FBS feature set to be enable for an adapter that doesn't support this +* feature, or: +* 2. the function called while EDMA is enabled. +* 3. useQueueLen128 is true and enableFBS is false. +* +* COMMENTS: +* This function only sets the sw configuration, the harware is configured +* accordingly by mvSataConfigEdmaMode() +*******************************************************************************/ +MV_BOOLEAN mvSataSetFBSMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_BOOLEAN enableFBS, MV_BOOLEAN useQueueLen128) +{ + MV_SATA_CHANNEL *pSataChannel; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataSetFBSMode" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataSetFBSMode" + " Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + mvOsSemTake(&pSataChannel->semaphore); + + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: mvSataSetFBSMode failed, EDMA is enabled\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + if (enableFBS == MV_FALSE) + { + pSataChannel->FBSEnabled = MV_FALSE; + pSataChannel->use128Entries = MV_FALSE; + mvOsSemRelease(&pSataChannel->semaphore); + if (useQueueLen128 == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: mvSataSetFBSMode failed, 128 entries queue len is set" + "while FBS mode is disabled\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + return MV_TRUE; + } + + if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_IIE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," %d %d: mvSataSetFBSMode failed," + " Feature not supported by the adapter\n", + pAdapter->adapterId, channelIndex); + pSataChannel->FBSEnabled = MV_FALSE; + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + pSataChannel->FBSEnabled = MV_TRUE; + pSataChannel->use128Entries = useQueueLen128; + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataConfigEdmaMode - set EDMA operating mode. +* +* DESCRIPTION: +* Set the EDMA operating mode - MV_EDMA_MODE_NOT_QUEUED, +* MV_EDMA_MODE_QUEUED or MV_EDMA_MODE_NATIVE_QUEUING. +* When set toe MV_EDMA_MODE_QUEUED or MV_EDMA_MODE_NATIVE_QUEUING then +* the maxQueueDepth should be valud. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* eDmaMode - the selected mode +* maxQueueDepth - the maximum depth of the queue +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* +* COMMENTS: +* None. +* +*******************************************************************************/ +MV_BOOLEAN mvSataConfigEdmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_EDMA_MODE eDmaMode, MV_U8 maxQueueDepth) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 eDmaRegsOffset; + MV_U32 val; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataConfigEdmaMode" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataConfigEdmaMode" + " Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + ioBaseAddr = pAdapter->adapterIoBaseAddress; + mvOsSemTake(&pSataChannel->semaphore); + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," %d %d: mvSataConfigEdmaMode failed," + " EDMA is enabled\n", pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + + val = MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_CONFIG_REG_OFFSET); + if (eDmaMode == MV_EDMA_MODE_NATIVE_QUEUING) + { + if ((maxQueueDepth > MV_EDMA_QUEUE_LENGTH) || (maxQueueDepth == 0)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR," %d %d: mvSataConfigEdmaMode " + "failed, Bad queue depth(%d)\n", pAdapter->adapterId, + channelIndex, maxQueueDepth); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Trying to configure " + "EDMA to NCQ on a non NCQ enabled EDMA\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + val &= ~MV_EDMA_CONFIG_Q_DEPTH_MASK; /* clear queue depth */ + /* set the NCQ enable mode bit, and the queue depth bits*/ + val |= MV_EDMA_CONFIG_NATIVE_QUEUING_MASK | (maxQueueDepth - 1); + } + if (eDmaMode == MV_EDMA_MODE_QUEUED) + { + if ((maxQueueDepth > MV_EDMA_QUEUE_LENGTH) || (maxQueueDepth == 0)) + { + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + val &= ~MV_EDMA_CONFIG_Q_DEPTH_MASK; /* clear queue depth */ + val &= ~MV_EDMA_CONFIG_NATIVE_QUEUING_MASK; /* clear NCQ mode*/ + /* set the queue enable mode bit, and the queue depth bits*/ + val |= MV_EDMA_CONFIG_EQUEUE_ENABLED_MASK | (maxQueueDepth - 1); + } + + if (eDmaMode == MV_EDMA_MODE_NOT_QUEUED) + { + val &= ~MV_EDMA_CONFIG_Q_DEPTH_MASK; /* clear queue depth */ + val &= ~MV_EDMA_CONFIG_NATIVE_QUEUING_MASK; /* clear NCQ mode*/ + val &= ~MV_EDMA_CONFIG_EQUEUE_ENABLED_MASK; + } + pSataChannel->queuedDMA = eDmaMode; + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + val |= MV_EDMA_CONFIG_BURST_SIZE_MASK; + } + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + && (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) + + { + val |= (MV_EDMA_CONFIG_BURST_SIZE_EXT_MASK | MV_BIT13); + } + + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { + /* disable RX PM port mask, required for PM*/ + val |= MV_BIT23; + + if (pSataChannel->FBSEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + " %d %d: Enable FBS feature\n", + pAdapter->adapterId, channelIndex); + val |= MV_BIT16; + /* Set bit 16 at FISDMAActiveSyncResp */ + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_EDMA_FIS_CONFIGURATION_REG_OFFSET, MV_BIT16); + /* Set bit 8 at SingleSync */ + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + 0x30C, MV_BIT8); + } + else + { + val &= ~MV_BIT16; + } + + if (pSataChannel->use128Entries == MV_TRUE) + { + val |= MV_BIT19; + pSataChannel->EDMAQueuePtrMask = MV_EDMA_GEN2E_QUEUE_MASK; + pSataChannel->EDMARequestInpMask = MV_EDMA_GEN2E_REQUEST_Q_INP_MASK; + } + else + { + val &= ~MV_BIT19; + pSataChannel->EDMAQueuePtrMask = MV_EDMA_QUEUE_MASK; + pSataChannel->EDMARequestInpMask = MV_EDMA_REQUEST_Q_INP_MASK; + } + if(pAdapter->hostInterface != MV_HOST_IF_INTEGRATED) + { + /*enable cutthrough*/ + val |= MV_BIT17; +#ifdef MV_SUPPORT_ATAPI + /*enable early completion*/ + val |= MV_BIT18; +#endif + } + /*enable host queue cache*/ + val |= MV_BIT22; + + if (pAdapter->hostInterface == MV_HOST_IF_PCI) + { + MV_U32 pciMode = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_MODE_REG_OFFSET); + + if (getRegField(pciMode, MV_PCI_MODE_OFFSET, 2) == 0) /* PCI*/ + { + if (MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_PCI_REGS_OFFSET + + MV_PCI_COMMAND_REG_OFFSET) & MV_BIT7) + { + /*in this case disable cut through*/ + val &= ~MV_BIT17; + } + } + } + } + /* by defualt, the tags data srutcure initialized in mvSataConfigureChannel*/ + /* for 32 host commands, so we call it again since use128Entries could be */ + /* changed */ + initChannelTags(pSataChannel); + MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset + MV_EDMA_CONFIG_REG_OFFSET, + val); + setupEdmaDeviceErrorHandlingConfiguration(pSataChannel); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG," %d %d: Edma Configuration Reg Value: 0x%08x\n", + pAdapter->adapterId, channelIndex, + MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_CONFIG_REG_OFFSET)); + + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataEnableChannelDma - enable EDMA engine +* +* DESCRIPTION: +* enable the EDMA engine for the given channel +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvSataEnableChannelDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataEnableChannelDma" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataEnableChannelD" + "ma Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex ); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataEnableChannelDma " + "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } +#ifdef MV_SATA_C2C_COMM + /* C2C */ + if (pSataChannel->C2CmodeEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataEnableChannelDma " + "failed, C2C mode is enabled\n", pAdapter->adapterId, + channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } +#endif + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataEnableChannelDma\n", + pAdapter->adapterId, channelIndex); + pSataChannel->queueCommandsEnabled = MV_TRUE; + activateEdma(pAdapter,channelIndex); + + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataDisableChannelDma - disable EDMA engine +* +* DESCRIPTION: +* disable the EDMA engine for the given channel +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvSataDisableChannelDma(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_BUS_ADDR_T ioBaseAddr; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataDisableChannelDma" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + ioBaseAddr = pAdapter->adapterIoBaseAddress; + if (pAdapter->sataChannel[channelIndex] == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataDisableChannel" + "Dma Failed, channel data structure is not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataDisableChannel\n", + pAdapter->adapterId, channelIndex); + /* if this function called while commands still not finished, then it's */ + /* probably timeout*/ + if (pAdapter->sataChannel[channelIndex]->outstandingCommands) + { + _dumpSataRegs(pAdapter, channelIndex); + _dumpEDMARegs(pAdapter, channelIndex); + _dumpChannelQueues(pAdapter, channelIndex); + } + + mvOsSemTake(&pAdapter->sataChannel[channelIndex]->semaphore); + pAdapter->sataChannel[channelIndex]->queueCommandsEnabled = MV_FALSE; + deactivateEdma(pAdapter,channelIndex); + mvOsSemRelease(&pAdapter->sataChannel[channelIndex]->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataFlushDmaQueue - flush the outstanding UDMA commands +* +* DESCRIPTION: +* flush posted UDMA ATA commands on a certain MV88SX50XX SATA channel. if +* the flush type is MV_FLUSH_TYPE_CALLBACK then all call back functions of +* the UDMA commands are called with a flush indication. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* flushType - indicates wheather to call the callBack function or not. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvSataFlushDmaQueue(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_FLUSH_TYPE flushType) +{ + MV_SATA_CHANNEL *pSataChannel; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataFlushDmaQueue" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataFlushDmaQueue " + "Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataFlushDmaQueue " + "Failed, EDMA not disabled\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + flushDmaQueue(pSataChannel, flushType, MV_COMPLETION_TYPE_ABORT, 0); + resetEdmaChannel(pSataChannel); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataNumOfDmaCommands - get the number of the outstanding commmands for the +* given channel +* +* DESCRIPTION: +* return the number of posted ATA commands on an EDMA engine for a +* specific SATA channel. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* +* RETURN: +* num of queue commands. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_U8 mvSataNumOfDmaCommands(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_U8 result; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataNumOfDmaCommands" + " Failed, Bad adapter data structure pointer\n"); + return 0xFF; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataNumOfDmaComman" + "ds Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return 0xFF; + } + mvOsSemTake(&pSataChannel->semaphore); + result = pSataChannel->outstandingCommands; + mvOsSemRelease(&pSataChannel->semaphore); + + return result; +} +/******************************************************************************* +* mvSataGetNumOfPortQueuedCommands - get the number of the outstanding commmands for +* the given port +* +* DESCRIPTION: +* return the number of posted ATA commands on an EDMA engine for a +* specific SATA port. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* PMPort - port number +* pCommandsPerChannel - if not null, gets the total number of outstanding +* command for the given channel +* +* RETURN: +* num of queue commands, 0xFF if error detected. +* COMMENTS: +* +* +*******************************************************************************/ +MV_U8 mvSataGetNumOfPortQueuedCommands(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_U8 *pCommandsPerChannel) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_U8 result; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataGetNumOfPortQueuedCommands" + " Failed, Bad adapter data structure pointer\n"); + return 0xFF; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: mvSataGetNumOfPortQueuedCommands" + "ds Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex, PMPort); + return 0xFF; + } + if (PMPort > MV_SATA_PM_MAX_PORTS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d %d: mvSataGetNumOfPortQueuedCommands" + "ds Failed, non valid port\n", + pAdapter->adapterId, channelIndex, PMPort); + return 0xFF; + } + mvOsSemTake(&pSataChannel->semaphore); + result = pSataChannel->portQueuedCommands[PMPort]; + if (pCommandsPerChannel) + { + *pCommandsPerChannel = pSataChannel->outstandingCommands; + } + mvOsSemRelease(&pSataChannel->semaphore); + + return result; +} + +/******************************************************************************* +* mvSataSetIntCoalParams - update the interrupt Coalescing registers +* +* DESCRIPTION: Sets the interrupt coalescing for a specific SATA unit +* (each SATA unit contains quad SATA channels). +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* sataUnit - which SATA unit to be changed (0xff for all SATA ports) +* intCoalThre - the value to be written to the Coalescing threshold register +* intTimeThre - the value to be written to the Time threshold register +* +* OUTPUT: +* None. +* RETURN: +* MV_TRUE +* COMMENTS: +* None. +* +*******************************************************************************/ +MV_BOOLEAN mvSataSetIntCoalParams (MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, + MV_U32 intCoalThre, MV_U32 intTimeThre) +{ + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataSetIntCoalParams" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + + if ((sataUnit != 0) && (sataUnit != 1) && (sataUnit != 0xff)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d : %d Bad" + " unit number\n", pAdapter->adapterId, sataUnit); + return MV_FALSE; + } + + mvOsSemTake(&pAdapter->semaphore); + if (sataUnit == 0xff) + { + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATA_II_ALL_PORTS_INT_COAL_CMND_THR_REG_OFFSET, + intCoalThre); + + pAdapter->intCoalThre[0] = intCoalThre; + pAdapter->intCoalThre[1] = intCoalThre; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATA_II_ALL_PORTS_INT_COAL_TIME_THR_REG_OFFSET, + intTimeThre); + pAdapter->intTimeThre[0] = intTimeThre; + pAdapter->intTimeThre[1] = intTimeThre; + pAdapter->mainMask |= MV_BIT21; + pAdapter->mainMask &= ~(MV_BIT17 | MV_BIT8); + } + else + { + MV_U8 count; + for (count = 0 ; count < pAdapter->numberOfUnits ; count ++) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(count) + + MV_SATAHC_INT_COAL_THRE_REG_OFFSET, + intCoalThre); + + pAdapter->intCoalThre[count] = intCoalThre; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(count) + + MV_SATAHC_INT_TIME_THRE_REG_OFFSET, + intTimeThre); + pAdapter->intTimeThre[count] = intTimeThre; + } + } + } + else + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INT_COAL_THRE_REG_OFFSET, + intCoalThre); + + pAdapter->intCoalThre[sataUnit] = intCoalThre; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INT_TIME_THRE_REG_OFFSET, + intTimeThre); + pAdapter->intTimeThre[sataUnit] = intTimeThre; + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + pAdapter->mainMask |= (MV_BIT17 | MV_BIT8); + pAdapter->mainMask &= ~MV_BIT21; + } + } + if (pAdapter->interruptsAreMasked == MV_FALSE) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset); + + } + mvOsSemRelease(&pAdapter->semaphore); + + return MV_TRUE; +} + +/******************************************************************************* +* mvSataSetChannelPhyParams - update the channel's Sata Phy params +* +* DESCRIPTION: This functoin changes the Sata Phy params such as the AMP and +* PRE by updating the PHY Mode register. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex- index of the Edma channel number. +* signalAmps - three bits value to be written to the Phy Mode register at +* bits[7:5] +* pre - two bits value to be written to the Phy Mode register at +* bits[12:11] +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE on success, MV_FASLE otherwisw +* +* +*******************************************************************************/ +MV_BOOLEAN mvSataSetChannelPhyParams(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 signalAmps, MV_U8 pre) +{ + MV_U32 regAddr; + MV_U32 val; + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U8 unit = (channelIndex & MV_BIT2) >> 2; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataSetChannelPhyParam" + "s Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + + if (pAdapter->chipIs62X1Z0 == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "%d : mvSataSetChannelPhyPara\ +m" + "s Failed, This function not supported for this adapter\n", + pAdapter->adapterId); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + if ((signalAmps & 0xf8) || (pre & 0xfc)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "mvSataSetChannelPhyParams Failed. Bad params\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + regAddr = MV_SATAHC_REGS_BASE_OFFSET(unit) + + MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port); + + val = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, regAddr); + + val &= ~MV_SATA_I_PHY_MODE_AMP_MASK; + val |= (signalAmps << MV_SATA_I_PHY_MODE_AMP_OFFSET) & + MV_SATA_I_PHY_MODE_AMP_MASK; + + val &= ~MV_SATA_I_PHY_MODE_PRE_MASK; + val |= (pre << MV_SATA_I_PHY_MODE_PRE_OFFSET) & + MV_SATA_I_PHY_MODE_PRE_MASK; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, regAddr, val); + pAdapter->pre[channelIndex] = pre; + pAdapter->signalAmps[channelIndex] = signalAmps; + } + + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + if ((signalAmps & 0xf8) || (pre & 0xf8)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "mvSataSetChannelPhyParams Failed. Bad params\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + + pAdapter->pre[channelIndex] = pre; + pAdapter->signalAmps[channelIndex] = signalAmps; + regAddr = getEdmaRegOffset(channelIndex) + + MV_SATA_II_PHY_MODE_2_REG_OFFSET; + val = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, regAddr); + + val &= ~MV_SATA_II_PHY_MODE_2_AMP_MASK; + val |= (signalAmps << MV_SATA_II_PHY_MODE_2_AMP_OFFSET) & + MV_SATA_II_PHY_MODE_2_AMP_MASK; + val &= ~MV_SATA_II_PHY_MODE_2_PRE_MASK; + val |= (pre << MV_SATA_II_PHY_MODE_2_PRE_OFFSET) & + MV_SATA_II_PHY_MODE_2_PRE_MASK; + val &= ~MV_BIT16; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, regAddr, val); + } + + return MV_TRUE; +} +/******************************************************************************* +* mvSataChannelPhyShutdown - +* +* DESCRIPTION: Shutdown the sata Phy of the given channel. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise +* +* COMMENTS: +* After shutdown no connect / disconnect indication will be available. +* +*******************************************************************************/ + +MV_BOOLEAN mvSataChannelPhyShutdown(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_U32 regVal; + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataChannelPhyShutdown" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* Fix for 88SX60x1 FEr SATA#8*/ + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + regVal |= MV_BIT9; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, + regVal); + return MV_TRUE; + } + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET); + regVal |= MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port); + + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, regVal); + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET); + return MV_TRUE; +} +/******************************************************************************* +* mvSataChannelPhyPowerOn - +* +* DESCRIPTION: power on the sata Phy of the given channel. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise +* +* COMMENTS: +* None. +* +*******************************************************************************/ + +MV_BOOLEAN mvSataChannelPhyPowerOn(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_U32 regVal; + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataChannelPhyPowerOn" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* Fix for 88SX60x1 FEr SATA#8*/ + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + + regVal &= ~(MV_BIT9); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, + regVal); + _channelHardReset(pAdapter, channelIndex); + return MV_TRUE; + } + _fixPhyParams(pAdapter, channelIndex); + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " : %d %d %d mvSataChannelPhyPowerOn" + " reg[%x] = 0x%x -> 0x%x\n", pAdapter->adapterId, sataUnit, port, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, regVal, + regVal & ~(MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port))); + regVal &= ~(MV_SATA_I_TEST_CONTROL_PHY_SHUTDOWN_MASK(port)); + + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET, regVal); + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_BRIDGES_TEST_CONTROL_REG_OFFSET);{ + MV_U32 temp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port)); + temp &= ~0xf; + temp |= MV_BIT0; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port), temp); + } + _fixPhyParams(pAdapter, channelIndex); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataChannelFarLoopbackDiagnostic - do far end loopback +* +* DESCRIPTION: operate the far-end LB mode on the bridge +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - index of the required channel +* +* OUTPUT: +* None. +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise +* COMMENTS: +* None. +*******************************************************************************/ + +MV_BOOLEAN mvSataChannelFarLoopbackDiagnostic(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U32 regVal = 0, temp; + MV_U32 tryCount, pollCount; + MV_BOOLEAN result = MV_TRUE; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataChannelFarLoopback" + "Diagnostic Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /* TODO - Add support for far end loopback */ + return MV_TRUE; + } + + for (tryCount = 0; tryCount < 5; tryCount++) + { + + /* Set Far-end loopback */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R04_STATUS_BRIDGE_PORT_OFFSET(port), + 0x00100000); + /* BIST pattern */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R05_STATUS_BRIDGE_PORT_OFFSET(port), + 0xb5b5b5b5); + /* BIST pattern */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R06_STATUS_BRIDGE_PORT_OFFSET(port), + 0xb5b5b5b5); + /* enable BIST */ + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R0F_STATUS_BRIDGE_PORT_OFFSET(port), + 0x00200000); + + mvMicroSecondsDelay(pAdapter, MV_FAR_END_LOOPBACK_TEST_WAIT_TIME); + + /* poll bit 20 of register 0F(bist finish) for 50 times*/ + for (pollCount = 0; pollCount < 50; pollCount++) + { + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R0F_STATUS_BRIDGE_PORT_OFFSET(port)); + + if (regVal & MV_BIT20) + { + break; + } + } + + if (regVal & MV_BIT20) + { + break; + }/*if bit 20 still 0, then try the bist sequence again for 5 times*/ + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Warning: FarEnd LoopBack " + "- bit 20 still not set try again, tryCount %d\n",pAdapter->adapterId, + channelIndex, tryCount); + temp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port)); + temp &= 0xff0; + temp |= MV_BIT0; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port), temp); + + if (waitForBusyAfterHReset(pAdapter, channelIndex) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard Rese" + "t storage drive is not ready\n",pAdapter->adapterId, + channelIndex); + + result = MV_FALSE; + } + _fixPhyParams(pAdapter, channelIndex); + + + + + + + + } + } + if (tryCount == 5) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: FarEnd LoopBack Failed" + "- the test doesn't finish\n",pAdapter->adapterId, + channelIndex); + result = MV_FALSE; + } + else + { + if (((regVal & MV_BIT20) == 0) && (regVal & MV_BIT19)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: FarEnd LoopBack" + " finished with error, 0F regVal= %x\n",pAdapter->adapterId, + channelIndex, regVal); + result = MV_FALSE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: FarEnd LoopBack finished " + "successfuly, 0F regVal= %x\n",pAdapter->adapterId, + channelIndex, regVal); + } + } + /* disable BIST and start phy communication */ + temp = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port)); + temp &= 0xff0; + temp |= MV_BIT0; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATA_I_HC_R02_STATUS_BRIDGE_PORT_OFFSET(port), temp); + + if (waitForBusyAfterHReset(pAdapter, channelIndex) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard Rese" + "t storage drive is not ready\n",pAdapter->adapterId, + channelIndex); + + result = MV_FALSE; + } + _fixPhyParams(pAdapter, channelIndex); + + return result; +} + +/******************************************************************************* +* mvSataQueueCommand - Execute ATA command (PIO or UDMA) +* +* DESCRIPTION: +* adds ATA PIO or UDMA request to a MV88SX50XX specific sata channel +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* pCommandInfo - Pointer to the PIO or UDMA command +* +* RETURN: +* MV_DMA_QUEUE_RESULT_OK - Command queuing is successfull +* MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED - when trying to add command + while command queuing is disabled +* MV_QUEUE_COMMAND_RESULT_FULL - Command queue is full +* MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS - when the connected device doesn't +* support 48 bit addressing but the new command need's to use 48bit +* addressing. +* MV_QUEUE_RESULT_BAD_PARAMS - When bad parameters are received +* +* COMMENTS: +* None. +* +*******************************************************************************/ +MV_QUEUE_COMMAND_RESULT mvSataQueueCommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_QUEUE_COMMAND_INFO *pCommandInfo) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_QUEUED_COMMAND_ENTRY *pCommandEntry; + MV_U32 eDmaRegsOffset; + MV_U8 hostTag; + MV_U8 deviceTag; + +#ifdef MV_SATA_IO_GRANULARITY + MV_U8 nextTransId; +#endif + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataQueueCommand" + " Failed, Bad adapter data structure pointer\n"); + return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS; + } + + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataQueueCommand" + " Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS; + } + mvOsSemTake(&pSataChannel->semaphore); +#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION + if ((pAdapter->sataAdapterGeneration < MV_SATA_GEN_IIE) && + (MV_QUEUED_COMMAND_TYPE_UDMA == pCommandInfo->type) && + (pCommandInfo->commandParams.udmaCommand.singleDataRegion == MV_TRUE)) + { + mvOsSemRelease(&pSataChannel->semaphore); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: " + "mvSataQueueCommand single Data region not supported\n", + pAdapter->adapterId, channelIndex); + return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS; + } +#endif + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + if (pSataChannel->queueCommandsEnabled == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: queued commands mode" + " is disabled\n", pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED; + } + + if (getTag(pSataChannel, pCommandInfo->PMPort, &hostTag, &deviceTag) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: queue is full\n", + pAdapter->adapterId, channelIndex ); + + mvOsSemRelease(&pSataChannel->semaphore); + return MV_QUEUE_COMMAND_RESULT_FULL; + } +#ifdef MV_SATA_IO_GRANULARITY + if ((MV_QUEUED_COMMAND_TYPE_UDMA == pCommandInfo->type) && + (MV_TRUE == + pCommandInfo->commandParams.udmaCommand.ioGranularityEnabled)) + { + + if (MV_FALSE == pAdapter->iogEnabled) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: IO granularity is " + "disabled for the adapter\n", + pAdapter->adapterId, channelIndex ); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_QUEUE_COMMAND_RESULT_BAD_PARAMS; + } + else + { + if (pAdapter->iogFreeIdsNum <= 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: IO granularity " + "queue is full\n", + pAdapter->adapterId); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_QUEUE_COMMAND_RESULT_FULL; + } + } + } +#endif + pCommandEntry = &(pSataChannel->commandsQueue[hostTag]); + pCommandEntry->hostTag = hostTag; + pCommandEntry->deviceTag = deviceTag; + pCommandEntry->isCommandInEdma = MV_FALSE; + pCommandEntry->commandAborted = MV_FALSE; + if (pCommandInfo->type == MV_QUEUED_COMMAND_TYPE_UDMA) + { + MV_UDMA_COMMAND_PARAMS *pUdmaCommand = &pCommandInfo->commandParams.udmaCommand; + if (pSataChannel->queuedDMA == MV_EDMA_MODE_NATIVE_QUEUING) + { + pUdmaCommand->isEXT = MV_TRUE; + } +#ifdef MV_SATA_IO_GRANULARITY + pUdmaCommand->iogCurrentTransId = MV_IOG_INVALID_COMMAND_ID; + if ((MV_TRUE == pAdapter->iogEnabled) && + (MV_TRUE == pUdmaCommand->ioGranularityEnabled)) + { + if (pUdmaCommand->iogCommandType == MV_IOG_COMMAND_TYPE_FIRST) + { + mvOsSemTake(&pAdapter->iogSemaphore); + nextTransId = + pAdapter->iogFreeIdsStack[--(pAdapter->iogFreeIdsNum)]; + setIoGranularityCount(pAdapter, + nextTransId, + pUdmaCommand->ioGranularityCommandParam.transCount); + mvOsSemRelease(&pAdapter->iogSemaphore); + } + else + { + nextTransId = + pUdmaCommand->ioGranularityCommandParam.transId; + } + pUdmaCommand->iogCurrentTransId = nextTransId; + } +#endif + if ((pSataChannel->noneUdmaOutstandingCommands == 0) && +#ifdef MV_SUPPORT_ATAPI + (pSataChannel->packetOutstandingCommands == 0) && +#endif + (pSataChannel->ErrorHandlingInfo.state == MV_ERROR_HANDLING_STATE_IDLE)) + { + if (pSataChannel->EdmaActive == MV_FALSE) + { + disableSaDevInterrupts(pAdapter,channelIndex); + activateEdma(pAdapter,channelIndex); + } + addCommand(pSataChannel, pCommandEntry, pCommandInfo); + EdmaReqQueueInsert(pSataChannel, pCommandEntry, + &pCommandInfo->commandParams.udmaCommand); + } + else + { + addCommand(pSataChannel, pCommandEntry, pCommandInfo); + } + } + else + { + addCommand(pSataChannel, pCommandEntry, pCommandInfo); + if (pSataChannel->outstandingCommands == 1) + { + if (pSataChannel->EdmaActive == MV_TRUE) + { + deactivateEdma(pAdapter,channelIndex); + } + if (pSataChannel->PMSupported == MV_TRUE) + { + _setActivePMPort(pSataChannel, pCommandInfo->PMPort); + } + if (sendNoneUdmaCommand(pSataChannel, pCommandEntry) == MV_FALSE) + { + removeCommand(pSataChannel,pCommandEntry); + _doSoftReset(pSataChannel); + mvOsSemRelease(&pSataChannel->semaphore); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Failed to " + "Issue PIO command\n", pAdapter->adapterId, + channelIndex); + return MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED; + } + } + } + + mvOsSemRelease(&pSataChannel->semaphore); + return MV_QUEUE_COMMAND_RESULT_OK; + + + + + + + +} +/******************************************************************************* +* mvSataSetInterruptsScheme - Modify interrupt scheme +* +* DESCRIPTION: +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* interruptScheme = A parameter containing the rquired interrupt scheme +* +* RETURN: +* MV_TRUE on success, otherwise MV_FALSE. +* COMMENTS: This function doesn't modify the HW main mask register +* +*******************************************************************************/ +MV_BOOLEAN mvSataSetInterruptsScheme(MV_SATA_ADAPTER *pAdapter, + MV_SATA_INTERRUPT_SCHEME interruptScheme) +{ + mvOsSemTake(&pAdapter->semaphore); + switch (interruptScheme) + { + case MV_SATA_INTERRUPT_HANDLING_IN_ISR: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d : Interrupts" + " scheme set to Handling in ISR\n", pAdapter->adapterId); + break; + case MV_SATA_INTERRUPT_HANDLING_IN_TASK: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d : Interrupts" + " scheme set to Handling in TASK\n", pAdapter->adapterId); + break; + case MV_SATA_INTERRUPTS_DISABLED: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d : Interrupts" + " scheme set to interrupts Disabled\n", pAdapter->adapterId); + break; + default: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d : in mvSataSet" + "InterruptsScheme: Invalid Interrup scheme (%d)\n", + pAdapter->adapterId, interruptScheme); + mvOsSemRelease(&pAdapter->semaphore); + return MV_FALSE; + } + pAdapter->interruptsScheme = interruptScheme; + mvOsSemRelease(&pAdapter->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataCheckPendingInterrupt - Check and mask interrupts +* +* DESCRIPTION: +* Check if an interrupt is pending, If there is a pending interrupt then +* this function masks the adapter's interrupts and returns MV_TRUE +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* +* RETURN: +* MV_TRUE if the interrupt issued by mv adapter, otherwise MV_FALSE. +* COMMENTS: +* this function must be used only when interrupt scheme is set to +* MV_SATA_INTERRUPT_IN_TASK +* +*******************************************************************************/ +MV_BOOLEAN mvSataCheckPendingInterrupt(MV_SATA_ADAPTER *pAdapter) +{ + MV_U32 mainMask; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + + /*mvOsSemTake(&pAdapter->interruptsMaskSem);*/ + mainMask = pAdapter->mainMask; + /*mvOsSemRelease(&pAdapter->interruptsMaskSem);*/ + /* if the interrupt it ours*/ + if (MV_REG_READ_DWORD(ioBaseAddr,pAdapter->mainCauseOffset) & + mainMask) + { + /*clear mainMask, the ISR enables the interrupt once served*/ + MV_REG_WRITE_DWORD(ioBaseAddr, pAdapter->mainMaskOffset, 0); + return MV_TRUE; + } + /*bogus interrupt*/ + return MV_FALSE; +} +/******************************************************************************* +* mvSataInterruptServiceRoutine - Interrupt service routine +* +* DESCRIPTION: +* this function is an interrupt service routine that is called upon +* reception of an interrupt from a MV88SX50XX adapter. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* +* RETURN: +* MV_TRUE if the interrupt issued by mv adapter, otherwise MV_FALSE. +* COMMENTS: +* this function handles all the events that generate interrupts incuding +* calling the upper layer call back functions. +* +*******************************************************************************/ +MV_BOOLEAN mvSataInterruptServiceRoutine(MV_SATA_ADAPTER *pAdapter) +{ + MV_U32 mainCause; + MV_U32 mainMask; + MV_U32 unitCause = 0; + MV_U32 responseDone; + MV_U32 edmaError; + MV_U32 deviceInterrupt; + MV_U8 sataUnit; + MV_U8 port; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + mvOsSemTake(&pAdapter->semaphore); + mainCause = MV_REG_READ_DWORD(ioBaseAddr, + pAdapter->mainCauseOffset); + + /* Check if the interrupt is ours */ + mvOsSemTake(&pAdapter->interruptsMaskSem); + mainMask = pAdapter->mainMask; + mvOsSemRelease(&pAdapter->interruptsMaskSem); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_INTERRUPTS, + " %d : Interrupt. Cause = 0x%08x, mask 0x%08x\n", + pAdapter->adapterId, mainCause, mainMask); + + /* + * Check if interrupt is our or interrupts are masked. + * in interrupts disaled scheme, the main mask register is cleared but the + * mainMask variable will hold the bits where interrupts expected, this why + * the sheme is not checked + */ + if ((0 == (mainCause & mainMask)) || + ((pAdapter->interruptsAreMasked == MV_TRUE) && + (pAdapter->interruptsScheme != MV_SATA_INTERRUPTS_DISABLED))) + { + /* when interrupts handled in task, we expect to find interrupts here*/ + if (pAdapter->interruptsScheme == MV_SATA_INTERRUPT_HANDLING_IN_TASK) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," %d : ISR called " + "but no interrutps are found in interrupts handle in task" + "scheme!\n", pAdapter->adapterId); + /*anyway unmask interrupts*/ + mvOsSemTake(&pAdapter->interruptsMaskSem); + if (pAdapter->interruptsAreMasked == MV_FALSE) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + } + mvOsSemRelease(&pAdapter->interruptsMaskSem); + } + mvOsSemRelease(&pAdapter->semaphore); + return MV_FALSE; + } + + if (mainCause & MV_MAIN_INTERRUPT_MASK_REG_PCIERR_BIT) + { + handlePCIErrorInterrupt(pAdapter); + } +#ifdef MV_SATA_IO_GRANULARITY + /*IO Granularity interrupt*/ + if (mainCause & MV_IOG_TRANS_INT_MASK) + { + mvOsSemTake(&pAdapter->iogSemaphore); + iogInterrupt(pAdapter, ioBaseAddr, mainCause); + mvOsSemRelease(&pAdapter->iogSemaphore); + } +#endif + for (sataUnit = 0; sataUnit < pAdapter->numberOfUnits; sataUnit++) + { + if ((pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) && + (pAdapter->hostInterface != MV_HOST_IF_INTEGRATED)) + { + /* Clear the all ports interrupt coalescing cause register */ + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_SATA_II_ALL_PORTS_INT_CAUSE_REG_OFFSET, + 0); + } + + if (mainCause & 0x1ff) + { + MV_U32 unitCauseAddr = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET; + MV_U32 unitRspInPtr; + + /* clear the cause bit of the Coalescing interrupt*/ + MV_REG_WRITE_DWORD(ioBaseAddr, unitCauseAddr, ~MV_BIT4); + unitCause = MV_REG_READ_DWORD(ioBaseAddr, unitCauseAddr); + /* clear the cause register of the current unit */ + MV_REG_WRITE_DWORD(ioBaseAddr, unitCauseAddr, ~unitCause | MV_BIT4); + + unitRspInPtr = MV_REG_READ_DWORD(ioBaseAddr, + MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_RESPONSE_Q_IN_POINTER_OFFSET); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d unit %d : unitCause = 0x%08x," + " unitRspInPtr 0x%08x\n", pAdapter->adapterId, sataUnit, + unitCause, unitRspInPtr); + + for (port = 0; port < pAdapter->portsPerUnit; port++) + { + deviceInterrupt = unitCause & (MV_BIT8 << port); + responseDone = unitCause & (1 << port); + edmaError = (mainCause & MV_BIT0) ; + + if (responseDone || edmaError) + { + handleEdmaInterrupt(pAdapter, sataUnit, port, + (MV_U8)(unitRspInPtr), + responseDone, + edmaError, unitCause); + } + if (deviceInterrupt && + (SaDevInterrutpBit((MV_U8)MV_CHANNEL_INDEX(sataUnit, port)) & mainMask)) + { + handleDeviceInterrupt(pAdapter, sataUnit, port); + } + + + mainCause >>= 2; + unitRspInPtr >>= 8; + } + } + else + { + mainCause >>=8; + } + mainCause >>= 1; /* this is for the coalescing 0-3 bit*/ + } + if (pAdapter->interruptsScheme == MV_SATA_INTERRUPT_HANDLING_IN_TASK) + { + if (pAdapter->interruptsAreMasked == MV_FALSE) + { + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + } + } + mvOsSemRelease(&pAdapter->semaphore); + return MV_TRUE; +} +/******************************************************************************* +* mvSataMaskAdapterInterrupt - mask any interrupts can be generated from a +* MV88SX50XX adapter +* +* DESCRIPTION: +* mask all the interrupts that could occur from the adapter. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* Before masking the interrupts, the value of the interrupt maks register +* will be stored in the adapter data structure. +* +*******************************************************************************/ +MV_BOOLEAN mvSataMaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter) +{ + pAdapter->interruptsAreMasked = MV_TRUE; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, 0); + return MV_TRUE; +} + +/******************************************************************************* +* mvSataUnmaskAdapterInterrupt - unmask interrupts can be generated from a +* MV88SX50XX adapter +* +* DESCRIPTION: +* Restore a previous value in the MV88SX50XX interrupt maks register by +* writing the previously stored value in the interruptMaskRegister field +* in the adapter data structure to the MV88SX50XX adapter main interrupt +* mask register +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvSataUnmaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter) +{ + mvOsSemTake(&pAdapter->interruptsMaskSem); + pAdapter->interruptsAreMasked = MV_FALSE; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + mvOsSemRelease(&pAdapter->interruptsMaskSem); + return MV_TRUE; +} + + +/******************************************************************************* +* mvSataEnableStaggeredSpinUpAll - Enables staggared spin-up of all SATA channels +* +* DESCRIPTION: +* Enables staggared spin-up of all SATA II chnannel. This function is not +* relevant for SATA I. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvSataEnableStaggeredSpinUpAll (MV_SATA_ADAPTER *pAdapter) +{ + MV_U8 channelIndex; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataEnableStaggeredSpinUp Failed, Bad adapter data structure" + " pointer\n"); + return MV_FALSE; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d : Staggered spin-up called for all " + "SATA channels\n",pAdapter->adapterId); + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + + mvOsSemTake(&pAdapter->semaphore); + _establishSataCommAll(pAdapter); + for (channelIndex = 0 ; channelIndex < pAdapter->numberOfChannels ; + channelIndex ++) + { + MV_U32 SStatusReg; + SStatusReg = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET); + + /* + * Fix for 88SX60X1 FEr #10 + */ + + if ((SStatusReg != 0x0) && (SStatusReg != 0x113) && (SStatusReg != 0x123)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: SStatusRegs = %x ; " + "retrying communication...", + pAdapter->adapterId, channelIndex, SStatusReg); + _establishSataComm(pAdapter,channelIndex); + SStatusReg = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: New SStatus is %x\n", + pAdapter->adapterId, channelIndex, SStatusReg); + + } + if ( ((SStatusReg & 0xf) == MV_PHY_DET_STATE_DEVICE_NO_PHY_COM) || + ((SStatusReg & 0xf) == MV_PHY_DET_STATE_PHY_OFFLINE)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "Error - failed to establish SATA link after staggered " + "spin up (S Status = %08x)\n", pAdapter->adapterId, + channelIndex, SStatusReg); + } + pAdapter->staggaredSpinup[channelIndex] = MV_TRUE; + } + mvOsSemRelease(&pAdapter->semaphore); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK | MV_DEBUG, " %d : " + "Finished staggered spin-up\n", pAdapter->adapterId); + + return MV_TRUE; +} + +/******************************************************************************* +* mvSataEnableStaggeredSpinUp - Enables staggared spin-up. +* +* DESCRIPTION: +* Enables staggared spin-up of SATA II chnannel. This function is not +* relevant for SATA I. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvSataEnableStaggeredSpinUp (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataEnableStaggeredSpinUp Failed, Bad adapter data structure" + " pointer\n"); + return MV_FALSE; + } + if (channelIndex >= pAdapter->numberOfChannels) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataEnableStaggeredSpinUp Failed, bad channel index\n"); + return MV_FALSE; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Staggered spin-up called\n", + pAdapter->adapterId, channelIndex); + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + MV_U32 SStatusReg; + + mvOsSemTake(&pAdapter->semaphore); + _establishSataComm(pAdapter, channelIndex); + SStatusReg = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET); + if ( ((SStatusReg & 0xf) == MV_PHY_DET_STATE_DEVICE_NO_PHY_COM) || + ((SStatusReg & 0xf) == MV_PHY_DET_STATE_PHY_OFFLINE)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "Error - failed to establish SATA link after staggered " + "spin up (S Status = %08x)\n", pAdapter->adapterId, + channelIndex, SStatusReg); + } + pAdapter->staggaredSpinup[channelIndex] = MV_TRUE; + mvOsSemRelease(&pAdapter->semaphore); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK | MV_DEBUG, " %d %d: " + "Finished staggered spin-up\n", pAdapter->adapterId, + channelIndex); + + return MV_TRUE; +} + +/******************************************************************************* +* mvSataDisableStaggeredSpinUpAll - Disables staggared spin-up on all channels +* +* DESCRIPTION: +* Disables staggared spin-up of all SATA II chnannel. This function is not +* relevant for SATA I. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvSataDisableStaggeredSpinUpAll (MV_SATA_ADAPTER *pAdapter) +{ + MV_U8 channelIndex; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataDisableStaggeredSpinUp Failed, Bad adapter data structure" + " pointer\n"); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /* OK to use mvSataDisableStaggeredSpinUp since it's fast enough */ + for (channelIndex = 0 ; channelIndex < pAdapter->numberOfChannels ; + channelIndex ++) + { + mvSataDisableStaggeredSpinUp(pAdapter,channelIndex); + } + } + return MV_TRUE; +} + +/******************************************************************************* +* mvSataDisableStaggeredSpinUp - Disables staggared spin-up. +* +* DESCRIPTION: +* Disables staggared spin-up of SATA II chnannel. This function is not +* relevant for SATA I. +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvSataDisableStaggeredSpinUp (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_U32 SControlOffset, regVal; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataDisableStaggeredSpinUp Failed, Bad adapter data structure" + " pointer\n"); + return MV_FALSE; + } + if (channelIndex >= pAdapter->numberOfChannels) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataDisableStaggeredSpinUp Failed, bad channel index\n"); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + mvOsSemTake(&pAdapter->semaphore); + SControlOffset = getEdmaRegOffset( channelIndex) + + MV_SATA_II_S_CONTROL_REG_OFFSET; + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset); + regVal &= ~0xf; + regVal |= MV_PHY_DET_CONTROL_SHUTDOWN; + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset, + regVal); + pAdapter->staggaredSpinup[channelIndex] = MV_FALSE; + mvOsSemRelease(&pAdapter->semaphore); + } + return MV_TRUE; +} + +/******************************************************************************* +* mvSataSetInterfaceSpeed - Sets the interface speed of a specific SATA channel +* +* DESCRIPTION: +* Sets the interface speed of a specific SATA channel (1.5/3 Gbps) +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* +* RETURN: +* MV_SATA_IF_SPEED_1_5 for 1.5 Gbps +* MV_SATA_IF_SPEED_3 for 3 Gbps +* MV_SATA_IF_SPEED_INVALID if no speed is negotiated +* +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataSetInterfaceSpeed (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_SATA_IF_SPEED ifSpeed) +{ + MV_U32 SStatusOffset; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataSetInterfaceSpeed Failed, Bad adapter data structure" + " pointer\n"); + return MV_FALSE; + } + if (channelIndex >= pAdapter->numberOfChannels) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataSetInterfaceSpeed Failed, bad channel index\n"); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + MV_SATA_CHANNEL *pSataChannel; + + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel != NULL) + { + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Error:" + "mvSataSetInterfaceSpeed called while EDMA is active\n", + pAdapter->adapterId,channelIndex); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + mvOsSemRelease(&pSataChannel->semaphore); + } + + SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + + if (ifSpeed == MV_SATA_IF_SPEED_1_5_GBPS) + { + pAdapter->limitInterfaceSpeed[channelIndex] = MV_TRUE; + pAdapter->ifSpeed[channelIndex] = MV_SATA_IF_SPEED_1_5_GBPS; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: Set Sata speed to " + "1.5Gbps\n", pAdapter->adapterId,channelIndex); + } + else if (ifSpeed == MV_SATA_IF_SPEED_3_GBPS) + { + pAdapter->limitInterfaceSpeed[channelIndex] = MV_TRUE; + pAdapter->ifSpeed[channelIndex] = MV_SATA_IF_SPEED_3_GBPS; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: Set Sata speed to " + "3Gbps\n", pAdapter->adapterId,channelIndex); + } + else if (ifSpeed == MV_SATA_IF_SPEED_NO_LIMIT) + { + pAdapter->limitInterfaceSpeed[channelIndex] = MV_FALSE; + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_SATA_LINK, " %d %d: don't limit Sata" + " speed \n", pAdapter->adapterId,channelIndex); + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataSetInterfaceSpeed Failed, bad IF speed\n"); + return MV_FALSE; + } + + mvOsSemTake(&pAdapter->semaphore); + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + MV_U32 regVal; + + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + if ((pAdapter->limitInterfaceSpeed[channelIndex] == MV_TRUE) && + (pAdapter->ifSpeed[channelIndex] == MV_SATA_IF_SPEED_1_5_GBPS)) + { + regVal &= ~MV_BIT7; /* Disable GEn II */ + } + else + { + regVal |= MV_BIT7; /* Enable GEn II */ + + } + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + getEdmaRegOffset (channelIndex) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, + regVal); + } + + _channelHardReset(pAdapter, channelIndex); + /* If interface is already active, then device detection is needed */ + if (pAdapter->staggaredSpinup[channelIndex] == MV_TRUE) + { + _establishSataComm(pAdapter, channelIndex); + } + mvOsSemRelease(&pAdapter->semaphore); + return MV_TRUE; + } + if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) && + ((ifSpeed == MV_SATA_IF_SPEED_NO_LIMIT) || + (ifSpeed == MV_SATA_IF_SPEED_1_5_GBPS))) + { + return MV_TRUE; + } + return MV_FALSE; +} + +/******************************************************************************* +* mvSataGetInterfaceSpeed - Gets the interface speed of a specific SATA channel +* +* DESCRIPTION: +* Gets the interface speed of a specific SATA channel (1.5/3 Gbps) +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* +* RETURN: +* MV_SATA_IF_SPEED_1_5 for 1.5 Gbps +* MV_SATA_IF_SPEED_3 for 3 Gbps +* MV_SATA_IF_SPEED_INVALID if no speed is negotiated +* +* COMMENTS: +* +*******************************************************************************/ +MV_SATA_IF_SPEED mvSataGetInterfaceSpeed (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_U32 SStatusOffset, regVal; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataGetInterfaceSpeed Failed, Bad adapter data structure" + " pointer\n"); + return MV_SATA_IF_SPEED_INVALID; + } + if (channelIndex >= pAdapter->numberOfChannels) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataGetInterfaceSpeed Failed, bad channel index\n"); + return MV_SATA_IF_SPEED_INVALID; + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + if (pAdapter->staggaredSpinup[channelIndex] == MV_TRUE) + { + SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + regVal = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, SStatusOffset); + if (regVal & MV_BIT4) + { + return MV_SATA_IF_SPEED_1_5_GBPS; + } + if (regVal & MV_BIT5) + { + return MV_SATA_IF_SPEED_3_GBPS; + } + } + return MV_SATA_IF_SPEED_INVALID; + } + return MV_SATA_IF_SPEED_1_5_GBPS;/*TBD*/ +} + +/******************************************************************************* +* mvSataSetInterfacePowerState - Sets the sata interface power state of a +* specific SATA channel +* +* DESCRIPTION: +* Sets the interface power state of a specific SATA channel +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* ifPowerState - sata interface power state +* +* RETURN: +* MV_TRUE if the desired power state entered successfully. +* MV_FALSE otherwise +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvSataSetInterfacePowerState (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_SATA_IF_POWER_STATE ifPowerState) +{ + MV_U32 SControlOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_CONTROL_REG_OFFSET; + MV_U32 SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + MV_U32 SControl; + MV_U32 SStatus; + MV_U32 IPM; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataSetInterfacePowerState Failed, Bad adapter data structure" + " pointer\n"); + return MV_FALSE; + } + if (channelIndex >= pAdapter->numberOfChannels) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataSetInterfacePowerState Failed, bad channel index\n"); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "mvSataSetInterfacePowerState Failed, adapter not supported\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + if (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "mvSataSetInterfacePowerState Failed, sata link not established yet\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + switch (ifPowerState) + { + case MV_SATA_IF_POWER_PHY_READY: + SControl = 0x4300; + break; + case MV_SATA_IF_POWER_PARTIAL: + SControl = 0x1300; + break; + case MV_SATA_IF_POWER_SLUMBER: + SControl = 0x2300; + break; + default: + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: " + "mvSataSetInterfacePowerState Failed, unkniwn state (0x%x)\n", + pAdapter->adapterId, channelIndex, ifPowerState); + return MV_FALSE; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: " + "mvSataSetInterfacePowerState: enter state 0x%x (prev 0x%x)\n", + pAdapter->adapterId, channelIndex, ifPowerState, + pAdapter->ifPowerState[channelIndex]); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset, SControl); + MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, SControlOffset); + if (pAdapter->ifPowerState[channelIndex] == MV_SATA_IF_POWER_SLUMBER) + { + mvMicroSecondsDelay(pAdapter, 10000); + } + else + { + mvMicroSecondsDelay(pAdapter, 10); + } + SStatus = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, SStatusOffset); + IPM = getRegField(SStatus, 8, 4); + if (IPM != ifPowerState) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: " + "mvSataSetInterfacePowerState: IPM (0x%x) doesn't match the " + "requested state 0x%x (prev 0x%x)\n", + pAdapter->adapterId, channelIndex, IPM, ifPowerState, + pAdapter->ifPowerState[channelIndex]); + pAdapter->ifPowerState[channelIndex] = MV_SATA_IF_POWER_SLUMBER; + return MV_FALSE; + } + pAdapter->ifPowerState[channelIndex] = ifPowerState; + return MV_TRUE; +} +/******************************************************************************* +* mvSataGetInterfacePowerState - Gets the sata interface power state of a +* specific SATA channel +* +* DESCRIPTION: +* Gets the interface power state of a specific SATA channel from the HW +* registers (SStatus) +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* ifPowerState - sata interface power state +* +* RETURN: +* ifPowerState - sata interface power state +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvSataGetInterfacePowerState (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_SATA_IF_POWER_STATE *ifPowerState) +{ + MV_U32 SStatusOffset = getEdmaRegOffset(channelIndex) + + MV_SATA_II_S_STATUS_REG_OFFSET; + + MV_U32 SStatus; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataGetInterfacePowerState Failed, Bad adapter data structure" + " pointer\n"); + return MV_FALSE; + } + if (channelIndex >= pAdapter->numberOfChannels) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + "mvSataGetInterfacePowerState Failed, bad channel index\n"); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "mvSataGetInterfacePowerState Failed, adapter not supported\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + if (pAdapter->staggaredSpinup[channelIndex] == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: " + "mvSataGetInterfacePowerState Failed, sata link not established yet\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + SStatus = MV_REG_READ_DWORD (pAdapter->adapterIoBaseAddress, SStatusOffset); + *ifPowerState = getRegField(SStatus, 8, 4); + return MV_TRUE; +} +#if defined (MV_SUPPORT_ATAPI) || defined (MV_SATA_C2C_COMM) +static void activateBMDmaMode(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 prdTableHi, + MV_U32 prdTableLow, + MV_UDMA_TYPE dmaType) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + " activateBMDmaMode: BMDMA status(1) 0x%08x\n", + MV_REG_READ_DWORD (ioBaseAddr, + getEdmaRegOffset(pSataChannel->channelNumber) +MV_BMDMA_STATUS_OFFSET) + ); + if(pAdapter->hostInterface == MV_HOST_IF_INTEGRATED) + { + _setRegBits(ioBaseAddr, pSataChannel->eDmaRegsOffset + 0x6C, MV_BIT0); + } + + + MV_REG_WRITE_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_BMDMA_COMMAND_OFFSET, 0); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + " activateBMDmaMode: BMDMA status(2) 0x%08x\n", + MV_REG_READ_DWORD (ioBaseAddr, + getEdmaRegOffset(pSataChannel->channelNumber) +MV_BMDMA_STATUS_OFFSET) + ); + + MV_REG_WRITE_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_BMDMA_PRD_TABLE_LOW_ADDRESS_OFFSET, prdTableLow); + MV_REG_WRITE_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_BMDMA_PRD_TABLE_HIGH_ADDRESS_OFFSET, prdTableHi); + + if (dmaType == MV_UDMA_TYPE_READ) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Activate BM-DMA in write Mode" + " (Read from disk)\n", pAdapter->adapterId, channelIndex); + MV_REG_WRITE_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_BMDMA_COMMAND_OFFSET, MV_BIT3 | MV_BIT0); + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Activate BM-DMA in read Mode" + " (Writes to disk)\n", pAdapter->adapterId, channelIndex); + MV_REG_WRITE_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_BMDMA_COMMAND_OFFSET, MV_BIT0); + } +} +#endif +/*================C2C functions==========================================*/ +#ifdef MV_SATA_C2C_COMM +/******************************************************************************* +* mvSataC2CInit - setup channel-to-channel communication mode on +* specific SATA channel +* +* DESCRIPTION: +* Initializes channel for channel-to-channel communication mode +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific SATA channel +* mvSataC2CMode - Comunication mode for the channel: +* target or initiator +* +* mvSataC2CCallBack - callback function called on channel 2 channel +* communication event +* +* RETURN: +* MV_TRUE on success +* MV_FALSE on error +* +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataC2CInit (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_SATA_C2C_MODE mvSataC2CMode, + C2CCallBack_t mvSataC2CCallBack) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 regVal; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataC2CInit" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataC2CInit Failed" + ", channel data structure not allocated\n", + pAdapter->adapterId, channelIndex ); + return MV_FALSE; + } + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CInit " + "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CInit " + "failed, Feature not supported by this HW\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + + regVal = MV_REG_READ_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* Enable communication mode */ + regVal |= MV_BIT11; + /* Fix for 88SX60xx FEr SATA#8*/ + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + + if (mvSataC2CMode == MV_SATA_C2C_MODE_INITIATOR) + { + regVal |= MV_BIT10; /* Initiator */ + } + else + { + regVal &= ~MV_BIT10; /* Target */ + } + + maskEdmaInterrupts(pAdapter, channelIndex); + + MV_REG_WRITE_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal); + + _channelHardReset(pAdapter, channelIndex); + + pSataChannel->C2CmodeEnabled = MV_TRUE; + pSataChannel->C2CMode = mvSataC2CMode; + pSataChannel->C2CCallback = mvSataC2CCallBack; + + mvSataMaskAdapterInterrupt(pAdapter); + pAdapter->mainMask |= SaDevInterrutpBit(channelIndex); + mvSataUnmaskAdapterInterrupt(pAdapter); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataC2CInit %s mode\n", + pAdapter->adapterId, channelIndex, + (mvSataC2CMode == MV_SATA_C2C_MODE_INITIATOR) ? "Initiator" : + "Target"); + + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; +} + + +/******************************************************************************* +* mvSataC2CStop - Stop channel to channel communication mode +* +* DESCRIPTION: +* Stop channel to channel communication mode on +* specific SATA channel +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific SATA channel +* +* RETURN: +* MV_TRUE on success +* MV_FALSE on error +* +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataC2CStop (MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 regVal; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvSataC2CStop" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvSataC2CStop Failed" + ", channel data structure not allocated\n", + pAdapter->adapterId, channelIndex ); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CStop " + "failed, DMA is enabled\n", pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + + regVal = MV_REG_READ_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + regVal &= ~MV_BIT11; /* Disable communication mode */ + /* Fix for 88SX60xx FEr SATA#8*/ + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + MV_REG_WRITE_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, regVal); + MV_REG_READ_DWORD (ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + mvSataMaskAdapterInterrupt(pAdapter); + pAdapter->mainMask &= ~SaDevInterrutpBit(channelIndex); + mvSataUnmaskAdapterInterrupt(pAdapter); + + _channelHardReset(pAdapter, channelIndex); + pSataChannel->C2CmodeEnabled = MV_FALSE; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: mvSataC2CStop\n", + pAdapter->adapterId, channelIndex); + + mvOsSemRelease(&pSataChannel->semaphore); + return MV_TRUE; +} + + + +/******************************************************************************* +* mvSataC2CSendRegisterDeviceToHostFIS - sends Register device to host FIS +* +* DESCRIPTION: +* Sends Register device to host FIS +* used for channel-to-channel communication mode on +* specific SATA channel +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific SATA channel +* pmPort - port multiplier port +* bInterrupt - determine whether the interrupt is being generated on +* the receiver side +* msg - message containing 10 bytes of user data +* +* RETURN: +* MV_TRUE on success +* MV_FALSE on error +* +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataC2CSendRegisterDeviceToHostFIS( + MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 pmPort, + MV_BOOLEAN bInterrupt, + MV_U8 msg[MV_C2C_MESSAGE_SIZE]) + +{ + + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 buffer[5]; + MV_BOOLEAN res; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d " + "mvSataC2CSendRegisterDeviceToHostFIS failed - " + "Bad adapter data structure pointer.\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d " + "mvSataC2CSendRegisterDeviceToHostFIS failed - " + "channel data structure not allocated.\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + + if (pSataChannel->C2CmodeEnabled == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvSataC2CInitiator" + "mvSataC2CSendRegisterDeviceToHostFIS failed - " + "Bad C2C configuration.\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + + buffer[0] = MV_SATA_REGISTER_HOST_2_DEVICE_FIS; + buffer[0] |= ((MV_U32)(pmPort & 0xF)) << 8; + if (MV_TRUE == bInterrupt) + { + buffer[0] |= 1 << 14; + } + buffer[0] |= ((MV_U32)msg[0]) << 24; + buffer[1] = msg[1] | + ((MV_U32)msg[2]) << 8 | + ((MV_U32)msg[3]) << 16 | + ((MV_U32)msg[4]) << 24; + buffer[2] = msg[5] | + ((MV_U32)msg[6]) << 8 | + ((MV_U32)msg[7]) << 16; + buffer[3] = msg[8] | + ((MV_U32)msg[9]) << 8; + buffer[4] = 0; + res = sendVendorUniqueFIS(pAdapter, + channelIndex, + (MV_U32*)buffer, + 5); + mvOsSemRelease(&pSataChannel->semaphore); + return res; +} + + + +/******************************************************************************* +* mvSataC2CActivateBmDma - activate B-M DMA +* +* DESCRIPTION: +* Activates Bus Master DMA for the specific SATA channel +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* pmPort - port multiplier port +* prdTableHi - upper 32 bits of PRD table address +* prdTableHi - lower 32 bits of PRD table address +* dmaType - DMA type (read o write) from the initiator point + of view +* +* RETURN: +* MV_TRUE on success +* MV_FALSE on error +* +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataC2CActivateBmDma(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 pmPort, + MV_U32 prdTableHi, + MV_U32 prdTableLow, + MV_UDMA_TYPE dmaType) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_BOOLEAN res = MV_TRUE; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d " + "mvSataC2CActivateBmDma failed - " + "Bad adapter data structure pointer.\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d " + "mvSataC2CActivateBmDma failed - " + "channel data structure not allocated\n", + pAdapter->adapterId, channelIndex ); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->C2CmodeEnabled == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d " + "mvSataC2CActivateBmDma failed - " + "bad C2C configuration.\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + if (pSataChannel->C2CMode == MV_SATA_C2C_MODE_TARGET) + { + activateBMDmaMode(pAdapter, channelIndex, + prdTableHi, prdTableLow, + (dmaType == MV_UDMA_TYPE_WRITE) ? + MV_UDMA_TYPE_READ : MV_UDMA_TYPE_WRITE); + if (dmaType == MV_UDMA_TYPE_WRITE) + { + MV_U32 buffer[1] = {MV_SATA_DMA_ACTIVATE_FIS}; + + buffer[0] |= ((MV_U32)(pmPort & 0xF)) << 8; + res = sendVendorUniqueFIS(pAdapter, + channelIndex, + (MV_U32*)buffer, + 1); + } + else + { + MV_U32 val = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->sataChannel[channelIndex]->eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET); + val |= MV_BIT16; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->sataChannel[channelIndex]->eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET, + val); + } + } + else + { + activateBMDmaMode(pAdapter, channelIndex, prdTableHi, prdTableLow, + dmaType); + } + mvOsSemRelease(&pSataChannel->semaphore); + return res; +} + + +/******************************************************************************* +* mvSataC2CResetBmDma - reset B-M DMA +* +* DESCRIPTION: +* Reset Bus Master DMA for the specific SATA channel +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific EDMA channel +* +* RETURN: +* MV_TRUE on success +* MV_FALSE on error +* +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataC2CResetBmDma(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d " + "mvSataC2CResetBmDma failed - " + "Bad adapter data structure pointer.\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel) + { + + mvOsSemTake(&pSataChannel->semaphore); + } + + _resetBmDma(pAdapter, channelIndex); + + if (pSataChannel) + { + mvOsSemRelease(&pSataChannel->semaphore); + } + return MV_TRUE; +} +#endif +void _resetBmDma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + MV_U32 val; + MV_U8 port = channelIndex & (MV_BIT0 | MV_BIT1); + MV_U8 sataUnit = (channelIndex & MV_BIT2) >> 2; + MV_U32 unitCauseAddr = MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET; + + /*Reset bm dma*/ + val = MV_REG_READ_DWORD (ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_BMDMA_COMMAND_OFFSET); + /*The DMA direction must be preserved*/ + val &= ~MV_BIT0; + MV_REG_WRITE_DWORD (ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_BMDMA_COMMAND_OFFSET, val); + + MV_REG_WRITE_DWORD(ioBaseAddr, + getEdmaRegOffset(channelIndex) + + MV_SATA_II_IF_CONTROL_REG_OFFSET, + 0); + /*clear BM Done interrupt*/ + MV_REG_WRITE_DWORD(ioBaseAddr, unitCauseAddr, ~(1 << port)); +} +/******************************************************************************* +* sendVendorUniqueFIS - send vendor unique FIS +* +* DESCRIPTION: +* Performs vendor unique FIS transmission +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific SATA channel +* vendorUniqueBuffer - data buffer to transmit +* numOfDWords - number of double words in the buffer +* +* RETURN: +* MV_TRUE on success +* MV_FALSE on error +* +* COMMENTS: +* +* 1. Verify the Transport Layer is in idle, field TransFsmSts in +* Serial-ATA Interface Status Register is cleared. +* 2. Set Vendor Unique Mode. Write 1 to bit VendorUqMd in register +* Serial-ATA Interface Control Register. +* 3. Insert data into Vendor Unique Register. +* 4. Repeat steps 3 until all data except last Dword in the vendor unique +* FIS is transferred. Note that according to Serial-ATA protocol the +* FIS length is limited to 8 KB. +* 5. Write 1 to bit VendorUqSend in register Serial-ATA Interface Control +* Register. +* 6. Write last Dword in the FIS to Complete FIS transmission. +* 7. Wait for transmission completion. Bit VendorUqDn or bit VendorUqErr +* in Serial-ATA Interface Status Register is set to 1. +* 8. Verify successful transmission of the FIS. Bit VendorUqErr in +* Serial-ATA Interface Status Register is cleared. +* 9. Clear Vendor Unique Mode. Write 0 to bit VendorUqMd in register +* Serial-ATA Interface Control Register. +*******************************************************************************/ +static MV_BOOLEAN sendVendorUniqueFIS(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U32 *vendorUniqueBuffer, + MV_U8 numOfDWords) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + MV_U32 regVal; + MV_U8 i; + MV_BOOLEAN res = MV_FALSE; + + regVal = MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_STATUS_REG_OFFSET); + + if (regVal & MV_SATA_II_IF_STATUS_FSM_STATUS_MASK) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ERROR : sendVendorUniqueFIS" + " Transport Layer is not in Idle status\n", pAdapter->adapterId, + channelIndex); + return MV_FALSE; + } + + /* Set Vendor Unique Mode */ + MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET, MV_BIT8); + + for (i = 1; i < numOfDWords; i++) + { + MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_VENDOR_UQ_REG_OFFSET, + vendorUniqueBuffer[i - 1]); + } + + /* Write 1 to bit VendorUqSend */ + MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET, MV_BIT9|MV_BIT8); + + MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_VENDOR_UQ_REG_OFFSET, + vendorUniqueBuffer[i - 1]); + + + /* polling with timeout*/ + for (i = 0; i < 200; i++) + { + regVal = MV_REG_READ_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_STATUS_REG_OFFSET); + + if (regVal & (MV_SATA_II_IF_STATUS_VUQ_DONE_MASK | + MV_SATA_II_IF_STATUS_VUQ_ERR_MASK)) + { + if (regVal & MV_SATA_II_IF_STATUS_VUQ_DONE_MASK) + { + res = MV_TRUE; + break; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ERROR" + "sendVendorUniqueFIS operation failed. " + "regVal = 0x%08x\n", + pAdapter->adapterId, channelIndex, regVal); + break; + } + } + mvMicroSecondsDelay(pAdapter, 1); + } + /* Clear Vendor Unique Mode */ + MV_REG_WRITE_DWORD(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_CONTROL_REG_OFFSET, 0); + + if (res != MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: ERROR in sendVendorUniqueFI" + "S operation didn't finish. regVal = 0x%08x\n", + pAdapter->adapterId, channelIndex, regVal); + } + return res; +} + +/******************************************************************************* +* mvSata60X1B2CheckDevError - check if device errors occurred +* +* DESCRIPTION: +* This function checks if the drive reported device errors, the 60X1 B2 +* may not issue error interrupt when the device error reported after +* transferring part of the data, this function need to be called every +* period of time(e.g 0.5 seconds). +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - the index of the specific SATA channel +* +* RETURN: +* MV_TRUE if device error is reported +* MV_FALSE otherwise +* +* COMMENTS: +*******************************************************************************/ +MV_BOOLEAN mvSata60X1B2CheckDevError(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 testCtrlReg; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + " : mvSata60X1B2CheckDevError Failed, Bad adapter " + "data structure pointer\n"); + return MV_FALSE; + } + ioBaseAddr = pAdapter->adapterIoBaseAddress; + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + " %d %d: mvSata60X1B2CheckDevError Failed, channel " + "data structure not allocated\n", pAdapter->adapterId, + channelIndex ); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + + if ((pAdapter->chipIs60X1B2 == MV_FALSE) || + (pSataChannel->queueCommandsEnabled == MV_FALSE) || + (pSataChannel->EdmaActive == MV_FALSE) || + (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED)) + { + mvOsSemRelease(&pSataChannel->semaphore); + return MV_FALSE; + } + mvOsSemRelease(&pSataChannel->semaphore); + + testCtrlReg = MV_REG_READ_DWORD (ioBaseAddr, + pSataChannel->eDmaRegsOffset + + MV_SATA_II_IF_TEST_CTRL_REG_OFFSET); + if (testCtrlReg & 0xFFFF0000) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d: PortNumDevErr is set 0x%04x\n", + pAdapter->adapterId, + channelIndex, + (testCtrlReg >> 16) & 0xFFFF); + MV_REG_WRITE_DWORD (ioBaseAddr, + pSataChannel->eDmaRegsOffset + + MV_EDMA_COMMAND_REG_OFFSET, + MV_EDMA_COMMAND_DISABLE_MASK); + handleSelfDisable(pAdapter, channelIndex, MV_BIT7|MV_BIT2); + return MV_TRUE; + } + return MV_FALSE; +} + +MV_BOOLEAN mvSataIfD2HReceived(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 port) +{ + MV_U32 regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_IF_STATUS_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + " %d %d: mvSataIfD2HReceived: if status reg %08x\n", + pAdapter->adapterId, + channelIndex, + regVal); + if(((regVal & 0xFF) == 0x34) && (((regVal >> 8) & 0xF) == port)) + return MV_TRUE; + + return MV_FALSE; +} + +#ifdef MV_SATA_IO_GRANULARITY + +/*Public functions*/ + +/******************************************************************************* +* mvSataEnableIoGranularity - Enable/disable I/O granularity for the specific +* SATA adapter +* +* DESCRIPTION: +* Enable/disable I/O granularity for the specific +* SATA adapter. if IO/granularity is enabled, the function masks +* all channel's and channel coalescing interrupts and enables +* I/O granularity coalescing interupts +* INPUT: +* pAdapter - pointer to the adapter data structure. +* enable - MV_TRUE to enable I/O granularity +* MV_FALSE to disable I/O granularity +* +* RETURN: +* MV_TRUE if succeed +* MV_FALSE otherwise +* +* COMMENTS: +* +*******************************************************************************/ + +MV_BOOLEAN mvSataEnableIoGranularity(MV_SATA_ADAPTER *pAdapter, + MV_BOOLEAN enable) +{ + MV_U32 i; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d: " + "mvSataEnableIoGranularity Failed, Bad adapter data structure" + " pointer\n", pAdapter->adapterId); + return MV_FALSE; + } + if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_II) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d: " + "mvSataEnableIoGranularity Failed, Feature is not supported by HW\n", + pAdapter->adapterId); + return MV_FALSE; + } + if (enable) + { + if (MV_TRUE == pAdapter->iogEnabled) + { + return MV_TRUE; + } + mvOsSemTake(&pAdapter->iogSemaphore); + for (i = 0; i < MV_IOG_QUEUE_SIZE; i++) + { + pAdapter->iogFreeIdsStack[i] = i; + + } + pAdapter->iogFreeIdsNum = MV_IOG_QUEUE_SIZE; + pAdapter->iogEnabled = MV_TRUE; + mvOsSemRelease(&pAdapter->iogSemaphore); + + mvOsSemTake(&pAdapter->interruptsMaskSem); + pAdapter->mainMask &= ~(MV_BIT1 | MV_BIT3 | MV_BIT5 | MV_BIT7 | + MV_BIT10 | MV_BIT12 | MV_BIT14 | MV_BIT16 | + MV_BIT17 | MV_BIT8); + pAdapter->mainMask |= MV_IOG_TRANS_INT_MASK; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + mvOsSemRelease(&pAdapter->interruptsMaskSem); + + } + else + { + if (MV_FALSE == pAdapter->iogEnabled) + { + return MV_TRUE; + } + + mvOsSemTake(&pAdapter->interruptsMaskSem); + pAdapter->mainMask &= ~MV_IOG_TRANS_INT_MASK; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + pAdapter->mainMask); + mvOsSemRelease(&pAdapter->interruptsMaskSem); + + mvOsSemTake(&pAdapter->iogSemaphore); + pAdapter->iogFreeIdsNum = 0; + pAdapter->iogEnabled = MV_FALSE; + mvOsSemRelease(&pAdapter->iogSemaphore); + } + return MV_TRUE; +} +/*Static functions*/ + +/******************************************************************************* +* setIoGranularityCount - Set I/O granularity transaction control register. +* +* DESCRIPTION: +* This function Sets I/O granularity transaction control register for +* specific transaction ID +* +* INPUT: +* pAdapter - Pointer to the MV88SX60XX adapter data structure. +* transId - transaction ID +* counter - I/O granularity counter transaction for current +* transaction Id +* +* RETURN: +* None +* +* COMMENTS: +* This function assumes that the channel semaphore is locked. +* +*******************************************************************************/ + +static void setIoGranularityCount(MV_SATA_ADAPTER *pAdapter, + MV_U8 transId, + MV_U8 counter) +{ + MV_U32 offset = MV_IOG_TRANS_CTRL_REG_OFFSET + transId; + MV_U8 value = (counter & 0x1F); + MV_REG_WRITE_BYTE(pAdapter->adapterIoBaseAddress, offset, value); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_UDMA_COMMAND, + " %d : setIoGranularityCount " + "writing 0x%X to 0x%X, transId = 0x%X\n", + pAdapter->adapterId, value, offset, transId); +} + +/******************************************************************************* +* readIoGranularityCount - Read I/O granularity transaction control register. +* +* DESCRIPTION: +* This function reads I/O granularity transaction control register for +* specific transaction ID +* +* INPUT: +* pAdapter - Pointer to the MV88SX60XX adapter data structure. +* transId - transaction ID +* +* +* RETURN: +* I/O granularity counter for transaction Id +* +* COMMENTS: +* This function assumes that the channel semaphore is locked. +* +*******************************************************************************/ +static MV_U8 readIoGranularityCount(MV_SATA_ADAPTER *pAdapter, + MV_U8 transId) +{ + MV_U32 offset = MV_IOG_TRANS_CTRL_REG_OFFSET + transId; + MV_U8 value = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress, offset); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, " %d : readIoGranularityCount " + "reading 0x%X from 0x%X, transId = 0x%X\n", + pAdapter->adapterId, value, offset, transId); + return value; +} + + +/******************************************************************************* +* checkIogBit - Check bit of I/O granularity cause register. +* +* DESCRIPTION: +* Checks bits in I/O granularity cause register for completion +* +* INPUT: +* pAdapter - Pointer to the MV88SX60XX adapter data structure. +* bitOffset - bit offset in register for current transaction id +* value - register value +* +* RETURN: +* None +* +* COMMENTS: +* Assume that is function is called while IO granularity semaphore is +* locked +*******************************************************************************/ + +static void checkIogBit(MV_SATA_ADAPTER *pAdapter, + MV_U8 bitOffset, + MV_U8 value) +{ + MV_U32 i; + MV_U8 id = 0x40; + for (i = 0; i < 8; i++) + { + if ((value >> i) & 0x1) + { + MV_U8 iogCount; + id = bitOffset + i; + iogCount = readIoGranularityCount(pAdapter, id); + if (iogCount > 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, + " %d: unexpected IO granularity " + "transaction counter = %d > 0\n", + pAdapter->adapterId, iogCount); + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS, + " %d: IO granularity transaction Id 0x%X done.\n", + pAdapter->adapterId, id); + } + pAdapter->iogFreeIdsStack[pAdapter->iogFreeIdsNum++] = id; + } + } +} + +/******************************************************************************* +* checkIogCompletion - Check bit of I/O granularity cause register. +* +* DESCRIPTION: +* Checks I/O granularity completion +* +* INPUT: +* pAdapter - Pointer to the MV88SX60XX adapter data structure. +* iogCause - I/O granularity cause register value +* Offset - 0 if transaction Id is 0-31, 32 if transaction Id 32-63 +* +* RETURN: +* None +* +* COMMENTS: +* +*******************************************************************************/ + +static void checkIogCompletion(MV_SATA_ADAPTER *pAdapter, + MV_U32 iogCause, MV_U8 offset) +{ + MV_U32 id; + MV_U8 byte; + + if (iogCause & 0xFFFF0000) + { + byte = (MV_U8)(iogCause >> 24); + if (byte) + { + checkIogBit(pAdapter, (offset) + 24, byte); + } + byte = (MV_U8)((iogCause >> 16) & 0xFF); + if (byte) + { + checkIogBit(pAdapter, (offset) + 16, byte); + } + } + if (iogCause & 0x0000FFFF) + { + byte = (MV_U8)(iogCause >> 8); + if (byte) + { + checkIogBit(pAdapter, (offset) + 8, byte); + } + byte = (MV_U8)(iogCause & 0xFF); + if (byte) + { + checkIogBit(pAdapter, (offset), byte); + } + } +} + +/******************************************************************************* +* iogInterrupt - I/O granularity ISR. +* +* DESCRIPTION: +* Checks bit of I/O granularity cause register for +* specific transaction ID +* +* INPUT: +* pAdapter - Pointer to the MV88SX60XX adapter data structure. +* ioBaseAddr - SATA Adapter base address +* mainCause - interrupt cause register +* +* RETURN: +* None +* +* COMMENTS: +* +*******************************************************************************/ + +static void iogInterrupt(MV_SATA_ADAPTER *pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 mainCause) +{ + MV_U32 iogCauseRegister; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG | MV_DEBUG_INTERRUPTS, + " %d: IO Granularity Interrupt." + "Cause = 0x%08x", pAdapter->adapterId, mainCause); + if (mainCause & MV_IOG_TRANS_LOW_BIT) + { + + iogCauseRegister = MV_REG_READ_DWORD(ioBaseAddr, + MV_IOG_TRANS_LOW_REG_OFFSET); + MV_REG_WRITE_DWORD (ioBaseAddr, + MV_IOG_TRANS_LOW_REG_OFFSET, + ~iogCauseRegister); + if (MV_TRUE == pAdapter->iogEnabled) + checkIogCompletion(pAdapter, iogCauseRegister, 0); + } + if (mainCause & MV_IOG_TRANS_HIGH_BIT) + { + iogCauseRegister = MV_REG_READ_DWORD(ioBaseAddr, + MV_IOG_TRANS_HIGH_REG_OFFSET); + MV_REG_WRITE_DWORD (ioBaseAddr, + MV_IOG_TRANS_HIGH_REG_OFFSET, + ~iogCauseRegister); + if (MV_TRUE == pAdapter->iogEnabled) + checkIogCompletion(pAdapter, iogCauseRegister, 32); + } +} + + +/******************************************************************************* +* iogReset - reset all settings in HW related to I/O granularity. +* +* DESCRIPTION: +* The function is executed when the error is occured and IO granularity +* is enabled for the adapter. The function performs the following +* operations +* 1. IO granularity interrupts are masked +* 2. Clear IO granularity cause registers +* 3. Reset all IO granularity transcation counters +* +* INPUT: +* pAdapter - Pointer to the MV88SX60XX adapter data structure. +* +* RETURN: +* None +* +* COMMENTS: +* +*******************************************************************************/ + +static MV_BOOLEAN iogReset(MV_SATA_ADAPTER *pAdapter) +{ + MV_U32 i; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d: IO Granularity error handler is executed.\n.", + pAdapter->adapterId); + /*Mask IO Granularity interrupt*/ + mvOsSemTake(&pAdapter->interruptsMaskSem); + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset, + (pAdapter->mainMask & (~MV_IOG_TRANS_INT_MASK))); + mvOsSemRelease(&pAdapter->interruptsMaskSem); + + mvOsSemTake(&pAdapter->iogSemaphore); + /*Clear IO Granularity cause registers*/ + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_IOG_TRANS_LOW_REG_OFFSET, + 0); + MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress, + MV_IOG_TRANS_HIGH_REG_OFFSET, + 0); + + /*Set all transaction counters to zero*/ + for (i = 0; i < MV_IOG_QUEUE_SIZE; i += 4) + { + MV_U32 offset = MV_IOG_TRANS_CTRL_REG_OFFSET + i; + MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress, offset, 0); + } + mvOsSemRelease(&pAdapter->iogSemaphore); +} + + + +#endif +static MV_U32 getRegField(MV_U32 regVal, MV_U32 fieldOff, MV_U32 bitsNum) +{ + MV_U32 mask = ((1 << bitsNum) - 1); + return(regVal >> fieldOff) & mask; +} + +#ifdef MV_LOGGER +void _dumpPCIRegs(MV_SATA_ADAPTER *pAdapter) +{ + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d " + "_dumpPCIRegs failed - " + "Bad adapter data structure pointer.\n", + pAdapter->adapterId); + return ; + } + if (pAdapter->hostInterface == MV_HOST_IF_INTEGRATED) + { + /* no pci interface*/ + return; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d :Dump PCI Regs\n", + pAdapter->adapterId); + + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Main interrupt Cause",pAdapter->mainCauseOffset, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainCauseOffset)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Main interrupt Mask",pAdapter->mainMaskOffset, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + pAdapter->mainMaskOffset)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "SErr Mask",0xC28, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0xc28)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Error Addr Low",0x1d40, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d40)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Error Addr High",0x1d44, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d44)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Error Attr",0x1d48, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d48)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Error Command",0x1d50, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d50)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Intr Cause",0x1d58, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d58)); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%-25s %04x %08x\n", + "Intr Mask",0x1d5c, + MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, 0x1d5c)); +} + +void _dumpEDMARegs(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelIndex) +{ + MV_U32 regVal, regOff; + + if (pMvSataAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d " + "_dumpEDMARegs failed - " + "Bad adapter data structure pointer.\n", + pMvSataAdapter->adapterId, channelIndex); + return; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d:Dump Edma HW Regs\n", + pMvSataAdapter->adapterId, channelIndex); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_CONFIG_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " EMDA CFG off 0x%08x val 0x%08x: depth 0x%x NCQ %x BURST SIZE %x " + "eQueue %x Stop On Err %x BURST EXT %x WRITE BURST SIZE %x\n", + regOff, regVal, + getRegField(regVal, 0, 5), + getRegField(regVal, 5, 1), + getRegField(regVal, 8, 1), + getRegField(regVal, 9, 1), + getRegField(regVal, 10, 1), + getRegField(regVal, 11, 1), + getRegField(regVal, 13, 1)); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Intr Cause off 0x%08x val 0x%08x\n", regOff, regVal); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Intr Mask off 0x%08x val 0x%08x\n", regOff, regVal); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_REQUEST_Q_BAH_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Req AddrHi off 0x%08x val 0x%08x\n", regOff, regVal); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_REQUEST_Q_INP_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Req INP off 0x%08x val 0x%08x: INP 0x%x BA 0x%x\n", + regOff, regVal, + getRegField(regVal, 5, 5), + getRegField(regVal, 10, 22)); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Req OUTP off 0x%08x val 0x%08x: OUT 0x%x\n", + regOff, regVal, + getRegField(regVal, 5, 5)); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Res AddrHi off 0x%08x val 0x%08x\n", + regOff, regVal); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Res INP off 0x%08x val 0x%08x: INP 0x%x\n", + regOff, regVal, + getRegField(regVal, 3, 5)); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Res OUTP off 0x%08x val 0x%08x: OUTP 0x%x BA 0x%x\n", + regOff, regVal, + getRegField(regVal, 3, 5), + getRegField(regVal, 8, 24)); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_COMMAND_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Command off 0x%08x val 0x%08x: EN %x DIS %x HW RESET %x\n", + regOff, regVal, + getRegField(regVal, 0, 1), + getRegField(regVal, 1, 1), + getRegField(regVal, 2, 1)); + + regOff = edmaRegOffst[ channelIndex] + MV_EDMA_STATUS_REG_OFFSET; + regVal = mvSataReadReg(pMvSataAdapter, regOff); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," Status off 0x%08x val 0x%08x: TAG 0x%x\n", + regOff, regVal, + getRegField(regVal, 0, 5)); + + if (pMvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_IIE) + { +#define PRINT_REG(name, offset)\ + {\ + regOff = edmaRegOffst[ channelIndex] + (offset);\ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR,"%s off 0x%08x val 0x%08x\n",\ + name, regOff, mvSataReadReg(pMvSataAdapter, regOff));\ + } + PRINT_REG("EDMA Halt Conditions Register", 0x60); + PRINT_REG("EDMA FSM Debug Status Register", 0x084); + PRINT_REG("EDMA Busy Status Register", 0x88); + PRINT_REG("EDMA TCQ Status Register", 0x08c); + PRINT_REG("EDMA Rx FIS Parser Register", 0x090); + PRINT_REG("EDMA NCQ0 Done/TCQ0 Outstanding Status Register", 0x098); + PRINT_REG("EDMA NCQ1 Done/TCQ1 Outstanding Status Register", 0x09c); + PRINT_REG("EDMA NCQ2 Done/TCQ2 Outstanding Status Register", 0x0a0); + PRINT_REG("EDMA NCQ3 Done/TCQ3 Outstanding Status Register", 0x0a4); + PRINT_REG("EDMA Interrupt Error 2 Cause Register", 0x064); + PRINT_REG("FIS Interrupt Cause Register", 0x364); + PRINT_REG("FIS Interrupt Mask Register", 0x368); + PRINT_REG("FIS DW0 Register", 0x370); + PRINT_REG("FIS DW1 Register", 0x374); + PRINT_REG("FIS DW2 Register", 0x378); + PRINT_REG("FIS DW3 Register", 0x37c); + PRINT_REG("FIS DW4 Register", 0x380); + PRINT_REG("FIS DW5 Register", 0x384); + PRINT_REG("FIS DW6 Register", 0x388); + + } + + + + + +} + +void _dumpChannelQueues(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_U32 i; + MV_U32 entries = MV_EDMA_QUEUE_LENGTH; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d " + "_dumpChannelQueues failed - " + "Bad adapter data structure pointer.\n", + pAdapter->adapterId, channelIndex); + return ; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d:Dump Channel Queues\n", + pAdapter->adapterId, channelIndex); + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: _dumpChannelQueues" + "el Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return ; + } + + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Request Qeueu Info:\n"); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " virt addr %p:\n", + pSataChannel->requestQueue); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy low addr %08x:\n", + pSataChannel->requestQueuePciLowAddress); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy high addr %08x:\n", + pSataChannel->requestQueuePciHiAddress); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " SW IN pointer %x:\n", + pSataChannel->reqInPtr); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Request Qeueu Entries:\n"); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "Index [3:0] [7:4] [11:8] [15:12]\n"); + if (pSataChannel->use128Entries == MV_TRUE) + { + entries = MV_EDMA_GEN2E_QUEUE_LENGTH; + } + for (i = 0; i < entries; i++) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "[%2d] 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",i, + *((MV_U32 *)(pSataChannel->requestQueue + i)), + *(((MV_U32 *)(pSataChannel->requestQueue + i)) + 1), + *(((MV_U32 *)(pSataChannel->requestQueue + i)) + 2), + *(((MV_U32 *)(pSataChannel->requestQueue + i)) + 3), + *(((MV_U32 *)(pSataChannel->requestQueue + i)) + 4), + *(((MV_U32 *)(pSataChannel->requestQueue + i)) + 5), + *(((MV_U32 *)(pSataChannel->requestQueue + i)) + 6), + *(((MV_U32 *)(pSataChannel->requestQueue + i)) + 7)); + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Responset Qeueu Info:\n"); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " virt addr %p:\n", + pSataChannel->responseQueue); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy low addr %08x:\n", + pSataChannel->responseQueuePciLowAddress); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " phy high addr %08x:\n", + pSataChannel->responseQueuePciHiAddress); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " SW OUT pointer %x:\n", + pSataChannel->rspOutPtr); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Response Qeueu Entries:\n"); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "Index [1:0] [3:2] [7:4]\n"); + for (i = 0; i < entries; i++) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "[%2d] 0x%04x 0x%04x 0x%08x\n",i, + *((MV_U16 *)(pSataChannel->responseQueue + i)), + *(((MV_U16 *)(pSataChannel->responseQueue + i)) + 1), + *(((MV_U32 *)(pSataChannel->responseQueue + i)) + 1)); + } +} +void _dumpSataRegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_U32 regVal; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d " + "_dumpSataRegs failed - " + "Bad adapter data structure pointer.\n", + pAdapter->adapterId, channelIndex); + return; + } + + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_S_STATUS_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " SStatus 0x%08x:\n", regVal); + + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_S_CONTROL_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " SControl 0x%08x:\n", regVal); + + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_S_ERROR_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " SError 0x%08x:\n", regVal); + + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_IF_CONTROL_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " IF Ctrl 0x%08x: TXPort 0x%x\n", regVal, + getRegField(regVal, 0, 4)); + regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress, + edmaRegOffst[ channelIndex] + + MV_SATA_II_IF_STATUS_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " IF status 0x%08x: RXFIS 0x%x RXPort 0x%x\n", regVal, + getRegField(regVal, 0, 8), + getRegField(regVal, 8, 4)); + } +} +void _printATARegs(MV_STORAGE_DEVICE_REGISTERS *pDeviceRegs) +{ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " ATA Drive Registers:\n"); + if (pDeviceRegs == NULL) + { + return; + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%20s : %04x\n","Error", pDeviceRegs->errorRegister); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%20s : %04x\n","SectorCount", pDeviceRegs->sectorCountRegister); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%20s : %04x\n","LBA Low", pDeviceRegs->lbaLowRegister); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%20s : %04x\n","LBA Mid", pDeviceRegs->lbaMidRegister); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%20s : %04x\n","LBA High", pDeviceRegs->lbaHighRegister); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%20s : %04x\n","Device", pDeviceRegs->deviceRegister); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "%20s : %04x\n","Status", pDeviceRegs->statusRegister); +} + +#endif /*MV_LOGGER*/ + + + + + + diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.h b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.h new file mode 100644 index 0000000..e4c0d23 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSata.h @@ -0,0 +1,774 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvSata.h - Header File for mvSata.c. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* mvOs.h +* ATA/ATAPI-6 standard +* +*******************************************************************************/ +#ifndef __INCmvSatah +#define __INCmvSatah +#ifdef __cplusplus +extern "C" /*{*/ +#endif /* __cplusplus */ + +/* Includes */ +#include "mvOsS.h" +#include "mvRegs.h" + +/* Definitions */ +#define MV_CORE_DRIVER_LOG_ID 0 + + + +/* MV88SX50XX specific defines */ +#define MV_SATA_VENDOR_ID 0x11AB +#define MV_SATA_DEVICE_ID_5080 0x5080 +#define MV_SATA_DEVICE_ID_5081 0x5081 +#define MV_SATA_DEVICE_ID_5040 0x5040 +#define MV_SATA_DEVICE_ID_5041 0x5041 +#define MV_SATA_DEVICE_ID_6041 0x6041 +#define MV_SATA_DEVICE_ID_6081 0x6081 +#define MV_SATA_DEVICE_ID_6042 0x6042 +#define MV_SATA_DEVICE_ID_7042 0x7042 +#define MV_SATA_DEVICE_ID_5182 0x5182 /*88F5182 integrated sata*/ +#define MV_SATA_DEVICE_ID_5082 0x5082 /*88F5082 integrated sata*/ +#define MV_SATA_DEVICE_ID_6082 0x6082 /* Same device ID for 6082L */ +#define MV_SATA_DEVICE_ID_6490 0x6490 /*64660 integrated sata*/ + +#define MV_SATA_DEVICE_ID_78XX0 0x7800 /*78x00 Z0/Y0 integrated sata*/ +#define MV_SATA_DEVICE_ID_78100 0x7810 /*78100 integrated sata*/ +#define MV_SATA_DEVICE_ID_78200 0x7820 /*78200 integrated sata*/ + +#define MV_SATA_DEVICE_ID_6281 0x6281 /*88f6281 integrated sata*/ +#define MV_SATA_DEVICE_ID_6192 0x6192 /*88f6192 integrated sata*/ +#define MV_SATA_DEVICE_ID_6190 0x6190 /*88f6190 integrated sata*/ + +#define MV_SATA_CHANNELS_NUM 8 +#define MV_SATA_UNITS_NUM 2 + +#define MV_SATA_5082_PORT_NUM 1 +#define MV_SATA_5182_PORT_NUM 2 +#define MV_SATA_6082_PORT_NUM 1 +#define MV_SATA_6490_PORT_NUM 1 +#define MV_SATA_6281_PORT_NUM 2 +#define MV_SATA_6192_PORT_NUM 2 +#define MV_SATA_6190_PORT_NUM 1 +#define MV_SATA_78XX0_PORT_NUM 2 + +#define MV_SATA_PM_MAX_PORTS 15 +#define MV_SATA_PM_CONTROL_PORT 15 + +#define MV_EDMA_QUEUE_LENGTH 32 /* Up to 32 outstanding */ +#define MV_EDMA_GEN2E_QUEUE_LENGTH 128 + +/* commands per SATA channel*/ +#ifndef MV_SATA_OVERRIDE_SW_QUEUE_SIZE + #define MV_SATA_SW_QUEUE_SIZE (MV_EDMA_QUEUE_LENGTH -1) +#else + #define MV_SATA_SW_QUEUE_SIZE MV_SATA_REQUESTED_SW_QUEUE_SIZE +#endif + +#ifdef MV_SATA_SUPPORT_GEN2E_128_QUEUE_LEN + #ifndef MV_SATA_OVERRIDE_GEN2E_SW_QUEUE_SIZE + #define MV_SATA_GEN2E_SW_QUEUE_SIZE (MV_EDMA_GEN2E_QUEUE_LENGTH -1) + #else + #define MV_SATA_GEN2E_SW_QUEUE_SIZE MV_SATA_REQUESTED_GEN2E_SW_QUEUE_SIZE + #endif +#else + #define MV_SATA_GEN2E_SW_QUEUE_SIZE (MV_SATA_SW_QUEUE_SIZE) +#endif + +#if ((MV_SATA_SW_QUEUE_SIZE) >= (MV_EDMA_QUEUE_LENGTH)) +#error "FATAL ERROR: Bad Value for MV_SATA_SW_QUEUE_SIZE " +#endif +#if ((MV_SATA_GEN2E_SW_QUEUE_SIZE) >= (MV_EDMA_GEN2E_QUEUE_LENGTH)) +#error "FATAL ERROR: Bad Value for MV_EDMA_GEN2E_QUEUE_LENGTH " +#endif +#if ((MV_SATA_SW_QUEUE_SIZE) > (MV_SATA_GEN2E_SW_QUEUE_SIZE)) +#error "FATAL ERROR: MV_SATA_SW_QUEUE_SIZE bigger than MV_EDMA_GEN2E_QUEUE_LENGTH" +#endif + +#if (((MV_SATA_GEN2E_SW_QUEUE_SIZE) * 4) > ((MV_SATA_SW_QUEUE_SIZE) * 8)) +#define _MV_SATA_COMMANDS_PER_ADAPTER ((MV_SATA_GEN2E_SW_QUEUE_SIZE) * 4) +#else +#define _MV_SATA_COMMANDS_PER_ADAPTER ((MV_SATA_SW_QUEUE_SIZE) * 8) +#endif + +#define MV_EDMA_QUEUE_MASK 0x1F +#define MV_EDMA_REQUEST_ENTRY_SIZE 32 +#define MV_EDMA_RESPONSE_ENTRY_SIZE 8 +#define MV_EDMA_REQUEST_QUEUE_SIZE 1024 /* 32*32 = 1KBytes */ +#define MV_EDMA_RESPONSE_QUEUE_SIZE 256 /* 32*8 = 256 Bytes */ + +#define MV_EDMA_GEN2E_QUEUE_MASK 0x7F +#define MV_EDMA_GEN2E_REQUEST_QUEUE_SIZE 4096 /* 128*32 = 4KBytes */ +#define MV_EDMA_GEN2E_RESPONSE_QUEUE_SIZE 1024 /* 128*8 = 1KBytes */ + +#define MV_EDMA_PRD_ENTRY_SIZE 16 /* 16Bytes*/ +#define MV_EDMA_PRD_NO_SNOOP_FLAG MV_BIT0 +#define MV_EDMA_PRD_EOT_FLAG MV_BIT15 + +#define MV_ATA_IDENTIFY_DEV_DATA_LENGTH 256 /* number of words(2 byte)*/ +#define MV_ATA_MODEL_NUMBER_LEN 40 +#define ATA_SECTOR_SIZE 512 +#define ATA_SECTOR_SIZE_IN_WORDS 256 + +#define MV_SATA_COMM_INIT_DELAY 1000 /*1000 us*/ +#define MV_SATA_COMM_INIT_WAIT_DELAY 20000 /*20 ms*/ + +/*Channel to Channel*/ +#ifdef MV_SATA_C2C_COMM + #define MV_SATA_REGISTER_HOST_2_DEVICE_FIS 0x00000034 + #define MV_SATA_DMA_ACTIVATE_FIS 0x00000039 + #define MV_C2C_MESSAGE_SIZE 10 + +#endif + +#ifdef MV_SATA_IO_GRANULARITY + #define MV_IOG_QUEUE_SIZE 0x40 + #define MV_IOG_INVALID_COMMAND_ID MV_IOG_QUEUE_SIZE +#endif + +/* Typedefs */ +typedef enum mvUdmaType +{ + MV_UDMA_TYPE_READ, MV_UDMA_TYPE_WRITE +} MV_UDMA_TYPE; + +typedef enum mvFlushType +{ + MV_FLUSH_TYPE_CALLBACK, MV_FLUSH_TYPE_NONE +} MV_FLUSH_TYPE; + +typedef enum mvCompletionType +{ + MV_COMPLETION_TYPE_NORMAL, MV_COMPLETION_TYPE_ERROR, + MV_COMPLETION_TYPE_ABORT +} MV_COMPLETION_TYPE; + +typedef enum mvEventType +{ + MV_EVENT_TYPE_ADAPTER_ERROR, MV_EVENT_TYPE_SATA_CABLE, + MV_EVENT_TYPE_SATA_ERROR +} MV_EVENT_TYPE; + +typedef enum mvSataCableEvent +{ + MV_SATA_CABLE_EVENT_DISCONNECT = 0, + MV_SATA_CABLE_EVENT_CONNECT, + MV_SATA_CABLE_EVENT_PM_HOT_PLUG +} MV_SATA_CABLE_EVENT; + +typedef enum mvSataErrorEvent +{ + MV_SATA_RECOVERABLE_COMMUNICATION_ERROR = 0, + MV_SATA_UNRECOVERABLE_COMMUNICATION_ERROR, + MV_SATA_DEVICE_ERROR +} MV_SATA_ERROR_EVENT; + +#ifdef MV_SATA_C2C_COMM +typedef enum mvC2CEventType +{ + MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_DONE, + MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_ERROR, + MV_C2C_BM_DMA_DONE, + MV_C2C_BM_DMA_ERROR, +} MV_C2C_EVENT_TYPE; +#endif + +typedef enum mvEdmaMode +{ + MV_EDMA_MODE_QUEUED, + MV_EDMA_MODE_NOT_QUEUED, + MV_EDMA_MODE_NATIVE_QUEUING +} MV_EDMA_MODE; + +typedef enum mvQueueCommandResult +{ + MV_QUEUE_COMMAND_RESULT_OK = 0, + MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED, + MV_QUEUE_COMMAND_RESULT_FULL, + MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS, + MV_QUEUE_COMMAND_RESULT_BAD_PARAMS +} MV_QUEUE_COMMAND_RESULT; + +typedef enum mvNonUdmaProtocol +{ + MV_NON_UDMA_PROTOCOL_NON_DATA, + MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, + MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT, + MV_NON_UDMA_PROTOCOL_PACKET_PIO_NON_DATA, + MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN, + MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_OUT, + MV_NON_UDMA_PROTOCOL_PACKET_DMA +} MV_NON_UDMA_PROTOCOL; + +typedef enum mvSataGeneration +{ + MV_SATA_GEN_I, MV_SATA_GEN_II, MV_SATA_GEN_IIE +} MV_SATA_GEN; + +typedef enum mvSataInterfaceSpeed +{ + MV_SATA_IF_SPEED_1_5_GBPS, MV_SATA_IF_SPEED_3_GBPS, + MV_SATA_IF_SPEED_NO_LIMIT, MV_SATA_IF_SPEED_INVALID +} MV_SATA_IF_SPEED; + +typedef enum mvSataInterfacePowerState +{ + MV_SATA_IF_POWER_PHY_READY = 1, MV_SATA_IF_POWER_PARTIAL = 2, + MV_SATA_IF_POWER_SLUMBER = 6 +} MV_SATA_IF_POWER_STATE; + +#ifdef MV_SATA_C2C_COMM +typedef enum mvSataC2CMode +{ + MV_SATA_C2C_MODE_INITIATOR, MV_SATA_C2C_MODE_TARGET +} MV_SATA_C2C_MODE; +#endif + +typedef enum mvSataDeviceType +{ + MV_SATA_DEVICE_TYPE_UNKNOWN = 0, + MV_SATA_DEVICE_TYPE_ATA_DISK, + MV_SATA_DEVICE_TYPE_ATAPI_DEVICE, + MV_SATA_DEVICE_TYPE_PM +} MV_SATA_DEVICE_TYPE; + +typedef enum mvPMSwitchingmode +{ + MV_SATA_SWITCHING_MODE_NONE = 0, + MV_SATA_SWITCHING_MODE_CBS, + MV_SATA_SWITCHING_MODE_QCBS, + MV_SATA_SWITCHING_MODE_FBS, +}MV_SATA_SWITCHING_MODE; + +struct mvDmaRequestQueueEntry; +struct mvDmaResponseQueueEntry; +struct mvDmaCommandEntry; + +struct mvSataAdapter; +struct mvStorageDevRegisters; +struct mvSataChannel; + +typedef MV_BOOLEAN (* mvSataCommandCompletionCallBack_t)(struct mvSataAdapter *, + MV_U8, + MV_COMPLETION_TYPE, + MV_VOID_PTR, MV_U16, + MV_U32, + struct mvStorageDevRegisters *); +#ifdef MV_SATA_C2C_COMM +typedef MV_BOOLEAN (*C2CCallBack_t)(struct mvSataAdapter *, + struct mvSataChannel *, + MV_C2C_EVENT_TYPE event, + MV_U32 msgSize, + MV_U8* msg); + +#endif + +typedef enum mvQueuedCommandType +{ + MV_QUEUED_COMMAND_TYPE_UDMA, + MV_QUEUED_COMMAND_TYPE_NONE_UDMA, + MV_QUEUED_COMMAND_TYPE_PACKET +} MV_QUEUED_COMMAND_TYPE; + +#ifdef MV_SATA_IO_GRANULARITY +typedef enum mvIogQueuedCommandType +{ + MV_IOG_COMMAND_TYPE_FIRST, + MV_IOG_COMMAND_TYPE_NEXT +} MV_IOG_COMMAND_TYPE; +#endif + +typedef enum mvSataInterruptScheme +{ + MV_SATA_INTERRUPT_HANDLING_IN_ISR, + MV_SATA_INTERRUPT_HANDLING_IN_TASK, + MV_SATA_INTERRUPTS_DISABLED +}MV_SATA_INTERRUPT_SCHEME; + +typedef struct mvUdmaCommandParams +{ + MV_UDMA_TYPE readWrite; + MV_BOOLEAN isEXT; + MV_BOOLEAN FUA; + MV_U32 lowLBAAddress; + MV_U16 highLBAAddress; + MV_U16 numOfSectors; + MV_U32 prdLowAddr; + MV_U32 prdHighAddr; +#ifdef MV_SATA_SUPPORT_EDMA_SINGLE_DATA_REGION + MV_BOOLEAN singleDataRegion; + MV_U16 byteCount; +#endif + mvSataCommandCompletionCallBack_t callBack; + MV_VOID_PTR commandId; +#ifdef MV_SATA_IO_GRANULARITY + MV_BOOLEAN ioGranularityEnabled; + MV_IOG_COMMAND_TYPE iogCommandType; + union + { + MV_U8 transId; + MV_U8 transCount; + } ioGranularityCommandParam; + MV_U8 iogCurrentTransId; +#endif +} MV_UDMA_COMMAND_PARAMS; + +typedef struct mvNoneUdmaCommandParams +{ + MV_NON_UDMA_PROTOCOL protocolType; + MV_BOOLEAN isEXT; + MV_U16_PTR bufPtr; + MV_U32 count; + MV_U16 features; + MV_U16 sectorCount; + MV_U16 lbaLow; + MV_U16 lbaMid; + MV_U16 lbaHigh; + MV_U8 device; + MV_U8 command; + mvSataCommandCompletionCallBack_t callBack; + MV_VOID_PTR commandId; +} MV_NONE_UDMA_COMMAND_PARAMS; + +typedef struct mvPacketCommandParams +{ + MV_NON_UDMA_PROTOCOL protocolType; + MV_U16_PTR bufPtr; + MV_U32 buffer_len; + MV_U32 transfered_data; + MV_U8 cdb_len; + MV_U16_PTR cdb_buffer; /*SCSI command desciptor block*/ + MV_U8 flags;/* bit 0:1-> DMA write*/ + /* bit 1:1-> single Data Region*/ + MV_U32 prdLowAddr; + MV_U32 prdHighAddr; + mvSataCommandCompletionCallBack_t callBack; + MV_VOID_PTR commandId; +} MV_PACKET_COMMAND_PARAMS; + +typedef struct mvQueueCommandInfo +{ + MV_QUEUED_COMMAND_TYPE type; + MV_U8 PMPort; + union + { + MV_UDMA_COMMAND_PARAMS udmaCommand; + MV_NONE_UDMA_COMMAND_PARAMS NoneUdmaCommand; + MV_PACKET_COMMAND_PARAMS packetCommand; + } commandParams; +} MV_QUEUE_COMMAND_INFO; + +/* The following structure is for the Core Driver internal usage */ +typedef struct mvQueuedCommandEntry +{ + MV_BOOLEAN isFreeEntry; + /*MV_U8 commandTag;*/ + MV_U8 hostTag; + MV_U8 deviceTag; + MV_BOOLEAN isCommandInEdma:1; + MV_BOOLEAN commandAborted:1; + struct mvQueuedCommandEntry *next; + struct mvQueuedCommandEntry *prev; + MV_QUEUE_COMMAND_INFO *pCommandInfo; +#ifndef MV_SATA_STORE_COMMANDS_INFO_ON_IAL_STACK + MV_QUEUE_COMMAND_INFO commandInfo; +#endif +} MV_QUEUED_COMMAND_ENTRY; + + +typedef enum mvErrorHandlingState +{ + MV_ERROR_HANDLING_STATE_IDLE, + MV_ERROR_HANDLING_STATE_WAIT_FOR_COMPLETIONS, + MV_ERROR_HANDLING_STATE_WAIT_FOR_BUSY, + MV_ERROR_HANDLING_STATE_REQUEST_SENSE +}MV_ERROR_HANDLING_STATE; + +typedef struct +{ + MV_ERROR_HANDLING_STATE state; + MV_U16 PortsWithErrors;/*which ports reported errors*/ + MV_U8 CurrPort; + MV_QUEUED_COMMAND_ENTRY *pReadLogExtEntry; + MV_U16_PTR ReadLogExtBuffer; + MV_BOOLEAN useVendorUniqGen2WA; +}MV_ERROR_HANDLING_INFO; + +/*for internal usage*/ +#define MV_SATA_TAGS_PER_POOL 32 +#ifdef MV_SATA_SUPPORT_GEN2E_128_QUEUE_LEN + #define MV_SATA_GEN2E_TAG_POOLS_NUM (MV_SATA_PM_MAX_PORTS + 1) + #define MV_SATA_GEN2E_TAG_PMPORT_MASK 0x0F +#else + #define MV_SATA_GEN2E_TAG_POOLS_NUM 1 + #define MV_SATA_GEN2E_TAG_PMPORT_MASK 0x00 +#endif + +struct _mvTagsStack +{ + MV_U8 *pTagsArray; + MV_U8 top; +}; +struct _mvChannelTags +{ + struct _mvTagsStack HostTagsPool; + struct _mvTagsStack DeviceTagsPool[MV_SATA_GEN2E_TAG_POOLS_NUM]; + MV_U8 HostTags[MV_SATA_GEN2E_SW_QUEUE_SIZE]; + MV_U8 DeviceTags[MV_SATA_GEN2E_TAG_POOLS_NUM][MV_SATA_TAGS_PER_POOL]; +}; + +typedef enum mvHostInterfase +{ + MV_HOST_IF_INTEGRATED, /*as in 5182*/ + MV_HOST_IF_PEX, + MV_HOST_IF_PCI /*PCI/PCI-X*/ +}MV_HOST_IF; + +/* The following structures are part of the Core Driver API */ +typedef struct mvSataChannel +{ + /* Fields set by Intermediate Application Layer */ + MV_U8 channelNumber; + struct mvDmaRequestQueueEntry *requestQueue; + struct mvDmaResponseQueueEntry *responseQueue; + MV_U32 requestQueuePciHiAddress; + MV_U32 requestQueuePciLowAddress; + MV_U32 responseQueuePciHiAddress; + MV_U32 responseQueuePciLowAddress; + /* DRQ Data Block size in sectors, Core Driver sets a default value of 1 */ + /* sector in mvSataConfigureChannel*/ + MV_U8 DRQDataBlockSize; + /* Fields set by CORE driver */ + struct mvSataAdapter *mvSataAdapter; + MV_OS_SEMAPHORE semaphore; + MV_U32 eDmaRegsOffset; + MV_BOOLEAN EdmaActive; + MV_EDMA_MODE queuedDMA; + MV_U8 outstandingCommands; + MV_U8 portQueuedCommands[MV_SATA_PM_MAX_PORTS + 1]; + struct mvQueuedCommandEntry *commandsQueue; + struct mvQueuedCommandEntry *commandsQueueHead; + struct mvQueuedCommandEntry *commandsQueueTail; + MV_BOOLEAN queueCommandsEnabled; + MV_U8 noneUdmaOutstandingCommands; +#ifdef MV_SUPPORT_ATAPI + MV_U8 packetOutstandingCommands; + MV_BOOLEAN waitForBMDMA; +#endif + MV_U8 EdmaQueuedCommands; + MV_U8 commandsQueueSize; + struct _mvChannelTags Tags; + MV_U8 reqInPtr; + MV_U8 rspOutPtr; + MV_U8 EDMAQueuePtrMask; + MV_U32 EDMARequestInpMask; + /* Port Multiplier fiels*/ + MV_BOOLEAN PMSupported; + MV_SATA_DEVICE_TYPE deviceType; + MV_BOOLEAN FBSEnabled; + MV_BOOLEAN use128Entries; +#ifdef MV_SATA_C2C_COMM + + /* Channel 2 Channel*/ + MV_BOOLEAN C2CmodeEnabled; + MV_SATA_C2C_MODE C2CMode; + C2CCallBack_t C2CCallback; +#endif + MV_U8 recoveredErrorsCounter; + /* NCQ error handling*/ + MV_ERROR_HANDLING_INFO ErrorHandlingInfo; +} MV_SATA_CHANNEL; + + + +typedef struct mvSataAdapter +{ + /* Fields set by Intermediate Application Layer */ + MV_U32 adapterId; + MV_VOID_PTR IALData; + MV_U8 pciConfigRevisionId; + MV_U16 pciConfigDeviceId; + MV_BUS_ADDR_T adapterIoBaseAddress; + MV_U32 intCoalThre[MV_SATA_UNITS_NUM]; + MV_U32 intTimeThre[MV_SATA_UNITS_NUM]; + MV_BOOLEAN (*mvSataEventNotify)(struct mvSataAdapter *, + MV_EVENT_TYPE, + MV_U32, MV_U32); + MV_SATA_CHANNEL *sataChannel[MV_SATA_CHANNELS_NUM]; + MV_U32 pciCommand; + MV_U32 pciSerrMask; + MV_U32 pciInterruptMask; + + + /* Fields set by CORE driver */ + MV_SATA_GEN sataAdapterGeneration; + MV_BOOLEAN staggaredSpinup[MV_SATA_CHANNELS_NUM]; /* For 60x1 only */ + MV_BOOLEAN limitInterfaceSpeed[MV_SATA_CHANNELS_NUM]; /* For 60x1 only */ + MV_SATA_IF_SPEED ifSpeed[MV_SATA_CHANNELS_NUM]; /* For 60x1 only */ + MV_SATA_IF_POWER_STATE ifPowerState[MV_SATA_CHANNELS_NUM]; + MV_U8 numberOfChannels;/* 4 channels for 504x, 8 for 508x*/ + MV_U8 numberOfUnits;/* 1 for 504x, 2 for 508x*/ + MV_U8 portsPerUnit; + MV_OS_SEMAPHORE semaphore; + MV_U32 mainMask; + MV_U32 mainMaskOffset; + MV_U32 mainCauseOffset; + MV_HOST_IF hostInterface; + MV_BOOLEAN interruptsAreMasked; + MV_SATA_INTERRUPT_SCHEME interruptsScheme; + MV_OS_SEMAPHORE interruptsMaskSem; + MV_BOOLEAN chipIs50XXB0; + MV_BOOLEAN chipIs50XXB2; + MV_BOOLEAN chipIs60X1B2; + MV_BOOLEAN chipIs60X1C0; + MV_BOOLEAN chipIs62X1Z0; + MV_U8 signalAmps[MV_SATA_CHANNELS_NUM]; + MV_U8 pre[MV_SATA_CHANNELS_NUM]; + struct mvQueuedCommandEntry adapterCommands[_MV_SATA_COMMANDS_PER_ADAPTER]; +#ifdef MV_SATA_IO_GRANULARITY + MV_BOOLEAN iogEnabled; + MV_U8 iogFreeIdsStack[MV_IOG_QUEUE_SIZE]; + MV_U8 iogFreeIdsNum; + MV_OS_SEMAPHORE iogSemaphore; +#endif +} MV_SATA_ADAPTER; + +/* this structure used by the IAL defines the PRD entries used by the EDMA HW */ +typedef struct mvSataEdmaPRDEntry +{ + volatile MV_U32 lowBaseAddr; + volatile MV_U16 byteCount; + volatile MV_U16 flags; + volatile MV_U32 highBaseAddr; + volatile MV_U32 reserved; +}MV_SATA_EDMA_PRD_ENTRY; + +/* API Functions */ + +/* CORE driver Adapter Management */ +MV_BOOLEAN mvSataInitAdapter(MV_SATA_ADAPTER *pAdapter); + +MV_BOOLEAN mvSataShutdownAdapter(MV_SATA_ADAPTER *pAdapter); + +MV_U32 mvSataReadReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset); + +MV_VOID mvSataWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset, + MV_U32 regValue); + +/* CORE driver SATA Channel Management */ +MV_BOOLEAN mvSataConfigureChannel(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataRemoveChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +MV_BOOLEAN mvSataIsStorageDeviceConnected(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_U32 *SStatus); + +MV_BOOLEAN mvSataIfD2HReceived(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 port); + +MV_BOOLEAN mvSataChannelHardReset(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataSetFBSMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_BOOLEAN enableFBS, MV_BOOLEAN useQueueLen128); + +MV_BOOLEAN mvSataConfigEdmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_EDMA_MODE eDmaMode, MV_U8 maxQueueDepth); + +MV_BOOLEAN mvSataEnableChannelDma(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataDisableChannelDma(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataFlushDmaQueue(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_FLUSH_TYPE flushType); + +MV_U8 mvSataNumOfDmaCommands(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +MV_U8 mvSataGetNumOfPortQueuedCommands(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_U8 *pCommandsPerChannel); + +MV_BOOLEAN mvSataSetIntCoalParams (MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, + MV_U32 intCoalThre, MV_U32 intTimeThre); + +MV_BOOLEAN mvSataSetChannelPhyParams(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 signalAmps, MV_U8 pre); + +MV_BOOLEAN mvSataChannelPhyShutdown(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataChannelPhyPowerOn(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataChannelFarLoopbackDiagnostic(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); +/* Queue ATA command */ +MV_QUEUE_COMMAND_RESULT mvSataQueueCommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_QUEUE_COMMAND_INFO *pCommandParams); + + +/* Interrupt Service Routine */ +MV_BOOLEAN mvSataInterruptServiceRoutine(MV_SATA_ADAPTER *pAdapter); + +MV_BOOLEAN mvSataMaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter); + +MV_BOOLEAN mvSataUnmaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter); + +MV_BOOLEAN mvSataCheckPendingInterrupt(MV_SATA_ADAPTER *pAdapter); + +MV_BOOLEAN mvSataSetInterruptsScheme(MV_SATA_ADAPTER *pAdapter, + MV_SATA_INTERRUPT_SCHEME interruptScheme); + +/* + * Staggered spin-ip support and SATA interface speed control + * (relevant for 60x1 adapters) + */ +MV_BOOLEAN mvSataEnableStaggeredSpinUpAll (MV_SATA_ADAPTER *pAdapter); + +MV_BOOLEAN mvSataEnableStaggeredSpinUp (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataDisableStaggeredSpinUpAll (MV_SATA_ADAPTER *pAdapter); + +MV_BOOLEAN mvSataDisableStaggeredSpinUp (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + + +MV_BOOLEAN mvSataSetInterfaceSpeed (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_SATA_IF_SPEED ifSpeed); + +MV_SATA_IF_SPEED mvSataGetInterfaceSpeed (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +MV_BOOLEAN mvSataSetInterfacePowerState (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_SATA_IF_POWER_STATE ifPowerState); + +MV_BOOLEAN mvSataGetInterfacePowerState (MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_SATA_IF_POWER_STATE *ifPowerState); + +/* Command Completion and Event Notification (user implemented) */ +MV_BOOLEAN mvSataEventNotify(MV_SATA_ADAPTER *, MV_EVENT_TYPE , + MV_U32, MV_U32); +#ifdef MV_SATA_C2C_COMM + +/* Channel 2 Channel communication */ +MV_BOOLEAN mvSataC2CInit (MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_SATA_C2C_MODE mvSataC2CMode, + C2CCallBack_t mvSataC2CCallBack); + +MV_BOOLEAN mvSataC2CStop (MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + + +MV_BOOLEAN mvSataC2CSendRegisterDeviceToHostFIS( + MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 pmPort, + MV_BOOLEAN bInterrupt, + MV_U8 message[MV_C2C_MESSAGE_SIZE]); + +MV_BOOLEAN mvSataC2CActivateBmDma(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 pmPort, + MV_U32 prdTableHi, + MV_U32 prdTableLow, + MV_UDMA_TYPE dmaType); + +MV_BOOLEAN mvSataC2CResetBmDma(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + +#endif + +#ifdef MV_SATA_IO_GRANULARITY + +MV_BOOLEAN mvSataEnableIoGranularity(MV_SATA_ADAPTER *pAdapter, + MV_BOOLEAN enable); + +#endif +MV_BOOLEAN mvSata60X1B2CheckDevError(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); +#ifdef __cplusplus + +/*}*/ +#endif /* __cplusplus */ + +#endif /* __INCmvSatah */ diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.c b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.c new file mode 100644 index 0000000..caa972a --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.c @@ -0,0 +1,114 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvSataSoc.h" + +/* Calculate the base address of the registers for a SATA channel */ +static MV_U32 edmaRegOffst[8] = {0x22000, 0x24000, 0x26000, 0x28000, +0x32000, 0x34000, 0x36000, 0x38000}; +#define getEdmaRegOffset(x) edmaRegOffst[(x)] + +MV_BOOL mvSataPhyShutdown(MV_U8 port) +{ + MV_U32 regVal; + MV_U32 adapterIoBaseAddress = SATA_REG_BASE - 0x20000; + + regVal = MV_REG_READ (adapterIoBaseAddress + + getEdmaRegOffset (port) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* Fix for 88SX60x1 FEr SATA#8*/ + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + regVal |= BIT9; + MV_REG_WRITE (adapterIoBaseAddress + + getEdmaRegOffset (port) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, + regVal); + return MV_TRUE; +} +MV_BOOL mvSataPhyPowerOn(MV_U8 port) +{ + MV_U32 adapterIoBaseAddress = SATA_REG_BASE - 0x20000; + + MV_U32 regVal = MV_REG_READ (adapterIoBaseAddress + + getEdmaRegOffset (port) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET); + /* Fix for 88SX60x1 FEr SATA#8*/ + /* according to the spec, bits [31:12] must be set to 0x009B1 */ + regVal &= 0x00000FFF; + /* regVal |= MV_BIT12;*/ + regVal |= 0x009B1000; + + + regVal &= ~(BIT9); + MV_REG_WRITE (adapterIoBaseAddress + + getEdmaRegOffset (port) + + MV_SATA_II_SATA_CONFIG_REG_OFFSET, + regVal); + return MV_TRUE; +} + diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.h b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.h new file mode 100644 index 0000000..3768ba3 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvSataSoc.h @@ -0,0 +1,86 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvSataSoch +#define __INCmvSataSoch +#ifdef __cplusplus +extern "C" /*{*/ +#endif /* __cplusplus */ + +#include "mvCommon.h" +#include "mvRegs.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + + +MV_BOOL mvSataPhyShutdown(MV_U8 port); +MV_BOOL mvSataPhyPowerOn(MV_U8 port); + + +#ifdef __cplusplus + +/*}*/ +#endif /* __cplusplus */ + +#endif /* __INCmvSatah */ + diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.c b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.c new file mode 100644 index 0000000..aebb792 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.c @@ -0,0 +1,2186 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvStorageDev.c - C File for implementation of the core driver. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* mvOs.h +* mvSata.h. +* mvStorageDev.h +* mvRegs.h +* +*******************************************************************************/ +#include "mvOsS.h" +#include "mvSata.h" +#include "mvStorageDev.h" +#include "mvRegs.h" + +/* Defines */ + +/* functions for internal driver use */ +MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delayParam); +MV_BOOLEAN waitForDRQToClear(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delayParam); + +void enableStorageDevInterrupt (MV_SATA_CHANNEL *pSataChannel); +void disableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel); +static MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel); +void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_BOOLEAN isEXT, + MV_STORAGE_DEVICE_REGISTERS *pRegisters); +MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel); +extern void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort); +extern void disableSaDevInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); + +MV_BOOLEAN _PMAccessReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue, + MV_STORAGE_DEVICE_REGISTERS *registerStruct, + MV_BOOLEAN isRead); + +MV_BOOLEAN executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_NON_UDMA_PROTOCOL protocolType, + MV_BOOLEAN isEXT, + MV_U16_PTR bufPtr, MV_U32 count, + MV_U16 features, + MV_U16 sectorCount, + MV_U16 lbaLow, MV_U16 lbaMid, + MV_U16 lbaHigh, MV_U8 device, + MV_U8 command); + +MV_BOOLEAN waitWhileStorageDevIsBusy_88SX60X1(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U8 channelIndex, + MV_U32 loops, + MV_U32 delayParam); + +MV_BOOLEAN waitForDRQ(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delayParam); + +void _startSoftResetDevice(MV_SATA_CHANNEL *pSataChannel); +MV_BOOLEAN _isDeviceBsyBitOff(MV_SATA_CHANNEL *pSataChannel); +/******************************************************************************* +* waitWhileStorageDevIsBusy - Wait for the storage device to be released from +* busy state. +* +* DESCRIPTION: +* The busy bit is set to one to indicate that the storage device is busy. The +* busy bit shall be set to one by the device only when one of the following +* events occurs: +* +* 1) after either the negation of RESET- or the setting of the SRST bit to one +* in the Device Control register. +* 2) after writing the Command register if the DRQ bit is not set to one. +* 3) between blocks of a data transfer during PIO data-in commands before the +* DRQ bit is cleared to zero. +* 4) after the transfer of a data block during PIO data-out commands before +* the DRQ bit is cleared to zero. +* 5) during the data transfer of DMA commands either the BSY bit, the DRQ bit, +* or both shall be set to one. +* 6) after the command packet is received during the execution of a PACKET +* command. +* +* INPUT: +* ioBaseAddr - The PCI I/O window base address of the adapter. +* eDmaRegsOffset - The EDMA register's offset of the relevant SATA channel. +* loops - max number of times to pool the status register. +* delay - number of u seconds to wait each loop. +* +* RETURN: +* MV_TRUE if the device is released from busy state, MV_FALSE otherwise. +* COMMENTS: +* None. +* +*******************************************************************************/ +MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delayParam) +{ + MV_U8 ATAstatus = 0; + MV_U32 i; + + for (i = 0;i < loops; i++) + { + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) + { + + if ((ATAstatus & MV_ATA_ERROR_STATUS) == 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *" + "%d usecs\n", i, delayParam); + return MV_TRUE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy: Device ERROR" + " Status: 0x%02x\n", ATAstatus); + return MV_FALSE; + } + } + mvMicroSecondsDelay(pAdapter, delayParam); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "waitWhileStorageDevIsBusy: Time out - Device ERROR" + " Status: 0x%02x. loops %d, delay %d\n", ATAstatus, loops, delayParam); + + return MV_FALSE; +} + + +MV_BOOLEAN waitWhileStorageDevIsBusy_88SX60X1(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U8 channelIndex, + MV_U32 loops, + MV_U32 delayParam) +{ + MV_U8 ATAstatus = 0; + MV_U32 i,intReg; + MV_U8 sataUnit = channelIndex >> 2, portNum = (channelIndex & 0x3); + + + for (i = 0;i < loops; i++) + { + intReg = MV_REG_READ_DWORD (ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET); + + if (intReg & (1 << (8 + portNum))) + { + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + MV_REG_WRITE_DWORD (ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, + ~(1 << (8 + portNum))); + if ((ATAstatus & MV_ATA_ERROR_STATUS) == 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID,MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *" + "%d usecs\n", i, delayParam); + return MV_TRUE; + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID,MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy: Device ERROR" + " Status: 0x%02x\n", ATAstatus); + return MV_FALSE; + } + } + mvMicroSecondsDelay(pAdapter, delayParam); + } + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy: Time out - Device ERROR" + " Status: 0x%02x. loops %d, delay %d\n", ATAstatus, loops, delayParam); + return MV_FALSE; +} + +MV_BOOLEAN waitForDRQ(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delayParam) +{ + MV_U8 ATAstatus = 0; + MV_U32 i; + + for (i = 0;i < loops; i++) + { + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) + { + if (ATAstatus & MV_ATA_DATA_REQUEST_STATUS) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *" + "%d usecs\n", i, delayParam); + return MV_TRUE; + } + } + mvMicroSecondsDelay(pAdapter, delayParam); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, "waitWhileStorageDevIsBusy: Time out - Device ERROR" + " Status: 0x%02x. loops %d, delay %d\n", ATAstatus, loops, delayParam); + + return MV_FALSE; +} +/******************************************************************************* +* enableStorageDevInterrupt - Enable the storage device to be able to issue +* interrupt. +* +* DESCRIPTION: +* Enable the connected storage device to the given channel to assert INTRQ by +* clearing nIEN bit in the Device Control register. +* +* INPUT: +* pSataChannel - Pointer to the Sata channel data structure. +* +* RETURN: +* None. +* +* COMMENTS: +* this function also clears the SRST bit in the Device Control register. +* +*******************************************************************************/ +void enableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel) +{ + + MV_REG_WRITE_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET,0); + MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET); +} + +/******************************************************************************* +* disableStorageDevInterrupt - Disable the storage device to be able to issue +* interrupt. +* +* DESCRIPTION: +* This function disable the connected storage device to the given channel to +* assert INTRQ by setting nIEN bit in the Device Control register. +* +* INPUT: +* pSataChannel - Pointer to the Sata channel data structure. +* +* RETURN: +* None. +* +* COMMENTS: +* this function also clears the SRST bit +* +*******************************************************************************/ +void disableStorageDevInterrupt(MV_SATA_CHANNEL *pSataChannel) +{ + + + MV_REG_WRITE_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT1); + MV_REG_READ_BYTE(pSataChannel->mvSataAdapter->adapterIoBaseAddress, + pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); +} + +/******************************************************************************* +* isStorageDevReadyForPIO - Check that the storage device connected to the given +* channel and the channel itself are ready to perform +* PIO commands. +* +* DESCRIPTION: +* Check if the device connected to the given channel and the channel itself +* are ready for PIO commands. +* +* INPUT: +* pSataChannel - Pointer to the SATA channel data structure. +* +* RETURN: +* MV_TRUE if the channel and the connected device ready to do PIO, +* MV_FALSE otherwise. +* +* COMMENTS: +* If the adapter's eEnEDMA bit in the EDMA Command Register is set, PIO +* commands cannot be issued. The eEnEDMA bit cannot be reset by the CPU. +* Only the EDMA resets it, when bit eDsEDMA is set or when an error +* condition occurs. +* +*******************************************************************************/ +static MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr =pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + MV_U8 ATAcontrolRegValue; + + /* If the adapter's eEnEDMA bit in the EDMA Command Register is set */ + /* PIO commands cannot be issued. */ + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: PIO command failed:" + "EDMA is active\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_FALSE; + } + /* Check if BUSY bit is '0' */ + + /* Reading the Control register actually gives us the Alternate Status */ + /* register content (ATA protocol). If the busy bit is set in the */ + /* Alternate Status register, we wait for 50 mili-sec and try again, if */ + /* the busy bit is still set, we return false indicating that the */ + /* device is not ready for PIO commands. */ + ATAcontrolRegValue = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET); + if ((ATAcontrolRegValue & MV_ATA_BUSY_STATUS)!= 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: control regiser is " + "0x%02x\n",pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber,ATAcontrolRegValue); + return MV_FALSE; + } + if ( (pSataChannel->deviceType != MV_SATA_DEVICE_TYPE_ATAPI_DEVICE) && + ((ATAcontrolRegValue & MV_ATA_READY_STATUS) != MV_ATA_READY_STATUS)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: storage drive is not" + " ready, ATA STATUS=0x%02x\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAcontrolRegValue); + return MV_FALSE; + } + /* The device is ready for PIO commands */ + return MV_TRUE; +} + +MV_BOOLEAN mvStorageDevATAIdleImmediate(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 eDmaRegsOffset; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevATAIdentif" + "yDevice failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { /* If the pointer do not exists, retrun false */ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data " + "structure is not allocated\n", pAdapter->adapterId, + channelIndex); + return MV_FALSE; + } + + ioBaseAddr =pSataChannel->mvSataAdapter->adapterIoBaseAddress; + + mvOsSemTake(&pSataChannel->semaphore); + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvStorageDevATAIdle" + "Immediate command failed: EDMA is active\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "Issue IDLE IMMEDIATE COMMAND\n"); + disableStorageDevInterrupt(pSataChannel); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_COMMAND_REG_OFFSET, + MV_ATA_COMMAND_IDLE_IMMEDIATE); + + if (waitWhileStorageDevIsBusy(pAdapter, + ioBaseAddr, eDmaRegsOffset, 10000, 100) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: Idle Immediate failed\n", + pSataChannel->mvSataAdapter->adapterId, pSataChannel->channelNumber); + + enableStorageDevInterrupt(pSataChannel); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + + enableStorageDevInterrupt(pSataChannel); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvStorageDevATAIdentifyDevice - Perform an ATA IDENTIFY device command. +* +* DESCRIPTION: +* This function issues an IDENTIFY command to the connected device, and +* stores all the information in the identifyDevice buffer of the channel. +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - The index of the channel where the storage device +* connected to. +* PMPort - index of the required destination port multipliers +* device Port (0 if no PM available). +* identifyDeviceResult - a buffer that is allocated by IAL that will hold +* the IDENTIFY DEIVICE command result. +* +* RETURN: +* MV_TRUE on success, MV_FALSE on failure. +* +* COMMENTS: +* None. +* +*******************************************************************************/ +MV_BOOLEAN mvStorageDevATAIdentifyDevice(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_U16_PTR identifyDeviceResult + ) +{ + MV_BOOLEAN result; + /* Get the pointer to the relevant channel. */ + MV_SATA_CHANNEL *pSataChannel; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevATAIdentif" + "yDevice failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { /* If the pointer do not exists, retrun false */ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data " + "structure is not allocated\n", pAdapter->adapterId, + channelIndex); + return MV_FALSE; + } + if (identifyDeviceResult == NULL) + { /* If the pointer do not exists, retrun false */ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: identify data buffer" + " is not allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + result = mvStorageDevATAExecuteNonUDMACommand(pAdapter, channelIndex, + PMPort, + MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, + MV_FALSE, + /* pBuffer */ + identifyDeviceResult, + 256, /* count */ + 0, /* features */ + 0, /* sectorCount */ + 0, /* lbaLow */ + 0, /* lbaMid */ + 0, /* lbaHigh */ + 0, /* device */ + /* The command */ + MV_ATA_COMMAND_IDENTIFY); + if (result == MV_FALSE) + { + return MV_FALSE; + } + if (identifyDeviceResult[IDEN_ATA_VERSION] & (MV_BIT7 | MV_BIT6 | MV_BIT5)) + { + /* if ATA 5/6/7 then check CRC of Identify command result */ + MV_U8 crc = 0; + MV_U16 count; + MV_U8_PTR pointer = (MV_U8_PTR)identifyDeviceResult; + /* If no 0xa5 signature valid, then don't check CRC */ + if (pointer[510] != 0xa5) + { + return MV_TRUE; + } + for (count = 0 ; count < ATA_SECTOR_SIZE ; count ++) + { + crc += pointer[count]; + } + if (crc != 0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: IDENTIFY DEVICE " + "ATA Command failed due to wrong CRC checksum (%02x)\n", + pAdapter->adapterId, channelIndex,crc); + return MV_FALSE; + } + + } + return MV_TRUE; +} + +/******************************************************************************* +* mvStorageDevATASoftResetDevice - Issue SATA SOFTWARE reset to device. +* +* DESCRIPTION: +* Perform SOFTWARE RESET to the connected storage device by setting the +* SRST bit of the ATA device COMMAND +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel. +* PMPort - index of the required destination port multipliers +* device port (0 if no PM available). +* registerStruct - Pointer to ATA registers data structure +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvStorageDevATASoftResetDevice(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_STORAGE_DEVICE_REGISTERS *registerStruct + ) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_U32 eDmaRegsOffset; + MV_BOOLEAN result; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevATASoftRes" + "etDevice Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + ioBaseAddr = pAdapter->adapterIoBaseAddress; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data structu" + "re is not allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + mvOsSemTake(&pSataChannel->semaphore); + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvStorageDevATASoft" + "ResetDevice command failed: EDMA is active\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + _setActivePMPort(pSataChannel, PMPort); + result = _doSoftReset(pSataChannel); + if (registerStruct) + { + dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_FALSE, + registerStruct); + } + mvOsSemRelease( &pSataChannel->semaphore); + return result; +} + + + +void _startSoftResetDevice(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr = + pSataChannel->mvSataAdapter->adapterIoBaseAddress; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_NON_UDMA_COMMAND | MV_DEBUG, "Issue SRST COMMAND\n"); + +/* Write to the Device Control register, bits 1,2: */ +/* - bit 1 (nIEN): is the enable bit for the device assertion of INTRQ */ +/* to the host. When the nIEN bit is set to one, or the device is not */ +/* selected, the device shall release the INTRQ signal. */ +/* - bit 2 (SRST): is the host software reset bit. */ + MV_REG_WRITE_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT2|MV_BIT1); + MV_REG_READ_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET); + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 10); + /* enableStorageDevInterrupt will clear the SRST bit*/ + enableStorageDevInterrupt(pSataChannel); +} + +MV_BOOLEAN _isDeviceBsyBitOff(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr = + pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U8 ATAstatus; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) + { + return MV_TRUE; + } + else + { +#ifdef MV_LOGGER + if (pSataChannel->mvSataAdapter->sataAdapterGeneration >= + MV_SATA_GEN_II) + { + MV_U32 ifStatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_SATA_II_IF_STATUS_REG_OFFSET); + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "[%d %d] SATA interface status register = 0x%X\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, + ifStatus); + } +#endif + return MV_FALSE; + } +} + + +/******************************************************************************* +* mvStorageDevATAStartSoftResetDevice - +* begins device software reset +* +* DESCRIPTION: +* +* Submits SRST for channel connected device and exit. The IAL must call the +* mvStorageIsDeviceBsyBitOff later on to check whether the device is +* ready +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - channel number +* PMPort - port multiplier port +* +* OUTPUT: +* None +* RETURN: +* MV_TRUE on success, +* MV_FALSE otherwise. +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvStorageDevATAStartSoftResetDevice(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort + ) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevATASoftRes" + "etDevice Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + ioBaseAddr = pAdapter->adapterIoBaseAddress; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data structu" + "re is not allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvStorageDevATASoft" + "ResetDevice command failed: EDMA is active\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + _setActivePMPort(pSataChannel, PMPort); + _startSoftResetDevice(pSataChannel); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_TRUE; +} + +/******************************************************************************* +* mvStorageIsDeviceBsyBitOff - +* check if device is BUSY bit cleared after SRST +* +* DESCRIPTION: +* +* Checks the if BSY bit in ATA status is on/off +* +* INPUT: +* pAdapter - pointer to the adapter data structure. +* channelIndex - channel number +* registerStruct - If non-zero then this function dumps ATA registers +* to this data structure before exit. +* +* OUTPUT: +* None +* RETURN: +* MV_TRUE if BSY bit is off +* MV_FALSE if BSY bit is on (or on failure) +* COMMENTS: +* +*******************************************************************************/ +MV_BOOLEAN mvStorageIsDeviceBsyBitOff(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_STORAGE_DEVICE_REGISTERS *registerStruct + ) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BUS_ADDR_T ioBaseAddr; + MV_BOOLEAN result; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevATASoftRes" + "etDevice Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + ioBaseAddr = pAdapter->adapterIoBaseAddress; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data structu" + "re is not allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + mvOsSemTake(&pSataChannel->semaphore); + result = _isDeviceBsyBitOff(pSataChannel); + if (registerStruct) + { + dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_FALSE, + registerStruct); + } + mvOsSemRelease( &pSataChannel->semaphore); + return result; +} + + +/******************************************************************************* +* mvStorageDevATASetFeatures - Perform ATA SET FEATURES command. +* +* DESCRIPTION: +* Perform ATA SET FEATURES command to the ATA device connected to the +* given channel. This command is used by the host to establish parameters +* that affect the execution of certain device features (Table 44 in the +* ATA protocol document defines these features). +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* PMPort - index of the required destination port multipliers +* device Port (0 if no PM available). +* subCommand - Sub command for the SET FEATURES ATA command +* subCommandSpecific1 - First parameter to the sub command. +* subCommandSpecific2 - Second parameter to the sub command. +* subCommandSpecific3 - Third parameter to the sub command. +* subCommandSpecific4 - Fourth parameter to the sub command. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvStorageDevATASetFeatures(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_U8 subCommand, + MV_U8 subCommandSpecific1, + MV_U8 subCommandSpecific2, + MV_U8 subCommandSpecific3, + MV_U8 subCommandSpecific4) +{ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, + "ATA Set Features: %x , %x , %x , %x , %x\n", subCommand, + subCommandSpecific1, subCommandSpecific2, subCommandSpecific3, + subCommandSpecific4); + return mvStorageDevATAExecuteNonUDMACommand(pAdapter, channelIndex, + PMPort, + MV_NON_UDMA_PROTOCOL_NON_DATA, + MV_FALSE, + NULL, /* pBuffer*/ + 0, /* count */ + subCommand, /*features*/ + /* sectorCount */ + subCommandSpecific1, + subCommandSpecific2, /* lbaLow */ + subCommandSpecific3, /* lbaMid */ + /* lbaHigh */ + subCommandSpecific4, + 0, /* device */ + /* command */ + MV_ATA_COMMAND_SET_FEATURES); +} + + +/******************************************************************************* +* mvStorageDevATAExecuteNonUdmaCommand - perform ATA non udma command. +* +* DESCRIPTION: +* perform ATA non UDMA command to the ATA device connected to the given +* channel +* +* INPUT: +* pAdapter - pointer to the device data structure. +* channelIndex - index of the required channel +* PMPort - index of the required destination port multipliers +* device Port (0 if no PM available). +* protocolType - protocol type of the command +* isEXT - true when the given command is the EXTENDED +* bufPtr - pointer to the buffer to write/read to/from +* count - number of words to transfer +* features - the value to be written to the FEATURES register +* sectorCount - the value to be written to the SECTOR COUNT register +* lbaLow - the value to be written to the LBA LOW register +* lbaMid - the value to be written to the LBA MID register +* lbaHigh - the value to be written to the LBA HIGH register +* device - the value to be written to the DEVICE register +* command - the value to be written to the COMMAND register +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* when the command is EXTENDED, then the high 8 bits of the 16 bits values +* will be written first, so they should hold the previous value as defined in +* the ATA 6 standard +* +*******************************************************************************/ +MV_BOOLEAN mvStorageDevATAExecuteNonUDMACommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_NON_UDMA_PROTOCOL protocolType, + MV_BOOLEAN isEXT, + MV_U16_PTR bufPtr, MV_U32 count, + MV_U16 features, + MV_U16 sectorCount, + MV_U16 lbaLow, MV_U16 lbaMid, + MV_U16 lbaHigh, MV_U8 device, + MV_U8 command) +{ + MV_BOOLEAN result; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevATAExecute" + "NonUDMACommand Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + if (pAdapter->sataChannel[channelIndex] == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvStorageDevATAExecu" + "teNonUDMACommand Failed, channel data structure not allocated" + "\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + mvOsSemTake(&pAdapter->sataChannel[channelIndex]->semaphore); + result = executeNonUDMACommand(pAdapter, channelIndex, PMPort, protocolType, + isEXT, bufPtr, count, features, sectorCount, + lbaLow, lbaMid, lbaHigh, device, command); + mvOsSemRelease(&pAdapter->sataChannel[channelIndex]->semaphore); + return result; +} +#if 0 +MV_BOOLEAN executePacketCommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_NON_UDMA_PROTOCOL protocolType, + MV_U8 PMPort, + MV_U16_PTR cdb, + MV_U8 cdb_len, + MV_U16_PTR dataBufPtr + ) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset; + MV_U32 i; + MV_U32 count; + MV_U8 ATAstatus; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, " %d %d send PACKET " + " command: protocol(%d) cdb %p cdb len %p buffer %p \n", pAdapter->adapterId, + channelIndex, protocolType, cdb, cdb_len, dataBufPtr); + + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + if ((PMPort) && ((pSataChannel->PMSupported == MV_FALSE) || + (pSataChannel->deviceType != MV_SATA_DEVICE_TYPE_PM))) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: executePacketCommand" + " failed PM not supported for this channel\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + { + if (isStorageDevReadyForPIO(pSataChannel) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d : Error in Issue NON UDMA command:" + " isStorageDevReadyForPIO failed\n", + pAdapter->adapterId, channelIndex); + + return MV_FALSE; + } + } + _setActivePMPort(pSataChannel, PMPort); + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: PIO command failed:" + "EDMA is active\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_FALSE; + } + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + disableStorageDevInterrupt(pSataChannel); + } + + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_FEATURES_REG_OFFSET, 0); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, 0); + + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, 0); + + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, 0); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, 0x20); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_HEAD_REG_OFFSET, 0); + MV_CPU_WRITE_BUFFER_FLUSH(); + + /* 88SX60X1 FEr SATA #16 */ + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + enableStorageDevInterrupt(pSataChannel); + } + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_COMMAND_REG_OFFSET,MV_ATA_COMMAND_PACKET ); + + /* Wait for PIO Setup or completion*/ + if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 3100, 10000) == + MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + if (protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_NON_DATA) + { + enableStorageDevInterrupt(pSataChannel); + pSataChannel->recoveredErrorsCounter = 0; + return MV_TRUE; + } + + + /* Check the status register on DATA request commands */ + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS" + " register is not set\n", pAdapter->adapterId, channelIndex); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + + if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000) + == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS" + " register is not set\n", pAdapter->adapterId, channelIndex); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + for (i = 0; i < cdb_len; i++) + { + MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, cdb[i]); + MV_CPU_WRITE_BUFFER_FLUSH(); + } + + if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000) + == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS" + " register is not set\n", pAdapter->adapterId, channelIndex); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " Status: %x\n", + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET)); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " Sector Count: %x\n", + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET)); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " LBA Mid: %x\n", + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET)); + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " LBA High: %x\n", + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET)); + + count = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) + + (MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 8); + count >>= 1; + for ( i = 0 ; i < count; i++) + { + if(protocolType == MV_NON_UDMA_PROTOCOL_PACKET_PIO_DATA_IN) + { + dataBufPtr[i] = MV_REG_READ_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET); + } + else + { + MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, dataBufPtr[i]); + + } + } + + /* Wait for the storage device to be available */ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: on non-UDMA sequence - checking if" + " device is has finished the command\n", + pAdapter->adapterId, channelIndex); + + if (waitWhileStorageDevIsBusy(pAdapter, + ioBaseAddr, eDmaRegsOffset, 50000, 100) == + MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " Status: %x\n", + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET)); + + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + + if (waitForDRQToClear(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100) + == MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Finish NonUdma Command. Status=0x%02x" + "\n", pAdapter->adapterId, channelIndex, + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET)); + enableStorageDevInterrupt(pSataChannel); + pSataChannel->recoveredErrorsCounter = 0; + return MV_TRUE; +} +#endif /* 0 */ +MV_BOOLEAN executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_NON_UDMA_PROTOCOL protocolType, + MV_BOOLEAN isEXT, + MV_U16_PTR bufPtr, MV_U32 count, + MV_U16 features, + MV_U16 sectorCount, + MV_U16 lbaLow, MV_U16 lbaMid, + MV_U16 lbaHigh, MV_U8 device, + MV_U8 command) +{ + MV_SATA_CHANNEL *pSataChannel = pAdapter->sataChannel[channelIndex]; + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset; + MV_U32 i; + MV_U8 ATAstatus; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND, " %d %d Issue NON " + "UDMA command: protocol(%d) %p , %x , %x , %x , %x.%x.%x %x " + "command=%x\n", pAdapter->adapterId, channelIndex, protocolType, + bufPtr, count, features, sectorCount, lbaLow, lbaMid, + lbaHigh, device, command); + + eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + if ((PMPort) && ((pSataChannel->PMSupported == MV_FALSE) || + (pSataChannel->deviceType != MV_SATA_DEVICE_TYPE_PM))) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: executeNonUDMACommand" + " failed PM not supported for this channel\n", + pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + if (command != MV_ATA_COMMAND_PM_READ_REG && + command != MV_ATA_COMMAND_PM_WRITE_REG) + { + if (isStorageDevReadyForPIO(pSataChannel) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d : Error in Issue NON UDMA command:" + " isStorageDevReadyForPIO failed\n", + pAdapter->adapterId, channelIndex); + + return MV_FALSE; + } + } + _setActivePMPort(pSataChannel, PMPort); + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: PIO command failed:" + "EDMA is active\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber); + return MV_FALSE; + } + + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + disableStorageDevInterrupt(pSataChannel); + } + + if (isEXT == MV_TRUE) + { + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_FEATURES_REG_OFFSET, + (features & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, + (sectorCount & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, + (lbaLow & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, + (lbaMid & 0xff00) >> 8); + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, + (lbaHigh & 0xff00) >> 8); + } + else + { + if ((features & 0xff00) || (sectorCount & 0xff00) || (lbaLow & 0xff00) || + (lbaMid & 0xff00) || (lbaHigh & 0xff00)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + " %d %d : Error in Issue NON UDMA command:" + " bits[15:8] of register values should be reserved" + " Features 0x%02x, SectorCount 0x%02x, LBA Low 0x%02x," + " LBA Mid 0x%02x, LBA High 0x%02x\n", + pAdapter->adapterId, channelIndex, features, + sectorCount, lbaLow, lbaMid, lbaHigh); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_FEATURES_REG_OFFSET, features & 0xff); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET, sectorCount & 0xff); + + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET, lbaLow & 0xff); + + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET, lbaMid & 0xff); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET, lbaHigh & 0xff); + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_HEAD_REG_OFFSET, device); + MV_CPU_WRITE_BUFFER_FLUSH(); + + /* 88SX60X1 FEr SATA #16 */ + /* 88SX6042/88SX7042 FEr SATA #16 */ + /* 88F5182 FEr #SATA-S11 */ + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + enableStorageDevInterrupt(pSataChannel); + } + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_COMMAND_REG_OFFSET, command); + + if (protocolType == MV_NON_UDMA_PROTOCOL_NON_DATA) + { + /* Wait for the command to complete */ + if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 3100, 10000) == + MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + enableStorageDevInterrupt(pSataChannel); + pSataChannel->recoveredErrorsCounter = 0; + return MV_TRUE; + } + /* Wait for the command to complete */ + if (waitWhileStorageDevIsBusy(pAdapter, ioBaseAddr, eDmaRegsOffset, 3100, 10000) == + MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + /* Check the status register on DATA request commands */ + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS" + " register is not set\n", pAdapter->adapterId, channelIndex); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + + if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 500, 10000) + == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: DRQ bit in ATA STATUS" + " register is not set\n", pAdapter->adapterId, channelIndex); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + for (i = 0; i < count; i++) + { + /* Every DRQ data block we have to check the BUSY bit to verify that + the Disk is ready for next block transfer */ + if ((i & (((MV_U32)pSataChannel->DRQDataBlockSize * ATA_SECTOR_SIZE_IN_WORDS) - 1)) == 0) + { + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + /* Perform a dummy read */ + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_ALTERNATE_REG_OFFSET); + /* 88SX60X1 FEr SATA #16 */ + /* 88SX6042/88SX7042 FEr SATA #16 */ + /* 88F5182 FEr #SATA-S11 */ + if (i != 0) + { + if (waitWhileStorageDevIsBusy_88SX60X1(pAdapter, + ioBaseAddr, eDmaRegsOffset, channelIndex, + 50000, 100) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "Sata device interrupt timeout...i = %d\n",i); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + else + { + MV_U8 sataUnit = channelIndex >> 2,portNum = channelIndex & 3; + + if (waitWhileStorageDevIsBusy(pAdapter,ioBaseAddr, + eDmaRegsOffset, 50000, 100) == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "Busy bit timeout...i = %d\n",i); + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + MV_REG_WRITE_DWORD (ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) + + MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, + ~(1 << (8 + portNum))); + } + if (waitForDRQ(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100) + == MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + else if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) + { + if (waitWhileStorageDevIsBusy(pAdapter, + ioBaseAddr, eDmaRegsOffset, + 50000, 100) == MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + } + if (protocolType == MV_NON_UDMA_PROTOCOL_PIO_DATA_IN) + { + bufPtr[i] = MV_REG_READ_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET); + } + else + { + MV_REG_WRITE_WORD(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_PIO_DATA_REG_OFFSET, bufPtr[i]); + MV_CPU_WRITE_BUFFER_FLUSH(); + } +//Patch by QNAP:fix SATA DOM issue + udelay(1000); +//////////////////////////////////// + } + + + /* Wait for the storage device to be available */ + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: on non-UDMA sequence - checking if" + " device is has finished the command\n", + pAdapter->adapterId, channelIndex); + + if (waitWhileStorageDevIsBusy(pAdapter, + ioBaseAddr, eDmaRegsOffset, 50000, 100) == + MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + + if (pAdapter->sataAdapterGeneration >= MV_SATA_GEN_II) + { + + if (waitForDRQToClear(pAdapter, ioBaseAddr, eDmaRegsOffset, 50000, 100) + == MV_FALSE) + { + enableStorageDevInterrupt(pSataChannel); + return MV_FALSE; + } + } + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, " %d %d: Finish NonUdma Command. Status=0x%02x" + "\n", pAdapter->adapterId, channelIndex, + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET)); + enableStorageDevInterrupt(pSataChannel); + pSataChannel->recoveredErrorsCounter = 0; + return MV_TRUE; +} +MV_BOOLEAN _PMAccessReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue, + MV_STORAGE_DEVICE_REGISTERS *registerStruct, + MV_BOOLEAN isRead) +{ + MV_BOOLEAN result; + + if (isRead == MV_TRUE) + { + result = executeNonUDMACommand(pAdapter, channelIndex, + MV_SATA_PM_CONTROL_PORT, + MV_NON_UDMA_PROTOCOL_NON_DATA, + MV_TRUE/*isEXT*/, + NULL/*bufPtr*/, + 0/*count*/, + PMReg /*features*/, 0/*sectorCount*/, + 0 /*lbaLow*/, 0 /*lbaMid*/, 0 /*lbaHigh*/, + PMPort/*device*/, + MV_ATA_COMMAND_PM_READ_REG/*command*/); + if (result == MV_TRUE) + { + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pAdapter->sataChannel[channelIndex]->eDmaRegsOffset; + + *pValue = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET); + *pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) << 8; + *pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) << 16; + *pValue |= MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 24; + } + } + else + { + result = executeNonUDMACommand(pAdapter, channelIndex, + MV_SATA_PM_CONTROL_PORT, + MV_NON_UDMA_PROTOCOL_NON_DATA, + MV_TRUE/*isEXT*/, + NULL/*bufPtr*/, + 0/*count*/, + PMReg /*features*/, + (MV_U16)((*pValue) & 0xff)/*sectorCount*/, + (MV_U16)(((*pValue) & 0xff00) >> 8) /*lbaLow*/, + (MV_U16)(((*pValue) & 0xff0000) >> 16) /*lbaMid*/, + (MV_U16)(((*pValue) & 0xff000000) >> 24) /*lbaHigh*/, + PMPort/*device*/, + MV_ATA_COMMAND_PM_WRITE_REG/*command*/); + } + if (registerStruct) + { + dumpAtaDeviceRegisters(pAdapter, channelIndex, MV_FALSE, + registerStruct); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_PM, " %d %d: %s PM Reg %s: PM Port %x" + ", PM Reg %d, value %x\n", pAdapter->adapterId, channelIndex, + (isRead == MV_TRUE) ? "Read" : "Write", + (result == MV_TRUE) ? "Succeeded" : "Failed", + PMPort, PMReg, *pValue); + + return result; +} + +MV_BOOLEAN waitForDRQToClear(MV_SATA_ADAPTER* pAdapter, + MV_BUS_ADDR_T ioBaseAddr, + MV_U32 eDmaRegsOffset, MV_U32 loops, + MV_U32 delayParam) +{ + MV_U8 ATAstatus = 0; + MV_U32 i; + + for (i = 0;i < loops; i++) + { + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) + { + if (!(ATAstatus & MV_ATA_DATA_REQUEST_STATUS)) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "waitWhileStorageDevIsBusy: %d loops *" + "%d usecs\n", i, delayParam); + return MV_TRUE; + } + } + mvMicroSecondsDelay(pAdapter, delayParam); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "waitWhileStorageDevIsBusy: Time out - Device ERROR" + " Status: 0x%02x. loops %d, delay %d\n", ATAstatus, loops, delayParam); + + return MV_FALSE; +} + +void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_BOOLEAN isEXT, + MV_STORAGE_DEVICE_REGISTERS *pRegisters) +{ + MV_BUS_ADDR_T ioBaseAddr = pAdapter->adapterIoBaseAddress; + MV_U32 eDmaRegsOffset = pAdapter->sataChannel[channelIndex]->eDmaRegsOffset; + + if (pAdapter->sataAdapterGeneration < MV_SATA_GEN_IIE) + { + if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset + + MV_EDMA_COMMAND_REG_OFFSET) & MV_BIT0) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, + " %d %d: dumpAtaDeviceRegisters: Edma is active!!!\n", + pAdapter->adapterId, channelIndex); + return; + } + } + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET, 0); + + pRegisters->errorRegister = + MV_REG_READ_BYTE(ioBaseAddr, + eDmaRegsOffset + MV_ATA_DEVICE_ERROR_REG_OFFSET); + + pRegisters->sectorCountRegister = + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET) & 0x00ff; + pRegisters->lbaLowRegister = + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) & 0x00ff; + + pRegisters->lbaMidRegister = + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) & 0x00ff; + + pRegisters->lbaHighRegister = + MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) & 0x00ff; + + if (isEXT == MV_TRUE) + { + /*set the HOB bit of DEVICE CONTROL REGISTER */ + + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT7); + + pRegisters->sectorCountRegister |= (MV_REG_READ_BYTE(ioBaseAddr, + eDmaRegsOffset + + MV_ATA_DEVICE_SECTOR_COUNT_REG_OFFSET) << 8) & 0xff00; + + pRegisters->lbaLowRegister |= (MV_REG_READ_BYTE(ioBaseAddr, + eDmaRegsOffset + MV_ATA_DEVICE_LBA_LOW_REG_OFFSET) << 8) + & 0xff00; + + pRegisters->lbaMidRegister |= (MV_REG_READ_BYTE(ioBaseAddr, + eDmaRegsOffset + MV_ATA_DEVICE_LBA_MID_REG_OFFSET) << 8) + & 0xff00; + + pRegisters->lbaHighRegister |= (MV_REG_READ_BYTE(ioBaseAddr, + eDmaRegsOffset + MV_ATA_DEVICE_LBA_HIGH_REG_OFFSET) << 8) + & 0xff00; + MV_REG_WRITE_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET, 0); + + } + + pRegisters->deviceRegister = MV_REG_READ_BYTE(ioBaseAddr, + eDmaRegsOffset + MV_ATA_DEVICE_HEAD_REG_OFFSET); + + pRegisters->statusRegister = MV_REG_READ_BYTE(ioBaseAddr, + eDmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET); + + +} + + +MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel) +{ + MV_BUS_ADDR_T ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress; + MV_U32 i; + MV_U8 ATAstatus; + MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_NON_UDMA_COMMAND | MV_DEBUG, "Issue SRST COMMAND\n"); + +/* Write to the Device Control register, bits 1,2: */ +/* - bit 1 (nIEN): is the enable bit for the device assertion of INTRQ */ +/* to the host. When the nIEN bit is set to one, or the device is not */ +/* selected, the device shall release the INTRQ signal. */ +/* - bit 2 (SRST): is the host software reset bit. */ + MV_REG_WRITE_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET, MV_BIT2|MV_BIT1); + MV_REG_READ_BYTE(ioBaseAddr, pSataChannel->eDmaRegsOffset + + MV_ATA_DEVICE_CONTROL_REG_OFFSET); + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 10); + +/* enableStorageDevInterrupt will clear the SRST bit*/ + enableStorageDevInterrupt(pSataChannel); + + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500); + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500); + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500); + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 500); + + for (i = 0;i < 31000; i++) + { + ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset + + MV_ATA_DEVICE_STATUS_REG_OFFSET); + if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0) + { + return MV_TRUE; + } + mvMicroSecondsDelay(pSataChannel->mvSataAdapter, 1000); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: Software reset failed " + "Status=0x%02x\n", pSataChannel->mvSataAdapter->adapterId, + pSataChannel->channelNumber, ATAstatus); + + return MV_FALSE; +} + +/******************************************************************************* +* mvPMDevReadReg - Reads port multiplier's internal register +* +* +* DESCRIPTION: +* Performs PIO non-data command for reading port multiplier's internal +* register. +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* PMPort - This should be port 0xf +* PMReg - The required register to be read +* pValue - A pointer to 32bit data container that holds +* the result. +* registerStruct - A pointer to ATA register data structure. This +* holds the ATA registers dump after command +* is executed. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvPMDevReadReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue, + MV_STORAGE_DEVICE_REGISTERS *registerStruct) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BOOLEAN result; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevPMReadReg" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data structu" + "re is not allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->PMSupported == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvStorageDevPMReadReg" + " failed PM not supported for this channel\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvStorageDevPMReadReg" + " command failed: EDMA is active\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + + result = _PMAccessReg(pAdapter, channelIndex, PMPort, PMReg, pValue, + registerStruct, MV_TRUE); + + mvOsSemRelease( &pSataChannel->semaphore); + return result; +} + + + +/******************************************************************************* +* mvPMDevWriteReg - Writes to port multiplier's internal register +* +* +* DESCRIPTION: +* Performs PIO non-data command for writing to port multiplier's internal +* register. +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* PMPort - This should be port 0xf +* PMReg - The required register to be read +* value - Holds 32bit of the value to be written +* registerStruct - A pointer to ATA register data structure. This +* holds the ATA registers dump after command +* is executed. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvPMDevWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_U8 PMPort, MV_U8 PMReg, MV_U32 value, + MV_STORAGE_DEVICE_REGISTERS *registerStruct) +{ + MV_SATA_CHANNEL *pSataChannel; + MV_BOOLEAN result; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvStorageDevPMWriteReg" + " Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data structu" + "re is not allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + mvOsSemTake(&pSataChannel->semaphore); + if (pSataChannel->PMSupported == MV_FALSE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvStorageDevPMWriteReg" + " failed PM not supported for this channel\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + if (pSataChannel->queueCommandsEnabled == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: mvStorageDevPMWriteReg" + " command failed: EDMA is active\n", + pAdapter->adapterId, channelIndex); + mvOsSemRelease( &pSataChannel->semaphore); + return MV_FALSE; + } + + result = _PMAccessReg(pAdapter, channelIndex, PMPort, PMReg, &value, + registerStruct, MV_FALSE); + + mvOsSemRelease( &pSataChannel->semaphore); + return result; +} + +static MV_BOOLEAN _checkPMPortSStatus(MV_SATA_ADAPTER* pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_BOOLEAN *error) +{ + MV_BOOLEAN result; + MV_U32 SStatus; + + result = mvPMDevReadReg(pAdapter, channelIndex, PMPort, + MV_SATA_PSCR_SSTATUS_REG_NUM, &SStatus, NULL); + + if (result == MV_FALSE) + { + *error = MV_TRUE; + return result; + } + *error = MV_FALSE; + SStatus &= (MV_BIT0 | MV_BIT1 | MV_BIT2); + if ((SStatus == (MV_BIT0 | MV_BIT1)) || (SStatus == 0)) + { + return MV_TRUE; + } + return MV_FALSE; +} + +MV_BOOLEAN mvPMLinkUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort, + MV_BOOLEAN force_gen1) +{ + MV_BOOLEAN result; + MV_U32 speed_force = 0; + + if(force_gen1 == MV_TRUE) + speed_force = 0x10; + + result = mvPMDevWriteReg(pAdapter, channelIndex, PMPort, + MV_SATA_PSCR_SCONTROL_REG_NUM, 0x301 | speed_force, NULL); + if (result == MV_FALSE) + { + return result; + } + mvMicroSecondsDelay(pAdapter, MV_SATA_COMM_INIT_DELAY); + result = mvPMDevWriteReg(pAdapter, channelIndex, PMPort, + MV_SATA_PSCR_SCONTROL_REG_NUM, 0x300 | speed_force, NULL); + return result; +} + +/******************************************************************************* +* mvPMDevEnableStaggeredSpinUp - +* +* +* DESCRIPTION: +* Enables commnucation on a port multiplier's device SATA channel +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* PMPort - Required device SATA channel on port multiplier +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvPMDevEnableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_U8 PMPort) +{ + return mvPMLinkUp(pAdapter, channelIndex, PMPort, MV_FALSE); +} + + +/******************************************************************************* +* mvPMDevEnableStaggeredSpinUpAll - +* +* +* DESCRIPTION: +* Enables commnucation on all port multiplier's device SATA channels +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* PMNumOfPorts - Number of device SATA channel the port multiplier +* has. +* bitmask - A pointer to 16bit data container that holds +* a bitmask of '1' when the relevant port multiplier's +* device port staggered spinup operation is success. +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ + +MV_BOOLEAN mvPMDevEnableStaggeredSpinUpAll(MV_SATA_ADAPTER *pSataAdapter, + MV_U8 channelIndex, + MV_U8 PMNumOfPorts, + MV_U16 *bitmask) +{ + MV_U8 PMPort; + MV_U8 retryCount; + MV_U8 tmpBitmask = 1; + if (bitmask == NULL) + { + return MV_FALSE; + } + /*Do not issue staggered spinup for port 0 - already done because of + legacy port mode*/ + *bitmask = 1; + for (PMPort = 0; PMPort < PMNumOfPorts; PMPort++) + { + MV_BOOLEAN error; + /* if sata communication already done(No staggered spin-up)*/ + if (_checkPMPortSStatus(pSataAdapter, channelIndex, PMPort, &error) == + MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "[%d %d %d]: sata communication already established.\n", + pSataAdapter->adapterId, channelIndex, PMPort); + tmpBitmask |= (1 << PMPort); + continue; + } + if (mvPMDevEnableStaggeredSpinUp(pSataAdapter, + channelIndex, + PMPort) == MV_TRUE) + { + tmpBitmask |= (1 << PMPort); + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "Error [%d %d %d]: " + "PM enable staggered spin-up failed.\n", + pSataAdapter->adapterId, channelIndex, PMPort); + return MV_FALSE; + } + } + mvMicroSecondsDelay(pSataAdapter, MV_SATA_COMM_INIT_WAIT_DELAY); + for (retryCount = 0; retryCount < 200; retryCount++) + { + for (PMPort = 0; PMPort < PMNumOfPorts; PMPort++) + { + MV_BOOLEAN error; + if ((*bitmask) & (1 << PMPort)) + { + continue; + } + if (_checkPMPortSStatus(pSataAdapter, + channelIndex, PMPort, &error) == MV_FALSE) + { + if (error == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "[%d %d %d]: " + "Fatal error - cannot read PM port SStatus.\n", + pSataAdapter->adapterId, channelIndex, PMPort); + break; + } + mvMicroSecondsDelay(pSataAdapter, 1000); + } + else + { + if (bitmask != NULL) + { + *bitmask |= (1 << PMPort); + } + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "[%d %d %d] PM SATA PHY ready after %d msec\n", + pSataAdapter->adapterId, channelIndex, + PMPort, retryCount); + } + } + if (tmpBitmask == *bitmask) + { + break; + } + } + if (tmpBitmask != *bitmask) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "[%d %d %d]: " + "Some of PM ports PHY are not initialized.\n", + pSataAdapter->adapterId, channelIndex, PMPort); + + } + return MV_TRUE; +} + +/******************************************************************************* +* mvPMDevEnableStaggeredSpinUpPort - +* +* +* DESCRIPTION: +* Enables commnucation on port multiplier's device SATA port +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* PMPort - the port number +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvPMDevEnableStaggeredSpinUpPort(MV_SATA_ADAPTER *pSataAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_BOOLEAN force_speed_gen1) + +{ + MV_U8 retryCount; + + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "[%d %d %d]: init sata communication.\n", + pSataAdapter->adapterId, channelIndex, PMPort); + + if (mvPMLinkUp(pSataAdapter, channelIndex, PMPort, + force_speed_gen1) != MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "Error [%d %d %d]: " + "PM enable staggered spin-up failed.\n", + pSataAdapter->adapterId, channelIndex, PMPort); + return MV_FALSE; + } + mvMicroSecondsDelay(pSataAdapter, MV_SATA_COMM_INIT_WAIT_DELAY); + for (retryCount = 0; retryCount < 200; retryCount++) + { + MV_BOOLEAN error; + + if (_checkPMPortSStatus(pSataAdapter, + channelIndex, PMPort, &error) == MV_FALSE) + { + if (error == MV_TRUE) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, + "[%d %d %d]: " + "Fatal error - cannot read PM port SStatus.\n", + pSataAdapter->adapterId, channelIndex, PMPort); + return MV_FALSE; + } + mvMicroSecondsDelay(pSataAdapter, 1000); + } + else + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, + "[%d %d %d] PM SATA PHY ready after %d msec\n", + pSataAdapter->adapterId, channelIndex, + PMPort, retryCount); + break; + } + + } + + return MV_TRUE; +} + +/******************************************************************************* +* mvStorageDevExecutePIO - +* +* +* DESCRIPTION: +* Sends custom PIO command (polling driven) +* +* INPUT: +* pAdapter - pointer to the device data structure. +* channelIndex - index of the required channel +* PMPort - index of the required destination port multipliers +* device Port (0 if no PM available). +* protocolType - protocol type of the command +* isEXT - true when the given command is the EXTENDED +* bufPtr - pointer to the buffer to write/read to/from +* pInATARegs - Holds ATA registers for the command +* pOutATARegs - Holds ATA registers after the command completed +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* when the command is EXTENDED, then the high 8 bits of the 16 bits values +* will be written first, so they should hold the previous value as defined in +* the ATA 6 standard +*******************************************************************************/ +MV_BOOLEAN mvStorageDevExecutePIO(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_NON_UDMA_PROTOCOL protocolType, + MV_BOOLEAN isEXT, MV_U16_PTR bufPtr, + MV_U32 count, + MV_STORAGE_DEVICE_REGISTERS *pInATARegs, + MV_STORAGE_DEVICE_REGISTERS *pOutATARegs) +{ + MV_BOOLEAN result; + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : mvPMDevExecutePIO" + "Command Failed, Bad adapter data structure pointer\n"); + return MV_FALSE; + } + if (pAdapter->sataChannel[channelIndex] == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: mvPMDevExecutePIO" + "Command Failed, channel data structure not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + mvOsSemTake(&pAdapter->sataChannel[channelIndex]->semaphore); + result = executeNonUDMACommand(pAdapter, channelIndex, PMPort, + protocolType, isEXT, + bufPtr, count, pInATARegs->featuresRegister, + pInATARegs->sectorCountRegister, + pInATARegs->lbaLowRegister, + pInATARegs->lbaMidRegister, + pInATARegs->lbaHighRegister, + pInATARegs->deviceRegister, + pInATARegs->commandRegister); + if (pOutATARegs) + { + dumpAtaDeviceRegisters(pAdapter, channelIndex, isEXT, pOutATARegs); + } + mvOsSemRelease(&pAdapter->sataChannel[channelIndex]->semaphore); + return result; +} + +/******************************************************************************* +* mvStorageDevSetDeviceType - +* +* +* DESCRIPTION: +* Sets the device type connected directly to the specific adapter's +* SATA channel. +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* deviceType - Type of device +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_BOOLEAN mvStorageDevSetDeviceType(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_SATA_DEVICE_TYPE deviceType) +{ + MV_SATA_CHANNEL *pSataChannel; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + " mvStorageDevSetDeviceType Failed, Bad adapter data structure " + "pointer\n"); + return MV_SATA_DEVICE_TYPE_UNKNOWN; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: channel data structu" + "re is not allocated\n", pAdapter->adapterId, channelIndex); + return MV_FALSE; + } + + pSataChannel->deviceType = deviceType; + + return MV_TRUE; +} + +/******************************************************************************* +* mvStorageDevGetDeviceType - +* +* +* DESCRIPTION: +* Gets the device type connected directly to the specific adapter's +* SATA channel. +* +* INPUT: +* pAdapter - Pointer to the device data structure. +* channelIndex - Index of the required channel +* +* RETURN: +* MV_TRUE on success, MV_FALSE otherwise. +* COMMENTS: +* NONE +* +*******************************************************************************/ +MV_SATA_DEVICE_TYPE mvStorageDevGetDeviceType(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex) +{ + MV_SATA_CHANNEL *pSataChannel; + + if (pAdapter == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " : " + " mvStorageDevGetDeviceType Failed, Bad adapter data structure " + "pointer\n"); + return MV_SATA_DEVICE_TYPE_UNKNOWN; + } + pSataChannel = pAdapter->sataChannel[channelIndex]; + if (pSataChannel == NULL) + { + mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_FATAL_ERROR, " %d %d: " + "channel data structure is not allocated\n", + pAdapter->adapterId, channelIndex); + return MV_SATA_DEVICE_TYPE_UNKNOWN; + } + + return pSataChannel->deviceType; +} + diff --git a/board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.h b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.h new file mode 100644 index 0000000..44e3d71 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sata/CoreDriver/mvStorageDev.h @@ -0,0 +1,355 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/******************************************************************************* +* mvStorageDev.h - Header File for mvStorageDev.c. +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* mvSata.h. +* mvOs.h. +* ATA/ATAPI-6 standard +* +*******************************************************************************/ +#ifndef __INCmvStorageDevh +#define __INCmvStorageDevh +#ifdef __cplusplus + +extern "C" { +#endif /* __cplusplus */ + +/* Includes */ +#include "mvOsS.h" +#include "mvSata.h" +#include "mvRegs.h" + +/* Definitions */ + +/* ATA register on the ATA drive*/ + +#define MV_EDMA_ATA_FEATURES_ADDR 0x11 +#define MV_EDMA_ATA_SECTOR_COUNT_ADDR 0x12 +#define MV_EDMA_ATA_LBA_LOW_ADDR 0x13 +#define MV_EDMA_ATA_LBA_MID_ADDR 0x14 +#define MV_EDMA_ATA_LBA_HIGH_ADDR 0x15 +#define MV_EDMA_ATA_DEVICE_ADDR 0x16 +#define MV_EDMA_ATA_COMMAND_ADDR 0x17 + +#define MV_ATA_ERROR_STATUS MV_BIT0 +#define MV_ATA_DATA_REQUEST_STATUS MV_BIT3 +#define MV_ATA_SERVICE_STATUS MV_BIT4 +#define MV_ATA_DEVICE_FAULT_STATUS MV_BIT5 +#define MV_ATA_READY_STATUS MV_BIT6 +#define MV_ATA_BUSY_STATUS MV_BIT7 + + +#define MV_ATA_COMMAND_READ_SECTORS 0x20 +#define MV_ATA_COMMAND_READ_SECTORS_EXT 0x24 +#define MV_ATA_COMMAND_READ_LOG_EXT 0x2F +#define MV_ATA_COMMAND_READ_VERIFY_SECTORS 0x40 +#define MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT 0x42 +#define MV_ATA_COMMAND_READ_BUFFER 0xE4 +#define MV_ATA_COMMAND_WRITE_BUFFER 0xE8 +#define MV_ATA_COMMAND_WRITE_SECTORS 0x30 +#define MV_ATA_COMMAND_WRITE_SECTORS_EXT 0x34 +#define MV_ATA_COMMAND_DIAGNOSTIC 0x90 +#define MV_ATA_COMMAND_SMART 0xb0 +#define MV_ATA_COMMAND_READ_MULTIPLE 0xc4 +#define MV_ATA_COMMAND_WRITE_MULTIPLE 0xc5 +#define MV_ATA_COMMAND_STANDBY_IMMEDIATE 0xe0 +#define MV_ATA_COMMAND_IDLE_IMMEDIATE 0xe1 +#define MV_ATA_COMMAND_STANDBY 0xe2 +#define MV_ATA_COMMAND_IDLE 0xe3 +#define MV_ATA_COMMAND_SLEEP 0xe6 +#define MV_ATA_COMMAND_IDENTIFY 0xec +#define MV_ATA_COMMAND_ATAPI_IDENTIFY 0xa1 +#define MV_ATA_COMMAND_PACKET 0xa0 +#define MV_ATA_COMMAND_DEVICE_CONFIG 0xb1 +#define MV_ATA_COMMAND_SET_FEATURES 0xef +#define MV_ATA_COMMAND_WRITE_DMA 0xca +#define MV_ATA_COMMAND_WRITE_DMA_EXT 0x35 +#define MV_ATA_COMMAND_WRITE_DMA_QUEUED 0xcc +#define MV_ATA_COMMAND_WRITE_DMA_QUEUED_EXT 0x36 +#define MV_ATA_COMMAND_WRITE_FPDMA_QUEUED_EXT 0x61 +#define MV_ATA_COMMAND_READ_DMA 0xc8 +#define MV_ATA_COMMAND_READ_DMA_EXT 0x25 +#define MV_ATA_COMMAND_READ_DMA_QUEUED 0xc7 +#define MV_ATA_COMMAND_READ_DMA_QUEUED_EXT 0x26 +#define MV_ATA_COMMAND_READ_FPDMA_QUEUED_EXT 0x60 +#define MV_ATA_COMMAND_FLUSH_CACHE 0xe7 +#define MV_ATA_COMMAND_FLUSH_CACHE_EXT 0xea + +#define MV_ATA_COMMAND_PM_READ_REG 0xe4 +#define MV_ATA_COMMAND_PM_WRITE_REG 0xe8 + +#define MV_SATA_GSCR_ID_REG_NUM 0 +#define MV_SATA_GSCR_REVISION_REG_NUM 1 +#define MV_SATA_GSCR_INFO_REG_NUM 2 +#define MV_SATA_GSCR_ERROR_REG_NUM 32 +#define MV_SATA_GSCR_ERROR_ENABLE_REG_NUM 33 +#define MV_SATA_GSCR_FEATURES_REG_NUM 64 +#define MV_SATA_GSCR_FEATURES_ENABLE_REG_NUM 96 + + +#define MV_SATA_PSCR_SSTATUS_REG_NUM 0 +#define MV_SATA_PSCR_SERROR_REG_NUM 1 +#define MV_SATA_PSCR_SCONTROL_REG_NUM 2 +#define MV_SATA_PSCR_SACTIVE_REG_NUM 3 + + + +#define MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO 0x01 +#define MV_ATA_SET_FEATURES_ENABLE_WCACHE 0x02 /* Enable write cache */ +#define MV_ATA_SET_FEATURES_TRANSFER 0x03 /* Set transfer mode */ +#define MV_ATA_TRANSFER_UDMA_0 0x40 +#define MV_ATA_TRANSFER_UDMA_1 0x41 +#define MV_ATA_TRANSFER_UDMA_2 0x42 +#define MV_ATA_TRANSFER_UDMA_3 0x43 +#define MV_ATA_TRANSFER_UDMA_4 0x44 +#define MV_ATA_TRANSFER_UDMA_5 0x45 +#define MV_ATA_TRANSFER_UDMA_6 0x46 +#define MV_ATA_TRANSFER_UDMA_7 0x47 +#define MV_ATA_TRANSFER_PIO_SLOW 0x00 +#define MV_ATA_TRANSFER_PIO_0 0x08 +#define MV_ATA_TRANSFER_PIO_1 0x09 +#define MV_ATA_TRANSFER_PIO_2 0x0A +#define MV_ATA_TRANSFER_PIO_3 0x0B +#define MV_ATA_TRANSFER_PIO_4 0x0C + +/* Enable advanced power management */ +#define MV_ATA_SET_FEATURES_ENABLE_APM 0x05 + +/* Disable media status notification*/ +#define MV_ATA_SET_FEATURES_DISABLE_MSN 0x31 + +/* Disable read look-ahead */ +#define MV_ATA_SET_FEATURES_DISABLE_RLA 0x55 + +/* Enable release interrupt */ +#define MV_ATA_SET_FEATURES_ENABLE_RI 0x5D + +/* Enable SERVICE interrupt */ +#define MV_ATA_SET_FEATURES_ENABLE_SI 0x5E + +/* Disable revert power-on defaults */ +#define MV_ATA_SET_FEATURES_DISABLE_RPOD 0x66 + +/* Disable write cache */ +#define MV_ATA_SET_FEATURES_DISABLE_WCACHE 0x82 + +/* Disable advanced power management*/ +#define MV_ATA_SET_FEATURES_DISABLE_APM 0x85 + +/* Enable media status notification */ +#define MV_ATA_SET_FEATURES_ENABLE_MSN 0x95 + +/* Enable read look-ahead */ +#define MV_ATA_SET_FEATURES_ENABLE_RLA 0xAA + +/* Enable revert power-on defaults */ +#define MV_ATA_SET_FEATURES_ENABLE_RPOD 0xCC + +/* Disable release interrupt */ +#define MV_ATA_SET_FEATURES_DISABLE_RI 0xDD + +/* Disable SERVICE interrupt */ +#define MV_ATA_SET_FEATURES_DISABLE_SI 0xDE + +/* Defines for parsing the IDENTIFY command results*/ +#define IDEN_SERIAL_NUM_OFFSET 10 +#define IDEN_SERIAL_NUM_SIZE (20-10) +#define IDEN_FIRMWARE_OFFSET 23 +#define IDEN_FIRMWARE_SIZE (27-23) +#define IDEN_MODEL_OFFSET 27 +#define IDEN_MODEL_SIZE (47-27) +#define IDEN_CAPACITY_1_OFFSET 49 +#define IDEN_VALID 53 +#define IDEN_NUM_OF_ADDRESSABLE_SECTORS 60 +#define IDEN_PIO_MODE_SPPORTED 64 +#define IDEN_QUEUE_DEPTH 75 +#define IDEN_SATA_CAPABILITIES 76 +#define IDEN_SATA_FEATURES_SUPPORTED 78 +#define IDEN_SATA_FEATURES_ENABLED 79 +#define IDEN_ATA_VERSION 80 +#define IDEN_SUPPORTED_COMMANDS1 82 +#define IDEN_SUPPORTED_COMMANDS2 83 +#define IDEN_ENABLED_COMMANDS1 85 +#define IDEN_ENABLED_COMMANDS2 86 +#define IDEN_UDMA_MODE 88 + +/* Typedefs */ + +/* Structures */ + + typedef struct mvStorageDevRegisters + { +/* Fields set by CORE driver */ + MV_U8 errorRegister; + MV_U16 featuresRegister;/*input only*/ + MV_U8 commandRegister;/*input only*/ + MV_U16 sectorCountRegister; + MV_U16 lbaLowRegister; + MV_U16 lbaMidRegister; + MV_U16 lbaHighRegister; + MV_U8 deviceRegister; + MV_U8 statusRegister; + } MV_STORAGE_DEVICE_REGISTERS; + +/* Function */ + + MV_BOOLEAN mvStorageDevATAExecuteNonUDMACommand(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_NON_UDMA_PROTOCOL protocolType, + MV_BOOLEAN isEXT, + MV_U16_PTR bufPtr, MV_U32 count, + MV_U16 features, + MV_U16 sectorCount, + MV_U16 lbaLow, MV_U16 lbaMid, + MV_U16 lbaHigh, MV_U8 device, + MV_U8 command); + + MV_BOOLEAN mvStorageDevATAIdentifyDevice(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_U16_PTR identifyDeviceResult + ); + + MV_BOOLEAN mvStorageDevATASetFeatures(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_U8 subCommand, + MV_U8 subCommandSpecific1, + MV_U8 subCommandSpecific2, + MV_U8 subCommandSpecific3, + MV_U8 subCommandSpecific4); + + MV_BOOLEAN mvStorageDevATAIdleImmediate(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + + MV_BOOLEAN mvStorageDevATASoftResetDevice(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_STORAGE_DEVICE_REGISTERS *registerStruct + ); + +/*PM*/ + + MV_BOOLEAN mvPMDevReadReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_U8 PMPort, MV_U8 PMReg, MV_U32 *pValue, + MV_STORAGE_DEVICE_REGISTERS *registerStruct); + + MV_BOOLEAN mvPMDevWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_U8 PMPort, MV_U8 PMReg, MV_U32 value, + MV_STORAGE_DEVICE_REGISTERS *registerStruct); + + MV_BOOLEAN mvPMDevEnableStaggeredSpinUp(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, MV_U8 PMPort); + + MV_BOOLEAN mvPMDevEnableStaggeredSpinUpAll(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMNumOfPorts, + MV_U16 *bitmask); + + MV_BOOLEAN mvPMDevEnableStaggeredSpinUpPort(MV_SATA_ADAPTER *pSataAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_BOOLEAN force_gen1); + + MV_BOOLEAN mvPMLinkUp(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, MV_U8 PMPort, + MV_BOOLEAN force_gen1); + + MV_BOOLEAN mvStorageDevExecutePIO(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort, + MV_NON_UDMA_PROTOCOL protocolType, + MV_BOOLEAN isEXT, MV_U16_PTR bufPtr, + MV_U32 count, + MV_STORAGE_DEVICE_REGISTERS *pInATARegs, + MV_STORAGE_DEVICE_REGISTERS *pOutATARegs); + + + MV_BOOLEAN mvStorageDevATAStartSoftResetDevice(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_U8 PMPort); + + MV_BOOLEAN mvStorageIsDeviceBsyBitOff(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex, + MV_STORAGE_DEVICE_REGISTERS *registerStruct + ); + + MV_BOOLEAN mvStorageDevSetDeviceType(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, + MV_SATA_DEVICE_TYPE deviceType); + + MV_SATA_DEVICE_TYPE mvStorageDevGetDeviceType(MV_SATA_ADAPTER *pAdapter, + MV_U8 channelIndex); + + +#ifdef __cplusplus + +} +#endif /* __cplusplus */ + +#endif /* __INCmvStorageDevh */ diff --git a/board/mv_feroceon/mv_hal/sflash/mvSFlash.c b/board/mv_feroceon/mv_hal/sflash/mvSFlash.c new file mode 100644 index 0000000..54877c6 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sflash/mvSFlash.c @@ -0,0 +1,1518 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#include "mvOs.h" +#include "sflash/mvSFlash.h" +#include "sflash/mvSFlashSpec.h" +#include "spi/mvSpi.h" +#include "spi/mvSpiCmnd.h" +#include "ctrlEnv/mvCtrlEnvLib.h" + +/*#define MV_DEBUG*/ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +/* Globals */ +static MV_SFLASH_DEVICE_PARAMS sflash[] = { + /* ST M25P32 SPI flash, 4MB, 64 sectors of 64K each */ + { + MV_M25P_WREN_CMND_OPCD, + MV_M25P_WRDI_CMND_OPCD, + MV_M25P_RDID_CMND_OPCD, + MV_M25P_RDSR_CMND_OPCD, + MV_M25P_WRSR_CMND_OPCD, + MV_M25P_READ_CMND_OPCD, + MV_M25P_FAST_RD_CMND_OPCD, + MV_M25P_PP_CMND_OPCD, + MV_M25P_SE_CMND_OPCD, + MV_M25P_BE_CMND_OPCD, + MV_M25P_RES_CMND_OPCD, + MV_SFLASH_NO_SPECIFIC_OPCD, /* power save not supported */ + MV_M25P32_SECTOR_SIZE, + MV_M25P32_SECTOR_NUMBER, + MV_M25P_PAGE_SIZE, + "ST M25P32", + MV_M25PXXX_ST_MANF_ID, + MV_M25P32_DEVICE_ID, + MV_M25P32_MAX_SPI_FREQ, + MV_M25P32_MAX_FAST_SPI_FREQ, + MV_M25P32_FAST_READ_DUMMY_BYTES + }, + /* ST M25P64 SPI flash, 8MB, 128 sectors of 64K each */ + { + MV_M25P_WREN_CMND_OPCD, + MV_M25P_WRDI_CMND_OPCD, + MV_M25P_RDID_CMND_OPCD, + MV_M25P_RDSR_CMND_OPCD, + MV_M25P_WRSR_CMND_OPCD, + MV_M25P_READ_CMND_OPCD, + MV_M25P_FAST_RD_CMND_OPCD, + MV_M25P_PP_CMND_OPCD, + MV_M25P_SE_CMND_OPCD, + MV_M25P_BE_CMND_OPCD, + MV_M25P_RES_CMND_OPCD, + MV_SFLASH_NO_SPECIFIC_OPCD, /* power save not supported */ + MV_M25P64_SECTOR_SIZE, + MV_M25P64_SECTOR_NUMBER, + MV_M25P_PAGE_SIZE, + "ST M25P64", + MV_M25PXXX_ST_MANF_ID, + MV_M25P64_DEVICE_ID, + MV_M25P64_MAX_SPI_FREQ, + MV_M25P64_MAX_FAST_SPI_FREQ, + MV_M25P64_FAST_READ_DUMMY_BYTES + }, + /* ST M25P128 SPI flash, 16MB, 64 sectors of 256K each */ + { + MV_M25P_WREN_CMND_OPCD, + MV_M25P_WRDI_CMND_OPCD, + MV_M25P_RDID_CMND_OPCD, + MV_M25P_RDSR_CMND_OPCD, + MV_M25P_WRSR_CMND_OPCD, + MV_M25P_READ_CMND_OPCD, + MV_M25P_FAST_RD_CMND_OPCD, + MV_M25P_PP_CMND_OPCD, + MV_M25P_SE_CMND_OPCD, + MV_M25P_BE_CMND_OPCD, + MV_M25P_RES_CMND_OPCD, + MV_SFLASH_NO_SPECIFIC_OPCD, /* power save not supported */ + MV_M25P128_SECTOR_SIZE, + MV_M25P128_SECTOR_NUMBER, + MV_M25P_PAGE_SIZE, + "ST M25P128", + MV_M25PXXX_ST_MANF_ID, + MV_M25P128_DEVICE_ID, + MV_M25P128_MAX_SPI_FREQ, + MV_M25P128_MAX_FAST_SPI_FREQ, + MV_M25P128_FAST_READ_DUMMY_BYTES + }, + /* Macronix MXIC MX25L6405 SPI flash, 8MB, 128 sectors of 64K each */ + { + MV_MX25L_WREN_CMND_OPCD, + MV_MX25L_WRDI_CMND_OPCD, + MV_MX25L_RDID_CMND_OPCD, + MV_MX25L_RDSR_CMND_OPCD, + MV_MX25L_WRSR_CMND_OPCD, + MV_MX25L_READ_CMND_OPCD, + MV_MX25L_FAST_RD_CMND_OPCD, + MV_MX25L_PP_CMND_OPCD, + MV_MX25L_SE_CMND_OPCD, + MV_MX25L_BE_CMND_OPCD, + MV_MX25L_RES_CMND_OPCD, + MV_MX25L_DP_CMND_OPCD, + MV_MX25L6405_SECTOR_SIZE, + MV_MX25L6405_SECTOR_NUMBER, + MV_MXIC_PAGE_SIZE, + "MXIC MX25L6405", + MV_MXIC_MANF_ID, + MV_MX25L6405_DEVICE_ID, + MV_MX25L6405_MAX_SPI_FREQ, + MV_MX25L6405_MAX_FAST_SPI_FREQ, + MV_MX25L6405_FAST_READ_DUMMY_BYTES + }, + /* SPANSION S25FL128P SPI flash, 16MB, 64 sectors of 256K each */ + { + MV_S25FL_WREN_CMND_OPCD, + MV_S25FL_WRDI_CMND_OPCD, + MV_S25FL_RDID_CMND_OPCD, + MV_S25FL_RDSR_CMND_OPCD, + MV_S25FL_WRSR_CMND_OPCD, + MV_S25FL_READ_CMND_OPCD, + MV_S25FL_FAST_RD_CMND_OPCD, + MV_S25FL_PP_CMND_OPCD, + MV_S25FL_SE_CMND_OPCD, + MV_S25FL_BE_CMND_OPCD, + MV_S25FL_RES_CMND_OPCD, + MV_S25FL_DP_CMND_OPCD, + MV_S25FL128_SECTOR_SIZE, + MV_S25FL128_SECTOR_NUMBER, + MV_S25FL_PAGE_SIZE, + "SPANSION S25FL128", + MV_SPANSION_MANF_ID, + MV_S25FL128_DEVICE_ID, + MV_S25FL128_MAX_SPI_FREQ, + MV_M25P128_MAX_FAST_SPI_FREQ, + MV_M25P128_FAST_READ_DUMMY_BYTES + } +}; + +/* Static Functions */ +static MV_STATUS mvWriteEnable (MV_SFLASH_INFO * pFlinfo); +static MV_STATUS mvStatusRegGet (MV_SFLASH_INFO * pFlinfo, MV_U8 * pStatReg); +static MV_STATUS mvStatusRegSet (MV_SFLASH_INFO * pFlinfo, MV_U8 sr); +static MV_STATUS mvWaitOnWipClear(MV_SFLASH_INFO * pFlinfo); +static MV_STATUS mvSFlashPageWr (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, \ + MV_U8* pPageBuff, MV_U32 buffSize); +static MV_STATUS mvSFlashWithDefaultsIdGet (MV_SFLASH_INFO * pFlinfo, \ + MV_U8* manId, MV_U16* devId); + +/******************************************************************************* +* mvWriteEnable - serialize the write enable sequence +* +* DESCRIPTION: +* transmit the sequence for write enable +* +********************************************************************************/ +static MV_STATUS mvWriteEnable(MV_SFLASH_INFO * pFlinfo) +{ + MV_U8 cmd[MV_SFLASH_WREN_CMND_LENGTH]; + + + cmd[0] = sflash[pFlinfo->index].opcdWREN; + + return mvSpiWriteThenRead(cmd, MV_SFLASH_WREN_CMND_LENGTH, NULL, 0, 0); +} + +/******************************************************************************* +* mvStatusRegGet - Retrieve the value of the status register +* +* DESCRIPTION: +* perform the RDSR sequence to get the 8bit status register +* +********************************************************************************/ +static MV_STATUS mvStatusRegGet(MV_SFLASH_INFO * pFlinfo, MV_U8 * pStatReg) +{ + MV_STATUS ret; + MV_U8 cmd[MV_SFLASH_RDSR_CMND_LENGTH]; + MV_U8 sr[MV_SFLASH_RDSR_REPLY_LENGTH]; + + + + + cmd[0] = sflash[pFlinfo->index].opcdRDSR; + + if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_RDSR_CMND_LENGTH, sr, + MV_SFLASH_RDSR_REPLY_LENGTH,0)) != MV_OK) + return ret; + + *pStatReg = sr[0]; + + return MV_OK; +} + +/******************************************************************************* +* mvWaitOnWipClear - Block waiting for the WIP (write in progress) to be cleared +* +* DESCRIPTION: +* Block waiting for the WIP (write in progress) to be cleared +* +********************************************************************************/ +static MV_STATUS mvWaitOnWipClear(MV_SFLASH_INFO * pFlinfo) +{ + MV_STATUS ret; + MV_U32 i; + MV_U8 stat; + + for (i=0; iindex].opcdWRSR; + cmd[1] = sr; + + if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_WRSR_CMND_LENGTH, NULL, 0, 0)) != MV_OK) + return ret; + + if ((ret = mvWaitOnWipClear(pFlinfo)) != MV_OK) + return ret; + + mvOsDelay(1); + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashPageWr - Write up to 256 Bytes in the same page +* +* DESCRIPTION: +* Write a buffer up to the page size in length provided that the whole address +* range is within the same page (alligned to page bounderies) +* +*******************************************************************************/ +static MV_STATUS mvSFlashPageWr (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, + MV_U8* pPageBuff, MV_U32 buffSize) +{ + MV_STATUS ret; + MV_U8 cmd[MV_SFLASH_PP_CMND_LENGTH]; + + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invalid parameter device index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* check that we do not cross the page bounderies */ + if (((offset & (sflash[pFlinfo->index].pageSize - 1)) + buffSize) > + sflash[pFlinfo->index].pageSize) + { + DB(mvOsPrintf("%s WARNING: Page allignment problem!\n", __FUNCTION__);) + return MV_OUT_OF_RANGE; + } + + /* Issue the Write enable command prior the page program command */ + if ((ret = mvWriteEnable(pFlinfo)) != MV_OK) + return ret; + + cmd[0] = sflash[pFlinfo->index].opcdPP; + cmd[1] = ((offset >> 16) & 0xFF); + cmd[2] = ((offset >> 8) & 0xFF); + cmd[3] = (offset & 0xFF); + + if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_PP_CMND_LENGTH, pPageBuff, buffSize)) != MV_OK) + return ret; + + if ((ret = mvWaitOnWipClear(pFlinfo)) != MV_OK) + return ret; + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashWithDefaultsIdGet - Try to read the manufacturer and Device IDs from +* the device using the default RDID opcode and the default WREN opcode. +* +* DESCRIPTION: +* This is used to detect a generic device that uses the default opcodes +* for the WREN and RDID. +* +********************************************************************************/ +static MV_STATUS mvSFlashWithDefaultsIdGet (MV_SFLASH_INFO * pFlinfo, MV_U8* manId, MV_U16* devId) +{ + MV_STATUS ret; + MV_U8 cmdRDID[MV_SFLASH_RDID_CMND_LENGTH]; + MV_U8 id[MV_SFLASH_RDID_REPLY_LENGTH]; + + + + /* Use the default RDID opcode to read the IDs */ + cmdRDID[0] = MV_SFLASH_DEFAULT_RDID_OPCD; /* unknown model try default */ + if ((ret = mvSpiWriteThenRead(cmdRDID, MV_SFLASH_RDID_CMND_LENGTH, id, MV_SFLASH_RDID_REPLY_LENGTH, 0)) != MV_OK) + return ret; + + *manId = id[0]; + *devId = 0; + *devId |= (id[1] << 8); + *devId |= id[2]; + + return MV_OK; +} + +/* +##################################################################################### +##################################################################################### +*/ + +/******************************************************************************* +* mvSFlashInit - Initialize the serial flash device +* +* DESCRIPTION: +* Perform the neccessary initialization and configuration +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* pFlinfo->baseAddr: base address in fast mode. +* pFlinfo->index: Index of the flash in the sflash tabel. If the SPI +* flash device does not support read Id command with +* the standard opcode, then the user should supply this +* as an input to skip the autodetection process!!!! +* +* OUTPUT: +* pFlinfo: pointer to the Flash information structure after detection +* pFlinfo->manufacturerId: Manufacturer ID +* pFlinfo->deviceId: Device ID +* pFlinfo->sectorSize: size of the sector (all sectors are the same). +* pFlinfo->sectorNumber: number of sectors. +* pFlinfo->pageSize: size of the page. +* pFlinfo->index: Index of the detected flash in the sflash tabel +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashInit (MV_SFLASH_INFO * pFlinfo) +{ + MV_STATUS ret; + MV_U8 manf; + MV_U16 dev; + MV_U32 indx; + MV_BOOL detectFlag = MV_FALSE; + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Initialize the SPI interface with low frequency to make sure that the read ID succeeds */ + if ((ret = mvSpiInit(MV_SFLASH_BASIC_SPI_FREQ)) != MV_OK) + { + mvOsPrintf("%s ERROR: Failed to initialize the SPI interface!\n", __FUNCTION__); + return ret; + } + + /* First try to read the Manufacturer and Device IDs */ + if ((ret = mvSFlashIdGet(pFlinfo, &manf, &dev)) != MV_OK) + { + mvOsPrintf("%s ERROR: Failed to get the SFlash ID!\n", __FUNCTION__); + return ret; + } + + /* loop over the whole table and look for the appropriate SFLASH */ + for (indx=0; indxmanufacturerId = manf; + pFlinfo->deviceId = dev; + pFlinfo->index = indx; + detectFlag = MV_TRUE; + } + } + + if(!detectFlag) + { + mvOsPrintf("%s ERROR: Unknown SPI flash device!\n", __FUNCTION__); + return MV_FAIL; + } + + /* fill the info based on the model detected */ + pFlinfo->sectorSize = sflash[pFlinfo->index].sectorSize; + pFlinfo->sectorNumber = sflash[pFlinfo->index].sectorNumber; + pFlinfo->pageSize = sflash[pFlinfo->index].pageSize; + + /* Set the SPI frequency to the MAX allowed for the device for best performance */ + if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq)) != MV_OK) + { + mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __FUNCTION__); + return ret; + } + + /* As default lock the SR */ + if ((ret = mvSFlashStatRegLock(pFlinfo, MV_TRUE)) != MV_OK) + return ret; + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashSectorErase - Erasse a single sector of the serial flash +* +* DESCRIPTION: +* Issue the erase sector command and address +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* secNumber: sector Number to erase (0 -> (sectorNumber-1)) +* +* OUTPUT: +* None +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashSectorErase (MV_SFLASH_INFO * pFlinfo, MV_U32 secNumber) +{ + MV_STATUS ret; + MV_U8 cmd[MV_SFLASH_SE_CMND_LENGTH]; + + MV_U32 secAddr = (secNumber * pFlinfo->sectorSize); + MV_U32 i; + MV_U32 * pW = (MV_U32*) (secAddr + pFlinfo->baseAddr); + MV_U32 erasedWord = 0xFFFFFFFF; + MV_U32 wordsPerSector = (pFlinfo->sectorSize / sizeof(MV_U32)); + MV_BOOL eraseNeeded = MV_FALSE; + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* check that the sector number is valid */ + if (secNumber >= pFlinfo->sectorNumber) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter sector number!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* First compare to FF and check if erase is needed */ + for (i=0; iindex].opcdSE; + cmd[1] = ((secAddr >> 16) & 0xFF); + cmd[2] = ((secAddr >> 8) & 0xFF); + cmd[3] = (secAddr & 0xFF); + + /* Issue the Write enable command prior the sector erase command */ + if ((ret = mvWriteEnable(pFlinfo)) != MV_OK) + return ret; + + if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_SE_CMND_LENGTH, NULL, 0)) != MV_OK) + return ret; + + if ((ret = mvWaitOnWipClear(pFlinfo)) != MV_OK) + return ret; + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashChipErase - Erasse the whole serial flash +* +* DESCRIPTION: +* Issue the bulk (chip) erase command +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* +* OUTPUT: +* None +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashChipErase (MV_SFLASH_INFO * pFlinfo) +{ + MV_STATUS ret; + MV_U8 cmd[MV_SFLASH_BE_CMND_LENGTH]; + + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + cmd[0] = sflash[pFlinfo->index].opcdBE; + + /* Issue the Write enable command prior the Bulk erase command */ + if ((ret = mvWriteEnable(pFlinfo)) != MV_OK) + return ret; + + if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_BE_CMND_LENGTH, NULL, 0)) != MV_OK) + return ret; + + if ((ret = mvWaitOnChipEraseDone(pFlinfo)) != MV_OK) + return ret; + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashBlockRd - Read from the serial flash +* +* DESCRIPTION: +* Issue the read command and address then perfom the needed read +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* offset: byte offset with the flash to start reading from +* pReadBuff: pointer to the buffer to read the data in +* buffSize: size of the buffer to read. +* +* OUTPUT: +* pReadBuff: pointer to the buffer containing the read data +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashBlockRd (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, + MV_U8* pReadBuff, MV_U32 buffSize) +{ + MV_U8 cmd[MV_SFLASH_READ_CMND_LENGTH]; + + + /* check for NULL pointer */ + if ((pFlinfo == NULL) || (pReadBuff == NULL)) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + cmd[0] = sflash[pFlinfo->index].opcdREAD; + cmd[1] = ((offset >> 16) & 0xFF); + cmd[2] = ((offset >> 8) & 0xFF); + cmd[3] = (offset & 0xFF); + + return mvSpiWriteThenRead(cmd, MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize, 0); +} + +/******************************************************************************* +* mvSFlashFastBlockRd - Fast read from the serial flash +* +* DESCRIPTION: +* Issue the fast read command and address then perfom the needed read +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* offset: byte offset with the flash to start reading from +* pReadBuff: pointer to the buffer to read the data in +* buffSize: size of the buffer to read. +* +* OUTPUT: +* pReadBuff: pointer to the buffer containing the read data +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashFastBlockRd (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, + MV_U8* pReadBuff, MV_U32 buffSize) +{ + MV_U8 cmd[MV_SFLASH_READ_CMND_LENGTH]; + MV_STATUS ret; + + /* check for NULL pointer */ + if ((pFlinfo == NULL) || (pReadBuff == NULL)) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* Set the SPI frequency to the MAX allowed for fast-read operations */ + mvOsPrintf("Setting freq to %d.\n",sflash[pFlinfo->index].spiMaxFastFreq); + if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFastFreq)) != MV_OK) + { + mvOsPrintf("%s ERROR: Failed to set the SPI fast frequency!\n", __FUNCTION__); + return ret; + } + + cmd[0] = sflash[pFlinfo->index].opcdFSTRD; + cmd[1] = ((offset >> 16) & 0xFF); + cmd[2] = ((offset >> 8) & 0xFF); + cmd[3] = (offset & 0xFF); + + + ret = mvSpiWriteThenRead(cmd, MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize, + sflash[pFlinfo->index].spiFastRdDummyBytes); + + /* Reset the SPI frequency to the MAX allowed for the device for best performance */ + if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq)) != MV_OK) + { + mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __FUNCTION__); + return ret; + } + + return ret; +} + + +/******************************************************************************* +* mvSFlashBlockWr - Write a buffer with any size +* +* DESCRIPTION: +* write regardless of the page boundaries and size limit per Page +* program command +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* offset: byte offset within the flash region +* pWriteBuff: pointer to the buffer holding the data to program +* buffSize: size of the buffer to write +* +* OUTPUT: +* None +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashBlockWr (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, + MV_U8* pWriteBuff, MV_U32 buffSize) +{ + MV_STATUS ret; + MV_U32 data2write = buffSize; + MV_U32 preAllOffset = (offset & MV_SFLASH_PAGE_ALLIGN_MASK(MV_M25P_PAGE_SIZE)); + MV_U32 preAllSz = (preAllOffset ? (MV_M25P_PAGE_SIZE - preAllOffset) : 0); + MV_U32 writeOffset = offset; + + /* check for NULL pointer */ +#ifndef CONFIG_MARVELL + if(NULL == pWriteBuff) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } +#endif + + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* check that the buffer size does not exceed the flash size */ + if ((offset + buffSize) > mvSFlashSizeGet(pFlinfo)) + { + DB(mvOsPrintf("%s WARNING: Write exceeds flash size!\n", __FUNCTION__);) + return MV_OUT_OF_RANGE; + } + + /* check if the total block size is less than the first chunk remainder */ + if (data2write < preAllSz) + preAllSz = data2write; + + /* check if programing does not start at a 64byte alligned offset */ + if (preAllSz) + { + if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, preAllSz)) != MV_OK) + return ret; + + /* increment pointers and counters */ + writeOffset += preAllSz; + data2write -= preAllSz; + pWriteBuff += preAllSz; + } + + /* program the data that fits in complete page chunks */ + while (data2write >= sflash[pFlinfo->index].pageSize) + { + if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, sflash[pFlinfo->index].pageSize)) != MV_OK) + return ret; + + /* increment pointers and counters */ + writeOffset += sflash[pFlinfo->index].pageSize; + data2write -= sflash[pFlinfo->index].pageSize; + pWriteBuff += sflash[pFlinfo->index].pageSize; + } + + /* program the last partial chunk */ + if (data2write) + { + if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, data2write)) != MV_OK) + return ret; + } + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashIdGet - Get the manufacturer and device IDs. +* +* DESCRIPTION: +* Get the Manufacturer and device IDs from the serial flash through +* writing the RDID command then reading 3 bytes of data. In case that +* this command was called for the first time in order to detect the +* manufacturer and device IDs, then the default RDID opcode will be used +* unless the device index is indicated by the user (in case the SPI flash +* does not use the default RDID opcode). +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* pManId: pointer to the 8bit variable to hold the manufacturing ID +* pDevId: pointer to the 16bit variable to hold the device ID +* +* OUTPUT: +* pManId: pointer to the 8bit variable holding the manufacturing ID +* pDevId: pointer to the 16bit variable holding the device ID +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashIdGet (MV_SFLASH_INFO * pFlinfo, MV_U8* pManId, MV_U16* pDevId) +{ + MV_STATUS ret; + MV_U8 cmd[MV_SFLASH_RDID_CMND_LENGTH]; + MV_U8 id[MV_SFLASH_RDID_REPLY_LENGTH]; + + + + /* check for NULL pointer */ + if ((pFlinfo == NULL) || (pManId == NULL) || (pDevId == NULL)) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + return mvSFlashWithDefaultsIdGet(pFlinfo, pManId, pDevId); + else + cmd[0] = sflash[pFlinfo->index].opcdRDID; + + if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_RDID_CMND_LENGTH, id, MV_SFLASH_RDID_REPLY_LENGTH, 0)) != MV_OK) + return ret; + + *pManId = id[0]; + *pDevId = 0; + *pDevId |= (id[1] << 8); + *pDevId |= id[2]; + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashWpRegionSet - Set the Write-Protected region +* +* DESCRIPTION: +* Set the Write-Protected region +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* wpRegion: which region will be protected +* +* OUTPUT: +* None +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashWpRegionSet (MV_SFLASH_INFO * pFlinfo, MV_SFLASH_WP_REGION wpRegion) +{ + MV_U8 wpMask; + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* Check if the chip is an ST flash; then WP supports only 3 bits */ + if (pFlinfo->manufacturerId == MV_M25PXXX_ST_MANF_ID) + { + switch (wpRegion) + { + case MV_WP_NONE: + wpMask = MV_M25P_STATUS_BP_NONE; + break; + + case MV_WP_UPR_1OF128: + DB(mvOsPrintf("%s WARNING: Invaild option for this flash chip!\n", __FUNCTION__);) + return MV_NOT_SUPPORTED; + + case MV_WP_UPR_1OF64: + wpMask = MV_M25P_STATUS_BP_1_OF_64; + break; + + case MV_WP_UPR_1OF32: + wpMask = MV_M25P_STATUS_BP_1_OF_32; + break; + + case MV_WP_UPR_1OF16: + wpMask = MV_M25P_STATUS_BP_1_OF_16; + break; + + case MV_WP_UPR_1OF8: + wpMask = MV_M25P_STATUS_BP_1_OF_8; + break; + + case MV_WP_UPR_1OF4: + wpMask = MV_M25P_STATUS_BP_1_OF_4; + break; + + case MV_WP_UPR_1OF2: + wpMask = MV_M25P_STATUS_BP_1_OF_2; + break; + + case MV_WP_ALL: + wpMask = MV_M25P_STATUS_BP_ALL; + break; + + default: + DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + } + /* check if the manufacturer is MXIC then the WP is 4bits */ + else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID) + { + switch (wpRegion) + { + case MV_WP_NONE: + wpMask = MV_MX25L_STATUS_BP_NONE; + break; + + case MV_WP_UPR_1OF128: + wpMask = MV_MX25L_STATUS_BP_1_OF_128; + break; + + case MV_WP_UPR_1OF64: + wpMask = MV_MX25L_STATUS_BP_1_OF_64; + break; + + case MV_WP_UPR_1OF32: + wpMask = MV_MX25L_STATUS_BP_1_OF_32; + break; + + case MV_WP_UPR_1OF16: + wpMask = MV_MX25L_STATUS_BP_1_OF_16; + break; + + case MV_WP_UPR_1OF8: + wpMask = MV_MX25L_STATUS_BP_1_OF_8; + break; + + case MV_WP_UPR_1OF4: + wpMask = MV_MX25L_STATUS_BP_1_OF_4; + break; + + case MV_WP_UPR_1OF2: + wpMask = MV_MX25L_STATUS_BP_1_OF_2; + break; + + case MV_WP_ALL: + wpMask = MV_MX25L_STATUS_BP_ALL; + break; + + default: + DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + } + /* check if the manufacturer is SPANSION then the WP is 4bits */ + else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID) + { + switch (wpRegion) + { + case MV_WP_NONE: + wpMask = MV_S25FL_STATUS_BP_NONE; + break; + + case MV_WP_UPR_1OF128: + DB(mvOsPrintf("%s WARNING: Invaild option for this flash chip!\n", __FUNCTION__);) + return MV_NOT_SUPPORTED; + + case MV_WP_UPR_1OF64: + wpMask = MV_S25FL_STATUS_BP_1_OF_64; + break; + + case MV_WP_UPR_1OF32: + wpMask = MV_S25FL_STATUS_BP_1_OF_32; + break; + + case MV_WP_UPR_1OF16: + wpMask = MV_S25FL_STATUS_BP_1_OF_16; + break; + + case MV_WP_UPR_1OF8: + wpMask = MV_S25FL_STATUS_BP_1_OF_8; + break; + + case MV_WP_UPR_1OF4: + wpMask = MV_S25FL_STATUS_BP_1_OF_4; + break; + + case MV_WP_UPR_1OF2: + wpMask = MV_S25FL_STATUS_BP_1_OF_2; + break; + + case MV_WP_ALL: + wpMask = MV_S25FL_STATUS_BP_ALL; + break; + + + default: + DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + } + else + { + DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* Verify that the SRWD bit is always set - register is s/w locked */ + wpMask |= MV_SFLASH_STATUS_REG_SRWD_MASK; + + return mvStatusRegSet(pFlinfo, wpMask); +} + +/******************************************************************************* +* mvSFlashWpRegionGet - Get the Write-Protected region configured +* +* DESCRIPTION: +* Get from the chip the Write-Protected region configured +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* pWpRegion: pointer to the variable to return the WP region in +* +* OUTPUT: +* wpRegion: pointer to the variable holding the WP region configured +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashWpRegionGet (MV_SFLASH_INFO * pFlinfo, MV_SFLASH_WP_REGION * pWpRegion) +{ + MV_STATUS ret; + MV_U8 reg; + + /* check for NULL pointer */ + if ((pFlinfo == NULL) || (pWpRegion == NULL)) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + if ((ret = mvStatusRegGet(pFlinfo, ®)) != MV_OK) + return ret; + + /* Check if the chip is an ST flash; then WP supports only 3 bits */ + if (pFlinfo->manufacturerId == MV_M25PXXX_ST_MANF_ID) + { + switch ((reg & MV_M25P_STATUS_REG_WP_MASK)) + { + case MV_M25P_STATUS_BP_NONE: + *pWpRegion = MV_WP_NONE; + break; + + case MV_M25P_STATUS_BP_1_OF_64: + *pWpRegion = MV_WP_UPR_1OF64; + break; + + case MV_M25P_STATUS_BP_1_OF_32: + *pWpRegion = MV_WP_UPR_1OF32; + break; + + case MV_M25P_STATUS_BP_1_OF_16: + *pWpRegion = MV_WP_UPR_1OF16; + break; + + case MV_M25P_STATUS_BP_1_OF_8: + *pWpRegion = MV_WP_UPR_1OF8; + break; + + case MV_M25P_STATUS_BP_1_OF_4: + *pWpRegion = MV_WP_UPR_1OF4; + break; + + case MV_M25P_STATUS_BP_1_OF_2: + *pWpRegion = MV_WP_UPR_1OF2; + break; + + case MV_M25P_STATUS_BP_ALL: + *pWpRegion = MV_WP_ALL; + break; + + default: + DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __FUNCTION__);) + return MV_BAD_VALUE; + } + } + /* check if the manufacturer is MXIC then the WP is 4bits */ + else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID) + { + switch ((reg & MV_MX25L_STATUS_REG_WP_MASK)) + { + case MV_MX25L_STATUS_BP_NONE: + *pWpRegion = MV_WP_NONE; + break; + + case MV_MX25L_STATUS_BP_1_OF_128: + *pWpRegion = MV_WP_UPR_1OF128; + break; + + case MV_MX25L_STATUS_BP_1_OF_64: + *pWpRegion = MV_WP_UPR_1OF64; + break; + + case MV_MX25L_STATUS_BP_1_OF_32: + *pWpRegion = MV_WP_UPR_1OF32; + break; + + case MV_MX25L_STATUS_BP_1_OF_16: + *pWpRegion = MV_WP_UPR_1OF16; + break; + + case MV_MX25L_STATUS_BP_1_OF_8: + *pWpRegion = MV_WP_UPR_1OF8; + break; + + case MV_MX25L_STATUS_BP_1_OF_4: + *pWpRegion = MV_WP_UPR_1OF4; + break; + + case MV_MX25L_STATUS_BP_1_OF_2: + *pWpRegion = MV_WP_UPR_1OF2; + break; + + case MV_MX25L_STATUS_BP_ALL: + *pWpRegion = MV_WP_ALL; + break; + + default: + DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __FUNCTION__);) + return MV_BAD_VALUE; + } + } + /* Check if the chip is an SPANSION flash; then WP supports only 3 bits */ + else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID) + { + switch ((reg & MV_S25FL_STATUS_REG_WP_MASK)) + { + case MV_S25FL_STATUS_BP_NONE: + *pWpRegion = MV_WP_NONE; + break; + + case MV_S25FL_STATUS_BP_1_OF_64: + *pWpRegion = MV_WP_UPR_1OF64; + break; + + case MV_S25FL_STATUS_BP_1_OF_32: + *pWpRegion = MV_WP_UPR_1OF32; + break; + + case MV_S25FL_STATUS_BP_1_OF_16: + *pWpRegion = MV_WP_UPR_1OF16; + break; + + case MV_S25FL_STATUS_BP_1_OF_8: + *pWpRegion = MV_WP_UPR_1OF8; + break; + + case MV_S25FL_STATUS_BP_1_OF_4: + *pWpRegion = MV_WP_UPR_1OF4; + break; + + case MV_S25FL_STATUS_BP_1_OF_2: + *pWpRegion = MV_WP_UPR_1OF2; + break; + + case MV_S25FL_STATUS_BP_ALL: + *pWpRegion = MV_WP_ALL; + break; + + default: + DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __FUNCTION__);) + return MV_BAD_VALUE; + } + } + else + { + DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + return MV_OK; +} + +/******************************************************************************* +* mvSFlashStatRegLock - Lock the status register for writing - W/Vpp +* pin should be low to take effect +* +* DESCRIPTION: +* Lock the access to the Status Register for writing. This will +* cause the flash to enter the hardware protection mode if the W/Vpp +* is low. If the W/Vpp is hi, the chip will be in soft protection mode, but +* the register will continue to be writable if WREN sequence was used. +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* srLock: enable/disable (MV_TRUE/MV_FALSE) status registor lock mechanism +* +* OUTPUT: +* None +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashStatRegLock (MV_SFLASH_INFO * pFlinfo, MV_BOOL srLock) +{ + MV_STATUS ret; + MV_U8 reg; + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + if ((ret = mvStatusRegGet(pFlinfo, ®)) != MV_OK) + return ret; + + if (srLock) + reg |= MV_SFLASH_STATUS_REG_SRWD_MASK; + else + reg &= ~MV_SFLASH_STATUS_REG_SRWD_MASK; + + return mvStatusRegSet(pFlinfo, reg); +} + +/******************************************************************************* +* mvSFlashSizeGet - Get the size of the SPI flash +* +* DESCRIPTION: +* based on the sector number and size of each sector calculate the total +* size of the flash memory. +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* +* OUTPUT: +* None. +* +* RETURN: +* Size of the flash in bytes. +* +* +*******************************************************************************/ +MV_U32 mvSFlashSizeGet (MV_SFLASH_INFO * pFlinfo) +{ + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return 0; + } + + return (pFlinfo->sectorSize * pFlinfo->sectorNumber); +} + +/******************************************************************************* +* mvSFlashPowerSaveEnter - Cause the falsh device to go into power save mode +* +* DESCRIPTION: +* Enter a special power save mode. +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* +* OUTPUT: +* None. +* +* RETURN: +* Size of the flash in bytes. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashPowerSaveEnter(MV_SFLASH_INFO * pFlinfo) +{ + MV_STATUS ret; + MV_U8 cmd[MV_SFLASH_DP_CMND_LENGTH]; + + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return 0; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* check that power save mode is supported in the specific device */ + if (sflash[pFlinfo->index].opcdPwrSave == MV_SFLASH_NO_SPECIFIC_OPCD) + { + DB(mvOsPrintf("%s WARNING: Power save not supported for this device!\n", __FUNCTION__);) + return MV_NOT_SUPPORTED; + } + + cmd[0] = sflash[pFlinfo->index].opcdPwrSave; + + if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_DP_CMND_LENGTH, NULL, 0)) != MV_OK) + return ret; + + return MV_OK; + +} + +/******************************************************************************* +* mvSFlashPowerSaveExit - Cause the falsh device to exit the power save mode +* +* DESCRIPTION: +* Exit the deep power save mode. +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* +* OUTPUT: +* None. +* +* RETURN: +* Size of the flash in bytes. +* +* +*******************************************************************************/ +MV_STATUS mvSFlashPowerSaveExit (MV_SFLASH_INFO * pFlinfo) +{ + MV_STATUS ret; + MV_U8 cmd[MV_SFLASH_RES_CMND_LENGTH]; + + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return 0; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return MV_BAD_PARAM; + } + + /* check that power save mode is supported in the specific device */ + if (sflash[pFlinfo->index].opcdRES == MV_SFLASH_NO_SPECIFIC_OPCD) + { + DB(mvOsPrintf("%s WARNING: Read Electronic Signature not supported for this device!\n", __FUNCTION__);) + return MV_NOT_SUPPORTED; + } + + cmd[0] = sflash[pFlinfo->index].opcdRES; + + if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_RES_CMND_LENGTH, NULL, 0)) != MV_OK) + return ret; + + /* add the delay needed for the device to wake up */ + mvOsDelay(MV_MXIC_DP_EXIT_DELAY); /* 30 ms */ + + return MV_OK; + +} + +/******************************************************************************* +* mvSFlashModelGet - Retreive the string with the device manufacturer and model +* +* DESCRIPTION: +* Retreive the string with the device manufacturer and model +* +* INPUT: +* pFlinfo: pointer to the Flash information structure +* +* OUTPUT: +* None. +* +* RETURN: +* pointer to the string indicating the device manufacturer and model +* +* +*******************************************************************************/ +const MV_U8 * mvSFlashModelGet (MV_SFLASH_INFO * pFlinfo) +{ + static const MV_U8 * unknModel = (const MV_U8 *)"Unknown"; + + /* check for NULL pointer */ + if (pFlinfo == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return 0; + } + + /* Protection - check if the model was detected */ + if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) + { + DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) + return unknModel; + } + + return sflash[pFlinfo->index].deviceModel; +} + diff --git a/board/mv_feroceon/mv_hal/sflash/mvSFlash.h b/board/mv_feroceon/mv_hal/sflash/mvSFlash.h new file mode 100644 index 0000000..e268f89 --- /dev/null +++ b/board/mv_feroceon/mv_hal/sflash/mvSFlash.h @@ -0,0 +1,166 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSFlashH +#define __INCmvSFlashH + +#include "mvTypes.h" + +/* MCAROS */ +#define MV_SFLASH_PAGE_ALLIGN_MASK(pgSz) (pgSz-1) +#define MV_ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(a[0]))) + +/* Constants */ +#define MV_INVALID_DEVICE_NUMBER 0xFFFFFFFF +/* 10 MHz is the minimum possible SPI frequency when tclk is set 200MHz*/ +#define MV_SFLASH_BASIC_SPI_FREQ 10000000 +/* enumerations */ +typedef enum +{ + MV_WP_NONE, /* Unprotect the whole chip */ + MV_WP_UPR_1OF128, /* Write protect the upper 1/128 part */ + MV_WP_UPR_1OF64, /* Write protect the upper 1/64 part */ + MV_WP_UPR_1OF32, /* Write protect the upper 1/32 part */ + MV_WP_UPR_1OF16, /* Write protect the upper 1/16 part */ + MV_WP_UPR_1OF8, /* Write protect the upper 1/8 part */ + MV_WP_UPR_1OF4, /* Write protect the upper 1/4 part */ + MV_WP_UPR_1OF2, /* Write protect the upper 1/2 part */ + MV_WP_ALL /* Write protect the whole chip */ +} MV_SFLASH_WP_REGION; + +/* Type Definitions */ +typedef struct +{ + MV_U8 opcdWREN; /* Write enable opcode */ + MV_U8 opcdWRDI; /* Write disable opcode */ + MV_U8 opcdRDID; /* Read ID opcode */ + MV_U8 opcdRDSR; /* Read Status Register opcode */ + MV_U8 opcdWRSR; /* Write Status register opcode */ + MV_U8 opcdREAD; /* Read opcode */ + MV_U8 opcdFSTRD; /* Fast Read opcode */ + MV_U8 opcdPP; /* Page program opcode */ + MV_U8 opcdSE; /* Sector erase opcode */ + MV_U8 opcdBE; /* Bulk erase opcode */ + MV_U8 opcdRES; /* Read electronic signature */ + MV_U8 opcdPwrSave; /* Go into power save mode */ + MV_U32 sectorSize; /* Size of each sector */ + MV_U32 sectorNumber; /* Number of sectors */ + MV_U32 pageSize; /* size of each page */ + const char * deviceModel; /* string with the device model */ + MV_U32 manufacturerId; /* The manufacturer ID */ + MV_U32 deviceId; /* Device ID */ + MV_U32 spiMaxFreq; /* The MAX frequency that can be used with the device */ + MV_U32 spiMaxFastFreq; /* The MAX frequency that can be used with the device for fast reads */ + MV_U32 spiFastRdDummyBytes; /* Number of dumy bytes to read before real data when working in fast read mode. */ +} MV_SFLASH_DEVICE_PARAMS; + +typedef struct +{ + MV_U32 baseAddr; /* Flash Base Address used in fast mode */ + MV_U8 manufacturerId; /* Manufacturer ID */ + MV_U16 deviceId; /* Device ID */ + MV_U32 sectorSize; /* Size of each sector - all the same */ + MV_U32 sectorNumber; /* Number of sectors */ + MV_U32 pageSize; /* Page size - affect allignment */ + MV_U32 index; /* index of the device in the sflash table (internal parameter) */ +} MV_SFLASH_INFO; + +/* Function Prototypes */ +/* Init */ +MV_STATUS mvSFlashInit (MV_SFLASH_INFO * pFlinfo); + +/* erase */ +MV_STATUS mvSFlashSectorErase (MV_SFLASH_INFO * pFlinfo, MV_U32 secNumber); +MV_STATUS mvSFlashChipErase (MV_SFLASH_INFO * pFlinfo); + +/* Read */ +MV_STATUS mvSFlashBlockRd (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, + MV_U8* pReadBuff, MV_U32 buffSize); +MV_STATUS mvSFlashFastBlockRd (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, + MV_U8* pReadBuff, MV_U32 buffSize); + +/* write regardless of the page boundaries and size limit per Page program command */ +MV_STATUS mvSFlashBlockWr (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, + MV_U8* pWriteBuff, MV_U32 buffSize); +/* Get IDs */ +MV_STATUS mvSFlashIdGet (MV_SFLASH_INFO * pFlinfo, MV_U8* pManId, MV_U16* pDevId); + +/* Set and Get the Write Protection region - if the Status register is not locked */ +MV_STATUS mvSFlashWpRegionSet (MV_SFLASH_INFO * pFlinfo, MV_SFLASH_WP_REGION wpRegion); +MV_STATUS mvSFlashWpRegionGet (MV_SFLASH_INFO * pFlinfo, MV_SFLASH_WP_REGION * pWpRegion); + +/* Lock the status register for writing - W/Vpp pin should be low to take effect */ +MV_STATUS mvSFlashStatRegLock (MV_SFLASH_INFO * pFlinfo, MV_BOOL srLock); + +/* Get the regions sizes */ +MV_U32 mvSFlashSizeGet (MV_SFLASH_INFO * pFlinfo); + +/* Cause the falsh device to go into power save mode */ +MV_STATUS mvSFlashPowerSaveEnter(MV_SFLASH_INFO * pFlinfo); +MV_STATUS mvSFlashPowerSaveExit (MV_SFLASH_INFO * pFlinfo); + +/* Retreive the string with the device manufacturer and model */ +const MV_U8 * mvSFlashModelGet (MV_SFLASH_INFO * pFlinfo); + +#endif /* __INCmvSFlashH */ diff --git a/board/mv_feroceon/mv_hal/sflash/mvSFlashSpec.h b/board/mv_feroceon/mv_hal/sflash/mvSFlashSpec.h new file mode 100644 index 0000000..cefc99f --- /dev/null +++ b/board/mv_feroceon/mv_hal/sflash/mvSFlashSpec.h @@ -0,0 +1,237 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSFlashSpecH +#define __INCmvSFlashSpecH + +/* Constants */ +#define MV_SFLASH_READ_CMND_LENGTH 4 /* 1B opcode + 3B address */ +#define MV_SFLASH_SE_CMND_LENGTH 4 /* 1B opcode + 3B address */ +#define MV_SFLASH_BE_CMND_LENGTH 1 /* 1B opcode */ +#define MV_SFLASH_PP_CMND_LENGTH 4 /* 1B opcode + 3B address */ +#define MV_SFLASH_WREN_CMND_LENGTH 1 /* 1B opcode */ +#define MV_SFLASH_WRDI_CMND_LENGTH 1 /* 1B opcode */ +#define MV_SFLASH_RDID_CMND_LENGTH 1 /* 1B opcode */ +#define MV_SFLASH_RDID_REPLY_LENGTH 3 /* 1B manf ID and 2B device ID */ +#define MV_SFLASH_RDSR_CMND_LENGTH 1 /* 1B opcode */ +#define MV_SFLASH_RDSR_REPLY_LENGTH 1 /* 1B status */ +#define MV_SFLASH_WRSR_CMND_LENGTH 2 /* 1B opcode + 1B status value */ +#define MV_SFLASH_DP_CMND_LENGTH 1 /* 1B opcode */ +#define MV_SFLASH_RES_CMND_LENGTH 1 /* 1B opcode */ + +/* Status Register Bit Masks */ +#define MV_SFLASH_STATUS_REG_WIP_OFFSET 0 /* bit 0; write in progress */ +#define MV_SFLASH_STATUS_REG_WP_OFFSET 2 /* bit 2-4; write protect option */ +#define MV_SFLASH_STATUS_REG_SRWD_OFFSET 7 /* bit 7; lock status register write */ +#define MV_SFLASH_STATUS_REG_WIP_MASK (0x1 << MV_SFLASH_STATUS_REG_WIP_OFFSET) +#define MV_SFLASH_STATUS_REG_SRWD_MASK (0x1 << MV_SFLASH_STATUS_REG_SRWD_OFFSET) + +#define MV_SFLASH_MAX_WAIT_LOOP 1000000 +#define MV_SFLASH_CHIP_ERASE_MAX_WAIT_LOOP 0x50000000 + +#define MV_SFLASH_DEFAULT_RDID_OPCD 0x9F /* Default Read ID */ +#define MV_SFLASH_DEFAULT_WREN_OPCD 0x06 /* Default Write Enable */ +#define MV_SFLASH_NO_SPECIFIC_OPCD 0x00 + +/********************************/ +/* ST M25Pxxx Device Specific */ +/********************************/ + +/* Manufacturer IDs and Device IDs for SFLASHs supported by the driver */ +#define MV_M25PXXX_ST_MANF_ID 0x20 +#define MV_M25P32_DEVICE_ID 0x2016 +#define MV_M25P32_MAX_SPI_FREQ 20000000 /* 20MHz */ +#define MV_M25P32_MAX_FAST_SPI_FREQ 50000000 /* 50MHz */ +#define MV_M25P32_FAST_READ_DUMMY_BYTES 1 +#define MV_M25P64_DEVICE_ID 0x2017 +#define MV_M25P64_MAX_SPI_FREQ 20000000 /* 20MHz */ +#define MV_M25P64_MAX_FAST_SPI_FREQ 50000000 /* 50MHz */ +#define MV_M25P64_FAST_READ_DUMMY_BYTES 1 +#define MV_M25P128_DEVICE_ID 0x2018 +#define MV_M25P128_MAX_SPI_FREQ 20000000 /* 20MHz */ +#define MV_M25P128_MAX_FAST_SPI_FREQ 50000000 /* 50MHz */ +#define MV_M25P128_FAST_READ_DUMMY_BYTES 1 + + +/* Sector Sizes and population per device model*/ +#define MV_M25P32_SECTOR_SIZE 0x10000 /* 64K */ +#define MV_M25P64_SECTOR_SIZE 0x10000 /* 64K */ +#define MV_M25P128_SECTOR_SIZE 0x40000 /* 256K */ +#define MV_M25P32_SECTOR_NUMBER 64 +#define MV_M25P64_SECTOR_NUMBER 128 +#define MV_M25P128_SECTOR_NUMBER 64 +#define MV_M25P_PAGE_SIZE 0x100 /* 256 byte */ + +#define MV_M25P_WREN_CMND_OPCD 0x06 /* Write Enable */ +#define MV_M25P_WRDI_CMND_OPCD 0x04 /* Write Disable */ +#define MV_M25P_RDID_CMND_OPCD 0x9F /* Read ID */ +#define MV_M25P_RDSR_CMND_OPCD 0x05 /* Read Status Register */ +#define MV_M25P_WRSR_CMND_OPCD 0x01 /* Write Status Register */ +#define MV_M25P_READ_CMND_OPCD 0x03 /* Sequential Read */ +#define MV_M25P_FAST_RD_CMND_OPCD 0x0B /* Fast Read */ +#define MV_M25P_PP_CMND_OPCD 0x02 /* Page Program */ +#define MV_M25P_SE_CMND_OPCD 0xD8 /* Sector Erase */ +#define MV_M25P_BE_CMND_OPCD 0xC7 /* Bulk Erase */ +#define MV_M25P_RES_CMND_OPCD 0xAB /* Read Electronic Signature */ + +/* Status Register Write Protect Bit Masks - 3bits */ +#define MV_M25P_STATUS_REG_WP_MASK (0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_NONE (0x00 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_1_OF_64 (0x01 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_1_OF_32 (0x02 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_1_OF_16 (0x03 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_1_OF_8 (0x04 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_1_OF_4 (0x05 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_1_OF_2 (0x06 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_M25P_STATUS_BP_ALL (0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET) + +/************************************/ +/* MXIC MX25L6405 Device Specific */ +/************************************/ + +/* Manufacturer IDs and Device IDs for SFLASHs supported by the driver */ +#define MV_MXIC_MANF_ID 0xC2 +#define MV_MX25L6405_DEVICE_ID 0x2017 +#define MV_MX25L6405_MAX_SPI_FREQ 20000000 /* 20MHz */ +#define MV_MX25L6405_MAX_FAST_SPI_FREQ 50000000 /* 50MHz */ +#define MV_MX25L6405_FAST_READ_DUMMY_BYTES 1 +#define MV_MXIC_DP_EXIT_DELAY 30 /* 30 ms */ + +/* Sector Sizes and population per device model*/ +#define MV_MX25L6405_SECTOR_SIZE 0x10000 /* 64K */ +#define MV_MX25L6405_SECTOR_NUMBER 128 +#define MV_MXIC_PAGE_SIZE 0x100 /* 256 byte */ + +#define MV_MX25L_WREN_CMND_OPCD 0x06 /* Write Enable */ +#define MV_MX25L_WRDI_CMND_OPCD 0x04 /* Write Disable */ +#define MV_MX25L_RDID_CMND_OPCD 0x9F /* Read ID */ +#define MV_MX25L_RDSR_CMND_OPCD 0x05 /* Read Status Register */ +#define MV_MX25L_WRSR_CMND_OPCD 0x01 /* Write Status Register */ +#define MV_MX25L_READ_CMND_OPCD 0x03 /* Sequential Read */ +#define MV_MX25L_FAST_RD_CMND_OPCD 0x0B /* Fast Read */ +#define MV_MX25L_PP_CMND_OPCD 0x02 /* Page Program */ +#define MV_MX25L_SE_CMND_OPCD 0xD8 /* Sector Erase */ +#define MV_MX25L_BE_CMND_OPCD 0xC7 /* Bulk Erase */ +#define MV_MX25L_DP_CMND_OPCD 0xB9 /* Deep Power Down */ +#define MV_MX25L_RES_CMND_OPCD 0xAB /* Read Electronic Signature */ + +/* Status Register Write Protect Bit Masks - 4bits */ +#define MV_MX25L_STATUS_REG_WP_MASK (0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_NONE (0x00 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_1_OF_128 (0x01 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_1_OF_64 (0x02 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_1_OF_32 (0x03 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_1_OF_16 (0x04 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_1_OF_8 (0x05 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_1_OF_4 (0x06 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_1_OF_2 (0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_MX25L_STATUS_BP_ALL (0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET) + +/************************************/ +/* SPANSION S25FL128P Device Specific */ +/************************************/ + +/* Manufacturer IDs and Device IDs for SFLASHs supported by the driver */ +#define MV_SPANSION_MANF_ID 0x01 +#define MV_S25FL128_DEVICE_ID 0x2018 +#define MV_S25FL128_MAX_SPI_FREQ 33000000 /* 33MHz */ +#define MV_S25FL128_MAX_FAST_SPI_FREQ 104000000 /* 104MHz */ +#define MV_S25FL128_FAST_READ_DUMMY_BYTES 1 + +/* Sector Sizes and population per device model*/ +//modfiy by QNAP: Support SPANSION SPI flash sector size for 64K +//#define MV_S25FL128_SECTOR_SIZE 0x40000 /* 256K */ +//#define MV_S25FL128_SECTOR_NUMBER 64 +#define MV_S25FL128_SECTOR_SIZE 0x10000 /* 64K */ +#define MV_S25FL128_SECTOR_NUMBER 256 +////////////////////////////////////////////////// +#define MV_S25FL_PAGE_SIZE 0x100 /* 256 byte */ + +#define MV_S25FL_WREN_CMND_OPCD 0x06 /* Write Enable */ +#define MV_S25FL_WRDI_CMND_OPCD 0x04 /* Write Disable */ +#define MV_S25FL_RDID_CMND_OPCD 0x9F /* Read ID */ +#define MV_S25FL_RDSR_CMND_OPCD 0x05 /* Read Status Register */ +#define MV_S25FL_WRSR_CMND_OPCD 0x01 /* Write Status Register */ +#define MV_S25FL_READ_CMND_OPCD 0x03 /* Sequential Read */ +#define MV_S25FL_FAST_RD_CMND_OPCD 0x0B /* Fast Read */ +#define MV_S25FL_PP_CMND_OPCD 0x02 /* Page Program */ +#define MV_S25FL_SE_CMND_OPCD 0xD8 /* Sector Erase */ +#define MV_S25FL_BE_CMND_OPCD 0xC7 /* Bulk Erase */ +#define MV_S25FL_DP_CMND_OPCD 0xB9 /* Deep Power Down */ +#define MV_S25FL_RES_CMND_OPCD 0xAB /* Read Electronic Signature */ + +/* Status Register Write Protect Bit Masks - 4bits */ +#define MV_S25FL_STATUS_REG_WP_MASK (0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_NONE (0x00 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_1_OF_128 (0x01 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_1_OF_64 (0x02 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_1_OF_32 (0x03 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_1_OF_16 (0x04 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_1_OF_8 (0x05 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_1_OF_4 (0x06 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_1_OF_2 (0x07 << MV_SFLASH_STATUS_REG_WP_OFFSET) +#define MV_S25FL_STATUS_BP_ALL (0x0F << MV_SFLASH_STATUS_REG_WP_OFFSET) + +#endif /* __INCmvSFlashSpecH */ + diff --git a/board/mv_feroceon/mv_hal/spi/mvSpi.c b/board/mv_feroceon/mv_hal/spi/mvSpi.c new file mode 100644 index 0000000..7393882 --- /dev/null +++ b/board/mv_feroceon/mv_hal/spi/mvSpi.c @@ -0,0 +1,573 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "spi/mvSpi.h" +#include "spi/mvSpiSpec.h" + +#include "ctrlEnv/mvCtrlEnvLib.h" + +/* #define MV_DEBUG */ +#ifdef MV_DEBUG +#define DB(x) x +#define mvOsPrintf printf +#else +#define DB(x) +#endif + + +/******************************************************************************* +* mvSpi16bitDataTxRx - Transmt and receive data +* +* DESCRIPTION: +* Tx data and block waiting for data to be transmitted +* +********************************************************************************/ +static MV_STATUS mvSpi16bitDataTxRx (MV_U16 txData, MV_U16 * pRxData) +{ + MV_U32 i; + MV_BOOL ready = MV_FALSE; + + /* First clear the bit in the interrupt cause register */ + MV_REG_WRITE(MV_SPI_INT_CAUSE_REG, 0x0); + + /* Transmit data */ + MV_REG_WRITE(MV_SPI_DATA_OUT_REG, MV_16BIT_LE(txData)); + + /* wait with timeout for memory ready */ + for (i=0; i> 8) & 0xFF); + +#elif defined(MV_CPU_BE) + + /* perform the data write to the buffer in two stages with 8bit each */ + MV_U8 * bptr = (MV_U8 *)pRxData; + MV_U16 data = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG)); + *bptr = ((data >> 8) & 0xFF); + ++bptr; + *bptr = (data & 0xFF); + +#else + #error "CPU endianess isn't defined!\n" +#endif + + } + else + *pRxData = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG)); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvSpi8bitDataTxRx - Transmt and receive data (8bits) +* +* DESCRIPTION: +* Tx data and block waiting for data to be transmitted +* +********************************************************************************/ +static MV_STATUS mvSpi8bitDataTxRx (MV_U8 txData, MV_U8 * pRxData) +{ + MV_U32 i; + MV_BOOL ready = MV_FALSE; + + /* First clear the bit in the interrupt cause register */ + MV_REG_WRITE(MV_SPI_INT_CAUSE_REG, 0x0); + + /* Transmit data */ + MV_REG_WRITE(MV_SPI_DATA_OUT_REG, txData); + + /* wait with timeout for memory ready */ + for (i=0; i serialBaudRate) + continue; + + /* check for exact fit */ + if ((cpuClk / preScale[i]) == serialBaudRate) + { + bestPrescaleIndx = i; + break; + } + + /* check if this is better than the previous one */ + if ((serialBaudRate - (cpuClk / preScale[i])) < minBaudOffset) + { + minBaudOffset = (serialBaudRate - (cpuClk / preScale[i])); + bestPrescaleIndx = i; + } + } + + if (bestPrescaleIndx > 14) + { + mvOsPrintf("%s ERROR: SPI baud rate prescale error!\n", __FUNCTION__); + return MV_OUT_OF_RANGE; + } + + /* configure the Prescale */ + tempReg = MV_REG_READ(MV_SPI_IF_CONFIG_REG); + tempReg = ((tempReg & ~MV_SPI_CLK_PRESCALE_MASK) | (bestPrescaleIndx + 0x12)); + MV_REG_WRITE(MV_SPI_IF_CONFIG_REG, tempReg); + + return MV_OK; +} + +/******************************************************************************* +* mvSpiCsAssert - Assert the Chip Select pin indicating a new transfer +* +* DESCRIPTION: +* Assert The chip select - used to select an external SPI device +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +********************************************************************************/ +MV_VOID mvSpiCsAssert(MV_VOID) +{ + /* For devices in which the SPI is muxed on the MPP with other interfaces*/ + mvMPPConfigToSPI(); + + MV_REG_BIT_SET(MV_SPI_IF_CTRL_REG, MV_SPI_CS_ENABLE_MASK); +} + +/******************************************************************************* +* mvSpiCsDeassert - DeAssert the Chip Select pin indicating the end of a +* SPI transfer sequence +* +* DESCRIPTION: +* DeAssert the chip select pin +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +********************************************************************************/ +MV_VOID mvSpiCsDeassert(MV_VOID) +{ + MV_REG_BIT_RESET(MV_SPI_IF_CTRL_REG, MV_SPI_CS_ENABLE_MASK); + + /* For devices in which the SPI is muxed on the MPP with other interfaces*/ + mvMPPConfigToDefault(); +} + +/******************************************************************************* +* mvSpiRead - Read a buffer over the SPI interface +* +* DESCRIPTION: +* Receive (read) a buffer over the SPI interface in 16bit chunks. If the +* buffer size is odd, then the last chunk will be 8bits. Chip select is not +* handled at this level. +* +* INPUT: +* pRxBuff: Pointer to the buffer to hold the received data +* buffSize: length of the pRxBuff +* +* OUTPUT: +* pRxBuff: Pointer to the buffer with the received data +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSpiRead (MV_U8* pRxBuff, MV_U32 buffSize) +{ + MV_STATUS ret; + MV_U32 bytesLeft = buffSize; + MV_U16* rxPtr = (MV_U16*)pRxBuff; + + /* check for null parameters */ + if (pRxBuff == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Check that the buffer pointer and the buffer size are 16bit aligned */ + if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pRxBuff & 1) == 0)) + { + /* Verify that the SPI mode is in 16bit mode */ + MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK); + + /* TX/RX as long we have complete 16bit chunks */ + while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE) + { + /* Transmitted and wait for the transfer to be completed */ + if ((ret = mvSpi16bitDataTxRx(MV_SPI_DUMMY_WRITE_16BITS, rxPtr)) != MV_OK) + return ret; + + /* increment the pointers */ + rxPtr++; + bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE; + } + + } + else + { + /* Verify that the SPI mode is in 8bit mode */ + MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK); + + /* TX/RX in 8bit chanks */ + while (bytesLeft > 0) + { + /* Transmitted and wait for the transfer to be completed */ + if ((ret = mvSpi8bitDataTxRx(MV_SPI_DUMMY_WRITE_8BITS, pRxBuff)) != MV_OK) + return ret; + /* increment the pointers */ + pRxBuff++; + bytesLeft--; + } + } + + return MV_OK; +} + +/******************************************************************************* +* mvSpiWrite - Transmit a buffer over the SPI interface +* +* DESCRIPTION: +* Transmit a buffer over the SPI interface in 16bit chunks. If the +* buffer size is odd, then the last chunk will be 8bits. No chip select +* action is taken. +* +* INPUT: +* pTxBuff: Pointer to the buffer holding the TX data +* buffSize: length of the pTxBuff +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSpiWrite(MV_U8* pTxBuff, MV_U32 buffSize) +{ + MV_STATUS ret; + MV_U32 bytesLeft = buffSize; + MV_U16* txPtr = (MV_U16*)pTxBuff; + + /* check for null parameters */ + if (pTxBuff == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Check that the buffer pointer and the buffer size are 16bit aligned */ + if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pTxBuff & 1) == 0)) + { + /* Verify that the SPI mode is in 16bit mode */ + MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK); + + /* TX/RX as long we have complete 16bit chunks */ + while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE) + { + /* Transmitted and wait for the transfer to be completed */ + if ((ret = mvSpi16bitDataTxRx(*txPtr, NULL)) != MV_OK) + return ret; + + /* increment the pointers */ + txPtr++; + bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE; + } + } + else + { + + /* Verify that the SPI mode is in 8bit mode */ + MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK); + + /* TX/RX in 8bit chanks */ + while (bytesLeft > 0) + { + /* Transmitted and wait for the transfer to be completed */ + if ((ret = mvSpi8bitDataTxRx(*pTxBuff, NULL)) != MV_OK) + return ret; + + /* increment the pointers */ + pTxBuff++; + bytesLeft--; + } + } + + return MV_OK; +} + + +/******************************************************************************* +* mvSpiReadWrite - Read and Write a buffer simultanuosely +* +* DESCRIPTION: +* Transmit and receive a buffer over the SPI in 16bit chunks. If the +* buffer size is odd, then the last chunk will be 8bits. The SPI chip +* select is not handled implicitely. +* +* INPUT: +* pRxBuff: Pointer to the buffer to write the RX info in +* pTxBuff: Pointer to the buffer holding the TX info +* buffSize: length of both the pTxBuff and pRxBuff +* +* OUTPUT: +* pRxBuff: Pointer of the buffer holding the RX data +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSpiReadWrite(MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize) +{ + MV_STATUS ret; + MV_U32 bytesLeft = buffSize; + MV_U16* txPtr = (MV_U16*)pTxBuff; + MV_U16* rxPtr = (MV_U16*)pRxBuff; + + /* check for null parameters */ + if ((pRxBuff == NULL) || (pTxBuff == NULL)) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* Check that the buffer pointer and the buffer size are 16bit aligned */ + if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pTxBuff & 1) == 0) && (((MV_U32)pRxBuff & 1) == 0)) + { + /* Verify that the SPI mode is in 16bit mode */ + MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK); + + /* TX/RX as long we have complete 16bit chunks */ + while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE) + { + /* Transmitted and wait for the transfer to be completed */ + if ((ret = mvSpi16bitDataTxRx(*txPtr, rxPtr)) != MV_OK) + return ret; + + /* increment the pointers */ + txPtr++; + rxPtr++; + bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE; + } + } + else + { + /* Verify that the SPI mode is in 8bit mode */ + MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK); + + /* TX/RX in 8bit chanks */ + while (bytesLeft > 0) + { + /* Transmitted and wait for the transfer to be completed */ + if ( (ret = mvSpi8bitDataTxRx(*pTxBuff, pRxBuff) ) != MV_OK) + return ret; + pRxBuff++; + pTxBuff++; + bytesLeft--; + } + } + + return MV_OK; +} + + diff --git a/board/mv_feroceon/mv_hal/spi/mvSpi.h b/board/mv_feroceon/mv_hal/spi/mvSpi.h new file mode 100644 index 0000000..74859f0 --- /dev/null +++ b/board/mv_feroceon/mv_hal/spi/mvSpi.h @@ -0,0 +1,94 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSpihH +#define __INCmvSpihH + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + +/* Function Prototypes */ +/* Init */ +MV_STATUS mvSpiInit (MV_U32 serialBaudRate); + +/* Set the Frequency of the Spi clock */ +MV_STATUS mvSpiBaudRateSet(MV_U32 serialBaudRate); + +/* Assert the SPI chip select */ +MV_VOID mvSpiCsAssert (MV_VOID); + +/* De-assert the SPI chip select */ +MV_VOID mvSpiCsDeassert (MV_VOID); + +/* Simultanuous Read and write */ +MV_STATUS mvSpiReadWrite (MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize); + +/* serialize a buffer on the TX line - Rx is ignored */ +MV_STATUS mvSpiWrite (MV_U8* pTxBuff, MV_U32 buffSize); + +/* read from the RX line by writing dummy values to the TX line */ +MV_STATUS mvSpiRead (MV_U8* pRxBuff, MV_U32 buffSize); + +#endif /* __INCmvSpihH */ diff --git a/board/mv_feroceon/mv_hal/spi/mvSpiCmnd.c b/board/mv_feroceon/mv_hal/spi/mvSpiCmnd.c new file mode 100644 index 0000000..b84b962 --- /dev/null +++ b/board/mv_feroceon/mv_hal/spi/mvSpiCmnd.c @@ -0,0 +1,250 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "spi/mvSpi.h" +#include "spi/mvSpiSpec.h" +#include "spi/mvSpiCmnd.h" + +/*#define MV_DEBUG*/ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + + +/******************************************************************************* +* mvSpiReadAndWrite - Read and Write a buffer simultanuousely +* +* DESCRIPTION: +* Transmit and receive a buffer over the SPI in 16bit chunks. If the +* buffer size is odd, then the last chunk will be 8bits. +* +* INPUT: +* pRxBuff: Pointer to the buffer to write the RX info in +* pTxBuff: Pointer to the buffer holding the TX info +* buffSize: length of both the pTxBuff and pRxBuff +* +* OUTPUT: +* pRxBuff: Pointer of the buffer holding the RX data +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSpiReadAndWrite(MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize) +{ + MV_STATUS ret; + + /* check for null parameters */ + if ((pRxBuff == NULL) || (pTxBuff == NULL) || (buffSize == 0)) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* First assert the chip select */ + mvSpiCsAssert(); + + ret = mvSpiReadWrite(pRxBuff, pTxBuff, buffSize); + + /* Finally deassert the chip select */ + mvSpiCsDeassert(); + + return ret; +} + +/******************************************************************************* +* mvSpiWriteThenWrite - Serialize a command followed by the data over the TX line +* +* DESCRIPTION: +* Assert the chip select line. Transmit the command buffer followed by +* the data buffer. Then deassert the CS line. +* +* INPUT: +* pCmndBuff: Pointer to the command buffer to transmit +* cmndSize: length of the command size +* pTxDataBuff: Pointer to the data buffer to transmit +* txDataSize: length of the data buffer +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSpiWriteThenWrite (MV_U8* pCmndBuff, MV_U32 cmndSize, MV_U8* pTxDataBuff, + MV_U32 txDataSize) +{ + MV_STATUS ret = MV_OK, tempRet; + + /* check for null parameters */ +#ifndef CONFIG_MARVELL + if(NULL == pTxDataBuff) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } +#endif + + if (pCmndBuff == NULL) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* First assert the chip select */ + mvSpiCsAssert(); + + /* first write the command */ + if ((cmndSize) && (pCmndBuff != NULL)) + { + if ((tempRet = mvSpiWrite(pCmndBuff, cmndSize)) != MV_OK) + ret = tempRet; + } + + /* Then write the data buffer */ +#ifndef CONFIG_MARVELL + if (txDataSize) +#else + if ((txDataSize) && (pTxDataBuff != NULL)) +#endif + { + if ((tempRet = mvSpiWrite(pTxDataBuff, txDataSize)) != MV_OK) + ret = tempRet; + } + + /* Finally deassert the chip select */ + mvSpiCsDeassert(); + + return ret; +} + +/******************************************************************************* +* mvSpiWriteThenRead - Serialize a command then read a data buffer +* +* DESCRIPTION: +* Assert the chip select line. Transmit the command buffer then read +* the data buffer. Then deassert the CS line. +* +* INPUT: +* pCmndBuff: Pointer to the command buffer to transmit +* cmndSize: length of the command size +* pRxDataBuff: Pointer to the buffer to read the data in +* txDataSize: length of the data buffer +* +* OUTPUT: +* pRxDataBuff: Pointer to the buffer holding the data +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvSpiWriteThenRead (MV_U8* pCmndBuff, MV_U32 cmndSize, MV_U8* pRxDataBuff, + MV_U32 rxDataSize,MV_U32 dummyBytesToRead) +{ + MV_STATUS ret = MV_OK, tempRet; + MV_U8 dummyByte; + + /* check for null parameters */ + if ((pCmndBuff == NULL) && (pRxDataBuff == NULL)) + { + mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); + return MV_BAD_PARAM; + } + + /* First assert the chip select */ + mvSpiCsAssert(); + + /* first write the command */ + if ((cmndSize) && (pCmndBuff != NULL)) + { + if ((tempRet = mvSpiWrite(pCmndBuff, cmndSize)) != MV_OK) + ret = tempRet; + } + + /* Read dummy bytes before real data. */ + while(dummyBytesToRead) + { + mvSpiRead(&dummyByte,1); + dummyBytesToRead--; + } + + /* Then write the data buffer */ + if ((rxDataSize) && (pRxDataBuff != NULL)) + { + if ((tempRet = mvSpiRead(pRxDataBuff, rxDataSize)) != MV_OK) + ret = tempRet; + } + + /* Finally deassert the chip select */ + mvSpiCsDeassert(); + + return ret; +} + diff --git a/board/mv_feroceon/mv_hal/spi/mvSpiCmnd.h b/board/mv_feroceon/mv_hal/spi/mvSpiCmnd.h new file mode 100644 index 0000000..329e26b --- /dev/null +++ b/board/mv_feroceon/mv_hal/spi/mvSpiCmnd.h @@ -0,0 +1,82 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSpiCmndhH +#define __INCmvSpiCmndhH + +#include "mvTypes.h" + +/* Function Prototypes */ + +/* Simultanuous Read and write */ +MV_STATUS mvSpiReadAndWrite (MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize); + +/* write command - write a command and then write data */ +MV_STATUS mvSpiWriteThenWrite (MV_U8* pCmndBuff, MV_U32 cmndSize, MV_U8* pTxDataBuff, MV_U32 txDataSize); + +/* read command - write a command and then read data by writing dummy data */ +MV_STATUS mvSpiWriteThenRead (MV_U8* pCmndBuff, MV_U32 cmndSize, MV_U8* pRxDataBuff, + MV_U32 rxDataSize,MV_U32 dummyBytesToRead); + +#endif /* __INCmvSpiCmndhH */ diff --git a/board/mv_feroceon/mv_hal/spi/mvSpiSpec.h b/board/mv_feroceon/mv_hal/spi/mvSpiSpec.h new file mode 100644 index 0000000..658159a --- /dev/null +++ b/board/mv_feroceon/mv_hal/spi/mvSpiSpec.h @@ -0,0 +1,98 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSpiSpecH +#define __INCmvSpiSpecH + +/* Constants */ +#define MV_SPI_WAIT_RDY_MAX_LOOP 100000 +#define MV_SPI_16_BIT_CHUNK_SIZE 2 +#define MV_SPI_DUMMY_WRITE_16BITS 0xFFFF +#define MV_SPI_DUMMY_WRITE_8BITS 0xFF + +/* Marvell Flash Device Controller Registers */ +#define MV_SPI_CTRLR_OFST 0x10600 +#define MV_SPI_IF_CTRL_REG (MV_SPI_CTRLR_OFST + 0x00) +#define MV_SPI_IF_CONFIG_REG (MV_SPI_CTRLR_OFST + 0x04) +#define MV_SPI_DATA_OUT_REG (MV_SPI_CTRLR_OFST + 0x08) +#define MV_SPI_DATA_IN_REG (MV_SPI_CTRLR_OFST + 0x0c) +#define MV_SPI_INT_CAUSE_REG (MV_SPI_CTRLR_OFST + 0x10) +#define MV_SPI_INT_CAUSE_MASK_REG (MV_SPI_CTRLR_OFST + 0x14) + +/* Serial Memory Interface Control Register Masks */ +#define MV_SPI_CS_ENABLE_OFFSET 0 /* bit 0 */ +#define MV_SPI_MEMORY_READY_OFFSET 1 /* bit 1 */ +#define MV_SPI_CS_ENABLE_MASK (0x1 << MV_SPI_CS_ENABLE_OFFSET) +#define MV_SPI_MEMORY_READY_MASK (0x1 << MV_SPI_MEMORY_READY_OFFSET) + +/* Serial Memory Interface Configuration Register Masks */ +#define MV_SPI_CLK_PRESCALE_OFFSET 0 /* bit 0-4 */ +#define MV_SPI_BYTE_LENGTH_OFFSET 5 /* bit 5 */ +#define MV_SPI_ADDRESS_BURST_LENGTH_OFFSET 8 /* bit 8-9 */ +#define MV_SPI_CLK_PRESCALE_MASK (0x1F << MV_SPI_CLK_PRESCALE_OFFSET) +#define MV_SPI_BYTE_LENGTH_MASK (0x1 << MV_SPI_BYTE_LENGTH_OFFSET) +#define MV_SPI_ADDRESS_BURST_LENGTH_MASK (0x3 << MV_SPI_ADDRESS_BURST_LENGTH_OFFSET) + +#endif /* __INCmvSpiSpecH */ + diff --git a/board/mv_feroceon/mv_hal/ts/mvTsu.c b/board/mv_feroceon/mv_hal/ts/mvTsu.c new file mode 100644 index 0000000..ac059ba --- /dev/null +++ b/board/mv_feroceon/mv_hal/ts/mvTsu.c @@ -0,0 +1,1742 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvTsu.h" +#include "ctrlEnv/mvCtrlEnvLib.h" + +/********************************/ +/* Local enums and structures */ +/********************************/ +#define TSU_MIN_PKT_SIZE 188 +#define TSU_MAX_PKT_SIZE 256 +#define TSU_NUM_CLOCK_DIVIDERS 6 + +typedef struct +{ + MV_U32 aggrMode; + MV_U16 pktSize; + MV_TSU_PORT_DIRECTION portDir; + MV_ULONG descPhyAddr; + MV_U32 *descVirtAddr; + MV_U32 descMemHandle; + MV_U32 numTsDesc; + MV_U32 numDoneQEntry; + MV_U32 aggrNumPckts; + MV_U32 *tsDataBuff; + MV_U32 *tsDoneBuff; + MV_U32 dataBlockSize; + MV_U32 dataReadIdx; + MV_U32 statReadIdx; + MV_U32 cpuRollBit; + MV_U32 descSize; + MV_U32 queueMask; + MV_BOOL enableTimer; +}MV_TSU_PORT_CTRL; + +typedef struct +{ + MV_U32 numActPorts; + MV_TSU_PORTS_MODE mode; + MV_TSU_CORE_CLOCK coreClock; + void *osHandle; +}MV_TSU_CTRL; + +/********************************/ +/* Local Macros */ +/********************************/ +#define TS_SIGNAL_PARAMS_CONFIG(cfg,usedMask,polMask,reg) \ + { \ + if(cfg != TSU_SIGNAL_KEEP_DEF) \ + { \ + reg &= ~(usedMask | polMask); \ + if(cfg != TSU_SIGNAL_DIS) \ + { \ + reg |= usedMask; \ + if(cfg == TSU_SIGNAL_EN_ACT_HIGH) \ + reg |= polMask; \ + } \ + } \ + } + +#define TS_SIGNAL_PARAMS_GET(cfg,usedMask,polMask,reg) \ + { \ + if(reg & usedMask) \ + { \ + if(reg & polMask) \ + cfg = TSU_SIGNAL_EN_ACT_HIGH; \ + else \ + cfg = TSU_SIGNAL_EN_ACT_LOW; \ + } \ + else \ + { \ + cfg = TSU_SIGNAL_DIS; \ + } \ + } + + + +#define TSU_SET_DESC_BUFF_PTR(desc,addr) (*(MV_U32*)desc) = addr +#define TSU_SET_OUT_DESC_TMSTMP(desc,tms,err) \ + (*((MV_U32*)desc + 1)) = (tms | (err << 28)) + +#define TSU_BUFF_HNDL(d, s) (MV_U32) ((d & 0xFFFF) | ((s & 0xFFFF) << 16)) +#define TSU_BUFF_HNDL_2_DATA_IDX(h) (MV_U32)(h & 0xFFFF) +#define TSU_BUFF_HNDL_2_STAT_IDX(h) (MV_U32)((h >> 16) & 0xFFFF) + +/********************************/ +/* Control variables. */ +/********************************/ +MV_U32 mvTsuCoreClock2Val[] = { + 83 * _1M, /* TSU_CORE_CLK_83_MHZ */ + 71 * _1M, /* TSU_CORE_CLK_71_MHZ */ + 91 * _1M, /* TSU_CORE_CLK_91_MHZ */ + 100 * _1M /* TSU_CORE_CLK_100_MHZ */ +}; +MV_TSU_CTRL mvTsuCtrl; +MV_TSU_PORT_CTRL mvTsuPortCtrl[MV_TSU_NUM_PORTS]; + + +/********************************/ +/* Forward functions declaration*/ +/********************************/ +inline static MV_STATUS mvTsuOperationModeSet(MV_U8 port, MV_BOOL enable); +static MV_STATUS mvTsuReadyBuffCountGet(MV_U8 port, MV_U32 *numBlocks, + MV_U32 *numBuffers); +static MV_STATUS mvTsuPortEnable(MV_U8 port,MV_BOOL enable); + +/********************************/ +/* Functions Implementation */ +/********************************/ + + +/******************************************************************************* +* mvTsuHalInit +* +* DESCRIPTION: +* Initialize the TSU unit, and get unit out of reset. +* +* INPUT: +* coreClock - The core clock at which the TSU should operate. +* mode - The mode on configure the unit into (serial/parallel). +* osHandle - Memory handle used for memory allocations. +* OUTPUT: +* None. +* RETURN: +* MV_OK - on success, +* +*******************************************************************************/ +MV_STATUS mvTsuHalInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode, + void *osHandle) +{ + MV_U32 reg; + MV_U32 port; + + /* Setup the core clock. */ + reg = MV_REG_READ(MV_TSU_MODES_REG); + reg &= TSU_MODES_TSCK_MASK; + reg |= (coreClock << TSU_MODES_TSCK_OFF); + + /* Configure the mode */ + reg &= ~TSU_MODES_PAR_MODE_MASK; + if(mode == TSU_MODE_SERIAL) { + reg |= TSU_MODES_PAR_MODE_SER; + mvTsuCtrl.numActPorts = 2; + } else { + reg |= TSU_MODES_PAR_MODE_PAR; + mvTsuCtrl.numActPorts = 1; + } + MV_REG_WRITE(MV_TSU_MODES_REG,reg); + + /* Get ports out of reset. */ + for(port = 0; port < MV_TSU_NUM_PORTS; port++) + mvTsuPortReset(port); + + /* Setup control veraibles. */ + mvTsuCtrl.coreClock = coreClock; + mvTsuCtrl.osHandle = osHandle; + mvTsuCtrl.mode = mode; + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuShutdown +* +* DESCRIPTION: +* Shutdown the TS unit, and put into reset state. +* +* INPUT: +* None. +* OUTPUT: +* None. +* RETURN: +* MV_OK - on success, +* +*******************************************************************************/ +MV_STATUS mvTsuShutdown(void) +{ + //... + // Check if it's possible to put the module back into reset mode. + return MV_NOT_IMPLEMENTED; +} + + +/******************************************************************************* +* mvTsuPortReset +* +* DESCRIPTION: +* Perform a SW reset on a given port. +* +* INPUT: +* port - The port number to reset. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_BAD_VALUE - Bad port configuration option. +* MV_BAD_SIZE - Illegal number of ports. +* +*******************************************************************************/ +MV_STATUS mvTsuPortReset(MV_U8 port) +{ + MV_U32 reg; + + /* Check the correctness of parameters. */ + if(port >= MV_TSU_NUM_PORTS) + return MV_BAD_SIZE; + + /* First, set in reset mode, then get out of reset. */ + reg = MV_REG_READ(MV_TSU_CONFIG_REG(port)); + reg &= ~TSU_CFG_RESET_MASK; + reg |= TSU_CFG_RESET_SET; + MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg); + reg &= ~TSU_CFG_RESET_MASK; + reg |= TSU_CFG_RESET_CLEAR; + MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuPortInit +* +* DESCRIPTION: +* Initialize the TSU ports. +* +* INPUT: +* port - The port number to configure. +* portCfg - Port configurations parameters. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_BAD_VALUE - Bad port configuration option. +* MV_BAD_SIZE - Illegal number of ports. +* +*******************************************************************************/ +MV_STATUS mvTsuPortInit(MV_U8 port, MV_TSU_PORT_CONFIG *portCfg) +{ + MV_U32 reg; + + /* Check the correctness of parameters. */ + if(((mvTsuCtrl.mode == TSU_MODE_SERIAL) && (port >= MV_TSU_NUM_PORTS))|| + ((mvTsuCtrl.mode == TSU_MODE_PARALLEL) && (port >= 1))) + return MV_BAD_SIZE; + + if((portCfg->pktSize < TSU_MIN_PKT_SIZE) || + (portCfg->pktSize > TSU_MAX_PKT_SIZE)) + return MV_BAD_VALUE; + + /* configure the port parameters */ + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_CONFIG_REG(port)); + + /* Setup packet size. */ + reg &= ~TSU_CFG_PKT_SIZE_MASK; + reg |= (((portCfg->pktSize - 1) & 0xFF) << TSU_CFG_PKT_SIZE_OFFS); + + /* Setup data direction. */ + reg &= ~TSU_CFG_DATA_DIR_MASK; + if(portCfg->portDir == TSU_PORT_INPUT) + reg |= TSU_CFG_DATA_DIR_IN; + else + reg |= TSU_CFG_DATA_DIR_OUT; + + /* Setup serial / parallel mode. */ + reg &= ~TSU_CFG_DATA_MODE_MASK; + if(mvTsuCtrl.mode == TSU_MODE_SERIAL) + reg |= TSU_CFG_DATA_MODE_SER; + else + reg |= TSU_CFG_DATA_MODE_PAR; + + MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg); + + /* Setup DMA packet size. */ + reg = MV_REG_READ(MV_TSU_DMA_PARAMS_REG(port)); + reg &= ~TSU_DMAP_DMA_LEN_MASK; + reg |= portCfg->pktSize; + MV_REG_WRITE(MV_TSU_DMA_PARAMS_REG(port),reg); + + /* Setup timestamp auto adjust. */ + if(portCfg->portDir == TSU_PORT_OUTPUT) + { + reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port)); + reg &= ~TSU_TMS_CTRL_AUTO_ADJ_MASK; + reg |= TSU_TMS_CTRL_AUTO_ADJ_ON; + MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg); + } + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + + /* Update global control vars. */ + mvTsuPortCtrl[port].pktSize = portCfg->pktSize; + mvTsuPortCtrl[port].portDir = portCfg->portDir; + + MV_REG_BIT_SET(MV_TSU_CONFIG_REG(port),(1 << 17)); + return MV_OK; +} + + +/******************************************************************************* +* mvTsuPortSignalCfgSet +* +* DESCRIPTION: +* Configure port signals parameters. +* +* INPUT: +* port - The port to configure. +* signalCfg - Signal configuration options. +* serialflags - Serial signal configuration options (valid only if the +* port is working in serial mode). +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_BAD_VALUE - Bad port configuration option. +* MV_BAD_SIZE - Illegal number of ports. +* +*******************************************************************************/ +MV_STATUS mvTsuPortSignalCfgSet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg, + MV_U32 serialFlags) +{ + MV_U32 reg; + + if(port >= MV_TSU_NUM_PORTS) + return MV_OUT_OF_RANGE; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_CONFIG_REG(port)); + + /* Setup signal related options. */ + TS_SIGNAL_PARAMS_CONFIG(signalCfg->tsSync, + TSU_CFG_SYNC_USED_MASK, + TSU_CFG_SYNC_POL_MASK,reg); + TS_SIGNAL_PARAMS_CONFIG(signalCfg->tsValid, + TSU_CFG_VAL_USED_MASK, + TSU_CFG_VAL_POL_MASK,reg); + TS_SIGNAL_PARAMS_CONFIG(signalCfg->tsError, + TSU_CFG_ERR_USED_MASK, + TSU_CFG_ERR_POL_MASK,reg); + + if(signalCfg->tsDataEdge != TSU_SIGNAL_EDGE_KEEP_DEF) + { + if(signalCfg->tsDataEdge == TSU_SIGNAL_EDGE_FALL) + reg |= TSU_CFG_TX_EDGE_MASK; + else + reg &= ~TSU_CFG_TX_EDGE_MASK; + } + + /* Setup serial mode related configurations. */ + if(mvTsuCtrl.mode == TSU_MODE_SERIAL) + { + if(serialFlags & MV_TSU_SER_DATA_ORDER_MASK) + { + reg &= ~TSU_CFG_DATA_ORD_MASK; + if(serialFlags & MV_TSU_SER_DATA_ORDER_MSB) + reg |= TSU_CFG_DATA_ORD_MSB; + else if(serialFlags & MV_TSU_SER_DATA_ORDER_LSB) + reg |= TSU_CFG_DATA_ORD_LSB; + } + + if(serialFlags & MV_TSU_SER_SYNC_ACT_LEN_MASK) + { + reg &= ~TSU_CFG_TS_SYNC_MASK; + if(serialFlags & MV_TSU_SER_SYNC_ACT_1_BIT) + reg |= TSU_CFG_TS_SYNC_1BIT; + else if(serialFlags & MV_TSU_SER_SYNC_ACT_8_BIT) + reg |= TSU_CFG_TS_SYNC_8BIT; + } + + if(serialFlags & MV_TSU_SER_TX_CLK_MODE_MASK) + { + reg &= ~TSU_CFG_CLK_MODE_MASK; + if(serialFlags & MV_TSU_SER_TX_CLK_MODE_GAPPED) + reg |= TSU_CFG_CLK_MODE_GAPPED; + else if(serialFlags & MV_TSU_SER_TX_CLK_MODE_CONT) + reg |= TSU_CFG_CLK_MODE_CONT; + } + } + + MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuPortSignalCfgGet +* +* DESCRIPTION: +* Get port signals parameters. +* +* INPUT: +* port - The port to configure. +* OUTPUT: +* signalCfg - Signal configuration options. +* serialflags - Serial signal configuration options (valid only if the +* port is working in serial mode). +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Illegal port number. +* MV_BAD_PARAM - Bad pointers. +* +*******************************************************************************/ +MV_STATUS mvTsuPortSignalCfgGet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg, + MV_U32* serialFlags) +{ + MV_U32 reg; + + if(port >= MV_TSU_NUM_PORTS) + return MV_OUT_OF_RANGE; + + if((signalCfg == NULL) || + ( (mvTsuCtrl.mode == TSU_MODE_SERIAL) && (serialFlags == NULL))) + return MV_BAD_PARAM; + + reg = MV_REG_READ(MV_TSU_CONFIG_REG(port)); + + /* Setup signal related options. */ + TS_SIGNAL_PARAMS_GET(signalCfg->tsSync,TSU_CFG_SYNC_USED_MASK, + TSU_CFG_SYNC_POL_MASK,reg); + TS_SIGNAL_PARAMS_GET(signalCfg->tsValid,TSU_CFG_VAL_USED_MASK, + TSU_CFG_VAL_POL_MASK,reg); + TS_SIGNAL_PARAMS_GET(signalCfg->tsError,TSU_CFG_ERR_USED_MASK, + TSU_CFG_ERR_POL_MASK,reg); + + if(reg & TSU_CFG_TX_EDGE_MASK) + signalCfg->tsDataEdge = TSU_SIGNAL_EDGE_FALL; + else + signalCfg->tsDataEdge = TSU_SIGNAL_EDGE_RISE; + + /* Setup serial mode related configurations. */ + if(mvTsuCtrl.mode == TSU_MODE_SERIAL) + { + *serialFlags = 0; + + if((reg & TSU_CFG_DATA_ORD_MASK) == TSU_CFG_DATA_ORD_LSB) + *serialFlags |= MV_TSU_SER_DATA_ORDER_LSB; + else + *serialFlags |= MV_TSU_SER_DATA_ORDER_MSB; + + if((reg & TSU_CFG_TS_SYNC_MASK) == TSU_CFG_TS_SYNC_1BIT) + *serialFlags |= MV_TSU_SER_SYNC_ACT_1_BIT; + else + *serialFlags |= MV_TSU_SER_SYNC_ACT_8_BIT; + + if((reg & TSU_CFG_CLK_MODE_MASK) == MV_TSU_SER_TX_CLK_MODE_GAPPED) + *serialFlags |= TSU_CFG_CLK_MODE_GAPPED; + else + *serialFlags |= TSU_CFG_CLK_MODE_CONT; + } + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuStatusGet +* +* DESCRIPTION: +* Get the TSU port status for a given port. +* +* INPUT: +* port - The port number to configure. +* OUTPUT: +* status - Bitmask representing the TSU port status (a bitwise or +* between the MV_TSU_STATUS_* macros. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuStatusGet(MV_U8 port, MV_U32 *status) +{ + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + { + return MV_OUT_OF_RANGE; + } + + reg = MV_REG_READ(MV_TSU_STATUS_REG(port)); + reg &= TSU_STATUS_MASK; + + *status = 0; + if(reg & TSU_STATUS_IF_ERR) + *status |= MV_TSU_STATUS_TSIF_ERROR; + if(reg & TSU_STATUS_FIFO_OVFL_ERR) + *status |= MV_TSU_STATUS_OVFL_ERROR; + if(reg & TSU_STATUS_CONN_ERR) + *status |= MV_TSU_STATUS_CONN_ERROR; + return MV_OK; +} + + +/******************************************************************************* +* mvTsuBuffersInit +* +* DESCRIPTION: +* Initialize the TSU unit buffers. +* This function is used to initialize both Rx or Tx buffers according to +* the port mode configured in mvTsuPortsInit(). +* +* INPUT: +* port - The port number to configure. +* buffInfo- TSU buffer information. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad buffer configuration options. +* MV_NOT_ALIGNED - Bad data buffer alignemed. +* +*******************************************************************************/ +MV_STATUS mvTsuBuffersInit(MV_U8 port, MV_TSU_BUFF_INFO *buffInfo) +{ + MV_U32 reg; + MV_U32 descSize; + MV_U32 i; + MV_U8 *tsDataBuff; + MV_U32 *descEntry; + MV_U32 phyAddr; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + + if( ( (buffInfo->aggrMode != MV_TSU_AGGR_MODE_DISABLED) && + ( (buffInfo->aggrMode2TmstmpOff > 0xF ) || + (buffInfo->aggrMode2TmstmpOff < 4 ) || + (buffInfo->aggrNumPackets <= 1) || + (buffInfo->numDoneQEntry < buffInfo->aggrNumPackets) ) ) || + (!MV_IS_POWER_OF_2(buffInfo->numTsDesc) ) || + (!MV_IS_POWER_OF_2(buffInfo->numDoneQEntry) ) || + (buffInfo->numTsDesc == 0) || + (buffInfo->numDoneQEntry == 0) || + (buffInfo->numDoneQEntry > MV_TSU_MAX_DONEQ_LEN) || + ( (mvTsuPortCtrl[port].portDir == TSU_PORT_INPUT) && + (buffInfo->numTsDesc > MV_TSU_MAX_IN_QUEUE_LEN) ) || + ( (mvTsuPortCtrl[port].portDir == TSU_PORT_OUTPUT) && + (buffInfo->numTsDesc > MV_TSU_MAX_OUT_QUEUE_LEN) ) ) + { + return MV_BAD_PARAM; + } + + /* Check buffer alignment. */ + if( ( (buffInfo->aggrMode == MV_TSU_AGGR_MODE_2) && + (((buffInfo->tsDataBuffPhys + buffInfo->aggrMode2TmstmpOff) & + (TSU_DMA_ALIGN - 1)) != 0) ) || + ( (buffInfo->aggrMode == MV_TSU_AGGR_MODE_DISABLED) && + (buffInfo->tsDataBuffPhys & (TSU_DMA_ALIGN - 1)) != 0 ) ) + { + return MV_NOT_ALIGNED; + } + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + /* Setup aggregation mode. */ + reg = MV_REG_READ(MV_TSU_AGGREGATION_CTRL_REG(port)); + reg &= ~TSU_AGGR_ENABLE_MASK; + if(buffInfo->aggrMode == MV_TSU_AGGR_MODE_DISABLED) + { + reg |= TSU_AGGR_DISABLE; + mvTsuPortCtrl[port].aggrNumPckts = 1; + } + else + { + reg |= TSU_AGGR_ENABLE; + + reg &= ~TSU_AGGR_TMSTMP_OFF_MASK; + if(buffInfo->aggrMode == MV_TSU_AGGR_MODE_2) + { + reg |= (buffInfo->aggrMode2TmstmpOff << + TSU_AGGR_TMSTMP_OFF_OFFS); + reg &= ~TSU_AGGR_TMSTMP_MODE_MASK; + reg |= TSU_AGGR_TMSTMP_TO_PCKT; + } + + reg &= ~TSU_AGGR_PCKT_NUM_MASK; + reg |= (buffInfo->aggrNumPackets << TSU_AGGR_PCKT_NUM_OFFS); + + MV_REG_WRITE(MV_TSU_AGGREGATION_CTRL_REG(port),reg); + mvTsuPortCtrl[port].aggrNumPckts = buffInfo->aggrNumPackets; + } + + mvTsuPortCtrl[port].aggrMode = buffInfo->aggrMode; + if(mvTsuPortCtrl[port].portDir == TSU_PORT_INPUT) + descSize = TSU_INPUT_DESC_ENTRY_SIZE; + else + descSize = TSU_OUTPUT_DESC_ENTRY_SIZE; + + /* Initialize descriptor data. */ + mvTsuPortCtrl[port].descVirtAddr = mvOsIoUncachedMalloc( + mvTsuCtrl.osHandle,descSize * buffInfo->numTsDesc, + &(mvTsuPortCtrl[port].descPhyAddr), + &(mvTsuPortCtrl[port].descMemHandle)); + + /* Initialize the descriptors list with buffer pointers. */ + descEntry = (MV_U32*)mvTsuPortCtrl[port].descVirtAddr; + tsDataBuff = (MV_U8*)buffInfo->tsDataBuff; + phyAddr = buffInfo->tsDataBuffPhys; + for(i = 0; i < buffInfo->numTsDesc; i++) + { + TSU_SET_DESC_BUFF_PTR(descEntry,phyAddr); + descEntry += (descSize >> 2); + tsDataBuff += buffInfo->dataBlockSize; + phyAddr += buffInfo->dataBlockSize; + } + + mvTsuPortCtrl[port].queueMask = + ~(0xFFFFFFFF << mvLog2(buffInfo->numTsDesc * descSize)); + + if(mvTsuPortCtrl[port].portDir == TSU_PORT_INPUT) + mvTsuPortCtrl[port].cpuRollBit = + mvTsuPortCtrl[port].queueMask + 1; + else + mvTsuPortCtrl[port].cpuRollBit = 0; + + /* Write the read / write pointers for data & status buffers. */ + + /* Desc start pointer. */ + phyAddr = mvTsuPortCtrl[port].descPhyAddr; + MV_REG_WRITE(MV_TSU_DESC_QUEUE_BASE_REG(port),phyAddr); + + /* Desc read pointer. */ + MV_REG_WRITE(MV_TSU_DESC_QUEUE_READ_PTR_REG(port), + 0 << TSU_DESC_READ_PTR_OFFS); + + /* Desc write pointer. */ + MV_REG_WRITE(MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port), + mvTsuPortCtrl[port].cpuRollBit); + + /* Done start pointer. */ + phyAddr = buffInfo->tsDoneBuffPhys; + MV_REG_WRITE(MV_TSU_DONE_QUEUE_BASE_REG(port),phyAddr); + + /* Done read pointer. */ + MV_REG_WRITE(MV_TSU_DONE_QUEUE_READ_PTR_REG(port), + 0 << TSU_DONE_READ_PTR_OFFS); + + /* Done write pointer. */ + MV_REG_WRITE(MV_TSU_DONE_QUEUE_WRITE_PTR_REG(port), + mvTsuPortCtrl[port].cpuRollBit);//0 << TSU_DONE_WRITE_PTR_OFFS); + + /* Done & Data queues size. */ + reg = MV_REG_READ(MV_TSU_DMA_PARAMS_REG(port)); + reg &= ~(TSU_DMAP_DESC_Q_SIZE_MASK | TSU_DMAP_DONE_Q_SIZE_MASK); + + i = mvLog2((buffInfo->numTsDesc * descSize) >> 2); + reg |= (i << TSU_DMAP_DESC_Q_SIZE_OFFS); + + i = mvLog2((buffInfo->numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE) >> 2); + reg |= (i << TSU_DMAP_DONE_Q_SIZE_OFFS); + + MV_REG_WRITE(MV_TSU_DMA_PARAMS_REG(port),reg); + + mvTsuPortCtrl[port].descSize = descSize; + mvTsuPortCtrl[port].numTsDesc = buffInfo->numTsDesc; + mvTsuPortCtrl[port].numDoneQEntry = buffInfo->numDoneQEntry; + mvTsuPortCtrl[port].tsDataBuff = buffInfo->tsDataBuff; + mvTsuPortCtrl[port].tsDoneBuff = buffInfo->tsDoneBuff; + mvTsuPortCtrl[port].dataBlockSize = buffInfo->dataBlockSize; + mvTsuPortCtrl[port].dataReadIdx = 0; + mvTsuPortCtrl[port].statReadIdx = 0; + mvTsuPortCtrl[port].enableTimer = MV_FALSE; + + mvTsuPortEnable(port,MV_TRUE); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuPortShutdown +* +* DESCRIPTION: +* Shutdown the port, this will release any previously allocated port +* memory, and set the port to disable state. +* +* INPUT: +* port - The port number to shutdown. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad buffer configuration options. +* +*******************************************************************************/ +MV_STATUS mvTsuPortShutdown(MV_U8 port) +{ + MV_TSU_PORT_CTRL *portCtrl; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + /* Disable the port. */ + mvTsuPortEnable(port,MV_FALSE); + + /* Free descriptors buffer. */ + portCtrl = &mvTsuPortCtrl[port]; + mvOsIoUncachedFree(mvTsuCtrl.osHandle, + portCtrl->descSize * portCtrl->numTsDesc, + portCtrl->descPhyAddr,portCtrl->descVirtAddr, + portCtrl->descMemHandle); + return MV_OK; +} + + +/******************************************************************************* +* mvTsuDmaWatermarkSet +* +* DESCRIPTION: +* Set the watermark for starting a DMA transfer from / to the TSU +* internal FIFO to the CPU memory. +* +* INPUT: +* port - The port number to configure. +* watermark - The watermark to configure (in DWORD units). +* For Rx: Number of data DWORDS in FIFO to start DMA. +* For Tx: Number of free DWORDS in FIFO to start DMA. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad watermark value.. +* +*******************************************************************************/ +MV_STATUS mvTsuDmaWatermarkSet(MV_U8 port, MV_U32 watermark) +{ + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(watermark > TSU_DMAP_DATA_WTRMK_MAX) + return MV_BAD_PARAM; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_DMA_PARAMS_REG(port)); + reg &= ~TSU_DMAP_DATA_WTRMK_MASK; + reg |= (watermark << TSU_DMAP_DATA_WTRMK_OFFS); + MV_REG_WRITE(MV_TSU_DMA_PARAMS_REG(port),reg); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuAggrMode1TmsOnPcktEn +* +* DESCRIPTION: +* Set the TSU unit to add the timestamp to the packet buffer when working +* in aggregation mode-1. +* +* INPUT: +* port - The port number to configure. +* enable - When True, enables the placement of timestamp data in the +* packet buffer. +* When False, the timestamp is placed in the Done-Queue. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuAggrMode1TmsOnPcktEn(MV_U8 port, MV_BOOL enable) +{ + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_AGGREGATION_CTRL_REG(port)); + reg &= ~TSU_AGGR_TMSTMP_MODE_MASK; + if(enable == MV_TRUE) + reg |= TSU_AGGR_TMSTMP_TO_PCKT; + else + reg |= TSU_AGGR_TMSTMP_TO_DONE_Q; + MV_REG_WRITE(MV_TSU_AGGREGATION_CTRL_REG(port),reg); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + + return MV_OK; +} + + +/********************************/ +/* Rx related APIs */ +/********************************/ + + +/******************************************************************************* +* mvTsuRxSyncDetectionSet +* +* DESCRIPTION: +* Set TS synchronization parameters for Rx data. +* +* INPUT: +* port - The port number to configure. +* syncDetect - Number of TS sync matches to lock signal. +* syncLoss - Number of TS sync losses to unlock signal. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad sync values configuration. +* +*******************************************************************************/ +MV_STATUS mvTsuRxSyncDetectionSet(MV_U8 port, MV_U8 syncDetect, MV_U8 syncLoss) +{ + MV_U32 reg; + MV_U8 maxVal; + + if(port >= MV_TSU_NUM_PORTS) + return MV_OUT_OF_RANGE; + + maxVal = TSU_SYNC_LOSS_CNT_MASK >> TSU_SYNC_LOSS_CNT_OFFS; + if((syncDetect > maxVal) || (syncLoss > maxVal)) + return MV_BAD_PARAM; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_SYNCBYTE_DETECT_REG(port)); + reg &= ~(TSU_SYNC_LOSS_CNT_MASK | TSU_SYNC_DETECT_CNT_MASK); + reg |= ((syncDetect << TSU_SYNC_DETECT_CNT_OFFS) | + (syncLoss << TSU_SYNC_LOSS_CNT_OFFS)); + MV_REG_WRITE(MV_TSU_SYNCBYTE_DETECT_REG(port),reg); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuRxSyncDetectionGet +* +* DESCRIPTION: +* Get TS synchronization parameters for Rx data. +* +* INPUT: +* port - The port number. +* OUTPUT: +* syncDetect - Number of TS sync matches to lock signal. +* syncLoss - Number of TS sync losses to unlock signal. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad pointers. +* +*******************************************************************************/ +MV_STATUS mvTsuRxSyncDetectionGet(MV_U8 port, MV_U8 *syncDetect, MV_U8 *syncLoss) +{ + MV_U32 reg; + + if(port >= MV_TSU_NUM_PORTS) + return MV_OUT_OF_RANGE; + + if((syncDetect == NULL) || (syncLoss == NULL)) + return MV_BAD_PARAM; + + reg = MV_REG_READ(MV_TSU_SYNCBYTE_DETECT_REG(port)); + + *syncDetect = (reg & TSU_SYNC_DETECT_CNT_MASK) >> TSU_SYNC_DETECT_CNT_OFFS; + *syncLoss = (reg & TSU_SYNC_LOSS_CNT_MASK) >> TSU_SYNC_LOSS_CNT_OFFS; + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuRxFullBuffCountGet +* +* DESCRIPTION: +* Get number of Rx packets ready for CPU processing. +* +* INPUT: +* port - TSU port number. +* OUTPUT: +* numBlocks - Number of data blocks ready for CPU processing +* (already have data for processing). +* numBuffers - Number of buffers ready for CPU processing (already +* have data for processing). +* In non-aggreagtion mode numBlocks == numBuffers. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NOT_SUPPORTED- If the port is not configured in input mode. +* +*******************************************************************************/ +MV_STATUS mvTsuRxFullBuffCountGet(MV_U8 port, MV_U32 *numBlocks, + MV_U32 *numBuffers) +{ + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT) + return MV_NOT_SUPPORTED; + return mvTsuReadyBuffCountGet(port,numBlocks,numBuffers); +} + +/******************************************************************************* +* mvTsuRxNextBuffGet +* +* DESCRIPTION: +* Get a pointer to the next available Rx data & status buffers from the Rx +* queue. +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to return the address of the next data buffer. +* statBuff - Pointer to return the address of the next status +* buffer. +* OUTPUT: +* buffsHandle - A handle returned to the user to be used when freeing +* the buffers in mvTsuRxBuffFree(). +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad parameters. +* MV_NOT_SUPPORTED- Functionality not supported by the port configuration. +* MV_NO_MORE - No Rx data is available for copy. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* +*******************************************************************************/ +MV_U32 g_type; +MV_STATUS mvTsuRxNextBuffGet(MV_U8 port,MV_U32 **dataBuff, MV_U32 **statBuff, + MV_U32 *buffsHandle) +{ + MV_TSU_PORT_CTRL *portCtrl; + MV_U32 numBlocks; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT) + return MV_NOT_SUPPORTED; + if((dataBuff == NULL) || (statBuff == NULL) || (buffsHandle == NULL)) + return MV_BAD_PARAM; + + mvTsuReadyBuffCountGet(port,&numBlocks,NULL); + if(numBlocks <= 2) + return MV_NO_MORE; + + portCtrl = &mvTsuPortCtrl[port]; + + /* Get read pointer. */ + *dataBuff = (MV_U32*)(((MV_U32)portCtrl->tsDataBuff) + + (portCtrl->dataBlockSize * portCtrl->dataReadIdx)); + *statBuff = + (MV_U32*)(((MV_U32)portCtrl->tsDoneBuff) + + (TSU_DONE_STATUS_ENTRY_SIZE * portCtrl->statReadIdx)); + *buffsHandle = TSU_BUFF_HNDL(portCtrl->dataReadIdx, + portCtrl->statReadIdx); + return MV_OK; +} + + +/******************************************************************************* +* mvTsuRxTimestampCntEn +* +* DESCRIPTION: +* Enable / Disable the timestamp counter for Rx direction. +* +* INPUT: +* port - TSU port number. +* enable - MV_TRUE to enable the timestamp counter. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad parameters. +* NOTE: +* +*******************************************************************************/ +MV_STATUS mvTsuRxTimestampCntEn(MV_U8 port,MV_BOOL enable) +{ + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT) + return MV_NOT_SUPPORTED; + + reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port)); + reg &= ~TSU_TMS_CTRL_TIMER_MASK; + + if(enable == MV_TRUE) + reg |= TSU_TMS_CTRL_TIMER_EN; + else + reg |= TSU_TMS_CTRL_TIMER_DIS; + + MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuRxBuffFree +* +* DESCRIPTION: +* Mark a given set of buffers to be free (ready for new data Rx). +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to the start of data buffer to return. +* statBuff - Pointer to the start of status buffer to return. +* buffsHandle - The buffers handle as returned by mvTsuRxNextBuffGet() +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NO_MORE - No Rx data is available for copy. +* MV_BAD_PARAM - Bad parameters. +* MV_BAD_STATE - Bad buffer free order, attempting to free a buffer +* before all previous buffers where freed. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* +*******************************************************************************/ +MV_STATUS mvTsuRxBuffFree(MV_U8 port,MV_U32 *dataBuff, MV_U32 *statBuff, + MV_U32 buffsHandle) +{ + MV_TSU_PORT_CTRL *portCtrl; + MV_U32 ptr; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_INPUT) + return MV_NOT_SUPPORTED; + if((dataBuff == NULL) || (statBuff == NULL)) + return MV_BAD_PARAM; + + portCtrl = &mvTsuPortCtrl[port]; + + if(buffsHandle != + TSU_BUFF_HNDL(portCtrl->dataReadIdx,portCtrl->statReadIdx)){ + mvOsPrintf("Bad state..........................\n"); + return MV_BAD_STATE; + } + + portCtrl->dataReadIdx = + (portCtrl->dataReadIdx + 1) & (portCtrl->numTsDesc - 1); + if(portCtrl->dataReadIdx == 0) + portCtrl->cpuRollBit ^= (portCtrl->queueMask + 1); + + portCtrl->statReadIdx = + ((portCtrl->statReadIdx + portCtrl->aggrNumPckts) & + (portCtrl->numDoneQEntry - 1)); + + /* Update the desc queue write pointer. */ + ptr = (portCtrl->dataReadIdx << 2) | portCtrl->cpuRollBit; + + MV_REG_WRITE(MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port),ptr); + +#if defined(MV_BRIDGE_SYNC_REORDER) + mvOsBridgeReorderWA(); +#endif + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuRxFlushErrorPackets +* +* DESCRIPTION: +* Enable / Disable flushing of received erroneous packets. +* +* INPUT: +* port - TSU port number. +* enableFlush - MV_TRUE to flush recieved erroneous packets. +* MV_FALSE to copy erroneous packets to Rx buffers. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuRxFlushErrorPackets(MV_U8 port, MV_BOOL enableFlush) +{ + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_AGGREGATION_CTRL_REG(port)); + reg &= ~TSU_AGGR_FLUSH_ERR_MASK; + if(enableFlush == MV_TRUE) + reg |= TSU_AGGR_FLUSH_ERR_ENABLE; + else + reg |= TSU_AGGR_FLUSH_ERR_DISABLE; + MV_REG_WRITE(MV_TSU_AGGREGATION_CTRL_REG(port),reg); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + return MV_OK; +} + + +/********************************/ +/* Tx related APIs */ +/********************************/ + +/******************************************************************************* +* mvTsuTxClockFreqSet +* +* DESCRIPTION: +* Configure the transmit clock frequency and parameters. +* +* INPUT: +* port - TSU port number. +* freq - The frequency to configure in Hz. +* autoAdjust - Whether to adjust the Tx frequency according to the +* next packet timestamp. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_VALUE - Bad Tx frequency value. +* +*******************************************************************************/ +MV_STATUS mvTsuTxClockFreqSet(MV_U8 port, MV_U32 freq, MV_BOOL autoAdjust) +{ + MV_U32 reg; + MV_U32 clockVal; + MV_U32 divider; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + clockVal = mvTsuCoreClock2Val[mvTsuCtrl.coreClock]; + if(freq > clockVal) + return MV_BAD_VALUE; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + /* Find the correct divider that satisfies: freq <= (core_clock / div)*/ + divider = TSU_NUM_CLOCK_DIVIDERS - 1; + while(divider != 0) + { + if(freq <= (clockVal >> divider)) + break; + divider--; + } + + /* Now, bestDev holds the best divider value. */ + reg = MV_REG_READ(MV_TSU_CONFIG_REG(port)); + reg &= ~(TSU_CFG_OUT_CLOCK_MASK | TSU_CFG_FREQ_MODE_MASK); + switch(divider) + { + case(0): /* 1 */ + reg |= (1 << TSU_CFG_FREQ_MODE_OFFS); + /* Fall through */ + case(3): /* 8 */ + reg |= TSU_CFG_OUT_CLOCK_1_8; + break; + case(1): /* 2 */ + reg |= (1 << TSU_CFG_FREQ_MODE_OFFS); + /* Fall through */ + case(4): /* 16 */ + reg |= TSU_CFG_OUT_CLOCK_2_16; + break; + case(2): /* 4 */ + reg |= (1 << TSU_CFG_FREQ_MODE_OFFS); + /* Fall through */ + case(5): /* 32 */ + reg |= TSU_CFG_OUT_CLOCK_4_32; + break; + default: + break; + } + MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg); + + /* Setup auto adjust. */ + reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port)); + reg &= ~TSU_TMS_CTRL_AUTO_ADJ_MASK; + if(autoAdjust == MV_TRUE) + reg |= TSU_TMS_CTRL_AUTO_ADJ_ON; + else + reg |= TSU_TMS_CTRL_AUTO_ADJ_OFF; + MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuTxFreeBuffCountGet +* +* DESCRIPTION: +* Get the number of free packets ready to be transmitted in the TX +* descriptor list. +* +* INPUT: +* port - TSU port number. +* OUTPUT: +* numBlocks - Number of data blocks ready for CPU processing +* (does not have data for transmit). +* numBuffers - Number of buffers ready for CPU processing (does not +* have data for transmit). +* In non-aggreagtion mode numBlocks == numBuffers. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NOT_SUPPORTED- If the port is not configured in output mode. +* +*******************************************************************************/ +MV_STATUS mvTsuTxFreeBuffCountGet(MV_U8 port, MV_U32 *numBlocks, + MV_U32 *numBuffers) +{ + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT) + return MV_NOT_SUPPORTED; + return mvTsuReadyBuffCountGet(port,numBlocks,numBuffers); +} + + +/******************************************************************************* +* mvTsuRxNextBuffGet +* +* DESCRIPTION: +* Get a pointer to the next available Tx data & status buffers from the Tx +* queue. +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to return the address of the next data buffer. +* statBuff - Pointer to return the address of the next status +* buffer. +* OUTPUT: +* buffsHandle - A handle returned to the user to be used when freeing +* the buffers in mvTsuTxBuffPut(). +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad parameters. +* MV_NOT_SUPPORTED- Functionality not supported by the port configuration. +* MV_NO_MORE - No free Tx data is available. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* +*******************************************************************************/ +MV_STATUS mvTsuTxNextBuffGet(MV_U8 port,MV_U32 **dataBuff,MV_U32 *buffsHandle) +{ + MV_TSU_PORT_CTRL *portCtrl; + MV_U32 numBlocks; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT) + return MV_NOT_SUPPORTED; + if((dataBuff == NULL) || (buffsHandle == NULL)) + return MV_BAD_PARAM; + + mvTsuTxFreeBuffCountGet(port,&numBlocks,NULL); + //printk("g_type = 0x%x.\n",g_type); + if(numBlocks == 0) + return MV_NO_MORE; + + portCtrl = &mvTsuPortCtrl[port]; + + if(dataBuff != NULL) { + *dataBuff = (MV_U32*)(((MV_U32)portCtrl->tsDataBuff) + + (portCtrl->dataBlockSize * portCtrl->dataReadIdx)); + *buffsHandle = TSU_BUFF_HNDL(portCtrl->dataReadIdx,portCtrl->statReadIdx); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuTxBuffPut +* +* DESCRIPTION: +* Mark a given set of buffers to be ready for transmission. +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to the start of data buffer to put. +* tmsValue - The timestamp to associate with the buffer. +* This parameter is applicable only when working in +* non-aggregation mode. +* tsErr - Indicates if the TS packet should be sent as an +* erroneous packet. +* This parameter is applicable only when working in +* non-aggregation mode. +* buffsHandle - The buffer handle as returned by mvTsuTxNextBuffGet() +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad function parameters. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* +*******************************************************************************/ +MV_STATUS mvTsuTxBuffPut(MV_U8 port, MV_U32 *dataBuff, MV_U32 tmsValue, + MV_BOOL tsErr, MV_U32 buffsHandle) +{ + MV_TSU_PORT_CTRL *portCtrl; + MV_U32 *descEntry; + MV_U32 ptr; + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT) + return MV_NOT_SUPPORTED; + if(dataBuff == NULL) + return MV_BAD_PARAM; + + portCtrl = &mvTsuPortCtrl[port]; + if(TSU_BUFF_HNDL_2_DATA_IDX(buffsHandle) != portCtrl->dataReadIdx) + return MV_BAD_STATE; + + if(portCtrl->aggrMode == MV_TSU_AGGR_MODE_DISABLED) { + /* Write the timestamp value. */ + descEntry = (MV_U32*)(((MV_U32)portCtrl->descVirtAddr) + + (portCtrl->dataReadIdx << 3)); + TSU_SET_OUT_DESC_TMSTMP(descEntry,tmsValue,tsErr); + } + + portCtrl->dataReadIdx = + (portCtrl->dataReadIdx + 1) & (portCtrl->numTsDesc - 1); + if(portCtrl->dataReadIdx == 0) + portCtrl->cpuRollBit ^= (portCtrl->queueMask + 1); + + //mvTsuOperationModeSet(port,MV_FALSE); + /* Update the desc queue write pointer. */ + ptr = (portCtrl->dataReadIdx << 3) | portCtrl->cpuRollBit; + MV_REG_WRITE(MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port),ptr); + +#if defined(MV_BRIDGE_SYNC_REORDER) + mvOsBridgeReorderWA(); +#endif + + if(portCtrl->enableTimer) { + /* Enable the timestamp counter. */ + reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port)); + reg &= ~TSU_TMS_CTRL_TIMER_MASK; + reg |= TSU_TMS_CTRL_TIMER_EN; + MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg); + portCtrl->enableTimer = MV_FALSE; + } + + //mvTsuOperationModeSet(port,MV_TRUE); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuTxStatusGet +* +* DESCRIPTION: +* Get the next TX done buffer from the TX done queue. +* +* INPUT: +* port - TSU port number. +* doneBuff - Pointer to return the address of the next done buffer. +* buffsHandle - The buffer handle as returned by mvTsuTxNextBuffGet() +* OUTPUT: +* numBuffs - Number of returned buffers. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NO_MORE - No free Tx buffers are avilable. +* NOTE: +* +*******************************************************************************/ +MV_STATUS mvTsuTxStatusGet(MV_U8 port, MV_U32 **doneBuff, MV_U32 buffsHandle) +{ + MV_TSU_PORT_CTRL *portCtrl; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT) + return MV_NOT_SUPPORTED; + if(doneBuff == NULL) + return MV_BAD_PARAM; + + portCtrl = &mvTsuPortCtrl[port]; + if(TSU_BUFF_HNDL_2_STAT_IDX(buffsHandle) != portCtrl->statReadIdx) + return MV_BAD_STATE; + + *doneBuff = (MV_U32*)(portCtrl->tsDoneBuff + portCtrl->statReadIdx); + + portCtrl->statReadIdx = + ((portCtrl->statReadIdx + portCtrl->aggrNumPckts)& + (portCtrl->numDoneQEntry - 1)); + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuTxInitTimeStampSet +* +* DESCRIPTION: +* Set the initial timestamp value for TX operations. +* This function must be called before each transmit session. +* +* INPUT: +* port - TSU port number. +* enableTmstmp - Enable the timestamp mechanism for packet transmit. +* When false, the TSU will transmit packets back-to-back +* initTimestamp - (Valid only if enableTs == MV_TRUE) +* The initial timestamp to set. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad timestamp value. +* +*******************************************************************************/ +MV_STATUS mvTsuTxInitTimeStampSet(MV_U8 port, MV_BOOL enableTmstmp, + MV_U32 initTimestamp) +{ + MV_U32 reg; + MV_U32 tsReg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT) + return MV_NOT_SUPPORTED; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port)); + if(enableTmstmp == MV_TRUE) + { + /* Setup timestamp initial value. */ + tsReg = MV_REG_READ(MV_TSU_TIMESTAMP_REG(port)); + tsReg &= ~TSU_TMSTMP_TIMESTAMP_MASK; + tsReg |= (initTimestamp & + (TSU_TMSTMP_TIMESTAMP_MASK >> TSU_TMSTMP_TIMESTAMP_OFFS)); + MV_REG_WRITE(MV_TSU_TIMESTAMP_REG(port),tsReg); + + /* Trigger the TSU to read the timestamp. */ + reg |= (1 << TSU_TMS_CTRL_READ_TIMER_OFFS); + } + + /* Disable the timestamp counter (Will be enabled on */ + /* the first packet Tx */ + reg &= ~TSU_TMS_CTRL_TIMER_MASK; + reg |= TSU_TMS_CTRL_TIMER_DIS; + MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg); + mvTsuPortCtrl[port].enableTimer = enableTmstmp; + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + return MV_OK; +} + + +/******************************************************************************* +* mvTsuTxDone +* +* DESCRIPTION: +* Inform the TS unit that the current transmission session is over. +* This will stop the internal timestamp counters held by the unit. +* +* INPUT: +* port - TSU port number. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuTxDone(MV_U8 port) +{ + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + if(mvTsuPortCtrl[port].portDir != TSU_PORT_OUTPUT) + return MV_NOT_SUPPORTED; + + /* Disable operation mode. */ + mvTsuOperationModeSet(port,MV_FALSE); + + reg = MV_REG_READ(MV_TSU_TIMESTAMP_CTRL_REG(port)); + + /* Disable the timestamp counter. */ + reg &= ~TSU_TMS_CTRL_TIMER_MASK; + reg |= TSU_TMS_CTRL_TIMER_DIS; + MV_REG_WRITE(MV_TSU_TIMESTAMP_CTRL_REG(port),reg); + + /* Enable operation mode. */ + mvTsuOperationModeSet(port,MV_TRUE); + return MV_OK; +} + + +/******************************************************************************* +* mvTsuOperationModeSet +* +* DESCRIPTION: +* Set the given TS port into operaion mode. +* +* INPUT: +* port - TSU port number. +* enable - MV_TRUE: enable operation mode. +* MV_FALSE: disable operation mode. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +inline static MV_STATUS mvTsuOperationModeSet(MV_U8 port, MV_BOOL enable) +{ + MV_U32 reg; + + reg = MV_REG_READ(MV_TSU_CONFIG_REG(port)); + reg &= ~TSU_CFG_OPER_MASK; + if(enable) + reg |= TSU_CFG_OPER_ENABLE; + else + reg |= TSU_CFG_OPER_DISABLE; + MV_REG_WRITE(MV_TSU_CONFIG_REG(port),reg); + return MV_OK; +} + + +/******************************************************************************* +* mvTsuReadyBuffCountGet +* +* DESCRIPTION: +* Get number of packets ready for CPU processing. +* In Rx direction, this is the number of packets ready to be rpocessed by +* CPU. For Tx direction, this is the number of free buffers ready for data +* transmission. +* +* INPUT: +* port - TSU port number. +* OUTPUT: +* numBlocks - Number of data blocks ready for CPU processing +* (already have data for processing). +* numBuffers - Number of buffers ready for CPU processing (already +* have data for processing). +* In non-aggreagtion mode numBlocks == numBuffers. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +static MV_STATUS mvTsuReadyBuffCountGet(MV_U8 port, MV_U32 *numBlocks, + MV_U32 *numBuffers) +{ + MV_U32 cpuPtr; + MV_U32 tsuPtr; + MV_U32 result = 0; + MV_U32 tsuRollBit; + MV_TSU_PORT_CTRL *portCtrl = &mvTsuPortCtrl[port]; + + /* Get CPU pointer. */ + cpuPtr = portCtrl->dataReadIdx; + + /* Get TSU pointer. */ + tsuPtr = MV_REG_READ(MV_TSU_DESC_QUEUE_READ_PTR_REG(port)); + + tsuRollBit = tsuPtr & (portCtrl->queueMask + 1); + tsuPtr &= portCtrl->queueMask; + tsuPtr /= portCtrl->descSize; + + g_type = (tsuPtr << 16) | (cpuPtr << 8) | (tsuRollBit << 24); + if(tsuPtr > cpuPtr) { +// printk("tsuPtr(%d) > cpuPtr(%d), ",tsuPtr,cpuPtr); + result = tsuPtr - cpuPtr; + g_type |= 1; + } else if(tsuPtr < cpuPtr) { +// printk("tsuPtr(%d) < cpuPtr(%d), ",tsuPtr,cpuPtr); + result = tsuPtr + portCtrl->numTsDesc - cpuPtr; + g_type |= 2; + } else if( (tsuPtr == cpuPtr) && (portCtrl->cpuRollBit == tsuRollBit) ) { +// printk("tsuPtr(%d) == cpuPtr(%d) - %d, ",tsuPtr,cpuPtr,tsuRollBit); + result = portCtrl->numTsDesc; + g_type |= 3; + } + + if(numBuffers) + *numBuffers = result * portCtrl->aggrNumPckts; + if(numBlocks) + *numBlocks = result; + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuPortEnable +* +* DESCRIPTION: +* Enable port for receiving & transmitting data after it has been +* configured. +* +* INPUT: +* port - The port number to configure. +* enable - MV_TRUE to enable port. +* MV_FALSE to disable it. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +static MV_STATUS mvTsuPortEnable(MV_U8 port,MV_BOOL enable) +{ + MV_U32 reg; + + if(port >= mvTsuCtrl.numActPorts) + return MV_OUT_OF_RANGE; + + if(enable == MV_TRUE) + reg = 0xFFFFFFFF; + else + reg = 0x04040404; + + reg = MV_REG_WRITE(MV_TSU_ENABLE_ACCESS_REG(port),reg); + return MV_OK; +} + diff --git a/board/mv_feroceon/mv_hal/ts/mvTsu.h b/board/mv_feroceon/mv_hal/ts/mvTsu.h new file mode 100644 index 0000000..3d511fa --- /dev/null +++ b/board/mv_feroceon/mv_hal/ts/mvTsu.h @@ -0,0 +1,830 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INC_MV_TSU_H__ +#define __INC_MV_TSU_H__ + +#include "ts/mvTsuRegs.h" +#include "mvCommon.h" + +/********************************/ +/* General enums and structures */ +/********************************/ + +#define MV_TSU_NUM_PORTS (2) + +#define MV_TSU_STATUS_CONN_ERROR (0x1) +#define MV_TSU_STATUS_OVFL_ERROR (0x2) +#define MV_TSU_STATUS_TSIF_ERROR (0x4) + +#define TSU_DONE_STATUS_ENTRY_SIZE (4) +#define TSU_INPUT_DESC_ENTRY_SIZE (4) +#define TSU_OUTPUT_DESC_ENTRY_SIZE (8) +#define TSU_MODE1_OUT_TMS_SIZE (8) +#define MV_TSU_MAX_IN_QUEUE_LEN (1024) +#define MV_TSU_MAX_OUT_QUEUE_LEN (512) +#define MV_TSU_MAX_DONEQ_LEN (1024) +#define TSU_DMA_ALIGN (32) + +#define MV_TSU_TX_CLOCK_EXTERNAL (0xFFFFFFFF) + +typedef enum +{ + TSU_CORE_CLK_83_MHZ = 0, + TSU_CORE_CLK_71_MHZ, + TSU_CORE_CLK_91_MHZ, + TSU_CORE_CLK_100_MHZ +}MV_TSU_CORE_CLOCK; + +typedef enum +{ + TSU_MODE_SERIAL, + TSU_MODE_PARALLEL +}MV_TSU_PORTS_MODE; + +typedef enum +{ + TSU_SIGNAL_KEEP_DEF, /* Keep default. */ + TSU_SIGNAL_DIS, + TSU_SIGNAL_EN_ACT_LOW, + TSU_SIGNAL_EN_ACT_HIGH +}MV_TSU_SIGNAL_MODE; + + +typedef enum +{ + TSU_SIGNAL_EDGE_KEEP_DEF, /* Keep default. */ + TSU_SIGNAL_EDGE_FALL, + TSU_SIGNAL_EDGE_RISE +}MV_TSU_SIGNAL_EDGE; + + +typedef enum +{ + TSU_PORT_INPUT, + TSU_PORT_OUTPUT +}MV_TSU_PORT_DIRECTION; + + +typedef struct +{ + MV_TSU_SIGNAL_MODE tsSync; + MV_TSU_SIGNAL_MODE tsValid; + MV_TSU_SIGNAL_MODE tsError; + MV_TSU_SIGNAL_EDGE tsDataEdge; +}MV_TSU_SIGNAL_CONFIG; + + +/* Serial data bits order, only one option can be selected. */ +#define MV_TSU_SER_DATA_ORDER_MSB (0x0001) +#define MV_TSU_SER_DATA_ORDER_LSB (0x0002) +#define MV_TSU_SER_DATA_ORDER_MASK \ + (MV_TSU_SER_DATA_ORDER_MSB | MV_TSU_SER_DATA_ORDER_LSB) + + +/* Serial sync signal active length in bits, only one option */ +/* can be selected. */ +#define MV_TSU_SER_SYNC_ACT_1_BIT (0x0004) +#define MV_TSU_SER_SYNC_ACT_8_BIT (0x0008) +#define MV_TSU_SER_SYNC_ACT_LEN_MASK \ + (MV_TSU_SER_SYNC_ACT_1_BIT | MV_TSU_SER_SYNC_ACT_8_BIT) + +/* Serial Tx signal mode, continuous or gapped, only one option */ +/* can be selected. */ +#define MV_TSU_SER_TX_CLK_MODE_CONT (0x0010) +#define MV_TSU_SER_TX_CLK_MODE_GAPPED (0x0020) +#define MV_TSU_SER_TX_CLK_MODE_MASK \ + (MV_TSU_SER_TX_CLK_MODE_CONT | MV_TSU_SER_TX_CLK_MODE_GAPPED) + + +typedef struct +{ + MV_TSU_PORT_DIRECTION portDir; + MV_U16 pktSize; /* 188 to 256 */ +}MV_TSU_PORT_CONFIG; + + +#define MV_TSU_AGGR_MODE_DISABLED (1) +#define MV_TSU_AGGR_MODE_1 (2) +#define MV_TSU_AGGR_MODE_2 (3) + +/* + * MV_TSU_BUFF_INFO: + * + * aggrMode: Aggregation mode MV_TSU_AGGR_MODE_X + * aggrMode2TmstmpOff: Timestamp offset in case of aggr mode 2. + * aggrNumPackets: Number of packets in each aggregation. + * numTsDesc: Number of descriptors (Power of 2). + * numDoneQEntry: Number of done queue entries (Power of 2). + * tsDataBuff: Pointer to the data buffers list, the user must ensure + * DMA coherency for these buffers. The content of these + * buffers is never accessed by the HAL. + * tsDoneBuff: Pointer to the data status list, the user must ensure + * DMA coherency for these buffers. The content of these + * buffers is never accessed by the HAL. + * dataBlockSize: the size of a single data block, this can be larger than + * the amount of memory needed to hold TS packets in order + * to insure a certain alignment of the buffers. + * + * Guidelines for calculating the data & status buffers length: + * + * data-buff-len = dataBlockSize * numTsDesc + * In normal mode: + * dataBlockSize = + alignment_space + * done-buff-len= numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE + * + * In aggregation mode 1: + * dataBlockSize = * aggrNumPackets + alignment_space + * done-buff-len= numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE + * + * In aggregation mode 2: + * dataBlockSize = (( + aggrMode2TmstmpOff)* + * aggrNumPackets) + alignment_space + * done-buff-len= numDoneQEntry * TSU_DONE_STATUS_ENTRY_SIZE + */ +typedef struct +{ + MV_U8 aggrMode; + MV_U8 aggrMode2TmstmpOff; + MV_U8 aggrNumPackets; + + MV_U32 numTsDesc; + MV_U32 numDoneQEntry; + MV_U32 *tsDataBuff; + MV_U32 tsDataBuffPhys; + MV_U32 *tsDoneBuff; + MV_U32 tsDoneBuffPhys; + MV_U32 dataBlockSize; +}MV_TSU_BUFF_INFO; + + +/********************************/ +/* Macros */ +/********************************/ +#define MV_TSU_STATUS_ENTRY_TMS_GET(stat) (MV_U32)(stat & 0xFFFFFFF) + + +/********************************/ +/* Functions API */ +/********************************/ + +/******************************************************************************* +* mvTsuHalInit +* +* DESCRIPTION: +* Initialize the TSU unit, and get unit out of reset. +* +* INPUT: +* coreClock - The core clock at which the TSU should operate. +* mode - The mode on configure the unit into (serial/parallel). +* osHandle - Memory handle used for memory allocations. +* OUTPUT: +* None. +* RETURN: +* MV_OK - on success, +* +*******************************************************************************/ +MV_STATUS mvTsuHalInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode, + void *osHandle); + + +/******************************************************************************* +* mvTsuShutdown +* +* DESCRIPTION: +* Shutdown the TS unit, and put into reset state. +* +* INPUT: +* None. +* OUTPUT: +* None. +* RETURN: +* MV_OK - on success, +* +*******************************************************************************/ +MV_STATUS mvTsuShutdown(void); + + +/******************************************************************************* +* mvTsuPortReset +* +* DESCRIPTION: +* Perform a SW reset on a given port. +* +* INPUT: +* port - The port number to reset. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_BAD_VALUE - Bad port configuration option. +* MV_BAD_SIZE - Illegal number of ports. +* +*******************************************************************************/ +MV_STATUS mvTsuPortReset(MV_U8 port); + + +/******************************************************************************* +* mvTsuWinInit +* +* DESCRIPTION: +* Initialize the TSU unit access windows mapping. +* +* INPUT: +* None. +* OUTPUT: +* None. +* RETURN: +* MV_OK - on success, +* +*******************************************************************************/ +MV_STATUS mvTsuWinInit(void); + + +/******************************************************************************* +* mvTsuPortInit +* +* DESCRIPTION: +* Initialize the TSU ports. +* +* INPUT: +* port - The port number to configure. +* portCfg - Port configurations parameters. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_BAD_VALUE - Bad port configuration option. +* MV_BAD_SIZE - Illegal number of ports. +* +*******************************************************************************/ +MV_STATUS mvTsuPortInit(MV_U8 port, MV_TSU_PORT_CONFIG *portCfg); + + +/******************************************************************************* +* mvTsuPortSignalCfgSet +* +* DESCRIPTION: +* Configure port signals parameters. +* +* INPUT: +* port - The port to configure. +* signalCfg - Signal configuration options. +* serialflags - Serial signal configuration options (valid only if the +* port is working in serial mode). +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_BAD_VALUE - Bad port configuration option. +* MV_BAD_SIZE - Illegal number of ports. +* +*******************************************************************************/ +MV_STATUS mvTsuPortSignalCfgSet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg, + MV_U32 serialFlags); + + +/******************************************************************************* +* mvTsuPortSignalCfgGet +* +* DESCRIPTION: +* Get port signals parameters. +* +* INPUT: +* port - The port to configure. +* OUTPUT: +* signalCfg - Signal configuration options. +* serialflags - Serial signal configuration options (valid only if the +* port is working in serial mode). +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Illegal port number. +* MV_BAD_PARAM - Bad pointers. +* +*******************************************************************************/ +MV_STATUS mvTsuPortSignalCfgGet(MV_U8 port, MV_TSU_SIGNAL_CONFIG *signalCfg, + MV_U32* serialFlags); + + +/******************************************************************************* +* mvTsuStatusGet +* +* DESCRIPTION: +* Get the TSU port status for a given port. +* +* INPUT: +* port - The port number to configure. +* OUTPUT: +* status - Bitmask representing the TSU port status (a bitwise or +* between the MV_TSU_STATUS_* macros. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuStatusGet(MV_U8 port, MV_U32 *status); + + +/******************************************************************************* +* mvTsuBuffersInit +* +* DESCRIPTION: +* Initialize the TSU unit buffers. +* This function is used to initialize both Rx or Tx buffers according to +* the port mode configured in mvTsuPortsInit(). +* +* INPUT: +* port - The port number to configure. +* buffInfo- TSU buffer information. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad buffer configuration options. +* MV_NOT_ALIGNED - Bad data buffer alignemed. +* +*******************************************************************************/ +MV_STATUS mvTsuBuffersInit(MV_U8 port, MV_TSU_BUFF_INFO *buffInfo); + + +/******************************************************************************* +* mvTsuPortShutdown +* +* DESCRIPTION: +* Shutdown the port, this will release any previously allocated port +* memory, and set the port to disable state. +* +* INPUT: +* port - The port number to shutdown. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad buffer configuration options. +* +*******************************************************************************/ +MV_STATUS mvTsuPortShutdown(MV_U8 port); + + +/******************************************************************************* +* mvTsuDmaWatermarkSet +* +* DESCRIPTION: +* Set the watermark for starting a DMA transfer from / to the TSU +* internal FIFO to the CPU memory. +* +* INPUT: +* port - The port number to configure. +* watermark - The watermark to configure (in DWORD units). +* For Rx: Number of data DWORDS in FIFO to start DMA. +* For Tx: Number of free DWORDS in FIFO to start DMA. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad watermark value.. +* +*******************************************************************************/ +MV_STATUS mvTsuDmaWatermarkSet(MV_U8 port, MV_U32 watermark); + + +/******************************************************************************* +* mvTsuAggrMode1TmsOnPcktEn +* +* DESCRIPTION: +* Set the TSU unit to add the timestamp to the packet buffer when working +* in aggregation mode-1. +* +* INPUT: +* port - The port number to configure. +* enable - When True, enables the placement of timestamp data in the +* packet buffer. +* When False, the timestamp is placed in the Done-Queue. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuAggrMode1TmsOnPcktEn(MV_U8 port, MV_BOOL enable); + + +/********************************/ +/* Rx related APIs */ +/********************************/ + + +/******************************************************************************* +* mvTsuRxSyncDetectionSet +* +* DESCRIPTION: +* Set TS synchronization parameters for Rx data. +* +* INPUT: +* port - The port number to configure. +* syncDetect - Number of TS sync matches to lock signal. +* syncLoss - Number of TS sync losses to unlock signal. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad sync values configuration. +* +*******************************************************************************/ +MV_STATUS mvTsuRxSyncDetectionSet(MV_U8 port, MV_U8 syncDetect, MV_U8 syncLoss); + + +/******************************************************************************* +* mvTsuRxSyncDetectionGet +* +* DESCRIPTION: +* Get TS synchronization parameters for Rx data. +* +* INPUT: +* port - The port number. +* OUTPUT: +* syncDetect - Number of TS sync matches to lock signal. +* syncLoss - Number of TS sync losses to unlock signal. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad pointers. +* +*******************************************************************************/ +MV_STATUS mvTsuRxSyncDetectionGet(MV_U8 port, MV_U8 *syncDetect, MV_U8 *syncLoss); + + +/******************************************************************************* +* mvTsuRxFullBuffCountGet +* +* DESCRIPTION: +* Get number of Rx packets ready for CPU processing. +* +* INPUT: +* port - TSU port number. +* OUTPUT: +* numBlocks - Number of data blocks ready for CPU processing +* (already have data for processing). +* numBuffers - Number of buffers ready for CPU processing (already +* have data for processing). +* In non-aggreagtion mode numBlocks == numBuffers. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NOT_SUPPORTED- If the port is not configured in input mode. +* +*******************************************************************************/ +MV_STATUS mvTsuRxFullBuffCountGet(MV_U8 port, MV_U32 *numBlocks, + MV_U32 *numBuffers); + + +/******************************************************************************* +* mvTsuRxNextBuffGet +* +* DESCRIPTION: +* Get a pointer to the next available Rx data & status buffers from the Rx +* queue. +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to return the address of the next data buffer. +* statBuff - Pointer to return the address of the next status buffer. +* OUTPUT: +* buffsHandle - A handle returned to the user to be used when freeing +* the buffers in mvTsuRxBuffFree(). +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad parameters. +* MV_NOT_SUPPORTED- Functionality not supported by the port configuration. +* MV_NO_MORE - No Rx data is available for copy. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* +*******************************************************************************/ +MV_STATUS mvTsuRxNextBuffGet(MV_U8 port,MV_U32 **dataBuff, MV_U32 **statBuff, + MV_U32 *buffsHandle); + + +/******************************************************************************* +* mvTsuRxTimestampCntEn +* +* DESCRIPTION: +* Enable / Disable the timestamp counter for Rx direction. +* +* INPUT: +* port - TSU port number. +* enable - MV_TRUE to enable the timestamp counter. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad parameters. +* NOTE: +* +*******************************************************************************/ +MV_STATUS mvTsuRxTimestampCntEn(MV_U8 port,MV_BOOL enable); + + +/******************************************************************************* +* mvTsuRxBuffFree +* +* DESCRIPTION: +* Mark a given set of buffers to be free (ready for new data Rx). +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to the start of data buffer to return. +* statBuff - Pointer to the start of status buffer to return. +* buffsHandle - The buffers handle as returned by mvTsuRxNextBuffGet() +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NO_MORE - No Rx data is available for copy. +* MV_BAD_PARAM - Bad parameters. +* MV_BAD_STATE - Bad buffer free order, attempting to free a buffer +* before all previous buffers where freed. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* The numBuffs represents the number of aggregation buffers and not to the +* number of packets. +* +*******************************************************************************/ +MV_STATUS mvTsuRxBuffFree(MV_U8 port,MV_U32 *dataBuff, MV_U32 *statBuff, + MV_U32 buffsHandle); + + +/******************************************************************************* +* mvTsuRxFlushErrorPackets +* +* DESCRIPTION: +* Enable / Disable flushing of received erroneous packets. +* +* INPUT: +* port - TSU port number. +* enableFlush - MV_TRUE to flush recieved erroneous packets. +* MV_FALSE to copy erroneous packets to Rx buffers. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuRxFlushErrorPackets(MV_U8 port, MV_BOOL enableFlush); + + +/********************************/ +/* Tx related APIs */ +/********************************/ + + +/******************************************************************************* +* mvTsuTxClockFreqSet +* +* DESCRIPTION: +* Configure the transmit clock frequency and parameters. +* +* INPUT: +* port - TSU port number. +* freq - The frequency to configure in Hz. +* range is 2500000 (2.5MHz) to 80000000 (80MHz). +* autoAdjust - Whether to adjust the Tx frequency according to the +* next packet timestamp. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_VALUE - Bad Tx frequency value. +* +*******************************************************************************/ +MV_STATUS mvTsuTxClockFreqSet(MV_U8 port, MV_U32 freq, MV_BOOL autoAdjust); + + +/******************************************************************************* +* mvTsuTxFreeBuffCountGet +* +* DESCRIPTION: +* Get the number of free packets ready to be transmitted in the TX +* descriptor list. +* +* INPUT: +* port - TSU port number. +* OUTPUT: +* numBlocks - Number of data blocks ready for CPU processing +* (does not have data for transmit). +* numBuffers - Number of buffers ready for CPU processing (does not +* have data for transmit). +* In non-aggreagtion mode numBlocks == numBuffers. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NOT_SUPPORTED- If the port is not configured in input mode. +* +*******************************************************************************/ +MV_STATUS mvTsuTxFreeBuffCountGet(MV_U8 port, MV_U32 *numBlocks, + MV_U32 *numBuffers); + + +/******************************************************************************* +* mvTsuRxNextBuffGet +* +* DESCRIPTION: +* Get a pointer to the next available Tx data & status buffers from the Tx +* queue. +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to return the address of the next data buffer. +* numBuffs - Pointer to the maximum number of buffers to return. +* OUTPUT: +* numBuffs - Number of data / status buffers that where returned. +* buffsHandle - A handle returned to the user to be used when freeing +* the buffers in mvTsuRxBuffFree(). +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NO_MORE - No Rx data is available for copy. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* The numBuffs represents the number of aggregation buffers and not to the +* number of packets. +* +*******************************************************************************/ +MV_STATUS mvTsuTxNextBuffGet(MV_U8 port,MV_U32 **dataBuff,MV_U32 *buffsHandle); + + +/******************************************************************************* +* mvTsuTxBuffPut +* +* DESCRIPTION: +* Mark a given set of buffers to be ready for transmission. +* +* INPUT: +* port - TSU port number. +* dataBuff - Pointer to the start of data buffer to put. +* tmsValue - The timestamp to associate with the buffer. +* This parameter is applicable only when working in +* non-aggregation mode. +* tsErr - Indicates if the TS packet should be sent as an +* erroneous packet. +* buffsHandle - The buffer handle as returned by mvTsuTxNextBuffGet() +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad function parameters. +* NOTE: +* When working in Aggregation mode, the buffer will point to the +* beggining of the aggregation buffer and not to a single packet inside +* the buffer. +* +*******************************************************************************/ +MV_STATUS mvTsuTxBuffPut(MV_U8 port, MV_U32 *dataBuff, MV_U32 tmsValue, + MV_BOOL tsErr, MV_U32 buffsHandle); + + +/******************************************************************************* +* mvTsuTxStatusGet +* +* DESCRIPTION: +* Get the next TX done buffer from the TX done queue. +* +* INPUT: +* port - TSU port number. +* doneBuff - Pointer to return the address of the next done buffer. +* buffsHandle - The buffer handle as returned by mvTsuTxNextBuffGet() +* OUTPUT: +* numBuffs - Number of returned buffers. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_NO_MORE - No free Tx buffers are avilable. +* NOTE: +* +*******************************************************************************/ +MV_STATUS mvTsuTxStatusGet(MV_U8 port, MV_U32 **doneBuff, MV_U32 buffsHandle); + + +/******************************************************************************* +* mvTsuTxInitTimeStampSet +* +* DESCRIPTION: +* Set the initial timestamp value for TX operations. +* This function must be called before each transmit session. +* +* INPUT: +* port - TSU port number. +* enableTmstmp - Enable the timestamp mechanism for packet transmit. +* When false, the TSU will transmit packets back-to-back +* initTimestamp - (Valid only if enableTs == MV_TRUE) +* The initial timestamp to set. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* MV_BAD_PARAM - Bad timestamp value. +* +*******************************************************************************/ +MV_STATUS mvTsuTxInitTimeStampSet(MV_U8 port, MV_BOOL enableTmstmp, + MV_U32 initTimestamp); + + +/******************************************************************************* +* mvTsuTxDone +* +* DESCRIPTION: +* Inform the TS unit that the current transmission session is over. +* This will stop the internal timestamp counters held by the unit. +* +* INPUT: +* port - TSU port number. +* OUTPUT: +* None. +* RETURN: +* MV_OK - On success, +* MV_OUT_OF_RANGE - Unsupported port number. +* +*******************************************************************************/ +MV_STATUS mvTsuTxDone(MV_U8 port); + + +#endif /* __INC_MV_TSU__H__ */ + diff --git a/board/mv_feroceon/mv_hal/ts/mvTsuRegs.h b/board/mv_feroceon/mv_hal/ts/mvTsuRegs.h new file mode 100644 index 0000000..69c9adb --- /dev/null +++ b/board/mv_feroceon/mv_hal/ts/mvTsuRegs.h @@ -0,0 +1,267 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INC_MV_TSU_REGS_H__ +#define __INC_MV_TSU_REGS_H__ + +#define TSU_MAX_DECODE_WIN 4 + +#define TSU_GLOBAL_REG_BASE 0xB4000 +#define TSU_REG_BASE(port) (0xB8000 + (port * 0x800)) + +#define MV_TSU_MODES_REG (TSU_GLOBAL_REG_BASE + 0x00) + + +#define MV_TSU_CONFIG_REG(port) (TSU_REG_BASE(port) + 0x00) +#define MV_TSU_DMA_PARAMS_REG(port) (TSU_REG_BASE(port) + 0x04) +#define MV_TSU_DONE_QUEUE_BASE_REG(port) (TSU_REG_BASE(port) + 0x08) +#define MV_TSU_DESC_QUEUE_BASE_REG(port) (TSU_REG_BASE(port) + 0x0C) +#define MV_TSU_DONE_QUEUE_WRITE_PTR_REG(port) (TSU_REG_BASE(port) + 0x10) +#define MV_TSU_DONE_QUEUE_READ_PTR_REG(port) (TSU_REG_BASE(port) + 0x14) +#define MV_TSU_DESC_QUEUE_WRITE_PTR_REG(port) (TSU_REG_BASE(port) + 0x18) +#define MV_TSU_DESC_QUEUE_READ_PTR_REG(port) (TSU_REG_BASE(port) + 0x1C) +#define MV_TSU_ENABLE_ACCESS_REG(port) (TSU_REG_BASE(port) + 0x2C) +#define MV_TSU_TIMESTAMP_REG(port) (TSU_REG_BASE(port) + 0x30) +#define MV_TSU_STATUS_REG(port) (TSU_REG_BASE(port) + 0x34) +#define MV_TSU_TIMESTAMP_CTRL_REG(port) (TSU_REG_BASE(port) + 0x38) +#define MV_TSU_TEST_REG(port) (TSU_REG_BASE(port) + 0x3C) +#define MV_TSU_INTERRUPT_SRC_REG(port) (TSU_REG_BASE(port) + 0x40) +#define MV_TSU_INTERRUPT_MASK_REG(port) (TSU_REG_BASE(port) + 0x44) +#define MV_TSU_IRQ_PARAM_REG(port) (TSU_REG_BASE(port) + 0x48) +#define MV_TSU_DEBUG_REG(port) (TSU_REG_BASE(port) + 0x4C) +#define MV_TSU_NEXT_DESC_1_REG(port) (TSU_REG_BASE(port) + 0x50) +#define MV_TSU_NEXT_DESC_2_REG(port) (TSU_REG_BASE(port) + 0x54) +#define MV_TSU_SYNCBYTE_DETECT_REG(port) (TSU_REG_BASE(port) + 0x58) +#define MV_TSU_AGGREGATION_CTRL_REG(port) (TSU_REG_BASE(port) + 0x60) +#define MV_TSU_TIMESTAMP_INTERVAL_REG(port) (TSU_REG_BASE(port) + 0x64) +#define MV_TSU_CONFIG_2_REG(port) (TSU_REG_BASE(port) + 0x68) + + +/* TSU Modes register. */ +#define TSU_MODES_PAR_MODE_OFFS 14 +#define TSU_MODES_PAR_MODE_MASK (0x1 << TSU_MODES_PAR_MODE_OFFS) +#define TSU_MODES_PAR_MODE_SER (0x0 << TSU_MODES_PAR_MODE_OFFS) +#define TSU_MODES_PAR_MODE_PAR (0x1 << TSU_MODES_PAR_MODE_OFFS) +#define TSU_MODES_TSCK_OFF 15 +#define TSU_MODES_TSCK_MASK (0x3 << TSU_MODES_TSCK_OFF) + + +/* TSU config register. */ +#define TSU_CFG_RESET_OFFS 0 +#define TSU_CFG_RESET_MASK (0x3 << TSU_CFG_RESET_OFFS) +#define TSU_CFG_RESET_SET (0x1 << TSU_CFG_RESET_OFFS) +#define TSU_CFG_RESET_CLEAR (0x2 << TSU_CFG_RESET_OFFS) +#define TSU_CFG_OPER_OFFS 2 +#define TSU_CFG_OPER_MASK (0x3 << TSU_CFG_OPER_OFFS) +#define TSU_CFG_OPER_DISABLE (0x1 << TSU_CFG_OPER_OFFS) +#define TSU_CFG_OPER_ENABLE (0x2 << TSU_CFG_OPER_OFFS) +#define TSU_CFG_DATA_DIR_OFFS 8 +#define TSU_CFG_DATA_DIR_MASK (0x1 << TSU_CFG_DATA_DIR_OFFS) +#define TSU_CFG_DATA_DIR_IN (0x0 << TSU_CFG_DATA_DIR_OFFS) +#define TSU_CFG_DATA_DIR_OUT (0x1 << TSU_CFG_DATA_DIR_OFFS) +#define TSU_CFG_DATA_MODE_OFFS 9 +#define TSU_CFG_DATA_MODE_MASK (0x1 << TSU_CFG_DATA_MODE_OFFS) +#define TSU_CFG_DATA_MODE_SER (0x0 << TSU_CFG_DATA_MODE_OFFS) +#define TSU_CFG_DATA_MODE_PAR (0x1 << TSU_CFG_DATA_MODE_OFFS) +#define TSU_CFG_OUT_CLOCK_OFFS 10 +#define TSU_CFG_OUT_CLOCK_MASK (0x3 << TSU_CFG_OUT_CLOCK_OFFS) +#define TSU_CFG_OUT_CLOCK_4_32 (0x0 << TSU_CFG_OUT_CLOCK_OFFS) +#define TSU_CFG_OUT_CLOCK_2_16 (0x1 << TSU_CFG_OUT_CLOCK_OFFS) +#define TSU_CFG_OUT_CLOCK_1_8 (0x2 << TSU_CFG_OUT_CLOCK_OFFS) +#define TSU_CFG_OUT_CLOCK_EXT (0x3 << TSU_CFG_OUT_CLOCK_OFFS) +#define TSU_CFG_CLK_MODE_OFFS 12 +#define TSU_CFG_CLK_MODE_MASK (0x1 << TSU_CFG_CLK_MODE_OFFS) +#define TSU_CFG_CLK_MODE_CONT (0x0 << TSU_CFG_CLK_MODE_OFFS) +#define TSU_CFG_CLK_MODE_GAPPED (0x1 << TSU_CFG_CLK_MODE_OFFS) +#define TSU_CFG_TS_SYNC_OFFS 13 +#define TSU_CFG_TS_SYNC_MASK (0x1 << TSU_CFG_TS_SYNC_OFFS) +#define TSU_CFG_TS_SYNC_8BIT (0x0 << TSU_CFG_TS_SYNC_OFFS) +#define TSU_CFG_TS_SYNC_1BIT (0x1 << TSU_CFG_TS_SYNC_OFFS) +#define TSU_CFG_DATA_ORD_OFFS 14 +#define TSU_CFG_DATA_ORD_MASK (0x1 << TSU_CFG_DATA_ORD_OFFS) +#define TSU_CFG_DATA_ORD_MSB (0x0 << TSU_CFG_DATA_ORD_OFFS) +#define TSU_CFG_DATA_ORD_LSB (0x1 << TSU_CFG_DATA_ORD_OFFS) +#define TSU_CFG_TX_EDGE_OFFS 15 +#define TSU_CFG_TX_EDGE_MASK (0x1 << TSU_CFG_TX_EDGE_OFFS) +#define TSU_CFG_FREQ_MODE_OFFS 16 +#define TSU_CFG_FREQ_MODE_MASK (0x1 << TSU_CFG_FREQ_MODE_OFFS) +#define TSU_CFG_ERR_POL_OFFS 18 +#define TSU_CFG_ERR_POL_MASK (0x1 << TSU_CFG_ERR_POL_OFFS) +#define TSU_CFG_ERR_USED_OFFS 19 +#define TSU_CFG_ERR_USED_MASK (0x1 << TSU_CFG_ERR_USED_OFFS) +#define TSU_CFG_VAL_POL_OFFS 20 +#define TSU_CFG_VAL_POL_MASK (0x1 << TSU_CFG_VAL_POL_OFFS) +#define TSU_CFG_VAL_USED_OFFS 21 +#define TSU_CFG_VAL_USED_MASK (0x1 << TSU_CFG_VAL_USED_OFFS) +#define TSU_CFG_SYNC_POL_OFFS 22 +#define TSU_CFG_SYNC_POL_MASK (0x1 << TSU_CFG_SYNC_POL_OFFS) +#define TSU_CFG_SYNC_USED_OFFS 23 +#define TSU_CFG_SYNC_USED_MASK (0x1 << TSU_CFG_SYNC_USED_OFFS) +#define TSU_CFG_RESET_SET (0x1 << TSU_CFG_RESET_OFFS) +#define TSU_CFG_PKT_SIZE_OFFS 24 +#define TSU_CFG_PKT_SIZE_MASK (0xFF << TSU_CFG_PKT_SIZE_OFFS) + +/* TSU DMA parameters register. */ +#define TSU_DMAP_DMA_LEN_OFFS 0 +#define TSU_DMAP_DMA_LEN_MASK (0xFFFF << TSU_DMAP_DMA_LEN_OFFS) +#define TSU_DMAP_DATA_WTRMK_OFFS 16 +#define TSU_DMAP_DATA_WTRMK_MASK (0xFF << TSU_DMAP_DATA_WTRMK_OFFS) +#define TSU_DMAP_DATA_WTRMK_MAX 0xFF +#define TSU_DMAP_DESC_Q_SIZE_OFFS 24 +#define TSU_DMAP_DESC_Q_SIZE_MASK (0xF << TSU_DMAP_DESC_Q_SIZE_OFFS) +#define TSU_DMAP_DONE_Q_SIZE_OFFS 28 +#define TSU_DMAP_DONE_Q_SIZE_MASK (0xF << TSU_DMAP_DONE_Q_SIZE_OFFS) + +/* TSU Done queue base register. */ +#define TSU_DONE_PTR_BASE_OFFS 2 +#define TSU_DONE_PTR_BASE_MASK (0x3FFFFFFF << TSU_DONE_PTR_BASE_OFFS) + +/* TSU Desc queue base register. */ +#define TSU_DESC_PTR_BASE_OFFS 2 +#define TSU_DESC_PTR_BASE_MASK (0x3FFFFFFF << TSU_DESC_PTR_BASE_OFFS) + +/* TSU Done queue write pointer register. */ +#define TSU_DONE_WRITE_PTR_OFFS 0 +#define TSU_DONE_WRITE_PTR_MASK (0xFFF << TSU_DONE_WRITE_PTR_OFFS) + +/* TSU Done queue read pointer register. */ +#define TSU_DONE_READ_PTR_OFFS 0 +#define TSU_DONE_READ_PTR_MASK (0xFFF << TSU_DONE_READ_PTR_OFFS) + +/* TSU Desc queue write pointer register. */ +#define TSU_DESC_WRITE_PTR_OFFS 0 +#define TSU_DESC_WRITE_PTR_MASK (0xFFF << TSU_DESC_WRITE_PTR_OFFS) + +/* TSU Desc queue read pointer register. */ +#define TSU_DESC_READ_PTR_OFFS 0 +#define TSU_DESC_READ_PTR_MASK (0xFFF << TSU_DESC_READ_PTR_OFFS) + +/* TSU access enable reg. */ +#define TSU_ENACC_TS_READ_OFFS 0 +#define TSU_ENACC_TS_WRITE_OFFS 8 +#define TSU_ENACC_DESC_WRITE_OFFS 16 +#define TSU_ENACC_DESC_READ_OFFS 24 + +/* TSU Timestamp register. */ +#define TSU_TMSTMP_TIMESTAMP_OFFS 0 +#define TSU_TMSTMP_TIMESTAMP_MASK (0xFFFFFFF << TSU_TMSTMP_TIMESTAMP_OFFS) + +/* TSU status register. */ +#define TSU_STATUS_OFFS 0 +#define TSU_STATUS_MASK (0x7FF << TSU_STATUS_OFFS) +#define TSU_STATUS_IF_ERR (0x100 << TSU_STATUS_OFFS) +#define TSU_STATUS_FIFO_OVFL_ERR (0x200 << TSU_STATUS_OFFS) +#define TSU_STATUS_CONN_ERR (0x400 << TSU_STATUS_OFFS) + +/* TSU interrupt source register. */ +#define TSU_INT_TS_IF_ERROR (1 << 3) +#define TSU_INT_FIFO_OVFL_ERROR (1 << 4) +#define TSU_INT_TS_CONN_ERROR (1 << 5) +#define TSU_INT_CLOCK_SYNC_EXP (1 << 6) + +/* TSU SyncByte detect register. */ +#define TSU_SYNC_DETECT_CNT_OFFS 0 +#define TSU_SYNC_DETECT_CNT_MASK (0xF << TSU_SYNC_DETECT_CNT_OFFS) +#define TSU_SYNC_LOSS_CNT_OFFS 4 +#define TSU_SYNC_LOSS_CNT_MASK (0xF << TSU_SYNC_LOSS_CNT_OFFS) + +/* TSU Aggregation control register. */ +#define TSU_AGGR_PCKT_NUM_OFFS 0 +#define TSU_AGGR_PCKT_NUM_MASK (0xFF << TSU_AGGR_PCKT_NUM_OFFS) +#define TSU_AGGR_TMSTMP_OFF_OFFS 8 +#define TSU_AGGR_TMSTMP_OFF_MASK (0xF << TSU_AGGR_TMSTMP_OFF_OFFS) +#define TSU_AGGR_FLUSH_ERR_OFFS 26 +#define TSU_AGGR_FLUSH_ERR_MASK (0x3 << TSU_AGGR_FLUSH_ERR_OFFS) +#define TSU_AGGR_FLUSH_ERR_DISABLE (0x1 << TSU_AGGR_FLUSH_ERR_OFFS) +#define TSU_AGGR_FLUSH_ERR_ENABLE (0x2 << TSU_AGGR_FLUSH_ERR_OFFS) +#define TSU_AGGR_TMSTMP_MODE_OFFS 28 +#define TSU_AGGR_TMSTMP_MODE_MASK (0x3 << TSU_AGGR_TMSTMP_MODE_OFFS) +#define TSU_AGGR_TMSTMP_TO_DONE_Q (0x1 << TSU_AGGR_TMSTMP_MODE_OFFS) +#define TSU_AGGR_TMSTMP_TO_PCKT (0x2 << TSU_AGGR_TMSTMP_MODE_OFFS) +#define TSU_AGGR_ENABLE_OFFS 30 +#define TSU_AGGR_ENABLE_MASK (0x3 << TSU_AGGR_ENABLE_OFFS) +#define TSU_AGGR_DISABLE (0x1 << TSU_AGGR_ENABLE_OFFS) +#define TSU_AGGR_ENABLE (0x2 << TSU_AGGR_ENABLE_OFFS) + + +/* TSU timestamp interval register. */ +#define TSU_TMSTP_INTRVL_OFFS 0 +#define TSU_TMSTP_INTRVL_MASK (0xFFFFFFF << TSU_TMSTP_INTRVL_OFFS) + +/* TSU timestamp control register. */ +#define TSU_TMS_CTRL_TIMER_OFFS 0 +#define TSU_TMS_CTRL_TIMER_MASK (0x3 << TSU_TMS_CTRL_TIMER_OFFS) +#define TSU_TMS_CTRL_TIMER_DIS (0x1 << TSU_TMS_CTRL_TIMER_OFFS) +#define TSU_TMS_CTRL_TIMER_EN (0x2 << TSU_TMS_CTRL_TIMER_OFFS) +#define TSU_TMS_CTRL_AUTO_ADJ_OFFS 2 +#define TSU_TMS_CTRL_AUTO_ADJ_MASK (0x3 << TSU_TMS_CTRL_AUTO_ADJ_OFFS) +#define TSU_TMS_CTRL_AUTO_ADJ_OFF (0x1 << TSU_TMS_CTRL_AUTO_ADJ_OFFS) +#define TSU_TMS_CTRL_AUTO_ADJ_ON (0x2 << TSU_TMS_CTRL_AUTO_ADJ_OFFS) +#define TSU_TMS_CTRL_READ_TIMER_OFFS 4 +#define TSU_TMS_CTRL_READ_TIMER_MASK (0x1 << TSU_TMS_CTRL_READ_TIMER_OFFS) + + + + +#endif /* __INC_MV_TSU_REGS_H__ */ + diff --git a/board/mv_feroceon/mv_hal/twsi/mvTwsi.c b/board/mv_feroceon/mv_hal/twsi/mvTwsi.c new file mode 100644 index 0000000..75229ac --- /dev/null +++ b/board/mv_feroceon/mv_hal/twsi/mvTwsi.c @@ -0,0 +1,1026 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "mvTwsi.h" +#include "mvTwsiSpec.h" +#include "cpu/mvCpu.h" + + +/*#define MV_DEBUG*/ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +static MV_VOID twsiIntFlgClr(MV_U8 chanNum); +static MV_BOOL twsiMainIntGet(MV_U8 chanNum); +static MV_VOID twsiAckBitSet(MV_U8 chanNum); +static MV_U32 twsiStsGet(MV_U8 chanNum); +static MV_VOID twsiReset(MV_U8 chanNum); +static MV_STATUS twsiAddr7BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command); +static MV_STATUS twsiAddr10BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command); +static MV_STATUS twsiDataTransmit(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize); +static MV_STATUS twsiDataReceive(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize); +static MV_STATUS twsiTargetOffsSet(MV_U8 chanNum, MV_U32 offset,MV_BOOL moreThen256); + + +MV_BOOL twsiTimeoutChk(MV_U32 timeout, MV_U8 *pString) +{ + if(timeout >= TWSI_TIMEOUT_VALUE) + { + DB(mvOsPrintf("%s",pString)); + return MV_TRUE; + } + return MV_FALSE; + +} +/******************************************************************************* +* mvTwsiStartBitSet - Set start bit on the bus +* +* DESCRIPTION: +* This routine sets the start bit on the TWSI bus. +* The routine first checks for interrupt flag condition, then it sets +* the start bit in the TWSI Control register. +* If the interrupt flag condition check previously was set, the function +* will clear it. +* The function then wait for the start bit to be cleared by the HW. +* Then it waits for the interrupt flag to be set and eventually, the +* TWSI status is checked to be 0x8 or 0x10(repeated start bit). +* +* INPUT: +* chanNum - TWSI channel. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK is start bit was set successfuly on the bus. +* MV_FAIL if interrupt flag was set before setting start bit. +* +*******************************************************************************/ +MV_STATUS mvTwsiStartBitSet(MV_U8 chanNum) +{ + MV_BOOL isIntFlag = MV_FALSE; + MV_U32 timeout, temp; + + DB(mvOsPrintf("TWSI: mvTwsiStartBitSet \n")); + /* check Int flag */ + if(twsiMainIntGet(chanNum)) + isIntFlag = MV_TRUE; + /* set start Bit */ + temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); + MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_START_BIT); + + /* in case that the int flag was set before i.e. repeated start bit */ + if(isIntFlag){ + DB(mvOsPrintf("TWSI: mvTwsiStartBitSet repeated start Bit\n")); + twsiIntFlgClr(chanNum); + } + + /* wait for interrupt */ + timeout = 0; + while(!twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: mvTwsiStartBitSet ERROR - Start Clear bit TimeOut .\n")) + return MV_TIMEOUT; + + + /* check that start bit went down */ + if((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_START_BIT) != 0) + { + mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - start bit didn't went down\n"); + return MV_FAIL; + } + + /* check the status */ + temp = twsiStsGet(chanNum); + if(( temp != TWSI_START_CON_TRA ) && ( temp != TWSI_REPEATED_START_CON_TRA )) + { + mvOsPrintf("TWSI: mvTwsiStartBitSet ERROR - status %x after Set Start Bit. \n",temp); + return MV_FAIL; + } + + return MV_OK; + +} + +/******************************************************************************* +* mvTwsiStopBitSet - Set stop bit on the bus +* +* DESCRIPTION: +* This routine set the stop bit on the TWSI bus. +* The function then wait for the stop bit to be cleared by the HW. +* Finally the function checks for status of 0xF8. +* +* INPUT: +* chanNum - TWSI channel +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE is stop bit was set successfuly on the bus. +* +*******************************************************************************/ +MV_STATUS mvTwsiStopBitSet(MV_U8 chanNum) +{ + MV_U32 timeout, temp; + + /* Generate stop bit */ + temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); + MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_STOP_BIT); + + twsiIntFlgClr(chanNum); + + /* wait for stop bit to come down */ + timeout = 0; + while( ((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: mvTwsiStopBitSet ERROR - Stop bit TimeOut .\n")) + return MV_TIMEOUT; + + /* check that the stop bit went down */ + if((MV_REG_READ(TWSI_CONTROL_REG(chanNum)) & TWSI_CONTROL_STOP_BIT) != 0) + { + mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - stop bit didn't went down. \n"); + return MV_FAIL; + } + + /* check the status */ + temp = twsiStsGet(chanNum); + if( temp != TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0){ + mvOsPrintf("TWSI: mvTwsiStopBitSet ERROR - status %x after Stop Bit. \n", temp); + return MV_FAIL; + } + + return MV_OK; +} + +/******************************************************************************* +* twsiMainIntGet - Get twsi bit from main Interrupt cause. +* +* DESCRIPTION: +* This routine returns the twsi interrupt flag value. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE is interrupt flag is set, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL twsiMainIntGet(MV_U8 chanNum) +{ + MV_U32 temp; + + /* get the int flag bit */ + + temp = MV_REG_READ(TWSI_CPU_MAIN_INT_CAUSE_REG); + if (temp & (TWSI0_CPU_MAIN_INT_BIT << chanNum)) + return MV_TRUE; + + return MV_FALSE; +} +/******************************************************************************* +* twsiIntFlgClr - Clear Interrupt flag. +* +* DESCRIPTION: +* This routine clears the interrupt flag. It does NOT poll the interrupt +* to make sure the clear. After clearing the interrupt, it waits for at +* least 1 miliseconds. +* +* INPUT: +* chanNum - TWSI channel +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID twsiIntFlgClr(MV_U8 chanNum) +{ + MV_U32 temp; + + /* wait for 1 mili to prevent TWSI register write after write problems */ + mvOsDelay(1); + /* clear the int flag bit */ + temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); + MV_REG_WRITE(TWSI_CONTROL_REG(chanNum),temp & ~(TWSI_CONTROL_INT_FLAG_SET)); + + /* wait for 1 mili sec for the clear to take effect */ + mvOsDelay(1); + + return; +} + + +/******************************************************************************* +* twsiAckBitSet - Set acknowledge bit on the bus +* +* DESCRIPTION: +* This routine set the acknowledge bit on the TWSI bus. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +static MV_VOID twsiAckBitSet(MV_U8 chanNum) +{ + MV_U32 temp; + + /*Set the Ack bit */ + temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); + MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp | TWSI_CONTROL_ACK); + + /* Add delay of 1ms */ + mvOsDelay(1); + return; +} + + +/******************************************************************************* +* twsiInit - Initialize TWSI interface +* +* DESCRIPTION: +* This routine: +* -Reset the TWSI. +* -Initialize the TWSI clock baud rate according to given frequancy +* parameter based on Tclk frequancy and enables TWSI slave. +* -Set the ack bit. +* -Assign the TWSI slave address according to the TWSI address Type. +* +* +* INPUT: +* chanNum - TWSI channel +* frequancy - TWSI frequancy in KHz. (up to 100KHZ) +* +* OUTPUT: +* None. +* +* RETURN: +* Actual frequancy. +* +*******************************************************************************/ +MV_U32 mvTwsiInit(MV_U8 chanNum, MV_HZ frequancy, MV_U32 Tclk, MV_TWSI_ADDR *pTwsiAddr, MV_BOOL generalCallEnable) +{ + MV_U32 n,m,freq,margin,minMargin = 0xffffffff; + MV_U32 power; + MV_U32 actualFreq = 0,actualN = 0,actualM = 0,val; + + if(frequancy > 100000) + { + mvOsPrintf("Warning TWSI frequancy is too high, please use up tp 100Khz. \n"); + } + + DB(mvOsPrintf("TWSI: mvTwsiInit - Tclk = %d freq = %d\n",Tclk,frequancy)); + /* Calucalte N and M for the TWSI clock baud rate */ + for(n = 0 ; n < 8 ; n++) + { + for(m = 0 ; m < 16 ; m++) + { + power = 2 << n; /* power = 2^(n+1) */ + freq = Tclk/(10*(m+1)*power); + margin = MV_ABS(frequancy - freq); + if(margin < minMargin) + { + minMargin = margin; + actualFreq = freq; + actualN = n; + actualM = m; + } + } + } + DB(mvOsPrintf("TWSI: mvTwsiInit - actN %d actM %d actFreq %d\n",actualN , actualM, actualFreq)); + /* Reset the TWSI logic */ + twsiReset(chanNum); + + /* Set the baud rate */ + val = ((actualM<< TWSI_BAUD_RATE_M_OFFS) | actualN << TWSI_BAUD_RATE_N_OFFS); + MV_REG_WRITE(TWSI_STATUS_BAUDE_RATE_REG(chanNum),val); + + /* Enable the TWSI and slave */ + MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), TWSI_CONTROL_ENA | TWSI_CONTROL_ACK); + + /* set the TWSI slave address */ + if( pTwsiAddr->type == ADDR10_BIT )/* 10 Bit deviceAddress */ + { + /* writing the 2 most significant bits of the 10 bit address*/ + val = ((pTwsiAddr->address & TWSI_SLAVE_ADDR_10BIT_MASK) >> TWSI_SLAVE_ADDR_10BIT_OFFS ); + /* bits 7:3 must be 0x11110 */ + val |= TWSI_SLAVE_ADDR_10BIT_CONST; + /* set GCE bit */ + if(generalCallEnable) + val |= TWSI_SLAVE_ADDR_GCE_ENA; + /* write slave address */ + MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum),val); + + /* writing the 8 least significant bits of the 10 bit address*/ + val = (pTwsiAddr->address << TWSI_EXTENDED_SLAVE_OFFS) & TWSI_EXTENDED_SLAVE_MASK; + MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum), val); + } + else /*7 bit address*/ + { + /* set the 7 Bits address */ + MV_REG_WRITE(TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum),0x0); + val = (pTwsiAddr->address << TWSI_SLAVE_ADDR_7BIT_OFFS) & TWSI_SLAVE_ADDR_7BIT_MASK; + MV_REG_WRITE(TWSI_SLAVE_ADDR_REG(chanNum), val); + } + + /* unmask twsi int */ + val = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); + MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), val | TWSI_CONTROL_INT_ENA); + /* Add delay of 1ms */ + mvOsDelay(1); + + return actualFreq; +} + + +/******************************************************************************* +* twsiStsGet - Get the TWSI status value. +* +* DESCRIPTION: +* This routine returns the TWSI status value. +* +* INPUT: +* chanNum - TWSI channel +* +* OUTPUT: +* None. +* +* RETURN: +* MV_U32 - the TWSI status. +* +*******************************************************************************/ +static MV_U32 twsiStsGet(MV_U8 chanNum) +{ + return MV_REG_READ(TWSI_STATUS_BAUDE_RATE_REG(chanNum)); + +} + +/******************************************************************************* +* twsiReset - Reset the TWSI. +* +* DESCRIPTION: +* Resets the TWSI logic and sets all TWSI registers to their reset values. +* +* INPUT: +* chanNum - TWSI channel +* +* OUTPUT: +* None. +* +* RETURN: +* None +* +*******************************************************************************/ +static MV_VOID twsiReset(MV_U8 chanNum) +{ + /* Reset the TWSI logic */ + MV_REG_WRITE(TWSI_SOFT_RESET_REG(chanNum),0); + + /* wait for 2 mili sec */ + mvOsDelay(2); + + return; +} + + + + +/******************************* POLICY ****************************************/ + + + +/******************************************************************************* +* mvTwsiAddrSet - Set address on TWSI bus. +* +* DESCRIPTION: +* This function Set address (7 or 10 Bit address) on the Twsi Bus. +* +* INPUT: +* chanNum - TWSI channel +* pTwsiAddr - twsi address. +* command - read / write . +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK - if setting the address completed succesfully. +* MV_FAIL otherwmise. +* +*******************************************************************************/ +MV_STATUS mvTwsiAddrSet(MV_U8 chanNum, MV_TWSI_ADDR *pTwsiAddr, MV_TWSI_CMD command) +{ + DB(mvOsPrintf("TWSI: mvTwsiAddr7BitSet addr %x , type %d, cmd is %s\n",pTwsiAddr->address,\ + pTwsiAddr->type, ((command==MV_TWSI_WRITE)?"Write":"Read") )); + /* 10 Bit address */ + if(pTwsiAddr->type == ADDR10_BIT) + { + return twsiAddr10BitSet(chanNum, pTwsiAddr->address,command); + } + /* 7 Bit address */ + else + { + return twsiAddr7BitSet(chanNum, pTwsiAddr->address,command); + } + +} + +/******************************************************************************* +* twsiAddr10BitSet - Set 10 Bit address on TWSI bus. +* +* DESCRIPTION: +* There are two address phases: +* 1) Write '11110' to data register bits [7:3] and 10-bit address MSB +* (bits [9:8]) to data register bits [2:1] plus a write(0) or read(1) bit +* to the Data register. Then it clears interrupt flag which drive +* the address on the TWSI bus. The function then waits for interrupt +* flag to be active and status 0x18 (write) or 0x40 (read) to be set. +* 2) write the rest of 10-bit address to data register and clears +* interrupt flag which drive the address on the TWSI bus. The +* function then waits for interrupt flag to be active and status +* 0xD0 (write) or 0xE0 (read) to be set. +* +* INPUT: +* chanNum - TWSI channel +* deviceAddress - twsi address. +* command - read / write . +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK - if setting the address completed succesfully. +* MV_FAIL otherwmise. +* +*******************************************************************************/ +static MV_STATUS twsiAddr10BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command) +{ + MV_U32 val,timeout; + + /* writing the 2 most significant bits of the 10 bit address*/ + val = ((deviceAddress & TWSI_DATA_ADDR_10BIT_MASK) >> TWSI_DATA_ADDR_10BIT_OFFS ); + /* bits 7:3 must be 0x11110 */ + val |= TWSI_DATA_ADDR_10BIT_CONST; + /* set command */ + val |= command; + MV_REG_WRITE(TWSI_DATA_REG(chanNum), val); + /* WA add a delay */ + mvOsDelay(1); + + /* clear Int flag */ + twsiIntFlgClr(chanNum); + + /* wait for Int to be Set */ + timeout = 0; + while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: twsiAddr10BitSet ERROR - 1st addr (10Bit) Int TimeOut.\n")) + return MV_TIMEOUT; + + /* check the status */ + val = twsiStsGet(chanNum); + if(( (val != TWSI_AD_PLS_RD_BIT_TRA_ACK_REC) && (command == MV_TWSI_READ ) ) || + ( (val != TWSI_AD_PLS_WR_BIT_TRA_ACK_REC) && (command == MV_TWSI_WRITE) )) + { + mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 1st addr (10 Bit) in %s mode.\n"\ + ,val, ((command==MV_TWSI_WRITE)?"Write":"Read") ); + return MV_FAIL; + } + + /* set 8 LSB of the address */ + val = (deviceAddress << TWSI_DATA_ADDR_7BIT_OFFS) & TWSI_DATA_ADDR_7BIT_MASK; + MV_REG_WRITE(TWSI_DATA_REG(chanNum), val); + + /* clear Int flag */ + twsiIntFlgClr(chanNum); + + /* wait for Int to be Set */ + timeout = 0; + while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: twsiAddr10BitSet ERROR - 2nd (10 Bit) Int TimOut.\n")) + return MV_TIMEOUT; + + /* check the status */ + val = twsiStsGet(chanNum); + if(( (val != TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_REC) && (command == MV_TWSI_READ ) ) || + ( (val != TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_REC) && (command == MV_TWSI_WRITE) )) + { + mvOsPrintf("TWSI: twsiAddr10BitSet ERROR - status %x 2nd addr(10 Bit) in %s mode.\n"\ + ,val, ((command==MV_TWSI_WRITE)?"Write":"Read") ); + return MV_FAIL; + } + + return MV_OK; +} + +/******************************************************************************* +* twsiAddr7BitSet - Set 7 Bit address on TWSI bus. +* +* DESCRIPTION: +* This function writes 7 bit address plus a write or read bit to the +* Data register. Then it clears interrupt flag which drive the address on +* the TWSI bus. The function then waits for interrupt flag to be active +* and status 0x18 (write) or 0x40 (read) to be set. +* +* INPUT: +* chanNum - TWSI channel +* deviceAddress - twsi address. +* command - read / write . +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK - if setting the address completed succesfully. +* MV_FAIL otherwmise. +* +*******************************************************************************/ +static MV_STATUS twsiAddr7BitSet(MV_U8 chanNum, MV_U32 deviceAddress,MV_TWSI_CMD command) +{ + MV_U32 val,timeout; + + /* set the address */ + val = (deviceAddress << TWSI_DATA_ADDR_7BIT_OFFS) & TWSI_DATA_ADDR_7BIT_MASK; + /* set command */ + val |= command; + MV_REG_WRITE(TWSI_DATA_REG(chanNum), val); + /* WA add a delay */ + mvOsDelay(1); + + /* clear Int flag */ + twsiIntFlgClr(chanNum); + + /* wait for Int to be Set */ + timeout = 0; + while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: twsiAddr7BitSet ERROR - Addr (7 Bit) int TimeOut.\n")) + return MV_TIMEOUT; + + /* check the status */ + val = twsiStsGet(chanNum); + if(( (val != TWSI_AD_PLS_RD_BIT_TRA_ACK_REC) && (command == MV_TWSI_READ ) ) || + ( (val != TWSI_AD_PLS_WR_BIT_TRA_ACK_REC) && (command == MV_TWSI_WRITE) )) + { + /* only in debug, since in boot we try to read the SPD of both DRAM, and we don't + want error messeges in case DIMM doesn't exist. */ + DB(mvOsPrintf("TWSI: twsiAddr7BitSet ERROR - status %x addr (7 Bit) in %s mode.\n"\ + ,val,((command==MV_TWSI_WRITE)?"Write":"Read") )); + return MV_FAIL; + } + + return MV_OK; +} + +/******************************************************************************* +* twsiDataWrite - Trnasmit a data block over TWSI bus. +* +* DESCRIPTION: +* This function writes a given data block to TWSI bus in 8 bit granularity. +* first The function waits for interrupt flag to be active then +* For each 8-bit data: +* The function writes data to data register. It then clears +* interrupt flag which drives the data on the TWSI bus. +* The function then waits for interrupt flag to be active and status +* 0x28 to be set. +* +* +* INPUT: +* chanNum - TWSI channel +* pBlock - Data block. +* blockSize - number of chars in pBlock. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK - if transmiting the block completed succesfully, +* MV_BAD_PARAM - if pBlock is NULL, +* MV_FAIL otherwmise. +* +*******************************************************************************/ +static MV_STATUS twsiDataTransmit(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize) +{ + MV_U32 timeout, temp, blockSizeWr = blockSize; + + if(NULL == pBlock) + return MV_BAD_PARAM; + + /* wait for Int to be Set */ + timeout = 0; + while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n")) + return MV_TIMEOUT; + + while(blockSizeWr) + { + /* write the data*/ + MV_REG_WRITE(TWSI_DATA_REG(chanNum),(MV_U32)*pBlock); + DB(mvOsPrintf("TWSI: twsiDataTransmit place = %d write %x \n",\ + blockSize - blockSizeWr, *pBlock)); + pBlock++; + blockSizeWr--; + + twsiIntFlgClr(chanNum); + + /* wait for Int to be Set */ + timeout = 0; + while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: twsiDataTransmit ERROR - Read Data Int TimeOut.\n")) + return MV_TIMEOUT; + + /* check the status */ + temp = twsiStsGet(chanNum); + if(temp != TWSI_M_TRAN_DATA_BYTE_ACK_REC) + { + mvOsPrintf("TWSI: twsiDataTransmit ERROR - status %x in write trans\n",temp); + return MV_FAIL; + } + + } + + return MV_OK; +} + +/******************************************************************************* +* twsiDataReceive - Receive data block from TWSI bus. +* +* DESCRIPTION: +* This function receive data block from TWSI bus in 8bit granularity +* into pBlock buffer. +* first The function waits for interrupt flag to be active then +* For each 8-bit data: +* It clears the interrupt flag which allows the next data to be +* received from TWSI bus. +* The function waits for interrupt flag to be active, +* and status reg is 0x50. +* Then the function reads data from data register, and copies it to +* the given buffer. +* +* INPUT: +* chanNum - TWSI channel +* blockSize - number of bytes to read. +* +* OUTPUT: +* pBlock - Data block. +* +* RETURN: +* MV_OK - if receive transaction completed succesfully, +* MV_BAD_PARAM - if pBlock is NULL, +* MV_FAIL otherwmise. +* +*******************************************************************************/ +static MV_STATUS twsiDataReceive(MV_U8 chanNum, MV_U8 *pBlock, MV_U32 blockSize) +{ + MV_U32 timeout, temp, blockSizeRd = blockSize; + if(NULL == pBlock) + return MV_BAD_PARAM; + + /* wait for Int to be Set */ + timeout = 0; + while( !twsiMainIntGet(chanNum) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: twsiDataReceive ERROR - Read Data int Time out .\n")) + return MV_TIMEOUT; + + while(blockSizeRd) + { + if(blockSizeRd == 1) + { + /* clear ack and Int flag */ + temp = MV_REG_READ(TWSI_CONTROL_REG(chanNum)); + temp &= ~(TWSI_CONTROL_ACK); + MV_REG_WRITE(TWSI_CONTROL_REG(chanNum), temp); + } + twsiIntFlgClr(chanNum); + /* wait for Int to be Set */ + timeout = 0; + while( (!twsiMainIntGet(chanNum)) && (timeout++ < TWSI_TIMEOUT_VALUE)); + + /* check for timeout */ + if(MV_TRUE == twsiTimeoutChk(timeout,(MV_U8 *)"TWSI: twsiDataReceive ERROR - Read Data Int Time out .\n")) + return MV_TIMEOUT; + + /* check the status */ + temp = twsiStsGet(chanNum); + if((temp != TWSI_M_REC_RD_DATA_ACK_TRA) && (blockSizeRd !=1)) + { + mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in read trans \n",temp); + return MV_FAIL; + } + else if((temp != TWSI_M_REC_RD_DATA_ACK_NOT_TRA) && (blockSizeRd ==1)) + { + mvOsPrintf("TWSI: twsiDataReceive ERROR - status %x in Rd Terminate\n",temp); + return MV_FAIL; + } + + /* read the data*/ + *pBlock = (MV_U8)MV_REG_READ(TWSI_DATA_REG(chanNum)); + DB(mvOsPrintf("TWSI: twsiDataReceive place %d read %x \n",\ + blockSize - blockSizeRd,*pBlock)); + pBlock++; + blockSizeRd--; + } + + return MV_OK; +} + + + +/******************************************************************************* +* twsiTargetOffsSet - Set TWST target offset on TWSI bus. +* +* DESCRIPTION: +* The function support TWSI targets that have inside address space (for +* example EEPROMs). The function: +* 1) Convert the given offset into pBlock and size. +* in case the offset should be set to a TWSI slave which support +* more then 256 bytes offset, the offset setting will be done +* in 2 transactions. +* 2) Use twsiDataTransmit to place those on the bus. +* +* INPUT: +* chanNum - TWSI channel +* offset - offset to be set on the EEPROM device. +* moreThen256 - whether the EEPROM device support more then 256 byte offset. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK - if setting the offset completed succesfully. +* MV_FAIL otherwmise. +* +*******************************************************************************/ +static MV_STATUS twsiTargetOffsSet(MV_U8 chanNum, MV_U32 offset, MV_BOOL moreThen256) +{ + MV_U8 offBlock[4]; + MV_U32 offSize; + + if(moreThen256 == MV_TRUE) + { + offBlock[0] = (offset >> 24) & 0xff; + offBlock[1] = (offset >> 16) & 0xff; + offBlock[2] = (offset >> 8) & 0xff; + offBlock[3] = offset & 0xff; + offSize = 4; + } + else + { + offBlock[0] = offset & 0xff; + offSize = 1; + } + + DB(mvOsPrintf("TWSI: twsiTargetOffsSet offSize = %x addr1 = %x addr2 = %x\n",\ + offSize,offBlock[0],offBlock[1])); + return twsiDataTransmit(chanNum, offBlock, offSize); + +} + +/******************************************************************************* +* mvTwsiRead - Read data block from a TWSI Slave. +* +* DESCRIPTION: +* The function calls the following functions: +* -) mvTwsiStartBitSet(); +* if(EEPROM device) +* -) mvTwsiAddrSet(w); +* -) twsiTargetOffsSet(); +* -) mvTwsiStartBitSet(); +* -) mvTwsiAddrSet(r); +* -) twsiDataReceive(); +* -) mvTwsiStopBitSet(); +* +* INPUT: +* chanNum - TWSI channel +* pTwsiSlave - Twsi Slave structure. +* blockSize - number of bytes to read. +* +* OUTPUT: +* pBlock - Data block. +* +* RETURN: +* MV_OK - if EEPROM read transaction completed succesfully, +* MV_BAD_PARAM - if pBlock is NULL, +* MV_FAIL otherwmise. +* +*******************************************************************************/ +MV_STATUS mvTwsiRead(MV_U8 chanNum, MV_TWSI_SLAVE *pTwsiSlave, MV_U8 *pBlock, MV_U32 blockSize) +{ + if((NULL == pBlock) || (NULL == pTwsiSlave)) + return MV_BAD_PARAM; + if(MV_OK != mvTwsiStartBitSet(chanNum)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + + DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n")); + + /* in case offset exsist (i.e. eeprom ) */ + if(MV_TRUE == pTwsiSlave->validOffset) + { + if(MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_WRITE)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n")); + if(MV_OK != twsiTargetOffsSet(chanNum, pTwsiSlave->offset, pTwsiSlave->moreThen256)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiTargetOffsSet\n")); + if(MV_OK != mvTwsiStartBitSet(chanNum)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStartBitSet\n")); + } + if(MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_READ)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiAddrSet\n")); + if(MV_OK != twsiDataReceive(chanNum, pBlock, blockSize)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromRead after twsiDataReceive\n")); + + if(MV_OK != mvTwsiStopBitSet(chanNum)) + { + return MV_FAIL; + } + + twsiAckBitSet(chanNum); + + DB(mvOsPrintf("TWSI: mvTwsiEepromRead after mvTwsiStopBitSet\n")); + + return MV_OK; +} + +/******************************************************************************* +* mvTwsiWrite - Write data block to a TWSI Slave. +* +* DESCRIPTION: +* The function calls the following functions: +* -) mvTwsiStartBitSet(); +* -) mvTwsiAddrSet(); +* -)if(EEPROM device) +* -) twsiTargetOffsSet(); +* -) twsiDataTransmit(); +* -) mvTwsiStopBitSet(); +* +* INPUT: +* chanNum - TWSI channel +* eepromAddress - eeprom address. +* blockSize - number of bytes to write. +* pBlock - Data block. +* +* OUTPUT: +* None +* +* RETURN: +* MV_OK - if EEPROM read transaction completed succesfully. +* MV_BAD_PARAM - if pBlock is NULL, +* MV_FAIL otherwmise. +* +* NOTE: Part of the EEPROM, required that the offset will be aligned to the +* max write burst supported. +*******************************************************************************/ +MV_STATUS mvTwsiWrite(MV_U8 chanNum, MV_TWSI_SLAVE *pTwsiSlave, MV_U8 *pBlock, MV_U32 blockSize) +{ + if((NULL == pBlock) || (NULL == pTwsiSlave)) + return MV_BAD_PARAM; + + if(MV_OK != mvTwsiStartBitSet(chanNum)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + + DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStartBitSet\n")); + if(MV_OK != mvTwsiAddrSet(chanNum, &(pTwsiSlave->slaveAddr), MV_TWSI_WRITE)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI :mvTwsiEepromWrite after mvTwsiAddrSet\n")); + + /* in case offset exsist (i.e. eeprom ) */ + if(MV_TRUE == pTwsiSlave->validOffset) + { + if(MV_OK != twsiTargetOffsSet(chanNum, pTwsiSlave->offset, pTwsiSlave->moreThen256)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiTargetOffsSet\n")); + } + if(MV_OK != twsiDataTransmit(chanNum, pBlock, blockSize)) + { + mvTwsiStopBitSet(chanNum); + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after twsiDataTransmit\n")); + if(MV_OK != mvTwsiStopBitSet(chanNum)) + { + return MV_FAIL; + } + DB(mvOsPrintf("TWSI: mvTwsiEepromWrite after mvTwsiStopBitSet\n")); + + return MV_OK; +} diff --git a/board/mv_feroceon/mv_hal/twsi/mvTwsi.h b/board/mv_feroceon/mv_hal/twsi/mvTwsi.h new file mode 100644 index 0000000..bd5b6d0 --- /dev/null +++ b/board/mv_feroceon/mv_hal/twsi/mvTwsi.h @@ -0,0 +1,121 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvTwsiH +#define __INCmvTwsiH + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* need to update this includes */ +#include "twsi/mvTwsiSpec.h" +#include "ctrlEnv/mvCtrlEnvLib.h" + + +/* The TWSI interface supports both 7-bit and 10-bit addressing. */ +/* This enumerator describes addressing type. */ +typedef enum _mvTwsiAddrType +{ + ADDR7_BIT, /* 7 bit address */ + ADDR10_BIT /* 10 bit address */ +}MV_TWSI_ADDR_TYPE; + +/* This structure describes TWSI address. */ +typedef struct _mvTwsiAddr +{ + MV_U32 address; /* address */ + MV_TWSI_ADDR_TYPE type; /* Address type */ +}MV_TWSI_ADDR; + +/* This structure describes a TWSI slave. */ +typedef struct _mvTwsiSlave +{ + MV_TWSI_ADDR slaveAddr; + MV_BOOL validOffset; /* whether the slave has offset (i.e. Eeprom etc.) */ + MV_U32 offset; /* offset in the slave. */ + MV_BOOL moreThen256; /* whether the ofset is bigger then 256 */ +}MV_TWSI_SLAVE; + +/* This enumerator describes TWSI protocol commands. */ +typedef enum _mvTwsiCmd +{ + MV_TWSI_WRITE, /* TWSI write command - 0 according to spec */ + MV_TWSI_READ /* TWSI read command - 1 according to spec */ +}MV_TWSI_CMD; + +MV_STATUS mvTwsiStartBitSet(MV_U8 chanNum); +MV_STATUS mvTwsiStopBitSet(MV_U8 chanNum); +MV_STATUS mvTwsiAddrSet(MV_U8 chanNum, MV_TWSI_ADDR *twsiAddr, MV_TWSI_CMD command); + +MV_U32 mvTwsiInit(MV_U8 chanNum, MV_KHZ frequancy, MV_U32 Tclk, MV_TWSI_ADDR *twsiAddr, MV_BOOL generalCallEnable); +MV_STATUS mvTwsiRead (MV_U8 chanNum, MV_TWSI_SLAVE *twsiSlave, MV_U8 *pBlock, MV_U32 blockSize); +MV_STATUS mvTwsiWrite(MV_U8 chanNum, MV_TWSI_SLAVE *twsiSlave, MV_U8 *pBlock, MV_U32 blockSize); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvTwsiH */ + diff --git a/board/mv_feroceon/mv_hal/twsi/mvTwsiEeprom.S b/board/mv_feroceon/mv_hal/twsi/mvTwsiEeprom.S new file mode 100644 index 0000000..e83e4cd --- /dev/null +++ b/board/mv_feroceon/mv_hal/twsi/mvTwsiEeprom.S @@ -0,0 +1,457 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#define MV_ASMLANGUAGE +#include "mvCtrlEnvSpec.h" +#include "mvBoardEnvSpec.h" +#include "mvOsAsm.h" +#include "mvTwsiSpec.h" +#include "mvSysHwConfig.h" +#include "mvCpuIfRegs.h" +#include "mvCommon.h" + +#define I2C_CH MV_BOARD_DIMM_I2C_CHANNEL + +/* defines */ +/* defines */ + + + .data + .global _i2cInit + .global _i2cRead + + .text + +/******************************************************************************* +* _i2cInit - Initialize TWSI interface +* +* DESCRIPTION: +* The function performs TWSI interface initialization. It resets the +* TWSI state machine and initialize its clock to 100KHz assuming Tclock +* of 133MHz. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +_i2cInit: + mov r9, LR /* Save link register */ + mov r0, #0 /* Make sure r0 is zero */ + + /* Reset the i2c Mechanism first */ + MV_REG_WRITE_ASM (r0, r1, TWSI_SOFT_RESET_REG(I2C_CH)) + + bl _twsiDelay + bl _twsiDelay + + /* Initializing the I2C mechanism. Assuming Tclock frequency */ + /* of 166MHz. The I2C frequency in that case will be 100KHz. */ + /* For this settings, M = 9 and N = 3. Set the baud-rate with the */ + /* value of 0x2b (freq of ==> 100KHz */ + /* see spec for more details about the calculation of this value) */ + mov r6, #(9 << 3 | 3) + MV_REG_WRITE_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + + /* Enable the I2C master */ + /* Enable TWSI interrupt in main mask reg */ + mov r6, #0xC4 + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + + /* Let the slow TWSI machine get used to the idea that it is enabled */ + bl _twsiDelay + + + mov PC, r9 /* r9 is saved link register */ + +/******************************************************************************* +* _twsiDelay - Perform delay. +* +* DESCRIPTION: +* The function performs a delay to enable TWSI logic to stable. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +_twsiDelay: + mov r10, #0x400 + +_twsiDelayLoop: + subs r10, r10, #1 + bne _twsiDelayLoop + + mov PC, LR + +/******************************************************************************* +* _i2cRead - Read byte from I2C EEPROM device. +* +* DESCRIPTION: +* The function returns a byte from I2C EEPROM device. +* The EEPROM device is 7-bit address type. +* +* INPUT: +* r4 has the DIMM0 base address with shift 1 bit to the left +* r7 has the EEPROM offset +* +* OUTPUT: +* None. +* +* RETURN: +* r4 returns '0' if address can not be read. +* r7 has byte value in case read is successful. +* +*******************************************************************************/ +_i2cRead: + mov r9, LR /* Save link register */ + + /* Transmit the device address and desired offset within the EEPROM. */ + + /* Generate Start Bit */ + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + orr r6, r6, #TWSI_CONTROL_START_BIT + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + + /* Wait for the interrupt flag (bit3) to be set */ + mov r10, #0x50000 +loop_1: + subs r10, r10, #1 + beq loop_1_timeout +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH)) + tst r6, #BIT2 +#else + MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) + tst r6, #BIT5 +#endif + beq loop_1 + +loop_1_timeout: + + /* Wait for the start bit to be reset by HW */ + mov r10, #0x50000 +loop_2: + subs r10, r10, #1 + beq loop_2_timeout + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + tst r6, #TWSI_CONTROL_START_BIT + bne loop_2 + +loop_2_timeout: + + /* Wait for the status TWSI_START_CONDITION_TRA = 0x8 */ + mov r10, #0x50000 +loop_3: + subs r10, r10, #1 + beq loop_3_timeout + MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + cmp r6, #0x08 + bne loop_3 + +loop_3_timeout: + + /* writing the address of (DIMM0/1 << 1) with write indication */ + mov r6, r4, LSL #1 /* Write operation address bit 0 must be 0 */ + MV_REG_WRITE_ASM (r6, r1, TWSI_DATA_REG(I2C_CH)) + + bl _twsiDelay + /* Clear the interrupt flag */ + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bic r6, r6, #TWSI_CONTROL_INT_FLAG_SET + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bl _twsiDelay + + /* Waiting for the interrupt flag to be set which means that the + address has been transmitted */ +loop_4: +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH)) + tst r6, #BIT2 +#else + MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) + tst r6, #BIT5 +#endif + beq loop_4 /* if tst = 0, then the bit is not set yet */ + + /* Wait for status TWSI_ADDR_PLUS_WRITE_BIT_TRA_ACK_REC = 0x18 */ + mov r10, #0x50000 /* Set r10 to 0x50000 =~ 328,000 */ + +loop_5: + subs r10, r10, #1 /* timeout count down */ + bne testStatus + mov r4, #0 /* r4 = 0 -> operation failed */ + b exit_i2cRead /* Exit if timeout (No DIMM) */ + +testStatus: + MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + cmp r6, #0x18 + bne loop_5 + + + /* check if the offset is bigger than 256 byte*/ + tst r7, #0x80000000 + bne great_than_256 + + /* Write the offset to be read from the DIMM EEPROM */ + MV_REG_WRITE_ASM (r7, r1, TWSI_DATA_REG(I2C_CH)) + + b after_offset + +great_than_256: + mov r10, r7, LSR #8 + and r10, r10, #0xff + /* Write the offset0 to be read from the EEPROM */ + MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH)) + + /* Clear the interrupt flag ==> signaling that the address can now + be transmited */ + + bl _twsiDelay + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bic r6, r6, #TWSI_CONTROL_INT_FLAG_SET + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bl _twsiDelay + + /* Wait for the interrupt to be set again ==> address has transmited */ +loop_6_1: +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH)) + tst r6, #BIT2 +#else + MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) + tst r6, #BIT5 +#endif + beq loop_6_1 + + /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */ +loop_7_1: + MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + cmp r6, #0x28 + bne loop_7_1 + + + mov r10, r7 + and r10, r10, #0xff + /* Write the offset1 to be read from the EEPROM */ + MV_REG_WRITE_ASM (r10, r1, TWSI_DATA_REG(I2C_CH)) + + + +after_offset: + + /* Clear the interrupt flag ==> signaling that the address can now + be transmited */ + + bl _twsiDelay + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bic r6, r6, #TWSI_CONTROL_INT_FLAG_SET + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bl _twsiDelay + + /* Wait for the interrupt to be set again ==> address has transmited */ +loop_6: +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH)) + tst r6, #BIT2 +#else + MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) + tst r6, #BIT5 +#endif + beq loop_6 + + /* Wait for status TWSI_MAS_TRAN_DATA_BYTE_ACK_REC = 0x28 */ +loop_7: + MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + cmp r6, #0x28 + bne loop_7 + + /* Retransmit the device address with read indication to get the data */ + + /* generate a repeated start bit */ + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + orr r6, r6, #TWSI_CONTROL_START_BIT + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + + + /* Clear the interrupt flag ==> the start bit will be transmitted. */ + bl _twsiDelay + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bic r6, r6, #TWSI_CONTROL_INT_FLAG_SET + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bl _twsiDelay + + /* Wait for the interrupt flag (bit3) to be set */ +loop_9: +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH)) + tst r6, #BIT2 +#else + MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) + tst r6, #BIT5 +#endif + beq loop_9 + + /* Wait for the start bit to be reset by HW */ +loop_8: + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + tst r6, #TWSI_CONTROL_START_BIT + bne loop_8 + + /* Wait for status TWSI_REPEATED_START_CONDITION_TRA = 0x10 */ +loop_10: + MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + cmp r6, #0x10 + bne loop_10 + + /* Writing the address of (DIMM0<<1) with read indication (bit0 is 1) */ + mov r6, r4, LSL #1 + orr r6, r6, #1 /* Read operation address bit 0 must be 1 */ + MV_REG_WRITE_ASM (r6, r1, TWSI_DATA_REG(I2C_CH)) + + /* Clear the interrupt flag ==> the address will be transmitted */ + bl _twsiDelay + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bic r6, r6, #TWSI_CONTROL_INT_FLAG_SET + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bl _twsiDelay + + /* Wait for the interrupt flag (bit3) to be set as a result of + transmitting the address. */ +loop_11: +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH)) + tst r6, #BIT2 +#else + MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) + tst r6, #BIT5 +#endif + beq loop_11 + + /* Wait for status TWSI_ADDR_PLUS_READ_BIT_TRA_ACK_REC = 0x40 */ +loop_12: + MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + cmp r6, #0x40 + bne loop_12 + + /* Clear the interrupt flag and the Acknoledge bit */ + bl _twsiDelay + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bic r6, r6, #(TWSI_CONTROL_INT_FLAG_SET | TWSI_CONTROL_ACK) + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bl _twsiDelay + + /* Wait for the interrupt flag (bit3) to be set */ +loop_14: +#ifdef MV78XX0 + MV_REG_READ_ASM (r6, r1, CPU_INT_LOW_REG(I2C_CH)) + tst r6, #BIT2 +#else + MV_REG_READ_ASM (r6, r1, CPU_MAIN_INT_CAUSE_REG) + tst r6, #BIT5 +#endif + beq loop_14 + + /* Wait for status TWSI_MAS_REC_READ_DATA_ACK_NOT_TRA = 0x58 */ +loop_15: + MV_REG_READ_ASM (r6, r1, TWSI_STATUS_BAUDE_RATE_REG(I2C_CH)) + cmp r6, #0x58 + bne loop_15 + + /* Store the data in r7. */ + MV_REG_READ_ASM (r7, r1, TWSI_DATA_REG(I2C_CH)) + + /* Generate stop bit */ + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + orr r6, r6, #TWSI_CONTROL_STOP_BIT + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + + + /* Clear the interrupt flag */ + bl _twsiDelay + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bic r6, r6, #TWSI_CONTROL_INT_FLAG_SET + MV_REG_WRITE_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + bl _twsiDelay + + /* Wait for the stop bit to be reset by HW */ +loop_16: + MV_REG_READ_ASM (r6, r1, TWSI_CONTROL_REG(I2C_CH)) + tst r6, #TWSI_CONTROL_INT_FLAG_SET + bne loop_16 + +exit_i2cRead: + mov PC, r9 /* r9 is saved link register */ diff --git a/board/mv_feroceon/mv_hal/twsi/mvTwsiSpec.h b/board/mv_feroceon/mv_hal/twsi/mvTwsiSpec.h new file mode 100644 index 0000000..3c6283d --- /dev/null +++ b/board/mv_feroceon/mv_hal/twsi/mvTwsiSpec.h @@ -0,0 +1,160 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/****************************************/ +/* TWSI Registers */ +/****************************************/ +#ifndef __INCmvTwsiSpech +#define __INCmvTwsiSpech + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines */ +#define TWSI_SLAVE_ADDR_REG(chanNum) (TWSI_SLAVE_BASE(chanNum)+ 0x00) + +#define TWSI_SLAVE_ADDR_GCE_ENA BIT0 +#define TWSI_SLAVE_ADDR_7BIT_OFFS 0x1 +#define TWSI_SLAVE_ADDR_7BIT_MASK (0xFF << TWSI_SLAVE_ADDR_7BIT_OFFS) +#define TWSI_SLAVE_ADDR_10BIT_OFFS 0x7 +#define TWSI_SLAVE_ADDR_10BIT_MASK 0x300 +#define TWSI_SLAVE_ADDR_10BIT_CONST 0xF0 + + +#define TWSI_EXTENDED_SLAVE_ADDR_REG(chanNum) (TWSI_SLAVE_BASE(chanNum) + 0x10) +#define TWSI_EXTENDED_SLAVE_OFFS 0 +#define TWSI_EXTENDED_SLAVE_MASK (0xFF << TWSI_EXTENDED_SLAVE_OFFS) + + +#define TWSI_DATA_REG(chanNum) (TWSI_SLAVE_BASE(chanNum) + 0x04) +#define TWSI_DATA_COMMAND_OFFS 0x0 +#define TWSI_DATA_COMMAND_MASK (0x1 << TWSI_DATA_COMMAND_OFFS) +#define TWSI_DATA_COMMAND_WR (0x1 << TWSI_DATA_COMMAND_OFFS) +#define TWSI_DATA_COMMAND_RD (0x0 << TWSI_DATA_COMMAND_OFFS) +#define TWSI_DATA_ADDR_7BIT_OFFS 0x1 +#define TWSI_DATA_ADDR_7BIT_MASK (0xFF << TWSI_DATA_ADDR_7BIT_OFFS) +#define TWSI_DATA_ADDR_10BIT_OFFS 0x7 +#define TWSI_DATA_ADDR_10BIT_MASK 0x300 +#define TWSI_DATA_ADDR_10BIT_CONST 0xF0 + + +#define TWSI_CONTROL_REG(chanNum) (TWSI_SLAVE_BASE(chanNum) + 0x08) +#define TWSI_CONTROL_ACK BIT2 +#define TWSI_CONTROL_INT_FLAG_SET BIT3 +#define TWSI_CONTROL_STOP_BIT BIT4 +#define TWSI_CONTROL_START_BIT BIT5 +#define TWSI_CONTROL_ENA BIT6 +#define TWSI_CONTROL_INT_ENA BIT7 + + +#define TWSI_STATUS_BAUDE_RATE_REG(chanNum) (TWSI_SLAVE_BASE(chanNum) + 0x0c) +#define TWSI_BAUD_RATE_N_OFFS 0 +#define TWSI_BAUD_RATE_N_MASK (0x7 << TWSI_BAUD_RATE_N_OFFS) +#define TWSI_BAUD_RATE_M_OFFS 3 +#define TWSI_BAUD_RATE_M_MASK (0xF << TWSI_BAUD_RATE_M_OFFS) + +#define TWSI_SOFT_RESET_REG(chanNum) (TWSI_SLAVE_BASE(chanNum) + 0x1c) + +/* defines */ +#define TWSI_TIMEOUT_VALUE 0x500 + +/* TWSI status codes */ +#define TWSI_BUS_ERROR 0x00 +#define TWSI_START_CON_TRA 0x08 +#define TWSI_REPEATED_START_CON_TRA 0x10 +#define TWSI_AD_PLS_WR_BIT_TRA_ACK_REC 0x18 +#define TWSI_AD_PLS_WR_BIT_TRA_ACK_NOT_REC 0x20 +#define TWSI_M_TRAN_DATA_BYTE_ACK_REC 0x28 +#define TWSI_M_TRAN_DATA_BYTE_ACK_NOT_REC 0x30 +#define TWSI_M_LOST_ARB_DUR_AD_OR_DATA_TRA 0x38 +#define TWSI_AD_PLS_RD_BIT_TRA_ACK_REC 0x40 +#define TWSI_AD_PLS_RD_BIT_TRA_ACK_NOT_REC 0x48 +#define TWSI_M_REC_RD_DATA_ACK_TRA 0x50 +#define TWSI_M_REC_RD_DATA_ACK_NOT_TRA 0x58 +#define TWSI_SLA_REC_AD_PLS_WR_BIT_ACK_TRA 0x60 +#define TWSI_M_LOST_ARB_DUR_AD_TRA_AD_IS_TRGT_TO_SLA_ACK_TRA_W 0x68 +#define TWSI_GNL_CALL_REC_ACK_TRA 0x70 +#define TWSI_M_LOST_ARB_DUR_AD_TRA_GNL_CALL_AD_REC_ACK_TRA 0x78 +#define TWSI_SLA_REC_WR_DATA_AF_REC_SLA_AD_ACK_TRAN 0x80 +#define TWSI_SLA_REC_WR_DATA_AF_REC_SLA_AD_ACK_NOT_TRAN 0x88 +#define TWSI_SLA_REC_WR_DATA_AF_REC_GNL_CALL_ACK_TRAN 0x90 +#define TWSI_SLA_REC_WR_DATA_AF_REC_GNL_CALL_ACK_NOT_TRAN 0x98 +#define TWSI_SLA_REC_STOP_OR_REPEATED_STRT_CON 0xA0 +#define TWSI_SLA_REC_AD_PLS_RD_BIT_ACK_TRA 0xA8 +#define TWSI_M_LOST_ARB_DUR_AD_TRA_AD_IS_TRGT_TO_SLA_ACK_TRA_R 0xB0 +#define TWSI_SLA_TRA_RD_DATA_ACK_REC 0xB8 +#define TWSI_SLA_TRA_RD_DATA_ACK_NOT_REC 0xC0 +#define TWSI_SLA_TRA_LAST_RD_DATA_ACK_REC 0xC8 +#define TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_REC 0xD0 +#define TWSI_SEC_AD_PLS_WR_BIT_TRA_ACK_NOT_REC 0xD8 +#define TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_REC 0xE0 +#define TWSI_SEC_AD_PLS_RD_BIT_TRA_ACK_NOT_REC 0xE8 +#define TWSI_NO_REL_STS_INT_FLAG_IS_KEPT_0 0xF8 + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvTwsiSpech */ diff --git a/board/mv_feroceon/mv_hal/uart/mvUart.c b/board/mv_feroceon/mv_hal/uart/mvUart.c new file mode 100644 index 0000000..7f4a949 --- /dev/null +++ b/board/mv_feroceon/mv_hal/uart/mvUart.c @@ -0,0 +1,184 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + + +#include "mvUart.h" + + +/* static variables */ +static volatile MV_UART_PORT* uartBase[MV_UART_MAX_CHAN]; + + +/******************************************************************************* +* mvUartInit - Init a uart port. +* +* DESCRIPTION: +* This routine Initialize one of the uarts ports (channels). +* It initialize the baudrate, stop bit,parity bit etc. +* +* INPUT: +* port - uart port number. +* baudDivisor - baud divisior to use for the uart port. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvUartInit(MV_U32 port, MV_U32 baudDivisor, MV_UART_PORT* base) +{ + volatile MV_UART_PORT *pUartPort; + +#if defined(MV_UART_OVER_PEX_WA) || defined(MV_UART_OVER_PCI_WA) + uartBase[port] = pUartPort = (volatile MV_UART_PORT *)(base); + return; +#else + uartBase[port] = pUartPort = (volatile MV_UART_PORT *)base; + + pUartPort->ier = 0x00; + pUartPort->lcr = LCR_DIVL_EN; /* Access baud rate */ + pUartPort->dll = baudDivisor & 0xff; /* 9600 baud */ + pUartPort->dlm = (baudDivisor >> 8) & 0xff; + pUartPort->lcr = LCR_8N1; /* 8 data, 1 stop, no parity */ + + /* Clear & enable FIFOs */ + pUartPort->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR; + return; +#endif +} + +/******************************************************************************* +* mvUartPutc - Send char to the uart port. +* +* DESCRIPTION: +* This routine puts one charachetr on one of the uart ports. +* +* INPUT: +* port - uart port number. +* c - character. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvUartPutc(MV_U32 port, MV_U8 c) +{ + volatile MV_UART_PORT *pUartPort = uartBase[port]; + while ((pUartPort->lsr & LSR_THRE) == 0) ; + pUartPort->thr = c; + return; +} + +/******************************************************************************* +* mvUartGetc - Get char from uart port. +* +* DESCRIPTION: +* This routine gets one charachetr from one of the uart ports. +* +* INPUT: +* port - uart port number. +* +* OUTPUT: +* None. +* +* RETURN: +* carachter from the uart port. +* +*******************************************************************************/ +MV_U8 mvUartGetc(MV_U32 port) +{ + volatile MV_UART_PORT *pUartPort = uartBase[port]; + while ((pUartPort->lsr & LSR_DR) == 0) ; + return (pUartPort->rbr); +} + +/******************************************************************************* +* mvUartTstc - test for char in uart port. +* +* DESCRIPTION: +* This routine heck if a charachter is ready to be read from one of the +* the uart ports. +* +* INPUT: +* port - uart port number. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_BOOL mvUartTstc(MV_U32 port) +{ + volatile MV_UART_PORT *pUartPort = uartBase[port]; + return ((pUartPort->lsr & LSR_DR) != 0); +} + diff --git a/board/mv_feroceon/mv_hal/uart/mvUart.h b/board/mv_feroceon/mv_hal/uart/mvUart.h new file mode 100644 index 0000000..c1dcda8 --- /dev/null +++ b/board/mv_feroceon/mv_hal/uart/mvUart.h @@ -0,0 +1,159 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __NS16550_H__ +#define __NS16550_H__ + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + +/* This structure describes the registers offsets for one UART port(channel) */ +typedef struct mvUartPort +{ + MV_U8 rbr; /* 0 = 0-3*/ + MV_U8 pad1[3]; + + MV_U8 ier; /* 1 = 4-7*/ + MV_U8 pad2[3]; + + MV_U8 fcr; /* 2 = 8-b*/ + MV_U8 pad3[3]; + + MV_U8 lcr; /* 3 = c-f*/ + MV_U8 pad4[3]; + + MV_U8 mcr; /* 4 = 10-13*/ + MV_U8 pad5[3]; + + MV_U8 lsr; /* 5 = 14-17*/ + MV_U8 pad6[3]; + + MV_U8 msr; /* 6 =18-1b*/ + MV_U8 pad7[3]; + + MV_U8 scr; /* 7 =1c-1f*/ + MV_U8 pad8[3]; +} MV_UART_PORT; + +#if defined(MV_UART_OVER_PEX_WA) || defined(MV_UART_OVER_PCI_WA) +#define mvUartBase(port) \ + ((MV_UART_PORT *)(0xF2000000 + MV_UART_CHAN_BASE(port))) +#else +#define mvUartBase(port) \ + ((MV_UART_PORT *)(INTER_REGS_BASE + MV_UART_CHAN_BASE(port))) +#endif + +/* aliases - for registers which has the same offsets */ +#define thr rbr +#define iir fcr +#define dll rbr +#define dlm ier + +/* registers feilds */ +#define FCR_FIFO_EN BIT0 /* fifo enable*/ +#define FCR_RXSR BIT1 /* reciever soft reset*/ +#define FCR_TXSR BIT2 /* transmitter soft reset*/ + +#define MCR_RTS BIT1 /* ready to send */ +#define MCR_AFCE BIT5 /* Auto Flow Control Enable */ + +#define LCR_WLS_OFFS 0 +#define LCR_WLS_MASK 0x3 << LCR_WLS_OFFS /* character length mask */ +#define LCR_WLS_5 0x0 << LCR_WLS_OFFS /* 5 bit character length */ +#define LCR_WLS_6 0x1 << LCR_WLS_OFFS /* 6 bit character length */ +#define LCR_WLS_7 0x2 << LCR_WLS_OFFS /* 7 bit character length */ +#define LCR_WLS_8 0x3 << LCR_WLS_OFFS /* 8 bit character length */ +#define LCR_STP_OFFS 2 +#define LCR_1_STB 0x0 << LCR_STP_OFFS /* Number of stop Bits */ +#define LCR_2_STB 0x1 << LCR_STP_OFFS /* Number of stop Bits */ +#define LCR_PEN 0x8 /* Parity eneble*/ +#define LCR_PS_OFFS 4 +#define LCR_EPS 0x1 << LCR_PS_OFFS /* Even Parity Select*/ +#define LCR_OPS 0x0 << LCR_PS_OFFS /* Odd Parity Select*/ +#define LCR_SBRK_OFFS 0x6 +#define LCR_SBRK 0x1 << LCR_SBRK_OFFS /* Set Break*/ +#define LCR_DIVL_OFFS 7 +#define LCR_DIVL_EN 0x1 << LCR_DIVL_OFFS /* Divisior latch enable*/ + +#define LSR_DR BIT0 /* Data ready */ +#define LSR_OE BIT1 /* Overrun */ +#define LSR_PE BIT2 /* Parity error */ +#define LSR_FE BIT3 /* Framing error */ +#define LSR_BI BIT4 /* Break */ +#define LSR_THRE BIT5 /* Xmit holding register empty */ +#define LSR_TEMT BIT6 /* Xmitter empty */ +#define LSR_ERR BIT7 /* Error */ + +/* useful defaults for LCR*/ +#define LCR_8N1 LCR_WLS_8 | LCR_1_STB + + +/* APIs */ +MV_VOID mvUartPutc(MV_U32 port, MV_U8 c); +MV_U8 mvUartGetc(MV_U32 port); +MV_BOOL mvUartTstc(MV_U32 port); +MV_VOID mvUartInit(MV_U32 port, MV_U32 baudDivisor, MV_UART_PORT* base); + +#endif diff --git a/board/mv_feroceon/mv_hal/uart/mvUartRegs.h b/board/mv_feroceon/mv_hal/uart/mvUartRegs.h new file mode 100644 index 0000000..0574410 --- /dev/null +++ b/board/mv_feroceon/mv_hal/uart/mvUartRegs.h @@ -0,0 +1,72 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvUartRegsH +#define __INCmvUartRegsH + +/* registers offsets */ + +#define UART_EXTERNAL_CONTROL_REG 0x10700 + +#endif /* #ifndef __INCmvUartRegsH */ diff --git a/board/mv_feroceon/mv_hal/usb/api/mvUsbCh9.h b/board/mv_feroceon/mv_hal/usb/api/mvUsbCh9.h new file mode 100644 index 0000000..e8b71b0 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/api/mvUsbCh9.h @@ -0,0 +1,124 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbCh9_h__ +#define __mvUsbCh9_h__ + +#include "mvUsbTypes.h" +/*----------------------------------------------------------------** +** Chapter 9.4 Standard Device Requests -- all devices ** +** See Table 9-3 p. 250 of USB 2.0 spec for combinations ** +** of request type bitfields with requests, WVALUE, WINDEX etc. ** +**----------------------------------------------------------------*/ +#define REQ_RECIP_MASK 0x1f +#define REQ_RECIP_DEVICE 0x00 +#define REQ_RECIP_INTERFACE 0x01 +#define REQ_RECIP_ENDPOINT 0x02 +#define REQ_RECIP_OTHER 0x03 + +/* Also for class requests set the following bit */ +#define REQ_TYPE_OFFSET 5 +#define REQ_TYPE_MASK (0x03 << REQ_TYPE_OFFSET) +#define REQ_TYPE_STANDARD (0x00 << REQ_TYPE_OFFSET) +#define REQ_TYPE_CLASS (0x01 << REQ_TYPE_OFFSET) +#define REQ_TYPE_VENDOR (0x02 << REQ_TYPE_OFFSET) +#define REQ_TYPE_RESERVED (0x03 << REQ_TYPE_OFFSET) + +/* Combine one of the 3 above with one of the following 2 */ +#define REQ_DIR_OFFSET 7 +#define REQ_DIR_IN (1 << REQ_DIR_OFFSET) +#define REQ_DIR_OUT (0 << REQ_DIR_OFFSET) + +/* Standard USB requests, see Chapter 9 */ +#define REQ_GET_STATUS 0 +#define REQ_CLEAR_FEATURE 1 +#define REQ_SET_FEATURE 3 +#define REQ_SET_ADDRESS 5 +#define REQ_GET_DESCRIPTOR 6 +#define REQ_SET_DESCRIPTOR 7 +#define REQ_GET_CONFIGURATION 8 +#define REQ_SET_CONFIGURATION 9 +#define REQ_GET_INTERFACE 10 +#define REQ_SET_INTERFACE 11 +#define REQ_SYNCH_FRAME 12 + +#define DESC_TYPE_DEVICE 0x1 +#define DESC_TYPE_CONFIG 0x2 +#define DESC_TYPE_STRING 0x3 +#define DESC_TYPE_INTERFACE 0x4 +#define DESC_TYPE_ENDPOINT 0x5 +#define DESC_TYPE_QUALIFIER 0x6 +#define DESC_TYPE_OTHER_SPEED 0x7 +#define DESC_TYPE_INTF_POWER 0x8 +#define DESC_TYPE_OTG 0x9 + +/******************************************************************* +** +** Values specific to CLEAR FEATURE commands (must go to common.h later) +*/ + +#define ENDPOINT_HALT 0 +#define DEVICE_SELF_POWERED 0 +#define DEVICE_REMOTE_WAKEUP 1 +#define DEVICE_TEST_MODE 2 + + +/* States of device instances on the device list */ + +/* initial device state */ +#define DEVSTATE_INITIAL 0x00 + +/* device descriptor [0..7]*/ +#define DEVSTATE_DEVDESC8 0x01 + +/* address set */ +#define DEVSTATE_ADDR_SET 0x02 + +/* full device descriptor */ +#define DEVSTATE_DEV_DESC 0x03 + +/* config descriptor [0..7] */ +#define DEVSTATE_GET_CFG9 0x04 + +/* config set */ +#define DEVSTATE_SET_CFG 0x05 + +/* full config desc. read in */ +#define DEVSTATE_CFG_READ 0x06 + +/* application callbacks */ +#define DEVSTATE_APP_CALL 0x07 + +/* Select interface done */ +#define DEVSTATE_SET_INTF 0x08 + +#define DEVSTATE_ENUM_OK 0x09 + +#define DEVSTATE_CHK_OTG 0x0A + +/* Event codes for attach/detach etc. callback */ +#define USB_ATTACH_EVENT 1 /* device attach */ +#define USB_DETACH_EVENT 2 /* device detach */ +#define USB_CONFIG_EVENT 3 /* device reconfigured */ +#define USB_INTF_EVENT 4 /* device interface selected */ + +#endif /* __mvUsbCh9_h__ */ + +/* EOF */ diff --git a/board/mv_feroceon/mv_hal/usb/api/mvUsbDebug.h b/board/mv_feroceon/mv_hal/usb/api/mvUsbDebug.h new file mode 100644 index 0000000..e663b45 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/api/mvUsbDebug.h @@ -0,0 +1,109 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbDebug_h__ +#define __mvUsbDebug_h__ + +#include "mvUsbTypes.h" + +#define MV_USB_RT_DEBUG + +/************************************************************ +The following array is used to make a run time trace route +inside the USB stack. +*************************************************************/ + +#define ARC_DEBUG_FLAG_ANY 0x00000000 + +#define ARC_DEBUG_FLAG_TRACE 0x00000001 +#define ARC_DEBUG_FLAG_CTRL 0x00000002 +#define ARC_DEBUG_FLAG_RX 0x00000004 +#define ARC_DEBUG_FLAG_TX 0x00000008 +#define ARC_DEBUG_FLAG_STALL 0x00000010 +#define ARC_DEBUG_FLAG_STATUS 0x00000020 +#define ARC_DEBUG_FLAG_TRANSFER 0x00000040 +#define ARC_DEBUG_FLAG_INIT 0x00000080 +#define ARC_DEBUG_FLAG_ISR 0x00000100 +#define ARC_DEBUG_FLAG_ERROR 0x00000200 +#define ARC_DEBUG_FLAG_ADDR 0x00000400 +#define ARC_DEBUG_FLAG_DUMP 0x00000800 +#define ARC_DEBUG_FLAG_SETUP 0x00001000 +#define ARC_DEBUG_FLAG_CLASS 0x00002000 +#define ARC_DEBUG_FLAG_SPEED 0x00004000 +#define ARC_DEBUG_FLAG_RESET 0x00008000 +#define ARC_DEBUG_FLAG_SUSPEND 0x00010000 +#define ARC_DEBUG_FLAG_RESUME 0x00020000 +#define ARC_DEBUG_FLAG_EP0 0x00040000 +#define ARC_DEBUG_FLAG_EP1 0x00080000 +#define ARC_DEBUG_FLAG_STATS 0x00100000 + + +#define ARC_DEBUG_FLAG_ALL 0xffffffff + +extern uint_32 usbDebugFlags; + +#ifdef MV_USB_RT_DEBUG +# define ARC_DEBUG_CODE(flags, code) \ + if( (usbDebugFlags & (flags)) == (flags) ) \ + code +#else +# define ARC_DEBUG_CODE(flags, code) +#endif + +#if defined(MV_USB_TRACE_LOG) + +#define TRACE_ARRAY_SIZE 400 +#define MAX_STRING_SIZE 132 + +extern uint_16 DEBUG_TRACE_ARRAY_COUNTER; +extern char DEBUG_TRACE_ARRAY[TRACE_ARRAY_SIZE][MAX_STRING_SIZE]; + +#define ARC_DEBUG_TRACE(flags, format, x...) \ +{ \ + if( (usbDebugFlags & (flags)) == (flags)) \ + { \ + USB_sprintf(DEBUG_TRACE_ARRAY[DEBUG_TRACE_ARRAY_COUNTER], format, ##x); \ + DEBUG_TRACE_ARRAY_COUNTER++; \ + if(DEBUG_TRACE_ARRAY_COUNTER >= TRACE_ARRAY_SIZE) \ + {DEBUG_TRACE_ARRAY_COUNTER = 0;} \ + } \ +} + +#elif defined(MV_USB_TRACE_PRINT) + +# define ARC_DEBUG_TRACE(flags, format, x...) \ + if((usbDebugFlags & (flags)) == (flags)) \ + USB_printf(format, ##x) + +/*if trace switch is not enabled define debug log trace to empty*/ +#else +# define ARC_DEBUG_TRACE(flags, fromat, x...) +#endif + + +/************************************************************ +The following are global data structures that can be used +to copy data from stack on run time. This structure can +be analyzed at run time to see the state of various other +data structures in the memory. +*************************************************************/ + +#endif /* __mvUsbDebug_h__ */ +/* EOF */ diff --git a/board/mv_feroceon/mv_hal/usb/api/mvUsbDefs.h b/board/mv_feroceon/mv_hal/usb/api/mvUsbDefs.h new file mode 100644 index 0000000..66e2812 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/api/mvUsbDefs.h @@ -0,0 +1,139 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbDefs_h__ +#define __mvUsbDefs_h__ + +#include "mvUsbTypes.h" + +/* Host specific */ +#define USB_DEBOUNCE_DELAY (101) +#define USB_RESET_RECOVERY_DELAY (11) +#define USB_RESET_DELAY (60) + +/* Error codes */ +#define USB_OK (0x00) +#define USBERR_ALLOC (0x81) +#define USBERR_BAD_STATUS (0x82) +#define USBERR_CLOSED_SERVICE (0x83) +#define USBERR_OPEN_SERVICE (0x84) +#define USBERR_TRANSFER_IN_PROGRESS (0x85) +#define USBERR_ENDPOINT_STALLED (0x86) +#define USBERR_ALLOC_STATE (0x87) +#define USBERR_DRIVER_INSTALL_FAILED (0x88) +#define USBERR_DRIVER_NOT_INSTALLED (0x89) +#define USBERR_INSTALL_ISR (0x8A) +#define USBERR_INVALID_DEVICE_NUM (0x8B) +#define USBERR_ALLOC_SERVICE (0x8C) +#define USBERR_INIT_FAILED (0x8D) +#define USBERR_SHUTDOWN (0x8E) +#define USBERR_INVALID_PIPE_HANDLE (0x8F) +#define USBERR_OPEN_PIPE_FAILED (0x90) +#define USBERR_INIT_DATA (0x91) +#define USBERR_SRP_REQ_INVALID_STATE (0x92) +#define USBERR_TX_FAILED (0x93) +#define USBERR_RX_FAILED (0x94) +#define USBERR_EP_INIT_FAILED (0x95) +#define USBERR_EP_DEINIT_FAILED (0x96) +#define USBERR_TR_FAILED (0x97) +#define USBERR_BANDWIDTH_ALLOC_FAILED (0x98) +#define USBERR_INVALID_NUM_OF_ENDPOINTS (0x99) + +#define USBERR_DEVICE_NOT_FOUND (0xC0) +#define USBERR_DEVICE_BUSY (0xC1) +#define USBERR_NO_DEVICE_CLASS (0xC3) +#define USBERR_UNKNOWN_ERROR (0xC4) +#define USBERR_INVALID_BMREQ_TYPE (0xC5) +#define USBERR_GET_MEMORY_FAILED (0xC6) +#define USBERR_INVALID_MEM_TYPE (0xC7) +#define USBERR_NO_DESCRIPTOR (0xC8) +#define USBERR_NULL_CALLBACK (0xC9) +#define USBERR_NO_INTERFACE (0xCA) +#define USBERR_INVALID_CFIG_NUM (0xCB) +#define USBERR_INVALID_ANCHOR (0xCC) +#define USBERR_INVALID_REQ_TYPE (0xCD) + +/* Error Codes for lower-layer */ +#define USBERR_ALLOC_EP_QUEUE_HEAD (0xA8) +#define USBERR_ALLOC_TR (0xA9) +#define USBERR_ALLOC_DTD_BASE (0xAA) +#define USBERR_CLASS_DRIVER_INSTALL (0xAB) + + +/* Pipe Types */ +#define USB_ISOCHRONOUS_PIPE (0x01) +#define USB_INTERRUPT_PIPE (0x02) +#define USB_CONTROL_PIPE (0x03) +#define USB_BULK_PIPE (0x04) + +#define ARC_USB_STATE_UNKNOWN (0xff) +#define ARC_USB_STATE_POWERED (0x03) +#define ARC_USB_STATE_DEFAULT (0x02) +#define ARC_USB_STATE_ADDRESS (0x01) +#define ARC_USB_STATE_CONFIG (0x00) +#define ARC_USB_STATE_SUSPEND (0x80) + +#define ARC_USB_SELF_POWERED (0x01) +#define ARC_USB_REMOTE_WAKEUP (0x02) + +/* Bus Control values */ +#define ARC_USB_NO_OPERATION (0x00) +#define ARC_USB_ASSERT_BUS_RESET (0x01) +#define ARC_USB_DEASSERT_BUS_RESET (0x02) +#define ARC_USB_ASSERT_RESUME (0x03) +#define ARC_USB_DEASSERT_RESUME (0x04) +#define ARC_USB_SUSPEND_SOF (0x05) +#define ARC_USB_RESUME_SOF (0x06) + +/* possible values of XD->bStatus */ +#define ARC_USB_STATUS_IDLE (0) +#define ARC_USB_STATUS_TRANSFER_ACCEPTED (1) +#define ARC_USB_STATUS_TRANSFER_PENDING (2) +#define ARC_USB_STATUS_TRANSFER_IN_PROGRESS (3) +#define ARC_USB_STATUS_ERROR (4) +#define ARC_USB_STATUS_DISABLED (5) +#define ARC_USB_STATUS_STALLED (6) +#define ARC_USB_STATUS_TRANSFER_QUEUED (7) + +#define ARC_USB_RECV (0) +#define ARC_USB_SEND (1) + +#define ARC_USB_DEVICE_DONT_ZERO_TERMINATE (0x1) + +#define ARC_USB_SETUP_DATA_XFER_DIRECTION (0x80) + +#define ARC_USB_SPEED_FULL (0) +#define ARC_USB_SPEED_LOW (1) +#define ARC_USB_SPEED_HIGH (2) + +#define ARC_USB_MAX_PKTS_PER_UFRAME (0x6) + +/* USB 1.1 Setup Packet */ +typedef struct setup_struct { + uint_8 REQUESTTYPE; + uint_8 REQUEST; + uint_16 VALUE; + uint_16 INDEX; + uint_16 LENGTH; +} SETUP_STRUCT, _PTR_ SETUP_STRUCT_PTR; + +#endif /* __mvUsbDefs_h__ */ + +/* EOF */ diff --git a/board/mv_feroceon/mv_hal/usb/api/mvUsbDevApi.h b/board/mv_feroceon/mv_hal/usb/api/mvUsbDevApi.h new file mode 100644 index 0000000..0d06b68 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/api/mvUsbDevApi.h @@ -0,0 +1,159 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbDevApi_h__ +#define __mvUsbDevApi_h__ + +#include "mvUsbTypes.h" +#include "mvUsbDebug.h" +#include "mvUsbDefs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + + +#define ARC_USB_MAX_ENDPOINTS (16) + +#define MAX_EP_TR_DESCRS (48) +#define MAX_XDS_FOR_TR_CALLS (32) +#define MAX_USB_DEVICES MV_USB_MAX_CHAN + +/*Assumption here is that all control endpoints are sequential 0,1,.. +if they are not you need to modify the tr_complete routine to handle that */ +#define USB_MAX_CONTROL_ENDPOINTS (1) + +#define USB_MAX_CTRL_PAYLOAD (64) + + +/* Endpoint types */ +#define ARC_USB_CONTROL_ENDPOINT (0) +#define ARC_USB_ISOCHRONOUS_ENDPOINT (1) +#define ARC_USB_BULK_ENDPOINT (2) +#define ARC_USB_INTERRUPT_ENDPOINT (3) + +/* Informational Request/Set Types */ +#define ARC_USB_STATUS_DEVICE_STATE (0x01) +#define ARC_USB_STATUS_INTERFACE (0x02) +#define ARC_USB_STATUS_ADDRESS (0x03) +#define ARC_USB_STATUS_CURRENT_CONFIG (0x04) +#define ARC_USB_STATUS_SOF_COUNT (0x05) +#define ARC_USB_STATUS_DEVICE (0x06) +#define ARC_USB_STATUS_TEST_MODE (0x07) +#define ARC_USB_FORCE_FULL_SPEED (0x08) +#define ARC_USB_PHY_LOW_POWER_SUSPEND (0x09) + +#define ARC_USB_STATUS_ENDPOINT_NUMBER_MASK (0x000F) +#define ARC_USB_STATUS_ENDPOINT_DIR_MASK (0x0080) + +#define ARC_USB_TEST_MODE_TEST_PACKET (0x0400) + +/* Available service types */ +/* Services 0 through 15 are reserved for endpoints */ +#define ARC_USB_SERVICE_EP0 (0x00) +#define ARC_USB_SERVICE_EP1 (0x01) +#define ARC_USB_SERVICE_EP2 (0x02) +#define ARC_USB_SERVICE_EP3 (0x03) +#define ARC_USB_SERVICE_BUS_RESET (0x10) +#define ARC_USB_SERVICE_SUSPEND (0x11) +#define ARC_USB_SERVICE_SOF (0x12) +#define ARC_USB_SERVICE_RESUME (0x13) +#define ARC_USB_SERVICE_SLEEP (0x14) +#define ARC_USB_SERVICE_SPEED_DETECTION (0x15) +#define ARC_USB_SERVICE_ERROR (0x16) +#define ARC_USB_SERVICE_STALL (0x17) + +typedef pointer _usb_device_handle; +typedef void (*USB_SERVICE_FUNC)(void* handle, uint_8, boolean, uint_8, + uint_8_ptr, uint_32, uint_8); + +#ifdef __cplusplus +extern "C" { +#endif + +void _usb_dci_vusb20_isr(void* handle); + +void _usb_device_set_bsp_funcs(USB_IMPORT_FUNCS* pBspFuncs); + +uint_8 _usb_device_init(uint_8 devNo, void** pHandle); + +uint_8 _usb_device_get_max_endpoint(void* handle); + +uint_8 _usb_device_get_dev_num(void* handle); + +void _usb_device_shutdown(void* handle); + +void _usb_device_stop(void* handle); +void _usb_device_start(void* handle); + +uint_8 _usb_device_init_endpoint(void* handle, uint_8 ep_num, uint_16 max_pkt_size, + uint_8 direction, uint_8 type, uint_8 flag); +uint_8 _usb_device_deinit_endpoint(void* handle, uint_8 ep_num, uint_8 direction); + +uint_8 _usb_device_recv_data(void* handle, uint_8 ep_num, uint_8* buf_ptr, uint_32 size); +uint_8 _usb_device_send_data(void* handle, uint_8 ep_num, uint_8* buf_ptr, uint_32 size); +uint_8 _usb_device_cancel_transfer(void* handle, uint_8 ep_num, uint_8 direction); +uint_8 _usb_device_get_transfer_status(void* handle, uint_8 ep_num, uint_8 direction); +void _usb_device_stall_endpoint(void* handle, uint_8 ep_num, uint_8 direction); +void _usb_device_unstall_endpoint(void* handle, uint_8 ep_num, uint_8 direction); +uint_8 _usb_device_is_endpoint_stalled(void* handle, uint_8 ep_num, uint_8 direction); +void _usb_device_assert_resume(void* handle); +uint_8 _usb_device_get_status(void* handle, uint_8 component, uint_16* status_ptr); +uint_8 _usb_device_set_status(void* handle, uint_8 component, uint_16 setting); +void _usb_device_read_setup_data(void* handle, uint_8 ep_num, uint_8* buf_ptr); + +uint_8 _usb_device_register_service(void* handle, uint_8 type, USB_SERVICE_FUNC serviceFunc); + +uint_8 _usb_device_unregister_service(void* handle, uint_8 type); + + + +/* These functions that implement USB 2.0 standard Chapter 9 Setup requests */ +void mvUsbCh9GetStatus(void* handle, boolean setup, + SETUP_STRUCT* ctrl_req); + +void mvUsbCh9ClearFeature(void* handle, boolean setup, + SETUP_STRUCT* setup_ptr); + +void mvUsbCh9SetFeature(void* handle, boolean setup, + SETUP_STRUCT* setup_ptr); + +void mvUsbCh9SetAddress(void* handle, boolean setup, + SETUP_STRUCT* setup_ptr); + +/* DEBUG Functions */ +void _usb_dci_vusb20_set_test_mode(void* handle, uint_16 testMode); + +void _usb_debug_set_flags(uint_32 flags); +uint_32 _usb_debug_get_flags(void); + +void _usb_debug_init_trace_log(void); +void _usb_debug_print_trace_log(void); + +void _usb_regs(void* usbHandle); +void _usb_status(void* usbHandle); +void _usb_stats(void* usbHandle); +void _usb_clear_stats(void* usbHandle); +void _usb_ep_status(void* usbHandle, int ep_num, int direction); + +#ifdef __cplusplus +} +#endif + +#endif /* __mvUsbDevApi_h__ */ +/* EOF */ + diff --git a/board/mv_feroceon/mv_hal/usb/api/mvUsbTypes.h b/board/mv_feroceon/mv_hal/usb/api/mvUsbTypes.h new file mode 100644 index 0000000..e99a94d --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/api/mvUsbTypes.h @@ -0,0 +1,238 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbTypes_h__ +#define __mvUsbTypes_h__ + +#define _PTR_ * +#define _CODE_PTR_ * + +typedef char _PTR_ char_ptr; /* signed character */ + +typedef signed char int_8, _PTR_ int_8_ptr; /* 8-bit signed integer */ +typedef unsigned char uint_8, _PTR_ uint_8_ptr; /* 8-bit signed integer */ + +typedef short int_16, _PTR_ int_16_ptr; /* 16-bit signed integer */ +typedef unsigned short uint_16, _PTR_ uint_16_ptr; /* 16-bit unsigned integer*/ + +typedef int int_32, _PTR_ int_32_ptr; /* 32-bit signed integer */ +typedef unsigned int uint_32, _PTR_ uint_32_ptr; /* 32-bit unsigned integer*/ + +typedef unsigned long boolean; /* Machine representation of a boolean */ + +typedef void _PTR_ pointer; /* Machine representation of a pointer */ + +/*--------------------------------------------------------------------------*/ +/* +** STANDARD CONSTANTS +** +** Note that if standard 'C' library files are included after types.h, +** the defines of TRUE, FALSE and NULL may sometimes conflict, as most +** standard library files do not check for previous definitions. +*/ + +#ifndef FALSE +# define FALSE ((boolean)0) +#endif + +#ifndef TRUE +# define TRUE ((boolean)!FALSE) +#endif + +#ifndef NULL +# ifdef __cplusplus +# define NULL (0) +# else +# define NULL ((pointer)0) +# endif +#endif + +#ifndef _ASSERT_ + #define ASSERT(X,Y) +#else + #define ASSERT(X,Y) if(Y) { USB_printf(X); exit(1);} +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define USB_MEM_ALIGN(n, align) ((n) + (-(n) & (align-1))) + +/* Macro for aligning the EP queue head to 32 byte boundary */ +#define USB_MEM32_ALIGN(n) USB_MEM_ALIGN(n, 32) + +/* Macro for aligning the EP queue head to 1024 byte boundary */ +#define USB_MEM1024_ALIGN(n) USB_MEM_ALIGN(n, 1024) + +/* Macro for aligning the EP queue head to 1024 byte boundary */ +#define USB_MEM2048_ALIGN(n) USB_MEM_ALIGN(n, 2048) + +#define PSP_CACHE_LINE_SIZE 32 + +#define USB_uint_16_low(x) ((x) & 0xFF) +#define USB_uint_16_high(x) (((x) >> 8) & 0xFF) + +#define USB_CACHE_ALIGN(n) USB_MEM_ALIGN(n, PSP_CACHE_LINE_SIZE) + +#ifndef INLINE +# if defined(MV_VXWORKS) +# define INLINE __inline +# else +# define INLINE inline +# endif /* MV_VXWORKS */ +#endif /* INLINE */ + +/* 16bit byte swap. For example 0x1122 -> 0x2211 */ +static INLINE uint_16 USB_BYTE_SWAP_16BIT(uint_16 value) +{ + return ( ((value & 0x00ff) << 8) | + ((value & 0xff00) >> 8) ); +} + +/* 32bit byte swap. For example 0x11223344 -> 0x44332211 */ +static INLINE uint_32 USB_BYTE_SWAP_32BIT(uint_32 value) +{ + return ( ((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + ((value & 0xff000000) >> 24)); +} + + +/* Endianess macros. */ +#if defined(MV_CPU_LE) +# define USB_16BIT_LE(X) (X) +# define USB_32BIT_LE(X) (X) +# define USB_16BIT_BE(X) USB_BYTE_SWAP_16BIT(X) +# define USB_32BIT_BE(X) USB_BYTE_SWAP_32BIT(X) +#elif defined(MV_CPU_BE) +# define USB_16BIT_LE(X) USB_BYTE_SWAP_16BIT(X) +# define USB_32BIT_LE(X) USB_BYTE_SWAP_32BIT(X) +# define USB_16BIT_BE(X) (X) +# define USB_32BIT_BE(X) (X) +#else + #error "CPU endianess isn't defined!\n" +#endif + +typedef struct +{ + void (*bspPrintf) (const char * fmt, ...); + int (*bspSprintf) (char* buffer, const char * fmt, ...); + void* (*bspUncachedMalloc) (void* pDev, uint_32 size, uint_32 align, + unsigned long* pPhyAddr); + void (*bspUncachedFree) (void* pDev, uint_32 size, unsigned long phyAddr, + void* pVirtAddr); + void* (*bspMalloc) (unsigned int size); + void (*bspFree) (void* ptr); + void* (*bspMemset) (void* ptr, int val, unsigned int size); + void* (*bspMemcpy) (void* dst, const void* src, unsigned int size); + unsigned long (*bspCacheFlush) (void* pDev, void* pVirtAddr, int size); + unsigned long (*bspCacheInv) (void* pDev, void* pVirtAddr, int size); + unsigned long (*bspVirtToPhys) (void* pDev, void* pVirtAddr); + int (*bspLock) (void); + void (*bspUnlock) (int lockKey); + uint_32 (*bspGetCapRegAddr) (int devNo); + void (*bspResetComplete) (int devNo); + +} USB_IMPORT_FUNCS; + +extern USB_IMPORT_FUNCS* global_import_funcs; + +#define USB_sprintf(frmt, x...) if( (global_import_funcs != NULL) && \ + global_import_funcs->bspSprintf != NULL) \ + global_import_funcs->bspSprintf(frmt, ##x) + +#define USB_printf(frmt, x...) if( (global_import_funcs != NULL) && \ + (global_import_funcs->bspPrintf != NULL) ) \ + global_import_funcs->bspPrintf(frmt, ##x) + + +#define USB_virt_to_phys(pVirt) (global_import_funcs->bspVirtToPhys == NULL) ? \ + (uint_32)(pVirt) : global_import_funcs->bspVirtToPhys(NULL, pVirt) + +#define USB_get_cap_reg_addr(dev) global_import_funcs->bspGetCapRegAddr(dev) + +static INLINE void* USB_uncached_memalloc(uint_32 size, uint_32 align, unsigned long* pPhyAddr) +{ + /*USB_printf("**** USB_uncached_memalloc: size=%d\n", (size)); */ + return global_import_funcs->bspUncachedMalloc(NULL, size, align, pPhyAddr); +} + +static INLINE void* USB_memalloc(uint_32 size) +{ + /*USB_printf("**** USB_memalloc: size=%d\n", (size)); */ + return global_import_funcs->bspMalloc(size); +} + +#define USB_uncached_memfree(pVirt, size, physAddr) \ + /*USB_printf("#### USB_uncached_memfree: pVirt=0x%x\n", (pVirt)); */\ + global_import_funcs->bspUncachedFree(NULL, size, physAddr, pVirt); + +#define USB_memfree(ptr) \ + /*USB_printf("#### USB_memfree: ptr=0x%x\n", (ptr));*/ \ + global_import_funcs->bspFree(ptr); + +#define USB_memzero(ptr, n) global_import_funcs->bspMemset(ptr, 0, n) +#define USB_memcopy(src, dst, n) global_import_funcs->bspMemcpy(dst, src, n) + +#define USB_dcache_inv(ptr, size) if(global_import_funcs->bspCacheInv != NULL) \ + global_import_funcs->bspCacheInv(NULL, ptr, size) + +#define USB_dcache_flush(ptr, size) if(global_import_funcs->bspCacheFlush != NULL) \ + global_import_funcs->bspCacheFlush(NULL, ptr, size) + +#define USB_lock() (global_import_funcs->bspLock == NULL) ? \ + 0 : global_import_funcs->bspLock() + +#define USB_unlock(key) if(global_import_funcs->bspUnlock != NULL) \ + global_import_funcs->bspUnlock(key) + +#define USB_reset_complete(dev) if(global_import_funcs->bspResetComplete) \ + global_import_funcs->bspResetComplete(dev) + + +#if defined(USB_UNDERRUN_WA) + +#define USB_SRAM_MAX_PARTS 16 + +typedef struct +{ + uint_32 (*bspGetSramAddr) (uint_32* pSize); + void (*bspIdmaCopy) (void* dst, void* src, unsigned int size); + +} USB_WA_FUNCS; + +extern USB_WA_FUNCS* global_wa_funcs; +extern int global_wa_sram_parts; +extern int global_wa_threshold; + +#define USB_get_sram_addr(pSize) global_wa_funcs->bspGetSramAddr(pSize) + +#define USB_idma_copy(dst, src, size) \ + if(global_wa_funcs->bspIdmaCopy != NULL) \ + global_wa_funcs->bspIdmaCopy(dst, src, size) + +#endif /* USB_UNDERRUN_WA */ + +#endif /* __mvUsbTypes_h__ */ + +/* EOF */ + diff --git a/board/mv_feroceon/mv_hal/usb/common/mvUsbCore.h b/board/mv_feroceon/mv_hal/usb/common/mvUsbCore.h new file mode 100644 index 0000000..16ef053 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/common/mvUsbCore.h @@ -0,0 +1,720 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbCore_h__ +#define __mvUsbCore_h__ + +#include "mvUsbTypes.h" + +/* VUSBHS specific defines */ +#define VUSBHS_MAX_PORTS (8) +#define EHCI_CAP_LEN_MASK (0x000000FF) +#define EHCI_DATA_STRUCTURE_BASE_ADDRESS (0) + +/* Command Register Bit Masks */ +#define EHCI_CMD_RUN_STOP (0x00000001) +#define EHCI_CMD_CTRL_RESET (0x00000002) +#define EHCI_CMD_SETUP_TRIPWIRE_SET (0x00002000) +#define EHCI_CMD_SETUP_TRIPWIRE_CLEAR ~EHCI_CMD_SETUP_TRIPWIRE_SET + +#define EHCI_CMD_ATDTW_TRIPWIRE_SET (0x00004000) +#define EHCI_CMD_ATDTW_TRIPWIRE_CLEAR ~EHCI_CMD_ATDTW_TRIPWIRE_SET + +/*bit 15,3,2 are for frame list size */ +#define EHCI_CMD_FRAME_SIZE_1024 (0x00000000) /* 000 */ +#define EHCI_CMD_FRAME_SIZE_512 (0x00000004) /* 001 */ +#define EHCI_CMD_FRAME_SIZE_256 (0x00000008) /* 010 */ +#define EHCI_CMD_FRAME_SIZE_128 (0x0000000C) /* 011 */ +#define EHCI_CMD_FRAME_SIZE_64 (0x00008000) /* 100 */ +#define EHCI_CMD_FRAME_SIZE_32 (0x00008004) /* 101 */ +#define EHCI_CMD_FRAME_SIZE_16 (0x00008008) /* 110 */ +#define EHCI_CMD_FRAME_SIZE_8 (0x0000800C) /* 111 */ + +/* Hardware Rev 4.0 related change */ +/* Mode Register Bit Masks */ +#define VUSBHS_MODE_CTRL_MODE_IDLE (0x00000000) +#define VUSBHS_MODE_CTRL_MODE_DEV (0x00000002) +#define VUSBHS_MODE_CTRL_MODE_HOST (0x00000003) +#define VUSBHS_MODE_BIG_ENDIAN (0x00000004) +#define VUSBHS_MODE_SETUP_LOCK_DISABLE (0x00000008) +#define VUSBHS_MODE_STREAM_DISABLE (0x00000010) + +/* Interrupt Enable Register Bit Masks */ +#define EHCI_INTR_INT_EN (0x00000001) +#define EHCI_INTR_ERR_INT_EN (0x00000002) +#define EHCI_INTR_PORT_CHANGE_DETECT_EN (0x00000004) + +#define EHCI_INTR_ASYNC_ADV_AAE (0x00000020) +#define EHCI_INTR_ASYNC_ADV_AAE_ENABLE (0x00000020) /* | with this to enable */ +#define EHCI_INTR_ASYNC_ADV_AAE_DISABLE (0xFFFFFFDF) /* & with this to disable */ + +#define EHCI_INTR_RESET_EN (0x00000040) +#define EHCI_INTR_SOF_UFRAME_EN (0x00000080) +#define EHCI_INTR_DEVICE_SUSPEND (0x00000100) + +/* Interrupt Status Register Masks */ +#define EHCI_STS_SOF (0x00000080) +#define EHCI_STS_RESET (0x00000040) +#define EHCI_STS_PORT_CHANGE (0x00000004) +#define EHCI_STS_ERR (0x00000002) +#define EHCI_STS_INT (0x00000001) +#define EHCI_STS_SUSPEND (0x00000100) +#define EHCI_STS_HC_HALTED (0x00001000) + +/* Endpoint Queue Head Bit Masks */ +#define VUSB_EP_QUEUE_HEAD_IOS (0x00008000) +#define VUSB_EP_QUEUE_HEAD_IOC (0x00008000) +#define VUSB_EP_QUEUE_HEAD_INT (0x00000100) +#define VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE (0x00000001) +#define VUSB_EP_QUEUE_HEAD_MAX_PKT_LEN_POS (16) +#define VUSB_EP_QUEUE_HEAD_ZERO_LEN_TER_SEL (0x20000000) +#define VUSB_EP_QUEUE_HEAD_MULT_POS (30) +#define VUSB_EP_MAX_LENGTH_TRANSFER (0x4000) + +#define VUSB_EP_QUEUE_HEAD_STATUS_ACTIVE (0x00000080) + +#define VUSBHS_TD_NEXT_TERMINATE (0x00000001) +#define VUSBHS_TD_IOC (0x00008000) +#define VUSBHS_TD_STATUS_ACTIVE (0x00000080) +#define VUSBHS_TD_STATUS_HALTED (0x00000040) +#define VUSBHS_TD_RESERVED_FIELDS (0x00007F00) +#define VUSBHS_TD_ERROR_MASK (0x68) +#define VUSBHS_TD_ADDR_MASK (0xFFFFFFE0) +#define VUSBHS_TD_LENGTH_BIT_POS (16) + +#define EHCI_EPCTRL_TX_ALL_MASK (0xFFFF0000) +#define EHCI_EPCTRL_RX_ALL_MASK (0x0000FFFF) + +#define EHCI_EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) +#define EHCI_EPCTRL_TX_EP_STALL (0x00010000) +#define EHCI_EPCTRL_RX_EP_STALL (0x00000001) +#define EHCI_EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) +#define EHCI_EPCTRL_RX_ENABLE (0x00000080) +#define EHCI_EPCTRL_TX_ENABLE (0x00800000) +#define EHCI_EPCTRL_CONTROL (0x00000000) +#define EHCI_EPCTRL_ISOCHRONOUS (0x00040000) +#define EHCI_EPCTRL_BULK (0x00080000) +#define EHCI_EPCTRL_INT (0x000C0000) +#define EHCI_EPCTRL_TX_TYPE (0x000C0000) +#define EHCI_EPCTRL_RX_TYPE (0x0000000C) +#define EHCI_EPCTRL_DATA_TOGGLE_INHIBIT (0x00000020) +#define EHCI_EPCTRL_TX_EP_TYPE_SHIFT (18) +#define EHCI_EPCTRL_RX_EP_TYPE_SHIFT (2) + +/* set bit 24 (PFSC) in PORTSCX register */ +#define EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT (0x01000000) +/* set bit 23 (PHCD) in PORTSCX register */ +#define EHCI_PORTSCX_PHY_CLOCK_DISABLE (0x00800000) + +#define EHCI_PORTSCX_PORT_POWER (0x00001000) +#define EHCI_PORTSCX_LINE_STATUS_BITS (0x00000C00) +#define EHCI_PORTSCX_LINE_STATUS_SE0 (0x00000000) +#define EHCI_PORTSCX_LINE_STATUS_KSTATE (0x00000400) +#define EHCI_PORTSCX_LINE_STATUS_JSTATE (0x00000800) +#define EHCI_PORTSCX_PORT_HIGH_SPEED (0x00000200) +#define EHCI_PORTSCX_PORT_RESET (0x00000100) +#define EHCI_PORTSCX_PORT_SUSPEND (0x00000080) +#define EHCI_PORTSCX_PORT_FORCE_RESUME (0x00000040) +#define EHCI_PORTSCX_PORT_EN_DIS_CHANGE (0x00000008) +#define EHCI_PORTSCX_PORT_ENABLE (0x00000004) +#define EHCI_PORTSCX_CONNECT_STATUS_CHANGE (0x00000002) +#define EHCI_PORTSCX_CURRENT_CONNECT_STATUS (0x00000001) + +#define VUSBHS_PORTSCX_PORT_SPEED_FULL (0x00000000) +#define VUSBHS_PORTSCX_PORT_SPEED_LOW (0x04000000) +#define VUSBHS_PORTSCX_PORT_SPEED_HIGH (0x08000000) +#define VUSBHS_SPEED_MASK (0x0C000000) +#define VUSBHS_SPEED_BIT_POS (26) + +#define EHCI_PORTSCX_W1C_BITS (0x2A) +#define VUSB_EP_QH_PACKET_SIZE (0x3FFF0000) +#define VUSB_EP_TR_PACKET_SIZE (0x7FFF0000) + +#define VUSBHS_FRINDEX_MS_MASK (0xFFFFFFF8) +#define VUSBHS_ADDRESS_BIT_SHIFT (25) + +#define VUSB20_DCC_MAX_ENDPTS_SUPPORTED (0x1F) +#define VUSB20_DCC_HOST_MODE_MASK (1 << 8) +#define VUSB20_DCC_DEVICE_MODE_MASK (1 << 7) + +#define EHCI_HCC_PARAMS_64_BIT_ADDR_CAP (0x01) +#define EHCI_HCC_PARAMS_PGM_FRM_LIST_FLAG (0x02) +#define EHCI_HCC_PARAMS_ASYNC_PARK_CAP (0x04) +#define EHCI_HCC_PARAMS_ISOCH_SCHED_THRESHOLD (0xF0) +#define EHCI_HCC_PARAMS_ISOCH_FRAME_CACHED (0x80) + +#define VUSB20_HCS_PARAMS_PORT_POWER_CONTROL_FLAG (0x10) + +#define VUSB20_HOST_INTR_EN_BITS (0x37) + +#define VUSB20_DEFAULT_PERIODIC_FRAME_LIST_SIZE (1024) +#define VUSB20_NEW_PERIODIC_FRAME_LIST_BITS (2) +#define EHCI_FRAME_LIST_ELEMENT_POINTER_T_BIT (0x01) +#define EHCI_ITD_T_BIT (0x01) +#define EHCI_SITD_T_BIT (0x01) +#define EHCI_QUEUE_HEAD_POINTER_T_BIT (0x01) + + +/************************************************************ +Split transatcions specific defines +************************************************************/ +#define EHCI_START_SPLIT_MAX_BUDGET 188 + +#define EHCI_ELEMENT_TYPE_ITD (0x00) +#define EHCI_ELEMENT_TYPE_QH (0x02) +#define EHCI_ELEMENT_TYPE_SITD (0x04) +#define EHCI_ELEMENT_TYPE_FSTN (0x06) +#define EHCI_ELEMENT_TYPE_MASK (0x06) + +#define EHCI_FRAME_LIST_ELEMENT_TYPE_ITD (0x00) +#define EHCI_FRAME_LIST_ELEMENT_TYPE_QH (0x01) +#define EHCI_FRAME_LIST_ELEMENT_TYPE_SITD (0x02) +#define EHCI_FRAME_LIST_ELEMENT_TYPE_FSTN (0x03) +#define EHCI_FRAME_LIST_ELEMENT_TYPE_BIT_POS (1) + + +#define EHCI_QH_ELEMENT_TYPE_ITD (0x00) +#define EHCI_QH_ELEMENT_TYPE_QH (0x01) +#define EHCI_QH_ELEMENT_TYPE_SITD (0x02) +#define EHCI_QH_ELEMENT_TYPE_FSTN (0x03) + +#define EHCI_QH_ELEMENT_TYPE_BIT_POS (1) + +#define EHCI_QTD_PID_OUT_TOKEN (0x000) +#define EHCI_QTD_PID_IN_TOKEN (0x100) +#define EHCI_QTD_PID_SETUP_TOKEN (0x200) +#define EHCI_QTD_IOC (0x8000) +#define EHCI_QTD_STATUS_ACTIVE (0x0080) +#define EHCI_QTD_STATUS_HALTED (0x0040) +#define EHCI_QTD_PID_SETUP (0x0200) +#define EHCI_QTD_PID_IN (0x0100) +#define EHCI_QTD_PID_OUT (0x0000) +#define EHCI_QTD_LENGTH_BIT_POS (16) +#define EHCI_QTD_DATA_TOGGLE (0x80000000) +#define EHCI_QTD_DATA_TOGGLE_BIT_POS (31) +#define EHCI_QTD_LENGTH_BIT_MASK (0x7FFF0000) +#define EHCI_QTD_ERROR_BITS_MASK (0x0000003E) +#define EHCI_QTD_DEFAULT_CERR_VALUE (0xC00) + +#define EHCI_SETUP_TOKEN (2) +#define EHCI_OUT_TOKEN (0) +#define EHCI_IN_TOKEN (1) + +#define EHCI_QTD_T_BIT (0x01) + +#define EHCI_QH_ENDPOINT_SPEED_FULL (0x00) +#define EHCI_QH_ENDPOINT_SPEED_LOW (0x01) +#define EHCI_QH_ENDPOINT_SPEED_HIGH (0x02) +#define EHCI_QH_ENDPOINT_SPEED_RESERVED (0x03) + +#define EHCI_ITD_LENGTH_BIT_POS (16) +#define EHCI_ITD_IOC_BIT (0x00008000) +#define EHCI_ITD_ACTIVE_BIT (0x80000000) +#define EHCI_ITD_PG_SELECT_BIT_POS (12) +#define EHCI_ITD_DIRECTION_BIT_POS (11) +#define EHCI_ITD_EP_BIT_POS (8) +#define EHCI_ITD_STATUS (0xF0000000) +#define EHCI_ITD_STATUS_ACTIVE (0x80000000) /*bit 4 = 1000*/ +#define EHCI_ITD_STATUS_DATA_BUFFER_ERR (0x40000000) /*bit 3 = 0100*/ +#define EHCI_ITD_STATUS_BABBLE_ERROR (0x20000000) /*bit 2 = 0010*/ +#define EHCI_ITD_STATUS_TRANSACTION_ERR (0x10000000) /*bit 4 = 0001*/ + +#define EHCI_ITD_LENGTH_TRANSMITTED (0x0FFF0000) +#define EHCI_ITD_BUFFER_OFFSET (0x00000FFF) +#define EHCI_ITD_PAGE_NUMBER (0x00007000) +#define EHCI_ITD_BUFFER_POINTER (0xFFFFF000) +#define EHCI_ITD_MULTI_TRANSACTION_BITS (0x00000003) + + + +/* SITD position bits */ +#define EHCI_SITD_DIRECTION_BIT_POS (31) +#define EHCI_SITD_PORT_NUMBER_BIT_POS (24) +#define EHCI_SITD_HUB_ADDR_BIT_POS (16) +#define EHCI_SITD_EP_ADDR_BIT_POS (8) + +#define EHCI_SITD_COMPLETE_SPLIT_MASK_BIT_POS (8) + +#define EHCI_SITD_IOC_BIT_SET (0x80000000) +#define EHCI_SITD_PAGE_SELECT_BIT_POS (30) +#define EHCI_SITD_TRANSFER_LENGTH_BIT_POS (16) +#define EHCI_SITD_STATUS_ACTIVE (0x80) + +#define EHCI_SITD_STATUS (0xFF) +#define EHCI_SITD_LENGTH_TRANSMITTED (0x03FF0000) +#define EHCI_SITD_BUFFER_OFFSET (0x00000FFF) +#define EHCI_SITD_PAGE_NUMBER (0x40000000) +#define EHCI_SITD_BUFFER_POINTER (0xFFFFF000) + + + +#define EHCI_SITD_BUFFER_PTR_BIT_POS (12) +#define EHCI_SITD_TP_BIT_POS (3) +#define EHCI_SITD_TP_ALL (0) +#define EHCI_SITD_TP_BEGIN (1) +#define EHCI_SITD_TP_MID (2) +#define EHCI_SITD_TP_END (3) + + + +/* Interrupt enable bit masks */ +#define EHCI_IER_ASYNCH_ADVANCE (0x00000020) +#define EHCI_IER_HOST_SYS_ERROR (0x00000010) +#define EHCI_IER_FRAME_LIST_ROLLOVER (0x00000008) +#define EHCI_IER_PORT_CHANGE (0x00000004) +#define EHCI_IER_USB_ERROR (0x00000002) +#define EHCI_IER_USB_INTERRUPT (0x00000001) + +/* Interrupt status bit masks */ +#define EHCI_STS_RECLAIMATION (0x00002000) +#define EHCI_STS_SOF_COUNT (0x00000080) +#define EHCI_STS_ASYNCH_ADVANCE (0x00000020) +#define EHCI_STS_HOST_SYS_ERROR (0x00000010) +#define EHCI_STS_FRAME_LIST_ROLLOVER (0x00000008) +#define EHCI_STS_PORT_CHANGE (0x00000004) +#define EHCI_STS_USB_ERROR (0x00000002) +#define EHCI_STS_USB_INTERRUPT (0x00000001) + +/* Status bit masks */ +#define EHCI_STS_ASYNCH_SCHEDULE (0x00008000) +#define EHCI_STS_PERIODIC_SCHEDULE (0x00004000) +#define EHCI_STS_RECLAMATION (0x00002000) +#define EHCI_STS_HC_HALTED (0x00001000) + +/* USB command bit masks */ +#define EHCI_USBCMD_ASYNC_SCHED_ENABLE (0x00000020) +#define EHCI_USBCMD_PERIODIC_SCHED_ENABLE (0x00000010) + +#define EHCI_HCS_PARAMS_N_PORTS (0x0F) + +#define VUSB_HS_DELAY (3500) + +#define EHCI_QH_EP_NUM_MASK (0x0F00) +#define EHCI_QH_EP_NUM_BITS_POS (8) +#define EHCI_QH_DEVICE_ADDRESS_MASK (0x7F) +#define EHCI_QH_SPEED_BITS_POS (12) +#define EHCI_QH_MAX_PKT_SIZE_BITS_POS (16) +#define EHCI_QH_NAK_COUNT_RL_BITS_POS (28) +#define EHCI_QH_EP_CTRL_FLAG_BIT_POS (27) +#define EHCI_QH_HEAD_RECLAMATION_BIT_POS (15) +#define EHCI_QH_DTC_BIT_POS (14) +#define EHCI_QH_HIGH_BW_MULT_BIT_POS (30) +#define EHCI_QH_HUB_PORT_NUM_BITS_POS (23) +#define EHCI_QH_HUB_ADDR_BITS_POS (16) +#define EHCI_QH_SPLIT_COMPLETION_MASK_BITS_POS (8) +#define EHCI_QH_SPLIT_COMPLETION_MASK (0xFF00) +#define EHCI_QH_INTR_SCHED_MASK (0xFF) +#define EHCI_QH_INACTIVATE_NEXT_TR_BIT_POS (7) +#define EHCI_QH_HORIZ_PHY_ADDRESS_MASK (0xFFFFFFE0) +#define EHCI_QH_TR_OVERLAY_DT_BIT (0x80000000) + +#define EHCI_SITD_SPLIT_COMPLETION_MASK_BITS_POS (8) + +#define EHCI_INTR_NO_THRESHOLD_IMMEDIATE (0x00010000) +#define EHCI_NEW_PERIODIC_FRAME_LIST_SIZE (1024) +#define EHCI_FRAME_LIST_SIZE_BITS_POS (2) +#define EHCI_HORIZ_PHY_ADDRESS_MASK (0xFFFFFFE0) + +#define DEFAULT_MAX_NAK_COUNT (15) + +/* OTG Status and control register bit masks */ + +/* OTG interrupt enable bit masks */ +#define VUSBHS_OTGSC_INTERRUPT_ENABLE_BITS_MASK (0x5F000000) +#define VUSBHS_OTGSC_DPIE (0x40000000) /* Data-line pulsing IE */ +#define VUSBHS_OTGSC_1MSIE (0x20000000) +#define VUSBHS_OTGSC_BSEIE (0x10000000) /* B-session end IE */ +#define VUSBHS_OTGSC_BSVIE (0x08000000) /* B-session valid IE */ +#define VUSBHS_OTGSC_ASVIE (0x04000000) /* A-session valid IE */ +#define VUSBHS_OTGSC_AVVIE (0x02000000) /* A-V-bus valid IE */ +#define VUSBHS_OTGSC_IDIE (0x01000000) /* OTG ID IE */ + +/* OTG interrupt status bit masks */ +#define VUSBHS_OTGSC_INTERRUPT_STATUS_BITS_MASK (0x005F0000) +#define VUSBHS_OTGSC_DPIS (0x00400000) /* Data-line pulsing IS */ +#define VUSBHS_OTGSC_1MSIS (0x00200000) +#define VUSBHS_OTGSC_BSEIS (0x00100000) /* B-session end IS */ +#define VUSBHS_OTGSC_BSVIS (0x00080000) /* B-session valid IS */ +#define VUSBHS_OTGSC_ASVIS (0x00040000) /* A-session valid IS */ +#define VUSBHS_OTGSC_AVVIS (0x00020000) /* A-Vbus valid IS */ +#define VUSBHS_OTGSC_IDIS (0x00010000) /* OTG ID IS */ + +/* OTG status bit masks */ +#define VUSBHS_OTGSC_DPS (0x00004000) +#define VUSBHS_OTGSC_BSE (0x00001000) /* B-session end */ +#define VUSBHS_OTGSC_BSV (0x00000800) /* B-session valid */ +#define VUSBHS_OTGSC_ASV (0x00000400) /* A-session valid */ +#define VUSBHS_OTGSC_AVV (0x00000200) /* A-Vbus Valid */ +#define VUSBHS_OTGSC_ID (0x00000100) /* OTG ID */ + +/* OTG control bit masks */ +#define VUSBHS_OTGSC_CTL_BITS (0x2F) +#define VUSBHS_OTGSC_HABA (0x00000080) /* hardware assisted data pulse bits*/ +#define VUSBHS_OTGSC_HADP (0x00000040) /* hardware assisted data pulse bits*/ + +#ifdef PATCH_3 +/* the following change is to be compatable with 4.0 revision of +hardware. Enable the following switch in config.mk to enable the +changes. */ + + /* WEB20040409 below line changed from VUSBHS_OTGSC_B_HOST_EN to VUSBHS_OTGSC_IDPU + to reflect change in usbhs4.0 B_HOST_EN has not been used quite some time */ + #define VUSBHS_OTGSC_IDPU (0x00000020) /* ID pull enable */ +#else + #define VUSBHS_OTGSC_B_HOST_EN (0x00000020) /* B_host_enable */ +#endif + +#define VUSBHS_OTGSC_DP (0x00000010) /* Data-pulsing */ +#define VUSBHS_OTGSC_OT (0x00000008) /* OTG termination */ +#if 0 + #define VUSBHS_OTGSC_VO (0x00000004) /* Vbus on */ +#endif + +#define VUSBHS_OTGSC_HAAR (0x00000004) /* Auto reset bit*/ + +#define VUSBHS_OTGSC_VC (0x00000002) /* Vbus charge */ +#define VUSBHS_OTGSC_VD (0x00000001) /* Vbus discharge */ + +typedef uint_32 USB_REGISTER, _PTR_ USB_REGISTER_PTR; + +/* The VUSB register structure */ +typedef struct { + union { + struct { + volatile USB_REGISTER CAPLENGTH_HCIVER; + volatile USB_REGISTER HCS_PARAMS; /* HC structural parameters */ + volatile USB_REGISTER HCC_PARAMS; /* HC Capability Parameters*/ + volatile USB_REGISTER RESERVED1[5]; + volatile USB_REGISTER DCI_VERSION; /* DC version number and reserved 16 bits */ + volatile USB_REGISTER DCC_PARAMS; /* DC Capability Parameters */ + } CAPABILITY_REGISTERS; + + struct { + volatile USB_REGISTER USB_CMD; /* Command register */ + volatile USB_REGISTER USB_STS; /* Status register */ + volatile USB_REGISTER USB_INTR; /* Interrupt enable */ + volatile USB_REGISTER USB_FRINDEX; /* Frame index */ + volatile USB_REGISTER CTRLDSSEGMENT; /* 4G segment selector */ + volatile USB_REGISTER DEVICE_ADDR; /* Device Address */ + volatile USB_REGISTER EP_LIST_ADDR; /* Endpoint List Address */ + volatile USB_REGISTER RESERVED0[9]; + volatile USB_REGISTER CONFIG_FLAG; /* Configured Flag register */ + volatile USB_REGISTER PORTSCX[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */ + volatile USB_REGISTER OTGSC; + volatile USB_REGISTER USB_MODE; /* USB Host/Device mode */ + volatile USB_REGISTER ENDPT_SETUP_STAT; /* Endpoint Setup Status */ + volatile USB_REGISTER ENDPTPRIME; /* Endpoint Initialize */ + volatile USB_REGISTER ENDPTFLUSH; /* Endpoint De-initialize */ + volatile USB_REGISTER ENDPTSTATUS; /* Endpoint Status */ + volatile USB_REGISTER ENDPTCOMPLETE; /* Endpoint Interrupt On Complete */ + volatile USB_REGISTER ENDPTCTRLX[16]; /* Endpoint Control, where x = 0.. 15 */ + } OPERATIONAL_DEVICE_REGISTERS; + + struct { + volatile USB_REGISTER USB_CMD; /* Command register */ + volatile USB_REGISTER USB_STS; /* Status register */ + volatile USB_REGISTER USB_INTR; /* Interrupt enable */ + volatile USB_REGISTER USB_FRINDEX; /* Frame index */ + volatile USB_REGISTER CTRLDSSEGMENT; /* 4G segment selector */ + volatile USB_REGISTER PERIODIC_LIST_BASE_ADDR; /* Periodic schedule list */ + volatile USB_REGISTER CURR_ASYNC_LIST_ADDR; /* Current Asynch schedule list */ + volatile USB_REGISTER ASYNCTTSTS; /* Async buffer in embedded TT control */ + volatile USB_REGISTER RESERVED0[8]; + volatile USB_REGISTER CONFIG_FLAG; /* Configured Flag register */ + volatile USB_REGISTER PORTSCX[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */ + volatile USB_REGISTER OTGSC; /* OTG status and control register */ + volatile USB_REGISTER USB_MODE; /* USB Host/Device mode */ + } OPERATIONAL_HOST_REGISTERS; + } REGISTERS; +} VUSB20_REG_STRUCT, _PTR_ VUSB20_REG_STRUCT_PTR; + +typedef struct { + volatile uint_32 MAX_PKT_LENGTH; /* Bits 16..26 Bit 15 is Interrupt + ** On Setup + */ + volatile uint_32 CURR_DTD_PTR; /* Current dTD Pointer */ + volatile uint_32 NEXT_DTD_PTR; /* Next dTD Pointer */ + volatile uint_32 SIZE_IOC_INT_STS; /* Total bytes (16..30), IOC (15), + ** INT (8), STS (0-7) + */ + volatile uint_32 BUFF_PTR0; /* Buffer pointer Page 0 (12-31) */ + volatile uint_32 BUFF_PTR1; /* Buffer pointer Page 1 (12-31) */ + volatile uint_32 BUFF_PTR2; /* Buffer pointer Page 2 (12-31) */ + volatile uint_32 BUFF_PTR3; /* Buffer pointer Page 3 (12-31) */ + volatile uint_32 BUFF_PTR4; /* Buffer pointer Page 4 (12-31) */ + volatile uint_32 RESERVED1; + volatile uint_8 SETUP_BUFFER[8]; /* 8 bytes of setup data that follows + ** the Setup PID + */ + volatile uint_32 RESERVED2[4]; +} VUSB20_EP_QUEUE_HEAD_STRUCT, _PTR_ VUSB20_EP_QUEUE_HEAD_STRUCT_PTR; + +typedef struct { + pointer PRIVATE; + void (_CODE_PTR_ FREE)(pointer); + pointer XD_FOR_THIS_DTD; +} SCRATCH_STRUCT, _PTR_ SCRATCH_STRUCT_PTR; + +typedef struct ep_tr_struct { + volatile uint_32 NEXT_TR_ELEM_PTR; /* Memory address of next + ** dTD to be processed (5-31) + ** and the T (bit 0) indicating + ** pointer validity + */ + volatile uint_32 SIZE_IOC_STS; /* total bytes (16-30), + ** IOC (15), Status (0-7) + */ + volatile uint_32 BUFF_PTR0; /* Buffer pointer Page 0 */ + volatile uint_32 BUFF_PTR1; /* Buffer pointer Page 1 */ + volatile uint_32 BUFF_PTR2; /* Buffer pointer Page 2 */ + volatile uint_32 BUFF_PTR3; /* Buffer pointer Page 3 */ + volatile uint_32 BUFF_PTR4; /* Buffer pointer Page 4 */ + volatile SCRATCH_STRUCT_PTR SCRATCH_PTR; +} VUSB20_EP_TR_STRUCT, _PTR_ VUSB20_EP_TR_STRUCT_PTR; + +typedef struct { + uint_32 NEXT_LINK_PTR; /* (5-31) Memory address of + ** next schedule data structure + ** item Type (1..2 ) and the + ** T (bit 0) indicating pointer + ** validity + */ + uint_32 TR_STATUS_CTL_LIST[8]; /* bits 31-28: Status, + ** bits 27-16: Tr X length + ** bit 15: Int on complete + ** bits 14-12: Page Select + ** bits 11-0: Tr X offset + */ + uint_32 BUFFER_PAGE_PTR_LIST[7]; /* bits 31-12 4K aligned pointer + ** to physical memory + ** bits 11-8 endpoint no. + ** bit 7: reserved + ** bits 6-0 device address*/ + SCRATCH_STRUCT_PTR SCRATCH_PTR; + pointer PIPE_DESCR_FOR_THIS_ITD; + pointer PIPE_TR_DESCR_FOR_THIS_ITD; + uint_32_ptr frame_list_ptr; + uint_32 number_of_transactions; + /* 32-byte aligned structures */ + uint_32 RESERVED[11]; +} EHCI_ITD_STRUCT, _PTR_ EHCI_ITD_STRUCT_PTR; + +typedef struct { + uint_32 NEXT_LINK_PTR; /* (5-31) Memory address of + ** next schedule data structure + ** item Type (1..2 ) and the + ** T (bit 0) indicating pointer + ** validity + */ + uint_32 EP_CAPAB_CHARAC; /* bits 31: Direction (I/O), + ** bits 30-24: Port number + ** bit 23: reserved + ** bits 22-16: Hub address + ** bits 15-12: Reserved + ** bits 11-8: Endpoint number + ** bit 7: reserved + ** bits 6-0: device address + */ + uint_32 UFRAME_SCHED_CTL; /* bits 31-16: reserved + ** bits 15-8: Split completion mask + ** bits 7-0: Split start mask + */ + uint_32 TRANSFER_STATE; /* bit 31: int on complete + ** bit 30: Page Select + ** bits 29-26: Reserved + ** bits 25-16: total bytes to + ** transfer + ** bits 15-8: uframe + ** complete-split progress mask + ** bits 7-0: status + */ + uint_32 BUFFER_PTR_0; /* bits 31-12: 4K aligned pointer + ** to physical memory + ** bits 11-0: Current offset + */ + uint_32 BUFFER_PTR_1; /* bits 31-12: 4K aligned pointer + ** to physical memory + ** bits 11-5 reserved + ** bits 4-3 tr position + ** bits 2-0 tr count + */ + uint_32 BACK_LINK_PTR; /* bits 31-5 back pointer points to sITD + ** bits 4-1: reserved + ** bit 0: terminate + */ + SCRATCH_STRUCT_PTR SCRATCH_PTR; + pointer PIPE_DESCR_FOR_THIS_SITD; + pointer PIPE_TR_DESCR_FOR_THIS_SITD; + uint_32_ptr frame_list_ptr; + + /* align to 16 word boundry */ + uint_32 RESERVED[5]; + +} EHCI_SITD_STRUCT, _PTR_ EHCI_SITD_STRUCT_PTR; + +typedef struct { + uint_32 NEXT_QTD_PTR; /* (5-31) Memory address of + ** next qTD to be processed + ** (4..1) reserved + ** T (bit 0) indicating pointer + ** validity + */ + uint_32 ALT_NEXT_QTD_PTR; /* bits 31-5: alternate next + ** qTD if the above one encounters + ** a short packet + ** (4..1) reserved + ** T (bit 0) indicating pointer + ** validity + */ + uint_32 TOKEN; /* bits 31: data toggle + ** bits 30-16: Total bytes to transfer + ** bit 15: Interrupt on Complete + ** bits 14-12: Current page + ** bits 11-10: Error Counter + ** bits 9-8: PID code + ** bits 7-0: status + */ + uint_32 BUFFER_PTR_0; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: Current Offset + */ + uint_32 BUFFER_PTR_1; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: reserved + */ + uint_32 BUFFER_PTR_2; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: reserved + */ + uint_32 BUFFER_PTR_3; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: reserved + */ + uint_32 BUFFER_PTR_4; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: reserved + */ + SCRATCH_STRUCT_PTR SCRATCH_PTR; + pointer PIPE_DESCR_FOR_THIS_QTD; + pointer TR_FOR_THIS_QTD; + uint_32 RESERVED[5]; +} EHCI_QTD_STRUCT, _PTR_ EHCI_QTD_STRUCT_PTR; + +typedef struct { + uint_32 HORIZ_LINK_PTR; /* (5-31) Memory address of + ** next data object to be processed + ** (4..3) reserved + ** (2..1) type of the item + ** T (bit 0) indicating pointer + ** validity + */ + uint_32 EP_CAPAB_CHARAC1; /* bits 31-28: NAK count reload, + ** bit 27: Control endpoint flag + ** bit 26-16: Maximum packet length + ** bit 15: Head of reclamation + ** list flag + ** bit 14: data toggle control + ** bits 13-12: endpoint speed + ** bit 11-8: endpoint number + ** bits 7: Inactivate on next tr + ** bits 6-0: Device address + */ + uint_32 EP_CAPAB_CHARAC2; /* bits 31-30: High-BW pipe + ** Multiplier, + ** bit 29-23: Port number + ** bit 22-16: Hub address + ** bit 15-8: Split completion mask + ** bit 7-0: Interrupt schedule mask + */ + uint_32 CURR_QTD_LINK_PTR;/* bits 31-5: physical memory address + ** of the current xaction processed + */ + uint_32 NEXT_QTD_LINK_PTR;/* bits 31-5: physical memory address + ** of the current xaction processed + ** bit 0: Terminate bit + */ + uint_32 ALT_NEXT_QTD_LINK_PTR; /* bits 31-5: physical memory address + ** of the current xaction processed + ** bits 4-1: NAK counter + ** bit 0: Terminate bit + */ + uint_32 STATUS; /* bit 31: data-toggle + ** bits 30-16: total bytes to transfer + ** bit 15: Interrupt on complete + ** bits 11-10: Error counter + ** bit 0: Ping state/Err + ** physical memory address + ** bit 11-0: reserved + */ + uint_32 BUFFER_PTR_0; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: reserved + */ + uint_32 BUFFER_PTR_1; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 7-0: Split-transaction, + ** complete-split progress + */ + uint_32 BUFFER_PTR_2; /* bits 31-12: 4K-page aligned + ** physical memory address + ** bits 11-5: S-bytes + ** bits 4-0: Split-transaction + ** frame tag + */ + uint_32 BUFFER_PTR_3; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: reserved + */ + uint_32 BUFFER_PTR_4; /* bit 31-12: 4K-page aligned + ** physical memory address + ** bit 11-0: reserved + */ + SCRATCH_STRUCT_PTR SCRATCH_PTR; + pointer PIPE_DESCR_FOR_THIS_QH; + uint_32 RESERVED[18]; +} EHCI_QH_STRUCT, _PTR_ EHCI_QH_STRUCT_PTR; + +typedef struct { + uint_32 NORMAL_PATH_LINK_PTR; /* (5-31) Memory address of + ** next data object to be processed + ** in the periodic list + ** bits 4-3: reserved + ** (2..1) type of the item + ** T (bit 0) indicating pointer + ** validity + */ + uint_32 BACK_PATH_LINK_PTR; /* bits 31-5: Memory address of + ** the queue head, + ** bit 4-3: reserved + ** (2..1) type of the item + ** T (bit 0) indicating pointer + ** validity + */ + SCRATCH_STRUCT_PTR SCRATCH_PTR; + /* 32-bytes aligned */ + uint_32 RESERVED[6]; +} EHCI_FSTN_STRUCT, _PTR_ EHCI_FSTN_STRUCT_PTR; + +typedef uint_32 EHCI_FRAME_LIST_ELEMENT_POINTER; + +#endif /* __mvUsbCore_h__ */ +/* EOF */ + + diff --git a/board/mv_feroceon/mv_hal/usb/common/mvUsbDesc.h b/board/mv_feroceon/mv_hal/usb/common/mvUsbDesc.h new file mode 100644 index 0000000..1a95297 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/common/mvUsbDesc.h @@ -0,0 +1,162 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbDesc_h__ +#define __mvUsbDesc_h__ + +#include "mvUsbTypes.h" + +typedef struct usb_device_descriptor +{ + uint_8 bLength; /* Descriptor size in bytes = 18 */ + uint_8 bDescriptorType; /* DEVICE descriptor type = 1 */ + uint_8 bcdUSD[2]; /* USB spec in BCD, e.g. 0x0200 */ + uint_8 bDeviceClass; /* Class code, if 0 see interface */ + uint_8 bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */ + uint_8 bDeviceProtocol; /* Protocol, if 0 see interface */ + uint_8 bMaxPacketSize; /* Endpoint 0 max. size */ + uint_8 idVendor[2]; /* Vendor ID per USB-IF */ + uint_8 idProduct[2]; /* Product ID per manufacturer */ + uint_8 bcdDevice[2]; /* Device release # in BCD */ + uint_8 iManufacturer; /* Index to manufacturer string */ + uint_8 iProduct; /* Index to product string */ + uint_8 iSerialNumber; /* Index to serial number string */ + uint_8 bNumConfigurations; /* Number of possible configurations */ +} DEVICE_DESCRIPTOR, _PTR_ DEVICE_DESCRIPTOR_PTR; + +typedef struct usb_configuration_descriptor +{ + uint_8 bLength; /* Descriptor size in bytes = 9 */ + uint_8 bDescriptorType; /* CONFIGURATION type = 2 or 7 */ + uint_8 wTotalLength[2]; /* Length of concatenated descriptors */ + uint_8 bNumInterfaces; /* Number of interfaces, this config. */ + uint_8 bConfigurationValue; /* Value to set this config. */ + uint_8 iConfig; /* Index to configuration string */ + uint_8 bmAttributes; /* Config. characteristics */ + #define CONFIG_RES7 (0x80) /* Reserved, always = 1 */ + #define CONFIG_SELF_PWR (0x40) /* Self-powered device */ + #define CONFIG_WAKEUP (0x20) /* Remote wakeup */ + uint_8 bMaxPower; /* Max.power from bus, 2mA units */ +} CONFIGURATION_DESCRIPTOR, _PTR_ CONFIGURATION_DESCRIPTOR_PTR; + +typedef struct usb_interface_descriptor +{ + uint_8 bLength; /* Descriptor size in bytes = 9 */ + uint_8 bDescriptorType; /* INTERFACE descriptor type = 4 */ + uint_8 bInterfaceNumber; /* Interface no.*/ + uint_8 bAlternateSetting; /* Value to select this IF */ + uint_8 bNumEndpoints; /* Number of endpoints excluding 0 */ + uint_8 bInterfaceClass; /* Class code, 0xFF = vendor */ + uint_8 bInterfaceSubClass; /* Sub-Class code, 0 if class = 0 */ + uint_8 bInterfaceProtocol; /* Protocol, 0xFF = vendor */ + uint_8 iInterface; /* Index to interface string */ +} INTERFACE_DESCRIPTOR, _PTR_ INTERFACE_DESCRIPTOR_PTR; + +typedef struct usb_endpoint_descriptor +{ + uint_8 bLength; /* Descriptor size in bytes = 7 */ + uint_8 bDescriptorType; /* ENDPOINT descriptor type = 5 */ + uint_8 bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */ + #define IN_ENDPOINT (0x80) /* IN endpoint, device to host */ + #define OUT_ENDPOINT (0x00) /* OUT endpoint, host to device */ + #define ENDPOINT_MASK (0x0F) /* Mask endpoint # */ + uint_8 bmAttributes; /* Transfer type */ + #define CONTROL_ENDPOINT (0x00) /* Control transfers */ + #define ISOCH_ENDPOINT (0x01) /* Isochronous transfers */ + #define BULK_ENDPOINT (0x02) /* Bulk transfers */ + #define IRRPT_ENDPOINT (0x03) /* Interrupt transfers */ + #define EP_TYPE_MASK (0x03) /* Mask type bits */ + /* Following must be zero except for isochronous endpoints */ + #define ISOCH_NOSYNC (0x00) /* No synchronization */ + #define ISOCH_ASYNC (0x04) /* Asynchronous */ + #define ISOCH_ADAPT (0x08) /* Adaptive */ + #define ISOCH_SYNCH (0x0C) /* Synchrounous */ + #define ISOCH_DATA (0x00) /* Data endpoint */ + #define ISOCH_FEEDBACK (0x10) /* Feedback endpoint */ + #define ISOCH_IMPLICIT (0x20) /* Implicit feedback */ + #define ISOCH_RESERVED (0x30) /* Reserved */ + uint_8 wMaxPacketSize[2]; /* Bits 10:0 = max. packet size */ + /* For high-speed interrupt or isochronous only, additional + ** transaction opportunities per microframe follow.*/ + #define PACKET_SIZE_MASK (0x7FF) /* packet size bits */ + #define NO_ADDITONAL (0x0000) /* 1 / microframe */ + #define ONE_ADDITIONAL (0x0800) /* 2 / microframe */ + #define TWO_ADDITIONAL (0x1000) /* 3 / microframe */ + #define ADDITIONAL_MASK (ONE_ADDITIONAL | TWO_ADDITIONAL) + uint_8 iInterval; /* Polling interval in (micro) frames */ +} ENDPOINT_DESCRIPTOR, _PTR_ ENDPOINT_DESCRIPTOR_PTR; + +typedef struct usb_qualifier_descriptor +{ + uint_8 bLength; /* Descriptor size in bytes = 10 */ + uint_8 bDescriptorType; /* DEVICE QUALIFIER type = 6 */ + uint_8 bcdUSD[2]; /* USB spec in BCD, e.g. 0x0200 */ + uint_8 bDeviceClass; /* Class code, if 0 see interface */ + uint_8 bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */ + uint_8 bDeviceProtocol; /* Protocol, if 0 see interface */ + uint_8 bMaxPacketSize; /* Endpoint 0 max. size */ + uint_8 bNumConfigurations; /* Number of possible configurations */ + uint_8 bReserved; /* Reserved = 0 */ +} QUALIFIER_DESCRIPTOR, _PTR_ QUALIFIER_DESCRIPTOR_PTR; + +/* Other-Config type 7 fields are identical to type 2 above */ + +/* Interface-Power descriptor type 8 not used in this version */ + +typedef struct usb_otg_descriptor +{ + uint_8 bLength; /* Descriptor size in bytes = 9 */ + uint_8 bDescriptorType; /* CONFIGURATION type = 2 or 7 */ + uint_8 bmAttributes; /* OTG characteristics */ + #define OTG_SRP_SUPPORT (0x01) /* Supports SRP */ + #define OTG_HNP_SUPPORT (0x02) /* Supports HNP */ +} OTG_DESCRIPTOR, _PTR_ OTG_DESCRIPTOR_PTR; + +typedef union descriptor_union +{ + uint_32 word; + uint_8_ptr bufr; + pointer pntr; + DEVICE_DESCRIPTOR_PTR dvic; + CONFIGURATION_DESCRIPTOR_PTR cfig; + INTERFACE_DESCRIPTOR_PTR intf; + ENDPOINT_DESCRIPTOR_PTR ndpt; + QUALIFIER_DESCRIPTOR_PTR qual; + OTG_DESCRIPTOR_PTR otg; +} DESCRIPTOR_UNION, _PTR_ DESCRIPTOR_UNION_PTR; + +/* Prototypes */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint_32 usb_host_init(uint_8, uint_32, + _usb_host_handle _PTR_); +extern uint_32 _usb_host_open_pipe(_usb_host_handle, + PIPE_INIT_PARAM_STRUCT_PTR, _usb_pipe_handle _PTR_ ); + +#ifdef __cplusplus +} +#endif + +#endif /* __mvUsbDesc_h__ */ + +/* EOF */ diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbDevCh9.c b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevCh9.c new file mode 100644 index 0000000..78b08c3 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevCh9.c @@ -0,0 +1,301 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#include "mvUsbDevApi.h" +#include "mvUsbDevPrv.h" +#include "mvUsbCh9.h" + +static volatile boolean ENTER_TEST_MODE = FALSE; +static volatile uint_16 test_mode_index = 0; + + +void mvUsbCh9GetStatus(_usb_device_handle handle, boolean setup, + SETUP_STRUCT* ctrl_req) +{ /* Body */ + uint_8 endpoint, direction; + uint_16 usb_status; + USB_DEV_STATE_STRUCT* usb_dev_ptr = (USB_DEV_STATE_STRUCT*)handle; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup); + + if(!setup) + return; + + switch (ctrl_req->REQUESTTYPE) + { + case (REQ_DIR_IN | REQ_RECIP_DEVICE): + /* Device request */ + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); + break; + + case (REQ_DIR_IN | REQ_RECIP_INTERFACE): + /* Interface request */ + _usb_device_get_status(handle, ARC_USB_STATUS_INTERFACE, &usb_status); + break; + + case (REQ_DIR_IN | REQ_RECIP_ENDPOINT): + /* Endpoint request */ + endpoint = ctrl_req->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK; + if( (ctrl_req->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN) + direction = ARC_USB_SEND; + else + direction = ARC_USB_RECV; + + usb_status = _usb_device_is_endpoint_stalled(handle, endpoint, direction); + break; + + default: + /* Unknown request */ + USB_printf("GetStatus: Unknown request type 0x%x\n", ctrl_req->REQUESTTYPE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endswitch */ + + /* Send the requested data */ + *usb_dev_ptr->STATUS_PTR = USB_16BIT_LE(usb_status); + _usb_device_send_data(handle, 0, (uint_8_ptr)usb_dev_ptr->STATUS_PTR, sizeof(uint_16)); + + /* status phase */ + _usb_device_recv_data(handle, 0, NULL, 0); + + return; +} /* Endbody */ + +void mvUsbCh9ClearFeature(_usb_device_handle handle, boolean setup, + SETUP_STRUCT* setup_ptr) +{ /* Body */ + uint_8 endpoint, direction; + uint_16 usb_status; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup); + + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_status); + if ((usb_status != ARC_USB_STATE_CONFIG) && (usb_status != ARC_USB_STATE_ADDRESS)) + { + USB_printf("ClearFeature: Wrong USB state %d\n", usb_status); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + if(!setup) + return; + + switch (setup_ptr->REQUESTTYPE) + { + case (REQ_DIR_OUT | REQ_RECIP_DEVICE): + /* DEVICE */ + switch(setup_ptr->VALUE) + { + case DEVICE_REMOTE_WAKEUP: + /* clear remote wakeup */ + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); + usb_status &= ~ARC_USB_REMOTE_WAKEUP; + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, usb_status); + USB_printf("Clear REMOTE_WAKEUP feature\n"); + break; + + case DEVICE_TEST_MODE: + /* Exit Test Mode */ + _usb_device_set_status(handle, ARC_USB_STATUS_TEST_MODE, 0); + break; + + default: + USB_printf("ClearFeature: Unknown Device feature %d\n", + setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + break; + + case (REQ_DIR_OUT | REQ_RECIP_ENDPOINT): + /* ENDPOINT */ + if (setup_ptr->VALUE != ENDPOINT_HALT) + { + USB_printf("ClearFeature: Wrong Endpoint feature %d\n", + setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + endpoint = setup_ptr->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK; + if( (setup_ptr->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN) + direction = ARC_USB_SEND; + else + direction = ARC_USB_RECV; + + _usb_device_unstall_endpoint(handle, endpoint, direction); + break; + + default: + USB_printf("ClearFeature: Unknown REQUEST_TYPE %d\n", + setup_ptr->REQUESTTYPE); + + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endswitch */ + + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); +} + +void mvUsbCh9SetFeature(_usb_device_handle handle, boolean setup, + SETUP_STRUCT* setup_ptr) +{ + uint_16 usb_status; + uint_8 endpoint, direction; + USB_DEV_STATE_STRUCT* usb_dev_ptr = (USB_DEV_STATE_STRUCT*)handle; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "%s: setup=%d\n", __FUNCTION__, (int)setup); + + if (setup) + { + switch (setup_ptr->REQUESTTYPE) + { + case (REQ_DIR_OUT | REQ_RECIP_DEVICE): + /* DEVICE */ + switch (setup_ptr->VALUE) + { + case DEVICE_REMOTE_WAKEUP: + /* set remote wakeup */ + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); + usb_status |= ARC_USB_REMOTE_WAKEUP; + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, usb_status); + USB_printf("Set REMOTE_WAKEUP feature\n"); + break; + + case DEVICE_TEST_MODE: + /* Test Mode */ + if( (setup_ptr->INDEX & 0x00FF) || (usb_dev_ptr->SPEED != ARC_USB_SPEED_HIGH) ) + { + USB_printf("SetFeature: Wrong Test mode parameters: mode=%d, speed=%d\n", + (setup_ptr->INDEX & 0x00FF), usb_dev_ptr->SPEED); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_status); + if( (usb_status == ARC_USB_STATE_CONFIG) || + (usb_status == ARC_USB_STATE_ADDRESS) || + (usb_status == ARC_USB_STATE_DEFAULT)) + { + /* wait with Set Test mode */ + ENTER_TEST_MODE = TRUE; + test_mode_index = (setup_ptr->INDEX & 0xFF00); + USB_printf("SetFeature: Prepare for Test mode 0x%x\n", test_mode_index); + } + else + { + USB_printf("SetFeature: Wrong USB state for Test mode: state=%d\n", + usb_status); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + break; + + default: + USB_printf("SetFeature: Unknown Device feature %d\n", + setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endswitch */ + break; + + case (REQ_DIR_OUT | REQ_RECIP_ENDPOINT): + /* ENDPOINT */ + if (setup_ptr->VALUE != ENDPOINT_HALT) + { + USB_printf("SetFeature: Unknown Endpoint feature %d\n", + setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + endpoint = setup_ptr->INDEX & ARC_USB_STATUS_ENDPOINT_NUMBER_MASK; + if( (setup_ptr->INDEX & (1 << REQ_DIR_OFFSET)) == REQ_DIR_IN) + direction = ARC_USB_SEND; + else + direction = ARC_USB_RECV; + + _usb_device_stall_endpoint(handle, endpoint, direction); + break; + + default: + USB_printf("SetFeature: Unknown REQUEST_TYPE %d\n", + setup_ptr->REQUESTTYPE); + + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endswitch */ + + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); + } + else + { + if (ENTER_TEST_MODE) + { + /* Enter Test Mode */ + USB_printf("SetFeature: Activate Test mode 0x%x\n", test_mode_index); + _usb_device_set_status(handle, ARC_USB_STATUS_TEST_MODE, test_mode_index); + } /* Endif */ + } /* Endif */ +} + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SetAddress +* Returned Value : None +* Comments : +* Chapter 9 SetAddress command +* We setup a TX packet of 0 length ready for the IN token +* Once we get the TOK_DNE interrupt for the IN token, then +* we change the ADDR register and go to the ADDRESS state. +* +*END*--------------------------------------------------------------------*/ +void mvUsbCh9SetAddress(_usb_device_handle handle, + boolean setup, SETUP_STRUCT* setup_ptr) +{ /* Body */ + static uint_8 new_address; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ADDR, "usbDisk %s: setup=%d, address=%d\n", + __FUNCTION__, (int)setup, setup_ptr->VALUE); + + if (setup) + { + new_address = setup_ptr->VALUE; + /******************************************************* + * if hardware assitance is enabled for set_address (see + * hardware rev for details) we need to do the set_address + * before queuing the status phase. + *******************************************************/ +#ifdef SET_ADDRESS_HARDWARE_ASSISTANCE + _usb_device_set_status(handle, ARC_USB_STATUS_ADDRESS, new_address); +#endif + /* ack */ + _usb_device_send_data(handle, 0, 0, 0); + } + else + { +#ifndef SET_ADDRESS_HARDWARE_ASSISTANCE + _usb_device_set_status(handle, ARC_USB_STATUS_ADDRESS, new_address); +#endif + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, ARC_USB_STATE_ADDRESS); + } +} diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbDevMain.c b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevMain.c new file mode 100644 index 0000000..785b698 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevMain.c @@ -0,0 +1,768 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "mvUsbDevApi.h" +#include "mvUsbDevPrv.h" + +USB_IMPORT_FUNCS* global_import_funcs = NULL; + +#ifdef USB_UNDERRUN_WA +USB_WA_FUNCS* global_wa_funcs = NULL; +int global_wa_threshold = 64; +int global_wa_sram_parts = 2; +#endif /* USB_UNDERRUN_WA */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_cleanup +* Returned Value : void +* Comments : +* Cleanup allocated structures. +* +*END*-----------------------------------------------------------------*/ + +static void _usb_device_cleanup(USB_DEV_STATE_STRUCT_PTR usb_dev_ptr) +{ + /* Free all internal transfer descriptors */ + if(usb_dev_ptr->XD_BASE != NULL) + { + USB_memfree((pointer)usb_dev_ptr->XD_BASE); + } + + /* Free all XD scratch memory */ + if(usb_dev_ptr->XD_SCRATCH_STRUCT_BASE != NULL) + { + USB_memfree((pointer)usb_dev_ptr->XD_SCRATCH_STRUCT_BASE); + } + /* Free the temp ep init XD */ + if(usb_dev_ptr->TEMP_XD_PTR != NULL) + { + USB_memfree((pointer)usb_dev_ptr->TEMP_XD_PTR); + } + + if(usb_dev_ptr->STATUS_UNAIGNED_PTR != NULL) + USB_memfree((pointer)usb_dev_ptr->STATUS_UNAIGNED_PTR); + + if(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR != NULL) + USB_memfree((pointer)usb_dev_ptr->TEST_PKT_UNAIGNED_PTR); + + /* Free the USB state structure */ + USB_memfree((pointer)usb_dev_ptr); +} + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_free_XD +* Returned Value : void +* Comments : +* Enqueues a XD onto the free XD ring. +* +*END*-----------------------------------------------------------------*/ + +void _usb_device_free_XD + ( + /* [IN] the dTD to enqueue */ + pointer xd_ptr + ) +{ /* Body */ + int lockKey; + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)(((XD_STRUCT_PTR)xd_ptr)->SCRATCH_PTR->PRIVATE); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "free_XD: xd_ptr=0x%x\n", (unsigned)xd_ptr); + + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.free_XD_count++)); + + /* + ** This function can be called from any context, and it needs mutual + ** exclusion with itself. + */ + + lockKey = USB_lock(); + + /* + ** Add the XD to the free XD queue (linked via PRIVATE) and + ** increment the tail to the next descriptor + */ + USB_XD_QADD(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, (XD_STRUCT_PTR)xd_ptr); + usb_dev_ptr->XD_ENTRIES++; + + USB_unlock(lockKey); + +} /* Endbody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_set_bsp_funcs +* Returned Value : NONE +* Comments : +* Set pointer to structure of imported BSP functions +* +*END*-----------------------------------------------------------------*/ +void _usb_device_set_bsp_funcs(USB_IMPORT_FUNCS* pBspFuncs) +{ + static boolean isFirst = TRUE; + + if(isFirst) + { + global_import_funcs = pBspFuncs; + _usb_debug_init_trace_log(); + isFirst = FALSE; + } +} + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_get_max_endpoint +* Returned Value : handle or NULL +* Comments : +* Return maximum number of endpoints supportedby USB device +* (for DEBUG only) +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_get_max_endpoint(_usb_device_handle handle) +{ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + return usb_dev_ptr->MAX_ENDPOINTS; +} + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_get_dev_num +* Returned Value : handle or NULL +* Comments : +* Return unique USB device number +* (for DEBUG only) +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_get_dev_num(_usb_device_handle handle) +{ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + return usb_dev_ptr->DEV_NUM; +} + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_init +* Returned Value : USB_OK or error code +* Comments : +* Initializes the USB device specific data structures and calls +* the low-level device controller chip initialization routine. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_init + ( + /* [IN] the USB device controller to initialize */ + uint_8 devnum, + + /* [OUT] the USB_USB_dev_initialize state structure */ + _usb_device_handle* handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + XD_STRUCT_PTR xd_ptr; + uint_8 i, error; + SCRATCH_STRUCT_PTR temp_scratch_ptr; + + /* global_import_funcs must be initailized before */ + if(global_import_funcs == NULL) + return USBERR_INIT_FAILED; + + if (devnum > MAX_USB_DEVICES) + { + USB_printf("_usb_device_init, error invalid device number"); + return USBERR_INVALID_DEVICE_NUM; + } /* Endif */ + + /* Allocate memory for the state structure */ + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)USB_memalloc(sizeof(USB_DEV_STATE_STRUCT)); + if (usb_dev_ptr == NULL) + { + USB_printf("_usb_device_init, malloc of %d bytes for USB_DEV_STATE_STRUCT failed\n", + sizeof(USB_DEV_STATE_STRUCT)); + return USBERR_ALLOC_STATE; + } /* Endif */ + + /* Zero out the internal USB state structure */ + USB_memzero(usb_dev_ptr, sizeof(USB_DEV_STATE_STRUCT)); + + usb_dev_ptr->DEV_NUM = devnum; + + /* Multiple devices will have different base addresses and + ** interrupt vectors (For future) + */ + usb_dev_ptr->USB_STATE = ARC_USB_STATE_UNKNOWN; + + /* Allocate MAX_XDS_FOR_TR_CALLS */ + xd_ptr = (XD_STRUCT_PTR)USB_memalloc(sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS); + if (xd_ptr == NULL) + { + _usb_device_cleanup(usb_dev_ptr); + USB_printf("_usb_device_init, malloc of %d bytes for %d XD_STRUCT failed\n", + sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS, MAX_XDS_FOR_TR_CALLS); + return USBERR_ALLOC_TR; + } /* Endif */ + + usb_dev_ptr->XD_BASE = xd_ptr; + + _usb_clear_stats(usb_dev_ptr); + + USB_memzero(xd_ptr, sizeof(XD_STRUCT) * MAX_XDS_FOR_TR_CALLS); + + /* Allocate memory for internal scratch structure */ + usb_dev_ptr->XD_SCRATCH_STRUCT_BASE = (SCRATCH_STRUCT_PTR) + USB_memalloc(sizeof(SCRATCH_STRUCT) * MAX_XDS_FOR_TR_CALLS); + if (usb_dev_ptr->XD_SCRATCH_STRUCT_BASE == NULL) + { + _usb_device_cleanup(usb_dev_ptr); + USB_printf("_usb_device_init, malloc of %d bytes for %d XD_STRUCT failed\n", + sizeof(SCRATCH_STRUCT) * MAX_XDS_FOR_TR_CALLS, MAX_XDS_FOR_TR_CALLS); + return USBERR_ALLOC; + } /* Endif */ + + temp_scratch_ptr = usb_dev_ptr->XD_SCRATCH_STRUCT_BASE; + usb_dev_ptr->XD_HEAD = NULL; + usb_dev_ptr->XD_TAIL = NULL; + usb_dev_ptr->XD_ENTRIES = 0; + + /* Enqueue all the XDs */ + for (i=0;iSCRATCH_PTR = temp_scratch_ptr; + xd_ptr->SCRATCH_PTR->FREE = _usb_device_free_XD; + xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; + _usb_device_free_XD((pointer)xd_ptr); + xd_ptr++; + temp_scratch_ptr++; + } /* Endfor */ + + usb_dev_ptr->TEMP_XD_PTR = (XD_STRUCT_PTR)USB_memalloc(sizeof(XD_STRUCT)); + if(usb_dev_ptr->TEMP_XD_PTR == NULL) + { + USB_printf("_usb_device_init, malloc of %d bytes for TEMP_XD_STRUCT failed\n", + sizeof(XD_STRUCT)); + _usb_device_cleanup(usb_dev_ptr); + return USBERR_ALLOC; + } + USB_memzero(usb_dev_ptr->TEMP_XD_PTR, sizeof(XD_STRUCT)); + + /* Allocate 2 bytes for USB_STATUS to be sent over USB, so Cache line aligned */ + usb_dev_ptr->STATUS_UNAIGNED_PTR = (uint_8*)USB_memalloc(sizeof(uint_16) + PSP_CACHE_LINE_SIZE); + if(usb_dev_ptr->STATUS_UNAIGNED_PTR == NULL) + { + USB_printf("_usb_device_init, malloc of %d bytes for USB_STATUS failed\n", + sizeof(uint_16) + PSP_CACHE_LINE_SIZE); + _usb_device_cleanup(usb_dev_ptr); + return USBERR_ALLOC; + } + USB_memzero(usb_dev_ptr->STATUS_UNAIGNED_PTR, sizeof(uint_16) + PSP_CACHE_LINE_SIZE); + usb_dev_ptr->STATUS_PTR = (uint_16*)USB_CACHE_ALIGN((uint_32)usb_dev_ptr->STATUS_UNAIGNED_PTR); + + /* Allocate 53 bytes for USB Test packet to be sent over USB, so Cache line aligned */ + usb_dev_ptr->TEST_PKT_UNAIGNED_PTR = (uint_8*)USB_memalloc(USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE); + if(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR == NULL) + { + USB_printf("_usb_device_init, malloc of %d bytes for USB Test packet failed\n", + USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE); + _usb_device_cleanup(usb_dev_ptr); + return USBERR_ALLOC; + } + USB_memzero(usb_dev_ptr->TEST_PKT_UNAIGNED_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH + PSP_CACHE_LINE_SIZE); + usb_dev_ptr->TEST_PKT_PTR = (uint_8*)USB_CACHE_ALIGN((uint_32)usb_dev_ptr->TEST_PKT_UNAIGNED_PTR); + + /* Initialize the USB controller chip */ + error = _usb_dci_vusb20_init(devnum, usb_dev_ptr); + if (error) + { + _usb_device_cleanup(usb_dev_ptr); + USB_printf("_usb_device_init, init failed"); + return USBERR_INIT_FAILED; + } /* Endif */ + + USB_printf("device_init: pDev=0x%x, pXD(%d)=0x%x, pSCRATCH(%d)=0x%x, pTempXD=0x%x\n", + (unsigned)usb_dev_ptr, MAX_XDS_FOR_TR_CALLS, (unsigned)usb_dev_ptr->XD_BASE, + MAX_XDS_FOR_TR_CALLS, (unsigned)usb_dev_ptr->XD_SCRATCH_STRUCT_BASE, + (unsigned)usb_dev_ptr->TEMP_XD_PTR); + + *handle = usb_dev_ptr; + return USB_OK; +} /* EndBody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_shutdown +* Returned Value : USB_OK or error code +* Comments : +* Shutdown an initialized USB device +* +*END*-----------------------------------------------------------------*/ +void _usb_device_shutdown(_usb_device_handle handle) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + SERVICE_STRUCT_PTR service_ptr; + int ep; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CTRL, "shutdown\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + for(ep=0; ep<(usb_dev_ptr->MAX_ENDPOINTS); ep++) + { + /* Cancel all transfers on all endpoints */ + while(_usb_device_get_transfer_status(handle, ep, ARC_USB_RECV) != + ARC_USB_STATUS_IDLE) + { + _usb_device_cancel_transfer(handle, ep, ARC_USB_RECV); + } + while(_usb_device_get_transfer_status(handle, ep, ARC_USB_SEND) != + ARC_USB_STATUS_IDLE) + { + _usb_device_cancel_transfer(handle, ep, ARC_USB_SEND); + } + } + _usb_dci_vusb20_shutdown(usb_dev_ptr); + + /* Free all the Callback function structure memory */ + for( service_ptr = usb_dev_ptr->SERVICE_HEAD_PTR; service_ptr; + service_ptr = service_ptr->NEXT) + { + USB_printf("_usb_device_shutdown: free service_ptr = 0x%x\n", + service_ptr); + USB_memfree(service_ptr); + } + usb_dev_ptr->SERVICE_HEAD_PTR = NULL; + + _usb_device_cleanup(usb_dev_ptr); +} /* EndBody */ + + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _usb_device_register_service +* Returned Value : USB_OK or error code +* Comments : +* Registers a callback routine for a specified event or endpoint. +* +*END*--------------------------------------------------------------------*/ +uint_8 _usb_device_register_service + ( + /* [IN] Handle to the USB device */ + _usb_device_handle handle, + + /* [IN] type of event or endpoint number to service */ + uint_8 type, + + /* [IN] Pointer to the service's callback function */ + void(_CODE_PTR_ service)(pointer, uint_8, boolean, uint_8, uint_8_ptr, uint_32, uint_8) + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + SERVICE_STRUCT_PTR service_ptr; + SERVICE_STRUCT_PTR _PTR_ search_ptr; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + /* Needs mutual exclusion */ + lockKey = USB_lock(); + + /* Search for an existing entry for type */ + for (search_ptr = &usb_dev_ptr->SERVICE_HEAD_PTR; + *search_ptr; + search_ptr = &(*search_ptr)->NEXT) + { + if ((*search_ptr)->TYPE == type) + { + /* Found an existing entry */ + USB_unlock(lockKey); + USB_printf("_usb_device_register_service, service %d already opened\n"); + return USBERR_OPEN_SERVICE; + } /* Endif */ + } /* Endfor */ + + /* No existing entry found - create a new one */ + service_ptr = (SERVICE_STRUCT_PTR)USB_memalloc(sizeof(SERVICE_STRUCT)); + if (!service_ptr) + { + USB_unlock(lockKey); + USB_printf("_usb_device_register_service, malloc for %d bytes failed\n", + sizeof(SERVICE_STRUCT)); + return USBERR_ALLOC; + } /* Endif */ + + service_ptr->TYPE = type; + service_ptr->SERVICE = service; + service_ptr->NEXT = NULL; + *search_ptr = service_ptr; + + USB_unlock(lockKey); + + return USB_OK; +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _usb_device_unregister_service +* Returned Value : USB_OK or error code +* Comments : +* Unregisters a callback routine for a specified event or endpoint. +* +*END*--------------------------------------------------------------------*/ +uint_8 _usb_device_unregister_service + ( + /* [IN] Handle to the USB device */ + _usb_device_handle handle, + + /* [IN] type of event or endpoint number to service */ + uint_8 type + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + SERVICE_STRUCT_PTR service_ptr; + SERVICE_STRUCT_PTR _PTR_ search_ptr; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + /* Needs mutual exclusion */ + lockKey = USB_lock(); + + /* Search for an existing entry for type */ + for (search_ptr = &usb_dev_ptr->SERVICE_HEAD_PTR; + *search_ptr; + search_ptr = &(*search_ptr)->NEXT) + { + if ((*search_ptr)->TYPE == type) { + /* Found an existing entry - delete it */ + break; + } /* Endif */ + } /* Endfor */ + + /* No existing entry found */ + if (!*search_ptr) + { + USB_unlock(lockKey); + USB_printf("_usb_device_unregister_service, no service found\n"); + return USBERR_CLOSED_SERVICE; + } /* Endif */ + + service_ptr = *search_ptr; + *search_ptr = service_ptr->NEXT; + + USB_memfree((pointer)service_ptr); + + USB_unlock(lockKey); + + return USB_OK; + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _usb_device_call_service +* Returned Value : USB_OK or error code +* Comments : +* Calls the appropriate service for the specified type, if one is +* registered. Used internally only. +* +*END*--------------------------------------------------------------------*/ +uint_8 _usb_device_call_service + ( + /* [IN] Handle to the USB device */ + _usb_device_handle handle, + + /* [OUT] Type of service or endpoint */ + uint_8 type, + + /* [OUT] Is it a Setup transfer? */ + boolean setup, + + /* [OUT] Direction of transmission; is it a Transmit? */ + boolean direction, + + /* [OUT] Pointer to the data */ + uint_8_ptr buffer_ptr, + + /* [OUT] Number of bytes in transmission */ + uint_32 length, + + /* [OUT] Any errors */ + uint_8 errors + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + SERVICE_STRUCT _PTR_ service_ptr; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + /* Needs mutual exclusion */ + lockKey = USB_lock(); + + /* Search for an existing entry for type */ + for (service_ptr = usb_dev_ptr->SERVICE_HEAD_PTR; + service_ptr; + service_ptr = service_ptr->NEXT) + { + if (service_ptr->TYPE == type) + { + service_ptr->SERVICE(handle, type, setup, direction, buffer_ptr, length, errors); + USB_unlock(lockKey); + + return USB_OK; + } /* Endif */ + + } /* Endfor */ + + USB_unlock(lockKey); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CTRL, "_usb_device_call_service, service %d is closed\n", type); + + return USBERR_CLOSED_SERVICE; +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_init_endpoint +* Returned Value : USB_OK or error code +* Comments : +* Initializes the endpoint and the data structures associated with the +* endpoint +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_init_endpoint + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] MAX Packet size for this endpoint */ + uint_16 max_pkt_size, + + /* [IN] Direction */ + uint_8 direction, + + /* [IN] Type of Endpoint */ + uint_8 type, + + /* [IN] After all data is transfered, should we terminate the transfer + ** with a zero length packet if the last packet size == MAX_PACKET_SIZE? + */ + uint_8 flag + ) +{ /* Body */ + + int lockKey; + uint_8 error = 0; + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + /* Initialize the transfer descriptor */ + usb_dev_ptr->TEMP_XD_PTR->EP_NUM = ep_num; + usb_dev_ptr->TEMP_XD_PTR->BDIRECTION = direction; + usb_dev_ptr->TEMP_XD_PTR->WMAXPACKETSIZE = max_pkt_size; + usb_dev_ptr->TEMP_XD_PTR->EP_TYPE = type; + usb_dev_ptr->TEMP_XD_PTR->DONT_ZERO_TERMINATE = flag; + usb_dev_ptr->TEMP_XD_PTR->MAX_PKTS_PER_UFRAME = + ((flag & ARC_USB_MAX_PKTS_PER_UFRAME) >> 1); + + lockKey = USB_lock(); + error = _usb_dci_vusb20_init_endpoint(handle, usb_dev_ptr->TEMP_XD_PTR); + USB_unlock(lockKey); + + return error; + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_deinit_endpoint +* Returned Value : USB_OK or error code +* Comments : +* Disables the endpoint and the data structures associated with the +* endpoint +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_deinit_endpoint + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] Direction */ + uint_8 direction + ) +{ /* Body */ + int lockKey; + uint_8 error = 0; + lockKey = USB_lock(); + + error = _usb_dci_vusb20_deinit_endpoint(handle, ep_num, direction); + + USB_unlock(lockKey); + + return error; +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_get_transfer_status +* Returned Value : Status of the transfer +* Comments : +* returns the status of the transaction on the specified endpoint. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_get_transfer_status + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + uint_8 status; + int lockKey; + + lockKey = USB_lock(); + + status = _usb_dci_vusb20_get_transfer_status(handle, ep_num, direction); + + USB_unlock(lockKey); + + /* Return the status of the last queued transfer */ + return (status); + +} /* EndBody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_read_setup_data +* Returned Value : USB_OK or error code +* Comments : +* Reads the setup data from the hardware +* +*END*-----------------------------------------------------------------*/ +void _usb_device_read_setup_data + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] buffer for receiving Setup packet */ + uint_8_ptr buff_ptr + ) +{ /* Body */ + int lockKey; + + lockKey = USB_lock(); + + _usb_dci_vusb20_get_setup_data(handle, ep_num, buff_ptr); + + USB_unlock(lockKey); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_cancel_transfer +* Returned Value : USB_OK or error code +* Comments : +* returns the status of the transaction on the specified endpoint. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_cancel_transfer + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + uint_8 error = USB_OK; + int lockKey; + + lockKey = USB_lock(); + + /* Cancel transfer on the specified endpoint for the specified + ** direction + */ + error = _usb_dci_vusb20_cancel_transfer(handle, ep_num, direction); + + USB_unlock(lockKey); + + return error; +} /* EndBody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_stop +* Returned Value : None +* Comments : +* Stop USB device +* +*END*-----------------------------------------------------------------*/ +void _usb_device_stop(_usb_device_handle handle) +{ + int lockKey; + + lockKey = USB_lock(); + _usb_dci_vusb20_stop(handle); + USB_unlock(lockKey); +} + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_start +* Returned Value : None +* Comments : +* Start USB device +* +*END*-----------------------------------------------------------------*/ +void _usb_device_start(_usb_device_handle handle) +{ + int lockKey; + + lockKey = USB_lock(); + _usb_dci_vusb20_start(handle); + USB_unlock(lockKey); +} diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbDevPrv.h b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevPrv.h new file mode 100644 index 0000000..cafb4fb --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevPrv.h @@ -0,0 +1,267 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __mvUsbDevPrv_h__ +#define __mvUsbDevPrv_h__ + +#include "mvUsbCore.h" + + +#define USB_TEST_MODE_TEST_PACKET_LENGTH (53) + + +#define USB_XD_QADD(head,tail,XD) \ + if ((head) == NULL) { \ + (head) = (XD); \ + } else { \ + (tail)->SCRATCH_PTR->PRIVATE = (XD); \ + } /* Endif */ \ + (tail) = (XD); \ + (XD)->SCRATCH_PTR->PRIVATE = NULL + +#define USB_XD_QGET(head,tail,XD) \ + (XD) = (head); \ + if (head) { \ + (head) = (XD_STRUCT_PTR)((head)->SCRATCH_PTR->PRIVATE); \ + if ((head) == NULL) { \ + (tail) = NULL; \ + } /* Endif */ \ + } /* Endif */ + +#define EHCI_DTD_QADD(head,tail,dTD) \ + if ((head) == NULL) { \ + (head) = (dTD); \ + } else { \ + (tail)->SCRATCH_PTR->PRIVATE = (void *) (dTD); \ + } /* Endif */ \ + (tail) = (dTD); \ + (dTD)->SCRATCH_PTR->PRIVATE = NULL + +#define EHCI_DTD_QGET(head,tail,dTD) \ + (dTD) = (head); \ + if (head) { \ + (head) = (head)->SCRATCH_PTR->PRIVATE; \ + if ((head) == NULL) { \ + (tail) = NULL; \ + } /* Endif */ \ + } /* Endif */ + +/*************************************** +** +** Data structures +** +*/ + +typedef struct +{ + uint_32 usb_isr_count; + uint_32 usb_reset_count; + uint_32 usb_send_count; + uint_32 usb_recv_count; + uint_32 usb_setup_count; + uint_32 free_XD_count; + uint_32 free_dTD_count; + uint_32 usb_cancel_count; + uint_32 usb_add_count; + uint_32 usb_add_not_empty_count; + uint_32 usb_empty_isr_count; + uint_32 usb_empty_complete_count; + uint_32 usb_read_setup_count; + uint_32 usb_complete_isr_count; + uint_32 usb_complete_count; + uint_32 usb_complete_max_count; + uint_32 usb_port_change_count; + uint_32 usb_suspend_count; + uint_32 usb_complete_ep_count[ARC_USB_MAX_ENDPOINTS*2]; + +} USB_STATS; + + + +/* Callback function storage structure */ +typedef struct service_struct +{ + uint_8 TYPE; + void (_CODE_PTR_ SERVICE)(pointer, uint_8, boolean, uint_8, uint_8_ptr, uint_32, uint_8); + struct service_struct _PTR_ NEXT; + +} SERVICE_STRUCT, _PTR_ SERVICE_STRUCT_PTR; + +typedef struct xd_struct +{ + uint_8 EP_NUM; /* Endpoint number */ + uint_8 BDIRECTION; /* Direction : Send/Receive */ + uint_8 EP_TYPE; /* Type of the endpoint: Ctrl, Isoch, Bulk, Int */ + uint_8 BSTATUS; /* Current transfer status */ + uint_8_ptr WSTARTADDRESS; /* Address of first byte */ + uint_32 WTOTALLENGTH; /* Number of bytes to send/recv */ + uint_32 WSOFAR; /* Number of bytes recv'd so far */ + uint_16 WMAXPACKETSIZE; /* Max Packet size */ + boolean DONT_ZERO_TERMINATE; + uint_8 MAX_PKTS_PER_UFRAME; + SCRATCH_STRUCT *SCRATCH_PTR; +} XD_STRUCT, _PTR_ XD_STRUCT_PTR; + +/* The USB Device State Structure */ +typedef struct +{ + boolean BUS_RESETTING; /* Device is + ** being reset */ + volatile VUSB20_REG_STRUCT_PTR CAP_REGS_PTR; /* Capabilities registers */ + + volatile VUSB20_REG_STRUCT_PTR DEV_PTR; /* Device Controller + ** Register base + ** address */ + + SERVICE_STRUCT_PTR SERVICE_HEAD_PTR; /* Head struct + ** address of + ** registered services + */ + XD_STRUCT_PTR TEMP_XD_PTR; /* Temp xd for ep init */ + XD_STRUCT_PTR XD_BASE; + XD_STRUCT_PTR XD_HEAD; /* Head Transaction + ** descriptors + */ + XD_STRUCT_PTR XD_TAIL; /* Tail Transaction + ** descriptors + */ + uint_32 XD_ENTRIES; + uint_8* EP_QUEUE_HEAD_BASE; + uint_32 EP_QUEUE_HEAD_PHYS; + uint_32 EP_QUEUE_HEAD_SIZE; + VUSB20_EP_QUEUE_HEAD_STRUCT_PTR EP_QUEUE_HEAD_PTR; /* Endpoint Queue head */ + + uint_8* DTD_BASE_PTR; /* Device transfer descriptor pool address */ + uint_32 DTD_BASE_PHYS; + uint_32 DTD_SIZE; + VUSB20_EP_TR_STRUCT_PTR DTD_ALIGNED_BASE_PTR;/* Aligned transfer descriptor pool address */ + + VUSB20_EP_TR_STRUCT_PTR DTD_HEAD; + VUSB20_EP_TR_STRUCT_PTR DTD_TAIL; + VUSB20_EP_TR_STRUCT_PTR EP_DTD_HEADS[ARC_USB_MAX_ENDPOINTS * 2]; + VUSB20_EP_TR_STRUCT_PTR EP_DTD_TAILS[ARC_USB_MAX_ENDPOINTS * 2]; + SCRATCH_STRUCT_PTR XD_SCRATCH_STRUCT_BASE; + + + SCRATCH_STRUCT_PTR SCRATCH_STRUCT_BASE; + + uint_16 USB_STATE; + uint_16 USB_DEVICE_STATE; + uint_16 USB_SOF_COUNT; + uint_16 DTD_ENTRIES; + uint_16 ERRORS; + uint_16 ERROR_STATE; + uint_16 USB_DEV_STATE_B4_SUSPEND; + uint_8 DEV_NUM; /* USB device number + ** on the board + */ + uint_8 SPEED; /* Low Speed, + ** High Speed, + ** Full Speed + */ + uint_8 MAX_ENDPOINTS; /* Max endpoints + ** supported by this + ** device + */ + + uint_8 USB_CURR_CONFIG; + uint_8 DEVICE_ADDRESS; + uint_8 FORCE_FS; + USB_STATS STATS; + + uint_8* STATUS_UNAIGNED_PTR; + uint_16* STATUS_PTR; + + uint_8* TEST_PKT_UNAIGNED_PTR; + uint_8* TEST_PKT_PTR; + +} USB_DEV_STATE_STRUCT, _PTR_ USB_DEV_STATE_STRUCT_PTR; + +/* ONLY For data bases allocated by the driver (when PHYS and VIRT bases are known) */ +#define USB_EP_QH_VIRT_TO_PHYS(handle, virtAddr) \ + (((virtAddr) == NULL) ? 0 : ((handle)->EP_QUEUE_HEAD_PHYS + \ + ((uint_32)(virtAddr) - (uint_32)(handle)->EP_QUEUE_HEAD_BASE))) + +#define USB_DTD_VIRT_TO_PHYS(handle, virtAddr) \ + (((virtAddr) == NULL) ? 0 : ((handle)->DTD_BASE_PHYS + \ + ((uint_32)(virtAddr) - (uint_32)(handle)->DTD_BASE_PTR))) + +#define USB_DTD_PHYS_TO_VIRT(handle, physAddr) \ + (((physAddr) == 0) ? NULL : ((handle)->DTD_BASE_PTR + \ + ((physAddr) - (handle)->DTD_BASE_PHYS))) + + +/*************************************** +** +** Prototypes +** +*/ +#ifdef __cplusplus +extern "C" { +#endif + +extern uint_8 _usb_device_call_service(void* handle, uint_8, boolean, + boolean, uint_8_ptr, uint_32, uint_8); + +extern uint_8 _usb_dci_vusb20_init(uint_8, _usb_device_handle); +extern void _usb_device_free_XD(pointer); +extern void _usb_dci_vusb20_free_dTD(pointer); +extern uint_8 _usb_dci_vusb20_add_dTD(_usb_device_handle, XD_STRUCT_PTR); +extern uint_8 _usb_dci_vusb20_cancel_transfer(_usb_device_handle, uint_8, uint_8); +extern uint_8 _usb_dci_vusb20_get_transfer_status(_usb_device_handle, uint_8, uint_8); +extern XD_STRUCT_PTR _usb_dci_vusb20_get_transfer_details(_usb_device_handle, uint_8, uint_8); +extern void _usb_dci_vusb20_process_tr_complete(_usb_device_handle); +extern void _usb_dci_vusb20_process_reset(_usb_device_handle); +extern void _usb_dci_vusb20_process_tr_complete(_usb_device_handle); +extern void _usb_dci_vusb20_process_suspend(_usb_device_handle); +extern void _usb_dci_vusb20_process_SOF(_usb_device_handle); +extern void _usb_dci_vusb20_process_port_change(_usb_device_handle); +extern void _usb_dci_vusb20_process_error(_usb_device_handle); +extern void _usb_dci_vusb20_shutdown(_usb_device_handle); +extern void _usb_dci_vusb20_set_speed_full(_usb_device_handle, uint_8); +extern void _usb_dci_vusb20_suspend_phy(_usb_device_handle, uint_8); +extern void _usb_dci_vusb20_hnp_shutdown(void); +extern void _usb_dci_vusb20_set_address(_usb_device_handle, uint_8); +extern void _usb_dci_vusb20_get_setup_data(_usb_device_handle, uint_8, uint_8_ptr); +extern void _usb_dci_vusb20_assert_resume(_usb_device_handle); +extern uint_8 _usb_dci_vusb20_init_endpoint(_usb_device_handle, XD_STRUCT_PTR); +extern void _usb_dci_vusb20_stall_endpoint(_usb_device_handle, uint_8, uint_8); +extern void _usb_dci_vusb20_unstall_endpoint(_usb_device_handle, uint_8, uint_8); +extern uint_8 _usb_dci_vusb20_is_endpoint_stalled(_usb_device_handle, uint_8, uint_8); +extern uint_8 _usb_dci_vusb20_deinit_endpoint(_usb_device_handle, uint_8, uint_8); +extern void _usb_dci_vusb20_chip_initialize(_usb_device_handle); +extern void _usb_dci_vusb20_stop(_usb_device_handle handle); +extern void _usb_dci_vusb20_start(_usb_device_handle handle); + +#if defined(USB_UNDERRUN_WA) + +extern uint_8* usbSramBase; +extern int usbSramSize; + +void _usb_reset_send_queue(void); +void usbSendComplete(void* handle, uint_8 type, boolean setup, uint_8 dir, + uint_8_ptr buffer, uint_32 length, uint_8 error); +#endif /* USB_UNDERRUN_WA */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbDevRecv.c b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevRecv.c new file mode 100644 index 0000000..25ddc68 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevRecv.c @@ -0,0 +1,99 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#include "mvUsbDevApi.h" +#include "mvUsbDevPrv.h" + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_recv_data +* Returned Value : USB_OK or error code +* Comments : +* Receives data on a specified endpoint. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_recv_data + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] buffer to receive data */ + uint_8_ptr buff_ptr, + + /* [IN] length of the transfer */ + uint_32 size + ) +{ /* Body */ + int lockKey; + uint_8 error = USB_OK; + XD_STRUCT_PTR xd_ptr; + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RX, "recv_data: ep=%d, buf_ptr=0x%x, size=%d\n", + ep_num, (unsigned)buff_ptr, (int)size); + + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_recv_count++)); + + if(buff_ptr != NULL) + USB_dcache_inv((pointer)buff_ptr,size); + + lockKey = USB_lock(); + + if (!usb_dev_ptr->XD_ENTRIES) + { + USB_unlock(lockKey); + USB_printf("_usb_device_recv_data, transfer in progress\n"); + return ARC_USB_STATUS_TRANSFER_IN_PROGRESS; + } /* Endif */ + + /* Get a transfer descriptor for the specified endpoint + ** and direction + */ + USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr); + + usb_dev_ptr->XD_ENTRIES--; + + /* Initialize the new transfer descriptor */ + xd_ptr->EP_NUM = ep_num; + xd_ptr->BDIRECTION = ARC_USB_RECV; + xd_ptr->WTOTALLENGTH = size; + xd_ptr->WSOFAR = 0; + xd_ptr->WSTARTADDRESS = buff_ptr; + + xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED; + + error = _usb_dci_vusb20_add_dTD(handle, xd_ptr); + + USB_unlock(lockKey); + + if (error) + { + USB_printf("_usb_device_recv_data, receive failed\n"); + return USBERR_RX_FAILED; + } /* Endif */ + + return error; + +} /* EndBody */ diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbDevSend.c b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevSend.c new file mode 100644 index 0000000..7fca8a0 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevSend.c @@ -0,0 +1,373 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#include "mvUsbDevApi.h" +#include "mvUsbDevPrv.h" + +#if defined(USB_UNDERRUN_WA) + +typedef struct +{ + uint_8* buff_ptr[MAX_XDS_FOR_TR_CALLS]; + uint_32 size[MAX_XDS_FOR_TR_CALLS]; + uint_8 ep_num[MAX_XDS_FOR_TR_CALLS]; + int head; + int tail; + int tail_dma; + int num; + int num_dma; + +} USB_SEND_QUEUE; + +uint_8* usbSramBase; +int usbSramSize; +int usbSramPartSize; +USB_SEND_QUEUE usbSendQueue; + +uint_32 usbSentSize = 0; +uint_32 usbDmaSize = 0; + +#define S_FREE 0 +#define S_BUSY 1 + +uint_32 dma_index = 0; +uint_32 sent_index = 0; +uint_32 sram_parts[USB_SRAM_MAX_PARTS]; + + +void _usb_reset_send_queue(void) +{ + int i; + + usbSendQueue.num = 0; + usbSendQueue.num_dma = 0; + usbSendQueue.head = 0; + usbSendQueue.tail = 0; + usbSendQueue.tail_dma = 0; + for(i=0; i= usbSendQueue.size[tail_dma]) + { + /* Remove from the usbSendQueues */ + num_dma--; + tail_dma++; + if(tail_dma == MAX_XDS_FOR_TR_CALLS) + tail_dma = 0; + + usbSendQueue.tail_dma = tail_dma; + usbSendQueue.num_dma = num_dma; + usbDmaSize = 0; + + if(num_dma == 0) + break; + } + + buff_ptr = usbSendQueue.buff_ptr[tail_dma] + usbDmaSize; + size = MIN(usbSramPartSize, (usbSendQueue.size[tail_dma] - usbDmaSize) ); + + usbDmaSize += size; + + if(size > global_wa_threshold) + { + tmp_buff = buff_ptr; + buff_ptr = (uint_8*)((int)usbSramBase + (dma_index * usbSramPartSize)); + USB_idma_copy(buff_ptr, tmp_buff, size); + + sram_parts[dma_index] = S_BUSY; + dma_index++; + if(dma_index == global_wa_sram_parts) + dma_index = 0; + } + + + /* Get a transfer descriptor */ + USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr); + + usb_dev_ptr->XD_ENTRIES--; + USB_dcache_flush((pointer)buff_ptr, size); + + /* Initialize the new transfer descriptor */ + xd_ptr->EP_NUM = usbSendQueue.ep_num[tail_dma]; + xd_ptr->BDIRECTION = ARC_USB_SEND; + xd_ptr->WTOTALLENGTH = size; + xd_ptr->WSOFAR = 0; + xd_ptr->WSTARTADDRESS = buff_ptr; + xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED; + + error = _usb_dci_vusb20_add_dTD(handle, xd_ptr); + + if(error) + break; + } + + return error; +} + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : usbSendComplete +* Returned Value : None +* Comments : +* Callback for send transfer complete event. +* +*END*-----------------------------------------------------------------*/ +void usbSendComplete(void* handle, uint_8 type, boolean setup, uint_8 dir, + uint_8_ptr buffer, uint_32 length, uint_8 error) +{ + /* Check if this complete is one from the sendQueue */ + if( (usbSendQueue.ep_num[usbSendQueue.tail] == type) && + (usbSendQueue.num > 0) ) + { + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + uint_8* buff_ptr; + uint_32 size; + int num, tail; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + tail = usbSendQueue.tail; + num = usbSendQueue.num; + buff_ptr = usbSendQueue.buff_ptr[tail]; + size = usbSendQueue.size[tail]; +/* + USB_printf("usbSendComplete: num=%d, tail=%d, usbSentSize=%d, type=%d, length=%d (%d), buff=%p (%p)\n", + num, tail, usbSentSize, type, length, usbSendQueue.size[tail], + buffer, usbSendQueue.buff_ptr[tail]); +*/ + usbSentSize += length; + + /* if the buffer was on the SRAM */ + if( ((unsigned)buffer >= (unsigned)usbSramBase) && + ((unsigned)buffer < ((unsigned)usbSramBase + (usbSramPartSize * global_wa_sram_parts))) ) + { + sram_parts[sent_index] = S_FREE; + sent_index++; + if(sent_index == global_wa_sram_parts) + sent_index = 0; + } + + if(usbSentSize >= usbSendQueue.size[tail]) + { + /* Remove from the usbSendQueues */ + num--; + tail++; + if(tail == MAX_XDS_FOR_TR_CALLS) + tail = 0; + + usbSendQueue.tail = tail; + usbSendQueue.num = num; + usbSentSize = 0; + + /* Call complete callback */ + _usb_device_call_service(handle, type, setup, dir, + buff_ptr, size, error); + + if(num == 0) + return; + } + + error = _usb_prepare_to_send(handle); + if (error) + { + USB_printf("usbSendComplete, add_dTD failed\n"); + } + + } + else + { + /* Call complete callback */ + _usb_device_call_service(handle, type, setup, dir, + buffer, length, error); + } +} +#endif /* USB_UNDERRUN_WA */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_send_data +* Returned Value : USB_OK or error code +* Comments : +* Sends data on a specified endpoint. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_send_data + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] buffer to send */ + uint_8_ptr buff_ptr, + + /* [IN] length of the transfer */ + uint_32 size + ) +{ /* Body */ + int lockKey; + uint_8 error = 0; + XD_STRUCT_PTR xd_ptr; + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + boolean toSend = TRUE; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TX, + "send_data: handle=%p, ep=%d, pBuf=0x%x, size=%d, EP_QH=%p\n", + handle, ep_num, (unsigned)buff_ptr, (int)size, usb_dev_ptr->EP_QUEUE_HEAD_PTR); + + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_send_count++)); + + lockKey = USB_lock(); + + if (!usb_dev_ptr->XD_ENTRIES) + { + USB_unlock(lockKey); + USB_printf("_usb_device_send_data, transfer in progress\n"); + return ARC_USB_STATUS_TRANSFER_IN_PROGRESS; + } /* Endif */ + +#if defined(USB_UNDERRUN_WA) + { + int head; + VUSB20_EP_QUEUE_HEAD_STRUCT* ep_queue_head_ptr; + + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + + 2*ep_num + ARC_USB_SEND; + + if( ((ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF) > global_wa_threshold) + { + /* Only Endpoints with maxPktSize more than 128 bytes need special processing */ + if( (size > global_wa_threshold) || + (usbSendQueue.num != 0) ) + { +/* + USB_printf("_usb_device_send_data: ep_num=%d, maxPktSize=%d, size=%d\n", + ep_num, (ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF, size); +*/ + /* Check if usbSendQueue is not Full */ + if(usbSendQueue.num == MAX_XDS_FOR_TR_CALLS) + { + USB_printf("ep=%d: usbSendQueue is FULL\n", ep_num); + USB_unlock(lockKey); + return USBERR_TX_FAILED; + } + + /* Add to usbSendQueu */ + head = usbSendQueue.head; + + usbSendQueue.num++; + usbSendQueue.num_dma++; + usbSendQueue.size[head] = size; + usbSendQueue.buff_ptr[head] = buff_ptr; + usbSendQueue.ep_num[head] = ep_num; + + head++; + if(head == MAX_XDS_FOR_TR_CALLS) + head = 0; + + usbSendQueue.head = head; + + /* Process first usbSendQueue element if possible */ + if(usbSendQueue.num == 1) + { + error = _usb_prepare_to_send(handle); + } + toSend = FALSE; + } + } + } +#endif /* USB_UNDERRUN_WA */ + + if(toSend == TRUE) + { + /* Get a transfer descriptor */ + USB_XD_QGET(usb_dev_ptr->XD_HEAD, usb_dev_ptr->XD_TAIL, xd_ptr); + + usb_dev_ptr->XD_ENTRIES--; + + if(buff_ptr != NULL) + USB_dcache_flush((pointer)buff_ptr, size); + + /* Initialize the new transfer descriptor */ + xd_ptr->EP_NUM = ep_num; + xd_ptr->BDIRECTION = ARC_USB_SEND; + xd_ptr->WTOTALLENGTH = size; + xd_ptr->WSOFAR = 0; + xd_ptr->WSTARTADDRESS = buff_ptr; + xd_ptr->BSTATUS = ARC_USB_STATUS_TRANSFER_ACCEPTED; + + error = _usb_dci_vusb20_add_dTD(handle, xd_ptr); + } + USB_unlock(lockKey); + + if (error) + { + USB_printf("_usb_device_send_data, transfer failed\n"); + return USBERR_TX_FAILED; + } /* Endif */ + return error; + +} /* EndBody */ + diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbDevUtl.c b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevUtl.c new file mode 100644 index 0000000..75201fa --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbDevUtl.c @@ -0,0 +1,634 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#include "mvUsbDevApi.h" +#include "mvUsbDevPrv.h" + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_unstall_endpoint +* Returned Value : USB_OK or error code +* Comments : +* Unstalls the endpoint in specified direction +* +*END*-----------------------------------------------------------------*/ +void _usb_device_unstall_endpoint + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + lockKey = USB_lock(); + + _usb_dci_vusb20_unstall_endpoint(handle, ep_num, direction); + + USB_unlock(lockKey); + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _usb_device_get_status +* Returned Value : USB_OK or error code +* Comments : +* Provides API to access the USB internal state. +* +*END*--------------------------------------------------------------------*/ +uint_8 _usb_device_get_status + ( + /* [IN] Handle to the USB device */ + _usb_device_handle handle, + + /* [IN] What to get the status of */ + uint_8 component, + + /* [OUT] The requested status */ + uint_16_ptr status + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + lockKey = USB_lock(); + + switch (component) + { + case ARC_USB_STATUS_DEVICE_STATE: + *status = usb_dev_ptr->USB_STATE; + break; + + case ARC_USB_STATUS_DEVICE: + *status = usb_dev_ptr->USB_DEVICE_STATE; + break; + + case ARC_USB_STATUS_INTERFACE: + *status = 0; + break; + + case ARC_USB_STATUS_ADDRESS: + *status = usb_dev_ptr->DEVICE_ADDRESS; + break; + + case ARC_USB_STATUS_CURRENT_CONFIG: + *status = usb_dev_ptr->USB_CURR_CONFIG; + break; + + case ARC_USB_STATUS_SOF_COUNT: + *status = usb_dev_ptr->USB_SOF_COUNT; + break; + + default: + USB_unlock(lockKey); + USB_printf("_usb_device_get_status, bad status\n"); + return USBERR_BAD_STATUS; + + } /* Endswitch */ + USB_unlock(lockKey); + + return USB_OK; +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _usb_device_set_status +* Returned Value : USB_OK or error code +* Comments : +* Provides API to set internal state +* +*END*--------------------------------------------------------------------*/ +uint_8 _usb_device_set_status + ( + /* [IN] Handle to the usb device */ + _usb_device_handle handle, + + /* [IN] What to set the status of */ + uint_8 component, + + /* [IN] What to set the status to */ + uint_16 setting + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + int lockKey; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STATUS, + "set_status: component=0x%x, value=0x%x\n", component, setting); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + lockKey = USB_lock(); + + switch (component) + { + case ARC_USB_STATUS_DEVICE_STATE: + usb_dev_ptr->USB_STATE = setting; + break; + + case ARC_USB_STATUS_DEVICE: + usb_dev_ptr->USB_DEVICE_STATE = setting; + break; + + case ARC_USB_STATUS_INTERFACE: + break; + + case ARC_USB_STATUS_CURRENT_CONFIG: + usb_dev_ptr->USB_CURR_CONFIG = setting; + break; + + case ARC_USB_STATUS_SOF_COUNT: + usb_dev_ptr->USB_SOF_COUNT = setting; + break; + + case ARC_USB_FORCE_FULL_SPEED: + _usb_dci_vusb20_set_speed_full((pointer)usb_dev_ptr, setting); + break; + + case ARC_USB_PHY_LOW_POWER_SUSPEND: + _usb_dci_vusb20_suspend_phy((pointer)usb_dev_ptr, setting); + break; + + case ARC_USB_STATUS_ADDRESS: + usb_dev_ptr->DEVICE_ADDRESS = setting; + + _usb_dci_vusb20_set_address((pointer)usb_dev_ptr, setting); + break; + + case ARC_USB_STATUS_TEST_MODE: + _usb_dci_vusb20_set_test_mode(handle, setting); + break; + + default: + USB_unlock(lockKey); + USB_printf("_usb_device_set_status, bad status\n"); + return USBERR_BAD_STATUS; + + } /* Endswitch */ + + USB_unlock(lockKey); + + return USB_OK; +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_stall_endpoint +* Returned Value : USB_OK or error code +* Comments : +* Stalls the endpoint. +* +*END*-----------------------------------------------------------------*/ +void _usb_device_stall_endpoint + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + lockKey = USB_lock(); + + _usb_dci_vusb20_stall_endpoint(handle, ep_num, direction); + + USB_unlock(lockKey); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_is_endpoint_stalled +* Returned Value : USB_OK or error code +* Comments : +* Stalls the endpoint. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_device_is_endpoint_stalled + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + uint_8 val; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + lockKey = USB_lock(); + + val = _usb_dci_vusb20_is_endpoint_stalled(handle, ep_num, direction); + + USB_unlock(lockKey); + + return val; + +} /* EndBody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_device_process_resume +* Returned Value : USB_OK or error code +* Comments : +* Process Resume event +* +*END*-----------------------------------------------------------------*/ +void _usb_device_assert_resume + ( + /* [IN] the USB_USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + _usb_dci_vusb20_assert_resume(handle); + +} /* EndBody */ + + +/***************************/ +/* ARC USB Debug functions */ +/***************************/ +void _usb_status(void* usbHandle) +{ + USB_DEV_STATE_STRUCT* pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle; + + if(pUsbDev == NULL) + { + USB_printf("USB Device core is not initialized\n"); + return; + } + + USB_printf("\n\tUSB Status\n\n"); + + USB_printf("DEV_NUM=%d, DEV_ADDR=%d, CAP_REGS=0x%x, DEV_REGS=0x%x, MAX_EP=%d\n", + pUsbDev->DEV_NUM, + pUsbDev->DEVICE_ADDRESS, + (unsigned)pUsbDev->CAP_REGS_PTR, + (unsigned)pUsbDev->DEV_PTR, + pUsbDev->MAX_ENDPOINTS); + + USB_printf("BUS_RESET=%s, USB_STATE=0x%02x, USB_DEV_STATE=0x%02x, SPEED=%d, ERRORS=0x%04x\n", + pUsbDev->BUS_RESETTING ? "Yes" : "No", + pUsbDev->USB_STATE, + pUsbDev->USB_DEVICE_STATE, + pUsbDev->SPEED, + pUsbDev->ERRORS); + + USB_printf("EP_QUEUE_HEAD: SIZE=%d, BASE=%p (0x%08x), ALIGNED=%p, SERVICE_HEAD=%p\n", + pUsbDev->EP_QUEUE_HEAD_SIZE, + pUsbDev->EP_QUEUE_HEAD_BASE, + pUsbDev->EP_QUEUE_HEAD_PHYS, + pUsbDev->EP_QUEUE_HEAD_PTR, + pUsbDev->SERVICE_HEAD_PTR); + + USB_printf("XD: BASE=%p, HEAD=%p, TAIL=%p, ENTRIES=%d, SCRATCH=%p, TEMP=%p\n", + pUsbDev->XD_BASE, + pUsbDev->XD_HEAD, + pUsbDev->XD_TAIL, + pUsbDev->XD_ENTRIES, + pUsbDev->XD_SCRATCH_STRUCT_BASE, + pUsbDev->TEMP_XD_PTR); + + USB_printf("DTD: SIZE=%d, BASE=%p (0x%08x), ALIGNED=%p, HEAD=0x%08x, TAIL=0x%08x, ENTRIES=%d, SCRATCH=%p\n", + pUsbDev->DTD_SIZE, + pUsbDev->DTD_BASE_PTR, + pUsbDev->DTD_BASE_PHYS, + pUsbDev->DTD_ALIGNED_BASE_PTR, + pUsbDev->DTD_HEAD, + pUsbDev->DTD_TAIL, + pUsbDev->DTD_ENTRIES, + pUsbDev->SCRATCH_STRUCT_BASE); +} + +void _usb_stats(void* usbHandle) +{ + USB_DEV_STATE_STRUCT* pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle; + USB_STATS* pUsbStats = &pUsbDev->STATS; + int i; + + USB_printf("\n\tUSB Statistics\n\n"); + + USB_printf("isr=%u, empty_isr=%u, reset=%u, setup=%u, read_setup=%u\n", + pUsbStats->usb_isr_count, pUsbStats->usb_empty_isr_count, + pUsbStats->usb_reset_count, pUsbStats->usb_setup_count, + pUsbStats->usb_read_setup_count); + + USB_printf("recv=%u, send=%u, add=%u (%u), cancel=%u\n", + pUsbStats->usb_recv_count, pUsbStats->usb_send_count, + pUsbStats->usb_add_count, pUsbStats->usb_add_not_empty_count, + pUsbStats->usb_cancel_count); + + USB_printf("free_XD=%u, free_dTD=%u\n", + pUsbStats->free_XD_count, pUsbStats->free_dTD_count); + + USB_printf("complete_isr=%u, complete=%u, empty_complete=%u, max_complete=%u\n", + pUsbStats->usb_complete_isr_count, pUsbStats->usb_complete_count, + pUsbStats->usb_empty_complete_count, pUsbStats->usb_complete_max_count); + + USB_printf("port_change=%u, suspend=%u\n", + pUsbStats->usb_port_change_count, pUsbStats->usb_suspend_count); + for(i=0; i<(pUsbDev->MAX_ENDPOINTS); i++) + { + if( (pUsbStats->usb_complete_ep_count[i*2] == 0) && + (pUsbStats->usb_complete_ep_count[i*2+1] == 0) ) + continue; + + USB_printf("EP #%d: RECV (OUT) = %3u, \tSEND (IN) = %u\n", i, + pUsbStats->usb_complete_ep_count[i*2], + pUsbStats->usb_complete_ep_count[i*2+1]); + } + USB_printf("\n"); +} + +void _usb_clear_stats(void* usbHandle) +{ + USB_DEV_STATE_STRUCT* pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle; + + USB_memzero(&pUsbDev->STATS, sizeof(pUsbDev->STATS)); +} + +void _usb_regs(void* usbHandle) +{ + USB_DEV_STATE_STRUCT* pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle; + VUSB20_REG_STRUCT* cap_regs, *dev_regs; + int dev_num; + + if(pUsbDev == NULL) + { + USB_printf("USB Device core is not initialized\n"); + return; + } + USB_printf("\n\tUSB Capability Registers\n\n"); + + cap_regs = pUsbDev->CAP_REGS_PTR; + USB_printf("CAPLENGTH_HCIVER (0x%08x) = 0x%08x\n", + (unsigned)&cap_regs->REGISTERS.CAPABILITY_REGISTERS.CAPLENGTH_HCIVER, + (unsigned)USB_32BIT_LE(cap_regs->REGISTERS.CAPABILITY_REGISTERS.CAPLENGTH_HCIVER)); + + USB_printf("DCI_VERSION (0x%08x) = 0x%08x\n", + (unsigned)&cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCI_VERSION, + (unsigned)USB_32BIT_LE(cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCI_VERSION)); + + USB_printf("DCC_PARAMS (0x%08x) = 0x%08x\n", + (unsigned)&cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCC_PARAMS, + (unsigned)USB_32BIT_LE(cap_regs->REGISTERS.CAPABILITY_REGISTERS.DCC_PARAMS)); + + dev_regs = pUsbDev->DEV_PTR; + dev_num = pUsbDev->DEV_NUM; + USB_printf("\n\tUSB Device Operational Registers\n\n"); + + USB_printf("USB_CMD (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD)); + + USB_printf("USB_STS (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS)); + + USB_printf("USB_INTR (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR)); + + USB_printf("USB_FRINDEX (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX)); + + /* Skip CTRLDSSEGMENT register */ + USB_printf("DEVICE_ADDR (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR)); + + USB_printf("EP_LIST_ADDR (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.EP_LIST_ADDR, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.EP_LIST_ADDR)); + + /* Skip CONFIG_FLAG register */ + + /* Skip PORTSCX[0..15] registers*/ + USB_printf("PORTSCX[0] (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0], + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0])); + + /* Skip OTGSC register */ + + USB_printf("USB_MODE (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_MODE, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_MODE)); + + USB_printf("ENDPT_SETUP_STAT (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT)); + + USB_printf("ENDPTPRIME (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME)); + + USB_printf("ENDPTFLUSH (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH)); + + USB_printf("ENDPTSTATUS (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS)); + + USB_printf("ENDPTCOMPLETE (0x%08x) = 0x%08x\n", + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE, + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE)); +} + + +void _usb_ep_status(void* usbHandle, int ep_num, int direction) +{ + USB_DEV_STATE_STRUCT* pUsbDev = (USB_DEV_STATE_STRUCT*)usbHandle; + int i, ep_idx; + VUSB20_EP_QUEUE_HEAD_STRUCT_PTR ep_queue_head_ptr; + VUSB20_EP_TR_STRUCT_PTR dTD_ptr, head_dTD_ptr, tail_dTD_ptr, next_dTD_ptr; + XD_STRUCT_PTR xd_ptr, next_xd_ptr; + VUSB20_REG_STRUCT_PTR dev_regs; + + if(pUsbDev == NULL) + { + USB_printf("USB Device core is not initialized\n"); + return; + } + + USB_printf("\n\tUSB Endpoint #%d - %s status\n\n", ep_num, + (direction == ARC_USB_SEND) ? "SEND (IN)" : "RECV (OUT)" ); + + ep_idx = ep_num*2 + direction; + dev_regs = pUsbDev->DEV_PTR; + + USB_printf("ENDPTCTRLX[%d] (0x%08x) = 0x%08x\n", ep_num, + (unsigned)&dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num], + (unsigned)USB_32BIT_LE(dev_regs->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num])); + + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)pUsbDev->EP_QUEUE_HEAD_PTR + ep_idx; + + head_dTD_ptr = pUsbDev->EP_DTD_HEADS[ep_idx]; + tail_dTD_ptr = pUsbDev->EP_DTD_TAILS[ep_idx]; + + USB_printf("EP_QH=0x%08x: MAX_PKT=0x%x, SIZE_IOC_INT_STS=0x%x, CURR_DTD=0x%x, NEXT_DTD=0x%x\n", + (unsigned)ep_queue_head_ptr, (unsigned)USB_32BIT_LE(ep_queue_head_ptr->MAX_PKT_LENGTH), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->CURR_DTD_PTR), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->NEXT_DTD_PTR)); + + USB_printf("\tBUF_0=0x%08x, BUF_1=0x%08x, BUF_2=0x%08x, BUF_3=0x%08x, BUF_4=0x%08x\n", + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR0), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR1), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR2), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR3), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->BUFF_PTR4)); + + USB_printf("\tSETUP_BUFFER (%p): ", ep_queue_head_ptr->SETUP_BUFFER); + for(i=0; iSETUP_BUFFER); i++) + USB_printf("%02x", ep_queue_head_ptr->SETUP_BUFFER[i] & 0xFF); + USB_printf("\n"); + + USB_printf("\ndTD_HEAD=0x%08x, dTD_TAIL=0x%08x\n", + (unsigned)head_dTD_ptr, (unsigned)tail_dTD_ptr); + + dTD_ptr = head_dTD_ptr; + i = 0; + while(dTD_ptr != NULL) + { + USB_printf("%d. dTD=0x%08x (0x%08x), SIZE_IOC_STS=0x%08x, BUF_0=0x%08x, NEXT=0x%08x\n", + i, (unsigned)dTD_ptr, USB_DTD_VIRT_TO_PHYS(pUsbDev, dTD_ptr), + (unsigned)USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS), + (unsigned)USB_32BIT_LE(dTD_ptr->BUFF_PTR0), + (unsigned)USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR)); + + xd_ptr = dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD; + + next_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(pUsbDev, + (uint_32)(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK)); + if(next_dTD_ptr != NULL) + next_xd_ptr = next_dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD; + else + next_xd_ptr = NULL; + + if(next_xd_ptr != xd_ptr) + { + USB_printf("\tXD=0x%08x, ADDR=0x%08x, SIZE=%u, STATUS=0x%02x\n", + (unsigned)xd_ptr, (unsigned)xd_ptr->WSTARTADDRESS, + (unsigned)xd_ptr->WTOTALLENGTH, xd_ptr->BSTATUS); + } + i++; + dTD_ptr = next_dTD_ptr; + } +} + + +/* DEBUG */ +uint_32 usbDebugFlags = ARC_DEBUG_FLAG_STATS + | ARC_DEBUG_FLAG_INIT + | ARC_DEBUG_FLAG_ERROR + | ARC_DEBUG_FLAG_STALL + | ARC_DEBUG_FLAG_RESET; + /*| ARC_DEBUG_FLAG_TRANSFER;*/ + +void _usb_debug_set_flags(uint_32 flags) +{ + usbDebugFlags = (flags); +} + +uint_32 _usb_debug_get_flags(void) +{ + return usbDebugFlags; +} + +#if defined(MV_USB_TRACE_LOG) + +uint_16 DEBUG_TRACE_ARRAY_COUNTER = 0; +char DEBUG_TRACE_ARRAY[TRACE_ARRAY_SIZE][MAX_STRING_SIZE]; + +void _usb_debug_init_trace_log(void) +{ + USB_memzero(DEBUG_TRACE_ARRAY, TRACE_ARRAY_SIZE*MAX_STRING_SIZE); + DEBUG_TRACE_ARRAY_COUNTER =0; +} + +void _usb_debug_print_trace_log(void) +{ + int i; + + USB_printf("USB Trace log: start=0x%x, end=0x%x, idx=%d, flags=0x%x\n\n", + &DEBUG_TRACE_ARRAY[0][0], &DEBUG_TRACE_ARRAY[TRACE_ARRAY_SIZE-1][0], + DEBUG_TRACE_ARRAY_COUNTER, usbDebugFlags); + + for(i=DEBUG_TRACE_ARRAY_COUNTER; iDEV_PTR; + + bit_pos = (1 << (16 * direction + ep_num)); + temp = (2*ep_num + direction); + + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp; + + /* Unlink the dTD */ + dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[temp]; + + if (dTD_ptr) + { + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_cancel_count++)); + + check_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, + ((uint_32)USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK)); + + if (USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) + { + /* Flushing will halt the pipe */ + /* Write 1 to the Flush register */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(bit_pos); + + /* Wait until flushing completed */ + timeout = 0x1000000; + while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH) & bit_pos) + { + /* ENDPTFLUSH bit should be cleared to indicate this operation is complete */ + timeout--; + if(timeout == 0) + { + USB_printf("USB Cancel: - TIMEOUT for ENDPTFLUSH=0x%x, bit_pos=0x%x \n", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH), + (unsigned)bit_pos); + break; + } + } /* EndWhile */ + status_timeout = 0x100000; + while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos) + { + status_timeout--; + if(status_timeout == 0) + { + USB_printf("USB Cancel: - TIMEOUT for ENDPTSTATUS=0x%x, bit_pos=0x%x\n", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + (unsigned)bit_pos); + break; + } + + /* Write 1 to the Flush register */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(bit_pos); + + /* Wait until flushing completed */ + timeout = 0x1000000; + while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH) & bit_pos) + { + /* ENDPTFLUSH bit should be cleared to indicate this operation is complete */ + timeout--; + if(timeout == 0) + { + USB_printf("USB Cancel: - TIMEOUT for ENDPTFLUSH=0x%x, ENDPTSTATUS=0x%x, bit_pos=0x%x\n", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + (unsigned)bit_pos); + break; + } + } /* EndWhile */ + } /* EndWhile */ + } /* Endif */ + + /* Retire the current dTD */ + dTD_ptr->SIZE_IOC_STS = 0; + dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(VUSBHS_TD_NEXT_TERMINATE); + + /* The transfer descriptor for this dTD */ + xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD; + dTD_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER, + "cncl_%d: fri=0x%x, ep=%d%s, buf=%p, size=%d, xd=%p, dTD=%p %p, bit=0x%x\n", + usb_dev_ptr->STATS.usb_cancel_count & 0xFFFF, + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), + ep_num, direction ? "in" : "out", + xd_ptr->WSTARTADDRESS, xd_ptr->WTOTALLENGTH, xd_ptr, + dTD_ptr, check_dTD_ptr, bit_pos); + + /* Free the dTD */ + _usb_dci_vusb20_free_dTD((pointer)dTD_ptr); + + /* Update the dTD head and tail for specific endpoint/direction */ + if (!check_dTD_ptr) + { + usb_dev_ptr->EP_DTD_HEADS[temp] = NULL; + usb_dev_ptr->EP_DTD_TAILS[temp] = NULL; + if (xd_ptr) + { + xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; + /* Free the transfer descriptor */ + _usb_device_free_XD((pointer)xd_ptr); + } /* Endif */ + /* No other transfers on the queue */ + ep_queue_head_ptr->NEXT_DTD_PTR = USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE); + ep_queue_head_ptr->SIZE_IOC_INT_STS = 0; + } + else + { + usb_dev_ptr->EP_DTD_HEADS[temp] = check_dTD_ptr; + + if (xd_ptr) + { + if ((uint_32)check_dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD != (uint_32)xd_ptr) + { + xd_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; + /* Free the transfer descriptor */ + _usb_device_free_XD((pointer)xd_ptr); + } /* Endif */ + } /* Endif */ + + if (USB_32BIT_LE(check_dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) + { + /* Start CR 1015 */ + /* Prime the Endpoint */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos); + + if (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos)) + { + timeout = 0x100000; + while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & bit_pos) + { + /* Wait for the ENDPTPRIME to go to zero */ + timeout--; + if(timeout == 0) + { + USB_printf("USB Cancel: - TIMEOUT for ENDPTPRIME=0x%x, bit_pos=0x%x\n", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), + (unsigned)bit_pos); + break; + } + } /* EndWhile */ + + if (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos) + { + /* The endpoint was not not primed so no other transfers on + ** the queue + */ + goto done; + } /* Endif */ + } + else + { + goto done; + } /* Endif */ + + /* No other transfers on the queue */ + ep_queue_head_ptr->NEXT_DTD_PTR = (uint_32)USB_32BIT_LE((uint_32)check_dTD_ptr); + ep_queue_head_ptr->SIZE_IOC_INT_STS = 0; + + /* Prime the Endpoint */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos); + } /* Endif */ + } /* Endif */ + } /* Endif */ + +done: + + /* End CR 1015 */ + return USB_OK; +} /* EndBody */ + +/* EOF */ diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevMain.c b/board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevMain.c new file mode 100644 index 0000000..928d108 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevMain.c @@ -0,0 +1,1864 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#include "mvUsbDevApi.h" +#include "mvUsbDevPrv.h" + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_init +* Returned Value : USB_OK or error code +* Comments : +* Initializes the USB device controller. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_dci_vusb20_init + ( + /* [IN] the USB device controller to initialize */ + uint_8 devnum, + + /* [OUT] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + uint_32 temp; + uint_8* pBuf; + unsigned long phyAddr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + usb_dev_ptr->CAP_REGS_PTR = + (VUSB20_REG_STRUCT_PTR)USB_get_cap_reg_addr(devnum); + + /* Get the base address of the VUSB_HS registers */ + usb_dev_ptr->DEV_PTR = + (VUSB20_REG_STRUCT_PTR)(((uint_32)usb_dev_ptr->CAP_REGS_PTR) + + (USB_32BIT_LE(usb_dev_ptr->CAP_REGS_PTR->REGISTERS.CAPABILITY_REGISTERS.CAPLENGTH_HCIVER) & + EHCI_CAP_LEN_MASK)); + + /* Get the maximum number of endpoints supported by this USB controller */ + usb_dev_ptr->MAX_ENDPOINTS = + (USB_32BIT_LE(usb_dev_ptr->CAP_REGS_PTR->REGISTERS.CAPABILITY_REGISTERS.DCC_PARAMS) & + VUSB20_DCC_MAX_ENDPTS_SUPPORTED); + + USB_printf("USB init: CAP_REGS=0x%x, DEV_REGS=0x%x, MAX_EP=%d\n", + (unsigned)usb_dev_ptr->CAP_REGS_PTR, (unsigned)usb_dev_ptr->DEV_PTR, + usb_dev_ptr->MAX_ENDPOINTS); + + temp = (usb_dev_ptr->MAX_ENDPOINTS * 2); + + pBuf = (uint_8*)USB_uncached_memalloc(temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT), + 2048, &phyAddr); + if (pBuf == NULL) + { + USB_printf("_usb_dci_vusb20_init, malloc of %d bytes in Uncached area failed\n", + temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT)); + return USBERR_ALLOC; + } + + /**************************************************************** + Assign QH base + ****************************************************************/ + usb_dev_ptr->EP_QUEUE_HEAD_BASE = pBuf; + usb_dev_ptr->EP_QUEUE_HEAD_PHYS = (uint_32)phyAddr; + + /* Align the endpoint queue head to 2K boundary */ + usb_dev_ptr->EP_QUEUE_HEAD_PTR = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR) + USB_MEM2048_ALIGN((uint_32)usb_dev_ptr->EP_QUEUE_HEAD_BASE); + + usb_dev_ptr->EP_QUEUE_HEAD_SIZE = temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT) + + ((uint_32)usb_dev_ptr->EP_QUEUE_HEAD_PTR - + (uint_32)usb_dev_ptr->EP_QUEUE_HEAD_BASE); + + /**************************************************************** + Zero out the memory allocated + ****************************************************************/ + USB_memzero( (void*)usb_dev_ptr->EP_QUEUE_HEAD_PTR, + temp*sizeof(VUSB20_EP_QUEUE_HEAD_STRUCT)); + + USB_printf("USB EP_QH: Base=%p (0x%x), Aligned(%d)=%p, Size=%d\n", + usb_dev_ptr->EP_QUEUE_HEAD_BASE, usb_dev_ptr->EP_QUEUE_HEAD_PHYS, + 2048, usb_dev_ptr->EP_QUEUE_HEAD_PTR, usb_dev_ptr->EP_QUEUE_HEAD_SIZE); + + /**************************************************************** + Assign DTD base + ****************************************************************/ + pBuf = (uint_8*)USB_uncached_memalloc(MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT), + 32, &phyAddr); + if (pBuf == NULL) + { + USB_printf("_usb_dci_vusb20_init, malloc of %d bytes in Uncached area failed\n", + MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT)); + return USBERR_ALLOC; + } + + usb_dev_ptr->DTD_BASE_PTR = pBuf; + usb_dev_ptr->DTD_BASE_PHYS = (uint_32)phyAddr; + + /* Align the dTD base to 32 byte boundary */ + usb_dev_ptr->DTD_ALIGNED_BASE_PTR = (VUSB20_EP_TR_STRUCT_PTR) + USB_MEM32_ALIGN((uint_32)usb_dev_ptr->DTD_BASE_PTR); + + usb_dev_ptr->DTD_SIZE = MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT) + + ((uint_32)usb_dev_ptr->EP_QUEUE_HEAD_PTR - + (uint_32)usb_dev_ptr->EP_QUEUE_HEAD_BASE); + + /**************************************************************** + Zero out the memory allocated + ****************************************************************/ + USB_memzero((void*)usb_dev_ptr->DTD_ALIGNED_BASE_PTR, + MAX_EP_TR_DESCRS*sizeof(VUSB20_EP_TR_STRUCT)); + + /**************************************************************** + Assign SCRATCH Structure base + ****************************************************************/ + /* Allocate memory for internal scratch structure */ + pBuf = USB_memalloc(MAX_EP_TR_DESCRS*sizeof(SCRATCH_STRUCT)); + if (pBuf == NULL) + { + USB_printf("_usb_dci_vusb20_init, malloc of %d bytes failed\n", + MAX_EP_TR_DESCRS*sizeof(SCRATCH_STRUCT)); + return USBERR_ALLOC; + } + usb_dev_ptr->SCRATCH_STRUCT_BASE = (SCRATCH_STRUCT_PTR)pBuf; + USB_memzero(usb_dev_ptr->SCRATCH_STRUCT_BASE, + MAX_EP_TR_DESCRS*sizeof(SCRATCH_STRUCT)); + + USB_printf("USB dTD(%d): Base=%p (0x%x), Aligned(%d)=%p, Size=%d, Scratch=%p\n", + MAX_EP_TR_DESCRS, usb_dev_ptr->DTD_BASE_PTR, usb_dev_ptr->DTD_BASE_PHYS, + 32, usb_dev_ptr->DTD_ALIGNED_BASE_PTR, usb_dev_ptr->DTD_SIZE, + usb_dev_ptr->SCRATCH_STRUCT_BASE); + +#ifdef USB_UNDERRUN_WA + usbSramBase = (uint_8*)USB_get_sram_addr(&usbSramSize); + if (usbSramBase == NULL) + { + USB_printf("_usb_dci_vusb20_init, SRAM is not available\n"); + return USBERR_ALLOC; + } + USB_memzero(usbSramBase, usbSramSize); + USB_printf("USB WA_Queue: base=%p, size=%d, parts=%d\n", + usbSramBase, usbSramSize, global_wa_sram_parts); +#endif /* USB_UNDERRUN_WA */ + + usb_dev_ptr->USB_STATE = ARC_USB_STATE_UNKNOWN; + + /* Initialize the VUSB_HS controller */ + _usb_dci_vusb20_chip_initialize((pointer)usb_dev_ptr); + + return USB_OK; +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_chip_initialize +* Returned Value : USB_OK or error code +* Comments : +* Initializes the USB device controller. +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_chip_initialize + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + VUSB20_EP_QUEUE_HEAD_STRUCT_PTR ep_queue_head_ptr; + VUSB20_EP_TR_STRUCT_PTR dTD_ptr; + uint_32 i, port_control; + SCRATCH_STRUCT_PTR temp_scratch_ptr; + volatile unsigned long delay; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, "chip_initialize\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Stop the controller */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= ~(USB_32BIT_LE(EHCI_CMD_RUN_STOP)); + + /* Reset the controller to get default values */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD = USB_32BIT_LE(EHCI_CMD_CTRL_RESET); + + USB_printf("USB Init: Wait for RESET completed\n"); + + delay = 0x100000; + while (dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD & + (USB_32BIT_LE(EHCI_CMD_CTRL_RESET))) + { + /* Wait for the controller reset to complete */ + delay--; + if(delay == 0) + break; + } /* EndWhile */ + + if(delay == 0) + { + USB_printf("USB Init: Wait for RESET completed TIMEOUT\n"); + } + else + { + USB_printf("USB Init: RESET completed\n"); + } + /* Call BSP callback to complete reset process */ + USB_reset_complete(usb_dev_ptr->DEV_NUM); + + /* Initialize the internal dTD head and tail to NULL */ + usb_dev_ptr->DTD_HEAD = NULL; + usb_dev_ptr->DTD_TAIL = NULL; + usb_dev_ptr->DTD_ENTRIES = 0; + usb_dev_ptr->ERROR_STATE = 0; + + /* Make sure the 16 MSBs of this register are 0s */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT = USB_32BIT_LE(0); + + ep_queue_head_ptr = usb_dev_ptr->EP_QUEUE_HEAD_PTR; + + /* Initialize all device queue heads */ + for (i=0; i<(usb_dev_ptr->MAX_ENDPOINTS*2); i++) + { + /* Interrupt on Setup packet */ + (ep_queue_head_ptr + i)->MAX_PKT_LENGTH = (USB_32BIT_LE( + ((uint_32)USB_MAX_CTRL_PAYLOAD << VUSB_EP_QUEUE_HEAD_MAX_PKT_LEN_POS) | + VUSB_EP_QUEUE_HEAD_IOS)); + + (ep_queue_head_ptr + i)->NEXT_DTD_PTR = (USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE)); + } /* Endfor */ + + /* Configure the Endpoint List Address */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.EP_LIST_ADDR = + USB_32BIT_LE(USB_EP_QH_VIRT_TO_PHYS(usb_dev_ptr, ep_queue_head_ptr)); + + port_control = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]); + if (usb_dev_ptr->CAP_REGS_PTR->REGISTERS.CAPABILITY_REGISTERS.HCS_PARAMS & + USB_32BIT_LE(VUSB20_HCS_PARAMS_PORT_POWER_CONTROL_FLAG)) + { + port_control &= (~EHCI_PORTSCX_W1C_BITS | ~EHCI_PORTSCX_PORT_POWER); + } /* Endif */ + + if(usb_dev_ptr->FORCE_FS == TRUE) + { + port_control |= EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT; + } + else + { + port_control &= (~EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT); + } + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = USB_32BIT_LE(port_control); + + dTD_ptr = usb_dev_ptr->DTD_ALIGNED_BASE_PTR; + + temp_scratch_ptr = usb_dev_ptr->SCRATCH_STRUCT_BASE; + + /* Enqueue all the dTDs */ + for (i=0; iSCRATCH_PTR = temp_scratch_ptr; + dTD_ptr->SCRATCH_PTR->FREE = _usb_dci_vusb20_free_dTD; + /* Set the dTD to be invalid */ + dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(VUSBHS_TD_NEXT_TERMINATE); + /* Set the Reserved fields to 0 */ + dTD_ptr->SIZE_IOC_STS &= ~(USB_32BIT_LE(VUSBHS_TD_RESERVED_FIELDS)); + dTD_ptr->SCRATCH_PTR->PRIVATE = (pointer)usb_dev_ptr; + _usb_dci_vusb20_free_dTD((pointer)dTD_ptr); + dTD_ptr++; + temp_scratch_ptr++; + } /* Endfor */ +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_free_dTD +* Returned Value : void +* Comments : +* Enqueues a dTD onto the free DTD ring. +* +*END*-----------------------------------------------------------------*/ + +void _usb_dci_vusb20_free_dTD + ( + /* [IN] the dTD to enqueue */ + pointer dTD_ptr + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + int lockKey; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)(((VUSB20_EP_TR_STRUCT_PTR)dTD_ptr)->SCRATCH_PTR->PRIVATE); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "free_dTD: dTD_ptr=0x%x\n", (unsigned)dTD_ptr); + + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.free_dTD_count++)); + + + /* + ** This function can be called from any context, and it needs mutual + ** exclusion with itself. + */ + lockKey = USB_lock(); + + /* + ** Add the dTD to the free dTD queue (linked via PRIVATE) and + ** increment the tail to the next descriptor + */ + EHCI_DTD_QADD(usb_dev_ptr->DTD_HEAD, usb_dev_ptr->DTD_TAIL, (VUSB20_EP_TR_STRUCT_PTR)dTD_ptr); + usb_dev_ptr->DTD_ENTRIES++; + + USB_unlock(lockKey); + +} /* Endbody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_add_dTD +* Returned Value : USB_OK or error code +* Comments : +* Adds a device transfer desriptor(s) to the queue. +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_dci_vusb20_add_dTD + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] The transfer descriptor address */ + XD_STRUCT_PTR xd_ptr + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + VUSB20_EP_TR_STRUCT_PTR dTD_ptr, temp_dTD_ptr, first_dTD_ptr = NULL; + VUSB20_EP_QUEUE_HEAD_STRUCT_PTR ep_queue_head_ptr; + uint_32 curr_pkt_len, remaining_len; + uint_32 curr_offset, temp, bit_pos; + volatile unsigned long timeout; + + /********************************************************************* + For a optimal implementation, we need to detect the fact that + we are adding DTD to an empty list. If list is empty, we can + actually skip several programming steps esp. those for ensuring + that there is no race condition.The following boolean will be useful + in skipping some code here. + *********************************************************************/ + boolean list_empty = FALSE; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + remaining_len = xd_ptr->WTOTALLENGTH; + + curr_offset = 0; + temp = (2*xd_ptr->EP_NUM + xd_ptr->BDIRECTION); + bit_pos = (1 << (16 * xd_ptr->BDIRECTION + xd_ptr->EP_NUM)); + + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp; + + /********************************************************************* + This loops iterates through the length of the transfer and divides + the data in to DTDs each handling the a max of 0x4000 bytes of data. + The first DTD in the list is stored in a pointer called first_dTD_ptr. + This pointer is later linked in to QH for processing by the hardware. + *********************************************************************/ + + do + { + /* Check if we need to split the transfer into multiple dTDs */ + if (remaining_len > VUSB_EP_MAX_LENGTH_TRANSFER) + { + curr_pkt_len = VUSB_EP_MAX_LENGTH_TRANSFER; + } + else + { + curr_pkt_len = remaining_len; + } /* Endif */ + + /* Get a dTD from the queue */ + EHCI_DTD_QGET(usb_dev_ptr->DTD_HEAD, usb_dev_ptr->DTD_TAIL, dTD_ptr); + + if (!dTD_ptr) + { + USB_printf("Error: Can't get dTD\n"); + return USBERR_TR_FAILED; + } /* Endif */ + + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_add_count++)); + + remaining_len -= curr_pkt_len; + + usb_dev_ptr->DTD_ENTRIES--; + + if (curr_offset == 0) + { + first_dTD_ptr = dTD_ptr; + } /* Endif */ + + /* Zero the dTD. Leave the last 4 bytes as that is the scratch pointer */ + USB_memzero((void *) dTD_ptr,(sizeof(VUSB20_EP_TR_STRUCT) - 4)); + + /* Initialize the dTD */ + dTD_ptr->SCRATCH_PTR->PRIVATE = handle; + + /* Set the Terminate bit */ + dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_NEXT_TERMINATE); + + /************************************************************* + FIX ME: For hig-speed and high-bandwidth ISO IN endpoints, + we must initialize the multiplied field so that Host can issues + multiple IN transactions on the endpoint. See the DTD data + structure for MultiIO field. + + S Garg 11/06/2003 + *************************************************************/ + + /* Fill in the transfer size */ + if (!remaining_len) + { + dTD_ptr->SIZE_IOC_STS = USB_32BIT_LE((curr_pkt_len << + VUSBHS_TD_LENGTH_BIT_POS) | (VUSBHS_TD_IOC) | (VUSBHS_TD_STATUS_ACTIVE)); + } + else + { + dTD_ptr->SIZE_IOC_STS = USB_32BIT_LE((curr_pkt_len << VUSBHS_TD_LENGTH_BIT_POS) + | VUSBHS_TD_STATUS_ACTIVE); + } /* Endif */ + + /* Set the reserved field to 0 */ + dTD_ptr->SIZE_IOC_STS &= ~USB_32BIT_LE(VUSBHS_TD_RESERVED_FIELDS); + + /* 4K apart buffer page pointers */ + if(xd_ptr->WSTARTADDRESS != NULL) + { + uint_32 physAddr = USB_virt_to_phys((uint_8*)xd_ptr->WSTARTADDRESS + curr_offset); + + dTD_ptr->BUFF_PTR0 = USB_32BIT_LE(physAddr); + + physAddr += 4096; + dTD_ptr->BUFF_PTR1 = USB_32BIT_LE(physAddr); + + physAddr += 4096; + dTD_ptr->BUFF_PTR2 = USB_32BIT_LE(physAddr); + + physAddr += 4096; + dTD_ptr->BUFF_PTR3 = USB_32BIT_LE(physAddr); + + physAddr += 4096; + dTD_ptr->BUFF_PTR4 = USB_32BIT_LE(physAddr); + } + else + { + dTD_ptr->BUFF_PTR0 = dTD_ptr->BUFF_PTR1 = dTD_ptr->BUFF_PTR2 = 0; + dTD_ptr->BUFF_PTR3 = dTD_ptr->BUFF_PTR4 = 0; + } + curr_offset += curr_pkt_len; + + /* Maintain the first and last device transfer descriptor per + ** endpoint and direction + */ + if (!usb_dev_ptr->EP_DTD_HEADS[temp]) + { + usb_dev_ptr->EP_DTD_HEADS[temp] = dTD_ptr; + /*********************************************** + If list does not have a head, it means that list + is empty. An empty condition is detected. + ***********************************************/ + list_empty = TRUE; + } /* Endif */ + + /* Check if the transfer is to be queued at the end or beginning */ + temp_dTD_ptr = usb_dev_ptr->EP_DTD_TAILS[temp]; + + /* Remember which XD to use for this dTD */ + dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD = (pointer)xd_ptr; + + /* New tail */ + usb_dev_ptr->EP_DTD_TAILS[temp] = dTD_ptr; + if (temp_dTD_ptr) + { + /* Should not do |=. The Terminate bit should be zero */ + temp_dTD_ptr->NEXT_TR_ELEM_PTR = USB_32BIT_LE(USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, dTD_ptr)); + } /* Endif */ + } while (remaining_len); /* EndWhile */ + + + /************************************************************** + In the loop above DTD has already been added to the list + However endpoint has not been primed yet. If list is not empty + we need safter ways to add DTD to the existing list. + Else we just skip to adding DTD to QH safely. + **************************************************************/ + + if(list_empty == FALSE) + { + volatile boolean read_safe = FALSE; + uint_32 prime, temp_ep_stat=0; + + /********************************************************* + Hardware v3.2+ require the use of semaphore to ensure that + QH is safely updated. + *********************************************************/ + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_add_not_empty_count++)); + + /********************************************************* + Check the prime bit. If set goto done + *********************************************************/ + prime = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME); +/* + USB_printf("%03d: Add not empty: bit_pos=%x, prime=0x%x, status=0x%x\n", + usb_dev_ptr->STATS.usb_add_not_empty_count, prime, bit_pos, + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS) ); +*/ + if(prime & bit_pos) + { + timeout = 0x1000; + while( dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME + & USB_32BIT_LE(bit_pos) ) + { + /* Wait for the ENDPTPRIME to go to zero */ + timeout--; + if(timeout <= 0) + { + USB_printf( + "timeout: CTRL=%x, PRIME=%x, STAT=%x, INTR=%x, ADDR=%x, PORTSC=%x, dTD=%p, temp_dTD=%p\n", + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0]), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]), + first_dTD_ptr, temp_dTD_ptr); + + _usb_ep_status(handle, xd_ptr->EP_NUM, xd_ptr->BDIRECTION); + + return USBERR_TR_FAILED; + } + } /* EndWhile */ + + /*ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER,*/ + if(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS & USB_32BIT_LE(bit_pos)) + { + goto done; + } + } + + read_safe = FALSE; + timeout = 1000000; + while(read_safe == FALSE) + { + timeout--; + if(timeout <= 0) + { + USB_printf("%s: Timeout for ATDTW_TRIPWIRE reg = 0x%x\n", __FUNCTION__, + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD)); + return USBERR_TR_FAILED; + } + + /********************************************************* + start with setting the semaphores + *********************************************************/ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD |= + USB_32BIT_LE(EHCI_CMD_ATDTW_TRIPWIRE_SET); + + /********************************************************* + Read the endpoint status + *********************************************************/ + temp_ep_stat = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) + & bit_pos; + + /********************************************************* + Reread the ATDTW semaphore bit to check if it is cleared. + When hardware see a hazard, it will clear the bit or + else we remain set to 1 and we can proceed with priming + of endpoint if not already primed. + *********************************************************/ + if( dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD & + USB_32BIT_LE(EHCI_CMD_ATDTW_TRIPWIRE_SET)) + { + read_safe = TRUE; + } + + }/*end while loop */ + + /********************************************************* + Clear the semaphore + *********************************************************/ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= + USB_32BIT_LE(EHCI_CMD_ATDTW_TRIPWIRE_CLEAR); + + /********************************************************* + * If endpoint is not active, we activate it now. + *********************************************************/ + if(!temp_ep_stat) + { + /* No other transfers on the queue */ + ep_queue_head_ptr->NEXT_DTD_PTR = USB_32BIT_LE( + USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, first_dTD_ptr)); + ep_queue_head_ptr->SIZE_IOC_INT_STS = 0; + + /* Prime the Endpoint */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos); + } + } + else + { + /* No other transfers on the queue */ + ep_queue_head_ptr->NEXT_DTD_PTR = USB_32BIT_LE( + USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, first_dTD_ptr)); + ep_queue_head_ptr->SIZE_IOC_INT_STS = 0; + + /* Prime the Endpoint */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos); + /* delay */ + timeout = 0x100; + while(timeout > 0) + timeout--; + + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME = USB_32BIT_LE(bit_pos); + } + +done: + if(first_dTD_ptr == NULL) + USB_printf("ERROR !!!! first_dTD_ptr=NULL\n"); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER, + " add_%d: fri=0x%x, ep=%d%s, buf=%p, size=%d, xd=%p, dTD=%p %p, empty=%d\n", + usb_dev_ptr->STATS.usb_add_count & 0xFFFF, + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), + xd_ptr->EP_NUM, xd_ptr->BDIRECTION ? "in" : "out", + xd_ptr->WSTARTADDRESS, (int)xd_ptr->WTOTALLENGTH, + xd_ptr, (unsigned)first_dTD_ptr, + usb_dev_ptr->EP_DTD_HEADS[temp], list_empty); + + + return USB_OK; + /* End CR 1015 */ +} /* EndBody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_process_tr_complete +* Returned Value : None +* Comments : +* Services transaction complete interrupt +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_process_tr_complete + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + volatile VUSB20_REG_STRUCT_PTR dev_ptr; + volatile VUSB20_EP_TR_STRUCT_PTR dTD_ptr; + VUSB20_EP_TR_STRUCT_PTR temp_dTD_ptr; + VUSB20_EP_QUEUE_HEAD_STRUCT_PTR ep_queue_head_ptr; + uint_32 temp, i, ep_num = 0, direction = 0, bit_pos; + uint_32 remaining_length = 0; + uint_32 actual_transfer_length = 0; + uint_32 counter, errors = 0; + XD_STRUCT_PTR xd_ptr; + XD_STRUCT_PTR temp_xd_ptr = NULL; + uint_8_ptr buff_start_address = NULL; + boolean endpoint_detected = FALSE; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_tr_complete_isr\n"); + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_complete_isr_count++)); + + /* We use separate loops for ENDPTSETUPSTAT and ENDPTCOMPLETE because the + ** setup packets are to be read ASAP + */ + + /* Process all Setup packet received interrupts */ + bit_pos = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT); + + if (bit_pos) + { + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "setup_isr: bit_pos=0x%x\n", (unsigned)bit_pos); + for(i=0; iSTATS.usb_setup_count++)); + _usb_device_call_service(handle, i, TRUE, 0, 0, 8, 0); + } /* Endif */ + } /* Endfor */ + } /* Endif */ + + /* Don't clear the endpoint setup status register here. It is cleared as a + ** setup packet is read out of the buffer + */ + + /* Process non-setup transaction complete interrupts */ + bit_pos = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE); + + /* Clear the bits in the register */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE = USB_32BIT_LE(bit_pos); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "tr_complete: bit_pos = 0x%x\n", (unsigned)bit_pos); + + if (bit_pos) + { + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_complete_count++)); + + /* Get the endpoint number and the direction of transfer */ + counter = 0; + for (i=0; i<(ARC_USB_MAX_ENDPOINTS*2); i++) + { + endpoint_detected = FALSE; + if ((i < ARC_USB_MAX_ENDPOINTS) && (bit_pos & (1 << i))) + { + ep_num = i; + direction = ARC_USB_RECV; + endpoint_detected = TRUE; + } + else + { + if( (i >= ARC_USB_MAX_ENDPOINTS) && + (bit_pos & (1 << (i+16-ARC_USB_MAX_ENDPOINTS)))) + { + ep_num = (i - ARC_USB_MAX_ENDPOINTS); + direction = ARC_USB_SEND; + endpoint_detected = TRUE; + } + } + + if(endpoint_detected) + { + temp = (2*ep_num + direction); + + /* Get the first dTD */ + dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[temp]; + + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp; + + /* Process all the dTDs for respective transfers */ + while (dTD_ptr) + { + if (USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_STATUS_ACTIVE) + { + /* No more dTDs to process. Next one is owned by VUSB */ + if(counter == 0) + { + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "tr_complete - break: ep=%d %s, bit_pos=0x%x\n", + (unsigned)ep_num, direction ? "SEND" : "RECV", (unsigned)bit_pos); + + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_empty_complete_count++)); + } + break; + } /* Endif */ + + /* Get the correct internal transfer descriptor */ + xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD; + if (xd_ptr) + { + buff_start_address = xd_ptr->WSTARTADDRESS; + actual_transfer_length = xd_ptr->WTOTALLENGTH; + temp_xd_ptr = xd_ptr; + } /* Endif */ + + /* Get the address of the next dTD */ + temp_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, + (uint_32)(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK) ); + + /* Read the errors */ + errors = (USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSBHS_TD_ERROR_MASK); + if (!errors) + { + /* No errors */ + /* Get the length of transfer from the current dTD */ + remaining_length += ((USB_32BIT_LE(dTD_ptr->SIZE_IOC_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16); + actual_transfer_length -= remaining_length; + } + else + { + USB_printf("complete_tr error: ep=%d %s: error = 0x%x\n", + (unsigned)ep_num, direction ? "SEND" : "RECV", (unsigned)errors); + if (errors & VUSBHS_TD_STATUS_HALTED) + { + /* Clear the errors and Halt condition */ + ep_queue_head_ptr->SIZE_IOC_INT_STS &= USB_32BIT_LE(~errors); + } /* Endif */ + } /* Endif */ + + /* Retire the processed dTD */ + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "tr_complete - cancel: ep=%d %s, bit_pos = 0x%x\n", + (unsigned)ep_num, direction ? "SEND" : "RECV", (unsigned)bit_pos); + + counter++; + _usb_dci_vusb20_cancel_transfer(handle, ep_num, direction); + if( (temp_dTD_ptr == NULL) || + (temp_dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD != temp_xd_ptr) ) + { + /* Transfer complete. Call the register service function for the endpoint */ + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_complete_ep_count[temp]++)); + +#if defined(USB_UNDERRUN_WA) + if( (direction == ARC_USB_SEND) && + (((ep_queue_head_ptr->MAX_PKT_LENGTH >> 16) & 0x7FF) > global_wa_threshold) ) + usbSendComplete(handle, ep_num, FALSE, direction, + buff_start_address, actual_transfer_length, errors); + else +#endif /* USB_UNDERRUN_WA */ + _usb_device_call_service(handle, ep_num, FALSE, direction, + buff_start_address, actual_transfer_length, errors); + remaining_length = 0; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER, + "comp_%d: fri=0x%x, ep=%d%s, buf=%p, size=%d, xd=%p, dTD=%p %p %p, COMP=0x%x\n", + usb_dev_ptr->STATS.usb_complete_count & 0xFFFF, + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), + (unsigned)ep_num, direction ? "in" : "out", + buff_start_address, actual_transfer_length, + temp_xd_ptr, dTD_ptr, temp_dTD_ptr, usb_dev_ptr->EP_DTD_HEADS[temp], (unsigned)bit_pos); + + } /* Endif */ + else + { + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRANSFER, "tr_complete not completed: ep=%d %s\n", + (unsigned)ep_num, direction ? "SEND" : "RECV"); + } + if( (temp_dTD_ptr == NULL) && (usb_dev_ptr->EP_DTD_HEADS[temp] != NULL) ) + { +/* + USB_printf("tr_complete: ep=%d, temp_dTD=%p, dTD_ptr=%p (%p), DTD_HEADS=%p, remain=%d\n", + temp, temp_dTD_ptr, dTD_ptr, + USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, (uint_32)(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK) ), + usb_dev_ptr->EP_DTD_HEADS[temp], remaining_length); +*/ + dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[temp]; + } + else + { + dTD_ptr = temp_dTD_ptr; + } + errors = 0; + } /* Endwhile */ + } /* Endif */ + } /* Endfor */ + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, + ( {if(usb_dev_ptr->STATS.usb_complete_max_count < counter) + usb_dev_ptr->STATS.usb_complete_max_count = counter;})); + } /* Endif */ +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_isr +* Returned Value : None +* Comments : +* Services all the VUSB_HS interrupt sources +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_isr + ( + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + uint_32 status; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_isr_count++)); + + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + status = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS); + + status &= USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR); + + if(status == 0) + { + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_empty_isr_count++)); + return; + } /* Endif */ +/* + USB_printf("USB_ISR: FRINDEX=0x%x, status=0x%x, PORTSC=0x%x, EP_SETUP=0x%x, EP_COMPLETE=0x%x\n", + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), + status, + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE) ); +*/ + /* Clear all the interrupts occured */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_STS = USB_32BIT_LE(status); + + if (status & EHCI_STS_ERR) + { + _usb_dci_vusb20_process_error((pointer)usb_dev_ptr); + USB_printf("USB process error: status=0x%x\n", status); + usb_dev_ptr->ERROR_STATE |= (status & 0xFFFF); + } /* Endif */ + + if (status & EHCI_STS_RESET) + { + _usb_dci_vusb20_process_reset((pointer)usb_dev_ptr); + } /* Endif */ + + if (status & EHCI_STS_PORT_CHANGE) + { + _usb_dci_vusb20_process_port_change((pointer)usb_dev_ptr); + } /* Endif */ + + if (status & EHCI_STS_SOF) + { + _usb_dci_vusb20_process_SOF((pointer)usb_dev_ptr); + } /* Endif */ + + if (status & EHCI_STS_INT) + { + _usb_dci_vusb20_process_tr_complete((pointer)usb_dev_ptr); + } /* Endif */ + + if (status & EHCI_STS_SUSPEND) + { + _usb_dci_vusb20_process_suspend((pointer)usb_dev_ptr); + } /* Endif */ + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_process_reset +* Returned Value : None +* Comments : +* Services reset interrupt +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_process_reset + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + uint_32 temp; + volatile unsigned long timeout; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_reset\n"); + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_reset_count++)); + + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Inform the application so that it can cancel all previously queued transfers */ + _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_BUS_RESET, 0, 0, 0, 0, 0); + +#if defined(USB_UNDERRUN_WA) + _usb_reset_send_queue(); +#endif /* USB_UNDERRUN_WA */ + + /* The address bits are past bit 25-31. Set the address */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR &= ~USB_32BIT_LE(0xFE000000); + + /* Clear all the setup token semaphores */ + temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT); + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT = USB_32BIT_LE(temp); + + /* Clear all the endpoint complete status bits */ + temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE); + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE = USB_32BIT_LE(temp); + + timeout = 0x10000; + while (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & 0xFFFFFFFF) + { + timeout--; + if(timeout <= 0) + { + USB_printf("%s: Timeout for ENDPTPRIME = 0x%x\n", __FUNCTION__, + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME)); + break; + } + + /* Wait until all ENDPTPRIME bits cleared */ + } /* Endif */ + + /* Write 1s to the Flush register */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTFLUSH = USB_32BIT_LE(0xFFFFFFFF); + + if( (usb_dev_ptr->ERROR_STATE == 0x0) && + (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & + EHCI_PORTSCX_PORT_RESET) ) + { + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, + "USB Bus Reset: fri=0x%x, dev_ptr=%p, STATE=%d, PORTSC=0x%x, CMD=0x%x, ENDPT[0]=0x%x\n", + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), + usb_dev_ptr, usb_dev_ptr->USB_STATE, + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD), + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0])); + + usb_dev_ptr->BUS_RESETTING = TRUE; + usb_dev_ptr->USB_STATE = ARC_USB_STATE_POWERED; + } + else + { + USB_printf("USB Chip reinit: PORTSC=0x%x\n", + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0])); + + /* re-initialize */ + _usb_dci_vusb20_chip_initialize((pointer)usb_dev_ptr); + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, "process_reset, Chip reinit hw\n"); + } /* Endif */ + + _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_BUS_RESET, 1, 0, 0, 0, 0); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_process_suspend +* Returned Value : None +* Comments : +* Services suspend interrupt +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_process_suspend + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_suspend\n"); + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_suspend_count++)); + + usb_dev_ptr->USB_DEV_STATE_B4_SUSPEND = usb_dev_ptr->USB_STATE; + + usb_dev_ptr->USB_STATE = ARC_USB_STATE_SUSPEND; + + /* Inform the upper layers */ + _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SLEEP, 0, 0, 0, 0, 0); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_process_SOF +* Returned Value : None +* Comments : +* Services SOF interrupt +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_process_SOF + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_SOF\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Inform the upper layer */ + _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SOF, 0, 0, 0, + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_FRINDEX), 0); + +} /* EndBody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_process_port_change +* Returned Value : None +* Comments : +* Services port change detect interrupt +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_process_port_change + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ISR, "process_port_change\n"); + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_port_change_count++)); + + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; +/* + USB_printf("port_change: PORTSC=0x%x, DTD_ENTRIES=%d, XD_ENTRIES=%d\n", + USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]), + usb_dev_ptr->DTD_ENTRIES, usb_dev_ptr->XD_ENTRIES); +*/ + if (usb_dev_ptr->BUS_RESETTING) + { + /* Bus reset operation complete */ + usb_dev_ptr->BUS_RESETTING = FALSE; + } /* Endif */ + + if (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & + EHCI_PORTSCX_PORT_RESET)) + { + /* Get the speed */ + if (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & + EHCI_PORTSCX_PORT_HIGH_SPEED) + { + usb_dev_ptr->SPEED = ARC_USB_SPEED_HIGH; + } + else + { + usb_dev_ptr->SPEED = ARC_USB_SPEED_FULL; + } /* Endif */ +/* + USB_printf("USB %s speed device detected\n", + (usb_dev_ptr->SPEED == ARC_USB_SPEED_HIGH) ? "High" : "Full"); +*/ + /* Inform the upper layers of the speed of operation */ + _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SPEED_DETECTION, 0, 0, + 0, usb_dev_ptr->SPEED, 0); + } /* Endif */ + + if (USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & + EHCI_PORTSCX_PORT_SUSPEND) + { + usb_dev_ptr->USB_DEV_STATE_B4_SUSPEND = usb_dev_ptr->USB_STATE; + usb_dev_ptr->USB_STATE = ARC_USB_STATE_SUSPEND; + + /* Inform the upper layers */ + USB_printf("USB suspend\n"); + _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_SUSPEND, 0, 0, 0, 0, 0); + } /* Endif */ + + if (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]) & EHCI_PORTSCX_PORT_SUSPEND) + && (usb_dev_ptr->USB_STATE == ARC_USB_STATE_SUSPEND)) + { + USB_printf("USB resume\n"); + usb_dev_ptr->USB_STATE = usb_dev_ptr->USB_DEV_STATE_B4_SUSPEND; + /* Inform the upper layers */ + _usb_device_call_service(usb_dev_ptr, ARC_USB_SERVICE_RESUME, 0, 0, 0, 0, 0); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SUSPEND, "process_port_change, SUCCESSFUL, resumed\n"); + return; + } /* Endif */ + + usb_dev_ptr->USB_STATE = ARC_USB_STATE_DEFAULT; + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_process_error +* Returned Value : None +* Comments : +* Services error interrupt +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_process_error + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ERROR, "process_error\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + /* Increment the error count */ + usb_dev_ptr->ERRORS++; + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_set_speed_full +* Returned Value : None +* Comments : +* Force the controller port in full speed mode. +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_set_speed_full + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* The port number on the device */ + uint_8 port_number + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + uint_32 port_control; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ANY, "FORCE set_speed_full\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + port_control = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number]); + port_control |= EHCI_PORTSCX_FORCE_FULL_SPEED_CONNECT; + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number] = USB_32BIT_LE(port_control); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_suspend_phy +* Returned Value : None +* Comments : +* Suspends the PHY in low power mode +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_suspend_phy + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* The port number on the device */ + uint_8 port_number + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + uint_32 port_control; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SUSPEND, "set_suspend_phy\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + port_control = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number]); + port_control |= EHCI_PORTSCX_PHY_CLOCK_DISABLE; + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[port_number] = USB_32BIT_LE(port_control); + +} /* EndBody */ + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_set_address +* Returned Value : None +* Comments : +* Sets the newly assigned device address +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_set_address + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* Address of the device assigned by the host */ + uint_8 address + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ADDR, "set_address: address=%d\n",address); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + +#ifdef SET_ADDRESS_HARDWARE_ASSISTANCE + /*********************************************************** + Hardware Rev 4.0 onwards have special assistance built in + for handling the set_address command. As per the USB specs + a device should be able to receive the response on a new + address, within 2 msecs after status phase of set_address is + completed. Since 2 mili second may be a very small time window + (on high interrupt latency systems) before software could + come to the code below and write the device register, + this routine will be called in advance when status phase of + set_address is still not finished. The following line in the + code will set the bit 24 to '1' and hardware will take + the address and queue it in an internal buffer. From which + it will use it to decode the next USB token. Please look + at hardware rev details for the implementation of this + assistance. + + Also note that writing bit 24 to 0x01 will not break + any old hardware revs because it was an unused bit. + ***********************************************************/ + /* The address bits are past bit 25-31. Set the address + also set the bit 24 to 0x01 to start hardware assitance*/ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR = + USB_32BIT_LE((uint_32)address << VUSBHS_ADDRESS_BIT_SHIFT) | + (0x01 << (VUSBHS_ADDRESS_BIT_SHIFT -1)); +#else + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.DEVICE_ADDR = + USB_32BIT_LE((uint_32)address << VUSBHS_ADDRESS_BIT_SHIFT); +#endif /* SET_ADDRESS_HARDWARE_ASSISTANCE */ + + usb_dev_ptr->USB_STATE = ARC_USB_STATE_ADDRESS; + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_get_setup_data +* Returned Value : None +* Comments : +* Reads the Setup data from the 8-byte setup buffer +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_get_setup_data + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [OUT] address of the buffer to read the setup data into */ + uint_8_ptr buffer_ptr + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + volatile VUSB20_REG_STRUCT_PTR dev_ptr; + volatile VUSB20_EP_QUEUE_HEAD_STRUCT_PTR ep_queue_head_ptr; + volatile boolean read_safe = FALSE; + volatile unsigned long timeout; + + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Get the endpoint queue head */ + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + + 2*ep_num + ARC_USB_RECV; + + /******************************************************************** + CR 1219. Hardware versions 2.3+ have a implementation of tripwire + semaphore mechanism that requires that we read the contents of + QH safely by using the semaphore. Read the USBHS document to under + stand how the code uses the semaphore mechanism. The following are + the steps in brief + + 1. USBCMD Write ‘1’ to Setup Tripwire in register. + 2. Duplicate contents of dQH.StatusBuffer into local software byte + array. + 3 Read Setup TripWire in register. (if set - continue; if + cleared goto 1.) + 4. Write '0' to clear Setup Tripwire in register. + 5. Process setup packet using local software byte array copy and + execute status/handshake phases. + + + ********************************************************************/ + timeout = 0x100000; + while(!read_safe) + { + /********************************************************* + start with setting the semaphores + *********************************************************/ + + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD |= + USB_32BIT_LE(EHCI_CMD_SETUP_TRIPWIRE_SET); + + /* Copy the setup packet to private buffer */ + USB_memcopy((uint_8_ptr)ep_queue_head_ptr->SETUP_BUFFER, buffer_ptr, 8); + + /********************************************************* + If setup tripwire semaphore is cleared by hardware it means + that we have a danger and we need to restart. + else we can exit out of loop safely. + *********************************************************/ + if(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD) & + EHCI_CMD_SETUP_TRIPWIRE_SET) + { + read_safe = TRUE; /* we can proceed exiting out of loop*/ + } + if(timeout <= 0) + { + USB_printf("%s: Timeout for SETUP_TRIPWIRE = 0x%x\n", __FUNCTION__, + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD)); + break; + } + } + ARC_DEBUG_CODE(ARC_DEBUG_FLAG_STATS, (usb_dev_ptr->STATS.usb_read_setup_count++)); + + /********************************************************* + Clear the semaphore bit now + *********************************************************/ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= + USB_32BIT_LE(EHCI_CMD_SETUP_TRIPWIRE_CLEAR); + + /* Clear the bit in the ENDPTSETUPSTAT */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT = USB_32BIT_LE(1 << ep_num); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_init_endpoint +* Returned Value : None +* Comments : +* Initializes the specified endpoint and the endpoint queue head +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_dci_vusb20_init_endpoint + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the transaction descriptor address */ + XD_STRUCT_PTR xd_ptr + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + VUSB20_EP_QUEUE_HEAD_STRUCT _PTR_ ep_queue_head_ptr; + uint_32 val, bit_pos; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Get the endpoint queue head address */ + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + + 2*xd_ptr->EP_NUM + xd_ptr->BDIRECTION; + + bit_pos = (1 << (16 * xd_ptr->BDIRECTION + xd_ptr->EP_NUM)); + + /* Check if the Endpoint is Primed */ + if ((!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & bit_pos)) && + (!(USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos))) + { + /* Set the max packet length, interrupt on Setup and Mult fields */ + if (xd_ptr->EP_TYPE == ARC_USB_ISOCHRONOUS_ENDPOINT) + { + /* Mult bit should be set for isochronous endpoints */ + ep_queue_head_ptr->MAX_PKT_LENGTH = USB_32BIT_LE((xd_ptr->WMAXPACKETSIZE << 16) | + ((xd_ptr->MAX_PKTS_PER_UFRAME ? xd_ptr->MAX_PKTS_PER_UFRAME : 1) << + VUSB_EP_QUEUE_HEAD_MULT_POS)); + } + else + { + if (xd_ptr->EP_TYPE != ARC_USB_CONTROL_ENDPOINT) + { + /* BULK or INTERRUPT */ + ep_queue_head_ptr->MAX_PKT_LENGTH = USB_32BIT_LE((xd_ptr->WMAXPACKETSIZE << 16) | + (xd_ptr->DONT_ZERO_TERMINATE ? VUSB_EP_QUEUE_HEAD_ZERO_LEN_TER_SEL : 0)); + } + else + { + /* CONTROL */ + ep_queue_head_ptr->MAX_PKT_LENGTH = USB_32BIT_LE((xd_ptr->WMAXPACKETSIZE << 16) | + VUSB_EP_QUEUE_HEAD_IOS); + } /* Endif */ + } /* Endif */ + + /* Enable the endpoint for Rx or Tx and set the endpoint type */ + val = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM]; + if(xd_ptr->BDIRECTION == ARC_USB_SEND) + { + val &= ~(USB_32BIT_LE(EHCI_EPCTRL_TX_ALL_MASK)); + val |= USB_32BIT_LE((EHCI_EPCTRL_TX_ENABLE | EHCI_EPCTRL_TX_DATA_TOGGLE_RST) | + (xd_ptr->EP_TYPE << EHCI_EPCTRL_TX_EP_TYPE_SHIFT)); + } + else + { + val &= ~(USB_32BIT_LE(EHCI_EPCTRL_RX_ALL_MASK)); + val |= USB_32BIT_LE((EHCI_EPCTRL_RX_ENABLE | EHCI_EPCTRL_RX_DATA_TOGGLE_RST) | + (xd_ptr->EP_TYPE << EHCI_EPCTRL_RX_EP_TYPE_SHIFT)); + } + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] = val; + + /* Implement Guideline (GL# USB-7) The unused endpoint type must */ + /* be programmed to bulk. */ + if( (dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] & + USB_32BIT_LE(EHCI_EPCTRL_RX_ENABLE)) == 0) + { + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] |= + USB_32BIT_LE(ARC_USB_BULK_ENDPOINT << EHCI_EPCTRL_RX_EP_TYPE_SHIFT); + } + + if( (dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] & + USB_32BIT_LE(EHCI_EPCTRL_TX_ENABLE)) == 0) + { + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM] |= + USB_32BIT_LE(ARC_USB_BULK_ENDPOINT << EHCI_EPCTRL_TX_EP_TYPE_SHIFT); + } + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, + "init ep #%d %s: type=0x%x, EPCTRLX=0x%x, SETUP=0x%x, PRIME=0x%x, STATUS=0x%x, COMPL=0x%x\n", + xd_ptr->EP_NUM, xd_ptr->BDIRECTION ? "SEND" : "RECV", xd_ptr->EP_TYPE, + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[xd_ptr->EP_NUM]), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE) ); + } + else + { + USB_printf("ep=%d %s: Init ERROR: ENDPTPRIME=0x%x, ENDPTSTATUS=0x%x, bit_pos=0x%x\n", + (unsigned)xd_ptr->EP_NUM, xd_ptr->BDIRECTION ? "SEND" : "RECV", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + (unsigned)bit_pos); + return USBERR_EP_INIT_FAILED; + } /* Endif */ + + return USB_OK; + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_get_transfer_status +* Returned Value : USB_OK or error code +* Comments : +* Gets the status of a transfer +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_dci_vusb20_get_transfer_status + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_EP_TR_STRUCT_PTR dTD_ptr; + XD_STRUCT_PTR xd_ptr; + uint_8 status; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + + /* Unlink the dTD */ + dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[2*ep_num + direction]; + + if (dTD_ptr) + { + /* Get the transfer descriptor for the dTD */ + xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD; + status = xd_ptr->BSTATUS; + } + else + { + status = ARC_USB_STATUS_IDLE; + } /* Endif */ + + return (status); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_get_transfer_details +* Returned Value : pointer to structure that has details for transfer +* Gets the status of a transfer +* +*END*-----------------------------------------------------------------*/ +XD_STRUCT_PTR _usb_dci_vusb20_get_transfer_details + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + VUSB20_EP_TR_STRUCT_PTR dTD_ptr, temp_dTD_ptr; + XD_STRUCT_PTR xd_ptr; + uint_32 temp, remaining_bytes; + VUSB20_EP_QUEUE_HEAD_STRUCT_PTR ep_queue_head_ptr; + + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + temp = (2*ep_num + direction); + + /* get a pointer to QH for this endpoint */ + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + temp; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "get_transfer_details\n"); + + /* Unlink the dTD */ + dTD_ptr = usb_dev_ptr->EP_DTD_HEADS[2*ep_num + direction]; + + if (dTD_ptr) + { + /* Get the transfer descriptor for the dTD */ + xd_ptr = (XD_STRUCT_PTR)dTD_ptr->SCRATCH_PTR->XD_FOR_THIS_DTD; + if(!xd_ptr) return NULL; + + /* Initialize the transfer length field */ + xd_ptr->WSOFAR =0; + remaining_bytes =0; + + /*if length of this transfer is greater than 20K + we have multiple DTDs to count */ + if(xd_ptr->WTOTALLENGTH > VUSB_EP_MAX_LENGTH_TRANSFER) + { + /* it is a valid DTD. We should parse all DTDs for this XD + and find the total bytes used so far */ + temp_dTD_ptr = dTD_ptr; + + /*loop through the list of DTDS until an active DTD is found + or list has finished */ + while(!(USB_32BIT_LE(dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_NEXT_TERMINATE)) + { + + /********************************************************** + If this DTD has been overlayed, we take the actual length + from QH. + **********************************************************/ + + if ((uint_32)(USB_32BIT_LE(ep_queue_head_ptr->CURR_DTD_PTR) & VUSBHS_TD_ADDR_MASK) == + USB_DTD_VIRT_TO_PHYS(usb_dev_ptr, temp_dTD_ptr) ) + { + remaining_bytes += + ((USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16); + } + else + { + /* take the length from DTD itself */ + remaining_bytes += + ((USB_32BIT_LE(temp_dTD_ptr->SIZE_IOC_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16); + } + + dTD_ptr = temp_dTD_ptr; + + /* Get the address of the next dTD */ + temp_dTD_ptr = (VUSB20_EP_TR_STRUCT_PTR)USB_DTD_PHYS_TO_VIRT(usb_dev_ptr, + (uint_32)(USB_32BIT_LE(temp_dTD_ptr->NEXT_TR_ELEM_PTR) & VUSBHS_TD_ADDR_MASK) ); + } + xd_ptr->WSOFAR = xd_ptr->WTOTALLENGTH - remaining_bytes; + } + else + { + /*look at actual length from QH*/ + xd_ptr->WSOFAR = xd_ptr->WTOTALLENGTH - + ((USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS) & VUSB_EP_TR_PACKET_SIZE) >> 16); + } + } + else + { + xd_ptr = NULL; + } /* Endif */ + + return (xd_ptr); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_deinit_endpoint +* Returned Value : None +* Comments : +* Disables the specified endpoint and the endpoint queue head +* +*END*-----------------------------------------------------------------*/ +uint_8 _usb_dci_vusb20_deinit_endpoint + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + VUSB20_EP_QUEUE_HEAD_STRUCT* ep_queue_head_ptr; + uint_32 bit_pos; + uint_8 status = USB_OK; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Get the endpoint queue head address */ + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + + (2*ep_num + direction); + + bit_pos = (1 << (16 * direction + ep_num)); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, + "deinit ep #%d-%s: bit_pos=0x%x, EPCTRLX=0x%x, SETUP=0x%x, PRIME=0x%x, STATUS=0x%x, COMPL=0x%x\n", + ep_num, direction ? "SEND" : "RECV", bit_pos, + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num]), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPT_SETUP_STAT), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCOMPLETE) ); + + /* Check if the Endpoint is Primed */ + if( ((USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME) & bit_pos)) || + ((USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS) & bit_pos)) ) + { + USB_printf("ep=%d %s: Deinit ERROR: ENDPTPRIME=0x%x, ENDPTSTATUS=0x%x, bit_pos=0x%x\n", + (unsigned)ep_num, direction ? "SEND" : "RECV", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTPRIME), + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTSTATUS), + (unsigned)bit_pos); + status = USBERR_EP_DEINIT_FAILED; + } + + /* Reset the max packet length and the interrupt on Setup */ + ep_queue_head_ptr->MAX_PKT_LENGTH = 0; + + /* Disable the endpoint for Rx or Tx and reset the endpoint type */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= + USB_32BIT_LE( ~((direction ? EHCI_EPCTRL_TX_ENABLE : EHCI_EPCTRL_RX_ENABLE) | + (direction ? EHCI_EPCTRL_TX_TYPE : EHCI_EPCTRL_RX_TYPE))); + + return status; +} + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_shutdown +* Returned Value : None +* Comments : +* Shuts down the VUSB_HS Device +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_shutdown + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Disable interrupts */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR &= + ~(USB_32BIT_LE(EHCI_INTR_INT_EN | EHCI_INTR_ERR_INT_EN | + EHCI_INTR_PORT_CHANGE_DETECT_EN | EHCI_INTR_RESET_EN)); + + USB_uncached_memfree(usb_dev_ptr->EP_QUEUE_HEAD_BASE, + usb_dev_ptr->EP_QUEUE_HEAD_SIZE, + usb_dev_ptr->EP_QUEUE_HEAD_PHYS); + + USB_uncached_memfree(usb_dev_ptr->DTD_BASE_PTR, + usb_dev_ptr->DTD_SIZE, + usb_dev_ptr->DTD_BASE_PHYS); + + USB_memfree(usb_dev_ptr->SCRATCH_STRUCT_BASE); + + USB_printf("USB shutdown: usb_dev_ptr=%p\n", usb_dev_ptr); + + /* Reset the Run the bit in the command register to stop VUSB */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= ~USB_32BIT_LE(EHCI_CMD_RUN_STOP); + + /* Reset the controller to get default values */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD = USB_32BIT_LE(EHCI_CMD_CTRL_RESET); + +} /* EndBody */ +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_stop +* Returned Value : None +* Comments : +* Stop USB device controller +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_stop(_usb_device_handle handle) +{ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Disable interrupts */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR &= + ~(USB_32BIT_LE(EHCI_INTR_INT_EN | EHCI_INTR_ERR_INT_EN | + EHCI_INTR_PORT_CHANGE_DETECT_EN | EHCI_INTR_RESET_EN)); + + /* Reset the Run the bit in the command register to stop VUSB */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD &= ~USB_32BIT_LE(EHCI_CMD_RUN_STOP); +} + + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_start +* Returned Value : None +* Comments : +* Start USB device controller +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_start(_usb_device_handle handle) +{ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Enable interrupts */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_INTR = USB_32BIT_LE( + EHCI_INTR_INT_EN + | EHCI_INTR_ERR_INT_EN + | EHCI_INTR_PORT_CHANGE_DETECT_EN + | EHCI_INTR_RESET_EN + | EHCI_INTR_DEVICE_SUSPEND + /* + | EHCI_INTR_SOF_UFRAME_EN + */ + ); + + usb_dev_ptr->USB_STATE = ARC_USB_STATE_UNKNOWN; + + /* Set the Run bit in the command register */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.USB_CMD = USB_32BIT_LE(EHCI_CMD_RUN_STOP); +} + +/* EOF */ + diff --git a/board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevUtl.c b/board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevUtl.c new file mode 100644 index 0000000..579bb3a --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/device/mvUsbHsDevUtl.c @@ -0,0 +1,271 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#include "mvUsbDevApi.h" +#include "mvUsbDevPrv.h" +#include "mvUsbDefs.h" + +/* Test packet for Test Mode : TEST_PACKET. USB 2.0 Specification section 7.1.20 */ +uint_8 test_packet[USB_TEST_MODE_TEST_PACKET_LENGTH] = +{ + /* Synch */ + /* DATA 0 PID */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xDF, + 0xEF, 0xF7, 0xFB, 0xFD, 0xFC, 0x7E, 0xBF, 0xDF, + 0xEF, 0xF7, 0xFB, 0xFD, 0x7E +}; + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_assert_resume +* Returned Value : None +* Comments : +* Resume signalling for remote wakeup +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_assert_resume + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + uint_32 temp; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Assert the Resume signal */ + temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]); + temp &= ~EHCI_PORTSCX_W1C_BITS; + temp |= EHCI_PORTSCX_PORT_FORCE_RESUME; + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = USB_32BIT_LE(temp); + + /* Port change interrupt will be asserted at the end of resume + ** operation + */ + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_stall_endpoint +* Returned Value : None +* Comments : +* Stalls the specified endpoint +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_stall_endpoint + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + VUSB20_EP_QUEUE_HEAD_STRUCT _PTR_ ep_queue_head_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Get the endpoint queue head address */ + ep_queue_head_ptr = (VUSB20_EP_QUEUE_HEAD_STRUCT_PTR)usb_dev_ptr->EP_QUEUE_HEAD_PTR + + 2*ep_num + direction; + /* Stall the endpoint for Rx or Tx and set the endpoint type */ + if (ep_queue_head_ptr->MAX_PKT_LENGTH & USB_32BIT_LE(VUSB_EP_QUEUE_HEAD_IOS)) + { + /* This is a control endpoint so STALL both directions */ + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= + USB_32BIT_LE((EHCI_EPCTRL_TX_EP_STALL | EHCI_EPCTRL_RX_EP_STALL)); + } + else + { + if(direction) + { + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= + USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL); + } + else { + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= + USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL); + } + } /* Endif */ + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STALL, + "STALL ep=%d %s: EPCTRLX=0x%x, CURR_dTD=0x%x, NEXT_dTD=0x%x, SIZE=0x%x\n", + ep_num, direction ? "SEND" : "RECV", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num]), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->CURR_DTD_PTR), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->NEXT_DTD_PTR), + (unsigned)USB_32BIT_LE(ep_queue_head_ptr->SIZE_IOC_INT_STS)); + +} /* EndBody */ + +/*FUNCTION*------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_unstall_endpoint +* Returned Value : None +* Comments : +* Unstall the specified endpoint in the specified direction +* +*END*-----------------------------------------------------------------*/ +void _usb_dci_vusb20_unstall_endpoint + ( + /* [IN] the USB_dev_initialize state structure */ + _usb_device_handle handle, + + /* [IN] the Endpoint number */ + uint_8 ep_num, + + /* [IN] direction */ + uint_8 direction + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + /* Enable the endpoint for Rx or Tx and set the endpoint type */ + if(direction) + { + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= + USB_32BIT_LE(EHCI_EPCTRL_TX_DATA_TOGGLE_RST); + + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= + ~(USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL)); + } + else + { + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] |= + USB_32BIT_LE(EHCI_EPCTRL_RX_DATA_TOGGLE_RST); + + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num] &= + ~(USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL)); + } + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_STALL, + "UNSTALL ep=%d %s: EPCTRLX=0x%x\n", + ep_num, direction ? "SEND" : "RECV", + (unsigned)USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep_num])); + + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_is_endpoint_stalled +* Returned Value : None +* Comments : +* Gets the endpoint status +* +*END*--------------------------------------------------------------------*/ +uint_8 _usb_dci_vusb20_is_endpoint_stalled + ( + /* [IN] Handle to the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep, + + /* [IN] Endpoint direction */ + uint_8 dir + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + uint_32 value; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_TRACE, "is_endpoint_stalled\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + if(dir) + { + value = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep] & + (USB_32BIT_LE(EHCI_EPCTRL_TX_EP_STALL)); + } + else + { + value = dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[ep] & + (USB_32BIT_LE(EHCI_EPCTRL_RX_EP_STALL)); + } + return (value) ? 1 : 0; +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _usb_dci_vusb20_set_test_mode +* Returned Value : None +* Comments : +* sets/resets the test mode +* +*END*--------------------------------------------------------------------*/ +void _usb_dci_vusb20_set_test_mode + ( + /* [IN] Handle to the USB device */ + _usb_device_handle handle, + + /* [IN] Test mode */ + uint_16 test_mode + ) +{ /* Body */ + USB_DEV_STATE_STRUCT_PTR usb_dev_ptr; + VUSB20_REG_STRUCT_PTR dev_ptr; + uint_32 temp; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_ANY, "set_test_mode\n"); + + usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)handle; + dev_ptr = (VUSB20_REG_STRUCT_PTR)usb_dev_ptr->DEV_PTR; + + temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0]); + + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.ENDPTCTRLX[0] = + USB_32BIT_LE((temp | EHCI_EPCTRL_TX_DATA_TOGGLE_RST)); + + if (test_mode == ARC_USB_TEST_MODE_TEST_PACKET) + { + USB_memcopy(test_packet, usb_dev_ptr->TEST_PKT_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH); + _usb_device_send_data(handle, 0, usb_dev_ptr->TEST_PKT_PTR, USB_TEST_MODE_TEST_PACKET_LENGTH); + + } /* Endif */ + + temp = USB_32BIT_LE(dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0]); + temp &= ~EHCI_PORTSCX_W1C_BITS; + + dev_ptr->REGISTERS.OPERATIONAL_DEVICE_REGISTERS.PORTSCX[0] = + USB_32BIT_LE(temp | ((uint_32)test_mode << 8)); + +} /* EndBody */ + diff --git a/board/mv_feroceon/mv_hal/usb/examples/disk.c b/board/mv_feroceon/mv_hal/usb/examples/disk.c new file mode 100644 index 0000000..48305c9 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/examples/disk.c @@ -0,0 +1,2296 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +/************************************************************************** +Include the USB stack and local header files. +**************************************************************************/ + +#include "mvUsbDefs.h" +#include "mvUsbCh9.h" +#include "mvUsbDebug.h" +#include "mvUsbDevApi.h" +#include "disk.h" + +/* MSB of debug flags for USB device usage */ +#define ARC_DEBUG_FLAG_DISK 0x01000000 +#define ARC_DEBUG_FLAG_DISK_READ 0x02000000 +#define ARC_DEBUG_FLAG_DISK_WRITE 0x04000000 +#define ARC_DEBUG_FLAG_DISK_CAP 0x08000000 +#define ARC_DEBUG_FLAG_DISK_DATA 0x10000000 +#define ARC_DEBUG_FLAG_DISK_DUMP 0x20000000 + + +/************************************************************************** +Include the OS and BSP dependent files that define IO functions and +basic types. You may like to change these files for your board and RTOS +**************************************************************************/ + + +/************************************************************************** +Global variables and some defines for device. +**************************************************************************/ + +#define BUFFERSIZE (2048) + +#define EP_TEMP_BUFFERSIZE (32) +#define MASS_STORAGE_INTERFACE (0) + +#define APP_CONTROL_MAX_PKT_SIZE (64) +#define DEV_DESC_MAX_PACKET_SIZE (7) +#define DISK_FS_MAX_PACKET_SIZE (64) +#define DISK_HS_MAX_PACKET_SIZE (512) + +#define CFG_DESC_EP_IN_TYPE_OFFSET (21) +#define CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET (22) +#define CFG_DESC_EP_OUT_TYPE_OFFSET (28) +#define CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET (29) + +#define TOTAL_LOGICAL_ADDRESS_BLOCKS (4096) +#define LENGTH_OF_EACH_LAB (512) + +#define DISK_IN_EP_NO 1 +#define DISK_OUT_EP_NO 2 + +#define DISK_IN_EP_TYPE 2 /* Bulk */ +#define DISK_OUT_EP_TYPE 2 /* Bulk */ + +typedef struct +{ + _usb_device_handle usbDevHandle; /* Must be first field */ + uint_32 devNo; + uint_8_ptr Send_Buffer_Unaligned; + + uint_8_ptr DevDesc; + uint_8_ptr DevQualifierDesc; + uint_8_ptr ConfigDesc; + uint_8_ptr other_speed_config; + uint_8_ptr ep1_buf; + uint_8_ptr epTemp_buf; + DISK_READ_CAPACITY* pReadCapacity; + CSW_STRUCT* pCSW; + uint_8_ptr MASS_STORAGE_DISK; + + SETUP_STRUCT local_setup_packet; + + volatile boolean TEST_ENABLED; + volatile boolean ENTER_TEST_MODE; + volatile uint_16 test_mode_index; + volatile uint_8 speed; + uint_16 logicalBlocks; + uint_32 hsMaxPktSize; + uint_32 fsMaxPktSize; + + uint_32 inEpType; + uint_32 outEpType; + + uint_32 inEpNo; + uint_32 outEpNo; + boolean CBW_PROCESSED; + boolean ZERO_TERMINATE; + +} USB_DISK_STRUCT; + +uint_32 diskHsMaxPktSize = DISK_HS_MAX_PACKET_SIZE; +uint_32 diskFsMaxPktSize = DISK_FS_MAX_PACKET_SIZE; + +uint_32 diskInEpType = DISK_IN_EP_TYPE; +uint_32 diskOutEpType = DISK_OUT_EP_TYPE; + +uint_32 diskInEpNo = DISK_IN_EP_NO; +uint_32 diskOutEpNo = DISK_OUT_EP_NO; + +static USB_DISK_STRUCT* usbDisksPtr[MAX_USB_DEVICES] = { NULL, NULL }; + +/************************************************************************** +DESCRIPTORS DESCRIPTORS DESCRIPTORS DESCRIPTORS DESCRIPTORS DESCRIPTORS +**************************************************************************/ + +#define DEVICE_DESCRIPTOR_SIZE 18 +static const uint_8 DevDescData[DEVICE_DESCRIPTOR_SIZE] = +{ + /* Length of DevDesc */ + DEVICE_DESCRIPTOR_SIZE, + /* "Device" Type of descriptor */ + 1, + /* BCD USB version */ + 0, 2, + /* Device Class is indicated in the interface descriptors */ + 0x00, + /* Device Subclass is indicated in the interface descriptors */ + 0x00, + /* Mass storage devices do not use class-specific protocols */ + 0x00, + /* Max packet size */ + APP_CONTROL_MAX_PKT_SIZE, + /* Vendor ID */ + USB_uint_16_low(0x1286), USB_uint_16_high(0x1286), + /* Product ID */ + USB_uint_16_low(0x1), USB_uint_16_high(0x1), + /* BCD Device version */ + USB_uint_16_low(0x0002), USB_uint_16_high(0x0002), + /* Manufacturer string index */ + 0x1, + /* Product string index */ + 0x2, + /* Serial number string index */ + 0x6, + /* Number of configurations available */ + 0x1 +}; + +/* USB 2.0 specific descriptor */ +#define DEVICE_QUALIFIER_DESCRIPTOR_SIZE 10 +static const uint_8 DevQualifierDescData[DEVICE_QUALIFIER_DESCRIPTOR_SIZE] = +{ + DEVICE_QUALIFIER_DESCRIPTOR_SIZE, /* bLength Length of this descriptor */ + 6, /* bDescType This is a DEVICE Qualifier descr */ + 0,2, /* bcdUSB USB revision 2.0 */ + 0, /* bDeviceClass */ + 0, /* bDeviceSubClass */ + 0, /* bDeviceProtocol */ + APP_CONTROL_MAX_PKT_SIZE, /* bMaxPacketSize0 */ + 0x01, /* bNumConfigurations */ + 0 +}; + +#define CONFIG_DESC_NUM_INTERFACES (4) +/* This must be counted manually and updated with the descriptor */ +/* 1*Config(9) + 1*Interface(9) + 2*Endpoint(7) = 32 bytes */ +#define CONFIG_DESC_SIZE (32) + +/************************************************************** +we declare the config desc as USB_Uncached because this descriptor +is updated on the fly for max packet size during enumeration. Making +it uncached ensures that main memory is updated whenever this +descriptor pointer is used. +**************************************************************/ +static const uint_8 ConfigDescData[CONFIG_DESC_SIZE] = +{ + /* Configuration Descriptor - always 9 bytes */ + 9, + /* "Configuration" type of descriptor */ + 2, + /* Total length of the Configuration descriptor */ + USB_uint_16_low(CONFIG_DESC_SIZE), + USB_uint_16_high(CONFIG_DESC_SIZE), + /* NumInterfaces */ + 1, + /* Configuration Value */ + 1, + /* Configuration Description String Index*/ + 4, + /* Attributes. Self-powered. */ + 0xc0, + /* Current draw from bus */ + 0, + /* Interface 0 Descriptor - always 9 bytes */ + 9, + /* "Interface" type of descriptor */ + 4, + /* Number of this interface */ + MASS_STORAGE_INTERFACE, + /* Alternate Setting */ + 0, + /* Number of endpoints on this interface */ + 2, + /* Interface Class */ + 0x08, + /* Interface Subclass: SCSI transparent command set */ + 0x06, + /* Interface Protocol: Bulk only protocol */ + 0x50, + /* Interface Description String Index */ + 0, + /* Endpoint 1 (Bulk In Endpoint), Interface 0 Descriptor - always 7 bytes*/ + 7, + /* "Endpoint" type of descriptor */ + 5, + /* + ** Endpoint address. The low nibble contains the endpoint number and the + ** high bit indicates TX(1) or RX(0). + */ + ((ARC_USB_SEND<<7) | DISK_IN_EP_NO) /*0x81*/, + /* Attributes. 0=Control 1=Isochronous 2=Bulk 3=Interrupt */ + DISK_IN_EP_TYPE, + /* Max Packet Size for this endpoint */ + USB_uint_16_low(DISK_FS_MAX_PACKET_SIZE), + USB_uint_16_high(DISK_FS_MAX_PACKET_SIZE), + /* Polling Interval (ms) */ + 0, + /* Endpoint 2 (Bulk Out Endpoint), Interface 0 Descriptor - always 7 bytes*/ + 7, + /* "Endpoint" type of descriptor */ + 5, + /* + ** Endpoint address. The low nibble contains the endpoint number and the + ** high bit indicates TX(1) or RX(0). + */ + ((ARC_USB_RECV<<7) | DISK_OUT_EP_NO), /*0x02*/ + /* Attributes. 0=Control 1=Isochronous 2=Bulk 3=Interrupt */ + DISK_OUT_EP_TYPE, + /* Max Packet Size for this endpoint */ + USB_uint_16_low(DISK_FS_MAX_PACKET_SIZE), + USB_uint_16_high(DISK_FS_MAX_PACKET_SIZE), + /* Polling Interval (ms) */ + 0 +}; + +#define OTHER_SPEED_CONFIG_DESC_SIZE CONFIG_DESC_SIZE +static const uint_8 other_speed_config_data[CONFIG_DESC_SIZE] = +{ + 9, /* bLength Length of this descriptor */ + 7, /* bDescType This is a Other speed config descr */ + USB_uint_16_low(OTHER_SPEED_CONFIG_DESC_SIZE), + USB_uint_16_high(OTHER_SPEED_CONFIG_DESC_SIZE), + 1, + 1, + 4, + 0xc0, + 0, + /* Interface 0 Descriptor - always 9 bytes */ + 9, + /* "Interface" type of descriptor */ + 4, + /* Number of this interface */ + MASS_STORAGE_INTERFACE, + /* Alternate Setting */ + 0, + /* Number of endpoints on this interface */ + 2, + /* Interface Class */ + 0x08, + /* Interface Subclass: SCSI transparent command set */ + 0x06, + /* Interface Protocol: Bulk only protocol */ + 0x50, + /* Interface Description String Index */ + 0, + /* Endpoint 1 (Bulk In Endpoint), Interface 0 Descriptor - always 7 bytes*/ + 7, + /* "Endpoint" type of descriptor */ + 5, + /* + ** Endpoint address. The low nibble contains the endpoint number and the + ** high bit indicates TX(1) or RX(0). + */ + ((ARC_USB_SEND<<7) | DISK_IN_EP_NO), /*0x81*/ + /* Attributes. 0=Control 1=Isochronous 2=Bulk 3=Interrupt */ + DISK_IN_EP_TYPE, + /* Max Packet Size for this endpoint */ + USB_uint_16_low(DISK_HS_MAX_PACKET_SIZE), + USB_uint_16_high(DISK_HS_MAX_PACKET_SIZE), + /* Polling Interval (ms) */ + 0, + /* Endpoint 2 (Bulk Out Endpoint), Interface 0 Descriptor - always 7 bytes*/ + 7, + /* "Endpoint" type of descriptor */ + 5, + /* + ** Endpoint address. The low nibble contains the endpoint number and the + ** high bit indicates TX(1) or RX(0). + */ + ((ARC_USB_RECV<<7) | DISK_OUT_EP_NO), /*0x02*/ + + /* Attributes. 0=Control 1=Isochronous 2=Bulk 3=Interrupt */ + DISK_OUT_EP_TYPE, + /* Max Packet Size for this endpoint */ + USB_uint_16_low(DISK_HS_MAX_PACKET_SIZE), + USB_uint_16_high(DISK_HS_MAX_PACKET_SIZE), + /* Polling Interval (ms) */ + 0 +}; + +static uint_8 USB_IF_ALT[4] = { 0, 0, 0, 0}; + +/* number of strings in the table not including 0 or n. */ +static const uint_8 USB_STR_NUM = 7; + +/* +** if the number of strings changes, look for USB_STR_0 everywhere and make +** the obvious changes. It should be found in 3 places. +*/ + +static uint_16 USB_STR_0[ 2] = {(0x300 + sizeof(USB_STR_0)),(0x0409)}; +static uint_16 USB_STR_1[26] = {(0x300 + sizeof(USB_STR_1)), + 'M','a','r','v','e','l','l',' ','S','e','m','i','c','o','n','d','u','c','t','o','r',' ','L','t','d'}; +static uint_16 USB_STR_2[28] = {(0x300 + sizeof(USB_STR_2)), + 'M','A','R','V','E','L','L',' ','M','a','s','s',' ','S','t','o','r','a','g','e',' ',\ + 'D','e','v','i','c','e'}; +static uint_16 USB_STR_3[ 5] = {(0x300 + sizeof(USB_STR_3)), + 'B','E','T','A'}; +static uint_16 USB_STR_4[ 4] = {(0x300 + sizeof(USB_STR_4)), + '#','0','2'}; +static uint_16 USB_STR_5[ 4] = {(0x300 + sizeof(USB_STR_5)), + '_','A','1'}; + /* Serial number has to be at least 12 bytes */ +static uint_16 USB_STR_6[ 13] = {(0x300 + sizeof(USB_STR_6)), + '0','0','0','0','0','0','0','0','0','0','0','1'}; +static uint_16 USB_STR_7[15] = {(0x300 + sizeof(USB_STR_7)), + 'Y','o','u','r',' ','n','a','m','e',' ','h','e','r','e'}; +static uint_16 USB_STR_n[17] = {(0x300 + sizeof(USB_STR_n)), + 'B','A','D',' ','S','T','R','I','N','G',' ','I','n','d','e','x'}; + +#define USB_STRING_ARRAY_SIZE 9 +static uint_8_ptr USB_STRING_DESC[USB_STRING_ARRAY_SIZE] = +{ + (uint_8_ptr)((pointer)USB_STR_0), + (uint_8_ptr)((pointer)USB_STR_1), + (uint_8_ptr)((pointer)USB_STR_2), + (uint_8_ptr)((pointer)USB_STR_3), + (uint_8_ptr)((pointer)USB_STR_4), + (uint_8_ptr)((pointer)USB_STR_5), + (uint_8_ptr)((pointer)USB_STR_6), + (uint_8_ptr)((pointer)USB_STR_7), + (uint_8_ptr)((pointer)USB_STR_n) +}; + +/***************************************************************** +MASS STORAGE SPECIFIC GLOBALS +*****************************************************************/ + +static const DISK_DEVICE_INFO device_information_data = +{ + 0, 0x80, 0, 0x01, 0x1F, + /* Reserved */ + {0, 0, 0}, + /* Vendor information: "MARVELL " */ + {0x4D, 0x41, 0x52, 0x56, 0x45, 0x4C, 0x4C, 0x20,}, + /* Product information: "Disk " */ + {0x44, 0x69, 0x73, 0x6B, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, + /* Product Revision level: "Demo" */ + {0x44, 0x65, 0x6D, 0x6F} +}; + +static const DISK_READ_CAPACITY read_capacity = +{ + /* Data for the capacity */ + { + 0x00, 0x00, USB_uint_16_high(TOTAL_LOGICAL_ADDRESS_BLOCKS-14), + USB_uint_16_low(TOTAL_LOGICAL_ADDRESS_BLOCKS-14) + }, + { + 0x00, 0x00, USB_uint_16_high(LENGTH_OF_EACH_LAB), + USB_uint_16_low(LENGTH_OF_EACH_LAB) + } +}; + +static const uint_8 BOOT_SECTOR_AREA[512] = +{ + /* Block 0 is the boot sector. Following is the data in the boot sector */ + /* 80x86 "short: jump instruction, indicating that the disk is formatted */ + 0xEB, + /* 8-bit displacement */ + 0x3C, + /* NOP OPCode */ + 0x90, + /* 8-bytes for OEM identification: "ARC 4.3 " */ + 0x41, 0x52, 0x43, 0x20, 0x34, 0x2E, 0x33, 0x20, + /* bytes/sector: 512 bytes (0x0200) */ + 0x00, 0x02, + /* Sectors/allocation unit */ + 0x01, + /* Reserved sectors: 0x0001 */ + 0x01, 0x00, + /* Number of File Allocation Tables (FATs): 2 */ + 0x02, + /* Number of root directory entries */ + 0x00, 0x02, + /* Total Small sectors in logical volume */ + USB_uint_16_low(TOTAL_LOGICAL_ADDRESS_BLOCKS), + USB_uint_16_high(TOTAL_LOGICAL_ADDRESS_BLOCKS), + /* Media descriptor byte: 0xF8: Fixed disk */ + 0xF8, + /* Sectors/FAT: 3 (Each FAT starts at a new sector) */ + 0x80, 0x00, + /* Sectors/track: 9 */ + 0x09, 0x00, + /* Number of heads */ + 0x02, 0x00, + /* Number of hidden sectors: 0 */ + 0x00, 0x00, 0x00, 0x00, + /* Total Large sectors in logical volume */ + 0x00, 0x00, 0x00, 0x00, + /* Physical drive number */ + 0x00, + /* Reserved */ + 0x00, + /* Extended boot signature record: 0x29 */ + 0x29, + /* 32-bit binary volume ID */ + 0x01, 0x02, 0x03, 0x04, + /* Volume label */ + 0x53, 0x54, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + /* Reserved FAT-16*/ + 0x46, 0x41, 0x54, 0x31, 0x36, 0x00, 0x00, 0x00, + /* Bootstrap */ + 0x33, 0xC0, 0x8E, 0xD0, 0xBC, 0x00, 0x7C, 0xFC, 0xE8, 0x45, 0x00, + /* String: \r\nNon-System disk\r\nPress any key to reboot\r\n" */ + 0x0D, 0x0A, 0x4E, 0x6F, 0x6E, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6D, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x0D, 0x0A, 0x50, 0x72, 0x65, + 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, + 0x74, 0x6F, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, 0x0D, 0x0A, + 0x5E, 0xEB, 0x02, 0xCD, 0x10, 0xB4, 0x0E, 0xBB, 0x07, 0x00, 0x2E, + 0xAC, 0x84, 0xC0, 0x75, 0xF3, 0x98, 0xCD, 0x16, 0xCD, 0x19, 0xEB, + 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Partition descriptors */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA +}; + + +static const uint_8 FAT16_SPECIAL_BYTES[3] = +{ + /* FAT ID: Same as Media descriptor */ + 0xF8, 0xFF, 0xFF +}; + + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9GetDescription +* Returned Value : None +* Comments : +* Chapter 9 GetDescription command +* The Device Request can ask for Device/Config/string/interface/endpoint +* descriptors (via wValue). We then post an IN response to return the +* requested descriptor. +* And then wait for the OUT which terminates the control transfer. +* +*END*--------------------------------------------------------------------*/ +static void ch9GetDescription + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + uint_32 max_pkt_size; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d, value=0x%x, length=%d\n", + __FUNCTION__, (int)setup, setup_ptr->VALUE, setup_ptr->LENGTH); + + if (setup) + { + /* Load the appropriate string depending on the descriptor requested.*/ + switch (setup_ptr->VALUE & 0xFF00) + { + case 0x0100: + _usb_device_send_data(handle, 0, pDiskCtrl->DevDesc, + MIN(setup_ptr->LENGTH, DEVICE_DESCRIPTOR_SIZE)); + break; + + case 0x0200: + /* Set the Max Packet Size in the config and other speed config */ + if(pDiskCtrl->speed == ARC_USB_SPEED_HIGH) + { + max_pkt_size = pDiskCtrl->hsMaxPktSize; + } + else + { + max_pkt_size = pDiskCtrl->fsMaxPktSize; + } /* Endif */ + + *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_IN_TYPE_OFFSET) = (uint_8)pDiskCtrl->inEpType; + + *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET) = + USB_uint_16_low(max_pkt_size); + *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET+1) = + USB_uint_16_high(max_pkt_size); + + *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_OUT_TYPE_OFFSET) = (uint_8)pDiskCtrl->outEpType; + + *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET) = + USB_uint_16_low(max_pkt_size); + *(pDiskCtrl->ConfigDesc + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET+1) = + USB_uint_16_high(max_pkt_size); + + _usb_device_send_data(handle, 0, pDiskCtrl->ConfigDesc, + MIN(setup_ptr->LENGTH, CONFIG_DESC_SIZE)); + break; + + case 0x0300: + if ((setup_ptr->VALUE & 0x00FF) > USB_STR_NUM) { + _usb_device_send_data(handle, 0, USB_STRING_DESC[USB_STR_NUM+1], + MIN(setup_ptr->LENGTH, USB_STRING_DESC[USB_STR_NUM+1][0])); + } + else + { + _usb_device_send_data(handle, 0, USB_STRING_DESC[setup_ptr->VALUE & 0x00FF], + MIN(setup_ptr->LENGTH, USB_STRING_DESC[setup_ptr->VALUE & 0x00FF][0])); + } /* Endif */ + break; + + case 0x600: + _usb_device_send_data(handle, 0, (uint_8_ptr)pDiskCtrl->DevQualifierDesc, + MIN(setup_ptr->LENGTH, DEVICE_QUALIFIER_DESCRIPTOR_SIZE)); + break; + + case 0x700: + if(pDiskCtrl->speed == ARC_USB_SPEED_HIGH) + { + max_pkt_size = pDiskCtrl->fsMaxPktSize; + } + else + { + max_pkt_size = pDiskCtrl->hsMaxPktSize; + } /* Endif */ + + *(pDiskCtrl->other_speed_config + CFG_DESC_EP_IN_TYPE_OFFSET) = (uint_8)pDiskCtrl->inEpType; + + *(pDiskCtrl->other_speed_config + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET) = + USB_uint_16_low(max_pkt_size); + *(pDiskCtrl->other_speed_config + CFG_DESC_EP_IN_MAX_PACKET_SIZE_OFFSET+1) = + USB_uint_16_high(max_pkt_size); + + *(pDiskCtrl->other_speed_config + CFG_DESC_EP_OUT_TYPE_OFFSET) = (uint_8)pDiskCtrl->outEpType; + + *(pDiskCtrl->other_speed_config + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET) = + USB_uint_16_low(max_pkt_size); + *(pDiskCtrl->other_speed_config + CFG_DESC_EP_OUT_MAX_PACKET_SIZE_OFFSET+1) = + USB_uint_16_high(max_pkt_size); + + _usb_device_send_data(handle, 0, (uint_8_ptr)pDiskCtrl->other_speed_config, + MIN(setup_ptr->LENGTH, OTHER_SPEED_CONFIG_DESC_SIZE)); + + break; + + default: + USB_printf("usbDisk_%d, %s: Unexpected VALUE=0x%04x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endswitch */ + /* status phase */ + _usb_device_recv_data(handle, 0, NULL, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SetDescription +* Returned Value : None +* Comments : +* Chapter 9 SetDescription command +* +*END*--------------------------------------------------------------------*/ +static void ch9SetDescription + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + USB_printf("usbDisk_%d, %s: setup=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, (int)setup); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9GetConfig +* Returned Value : None +* Comments : +* Chapter 9 GetConfig command +* +*END*--------------------------------------------------------------------*/ +static void ch9GetConfig + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + uint_16 current_config; + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", __FUNCTION__, (int)setup); + + /* Return the currently selected configuration */ + if (setup) + { + _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, + ¤t_config); + *pDiskCtrl->epTemp_buf = (current_config & 0xFF); + _usb_device_send_data(handle, 0, pDiskCtrl->epTemp_buf, sizeof(uint_8)); + /* status phase */ + _usb_device_recv_data(handle, 0, NULL, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SetConfig +* Returned Value : None +* Comments : +* Chapter 9 SetConfig command +* +*END*--------------------------------------------------------------------*/ +static void ch9SetConfig + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + uint_16 usb_state; + uint_32 max_pkt_size; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d, value=0x%x\n", + __FUNCTION__, (int)setup, setup_ptr->VALUE); + + if (setup) + { + if ((setup_ptr->VALUE & 0x00FF) > 1) + { + /* generate stall */ + USB_printf("usbDisk_%d, %s: Wrong VALUE=0x%04x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + /* 0 indicates return to unconfigured state */ + if ((setup_ptr->VALUE & 0x00FF) == 0) + { + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state); + if( (usb_state == ARC_USB_STATE_CONFIG) || + (usb_state == ARC_USB_STATE_ADDRESS) ) + { + /* clear the currently selected config value */ + _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, 0); + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, + ARC_USB_STATE_ADDRESS); + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); + } + else + { + USB_printf("usbDisk_%d, %s: Wrong usb_state=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, usb_state); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + } /* Endif */ + return; + } /* Endif */ + + /* + ** If the configuration value (setup_ptr->VALUE & 0x00FF) differs + ** from the current configuration value, then endpoints must be + ** reconfigured to match the new device configuration + */ + _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, + &usb_state); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk: Set configuration: old=%d, new=%d\n", + usb_state, setup_ptr->VALUE & 0x00FF); + + if (usb_state != (setup_ptr->VALUE & 0x00FF)) + { + /* Reconfigure endpoints here */ + switch (setup_ptr->VALUE & 0x00FF) + { + default: + break; + } /* Endswitch */ + + _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, + setup_ptr->VALUE & 0x00FF); + } /* Endif */ + + if (pDiskCtrl->speed == ARC_USB_SPEED_HIGH) + { + max_pkt_size = pDiskCtrl->hsMaxPktSize; + } + else + { + max_pkt_size = pDiskCtrl->fsMaxPktSize; + } /* Endif */ + + _usb_device_init_endpoint(handle, pDiskCtrl->outEpNo, max_pkt_size, + ARC_USB_RECV, ARC_USB_BULK_ENDPOINT, ARC_USB_DEVICE_DONT_ZERO_TERMINATE); + _usb_device_init_endpoint(handle, pDiskCtrl->inEpNo, max_pkt_size, + ARC_USB_SEND, ARC_USB_BULK_ENDPOINT, ARC_USB_DEVICE_DONT_ZERO_TERMINATE); + + if (_usb_device_get_transfer_status(handle, pDiskCtrl->outEpNo, ARC_USB_RECV) == USB_OK) + { + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + } /* Endif */ + + pDiskCtrl->TEST_ENABLED = TRUE; + + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, + ARC_USB_STATE_CONFIG); + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); + + USB_printf("USB %s speed disk: config = %d\n", + (pDiskCtrl->speed == ARC_USB_SPEED_HIGH) ? "High" : "Full", + setup_ptr->VALUE & 0x00FF); + + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9GetInterface +* Returned Value : None +* Comments : +* Chapter 9 GetInterface command +* +*END*--------------------------------------------------------------------*/ +static void ch9GetInterface + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + uint_16 usb_state; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", __FUNCTION__, (int)setup); + + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state); + if (usb_state != ARC_USB_STATE_CONFIG) + { + USB_printf("usbDisk_%d, %s: Wrong usb_state=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, usb_state); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + if (setup) + { + _usb_device_send_data(handle, 0, &USB_IF_ALT[setup_ptr->INDEX & 0x00FF], + MIN(setup_ptr->LENGTH, sizeof(uint_8))); + /* status phase */ + _usb_device_recv_data(handle, 0, NULL, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SetInterface +* Returned Value : None +* Comments : +* Chapter 9 SetInterface command +* +*END*--------------------------------------------------------------------*/ +static void ch9SetInterface + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", __FUNCTION__, (int)setup); + + if (setup) + { + if (setup_ptr->REQUESTTYPE != 0x01) + { + USB_printf("usbDisk_%d, %s: Wrong REQUESTTYPE=0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, + setup_ptr->REQUESTTYPE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + /* + ** If the alternate value (setup_ptr->VALUE & 0x00FF) differs + ** from the current alternate value for the specified interface, + ** then endpoints must be reconfigured to match the new alternate + */ + if (USB_IF_ALT[setup_ptr->INDEX & 0x00FF] + != (setup_ptr->VALUE & 0x00FF)) + { + USB_IF_ALT[setup_ptr->INDEX & 0x00FF] = (setup_ptr->VALUE & 0x00FF); + /* Reconfigure endpoints here. */ + + } /* Endif */ + + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SynchFrame +* Returned Value : +* Comments : +* Chapter 9 SynchFrame command +* +*END*--------------------------------------------------------------------*/ +static void ch9SynchFrame + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + + uint_16 usbStatus; + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, "usbDisk %s: setup=%d\n", + __FUNCTION__, (int)setup); + + if (setup) + { + if (setup_ptr->REQUESTTYPE != (REQ_RECIP_ENDPOINT | REQ_TYPE_STANDARD | REQ_DIR_OUT) ) + { + USB_printf("usbDisk_%d, %s: Wrong REQUESTTYPE=0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, + setup_ptr->REQUESTTYPE); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + if ((setup_ptr->INDEX & 0x00FF) >= + pDiskCtrl->ConfigDesc[CONFIG_DESC_NUM_INTERFACES]) + { + USB_printf("usbDisk_%d, %s: Wrong INDEX=0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->INDEX); + _usb_device_stall_endpoint(handle, 0, ARC_USB_RECV); + return; + } /* Endif */ + + _usb_device_get_status(handle, ARC_USB_STATUS_SOF_COUNT, &usbStatus); + pDiskCtrl->epTemp_buf[0] = USB_uint_16_low(usbStatus); + pDiskCtrl->epTemp_buf[1] = USB_uint_16_high(usbStatus); + _usb_device_send_data(handle, 0, pDiskCtrl->epTemp_buf, MIN(setup_ptr->LENGTH, sizeof(uint_16))); + /* status phase */ + _usb_device_recv_data(handle, 0, NULL, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9Class +* Returned Value : +* Comments : +* Chapter 9 Class specific request +* See section 9.4.11 (page 195) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9Class + ( + _usb_device_handle handle, + boolean setup, + uint_8 direction, + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_CLASS, + "usbDisk %s: setup=%d, request=0x%x, value=%d, index=%d, size=%d\n", + __FUNCTION__, (int)setup, setup_ptr->REQUEST, + setup_ptr->VALUE, setup_ptr->INDEX, setup_ptr->LENGTH); + + if (setup) + { + switch (setup_ptr->REQUEST) + { + case 0xFF: + /* Bulk-Only Mass Storage Reset: Ready the device for the next + ** CBW from the host + */ + if ((setup_ptr->VALUE != 0) || + (setup_ptr->INDEX != MASS_STORAGE_INTERFACE) || + (setup_ptr->LENGTH != 0)) + { + USB_printf("usbDisk_%d, %s: Wrong Setup: VALUE=%d, INDEX=%d, LENGTH=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE, + setup_ptr->INDEX, setup_ptr->LENGTH); + + _usb_device_stall_endpoint(handle, 0, 0); + } + else + { /* Body */ + pDiskCtrl->CBW_PROCESSED = FALSE; + pDiskCtrl->ZERO_TERMINATE = FALSE; + _usb_device_cancel_transfer(handle, pDiskCtrl->outEpNo, ARC_USB_RECV); + _usb_device_cancel_transfer(handle, pDiskCtrl->inEpNo, ARC_USB_SEND); + + /* unstall bulk endpoint */ + _usb_device_unstall_endpoint(handle, pDiskCtrl->outEpNo, ARC_USB_RECV); + _usb_device_unstall_endpoint(handle, pDiskCtrl->inEpNo, ARC_USB_SEND); + + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + /* send zero packet to control pipe */ + _usb_device_send_data(handle, 0, NULL, 0); + } /* Endbody */ + break; + + case 0xFE: + /* For Get Max LUN use any of these responses*/ + if (setup_ptr->LENGTH == 0) + { /* Body */ + + USB_printf("usbDisk_%d, %s: Wrong Length: LENGTH=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->LENGTH); + + _usb_device_stall_endpoint(handle, 0, 0); + } + else + { + if ((setup_ptr->VALUE != 0) || + (setup_ptr->INDEX != MASS_STORAGE_INTERFACE) || + (setup_ptr->LENGTH != 1)) + { /* Body */ + USB_printf("usbDisk_%d, %s: Wrong Setup: VALUE=%d, INDEX=%d, LENGTH=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE, + setup_ptr->INDEX, setup_ptr->LENGTH); + _usb_device_stall_endpoint(handle, 0, 0); + } + else + { /* Body */ + /* Send Max LUN = 0 to the the control pipe */ + *pDiskCtrl->epTemp_buf = 0; + _usb_device_send_data(handle, 0, pDiskCtrl->epTemp_buf, 1); + /* status phase */ + _usb_device_recv_data(handle, 0, 0, 0); + } /* Endbody */ + } + break; + + default : + USB_printf("usbDisk_%d, %s: Wrong REQUEST=0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->REQUEST); + _usb_device_stall_endpoint(handle, 0, 0); + return; + } /* EndSwitch */ + } + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : service_ep0 +* Returned Value : None +* Comments : +* Called upon a completed endpoint 0 (USB 1.1 Chapter 9) transfer +* +*END*--------------------------------------------------------------------*/ +static void service_ep0 + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] request type as registered */ + uint_8 type, + + /* [IN] Is it a setup packet? */ + boolean setup, + + /* [IN] Direction of the transfer. Is it transmit? */ + uint_8 direction, + + /* [IN] Pointer to the data buffer */ + uint_8_ptr buffer, + + /* [IN] Length of the transfer */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + SETUP_STRUCT* pSetupPacket = &pDiskCtrl->local_setup_packet; + + if (setup) + { + _usb_device_read_setup_data(handle, 0, (uint_8_ptr)pSetupPacket); + pSetupPacket->VALUE = USB_16BIT_LE(pSetupPacket->VALUE); + pSetupPacket->INDEX = USB_16BIT_LE(pSetupPacket->INDEX); + pSetupPacket->LENGTH = USB_16BIT_LE(pSetupPacket->LENGTH); + } + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_EP0, + "disk %s: setup=%s, dir=%s, pBuf=0x%x, length=%d, reqType=0x%x, req=0x%x\n", + __FUNCTION__, (setup ? "YES" : "NO"), + (direction == ARC_USB_RECV) ? "RECV" : "SEND", + (unsigned)buffer, (int)length, pSetupPacket->REQUESTTYPE, + pSetupPacket->REQUEST); + + switch (pSetupPacket->REQUESTTYPE & REQ_TYPE_MASK) + { + case REQ_TYPE_STANDARD: + switch (pSetupPacket->REQUEST) + { + case REQ_GET_STATUS: + mvUsbCh9GetStatus(handle, setup, pSetupPacket); + break; + + case REQ_CLEAR_FEATURE: + mvUsbCh9ClearFeature(handle, setup, pSetupPacket); + break; + + case REQ_SET_FEATURE: + mvUsbCh9SetFeature(handle, setup, pSetupPacket); + break; + + case REQ_SET_ADDRESS: + mvUsbCh9SetAddress(handle, setup, pSetupPacket); + break; + + case REQ_GET_DESCRIPTOR: + ch9GetDescription(handle, setup, pSetupPacket); + break; + + case REQ_SET_DESCRIPTOR: + ch9SetDescription(handle, setup, pSetupPacket); + break; + + case REQ_GET_CONFIGURATION: + ch9GetConfig(handle, setup, pSetupPacket); + break; + + case REQ_SET_CONFIGURATION: + ch9SetConfig(handle, setup, pSetupPacket); + break; + + case REQ_GET_INTERFACE: + ch9GetInterface(handle, setup, pSetupPacket); + break; + + case REQ_SET_INTERFACE: + ch9SetInterface(handle, setup, pSetupPacket); + break; + + case REQ_SYNCH_FRAME: + ch9SynchFrame(handle, setup, pSetupPacket); + break; + + default: + USB_printf("usbDisk_%d, %s: Wrong REQUEST = 0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, pSetupPacket->REQUEST); + _usb_device_stall_endpoint(handle, 0, 0); + break; + + } /* Endswitch */ + + break; + + case REQ_TYPE_CLASS: + /* class specific request */ + ch9Class(handle, setup, direction, pSetupPacket); + return; + + case REQ_TYPE_VENDOR: + /* vendor specific request can be handled here*/ + USB_printf("usbDisk_%d, %s: Vendor REQUESTTYPE (%d) not supported\n", + _usb_device_get_dev_num(handle), __FUNCTION__, REQ_TYPE_VENDOR); + + _usb_device_stall_endpoint(handle, 0, 0); + break; + + default: + USB_printf("usbDisk_%d, %s: Unexpected REQUESTTYPE = 0x%x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, + pSetupPacket->REQUESTTYPE); + + _usb_device_stall_endpoint(handle, 0, 0); + break; + + } /* Endswitch */ + + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_inquiry_command +* Returned Value : None +* Comments : +* Process a Mass storage class Inquiry command +* +*END*--------------------------------------------------------------------*/ +void _process_inquiry_command + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + if (cbw_ptr->DCBWDATALENGTH) + { + if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) + { + /* Send the device information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)&device_information_data, 36); + } /* Endif */ + } /* Endif */ + + /* The actual length will never exceed the DCBWDATALENGTH */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH - 36); + pDiskCtrl->pCSW->BCSWSTATUS = 0; + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_unsupported_command +* Returned Value : None +* Comments : +* Responds appropriately to unsupported commands +* +*END*--------------------------------------------------------------------*/ +void _process_unsupported_command + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK, + "disk unsupported command: BMCBWFLAGS = 0x%02x\n", cbw_ptr->BMCBWFLAGS); + + /* The actual length will never exceed the DCBWDATALENGTH */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 0; + + if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) + { + /* Send a zero-length packet */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)NULL, 0); + } + else + { + pDiskCtrl->CBW_PROCESSED = FALSE; + /* Send the command status information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13); + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + } /* Endif */ + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_report_capacity +* Returned Value : None +* Comments : +* Reports the media capacity as a response to READ CAPACITY Command. +* +*END*--------------------------------------------------------------------*/ +void _process_report_capacity + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_CAP, + "disk read_capacity: BMCBWFLAGS = 0x%02x\n", cbw_ptr->BMCBWFLAGS); + + if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) + { + /* Send a zero-length packet */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pReadCapacity, 8); + + } /* Endif */ + + /* The actual length will never exceed the DCBWDATALENGTH */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 0; + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_read_command +* Returned Value : None +* Comments : +* Sends data as a response to READ Command. +* +*END*--------------------------------------------------------------------*/ +void _process_read_command + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + uint_32 index1 = 0, index2 = 0; + uint_32 max_pkt_size, byteSize; + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + if (cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) + { + /* Send a zero-length packet */ + index1 = ((uint_32)cbw_ptr->CBWCB[4] << 8); + index1 |= cbw_ptr->CBWCB[5]; + index2 = ((uint_32)cbw_ptr->CBWCB[7] << 8); + index2 |= (uint_32)cbw_ptr->CBWCB[8]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_READ, + "disk read: FLAGS=0x%02x, LENGTH=0x%x, index1=0x%x, index2=0x%x\n", + cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH, index1, index2); + + if(cbw_ptr->CBWCB[0] != 0x3E) + { + byteSize = index2 * LENGTH_OF_EACH_LAB; + } + else + { + byteSize = index2; + index2 = (USB_MEM_ALIGN(byteSize, LENGTH_OF_EACH_LAB) / LENGTH_OF_EACH_LAB); + } + + /* Check index validities */ + if( (index1 + index2) >= pDiskCtrl->logicalBlocks) + { + USB_printf("USB disk read: invalid indexes - addr=%d, size=%d\n", + index1, index2); + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH); + pDiskCtrl->pCSW->BCSWSTATUS = 1; + /* Send zero size packet */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)NULL, 0); + return; + } + + if (cbw_ptr->DCBWDATALENGTH == 0) + { /* Body */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 2; + pDiskCtrl->CBW_PROCESSED = FALSE; + /* Send the command status information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13); + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + return; + } + else + { /* Body */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 0; + if (byteSize > cbw_ptr->DCBWDATALENGTH) + { /* Body */ + byteSize = cbw_ptr->DCBWDATALENGTH; + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH); + pDiskCtrl->pCSW->BCSWSTATUS = 2; + } + else + { + if (byteSize < cbw_ptr->DCBWDATALENGTH) + { /* Body */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH - index2); + if (byteSize > 0) + { /* Body */ + if (pDiskCtrl->speed == ARC_USB_SPEED_HIGH) + { + max_pkt_size = pDiskCtrl->hsMaxPktSize; + } + else + { + max_pkt_size = pDiskCtrl->fsMaxPktSize; + } + + if( (byteSize % max_pkt_size) == 0) + { /* Body */ + /* Need send a zero terminate packet to host */ + pDiskCtrl->ZERO_TERMINATE = TRUE; + } /* Endbody */ + } /* Endbody */ + } /* Endbody */ + } + + _usb_device_send_data(handle, pDiskCtrl->inEpNo, + pDiskCtrl->MASS_STORAGE_DISK + (index1*LENGTH_OF_EACH_LAB), byteSize); + } /* Endbody */ + } + else + { /* Body */ + USB_printf("disk read incorrect: FLAGS=0x%02x, LENGTH=0x%x\n", + cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH); + + /* Incorrect but valid CBW */ + if (cbw_ptr->DCBWDATALENGTH > BUFFERSIZE) + byteSize = BUFFERSIZE; + else + byteSize = cbw_ptr->DCBWDATALENGTH; + + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH); + pDiskCtrl->pCSW->BCSWSTATUS = 2; + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, index2); + } /* Endbody */ +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_write_command +* Returned Value : None +* Comments : +* Sends data as a response to WRITE Command. +* +*END*--------------------------------------------------------------------*/ +void _process_write_command + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + uint_32 index1 = 0, index2 = 0; + uint_32 byteSize; + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + if (!(cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT)) + { + index1 = ((uint_32)cbw_ptr->CBWCB[4] << 8); + index1 |= cbw_ptr->CBWCB[5]; + index2 = ((uint_32)cbw_ptr->CBWCB[7] << 8); + index2 |= (uint_32)cbw_ptr->CBWCB[8]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_WRITE, + "disk write: FLAGS=0x%02x, LENGTH=0x%x, index1=0x%x, index2=0x%x\n", + cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH, index1, index2); + + if(cbw_ptr->CBWCB[0] != 0x3F) + { + byteSize = index2 * LENGTH_OF_EACH_LAB; + } + else + { + byteSize = index2; + index2 = (USB_MEM_ALIGN(byteSize, LENGTH_OF_EACH_LAB) / LENGTH_OF_EACH_LAB); + } + + /* Check index validities */ + if( (index1 + index2) >= pDiskCtrl->logicalBlocks) + { + USB_printf("USB disk write: invalid indexes - addr=%d, size=%d\n", + index1, index2); + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 1; + pDiskCtrl->CBW_PROCESSED = FALSE; + /* Send the command status information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13); + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + return; + } + + if (cbw_ptr->DCBWDATALENGTH == 0) + { /* Body */ + /* Zero transfer length */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 2; + pDiskCtrl->CBW_PROCESSED = FALSE; + + /* Send the command status information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13); + + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + return; + } + else + { /* Body */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 0; + + if (byteSize < cbw_ptr->DCBWDATALENGTH) + { /* Body */ + /* The actual length will never exceed the DCBWDATALENGTH */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH - byteSize); + byteSize = cbw_ptr->DCBWDATALENGTH; + } + else if (byteSize > cbw_ptr->DCBWDATALENGTH) + { /* Body */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH); + pDiskCtrl->pCSW->BCSWSTATUS = 2; + byteSize = cbw_ptr->DCBWDATALENGTH; + } /* Endbody */ + + if (_usb_device_get_transfer_status(handle, pDiskCtrl->outEpNo, ARC_USB_RECV) != USB_OK) + { + _usb_device_cancel_transfer(handle, ep_num, ARC_USB_RECV); + } /* Endif */ + + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, + pDiskCtrl->MASS_STORAGE_DISK + (index1*LENGTH_OF_EACH_LAB), byteSize); + } + } + else + { /* Body */ + USB_printf("disk write incorrect: FLAGS=0x%02x, LENGTH=0x%x\n", + cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH); + + /* Incorrect but valid CBW */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH); + pDiskCtrl->pCSW->BCSWSTATUS = 2; + _usb_device_send_data(handle, pDiskCtrl->inEpNo, 0, 0); + return; + } /* Endbody */ + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_test_unit_ready +* Returned Value : None +* Comments : +* Responds appropriately to unit ready query +* +*END*--------------------------------------------------------------------*/ +void _process_test_unit_ready + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + uint_32 bufSize; + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + if ((cbw_ptr->BMCBWFLAGS & USB_CBW_DIRECTION_BIT) || + (cbw_ptr->DCBWDATALENGTH == 0)) + { + /* The actual length will never exceed the DCBWDATALENGTH */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 0; + + pDiskCtrl->CBW_PROCESSED = FALSE; + + /* Send the command status information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13); + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + } + else + { /* Body */ + /* Incorrect but valid CBW */ + if (cbw_ptr->DCBWDATALENGTH > BUFFERSIZE) + bufSize = BUFFERSIZE; + else + bufSize = cbw_ptr->DCBWDATALENGTH; + + pDiskCtrl->pCSW->DCSWDATARESIDUE = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH); + pDiskCtrl->pCSW->BCSWSTATUS = 1; + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, bufSize); + } /* Endbody */ + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_prevent_allow_medium_removal +* Returned Value : None +* Comments : +* Responds appropriately to unit ready query +* +*END*--------------------------------------------------------------------*/ +void _process_prevent_allow_medium_removal + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + /* The actual length will never exceed the DCBWDATALENGTH */ + pDiskCtrl->pCSW->DCSWDATARESIDUE = 0; + pDiskCtrl->pCSW->BCSWSTATUS = 0; + + pDiskCtrl->CBW_PROCESSED = FALSE; + + /* Send the command status information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13); + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : _process_mass_storage_command +* Returned Value : None +* Comments : +* Process a Mass storage class command +* +*END*--------------------------------------------------------------------*/ +void _process_mass_storage_command + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Endpoint number */ + uint_8 ep_num, + + /* [IN] Pointer to the data buffer */ + CBW_STRUCT_PTR cbw_ptr + ) +{ /* Body */ + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK, + "disk command: CBWCB[0]=0x%02x, FLAGS=0x%02x, LENGTH=0x%x\n", + cbw_ptr->CBWCB[0], cbw_ptr->BMCBWFLAGS, cbw_ptr->DCBWDATALENGTH); + + switch (cbw_ptr->CBWCB[0]) + { + case 0x00: /* Request the device to report if it is ready */ + _process_test_unit_ready(handle, ep_num, cbw_ptr); + break; + + case 0x12: /* Inquity command. Get device information */ + _process_inquiry_command(handle, ep_num, cbw_ptr); + break; + + case 0x1A: + _process_unsupported_command(handle, ep_num, cbw_ptr); + break; + + case 0x1E: /* Prevent or allow the removal of media from a removable media device */ + _process_prevent_allow_medium_removal(handle, ep_num, cbw_ptr); + break; + + case 0x23: /* Read Format Capacities. Report current media capacity and + ** formattable capacities supported by media + */ + /* We bahave like already installed medium. No need to send any data */ + _process_unsupported_command(handle, ep_num, cbw_ptr); + break; + + case 0x25: /* Report current media capacity */ + _process_report_capacity(handle, ep_num, cbw_ptr); + break; + + case 0x28: /* Read (10) Transfer binary data from media to the host */ + case 0x3E: + _process_read_command(handle, ep_num, cbw_ptr); + break; + + case 0x2A: /* Write (10) Transfer binary data from the host to the media */ + case 0x3F: + _process_write_command(handle, ep_num, cbw_ptr); + break; + + case 0x01: /* Position a head of the drive to zero track */ + case 0x03: /* Transfer status sense data to the host */ + case 0x04: /* Format unformatted media */ + case 0x1B: /* Request a request a removable-media device to load or + ** unload its media + */ + case 0x1D: /* Perform a hard reset and execute diagnostics */ + case 0x2B: /* Seek the device to a specified address */ + case 0x2E: /* Transfer binary data from the host to the media and + ** verify data + */ + case 0x2F: /* Verify data on the media */ + case 0x55: /* Allow the host to set parameters in a peripheral */ + case 0x5A: /* Report parameters to the host */ + case 0xA8: /* Read (12) Transfer binary data from the media to the host */ + case 0xAA: /* Write (12) Transfer binary data from the host to the + ** media + */ + default: + _process_unsupported_command(handle, ep_num, cbw_ptr); + break; + } /* Endswitch */ + +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : service_ep1 +* Returned Value : None +* Comments : +* Called upon a completed endpoint 1 (USB 1.1 Chapter 9) transfer +* +*END*--------------------------------------------------------------------*/ +static void service_ep1 + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] Service type as registered */ + uint_8 type, + + /* [IN] Is it a setup packet? */ + boolean setup, + + /* [IN] Direction of the transfer. Is it transmit? */ + uint_8 direction, + + /* [IN] Pointer to the data buffer */ + uint_8_ptr buffer, + + /* [IN] Length of the transfer */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + CBW_STRUCT_PTR cbw_ptr = (CBW_STRUCT_PTR)((pointer)buffer); + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_EP1, + "disk %s: ep=%d, dir=%s, pBuf=0x%x, length=%d, error=0x%x\n", + __FUNCTION__, type, (direction == ARC_USB_RECV) ? "RECV" : "SEND", + (unsigned)buffer, (int)length, error); + + if ((!direction) && (!pDiskCtrl->CBW_PROCESSED) && (length == 31) && + (cbw_ptr->DCBWSIGNATURE == USB_32BIT_LE(USB_DCBWSIGNATURE))) + { + /* A valid CBW was received */ + pDiskCtrl->pCSW->DCSWSIGNATURE = USB_32BIT_LE(USB_DCSWSIGNATURE); + pDiskCtrl->pCSW->DCSWTAG = cbw_ptr->DCBWTAG; + pDiskCtrl->CBW_PROCESSED = TRUE; + + /* Swap 32 bit fields if neccessary */ + cbw_ptr->DCBWDATALENGTH = USB_32BIT_LE(cbw_ptr->DCBWDATALENGTH); + + /* Process the command */ + _process_mass_storage_command(handle, type, cbw_ptr); + } + else + { + /* If a CBW was processed then send the status information and + ** queue another cbw receive request, else just queue another CBW receive + ** request if we received an invalid CBW + */ + if (pDiskCtrl->CBW_PROCESSED) + { + int i; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DATA, + "disk %s: ep=%d, dir=%s, pBuf=0x%x, length=%d, error=0x%x\n", + __FUNCTION__, type, (direction == ARC_USB_RECV) ? "RECV" : "SEND", + (unsigned)buffer, (int)length, error); + + for(i=0; i<64; i++) + { + if( (i % 16) == 0) + { + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DUMP, "\n0x%08x: ", &buffer[i]); + } + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DUMP, "%02x ", buffer[i]); + if( (i % 3) == 0) + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_DISK_DUMP, " "); + } + + if (pDiskCtrl->ZERO_TERMINATE) + { /* Body */ + pDiskCtrl->ZERO_TERMINATE = FALSE; + _usb_device_send_data(handle, pDiskCtrl->inEpNo, 0, 0); + } + else + { /* Body */ + pDiskCtrl->CBW_PROCESSED = FALSE; + + /* Send the command status information */ + _usb_device_send_data(handle, pDiskCtrl->inEpNo, (uint_8_ptr)pDiskCtrl->pCSW, 13); + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + } + } + else + { + if (!direction) + { + USB_printf("usbDisk_%d, %s: Wrong direction = %d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, direction); + _usb_device_stall_endpoint(handle, pDiskCtrl->outEpNo, ARC_USB_RECV); + _usb_device_stall_endpoint(handle, pDiskCtrl->inEpNo, ARC_USB_SEND); + + /* Invalid CBW received. Queue another receive buffer */ + _usb_device_recv_data(handle, pDiskCtrl->outEpNo, pDiskCtrl->ep1_buf, 31); + } + } /* Endif */ + } /* Endif */ + + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : service_speed +* Returned Value : None +* Comments : +* Called upon a speed detection event. +* +*END*--------------------------------------------------------------------*/ +static void service_speed + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] request type as registered */ + uint_8 type, + + /* [IN] Unused */ + boolean setup, + + /* [IN] Unused */ + uint_8 direction, + + /* [IN] Unused */ + uint_8_ptr buffer, + + /* [IN] Unused */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + + ) +{ /* EndBody */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SPEED, "disk %s: speed = %d\n", __FUNCTION__, (unsigned)length); + + pDiskCtrl->speed = length; + return; +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : reset_ep0 +* Returned Value : None +* Comments : +* Called upon a bus reset event. Initialises the control endpoint. +* +*END*--------------------------------------------------------------------*/ +static void reset_ep0 + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] request type as registered */ + uint_8 type, + + /* [IN] Unused */ + boolean setup, + + /* [IN] Unused */ + uint_8 direction, + + /* [IN] Unused */ + uint_8_ptr buffer, + + /* [IN] Unused */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + + ) +{ /* Body */ + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RESET, "disk-%d %s: pDiskCtrl=%p, handle=%p\n", + devNo, __FUNCTION__, pDiskCtrl, handle); + + /* on a reset always ensure all transfers are cancelled on control EP*/ + _usb_device_cancel_transfer(handle, 0, ARC_USB_RECV); + _usb_device_cancel_transfer(handle, 0, ARC_USB_SEND); + + _usb_device_start(handle); + /* Initialize the endpoint 0 in both directions */ + _usb_device_init_endpoint(handle, 0, pDiskCtrl->DevDesc[DEV_DESC_MAX_PACKET_SIZE], + ARC_USB_RECV, ARC_USB_CONTROL_ENDPOINT, 0); + _usb_device_init_endpoint(handle, 0, pDiskCtrl->DevDesc[DEV_DESC_MAX_PACKET_SIZE], + ARC_USB_SEND, ARC_USB_CONTROL_ENDPOINT, 0); + + + if (pDiskCtrl->TEST_ENABLED) + { + int out_ep_count=0, in_ep_count=0; + + while(_usb_device_get_transfer_status(handle, pDiskCtrl->outEpNo, ARC_USB_RECV) != + ARC_USB_STATUS_IDLE) + { + out_ep_count++; + _usb_device_cancel_transfer(handle, pDiskCtrl->outEpNo, ARC_USB_RECV); + } + while(_usb_device_get_transfer_status(handle, pDiskCtrl->inEpNo, ARC_USB_SEND) != + ARC_USB_STATUS_IDLE) + { + in_ep_count++; + _usb_device_cancel_transfer(handle, pDiskCtrl->inEpNo, ARC_USB_SEND); + } + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_RESET, "disk %s: out_ep_count=%d, in_ep_count=%d\n", + __FUNCTION__, out_ep_count, in_ep_count); + } /* Endif */ + + pDiskCtrl->TEST_ENABLED = FALSE; + + return; +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : usbDiskLoad - main task +* Inputs: +* int diskSize - size of created disk in KBytes +* Returned Value : None +* Comments : +* First function called. Initialises the USB and registers Chapter 9 +* callback functions. +* +*END*--------------------------------------------------------------------*/ +_usb_device_handle usbDiskLoad(int devNo, int diskSize) +{ /* Body */ + _usb_device_handle handle; + USB_DISK_STRUCT* pDiskCtrl; + uint_8_ptr Send_Buffer_aligned; + uint_8 error; + uint_32 send_data_buffer_size=0; + uint_8_ptr temp; + int lockKey, i, j; + static boolean isFirst = TRUE; + + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_INIT, "%s: devNo=%d, diskSize=%d\n", + __FUNCTION__, devNo, diskSize); + + if(devNo >= MAX_USB_DEVICES) + { + USB_printf("USB disk: devNo=%d too large\n", devNo); + return NULL; + } + + /*lock interrupts */ + lockKey = USB_lock(); + + if(isFirst) + { + for(i=0; ilogicalBlocks = TOTAL_LOGICAL_ADDRESS_BLOCKS; + else + pDiskCtrl->logicalBlocks = (diskSize*1024)/LENGTH_OF_EACH_LAB; + + if(pDiskCtrl->logicalBlocks < 16) + { + USB_printf("USB disk size (%d) is too small. Minimum is 8 Kbytes\n", + diskSize); + USB_unlock(lockKey); + return NULL; + } + + pDiskCtrl->devNo = devNo; + pDiskCtrl->hsMaxPktSize = diskHsMaxPktSize; + pDiskCtrl->fsMaxPktSize = diskFsMaxPktSize; + + pDiskCtrl->inEpType = diskInEpType; + pDiskCtrl->outEpType = diskOutEpType; + + pDiskCtrl->inEpNo = diskInEpNo; + pDiskCtrl->outEpNo = diskOutEpNo; + + /* Initialize the USB interface */ + error = _usb_device_init(devNo, &handle); + if (error != USB_OK) + { + USB_unlock(lockKey); + USB_printf("\nUSB Initialization failed. Error: %x", error); + return NULL; + } /* Endif */ + + /* Self Power, Remote wakeup disable */ + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE, (1 << DEVICE_SELF_POWERED)); + + error = _usb_device_register_service(handle, ARC_USB_SERVICE_EP0, service_ep0); + if (error != USB_OK) + { + USB_unlock(lockKey); + USB_printf("\nUSB Service Registration failed. Error: %x", error); + return NULL; + } /* Endif */ + + error = _usb_device_register_service(handle, ARC_USB_SERVICE_BUS_RESET, reset_ep0); + if (error != USB_OK) + { + USB_unlock(lockKey); + USB_printf("\nUSB Service Registration failed. Error: %x", error); + return NULL; + } /* Endif */ + + error = _usb_device_register_service(handle, ARC_USB_SERVICE_SPEED_DETECTION, + service_speed); + if (error != USB_OK) + { + USB_unlock(lockKey); + USB_printf("\nUSB Service Registration failed. Error: %x", error); + return NULL; + } /* Endif */ + + error = _usb_device_register_service(handle, pDiskCtrl->outEpNo, service_ep1); + if (error != USB_OK) + { + USB_unlock(lockKey); + USB_printf("\nUSB Service Registration failed. Error: %x", error); + return NULL; + } /* Endif */ + + if(pDiskCtrl->outEpNo != pDiskCtrl->inEpNo) + { + error = _usb_device_register_service(handle, pDiskCtrl->inEpNo, service_ep1); + if (error != USB_OK) + { + USB_unlock(lockKey); + USB_printf("\nUSB Service Registration failed. Error: %x", error); + return NULL; + } /* Endif */ + } + + /************************************************************************** + Best way to handle the Data cache is to allocate a large buffer that is + cache aligned and keep all data inside it. Flush the line of the cache + that you have changed. In this program, we have static data such as + descriptors which never changes. Such data can be kept in this buffer + and flushed only once. Note that you can reduce the size of this buffer + by aligning the addresses in a different way. + ***************************************************************************/ + send_data_buffer_size = (DEVICE_DESCRIPTOR_SIZE + PSP_CACHE_LINE_SIZE) + + (CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE) + + (DEVICE_QUALIFIER_DESCRIPTOR_SIZE + PSP_CACHE_LINE_SIZE) + + (OTHER_SPEED_CONFIG_DESC_SIZE + PSP_CACHE_LINE_SIZE) + + (BUFFERSIZE + PSP_CACHE_LINE_SIZE) + + (EP_TEMP_BUFFERSIZE + PSP_CACHE_LINE_SIZE) + + (sizeof(DISK_READ_CAPACITY) + PSP_CACHE_LINE_SIZE) + + (sizeof(CSW_STRUCT) + PSP_CACHE_LINE_SIZE) + + (pDiskCtrl->logicalBlocks*LENGTH_OF_EACH_LAB + PSP_CACHE_LINE_SIZE); + + pDiskCtrl->Send_Buffer_Unaligned = (uint_8_ptr) USB_memalloc(send_data_buffer_size); + if (pDiskCtrl->Send_Buffer_Unaligned == NULL) + { + USB_unlock(lockKey); + USB_printf("diskLoad: Buffer allocation of %d bytes is failed\n", + (unsigned)send_data_buffer_size); + return NULL; + } + + Send_Buffer_aligned = (uint_8_ptr) USB_CACHE_ALIGN((uint_32)pDiskCtrl->Send_Buffer_Unaligned); + /* keep a temporary copy of the aligned address */ + temp = Send_Buffer_aligned; + + /************************************************************************** + Assign pointers to different buffers from it and copy data inside. + ***************************************************************************/ + pDiskCtrl->DevDesc = (uint_8_ptr) Send_Buffer_aligned; + USB_memcopy(DevDescData, pDiskCtrl->DevDesc, DEVICE_DESCRIPTOR_SIZE); + Send_Buffer_aligned += ((DEVICE_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; + + pDiskCtrl->ConfigDesc = (uint_8_ptr) Send_Buffer_aligned; + USB_memcopy(ConfigDescData, pDiskCtrl->ConfigDesc, CONFIG_DESC_SIZE); + Send_Buffer_aligned += ((CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; + + pDiskCtrl->DevQualifierDesc = (uint_8_ptr) Send_Buffer_aligned; + USB_memcopy(DevQualifierDescData, pDiskCtrl->DevQualifierDesc, DEVICE_QUALIFIER_DESCRIPTOR_SIZE); + Send_Buffer_aligned += ((DEVICE_QUALIFIER_DESCRIPTOR_SIZE/PSP_CACHE_LINE_SIZE) + 1) * PSP_CACHE_LINE_SIZE; + + pDiskCtrl->other_speed_config = (uint_8_ptr) Send_Buffer_aligned; + USB_memcopy(other_speed_config_data, pDiskCtrl->other_speed_config, OTHER_SPEED_CONFIG_DESC_SIZE); + Send_Buffer_aligned += ((OTHER_SPEED_CONFIG_DESC_SIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; + + /*buffer to receive data from Bulk OUT */ + pDiskCtrl->ep1_buf = (uint_8_ptr) Send_Buffer_aligned; + USB_memzero(pDiskCtrl->ep1_buf, BUFFERSIZE); + Send_Buffer_aligned += ((BUFFERSIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; + + /*buffer for control endpoint to send data */ + pDiskCtrl->epTemp_buf = (uint_8_ptr) Send_Buffer_aligned; + USB_memzero(pDiskCtrl->epTemp_buf, EP_TEMP_BUFFERSIZE); + + Send_Buffer_aligned += ((EP_TEMP_BUFFERSIZE/PSP_CACHE_LINE_SIZE) + 1)* PSP_CACHE_LINE_SIZE; + + /* Buffer for read Capacity message */ + pDiskCtrl->pReadCapacity = (DISK_READ_CAPACITY*)Send_Buffer_aligned; + USB_memcopy((void*)&read_capacity, pDiskCtrl->pReadCapacity, sizeof(DISK_READ_CAPACITY)); + + /* Update read_capacity */ + pDiskCtrl->pReadCapacity->LAST_LOGICAL_BLOCK_ADDRESS[2] = + USB_uint_16_high(pDiskCtrl->logicalBlocks-14); + pDiskCtrl->pReadCapacity->LAST_LOGICAL_BLOCK_ADDRESS[3] = + USB_uint_16_low(pDiskCtrl->logicalBlocks-14); + + Send_Buffer_aligned += ((sizeof(DISK_READ_CAPACITY)/PSP_CACHE_LINE_SIZE) + 1) * PSP_CACHE_LINE_SIZE; + + /* Buffer for CSW message */ + pDiskCtrl->pCSW = (CSW_STRUCT*)Send_Buffer_aligned; + USB_memzero(pDiskCtrl->pCSW , sizeof(CSW_STRUCT)); + + Send_Buffer_aligned += ((sizeof(CSW_STRUCT)/PSP_CACHE_LINE_SIZE) + 1) * PSP_CACHE_LINE_SIZE; + + /*buffer for storage disk */ + pDiskCtrl->MASS_STORAGE_DISK = (uint_8_ptr)Send_Buffer_aligned; + + USB_printf("usbDisk-%d: pDiskCtrl=%p, %d bytes allocated addr=0x%x\n", + devNo, pDiskCtrl, (unsigned)send_data_buffer_size, + (unsigned)pDiskCtrl->Send_Buffer_Unaligned); + USB_printf("usbDisk-%d: DevDesc=0x%x, ConfigDesc=0x%x, QualifierDesc=0x%x, otherSpeedDesc=0x%x\n", + devNo, (unsigned)pDiskCtrl->DevDesc, (unsigned)pDiskCtrl->ConfigDesc, + (unsigned)pDiskCtrl->DevQualifierDesc, (unsigned)pDiskCtrl->other_speed_config); + USB_printf("usbDisk-%d: ep1_buf=0x%x, epTemp_buf=0x%x, MASS_STORAGE_DISK=0x%x\n", + devNo, (unsigned)pDiskCtrl->ep1_buf, (unsigned)pDiskCtrl->epTemp_buf, + (unsigned)pDiskCtrl->MASS_STORAGE_DISK); + + USB_memzero(pDiskCtrl->MASS_STORAGE_DISK, (pDiskCtrl->logicalBlocks*LENGTH_OF_EACH_LAB)); + + /* Format the "disk" */ + USB_memcopy(BOOT_SECTOR_AREA, pDiskCtrl->MASS_STORAGE_DISK, 512); + + /* Update BOOT Sector "Total Small sectors" field */ + pDiskCtrl->MASS_STORAGE_DISK[19] = USB_uint_16_low(pDiskCtrl->logicalBlocks); + pDiskCtrl->MASS_STORAGE_DISK[20] = USB_uint_16_high(pDiskCtrl->logicalBlocks); + + USB_memcopy((void *)FAT16_SPECIAL_BYTES, pDiskCtrl->MASS_STORAGE_DISK + 512, 3); + USB_memcopy((void *)FAT16_SPECIAL_BYTES, pDiskCtrl->MASS_STORAGE_DISK + 512*4, 3); + + /************************************************************************** + Flush the cache to ensure main memory is updated. + ***************************************************************************/ + USB_dcache_flush(temp, send_data_buffer_size); + + pDiskCtrl->usbDevHandle = handle; + usbDisksPtr[devNo] = pDiskCtrl; + + USB_unlock(lockKey); + + USB_printf("USB Disk is READY: diskSize=%d KBytes, blockSize=%d Bytes, numBlocks=%d\n", + diskSize, LENGTH_OF_EACH_LAB, pDiskCtrl->logicalBlocks); + + return pDiskCtrl->usbDevHandle; +} /* Endbody */ + +void usbDiskUnload(_usb_device_handle handle) +{ + int lockKey; + int devNo = _usb_device_get_dev_num(handle); + USB_DISK_STRUCT* pDiskCtrl = usbDisksPtr[devNo]; + + if(pDiskCtrl == NULL) + { + USB_printf("USB disk #%d: Disk is not loaded\n", pDiskCtrl->devNo); + return; + } + /*lock interrupts */ + lockKey = USB_lock(); + + /* ensure all transfers are cancelled */ + _usb_device_cancel_transfer(handle, pDiskCtrl->outEpNo, ARC_USB_RECV); + _usb_device_cancel_transfer(handle, pDiskCtrl->inEpNo, ARC_USB_SEND); + + /* Stop Endpoints */ + _usb_device_deinit_endpoint(handle, pDiskCtrl->outEpNo, ARC_USB_RECV); + _usb_device_deinit_endpoint(handle, pDiskCtrl->inEpNo, ARC_USB_SEND); + + _usb_device_deinit_endpoint(handle, 0, ARC_USB_RECV); + _usb_device_deinit_endpoint(handle, 0, ARC_USB_SEND); + + _usb_device_stop(handle); + + /* Deregister all services */ + _usb_device_unregister_service(handle, ARC_USB_SERVICE_EP0); + _usb_device_unregister_service(handle, ARC_USB_SERVICE_BUS_RESET); + _usb_device_unregister_service(handle, ARC_USB_SERVICE_SPEED_DETECTION); + _usb_device_unregister_service(handle, pDiskCtrl->outEpNo); + if(pDiskCtrl->outEpNo != pDiskCtrl->inEpNo) + { + _usb_device_unregister_service(handle, pDiskCtrl->inEpNo); + } + + _usb_device_shutdown(handle); + + /* Free memory allocated for Disk device */ + if(pDiskCtrl->Send_Buffer_Unaligned != NULL) + { + USB_memfree(pDiskCtrl->Send_Buffer_Unaligned); + } + + /* Free Control structure */ + USB_memfree(pDiskCtrl); + usbDisksPtr[devNo] = NULL; + + USB_unlock(lockKey); +} + +/* EOF */ + diff --git a/board/mv_feroceon/mv_hal/usb/examples/disk.h b/board/mv_feroceon/mv_hal/usb/examples/disk.h new file mode 100644 index 0000000..d01dc4e --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/examples/disk.h @@ -0,0 +1,86 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +#ifndef __disk_h__ +#define __disk_h__ + +#define USB_DCBWSIGNATURE (0x43425355) +#define USB_DCSWSIGNATURE (0x53425355) +#define USB_CBW_DIRECTION_BIT (0x80) + +/* USB Command Block Wrapper */ +typedef struct cbw_struct { + uint_32 DCBWSIGNATURE; + uint_32 DCBWTAG; + uint_32 DCBWDATALENGTH; + uint_8 BMCBWFLAGS; + /* 4 MSBs bits reserved */ + uint_8 BCBWCBLUN; + /* 3 MSB reserved */ + uint_8 BCBWCBLENGTH; + uint_8 CBWCB[16]; +} CBW_STRUCT, _PTR_ CBW_STRUCT_PTR; + +/* USB Command Status Wrapper */ +typedef struct csw_struct { + uint_32 DCSWSIGNATURE; + uint_32 DCSWTAG; + uint_32 DCSWDATARESIDUE; + uint_8 BCSWSTATUS; +} CSW_STRUCT, _PTR_ CSW_STRUCT_PTR; + +/* USB Mass storage Inquiry Command */ +typedef struct mass_storage_inquiry { + uint_8 OPCODE; + uint_8 LUN; + uint_8 PAGE_CODE; + uint_8 RESERVED1; + uint_8 ALLOCATION_LENGTH; + uint_8 RESERVED2[7]; +} DISK_INQUIRY, _PTR_ DISK_INQUIRY_PTR; + +/* USB Mass storage READ CAPACITY Data */ +typedef struct mass_storage_read_capacity { + uint_8 LAST_LOGICAL_BLOCK_ADDRESS[4]; + uint_8 BLOCK_LENGTH_IN_BYTES[4]; +} DISK_READ_CAPACITY, _PTR_ DISK_READ_CAPACITY_PTR; + +/* USB Mass storage Device information */ +typedef struct mass_storage_device_info { + uint_8 PERIPHERAL_DEVICE_TYPE; /* Bits 0-4. All other bits reserved */ + uint_8 RMB; /* Bit 7. All other bits reserved */ + uint_8 ANSI_ECMA_ISO_VERSION; /* ANSI: bits 0-2, ECMA: bits 3-5, + ** ISO: bits 6-7 + */ + uint_8 RESPONSE_DATA_FORMAT; /* bits 0-3. All other bits reserved */ + uint_8 ADDITIONAL_LENGTH; /* For UFI device: always set to 0x1F */ + uint_8 RESERVED1[3]; + uint_8 VENDOR_INFORMATION[8]; + uint_8 PRODUCT_ID[16]; + uint_8 PRODUCT_REVISION_LEVEL[4]; +} DISK_DEVICE_INFO, _PTR_ DISK_DEVICE_INFO_PTR; + + +extern _usb_device_handle usbDiskLoad(int devNo, int diskSize); +extern void usbDiskUnload(_usb_device_handle handle); + +#endif /* __disk_h__ */ + +/* EOF */ diff --git a/board/mv_feroceon/mv_hal/usb/examples/mouse.c b/board/mv_feroceon/mv_hal/usb/examples/mouse.c new file mode 100644 index 0000000..def3610 --- /dev/null +++ b/board/mv_feroceon/mv_hal/usb/examples/mouse.c @@ -0,0 +1,1709 @@ +/******************************************************************************* + +This software file (the "File") is distributed by Marvell International Ltd. +or its affiliate(s) under the terms of the GNU General Public License Version 2, +June 1991 (the "License"). You may use, redistribute and/or modify this File +in accordance with the terms and conditions of the License, a copy of which +is available along with the File in the license.txt file or by writing to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +(C) Copyright 2004 - 2007 Marvell Semiconductor Israel Ltd. All Rights Reserved. +(C) Copyright 1999 - 2004 Chipidea Microelectronica, S.A. All Rights Reserved. + +*******************************************************************************/ + +/************************************************************************** +Include the USB stack header files. +**************************************************************************/ +#include "mvUsbDefs.h" +#include "mvUsbDebug.h" +#include "mvUsbCh9.h" +#include "mvUsbDevApi.h" + +#include "mouse.h" + + +/************************************************************************** +global variables and some defines for device. +**************************************************************************/ + +#define CONTROL_MAX_PACKET_SIZE (64) +#define INTERRUPT_MAX_PACKET_SIZE (0x0008) +#define DEV_DESC_MAX_PACKET_SIZE (7) +#define INTERRUPT_EP (1) +#define FRAME_INTERVAL (15) + +/************************************************************************** +Include the OS and BSP dependent files that define IO functions and +basic types. You may like to change these files for your board and RTOS +**************************************************************************/ + +int frame_interval = FRAME_INTERVAL; +int mouseCntr = 0; +int mouseDelay = 2; + +static volatile boolean TEST_ENABLED = FALSE; +static volatile boolean USB_SUSPENDED = FALSE; + +#define EP1_RECV_BUFFER_SIZE 10 +static uint_8_ptr hid_test_rep_data; +static uint_8_ptr hid_test_rep_data_unaligned; + +/******************************** +Buffers for sending data to stack +********************************/ +#define EP0_SEND_BUFFER_SIZE 200 +static uint_8_ptr Send_Buffer_Unaligned; +static uint_8_ptr Send_Buffer_aligned; + +static uint_8 data_to_send; +static uint_16 sof_count; +static SETUP_STRUCT local_setup_packet; + + +/************************************************************************* +Device descriptors are always 18 bytes + +Offset| Field | Value | Description +------|--------------------|-------|-------------------- + 0 | bLength | 0x12 |The size of this + | | |descriptor is 18 bytes +------|--------------------|-------|-------------------- + 1 | bDescriptorType | 0x01 |DEVICE Descriptor Type +------|--------------------|-------|-------------------- + 2 | bcdUSB | 0x0100|Device compliant to + | | |the USB + | | |specification + | | |version 1.00 +------|--------------------|-------|-------------------- + 4 | bDeviceClass | 0x00 |Each interface + | | |specifies its own + | | |class information +------|--------------------|-------|-------------------- + 5 | bDeviceSubClass | 0x00 |Each interface + | | |specifies its own + | | |subclass information +------|--------------------|-------|-------------------- + 6 | bDeviceProtocol | 0x00 |No protocols on the + | | |device basis +------|--------------------|-------|-------------------- + 7 | bMaxPacketSize0 | 0x08 |Maximum packet size + | | |for endpoint zero is 8 +------|--------------------|-------|-------------------- + 8 | idVendor | 0x0261|Vendor ID is 609: + | | +------|--------------------|-------|-------------------- + 10 | idProduct | 0x4D03|The Product ID is 0x4D03 +------|--------------------|-------|-------------------- + 12 | bcdDevice | 0x0441|The device release + | | |number is 4.41 +------|--------------------|-------|-------------------- + 14 | iManufacturer | 0x00 |The device doesn't + | | |have the string + | | |descriptor + | | |describing the manufacturer +------|--------------------|-------|-------------------- + 15 | iProduct | 0x00 |The device doesn't + | | |have the string + | | |descriptor + | | |describing the product +------|--------------------|-------|-------------------- + 16 | iSerialNumber | 0x00 | +------|--------------------|-------|-------------------- + 17 | bNumConfigurations | 0x01 | +------|--------------------|-------|-------------------- +*************************************************************************/ +#define DEVICE_DESCRIPTOR_SIZE 18 +static uint_8_ptr DevDesc; +static uint_8 DevDescData[DEVICE_DESCRIPTOR_SIZE] = +{ + DEVICE_DESCRIPTOR_SIZE, + 0x01, + 0x0,2, + + 0x00, + 0x00, + 0x00, + CONTROL_MAX_PACKET_SIZE, + /* Vendor ID = MARVELL */ + USB_uint_16_low(0x1286), USB_uint_16_high(0x1286), + /* Product ID */ + USB_uint_16_low(0x1), USB_uint_16_high(0x1), + /* BCD Device version */ + USB_uint_16_low(0x0002), USB_uint_16_high(0x0002), + + 0x01, /* iManufacturer */ + 0x02, /* iProduct */ + 0x00, /* iSerialNumber */ + 0x01 /* bNumConfigurations */ + +}; + +/* USB 2.0 specific descriptor */ +#define DEVICE_QUALIFIER_DESCRIPTOR_SIZE 10 +static uint_8_ptr DevQualifierDesc; +static uint_8 DevQualifierDescData[DEVICE_QUALIFIER_DESCRIPTOR_SIZE] = +{ + DEVICE_QUALIFIER_DESCRIPTOR_SIZE, /* bLength Length of this descriptor */ + 6, /* bDescType This is a DEVICE Qualifier descr */ + 0,2, /* bcdUSB USB revision 2.0 */ + 0, /* bDeviceClass */ + 0, /* bDeviceSubClass */ + 0, /* bDeviceProtocol */ + CONTROL_MAX_PACKET_SIZE, /* bMaxPacketSize0 */ + 0x01, /* bNumConfigurations */ + 0 +}; + + +/******************************************************************* + CONFIG DESCRIPTOR + +Data stage (34 bytes) : +------------------------------------ + + CONFIGURATION Descriptor + ------------------------ +Offset| Field | Value | Description +------|---------------------|-------|-------------------- + 0 | bLength | 0x09 |The size of this + | | |descriptor is 9 bytes +------|---------------------|-------|-------------------- + 1 | bDescriptorType | 0x02 |CONFIGURATION + | | |Descriptor Type +------|---------------------|-------|-------------------- + 2 | wTotalLength | 0x0022|The total length of + | | |data for this + | | |configuration is 34. + | | |This includes the + | | |combined length of + | | |all the descriptors returned +------|---------------------|-------|-------------------- + 4 | bNumInterfaces | 0x01 |This configuration + | | |supports 1 interfaces +------|---------------------|-------|-------------------- + 5 | bConfigurationValue | 0x01 |The value 1 should + | | |be used to select + | | |this configuration +------|---------------------|-------|-------------------- + 6 | iConfiguration | 0x00 |The device doesn't + | | |have the string + | | |descriptor + | | |describing this configuration +------|---------------------|-------|-------------------- + 7 | bmAttributes | 0x80 |Configuration characteristics : + | | |Bit 7: Reserved (set to one) 1 + | | |Bit 6: Self-powered 0 + | | |Bit 5: Remote Wakeup 1 +------|---------------------|-------|-------------------- + 8 | MaxPower | 0x32 |Maximum power + | | |consumption of the + | | |device in this + | | |configuration is 100 mA +------|---------------------|-------|-------------------- + + INTERFACE Descriptor + -------------------- +Offset| Field | Value | Description +------|--------------------|-------|-------------------- + 0 | bLength | 0x09 |The size of this + | | |descriptor is 9 bytes +------|--------------------|-------|-------------------- + 1 | bDescriptorType | 0x04 |INTERFACE Descriptor Type +------|--------------------|-------|-------------------- + 2 | bInterfaceNumber | 0x00 |The number of this + | | |interface is 0 +------|--------------------|-------|-------------------- + 3 | bAlternateSetting | 0x00 |The value used to + | | |select alternate + | | |setting for this + | | |interface is 0 +------|--------------------|-------|-------------------- + 4 | bNumEndpoints | 0x01 |The number of + | | |endpoints used by + | | |this interface is 1 + | | |(excluding endpoint zero) +------|--------------------|-------|-------------------- + 5 | bInterfaceClass | 0x03 |The interface + | | |implements HID class +------|--------------------|-------|-------------------- + 6 | bInterfaceSubClass | 0x01 |The subclass code is 0x01 +------|--------------------|-------|-------------------- + 7 | bInterfaceProtocol | 0x02 |The protocol code is 0x02 +------|--------------------|-------|-------------------- + 8 | iInterface | 0x00 |The device doesn't + | | |have the string + | | |descriptor + | | |describing this interface +------|--------------------|-------|-------------------- + + HID Descriptor + -------------- +Offset| Field | Value | Description +------|-------------------|-------|-------------------- + 0 | bLength | 0x09 |The size of this + | | |descriptor is 9 bytes +------|-------------------|-------|-------------------- + 1 | bDescriptorType | 0x21 |HID Descriptor Type +------|-------------------|-------|-------------------- + 2 | bcdHID | 0x0100|Device compliant to + | | |the HID + | | |specification + | | |version 1.00 +------|-------------------|-------|-------------------- + 4 | bCountryCode | 0x00 |The country code is 0x00 +------|-------------------|-------|-------------------- + 5 | bNumDescriptors | 0x01 |The number of class + | | |descriptors is 1 +------|-------------------|-------|-------------------- + 6 | bDescriptorType | 0x22 |The class descriptor + | | |is Report descriptor +------|-------------------|-------|-------------------- + 7 | wDescriptorlength | 0x0034|The total size of + | | |the class descriptor + | | |is 52 +------|-------------------|-------|-------------------- + + ENDPOINT Descriptor + ------------------- +Offset| Field | Value | Description +------|------------------|-------|-------------------- + 0 | bLength | 0x07 |The size of this + | | |descriptor is 7 bytes +------|------------------|-------|-------------------- + 1 | bDescriptorType | 0x05 |ENDPOINT Descriptor Type +------|------------------|-------|-------------------- + 2 | bEndpointAddress | 0x81 |This is an IN + | | |endpoint with + | | |address (endpoint + | | |number) 1 +------|------------------|-------|-------------------- + 3 | bmAttributes | 0x03 |Types - + | | |Transfer:INTERRUPT + | | |Sync:No Sync + | | |Usage:Data EP +------|------------------|-------|-------------------- + 4 | wMaxPacketSize | 0x0004|Maximum packet size + | | |value for this + | | |endpoint is 0x4 + | | |(Bits 12-11: Addtl. Transactions/frame) +------|------------------|-------|-------------------- + 6 | bInterval | 0x0A |bInterval:10. The + | | |polling interval + | | |value is bInterval + | | |or 2**(bInterval-1) +------|------------------|-------|-------------------- + +*******************************************************************/ + + +#define CONFIG_DESC_NUM_INTERFACES (4) + +/* This must be counted manually and updated with the descriptor */ +/* 1*Config(9) + 1*Interface(9) + 1*HID(9) + 1* Endpoint (7)= 34 bytes */ +#define CONFIG_DESC_SIZE (34) + +static uint_8_ptr ConfigDesc; + +static uint_8 ConfigDescData[CONFIG_DESC_SIZE] = +{ + /*Config Descriptor */ + 0x09, + 0x02, + USB_uint_16_low(CONFIG_DESC_SIZE), + USB_uint_16_high(CONFIG_DESC_SIZE), + 0x01, + 0x01, + 0x00, + 0xE0, /* 0x80, */ + 0x0, + /* Interface Descriptor */ + 0x09, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x01, + 0x02, + 0x00, + + /* HID descriptor */ + 0x09, + 0x21, + USB_uint_16_low(0x0100), + USB_uint_16_high(0x0100), + 0x00, + 0x01, + 0x22, + USB_uint_16_low(0x0034), + USB_uint_16_high(0x0034), + + /*Endpoint descriptor */ + 0x07, + 0x05, + (0x80+INTERRUPT_EP), + 0x03, + USB_uint_16_low(INTERRUPT_MAX_PACKET_SIZE), + USB_uint_16_high(INTERRUPT_MAX_PACKET_SIZE), + FRAME_INTERVAL +}; + +#define OTHER_SPEED_CONFIG_DESC_SIZE CONFIG_DESC_SIZE +static uint_8_ptr other_speed_config; +static uint_8 other_speed_config_data[CONFIG_DESC_SIZE] = +{ + /*Config Descriptor */ + 0x09, + 0x07, + USB_uint_16_low(CONFIG_DESC_SIZE), + USB_uint_16_high(CONFIG_DESC_SIZE), + 0x01, + 0x01, + 0x00, + 0xE0, /* 0x80, */ + 0x0, + /* Interface Descriptor */ + 0x09, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x01, + 0x02, + 0x00, + + /* HID descriptor */ + 0x09, + 0x21, + USB_uint_16_low(0x0100), + USB_uint_16_high(0x0100), + 0x00, + 0x01, + 0x22, + USB_uint_16_low(0x0034), + USB_uint_16_high(0x0034), + + /*Endpoint descriptor */ + 0x07, + 0x05, + (0x80+INTERRUPT_EP), + 0x03, + USB_uint_16_low(INTERRUPT_MAX_PACKET_SIZE), + USB_uint_16_high(INTERRUPT_MAX_PACKET_SIZE), + FRAME_INTERVAL + +}; +/************************************************************************ + +HID Class Report Descriptor : + +Item Value(Hex) +------------------------------------------------------------------------------------------------------------ +Usage Page (Generic Desktop Control) 05 01 +Usage (Mouse) 09 02 +Collection (Application) A1 01 + Usage (Pointer) 09 01 + Collection (Physical) A1 00 + Usage Page (Button) 05 09 + Usage Minimum (1) 19 01 + Usage Maximum (3) 29 03 + Logical Minimum (0) 15 00 + Logical Maximum (1) 25 01 + Report Count (3) 95 03 + Report Size (1) 75 01 + Input (Data, Variable, Absolute) 81 02 + Report Count (1) 95 01 + Report Size (5) 75 05 + Input (Constant) 81 01 + Usage Page (Generic Desktop Control) 05 01 + Usage (X) 09 30 + Usage (Y) 09 31 + Usage (Wheel) 09 38 + Logical Minimum (-127) 15 81 + Logical Maximum (127) 25 7F + Report Size (8) 75 08 + Report Count (3) 95 03 + Input (Data, Variable, Relative) 81 06 + End Collection C0 +End Collection C0 + + +************************************************************************/ + +#define REPORT_DESC_SIZE (52) +static uint_8_ptr ReportDesc; + +static uint_8 ReportDescData[REPORT_DESC_SIZE] = +{ + 0x05, + 0x01, + 0x09, + 0x02, + 0xA1, + 0x01, + 0x09, + 0x01, + + 0xA1, + 0x00, + 0x05, + 0x09, + 0x19, + 0x01, + 0x29, + 0x03, + + 0x15, + 0x00, + 0x25, + 0x01, + 0x95, + 0x03, + 0x75, + 0x01, + + 0x81, + 0x02, + 0x95, + 0x01, + 0x75, + 0x05, + 0x81, + 0x01, + + 0x05, + 0x01, + 0x09, + 0x30, + 0x09, + 0x31, + 0x09, + 0x38, + + 0x15, + 0x81, + 0x25, + 0x7F, + 0x75, + 0x08, + 0x95, + 0x03, + + 0x81, + 0x06, + 0xC0, + 0xC0 +}; + +/************************************************************** +This report descriptor can be used to report the set_report +and get_report capability to host. When this is used, modify +the config descriptor to reflect the size of report descriptor. +The following lines should be changed, + +USB_uint_16_low(0x0038), // Changed from USB_uint_16_low(0x0034), +USB_uint_16_high(0x0038), // Changed from USB_uint_16_high(0x0034), + + + + +uint_8 ReportDesc[56] = { + 0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop) + 0x09, 0x01, // USAGE (Vendor Usage 1) + 0xa1, 0x01, // COLLECTION (Application) + + 0x09, 0x02, // USAGE (Vendor Usage 2) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + + 0x09, 0x03, // USAGE (Vendor Usage 3) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + + 0x09, 0x04, // USAGE (Vendor Usage 4) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + + 0x09, 0x05, // USAGE (Vendor Usage 5) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + + 0xc0 // END_COLLECTION +}; +***************************************************************/ + +/********************************************************************** +Mouse data (this structure is used to send mouse movement information) +**********************************************************************/ +typedef struct _MOUSE_DATA { + char a; + char b; + char c; + char d; + +} MOUSE_DATA_STRUCT; + +static MOUSE_DATA_STRUCT mouse_data = {0,0,0,0}; + +static uint_8 USB_IF_ALT[4] = { 0, 0, 0, 0}; + +/* number of strings in the table not including 0 or n. */ +static const uint_8 USB_STR_NUM = 6; + +/* +** if the number of strings changes, look for USB_STR_0 everywhere and make +** the obvious changes. It should be found in 3 places. +*/ + +static const uint_16 USB_STR_0[ 2] = {0x0300 + sizeof(USB_STR_0),0x0409}; +static const uint_16 USB_STR_1[26] = {0x0300 + sizeof(USB_STR_1), + 'M','a','r','v','e','l','l',' ','S','e','m','i','c','o','n','d','u','c','t','o','r',' ','L','t','d'}; +static const uint_16 USB_STR_2[28] = {0x0300 + sizeof(USB_STR_2), + 'M','A','R','V','E','L','L',' ','U','S','B',' ','h','i','d','m','o','u','s','e',' ',\ + 'D','e','v','i','c','e'}; +static const uint_16 USB_STR_3[ 5] = {0x0300 + sizeof(USB_STR_3), + 'B','E','T','A'}; +static const uint_16 USB_STR_4[ 4] = {0x0300 + sizeof(USB_STR_4), + '#','0','2'}; +static const uint_16 USB_STR_5[ 4] = {0x0300 + sizeof(USB_STR_5), + '_','A','1'}; +static const uint_16 USB_STR_6[15] = {0x0300 + sizeof(USB_STR_6), + 'Y','o','u','r',' ','n','a','m','e',' ','h','e','r','e'}; +static const uint_16 USB_STR_n[17] = {0x0300 + sizeof(USB_STR_n), + 'B','A','D',' ','S','T','R','I','N','G',' ','I','n','d','e','x'}; + +#define USB_STRING_ARRAY_SIZE 8 +static const uint_8_ptr USB_STRING_DESC[USB_STRING_ARRAY_SIZE] = +{ + (uint_8_ptr)USB_STR_0, + (uint_8_ptr)USB_STR_1, + (uint_8_ptr)USB_STR_2, + (uint_8_ptr)USB_STR_3, + (uint_8_ptr)USB_STR_4, + (uint_8_ptr)USB_STR_5, + (uint_8_ptr)USB_STR_6, + (uint_8_ptr)USB_STR_n +}; + + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9GetDescription +* Returned Value : None +* Comments : +* Chapter 9 GetDescription command +* The Device Request can ask for Device/Config/string/interface/endpoint +* descriptors (via wValue). We then post an IN response to return the +* requested descriptor. +* And then wait for the OUT which terminates the control transfer. +* See section 9.4.3 (page 189) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9GetDescription + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + if (setup) { + /* Load the appropriate string depending on the descriptor requested.*/ + switch (setup_ptr->VALUE & 0xFF00) { + + case 0x0100: + _usb_device_send_data(handle, 0, DevDesc, + MIN(setup_ptr->LENGTH, DEVICE_DESCRIPTOR_SIZE)); + + break; + + case 0x0200: + *(ConfigDesc + 33) = frame_interval; + _usb_device_send_data(handle, 0, ConfigDesc, + MIN(setup_ptr->LENGTH, CONFIG_DESC_SIZE)); + + break; + + case 0x2200: + _usb_device_send_data(handle, 0, ReportDesc, + MIN(setup_ptr->LENGTH, REPORT_DESC_SIZE)); + + /*send some data for the mouse in the interrupt pipe queue */ + _usb_device_send_data(handle, INTERRUPT_EP, (uint_8_ptr)((pointer)&mouse_data), + sizeof(MOUSE_DATA_STRUCT)); + + break; + + case 0x0300: + if ((setup_ptr->VALUE & 0x00FF) > USB_STR_NUM) { + _usb_device_send_data(handle, 0, USB_STRING_DESC[USB_STR_NUM+1], + MIN(setup_ptr->LENGTH, USB_STRING_DESC[USB_STR_NUM+1][0])); + } else { + _usb_device_send_data(handle, 0, + USB_STRING_DESC[setup_ptr->VALUE & 0x00FF], + MIN(setup_ptr->LENGTH, USB_STRING_DESC[setup_ptr->VALUE & 0x00FF][0])); + } /* Endif */ + break; + + case 0x600: + _usb_device_send_data(handle, 0, (uint_8_ptr)DevQualifierDesc, + MIN(setup_ptr->LENGTH, DEVICE_QUALIFIER_DESCRIPTOR_SIZE)); + break; + + case 0x700: + *(other_speed_config + 33) = frame_interval; + + _usb_device_send_data(handle, 0, (uint_8_ptr)other_speed_config, + MIN(setup_ptr->LENGTH, OTHER_SPEED_CONFIG_DESC_SIZE)); + break; + + default: + USB_printf("usbMouse_%d, %s: Unexpected VALUE=0x%04x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, 0); + return; + } /* Endswitch */ + /* status phase */ + _usb_device_recv_data(handle, 0, 0, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SetDescription +* Returned Value : None +* Comments : +* Chapter 9 SetDescription command +* See section 9.4.8 (page 193) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9SetDescription + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + USB_printf("usbMouse_%d, %s: setup=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, (int)setup); + _usb_device_stall_endpoint(handle, 0, 0); + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9GetConfig +* Returned Value : None +* Comments : +* Chapter 9 GetConfig command +* See section 9.4.2 (page 189) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9GetConfig + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + uint_16 current_config; + /* Return the currently selected configuration */ + if (setup){ + _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, + ¤t_config); + data_to_send = (uint_8)current_config; + _usb_device_send_data(handle, 0, (pointer) &data_to_send, sizeof(data_to_send)); + /* status phase */ + _usb_device_recv_data(handle, 0, 0, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SetConfig +* Returned Value : None +* Comments : +* Chapter 9 SetConfig command +* +*END*--------------------------------------------------------------------*/ +static void ch9SetConfig + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + uint_16 usb_state; + + if (setup) + { + if ((setup_ptr->VALUE & 0x00FF) > 1) + { + /* generate stall */ + USB_printf("usbMouse_%d, %s: Wrong VALUE=0x%04x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->VALUE); + _usb_device_stall_endpoint(handle, 0, 0); + return; + } /* Endif */ + + /* 0 indicates return to unconfigured state */ + if ((setup_ptr->VALUE & 0x00FF) == 0) + { + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state); + if ((usb_state == ARC_USB_STATE_CONFIG) || + (usb_state == ARC_USB_STATE_ADDRESS)) + { + /* clear the currently selected config value */ + _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, 0); + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, + ARC_USB_STATE_ADDRESS); + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); + } + else + { + USB_printf("usbMouse_%d, %s: Wrong usb_state=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, usb_state); + + _usb_device_stall_endpoint(handle, 0, 0); + } /* Endif */ + return; + } /* Endif */ + + /* + ** If the configuration value (setup_ptr->VALUE & 0x00FF) differs + ** from the current configuration value, then endpoints must be + ** reconfigured to match the new device configuration + */ + _usb_device_get_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, &usb_state); + ARC_DEBUG_TRACE(ARC_DEBUG_FLAG_SETUP, + "usbMouse: Set configuration: old=%d, new=%d\n", + usb_state, setup_ptr->VALUE & 0x00FF); + + if (usb_state != (setup_ptr->VALUE & 0x00FF)) + { + /* Reconfigure endpoints here */ + switch (setup_ptr->VALUE & 0x00FF) + { + default: + break; + } /* Endswitch */ + _usb_device_set_status(handle, ARC_USB_STATUS_CURRENT_CONFIG, + setup_ptr->VALUE & 0x00FF); + } /* Endif */ + /* Init Interrupt endpoint */ + _usb_device_init_endpoint(handle,INTERRUPT_EP, INTERRUPT_MAX_PACKET_SIZE, + ARC_USB_SEND, ARC_USB_INTERRUPT_ENDPOINT, + ARC_USB_DEVICE_DONT_ZERO_TERMINATE); + + TEST_ENABLED = TRUE; + + _usb_device_set_status(handle, ARC_USB_STATUS_DEVICE_STATE, + ARC_USB_STATE_CONFIG); + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9GetInterface +* Returned Value : None +* Comments : +* Chapter 9 GetInterface command +* See section 9.4.4 (page 190) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9GetInterface + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + uint_16 usb_state; + + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE_STATE, &usb_state); + if (usb_state != ARC_USB_STATE_CONFIG) + { + USB_printf("usbMouse_%d, %s: Wrong usb_state=%d\n", + _usb_device_get_dev_num(handle), __FUNCTION__, usb_state); + _usb_device_stall_endpoint(handle, 0, 0); + return; + } /* Endif */ + + if (setup) + { + _usb_device_send_data(handle, 0, &USB_IF_ALT[setup_ptr->INDEX & 0x00FF], + MIN(setup_ptr->LENGTH, sizeof(uint_8))); + /* status phase */ + _usb_device_recv_data(handle, 0, 0, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SetInterface +* Returned Value : None +* Comments : +* Chapter 9 SetInterface command +* See section 9.4.10 (page 195) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9SetInterface + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + if (setup) + { + if (setup_ptr->REQUESTTYPE != 0x01) + { + USB_printf("usbDisk_%d, %s: Wrong REQUESTTYPE=0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, + setup_ptr->REQUESTTYPE); + + _usb_device_stall_endpoint(handle, 0, 0); + return; + } /* Endif */ + + /* + ** If the alternate value (setup_ptr->VALUE & 0x00FF) differs + ** from the current alternate value for the specified interface, + ** then endpoints must be reconfigured to match the new alternate + */ + if (USB_IF_ALT[setup_ptr->INDEX & 0x00FF] + != (setup_ptr->VALUE & 0x00FF)) + { + USB_IF_ALT[setup_ptr->INDEX & 0x00FF] = (setup_ptr->VALUE & 0x00FF); + /* Reconfigure endpoints here. */ + + } /* Endif */ + + /* status phase */ + _usb_device_send_data(handle, 0, 0, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9SynchFrame +* Returned Value : +* Comments : +* Chapter 9 SynchFrame command +* See section 9.4.11 (page 195) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9SynchFrame + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + + if (setup) + { + if (setup_ptr->REQUESTTYPE != 0x02) + { + USB_printf("usbMouse_%d, %s: Wrong REQUESTTYPE=0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, + setup_ptr->REQUESTTYPE); + _usb_device_stall_endpoint(handle, 0, 0); + return; + } /* Endif */ + + if ((setup_ptr->INDEX & 0x00FF) >= + ConfigDesc[CONFIG_DESC_NUM_INTERFACES]) + { + USB_printf("usbMouse_%d, %s: Wrong INDEX=0x%04x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->INDEX); + _usb_device_stall_endpoint(handle, 0, 0); + return; + } /* Endif */ + + _usb_device_get_status(handle, ARC_USB_STATUS_SOF_COUNT, &sof_count); + + sof_count = USB_16BIT_LE(sof_count); + _usb_device_send_data(handle, 0, (uint_8_ptr)&sof_count, + MIN(setup_ptr->LENGTH, sizeof(sof_count))); + /* status phase */ + _usb_device_recv_data(handle, 0, 0, 0); + } /* Endif */ + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : get_report +* Returned Value : +* Comments : +* Chapter 9 Class specific request +* See section 9.4.11 (page 195) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ + +void get_report + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* [IN] Direction of the transfer. (1 for USB IN token)*/ + uint_8 direction, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + + ) +{ + int i; + + for(i=0;i<10;i++) + { + hid_test_rep_data[i] = (uint_8) i; + } + + if (setup) + { + _usb_device_send_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4)); + } + + _usb_device_recv_data(handle, 0, 0, 0); + + + return; +} + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : set_report +* Returned Value : +* Comments : +* Chapter 9 Class specific request +* See section 9.4.11 (page 195) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ + +void set_report + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* [IN] Direction of the transfer. (1 for USB IN token)*/ + uint_8 direction, + + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ + if (setup) /*on a SetUP packet*/ + { + _usb_device_recv_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4)); + + } + else if(direction == ARC_USB_RECV) /*on a OUT packet*/ + { + _usb_device_recv_data(handle, 0, (uint_8_ptr)hid_test_rep_data, MIN(setup_ptr->LENGTH,4)); + _usb_device_send_data(handle, 0, 0, 0); + } + + return; +} + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : set_idle +* Returned Value : +* Comments : +* Chapter 9 Class specific request +* See section 9.4.11 (page 195) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ + +void set_idle + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* [IN] Direction of the transfer. (1 for USB IN token)*/ + uint_8 direction, + + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ + /* SET_IDLE is a No data phase transaction from HID class. All it needs + is a terminating IN token */ + if (setup) /*on a SetUP packet*/ + { + _usb_device_send_data(handle, 0, 0, 0); + } + return; +} + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : ch9Class +* Returned Value : +* Comments : +* Chapter 9 Class specific request +* See section 9.4.11 (page 195) of the USB 1.1 Specification. +* +*END*--------------------------------------------------------------------*/ +static void ch9Class + ( + /* USB handle */ + _usb_device_handle handle, + + /* Is it a Setup phase? */ + boolean setup, + + /* [IN] Direction of the transfer. (1 for USB IN token)*/ + uint_8 direction, + + /* The setup packet pointer */ + SETUP_STRUCT_PTR setup_ptr + ) +{ /* Body */ + + switch (setup_ptr->REQUEST) + { + + case 0x01: + get_report(handle, setup, direction, setup_ptr); + break; + + case 0x09: + set_report(handle, setup, direction, setup_ptr); + break; + + case 0x0A: + set_idle(handle, setup, direction, setup_ptr); + break; + + default: + USB_printf("usbMouse_%d, %s: Wrong REQUEST=0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, setup_ptr->REQUEST); + + _usb_device_stall_endpoint(handle, 0, 0); + break; + + } /* EndSwitch */ + +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : service_ep0 +* Returned Value : None +* Comments : +* Called upon a completed endpoint 0 (USB 1.1 Chapter 9) transfer +* +*END*--------------------------------------------------------------------*/ +static void service_ep0 + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] request type as registered */ + uint_8 type, + + /* [IN] Is it a setup packet? */ + boolean setup, + + /* [IN] Direction of the transfer. Is it transmit? */ + uint_8 direction, + + /* [IN] Pointer to the data buffer */ + uint_8_ptr buffer, + + /* [IN] Length of the transfer */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + + + ) +{ /* Body */ + boolean class_request = FALSE; + + if (setup) + { + _usb_device_read_setup_data(handle, 0, (uint_8_ptr)&local_setup_packet); + local_setup_packet.VALUE = USB_16BIT_LE(local_setup_packet.VALUE); + local_setup_packet.INDEX = USB_16BIT_LE(local_setup_packet.INDEX); + local_setup_packet.LENGTH = USB_16BIT_LE(local_setup_packet.LENGTH); + } + else if (class_request) { + class_request = FALSE; + /* Finish your class or vendor request here */ + + return; + } /* Endif */ + + switch (local_setup_packet.REQUESTTYPE & 0x60) { + + case 0x00: + switch (local_setup_packet.REQUEST) { + + case 0x0: + mvUsbCh9GetStatus(handle, setup, &local_setup_packet); + break; + + case 0x1: + mvUsbCh9ClearFeature(handle, setup, &local_setup_packet); + break; + + case 0x3: + mvUsbCh9SetFeature(handle, setup, &local_setup_packet); + break; + + case 0x5: + mvUsbCh9SetAddress(handle, setup, &local_setup_packet); + break; + + case 0x6: + ch9GetDescription(handle, setup, &local_setup_packet); + break; + + case 0x7: + ch9SetDescription(handle, setup, &local_setup_packet); + break; + + case 0x8: + ch9GetConfig(handle, setup, &local_setup_packet); + break; + + case 0x9: + ch9SetConfig(handle, setup, &local_setup_packet); + break; + + case 0xa: + ch9GetInterface(handle, setup, &local_setup_packet); + break; + + case 0xb: + ch9SetInterface(handle, setup, &local_setup_packet); + break; + + case 0xc: + ch9SynchFrame(handle, setup, &local_setup_packet); + break; + + default: + USB_printf("usbMouse_%d, %s: Wrong REQUEST = 0x%02x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, local_setup_packet.REQUEST); + _usb_device_stall_endpoint(handle, 0, 0); + break; + + } /* Endswitch */ + + break; + + case 0x20: + ch9Class(handle, setup, direction, &local_setup_packet); + + break; + + case 0x40: + /* vendor specific request */ + break; + + default: + USB_printf("usbMouse_%d, %s: Unexpected REQUESTTYPE = 0x%x\n", + _usb_device_get_dev_num(handle), __FUNCTION__, + local_setup_packet.REQUESTTYPE); + + _usb_device_stall_endpoint(handle, 0, 0); + break; + + } /* Endswitch */ + + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : service_ep1 +* Returned Value : None +* Comments : +* Called upon a completed endpoint 1 (USB 1.1 Chapter 9) transfer +* +*END*--------------------------------------------------------------------*/ +static void service_ep1 + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] request type as registered */ + uint_8 type, + + /* [IN] Is it a setup packet? */ + boolean setup, + + /* [IN] Direction of the transfer. Is it transmit? */ + uint_8 direction, + + /* [IN] Pointer to the data buffer */ + uint_8_ptr buffer, + + /* [IN] Length of the transfer */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + + + ) +{ /* Body */ + +/******************************************************************** + The following code will move the mouse right and left on the screen. + Comment this out if this behaviour is not desired. +********************************************************************/ + + static int x = 0; + static boolean right = FALSE; + static int wait = 0; + + mouseCntr++; + if(wait == 0) + { + if (right == FALSE) + { + mouse_data.b = 1; + x++; + right = (x > 200) ? TRUE : FALSE; + } + + if (right == TRUE) + { + mouse_data.b = -1; + x--; + right = (x < 0) ? FALSE : TRUE; + } + wait = mouseDelay; + } + else + { + wait--; + mouse_data.b = 0; + } + + _usb_device_send_data(handle, INTERRUPT_EP, (uint_8_ptr)((pointer)&mouse_data), + sizeof(MOUSE_DATA_STRUCT)); + + return; +} /* Endbody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : reset_ep0 +* Returned Value : None +* Comments : +* Called upon a bus reset event. Initialises the control endpoint. +* +*END*--------------------------------------------------------------------*/ +static void reset_ep0 + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] request type as registered */ + uint_8 type, + + /* [IN] Unused */ + boolean setup, + + /* [IN] Unused */ + uint_8 direction, + + /* [IN] Unused */ + uint_8_ptr buffer, + + /* [IN] Unused */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + + + ) +{ /* Body */ + + /*on a reset always cancel all transfers all EP 0 */ + _usb_device_cancel_transfer(handle, 0, ARC_USB_RECV); + _usb_device_cancel_transfer(handle, 0, ARC_USB_SEND); + + _usb_device_start(handle); + + /* Initialize the endpoint 0 in both directions */ + _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 0, + ARC_USB_CONTROL_ENDPOINT, 0); + _usb_device_init_endpoint(handle, 0, DevDesc[DEV_DESC_MAX_PACKET_SIZE], 1, + ARC_USB_CONTROL_ENDPOINT, 0); + + if (TEST_ENABLED) + { + _usb_device_cancel_transfer(handle, INTERRUPT_EP, ARC_USB_SEND); + } /* Endif */ + + TEST_ENABLED = FALSE; + mouseCntr = 0; + + return; +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : service_suspend +* Returned Value : None +* Comments : +* Called when host suspend the USB port. Do remote wake up if desired. +* +*END*--------------------------------------------------------------------*/ +static void service_suspend + ( + /* [IN] Handle of the USB device */ + _usb_device_handle handle, + + /* [IN] request type as registered */ + uint_8 type, + + /* [IN] Unused */ + boolean setup, + + /* [IN] Unused */ + uint_8 direction, + + /* [IN] Unused */ + uint_8_ptr buffer, + + /* [IN] Unused */ + uint_32 length, + + /* [IN] Error, if any */ + uint_8 error + ) +{ /* Body */ + uint_16 usb_status; + int lockKey; + + _usb_device_get_status(handle, ARC_USB_STATUS_DEVICE, &usb_status); + if (usb_status & ARC_USB_REMOTE_WAKEUP) + { + lockKey = USB_lock(); + + USB_printf("Mouse Suspended: type=%d, usbStatus=0x%x\n", type, usb_status); + USB_SUSPENDED = TRUE; + + USB_unlock(lockKey); + } + + return; +} /* EndBody */ + +/*FUNCTION*---------------------------------------------------------------- +* +* Function Name : usbMouseLoad +* Returned Value : None +* Comments : +* First function called. Initialises the USB and registers Chapter 9 +* callback functions. +* +*END*--------------------------------------------------------------------*/ +_usb_device_handle usbMouseLoad(int devNo) +{ /* Body */ + _usb_device_handle handle; + uint_8 error; + uint_32 send_data_buffer_size=0; + uint_8_ptr temp; + int lockKey, i, j; + static boolean isFirst = TRUE; + + if(isFirst) + { + /* Swap all USB_STRING_DESC */ + for(i=0; i<(sizeof(USB_STRING_DESC)/sizeof(USB_STRING_DESC[0])); i++) + { + uint_16* usbStr = (uint_16*)(USB_STRING_DESC[i]); + uint_16 size = (usbStr[0]-0x300)/sizeof(uint_16); + + for(j=0; j gpp5, DDR2 => gpp1 */ + if(gppNo != (MV_U8)N_A) + { + /*mvOsPrintf("mvUsbGppInit: gppNo=%d\n", gppNo);*/ + + /* MPP Control Register - set to GPP*/ + regVal = MV_REG_READ(mvCtrlMppRegGet((unsigned int)(gppNo/8))); + regVal &= ~(0xf << ((gppNo%8)*4)); + MV_REG_WRITE(mvCtrlMppRegGet((unsigned int)(gppNo/8)), regVal); + + + if(gppNo < 32) + { + /* GPIO Data Out Enable Control Register - set to input*/ + mvGppTypeSet(0, (1< bits[17:16] = 0x1 */ + if( (mvCtrlModelGet() == MV64560_DEV_ID) || + (mvCtrlModelGet() == MV64660_DEV_ID)) + { + regVal &= ~(0x3 << 16); + regVal |= (0x1 << 16); + } + + /* bits[19:18] = 0x2 */ + regVal &= ~(0x3 << 18); + regVal |= (0x2 << 18); + + /* bit[20] = 0x0 */ + regVal &= ~(0x1 << 20); + + /* bit[21] = 0x1 */ + regVal |= (0x1 << 21); + + MV_REG_WRITE(MV_USB_PHY_IVREF_CTRL_REG(dev), regVal); + + /***** USB PHY TEST GROUP CONTROL Register: 0x450 *****/ + regVal = MV_REG_READ(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev)); + + /* bit[15] = 0 (REG_FIFO_SQ_RST = 0). */ + regVal &= ~(1 << 15); + + /* bit[17] = 0x1 */ + if( (mvCtrlModelGet() == MV64560_DEV_ID) || + (mvCtrlModelGet() == MV64660_DEV_ID)) + { + regVal |= (1 << 17); + } + + MV_REG_WRITE(MV_USB_PHY_TEST_GROUP_CTRL_REG_0(dev), regVal); +} + +/******************************************************************************* +* mvUsbHalInit - Initialize USB engine +* +* DESCRIPTION: +* This function initialize USB unit. It set the default address decode +* windows of the unit. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if setting fail. +*******************************************************************************/ +MV_STATUS mvUsbHalInit(int dev, MV_BOOL isHost) +{ + MV_U32 regVal; + + /* Clear Interrupt Cause and Mask registers */ + MV_REG_WRITE(MV_USB_BRIDGE_INTR_CAUSE_REG(dev), 0); + MV_REG_WRITE(MV_USB_BRIDGE_INTR_MASK_REG(dev), 0); + + /* Reset controller */ + regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev)); + MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal | MV_USB_CORE_CMD_RESET_MASK); + while( MV_REG_READ(MV_USB_CORE_CMD_REG(dev)) & MV_USB_CORE_CMD_RESET_MASK); + + /* Clear bit 4 in USB bridge control register for enableing core byte swap */ + if((mvCtrlModelGet() == MV64560_DEV_ID) || (mvCtrlModelGet() == MV64660_DEV_ID)) + { + MV_REG_WRITE(MV_USB_BRIDGE_CTRL_REG(dev),(MV_REG_READ(MV_USB_BRIDGE_CTRL_REG(dev)) + & ~MV_USB_BRIDGE_CORE_BYTE_SWAP_MASK)); + } + + /* GL# USB-10 */ + /* The new register 0x360 USB 2.0 IPG Metal Fix Register + * dont' exists in the following chip revisions: + * OrionN B1 (id=0x5180, rev 3) + * Orion1 B1 (id=0x5181, rev=3) and before + * Orion1-VoIP A0 (id=0x5181, rev=8) + * Orion1-NAS A1 (id=0x5182, rev=1) and before + * Orion2 B0 (id=0x5281, rev=1) and before + */ + if( ((mvCtrlModelGet() == MV_5181_DEV_ID) && + ((mvCtrlRevGet() <= MV_5181_B1_REV) || (mvCtrlRevGet() == MV_5181L_A0_REV))) || + ((mvCtrlModelGet() == MV_5182_DEV_ID) && + (mvCtrlRevGet() <= MV_5182_A1_REV)) || + ((mvCtrlModelGet() == MV_5180_DEV_ID) && + (mvCtrlRevGet() <= MV_5180N_B1_REV)) ) + { + /* Do nothing */ + } + else + { + /* Change value of new register 0x360 */ + regVal = MV_REG_READ(MV_USB_BRIDGE_IPG_REG(dev)); + + /* Change bits[14:8] - IPG for non Start of Frame Packets + * from 0x9(default) to 0xD + */ + regVal &= ~(0x7F << 8); + regVal |= (0xD << 8); + + MV_REG_WRITE(MV_USB_BRIDGE_IPG_REG(dev), regVal); + } + + /********* Update USB PHY configuration **********/ + if( (mvCtrlModelGet() == MV_78100_DEV_ID) || + (mvCtrlModelGet() == MV_78200_DEV_ID) || + (mvCtrlModelGet() == MV_6281_DEV_ID) || + (mvCtrlModelGet() == MV_6192_DEV_ID) || + (mvCtrlModelGet() == MV_6190_DEV_ID) || + (mvCtrlModelGet() == MV_6180_DEV_ID)) + { + mvUsbPhy65nmNewInit(dev); + } + else if((mvCtrlModelGet() == MV_78XX0_DEV_ID)) + { + mvUsbPhy65nmInit(dev); + } + else if( mvCtrlModelGet() == MV_6183_DEV_ID ) + { + mvUsbPhy90nmInit(dev); + } + else + { + mvUsbPhyInit(dev); + } + + /* Set Mode register (Stop and Reset USB Core before) */ + /* Stop the controller */ + regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev)); + regVal &= ~MV_USB_CORE_CMD_RUN_MASK; + MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal); + + /* Reset the controller to get default values */ + regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev)); + regVal |= MV_USB_CORE_CMD_RESET_MASK; + MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal); + + /* Wait for the controller reset to complete */ + do + { + regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev)); + } while (regVal & MV_USB_CORE_CMD_RESET_MASK); + + /* Set USB_MODE register */ + if(isHost) + { + regVal = MV_USB_CORE_MODE_HOST; + } + else + { + regVal = MV_USB_CORE_MODE_DEVICE | MV_USB_CORE_SETUP_LOCK_DISABLE_MASK; + } + +#if (MV_USB_VERSION == 0) + regVal |= MV_USB_CORE_STREAM_DISABLE_MASK; +#endif + + MV_REG_WRITE(MV_USB_CORE_MODE_REG(dev), regVal); + + return MV_OK; +} + + +void mvUsbPowerDown(int dev) +{ + MV_U32 regVal; + + /* Stop USB Controller core */ + regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev)); + if(regVal & MV_USB_CORE_CMD_RUN_MASK) + { + mvOsPrintf("USB #%d: Warning USB core was not disabled\n", dev); + regVal &= ~MV_USB_CORE_CMD_RUN_MASK; + MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal); + } + + /* Power Down USB PHY */ + regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev)); + regVal &= ~(MV_USB_PHY_POWER_UP_MASK | MV_USB_PHY_PLL_POWER_UP_MASK); + + MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal); +} + +void mvUsbPowerUp(int dev) +{ + MV_U32 regVal; + + /* Power Up USB PHY */ + regVal = MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev)); + regVal |= (MV_USB_PHY_POWER_UP_MASK | MV_USB_PHY_PLL_POWER_UP_MASK); + + MV_REG_WRITE(MV_USB_PHY_POWER_CTRL_REG(dev), regVal); + + /* Start USB core */ + regVal = MV_REG_READ(MV_USB_CORE_CMD_REG(dev)); + if(regVal & MV_USB_CORE_CMD_RUN_MASK) + { + mvOsPrintf("USB #%d: Warning USB core is enabled\n", dev); + } + else + { + regVal |= MV_USB_CORE_CMD_RUN_MASK; + MV_REG_WRITE(MV_USB_CORE_CMD_REG(dev), regVal); + } +} + + +void mvUsbRegs(int dev) +{ + mvOsPrintf("\n\tUSB-%d Bridge Registers\n\n", dev); + + mvOsPrintf("MV_USB_BRIDGE_CTRL_REG : 0x%X = 0x%08x\n", + MV_USB_BRIDGE_CTRL_REG(dev), + MV_REG_READ(MV_USB_BRIDGE_CTRL_REG(dev)) ); + + mvOsPrintf("MV_USB_BRIDGE_INTR_MASK_REG : 0x%X = 0x%08x\n", + MV_USB_BRIDGE_INTR_MASK_REG(dev), + MV_REG_READ(MV_USB_BRIDGE_INTR_MASK_REG(dev))); + + mvOsPrintf("MV_USB_BRIDGE_INTR_CAUSE_REG : 0x%X = 0x%08x\n", + MV_USB_BRIDGE_INTR_CAUSE_REG(dev), + MV_REG_READ(MV_USB_BRIDGE_INTR_CAUSE_REG(dev))); + + mvOsPrintf("MV_USB_BRIDGE_ERROR_ADDR_REG : 0x%X = 0x%08x\n", + MV_USB_BRIDGE_ERROR_ADDR_REG(dev), + MV_REG_READ(MV_USB_BRIDGE_ERROR_ADDR_REG(dev))); + + mvOsPrintf("\n\tUSB-%d PHY Registers\n\n", dev); + + mvOsPrintf("MV_USB_PHY_POWER_CTRL_REG : 0x%X = 0x%08x\n", + MV_USB_PHY_POWER_CTRL_REG(dev), + MV_REG_READ(MV_USB_PHY_POWER_CTRL_REG(dev)) ); + + mvOsPrintf("MV_USB_PHY_TX_CTRL_REG : 0x%X = 0x%08x\n", + MV_USB_PHY_TX_CTRL_REG(dev), + MV_REG_READ(MV_USB_PHY_TX_CTRL_REG(dev)) ); + mvOsPrintf("MV_USB_PHY_RX_CTRL_REG : 0x%X = 0x%08x\n", + MV_USB_PHY_RX_CTRL_REG(dev), + MV_REG_READ(MV_USB_PHY_RX_CTRL_REG(dev)) ); + mvOsPrintf("MV_USB_PHY_IVREF_CTRL_REG : 0x%X = 0x%08x\n", + MV_USB_PHY_IVREF_CTRL_REG(dev), + MV_REG_READ(MV_USB_PHY_IVREF_CTRL_REG(dev)) ); + + mvOsPrintf("\n"); + +} + +void mvUsbCoreRegs(int dev, MV_BOOL isHost) +{ + mvOsPrintf("\n\t USB-%d Core %s Registers\n\n", + dev, isHost ? "HOST" : "DEVICE"); + + mvOsPrintf("MV_USB_CORE_ID_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ID_REG(dev), + MV_REG_READ(MV_USB_CORE_ID_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_GENERAL_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_GENERAL_REG(dev), + MV_REG_READ(MV_USB_CORE_GENERAL_REG(dev)) ); + + if(isHost) + { + mvOsPrintf("MV_USB_CORE_HOST_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_HOST_REG(dev), + MV_REG_READ(MV_USB_CORE_HOST_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_TTTX_BUF_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_TTTX_BUF_REG(dev), + MV_REG_READ(MV_USB_CORE_TTTX_BUF_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_TTRX_BUF_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_TTRX_BUF_REG(dev), + MV_REG_READ(MV_USB_CORE_TTRX_BUF_REG(dev)) ); + } + else + { + mvOsPrintf("MV_USB_CORE_DEVICE_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_DEVICE_REG(dev), + MV_REG_READ(MV_USB_CORE_DEVICE_REG(dev)) ); + } + + mvOsPrintf("MV_USB_CORE_TX_BUF_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_TX_BUF_REG(dev), + MV_REG_READ(MV_USB_CORE_TX_BUF_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_RX_BUF_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_RX_BUF_REG(dev), + MV_REG_READ(MV_USB_CORE_RX_BUF_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_CAP_LENGTH_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_CAP_LENGTH_REG(dev), + MV_REG_READ(MV_USB_CORE_CAP_LENGTH_REG(dev)) ); + + if(isHost) + { + mvOsPrintf("MV_USB_CORE_CAP_HCS_PARAMS_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_CAP_HCS_PARAMS_REG(dev), + MV_REG_READ(MV_USB_CORE_CAP_HCS_PARAMS_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_CAP_HCC_PARAMS_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_CAP_HCC_PARAMS_REG(dev), + MV_REG_READ(MV_USB_CORE_CAP_HCC_PARAMS_REG(dev)) ); + } + else + { + mvOsPrintf("MV_USB_CORE_CAP_DCI_VERSION_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_CAP_DCI_VERSION_REG(dev), + MV_REG_READ(MV_USB_CORE_CAP_DCI_VERSION_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_CAP_DCC_PARAMS_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_CAP_DCC_PARAMS_REG(dev), + MV_REG_READ(MV_USB_CORE_CAP_DCC_PARAMS_REG(dev)) ); + } + + mvOsPrintf("MV_USB_CORE_CMD_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_CMD_REG(dev), + MV_REG_READ(MV_USB_CORE_CMD_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_STATUS_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_STATUS_REG(dev), + MV_REG_READ(MV_USB_CORE_STATUS_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_INTR_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_INTR_REG(dev), + MV_REG_READ(MV_USB_CORE_INTR_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_FRAME_INDEX_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_FRAME_INDEX_REG(dev), + MV_REG_READ(MV_USB_CORE_FRAME_INDEX_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_MODE_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_MODE_REG(dev), + MV_REG_READ(MV_USB_CORE_MODE_REG(dev)) ); + + if(isHost) + { + mvOsPrintf("MV_USB_CORE_PERIODIC_LIST_BASE_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_PERIODIC_LIST_BASE_REG(dev), + MV_REG_READ(MV_USB_CORE_PERIODIC_LIST_BASE_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_ASYNC_LIST_ADDR_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ASYNC_LIST_ADDR_REG(dev), + MV_REG_READ(MV_USB_CORE_ASYNC_LIST_ADDR_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_CONFIG_FLAG_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_CONFIG_FLAG_REG(dev), + MV_REG_READ(MV_USB_CORE_CONFIG_FLAG_REG(dev)) ); + } + else + { + int numEp, ep; + MV_U32 epCtrlVal; + + mvOsPrintf("MV_USB_CORE_DEV_ADDR_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_DEV_ADDR_REG(dev), + MV_REG_READ(MV_USB_CORE_DEV_ADDR_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_ENDPOINT_LIST_ADDR_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ENDPOINT_LIST_ADDR_REG(dev), + MV_REG_READ(MV_USB_CORE_ENDPOINT_LIST_ADDR_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_ENDPT_SETUP_STAT_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ENDPT_SETUP_STAT_REG(dev), + MV_REG_READ(MV_USB_CORE_ENDPT_SETUP_STAT_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_ENDPT_PRIME_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ENDPT_PRIME_REG(dev), + MV_REG_READ(MV_USB_CORE_ENDPT_PRIME_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_ENDPT_FLUSH_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ENDPT_FLUSH_REG(dev), + MV_REG_READ(MV_USB_CORE_ENDPT_FLUSH_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_ENDPT_STATUS_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ENDPT_STATUS_REG(dev), + MV_REG_READ(MV_USB_CORE_ENDPT_STATUS_REG(dev)) ); + + mvOsPrintf("MV_USB_CORE_ENDPT_COMPLETE_REG : 0x%X = 0x%08x\n", + MV_USB_CORE_ENDPT_COMPLETE_REG(dev), + MV_REG_READ(MV_USB_CORE_ENDPT_COMPLETE_REG(dev)) ); + + numEp = MV_REG_READ(MV_USB_CORE_CAP_DCC_PARAMS_REG(dev)) & 0x1F; + + for(ep=0; ep= MV_XOR_MAX_CHAN) + { + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n",__FUNCTION__ ,chan)); + return MV_BAD_PARAM; + } + if (NULL == pXorEccConfig) + { + DB(mvOsPrintf("%s: ERR. pXorEccConfig is NULL pointer\n", + __FUNCTION__ )); + return MV_BAD_PTR; + } + if (MV_ACTIVE == mvXorStateGet(chan)) + { + DB(mvOsPrintf("%s: ERR. Channel is already active\n", __FUNCTION__ )); + return MV_BUSY; + } + if ((pXorEccConfig->sectorSize < XETMCR_SECTION_SIZE_MIN_VALUE) || + (pXorEccConfig->sectorSize > XETMCR_SECTION_SIZE_MAX_VALUE)) + { + DB(mvOsPrintf("%s: ERR. sectorSize must be between %d to %d\n", + __FUNCTION__,XETMCR_SECTION_SIZE_MIN_VALUE, + XETMCR_SECTION_SIZE_MAX_VALUE)); + return MV_BAD_PARAM; + } + if ((pXorEccConfig->blockSize < XEXBSR_BLOCK_SIZE_MIN_VALUE) || + (pXorEccConfig->blockSize > XEXBSR_BLOCK_SIZE_MAX_VALUE)) + { + DB(mvOsPrintf("%s: ERR. Block size must be between %d to %ul\n", + __FUNCTION__,XEXBSR_BLOCK_SIZE_MIN_VALUE, + XEXBSR_BLOCK_SIZE_MAX_VALUE)); + return MV_BAD_PARAM; + } + if (0x0 == pXorEccConfig->destPtr) + { + DB(mvOsPrintf("%s: ERR. destPtr is NULL pointer\n",__FUNCTION__ )); + return MV_BAD_PARAM; + } + + /* set the operation mode to ECC */ + temp = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan),XOR_CHAN(chan))); + temp &= ~XEXCR_OPERATION_MODE_MASK; + temp |= XEXCR_OPERATION_MODE_ECC; + MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan),XOR_CHAN(chan)), temp); + + /* update the TimerEn bit in the XOR Engine Timer Mode + Control Register (XETMCR) */ + if (pXorEccConfig->periodicEnable) + { + MV_REG_BIT_SET(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)),XETMCR_TIMER_EN_MASK); + } + else + { + MV_REG_BIT_RESET(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)),XETMCR_TIMER_EN_MASK); + } + + /* update the SectionSizeCtrl bit in the XOR Engine Timer Mode Control + Register (XETMCR) */ + temp = MV_REG_READ(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan))); + temp &= ~XETMCR_SECTION_SIZE_CTRL_MASK; + temp |= (pXorEccConfig->sectorSize << XETMCR_SECTION_SIZE_CTRL_OFFS); + MV_REG_WRITE(XOR_TIMER_MODE_CTRL_REG(XOR_UNIT(chan)), temp); + + /* update the DstPtr field in the XOR Engine [0..1] Destination Pointer + Register (XExDPR0) */ + MV_REG_WRITE(XOR_DST_PTR_REG(XOR_UNIT(chan),XOR_CHAN(chan)), pXorEccConfig->destPtr); + + /* update the BlockSize field in the XOR Engine[0..1] Block Size + Registers (XExBSR) */ + MV_REG_WRITE(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + pXorEccConfig->blockSize); + + /* update the XOR Engine Timer Mode Initial Value Register (XETMIVR) */ + tClkCycles = pXorEccConfig->tClkTicks; + MV_REG_WRITE(XOR_TIMER_MODE_INIT_VAL_REG(XOR_UNIT(chan)), tClkCycles); + + /* start transfer */ + MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + XEXACTR_XESTART_MASK); + + return MV_OK; +} + +/******************************************************************************* +* mvXorEccCurrTimerGet - Return ECC timer current value. +* +* DESCRIPTION: +* Return the ECC timer mode Current value. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Timer ticks (in Tclk frequancy). +* +*******************************************************************************/ +MV_U32 mvXorEccCurrTimerGet(MV_U32 chan, MV_U32 tClk) +{ + /* read the current Tclk */ + return (MV_REG_READ(XOR_TIMER_MODE_CURR_VAL_REG(XOR_UNIT(chan)))); +} + +/******************************************************************************* +* mvXorMemInit - +* +* DESCRIPTION: +* +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_STATUS mvXorMemInit(MV_U32 chan, MV_U32 startPtr, MV_U32 blockSize, + MV_U32 initValHigh, MV_U32 initValLow) +{ + MV_U32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) + { + mvOsPrintf("%s: ERR. Invalid chan num %d\n",__FUNCTION__ , chan); + return MV_BAD_PARAM; + } + if (MV_ACTIVE == mvXorStateGet(chan)) + { + mvOsPrintf("%s: ERR. Channel is already active\n", __FUNCTION__ ); + return MV_BUSY; + } + if ((blockSize < XEXBSR_BLOCK_SIZE_MIN_VALUE) || + (blockSize > XEXBSR_BLOCK_SIZE_MAX_VALUE)) + { + mvOsPrintf("%s: ERR. Block size must be between %d to %ul\n", + __FUNCTION__,XEXBSR_BLOCK_SIZE_MIN_VALUE, + XEXBSR_BLOCK_SIZE_MAX_VALUE); + return MV_BAD_PARAM; + } +#if 0 +/* tzachi - this is done purposely by u-boot */ + if (0x0 == startPtr) + { + mvOsPrintf("%s: ERR. startPtr is NULL pointer\n", __FUNCTION__ ); + return MV_BAD_PARAM; + } +#endif + + /* set the operation mode to Memory Init */ + temp = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan),XOR_CHAN(chan))); + temp &= ~XEXCR_OPERATION_MODE_MASK; + temp |= XEXCR_OPERATION_MODE_MEM_INIT; + MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan),XOR_CHAN(chan)), temp); + + /* update the startPtr field in XOR Engine [0..1] Destination Pointer + Register (XExDPR0) */ + MV_REG_WRITE(XOR_DST_PTR_REG(XOR_UNIT(chan),XOR_CHAN(chan)), startPtr); + + /* update the BlockSize field in the XOR Engine[0..1] Block Size + Registers (XExBSR) */ + MV_REG_WRITE(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan),XOR_CHAN(chan)), blockSize); + + /* update the field InitValL in the XOR Engine Initial Value Register + Low (XEIVRL) */ + MV_REG_WRITE(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), initValLow); + + /* update the field InitValH in the XOR Engine Initial Value Register + High (XEIVRH) */ + MV_REG_WRITE(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), initValHigh); + + /* start transfer */ + MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + XEXACTR_XESTART_MASK); + + return MV_OK; +} + +/******************************************************************************* +* mvXorTransfer - Transfer data from source to destination on one of +* three modes (XOR,CRC32,DMA) +* +* DESCRIPTION: +* This function initiates XOR channel, according to function parameters, +* in order to perform XOR or CRC32 or DMA transaction. +* To gain maximum performance the user is asked to keep the following +* restrictions: +* 1) Selected engine is available (not busy). +* 1) This module does not take into consideration CPU MMU issues. +* In order for the XOR engine to access the appropreate source +* and destination, address parameters must be given in system +* physical mode. +* 2) This API does not take care of cache coherency issues. The source, +* destination and in case of chain the descriptor list are assumed +* to be cache coherent. +* 4) Parameters validity. For example, does size parameter exceeds +* maximum byte count of descriptor mode (16M or 64K). +* +* INPUT: +* chan - XOR channel number. See MV_XOR_CHANNEL enumerator. +* xorType - One of three: XOR, CRC32 and DMA operations. +* xorChainPtr - address of chain pointer +* +* OUTPUT: +* None. +* +* RETURS: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorTransfer(MV_U32 chan, MV_XOR_TYPE xorType, MV_U32 xorChainPtr) +{ + MV_U32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) + { + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n",__FUNCTION__ , chan)); + return MV_BAD_PARAM; + } + if (MV_ACTIVE == mvXorStateGet(chan)) + { + DB(mvOsPrintf("%s: ERR. Channel is already active\n", __FUNCTION__ )); + return MV_BUSY; + } + if (0x0 == xorChainPtr) + { + DB(mvOsPrintf("%s: ERR. xorChainPtr is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PARAM; + } + + /* read configuration register and mask the operation mode field */ + temp = MV_REG_READ(XOR_CONFIG_REG(XOR_UNIT(chan),XOR_CHAN(chan))); + temp &= ~XEXCR_OPERATION_MODE_MASK; + + switch (xorType) + { + case MV_XOR: + if (0 != (xorChainPtr & XEXDPR_DST_PTR_XOR_MASK)) + { + DB(mvOsPrintf("%s: ERR. Invalid chain pointer (bits [5:0] must " + "be cleared)\n",__FUNCTION__ )); + return MV_BAD_PARAM; + } + /* set the operation mode to XOR */ + temp |= XEXCR_OPERATION_MODE_XOR; + break; + + case MV_DMA: + if (0 != (xorChainPtr & XEXDPR_DST_PTR_DMA_MASK)) + { + DB(mvOsPrintf("%s: ERR. Invalid chain pointer (bits [4:0] must " + "be cleared)\n",__FUNCTION__ )); + return MV_BAD_PARAM; + } + /* set the operation mode to DMA */ + temp |= XEXCR_OPERATION_MODE_DMA; + break; + + case MV_CRC32: + if (0 != (xorChainPtr & XEXDPR_DST_PTR_CRC_MASK)) + { + DB(mvOsPrintf("%s: ERR. Invalid chain pointer (bits [4:0] must " + "be cleared)\n",__FUNCTION__ )); + return MV_BAD_PARAM; + } + /* set the operation mode to CRC32 */ + temp |= XEXCR_OPERATION_MODE_CRC; + break; + + default: + return MV_BAD_PARAM; + } + + /* write the operation mode to the register */ + MV_REG_WRITE(XOR_CONFIG_REG(XOR_UNIT(chan),XOR_CHAN(chan)), temp); + /* update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor + Pointer Register (XExNDPR) */ + MV_REG_WRITE(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + xorChainPtr); + + /* start transfer */ + MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + XEXACTR_XESTART_MASK); + + return MV_OK; +} + +/******************************************************************************* +* mvXorStateGet - Get XOR channel state. +* +* DESCRIPTION: +* XOR channel activity state can be active, idle, paused. +* This function retrunes the channel activity state. +* +* INPUT: +* chan - the channel number +* +* OUTPUT: +* None. +* +* RETURN: +* XOR_CHANNEL_IDLE - If the engine is idle. +* XOR_CHANNEL_ACTIVE - If the engine is busy. +* XOR_CHANNEL_PAUSED - If the engine is paused. +* MV_UNDEFINED_STATE - If the engine state is undefind or there is no +* such engine +* +*******************************************************************************/ +MV_STATE mvXorStateGet(MV_U32 chan) +{ + MV_U32 state; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) + { + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n",__FUNCTION__ , chan)); + return MV_UNDEFINED_STATE; + } + + /* read the current state */ + state = MV_REG_READ(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan))); + state &= XEXACTR_XESTATUS_MASK; + + /* return the state */ + switch (state) + { + case XEXACTR_XESTATUS_IDLE: + return MV_IDLE; + case XEXACTR_XESTATUS_ACTIVE: + return MV_ACTIVE; + case XEXACTR_XESTATUS_PAUSED: + return MV_PAUSED; + } + return MV_UNDEFINED_STATE; +} + +/******************************************************************************* +* mvXorCommandSet - Set command of XOR channel +* +* DESCRIPTION: +* XOR channel can be started, idle, paused and restarted. +* Paused can be set only if channel is active. +* Start can be set only if channel is idle or paused. +* Restart can be set only if channel is paused. +* Stop can be set only if channel is active. +* +* INPUT: +* chan - The channel number +* command - The command type (start, stop, restart, pause) +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on +* undefind XOR engine mode +* +*******************************************************************************/ +MV_STATUS mvXorCommandSet(MV_U32 chan, MV_COMMAND command) +{ + MV_STATE state; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) + { + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n",__FUNCTION__ , chan)); + return MV_BAD_PARAM; + } + + /* get the current state */ + state = mvXorStateGet(chan); + + /* command is start and current state is idle */ + if ((command == MV_START) && (state == MV_IDLE)) + { + MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + XEXACTR_XESTART_MASK); + return MV_OK; + } + /* command is stop and current state is active*/ + else if ((command == MV_STOP) && (state == MV_ACTIVE)) + { + MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + XEXACTR_XESTOP_MASK); + return MV_OK; + } + /* command is paused and current state is active */ + else if ((command == MV_PAUSED) && (state == MV_ACTIVE)) + { + MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + XEXACTR_XEPAUSE_MASK); + return MV_OK; + } + /* command is restart and current state is paused*/ + else if ((command == MV_RESTART) && (state == MV_PAUSED)) + { + MV_REG_BIT_SET(XOR_ACTIVATION_REG(XOR_UNIT(chan),XOR_CHAN(chan)), + XEXACTR_XERESTART_MASK); + return MV_OK; + } + + /* command is stop and current state is active*/ + else if ((command == MV_STOP) && (state == MV_IDLE)) + { + return MV_OK; + } + + /* illegal command */ + DB(mvOsPrintf("%s: ERR. Illegal command\n", __FUNCTION__)); + + return MV_BAD_PARAM; +} + +/******************************************************************************* +* mvXorOverrideSet - Set XOR target window override +* +* DESCRIPTION: +* The address override feature enables additional address decoupling. +* For example, it allows the use of the same source and destination +* addresses while the source is targeted to one interface and +* destination to a second interface. +* XOR source/destination/next descriptor addresses can be override per +* address decode windows 0,1,2 and 3 only. +* This function set override parameters per XOR channel. It access +* XOR control register low. +* +* INPUT: +* chan - XOR channel number. See MV_XOR_CHANNEL enumerator. +* winNum - Override window number. +* Note: Not all windows can override. +* override - Type of override. See MV_XOR_OVERRIDE enumerator. +* enable - Window override is enabled or disabled +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ + +MV_STATUS mvXorOverrideSet(MV_U32 chan, MV_XOR_OVERRIDE_TARGET target, + MV_U32 winNum, MV_BOOL enable) +{ + MV_U32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) + { + + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __FUNCTION__, chan)); + return MV_BAD_PARAM; + } + if (winNum >= XOR_MAX_OVERRIDE_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + + /* set the enable bit */ + if (enable) + { + MV_REG_BIT_SET(XOR_OVERRIDE_CTRL_REG(chan),XEXAOCR_OVR_EN_MASK(target)); + } + else + { + MV_REG_BIT_RESET(XOR_OVERRIDE_CTRL_REG(chan), + XEXAOCR_OVR_EN_MASK(target)); + } + + /* read the override control register */ + temp = MV_REG_READ(XOR_OVERRIDE_CTRL_REG(chan)); + temp &= ~XEXAOCR_OVR_PTR_MASK(target); + temp |= (winNum << XEXAOCR_OVR_PTR_OFFS(target)); + MV_REG_WRITE(XOR_OVERRIDE_CTRL_REG(chan), temp); + return MV_OK; +} + + diff --git a/board/mv_feroceon/mv_hal/xor/mvXor.h b/board/mv_feroceon/mv_hal/xor/mvXor.h new file mode 100644 index 0000000..1ab3208 --- /dev/null +++ b/board/mv_feroceon/mv_hal/xor/mvXor.h @@ -0,0 +1,230 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvXor.h - Header File for : +* +* DESCRIPTION: +* This file contains Marvell Controller XOR HW library API. +* NOTE: This HW library API assumes XOR source, destination and +* descriptors are cache coherent. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCMVxorh +#define __INCMVxorh + +#include "mvCommon.h" +#include "mvOs.h" +#include "xor/mvXorRegs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* typedefs */ + +/* This enumerator describes the type of functionality the XOR channel */ +/* can have while using the same data structures. */ +typedef enum _mvXorType +{ + MV_XOR, /* XOR channel functions as XOR accelerator */ + MV_DMA, /* XOR channel functions as IDMA channel */ + MV_CRC32 /* XOR channel functions as CRC 32 calculator */ +}MV_XOR_TYPE; + +#if defined(MV_CPU_LE) + /* This structure describes XOR descriptor size 64bytes */ +typedef struct _mvXorDesc +{ + MV_U32 status; /* Successful descriptor execution indication */ + MV_U32 crc32Result; /* Result of CRC-32 calculation */ + MV_U32 descCommand; /* type of operation to be carried out on the data */ + MV_U32 phyNextDescPtr;/* Next descriptor address pointer */ + MV_U32 byteCnt; /* Size of source and destination blocks in bytes */ + MV_U32 phyDestAdd; /* Destination Block address pointer */ + MV_U32 srcAdd0; /* source block #0 address pointer */ + MV_U32 srcAdd1; /* source block #1 address pointer */ + MV_U32 srcAdd2; /* source block #2 address pointer */ + MV_U32 srcAdd3; /* source block #3 address pointer */ + MV_U32 srcAdd4; /* source block #4 address pointer */ + MV_U32 srcAdd5; /* source block #6 address pointer */ + MV_U32 srcAdd6; /* source block #6 address pointer */ + MV_U32 srcAdd7; /* source block #7 address pointer */ + MV_U32 reserved0; + MV_U32 reserved1; +} MV_XOR_DESC; + + +/* XOR descriptor structure for CRC and DMA descriptor */ +typedef struct _mvCrcDmaDesc +{ + MV_U32 status; /* Successful descriptor execution indication */ + MV_U32 crc32Result; /* Result of CRC-32 calculation */ + MV_U32 descCommand; /* type of operation to be carried out on the data */ + MV_U32 nextDescPtr; /* Next descriptor address pointer */ + MV_U32 byteCnt; /* Size of source block part represented by the descriptor */ + MV_U32 destAdd; /* Destination Block address pointer (not used in CRC32 */ + MV_U32 srcAdd0; /* Mode: Source Block address pointer */ + MV_U32 srcAdd1; /* Mode: Source Block address pointer */ +} MV_CRC_DMA_DESC; + +#elif defined(MV_CPU_BE) +/* This structure describes XOR descriptor size 64bytes */ +typedef struct _mvXorDesc +{ + MV_U32 crc32Result; /* Result of CRC-32 calculation */ + MV_U32 status; /* Successful descriptor execution indication */ + MV_U32 phyNextDescPtr; /* Next descriptor address pointer */ + MV_U32 descCommand; /* type of operation to be carried out on the data */ + MV_U32 phyDestAdd; /* Destination Block address pointer */ + MV_U32 byteCnt; /* Size of source and destination blocks in bytes */ + MV_U32 srcAdd1; /* source block #1 address pointer */ + MV_U32 srcAdd0; /* source block #0 address pointer */ + MV_U32 srcAdd3; /* source block #3 address pointer */ + MV_U32 srcAdd2; /* source block #2 address pointer */ + MV_U32 srcAdd5; /* source block #5 address pointer */ + MV_U32 srcAdd4; /* source block #4 address pointer */ + MV_U32 srcAdd7; /* source block #7 address pointer */ + MV_U32 srcAdd6; /* source block #6 address pointer */ + MV_U32 reserved0; + MV_U32 reserved1; +} MV_XOR_DESC; + + +/* XOR descriptor structure for CRC and DMA descriptor */ +typedef struct _mvCrcDmaDesc +{ + MV_U32 crc32Result; /* Result of CRC-32 calculation */ + MV_U32 status; /* Successful descriptor execution indication */ + MV_U32 nextDescPtr; /* Next descriptor address pointer */ + MV_U32 descCommand; /* type of operation to be carried out on the data */ + MV_U32 destAdd; /* Destination Block address pointer (not used in CRC32 */ + MV_U32 byteCnt; /* Size of source block part represented by the descriptor */ + MV_U32 srcAdd1; /* Mode: Source Block address pointer */ + MV_U32 srcAdd0; /* Mode: Source Block address pointer */ +} MV_CRC_DMA_DESC; + +#endif + +typedef struct _mvXorEcc +{ + MV_U32 destPtr; /* Target block pointer to ECC/MemInit operation */ + MV_U32 blockSize; /* Block size in bytes for ECC/MemInit operation */ + MV_BOOL periodicEnable; /* Enable Timer Mode */ + MV_U32 tClkTicks; /* ECC timer mode initial count - down value */ + MV_U32 sectorSize; /* section size for ECC timer mode operation */ +}MV_XOR_ECC; + +typedef enum _mvXorOverrideTarget +{ + SRC_ADDR0, /* Source Address #0 Control */ + SRC_ADDR1, /* Source Address #1 Control */ + SRC_ADDR2, /* Source Address #2 Control */ + SRC_ADDR3, /* Source Address #3 Control */ + SRC_ADDR4, /* Source Address #4 Control */ + SRC_ADDR5, /* Source Address #5 Control */ + SRC_ADDR6, /* Source Address #6 Control */ + SRC_ADDR7, /* Source Address #7 Control */ + XOR_DST_ADDR, /* Destination Address Control */ + XOR_NEXT_DESC /* Next Descriptor Address Control */ + +}MV_XOR_OVERRIDE_TARGET; + +#define XOR_MAX_OVERRIDE_WIN 4 /* Maximum address override windows */ + +#define XOR_OVERRIDE_CTRL_REG(chan) (XOR_UNIT_BASE(XOR_UNIT(chan))+(0x2A0 + ((XOR_CHAN(chan)) * 4))) +/* XOR Engine [0..1] Address Override Control Register (XExAOCR) */ +#define XEXAOCR_OVR_EN_OFFS(target) (3 * target) +#define XEXAOCR_OVR_EN_MASK(target) (1 << (XEXAOCR_OVR_EN_OFFS(target))) +#define XEXAOCR_OVR_PTR_OFFS(target) ((3 * target) + 1) +#define XEXAOCR_OVR_PTR_MASK(target) (3 << (XEXAOCR_OVR_PTR_OFFS(target))) +#define XEXAOCR_OVR_BAR(winNum,target) (winNum << (XEXAOCR_OVR_PTR_OFFS(target))) + +/* for controllers that have two XOR units, then chans 2 & 3 will be mapped*/ +/* to channels 0 & 1 of unit 1 */ +#define XOR_UNIT(chan) ((chan) >> 1) +#define XOR_CHAN(chan) ((chan) & 1) + +MV_VOID mvXorHalInit (MV_U32 xorChanNum); +MV_STATUS mvXorCtrlSet(MV_U32 chan, MV_U32 xorCtrl); +MV_STATUS mvXorEccClean(MV_U32 chan, MV_XOR_ECC *pXorEccConfig); +MV_U32 mvXorEccCurrTimerGet(MV_U32 chan, MV_U32 tClk); +MV_STATUS mvXorMemInit(MV_U32 chan, MV_U32 startPtr, MV_U32 blockSize, + MV_U32 initValHigh, MV_U32 initValLow); +MV_STATUS mvXorTransfer(MV_U32 chan, MV_XOR_TYPE xorType, MV_U32 xorChainPtr); +MV_STATE mvXorStateGet(MV_U32 chan); +MV_STATUS mvXorCommandSet(MV_U32 chan, MV_COMMAND command); +MV_STATUS mvXorOverrideSet(MV_U32 chan, MV_XOR_OVERRIDE_TARGET target, + MV_U32 winNum, MV_BOOL enable); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/mv_feroceon/mv_hal/xor/mvXorRegs.h b/board/mv_feroceon/mv_hal/xor/mvXorRegs.h new file mode 100644 index 0000000..b81f347 --- /dev/null +++ b/board/mv_feroceon/mv_hal/xor/mvXorRegs.h @@ -0,0 +1,225 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvXorSpech +#define __INCmvXorSpech + +#ifdef __cplusplus +extern "C" { +#endif + +/* defines */ + +/* XOR Engine Control Register Map */ +#define XOR_CHANNEL_ARBITER_REG(unit) (XOR_UNIT_BASE(unit)) +#define XOR_CONFIG_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x10 + ((chan) * 4))) +#define XOR_ACTIVATION_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x20 + ((chan) * 4))) + +/* XOR Engine Interrupt Register Map */ +#define XOR_CAUSE_REG(unit) (XOR_UNIT_BASE(unit)+(0x30)) +#define XOR_MASK_REG(unit) (XOR_UNIT_BASE(unit)+(0x40)) +#define XOR_ERROR_CAUSE_REG(unit) (XOR_UNIT_BASE(unit)+(0x50)) +#define XOR_ERROR_ADDR_REG(unit) (XOR_UNIT_BASE(unit)+(0x60)) + +/* XOR Engine Descriptor Register Map */ +#define XOR_NEXT_DESC_PTR_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x200 + ((chan) * 4))) +#define XOR_CURR_DESC_PTR_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x210 + ((chan) * 4))) +#define XOR_BYTE_COUNT_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x220 + ((chan) * 4))) + +/* XOR Engine ECC/MemInit Register Map */ +#define XOR_DST_PTR_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x2B0 + ((chan) * 4))) +#define XOR_BLOCK_SIZE_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x2C0 + ((chan) * 4))) +#define XOR_TIMER_MODE_CTRL_REG(unit) (XOR_UNIT_BASE(unit)+(0x2D0)) +#define XOR_TIMER_MODE_INIT_VAL_REG(unit) (XOR_UNIT_BASE(unit)+(0x2D4)) +#define XOR_TIMER_MODE_CURR_VAL_REG(unit) (XOR_UNIT_BASE(unit)+(0x2D8)) +#define XOR_INIT_VAL_LOW_REG(unit) (XOR_UNIT_BASE(unit)+(0x2E0)) +#define XOR_INIT_VAL_HIGH_REG(unit) (XOR_UNIT_BASE(unit)+(0x2E4)) + +/* XOR Engine Debug Register Map */ +#define XOR_DEBUG_REG(unit) (XOR_UNIT_BASE(unit)+(0x70)) + + +/* XOR register fileds */ + + +/* XOR Engine Channel Arbiter Register */ +#define XECAR_SLICE_OFFS(sliceNum) (sliceNum) +#define XECAR_SLICE_MASK(sliceNum) (1 << (XECAR_SLICE_OFFS(sliceNum))) + +/* XOR Engine [0..1] Configuration Registers (XExCR) */ +#define XEXCR_OPERATION_MODE_OFFS (0) +#define XEXCR_OPERATION_MODE_MASK (7 << XEXCR_OPERATION_MODE_OFFS) +#define XEXCR_OPERATION_MODE_XOR (0 << XEXCR_OPERATION_MODE_OFFS) +#define XEXCR_OPERATION_MODE_CRC (1 << XEXCR_OPERATION_MODE_OFFS) +#define XEXCR_OPERATION_MODE_DMA (2 << XEXCR_OPERATION_MODE_OFFS) +#define XEXCR_OPERATION_MODE_ECC (3 << XEXCR_OPERATION_MODE_OFFS) +#define XEXCR_OPERATION_MODE_MEM_INIT (4 << XEXCR_OPERATION_MODE_OFFS) + +#define XEXCR_SRC_BURST_LIMIT_OFFS (4) +#define XEXCR_SRC_BURST_LIMIT_MASK (7 << XEXCR_SRC_BURST_LIMIT_OFFS) +#define XEXCR_DST_BURST_LIMIT_OFFS (8) +#define XEXCR_DST_BURST_LIMIT_MASK (7 << XEXCR_DST_BURST_LIMIT_OFFS) +#define XEXCR_DRD_RES_SWP_OFFS (12) +#define XEXCR_DRD_RES_SWP_MASK (1 << XEXCR_DRD_RES_SWP_OFFS) +#define XEXCR_DWR_REQ_SWP_OFFS (13) +#define XEXCR_DWR_REQ_SWP_MASK (1 << XEXCR_DWR_REQ_SWP_OFFS) +#define XEXCR_DES_SWP_OFFS (14) +#define XEXCR_DES_SWP_MASK (1 << XEXCR_DES_SWP_OFFS) +#define XEXCR_REG_ACC_PROTECT_OFFS (15) +#define XEXCR_REG_ACC_PROTECT_MASK (1 << XEXCR_REG_ACC_PROTECT_OFFS) + + +/* XOR Engine [0..1] Activation Registers (XExACTR) */ +#define XEXACTR_XESTART_OFFS (0) +#define XEXACTR_XESTART_MASK (1 << XEXACTR_XESTART_OFFS) +#define XEXACTR_XESTOP_OFFS (1) +#define XEXACTR_XESTOP_MASK (1 << XEXACTR_XESTOP_OFFS) +#define XEXACTR_XEPAUSE_OFFS (2) +#define XEXACTR_XEPAUSE_MASK (1 << XEXACTR_XEPAUSE_OFFS) +#define XEXACTR_XERESTART_OFFS (3) +#define XEXACTR_XERESTART_MASK (1 << XEXACTR_XERESTART_OFFS) +#define XEXACTR_XESTATUS_OFFS (4) +#define XEXACTR_XESTATUS_MASK (3 << XEXACTR_XESTATUS_OFFS) +#define XEXACTR_XESTATUS_IDLE (0 << XEXACTR_XESTATUS_OFFS) +#define XEXACTR_XESTATUS_ACTIVE (1 << XEXACTR_XESTATUS_OFFS) +#define XEXACTR_XESTATUS_PAUSED (2 << XEXACTR_XESTATUS_OFFS) + +/* XOR Engine Interrupt Cause Register (XEICR) */ +#define XEICR_CHAN_OFFS 16 +#define XEICR_CAUSE_OFFS(chan) (chan * XEICR_CHAN_OFFS) +#define XEICR_CAUSE_MASK(chan, cause) (1 << (cause + XEICR_CAUSE_OFFS(chan))) +#define XEICR_COMP_MASK_ALL 0x000f000f +#define XEICR_COMP_MASK(chan) (0x000f << XEICR_CAUSE_OFFS(chan)) +#define XEICR_ERR_MASK 0x03800380 + +/* XOR Engine Error Cause Register (XEECR) */ +#define XEECR_ERR_TYPE_OFFS 0 +#define XEECR_ERR_TYPE_MASK (0x1f << XEECR_ERR_TYPE_OFFS) + +/* XOR Engine Error Address Register (XEEAR) */ +#define XEEAR_ERR_ADDR_OFFS (0) +#define XEEAR_ERR_ADDR_MASK (0xFFFFFFFF << XEEAR_ERR_ADDR_OFFS) + +/* XOR Engine [0..1] Next Descriptor Pointer Register (XExNDPR) */ +#define XEXNDPR_NEXT_DESC_PTR_OFFS (0) +#define XEXNDPR_NEXT_DESC_PTR_MASK (0xFFFFFFFF << XEXNDPR_NEXT_DESC_PTR_OFFS) + +/* XOR Engine [0..1] Current Descriptor Pointer Register (XExCDPR) */ +#define XEXCDPR_CURRENT_DESC_PTR_OFFS (0) +#define XEXCDPR_CURRENT_DESC_PTR_MASK (0xFFFFFFFF << XEXCDPR_CURRENT_DESC_PTR_OFFS) + +/* XOR Engine [0..1] Byte Count Register (XExBCR) */ +#define XEXBCR_BYTE_CNT_OFFS (0) +#define XEXBCR_BYTE_CNT_MASK (0xFFFFFFFF << XEXBCR_BYTE_CNT_OFFS) + +/* XOR Engine [0..1] Destination Pointer Register (XExDPR0) */ +#define XEXDPR_DST_PTR_OFFS (0) +#define XEXDPR_DST_PTR_MASK (0xFFFFFFFF << XEXDPR_DST_PTR_OFFS) +#define XEXDPR_DST_PTR_XOR_MASK (0x3F) +#define XEXDPR_DST_PTR_DMA_MASK (0x1F) +#define XEXDPR_DST_PTR_CRC_MASK (0x1F) + +/* XOR Engine[0..1] Block Size Registers (XExBSR) */ +#define XEXBSR_BLOCK_SIZE_OFFS (0) +#define XEXBSR_BLOCK_SIZE_MASK (0xFFFFFFFF << XEXBSR_BLOCK_SIZE_OFFS) +#define XEXBSR_BLOCK_SIZE_MIN_VALUE (128) +#define XEXBSR_BLOCK_SIZE_MAX_VALUE (0xFFFFFFFF) + +/* XOR Engine Timer Mode Control Register (XETMCR) */ +#define XETMCR_TIMER_EN_OFFS (0) +#define XETMCR_TIMER_EN_MASK (1 << XETMCR_TIMER_EN_OFFS) +#define XETMCR_TIMER_EN_ENABLE (1 << XETMCR_TIMER_EN_OFFS) +#define XETMCR_TIMER_EN_DISABLE (0 << XETMCR_TIMER_EN_OFFS) +#define XETMCR_SECTION_SIZE_CTRL_OFFS (8) +#define XETMCR_SECTION_SIZE_CTRL_MASK (0x1F << XETMCR_SECTION_SIZE_CTRL_OFFS) +#define XETMCR_SECTION_SIZE_MIN_VALUE (7) +#define XETMCR_SECTION_SIZE_MAX_VALUE (31) + +/* XOR Engine Timer Mode Initial Value Register (XETMIVR) */ +#define XETMIVR_TIMER_INIT_VAL_OFFS (0) +#define XETMIVR_TIMER_INIT_VAL_MASK (0xFFFFFFFF << XETMIVR_TIMER_INIT_VAL_OFFS) + +/* XOR Engine Timer Mode Current Value Register (XETMCVR) */ +#define XETMCVR_TIMER_CRNT_VAL_OFFS (0) +#define XETMCVR_TIMER_CRNT_VAL_MASK (0xFFFFFFFF << XETMCVR_TIMER_CRNT_VAL_OFFS) + +/* XOR Engine Initial Value Register Low (XEIVRL) */ +#define XEIVRL_INIT_VAL_L_OFFS (0) +#define XEIVRL_INIT_VAL_L_MASK (0xFFFFFFFF << XEIVRL_INIT_VAL_L_OFFS) + +/* XOR Engine Initial Value Register High (XEIVRH) */ +#define XEIVRH_INIT_VAL_H_OFFS (0) +#define XEIVRH_INIT_VAL_H_MASK (0xFFFFFFFF << XEIVRH_INIT_VAL_H_OFFS) + +/* XOR Engine Debug Register (XEDBR) */ +#define XEDBR_PARITY_ERR_INSR_OFFS (0) +#define XEDBR_PARITY_ERR_INSR_MASK (1 << XEDBR_PARITY_ERR_INSR_OFFS) +#define XEDBR_XBAR_ERR_INSR_OFFS (1) +#define XEDBR_XBAR_ERR_INSR_MASK (1 << XEDBR_XBAR_ERR_INSR_OFFS) + + +#ifdef __cplusplus +} +#endif + +#endif /* __INCmvXorSpech */ diff --git a/board/mv_feroceon/mv_kw/bootstrap_def.h b/board/mv_feroceon/mv_kw/bootstrap_def.h new file mode 100644 index 0000000..cacd288 --- /dev/null +++ b/board/mv_feroceon/mv_kw/bootstrap_def.h @@ -0,0 +1,121 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _INC_BOOTSTRAP__DEF_H +#define _INC_BOOTSTRAP__DEF_H + +#ifndef MV_ASMLANGUAGE + +typedef struct BHR_t +{ +// type name byte order + MV_U8 blockID; //0 + MV_U8 rsvd0; //1 + MV_U16 nandPageSize; //2-3 + MV_U32 blockSize; //4-7 + MV_U32 rsvd1; //8-11 + MV_U32 sourceAddr; //12-15 + MV_U32 destinationAddr; //16-19 + MV_U32 executionAddr; //20-23 + MV_U8 sataPioMode; //24 + MV_U8 rsvd3; //25 + MV_U16 ddrInitDelay; //26-27 + MV_U16 rsvd2; //28-29 + MV_U8 ext; //30 + MV_U8 checkSum; //31 +} BHR_t, * pBHR_t; + + +typedef struct ExtBHR_t +{ +// type name byte order + MV_U32 dramRegsOffs; //0-3 + MV_U32 rsrvd1; //4-7 + MV_U32 rsrvd2; //8-11 + MV_U32 rsrvd3; //12-15 + MV_U32 rsrvd4; //16-19 + MV_U32 rsrvd5; //20-23 + MV_U32 rsrvd6; //24-27 + MV_U16 rsrvd7; //28-29 + MV_U8 rsrvd8; //30 + MV_U8 checkSum; //31 +}ExtBHR_t, *pExtBHR_t; + +#define BOOTROM_SIZE (12 * 1024) +#define HEADER_SIZE 512 +#define BHR_HDR_SIZE 0x20 +#define EXT_HEADER_SIZE (HEADER_SIZE - BHR_HDR_SIZE) + +/* Boot Type - block ID */ +#define IBR_HDR_I2C_ID 0x4D +#define IBR_HDR_SPI_ID 0x5A +#define IBR_HDR_NAND_ID 0x8B +#define IBR_HDR_SATA_ID 0x78 +#define IBR_HDR_PEX_ID 0x9C +#define IBR_HDR_UART_ID 0x69 +#define IBR_DEF_ATTRIB 0x00 + +#endif /* MV_ASMLANGUAGE */ +#endif /* _INC_BOOTSTRAP_H */ + diff --git a/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.c b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.c new file mode 100644 index 0000000..1d8c80a --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.c @@ -0,0 +1,2470 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "cpu/mvCpu.h" +#include "cntmr/mvCntmr.h" +#include "gpp/mvGpp.h" +#include "twsi/mvTwsi.h" +#include "pex/mvPex.h" +#include "device/mvDevice.h" +#include "ethswitch/mvSwitch.h" +#include "ethswitch/mvSwitchRegs.h" +#include "eth-phy/mvEthPhy.h" + +/* defines */ +/* #define MV_DEBUG */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +extern MV_CPU_ARM_CLK _cpuARMDDRCLK[]; + +#define CODE_IN_ROM MV_FALSE +#define CODE_IN_RAM MV_TRUE + +extern MV_BOARD_INFO* boardInfoTbl[]; +#define BOARD_INFO(boardId) boardInfoTbl[boardId - BOARD_ID_BASE] + +/* Locals */ +static MV_DEV_CS_INFO* boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); + +MV_U32 tClkRate = -1; + + +/******************************************************************************* +* mvBoardEnvInit - Init board +* +* DESCRIPTION: +* In this function the board environment take care of device bank +* initialization. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardEnvInit(MV_VOID) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardEnvInit:Board unknown.\n"); + return; + + } + + /* Set GPP Out value */ + MV_REG_WRITE(GPP_DATA_OUT_REG(0), BOARD_INFO(boardId)->gppOutValLow); + MV_REG_WRITE(GPP_DATA_OUT_REG(1), BOARD_INFO(boardId)->gppOutValHigh); + + /* set GPP polarity */ + mvGppPolaritySet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValLow); + mvGppPolaritySet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValHigh); + + /* Workaround for Erratum FE-MISC-70*/ + if(mvCtrlRevGet()==0x2) + { + BOARD_INFO(boardId)->gppOutEnValLow &= 0xfffffffd; + BOARD_INFO(boardId)->gppOutEnValLow |= (BOARD_INFO(boardId)->gppOutEnValHigh) & 0x00000002; + } /*End of WA*/ + + /* Set GPP Out Enable*/ + mvGppTypeSet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValLow); + mvGppTypeSet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValHigh); + + /* Nand CE */ + MV_REG_BIT_SET(NAND_CTRL_REG, NAND_ACTCEBOOT_BIT); +} + +/******************************************************************************* +* mvBoardModelGet - Get Board model +* +* DESCRIPTION: +* This function returns 16bit describing board model. +* Board model is constructed of one byte major and minor numbers in the +* following manner: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* String describing board model. +* +*******************************************************************************/ +MV_U16 mvBoardModelGet(MV_VOID) +{ + return (mvBoardIdGet() >> 16); +} + +/******************************************************************************* +* mbBoardRevlGet - Get Board revision +* +* DESCRIPTION: +* This function returns a 32bit describing the board revision. +* Board revision is constructed of 4bytes. 2bytes describes major number +* and the other 2bytes describes minor munber. +* For example for board revision 3.4 the function will return +* 0x00030004. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* String describing board model. +* +*******************************************************************************/ +MV_U16 mvBoardRevGet(MV_VOID) +{ + return (mvBoardIdGet() & 0xFFFF); +} + +/******************************************************************************* +* mvBoardNameGet - Get Board name +* +* DESCRIPTION: +* This function returns a string describing the board model and revision. +* String is extracted from board I2C EEPROM. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain board name string. Minimum size 32 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ +MV_STATUS mvBoardNameGet(char *pNameBuff) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsSPrintf (pNameBuff, "Board unknown.\n"); + return MV_ERROR; + + } + + mvOsSPrintf (pNameBuff, "%s",BOARD_INFO(boardId)->boardName); + + return MV_OK; +} + +/******************************************************************************* +* mvBoardIsPortInSgmii - +* +* DESCRIPTION: +* This routine returns MV_TRUE for port number works in SGMII or MV_FALSE +* For all other options. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - port in SGMII. +* MV_FALSE - other. +* +*******************************************************************************/ +MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum) +{ + MV_BOOL ethPortSgmiiSupport[BOARD_ETH_PORT_NUM] = MV_ETH_PORT_SGMII; + + if(ethPortNum >= BOARD_ETH_PORT_NUM) + { + mvOsPrintf ("Invalid portNo=%d\n", ethPortNum); + return MV_FALSE; + } + return ethPortSgmiiSupport[ethPortNum]; +} + +/******************************************************************************* +* mvBoardIsPortInGmii - +* +* DESCRIPTION: +* This routine returns MV_TRUE for port number works in GMII or MV_FALSE +* For all other options. +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - port in GMII. +* MV_FALSE - other. +* +*******************************************************************************/ +MV_BOOL mvBoardIsPortInGmii(MV_VOID) +{ + MV_U32 devClassId, devClass = 0; + if (mvBoardMppGroupTypeGet(devClass) == MV_BOARD_AUTO) + { + /* Get MPP module ID */ + devClassId = mvBoarModuleTypeGet(devClass); + if (MV_BOARD_MODULE_GMII_ID == devClassId) + return MV_TRUE; + } + else if (mvBoardMppGroupTypeGet(devClass) == MV_BOARD_GMII) + return MV_TRUE; + + return MV_FALSE; +} +/******************************************************************************* +* mvBoardPhyAddrGet - Get the phy address +* +* DESCRIPTION: +* This routine returns the Phy address of a given ethernet port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing Phy address, -1 if the port number is wrong. +* +*******************************************************************************/ +MV_32 mvBoardPhyAddrGet(MV_U32 ethPortNum) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardPhyAddrGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardEthSmiAddr; +} + +/******************************************************************************* +* mvBoardMacSpeedGet - Get the Mac speed +* +* DESCRIPTION: +* This routine returns the Mac speed if pre define of a given ethernet port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BOARD_MAC_SPEED, -1 if the port number is wrong. +* +*******************************************************************************/ +MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardMacSpeedGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardMacSpeed; +} + +/******************************************************************************* +* mvBoardLinkStatusIrqGet - Get the IRQ number for the link status indication +* +* DESCRIPTION: +* This routine returns the IRQ number for the link status indication. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* the number of the IRQ for the link status indication, -1 if the port +* number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardLinkStatusIrqGet(MV_U32 ethPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardLinkStatusIrqGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].linkStatusIrq; +} + +/******************************************************************************* +* mvBoardSwitchPortGet - Get the mapping between the board connector and the +* Ethernet Switch port +* +* DESCRIPTION: +* This routine returns the matching Switch port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* boardPortNum - logical number of the connector on the board +* +* OUTPUT: +* None. +* +* RETURN: +* the matching Switch port, -1 if the port number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardSwitchPortGet(MV_U32 ethPortNum, MV_U8 boardPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardSwitchPortGet: Board unknown.\n"); + return MV_ERROR; + } + if (boardPortNum >= BOARD_ETH_SWITCH_PORT_NUM) + { + mvOsPrintf("mvBoardSwitchPortGet: Illegal board port number.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].qdPort[boardPortNum]; +} + +/******************************************************************************* +* mvBoardSwitchCpuPortGet - Get the the Ethernet Switch CPU port +* +* DESCRIPTION: +* This routine returns the Switch CPU port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* the Switch CPU port, -1 if the port number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardSwitchCpuPortGet(MV_U32 ethPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardSwitchCpuPortGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].qdCpuPort; +} + +/******************************************************************************* +* mvBoardIsSwitchConnected - Get switch connection status +* DESCRIPTION: +* This routine returns port's connection status +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* 1 - if ethPortNum is connected to switch, 0 otherwise +* +*******************************************************************************/ +MV_32 mvBoardIsSwitchConnected(MV_U32 ethPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardIsSwitchConnected: Board unknown.\n"); + return MV_ERROR; + } + + if(ethPortNum >= BOARD_INFO(boardId)->numBoardMacInfo) + { + mvOsPrintf("mvBoardIsSwitchConnected: Illegal port number(%u)\n", ethPortNum); + return MV_ERROR; + } + + if((MV_32)(BOARD_INFO(boardId)->pSwitchInfo)) + return (MV_32)(BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].switchOnPort == ethPortNum); + else + return 0; +} +/******************************************************************************* +* mvBoardSmiScanModeGet - Get Switch SMI scan mode +* +* DESCRIPTION: +* This routine returns Switch SMI scan mode. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* 1 for SMI_MANUAL_MODE, -1 if the port number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardSmiScanModeGet(MV_U32 ethPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardSmiScanModeGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].smiScanMode; +} +/******************************************************************************* +* mvBoardSpecInitGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: Return MV_TRUE and parameters in case board need spesific phy init, +* otherwise return MV_FALSE. +* +* +*******************************************************************************/ + +MV_BOOL mvBoardSpecInitGet(MV_U32* regOff, MV_U32* data) +{ + return MV_FALSE; +} + +/******************************************************************************* +* mvBoardTclkGet - Get the board Tclk (Controller clock) +* +* DESCRIPTION: +* This routine extract the controller core clock. +* This function uses the controller counters to make identification. +* Note: In order to avoid interference, make sure task context switch +* and interrupts will not occure during this function operation +* +* INPUT: +* countNum - Counter number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +MV_U32 mvBoardTclkGet(MV_VOID) +{ +#if defined(TCLK_AUTO_DETECT) + MV_U32 tmpTClkRate = MV_BOARD_TCLK_166MHZ; + + tmpTClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET); + tmpTClkRate &= MSAR_TCLCK_MASK; + + switch (tmpTClkRate) + { + case MSAR_TCLCK_166: + tmpTClkRate = MV_BOARD_TCLK_166MHZ; + break; + case MSAR_TCLCK_200: + tmpTClkRate = MV_BOARD_TCLK_200MHZ; + break; + } + return tmpTClkRate; +#else + if(mvCtrlModelGet()==MV_6281_DEV_ID) + return MV_BOARD_TCLK_200MHZ; + else + return MV_BOARD_TCLK_166MHZ; +#endif + +} +/******************************************************************************* +* mvBoardSysClkGet - Get the board SysClk (CPU bus clock) +* +* DESCRIPTION: +* This routine extract the CPU bus clock. +* +* INPUT: +* countNum - Counter number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +static MV_U32 mvBoard6180SysClkGet(MV_VOID) +{ + MV_U32 sysClkRate=0; + MV_CPU_ARM_CLK _cpu6180_ddr_l2_CLK[] = MV_CPU6180_DDR_L2_CLCK_TBL; + + sysClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET); + sysClkRate = sysClkRate & MSAR_CPUCLCK_MASK_6180; + sysClkRate = sysClkRate >> MSAR_CPUCLCK_OFFS_6180; + + sysClkRate = _cpu6180_ddr_l2_CLK[sysClkRate].ddrClk; + + return sysClkRate; + +} + +MV_U32 mvBoardSysClkGet(MV_VOID) +{ +#ifdef SYSCLK_AUTO_DETECT + MV_U32 sysClkRate, tmp, pClkRate, indexDdrRtio; + MV_U32 cpuCLK[] = MV_CPU_CLCK_TBL; + MV_U32 ddrRtio[][2] = MV_DDR_CLCK_RTIO_TBL; + + if(mvCtrlModelGet() == MV_6180_DEV_ID) + return mvBoard6180SysClkGet(); + + tmp = MV_REG_READ(MPP_SAMPLE_AT_RESET); + pClkRate = MSAR_CPUCLCK_EXTRACT(tmp); + pClkRate = cpuCLK[pClkRate]; + + indexDdrRtio = tmp & MSAR_DDRCLCK_RTIO_MASK; + indexDdrRtio = indexDdrRtio >> MSAR_DDRCLCK_RTIO_OFFS; + + sysClkRate = ((pClkRate * ddrRtio[indexDdrRtio][1]) / ddrRtio[indexDdrRtio][0]); + + return sysClkRate; +#else + return MV_BOARD_DEFAULT_SYSCLK; +#endif +} + + +/******************************************************************************* +* mvBoardPexBridgeIntPinGet - Get PEX to PCI bridge interrupt pin number +* +* DESCRIPTION: +* Multi-ported PCI Express bridges that is implemented on the board +* collapse interrupts across multiple conventional PCI/PCI-X buses. +* A dual-headed PCI Express bridge would map (or "swizzle") the +* interrupts per the following table (in accordance with the respective +* logical PCI/PCI-X bridge's Device Number), collapse the INTA#-INTD# +* signals from its two logical PCI/PCI-X bridges, collapse the +* INTA#-INTD# signals from any internal sources, and convert the +* signals to in-band PCI Express messages. 10 +* This function returns the upstream interrupt as it was converted by +* the bridge, according to board configuration and the following table: +* PCI dev num +* Interrupt pin 7, 8, 9 +* A -> A D C +* B -> B A D +* C -> C B A +* D -> D C B +* +* +* INPUT: +* devNum - PCI/PCIX device number. +* intPin - PCI Int pin +* +* OUTPUT: +* None. +* +* RETURN: +* Int pin connected to the Interrupt controller +* +*******************************************************************************/ +MV_U32 mvBoardPexBridgeIntPinGet(MV_U32 devNum, MV_U32 intPin) +{ + MV_U32 realIntPin = ((intPin + (3 - (devNum % 4))) %4 ); + + if (realIntPin == 0) return 4; + else return realIntPin; + +} + +/******************************************************************************* +* mvBoardDebugLedNumGet - Get number of debug Leds +* +* DESCRIPTION: +* INPUT: +* boardId +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_U32 mvBoardDebugLedNumGet(MV_U32 boardId) +{ + return BOARD_INFO(boardId)->activeLedsNumber; +} + +/******************************************************************************* +* mvBoardDebugLeg - Set the board debug Leds +* +* DESCRIPTION: turn on/off status leds. +* Note: assume MPP leds are part of group 0 only. +* +* INPUT: +* hexNum - Number to be displied in hex by Leds. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardDebugLed(MV_U32 hexNum) +{ + MV_U32 val = 0,totalMask, currentBitMask = 1,i; + MV_U32 boardId= mvBoardIdGet(); + + totalMask = (1 << BOARD_INFO(boardId)->activeLedsNumber) -1; + hexNum &= totalMask; + totalMask = 0; + + for (i = 0 ; i < BOARD_INFO(boardId)->activeLedsNumber ; i++) + { + if (hexNum & currentBitMask) + { + val |= (1 << BOARD_INFO(boardId)->pLedGppPin[i]); + } + + totalMask |= (1 << BOARD_INFO(boardId)->pLedGppPin[i]); + + currentBitMask = (currentBitMask << 1); + } + + if (BOARD_INFO(boardId)->ledsPolarity) + { + mvGppValueSet(0, totalMask, val); + } + else + { + mvGppValueSet(0, totalMask, ~val); + } +} + + +/******************************************************************************* +* mvBoarGpioPinGet - mvBoarGpioPinGet +* +* DESCRIPTION: +* +* INPUT: +* class - MV_BOARD_GPP_CLASS enum. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoarGpioPinNumGet(MV_BOARD_GPP_CLASS class, MV_U32 index) +{ + MV_U32 boardId, i; + MV_U32 indexFound = 0; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardRTCGpioPinGet:Board unknown.\n"); + return MV_ERROR; + + } + + for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) + if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == class) { + if (indexFound == index) + return (MV_U32)BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum; + else + indexFound++; + + } + + return MV_ERROR; +} + + +/******************************************************************************* +* mvBoardRTCGpioPinGet - mvBoardRTCGpioPinGet +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardRTCGpioPinGet(MV_VOID) +{ + return mvBoarGpioPinNumGet(BOARD_GPP_RTC, 0); +} + + +/******************************************************************************* +* mvBoardReset - mvBoardReset +* +* DESCRIPTION: +* Reset the board +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None +* +*******************************************************************************/ +MV_VOID mvBoardReset(MV_VOID) +{ + MV_32 resetPin; + + /* Get gpp reset pin if define */ + resetPin = mvBoardResetGpioPinGet(); + if (resetPin != MV_ERROR) + { + MV_REG_BIT_RESET( GPP_DATA_OUT_REG(0) ,(1 << resetPin)); + MV_REG_BIT_RESET( GPP_DATA_OUT_EN_REG(0) ,(1 << resetPin)); + + } + else + { + /* No gpp reset pin was found, try to reset ussing + system reset out */ + MV_REG_BIT_SET( CPU_RSTOUTN_MASK_REG , BIT2); + MV_REG_BIT_SET( CPU_SYS_SOFT_RST_REG , BIT0); + } + + while(1); +} + +/******************************************************************************* +* mvBoardResetGpioPinGet - mvBoardResetGpioPinGet +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardResetGpioPinGet(MV_VOID) +{ + return mvBoarGpioPinNumGet(BOARD_GPP_RESET, 0); +} +/******************************************************************************* +* mvBoardSDIOGpioPinGet - mvBoardSDIOGpioPinGet +* +* DESCRIPTION: +* used for hotswap detection +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardSDIOGpioPinGet(MV_VOID) +{ + return mvBoarGpioPinNumGet(BOARD_GPP_SDIO_DETECT, 0); +} + +/******************************************************************************* +* mvBoardUSBVbusGpioPinGet - return Vbus input GPP +* +* DESCRIPTION: +* +* INPUT: +* int devNo. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardUSBVbusGpioPinGet(MV_32 devId) +{ + return mvBoarGpioPinNumGet(BOARD_GPP_USB_VBUS, devId); +} + +/******************************************************************************* +* mvBoardUSBVbusEnGpioPinGet - return Vbus Enable output GPP +* +* DESCRIPTION: +* +* INPUT: +* int devNo. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardUSBVbusEnGpioPinGet(MV_32 devId) +{ + return mvBoarGpioPinNumGet(BOARD_GPP_USB_VBUS_EN, devId); +} + + +/******************************************************************************* +* mvBoardGpioIntMaskGet - Get GPIO mask for interrupt pins +* +* DESCRIPTION: +* This function returns a 32-bit mask of GPP pins that connected to +* interrupt generating sources on board. +* For example if UART channel A is hardwired to GPP pin 8 and +* UART channel B is hardwired to GPP pin 4 the fuinction will return +* the value 0x000000110 +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* See description. The function return -1 if board is not identified. +* +*******************************************************************************/ +MV_32 mvBoardGpioIntMaskLowGet(MV_VOID) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardGpioIntMaskGet:Board unknown.\n"); + return MV_ERROR; + + } + + return BOARD_INFO(boardId)->intsGppMaskLow; +} +MV_32 mvBoardGpioIntMaskHighGet(MV_VOID) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardGpioIntMaskGet:Board unknown.\n"); + return MV_ERROR; + + } + + return BOARD_INFO(boardId)->intsGppMaskHigh; +} + + +/******************************************************************************* +* mvBoardMppGet - Get board dependent MPP register value +* +* DESCRIPTION: +* MPP settings are derived from board design. +* MPP group consist of 8 MPPs. An MPP group represent MPP +* control register. +* This function retrieves board dependend MPP register value. +* +* INPUT: +* mppGroupNum - MPP group number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit value describing MPP control register value. +* +*******************************************************************************/ +MV_32 mvBoardMppGet(MV_U32 mppGroupNum) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardMppGet:Board unknown.\n"); + return MV_ERROR; + + } + + return BOARD_INFO(boardId)->pBoardMppConfigValue[0].mppGroup[mppGroupNum]; +} + + +/******************************************************************************* +* mvBoardMppGroupId - If MPP group type is AUTO then identify it using twsi +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvBoardMppGroupIdUpdate(MV_VOID) +{ + + MV_BOARD_MPP_GROUP_CLASS devClass; + MV_BOARD_MODULE_ID_CLASS devClassId; + MV_BOARD_MPP_TYPE_CLASS mppGroupType; + MV_U32 devId; + MV_U32 maxMppGrp = 1; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + maxMppGrp = MV_6281_MPP_MAX_MODULE; + break; + case MV_6192_DEV_ID: + maxMppGrp = MV_6192_MPP_MAX_MODULE; + break; + case MV_6190_DEV_ID: + maxMppGrp = MV_6190_MPP_MAX_MODULE; + break; + case MV_6180_DEV_ID: + maxMppGrp = MV_6180_MPP_MAX_MODULE; + break; + } + + for (devClass = 0; devClass < maxMppGrp; devClass++) + { + /* If MPP group can be defined by the module connected to it */ + if (mvBoardMppGroupTypeGet(devClass) == MV_BOARD_AUTO) + { + /* Get MPP module ID */ + devClassId = mvBoarModuleTypeGet(devClass); + if (MV_ERROR != devClassId) + { + switch(devClassId) + { + case MV_BOARD_MODULE_TDM_ID: + mppGroupType = MV_BOARD_TDM; + break; + case MV_BOARD_MODULE_AUDIO_ID: + mppGroupType = MV_BOARD_AUDIO; + break; + case MV_BOARD_MODULE_RGMII_ID: + mppGroupType = MV_BOARD_RGMII; + break; + case MV_BOARD_MODULE_GMII_ID: + mppGroupType = MV_BOARD_GMII; + break; + case MV_BOARD_MODULE_TS_ID: + mppGroupType = MV_BOARD_TS; + break; + default: + mppGroupType = MV_BOARD_OTHER; + break; + } + } + else + /* The module bay is empty */ + mppGroupType = MV_BOARD_OTHER; + + /* Update MPP group type */ + mvBoardMppGroupTypeSet(devClass, mppGroupType); + } + + /* Update MPP output voltage for RGMII 1.8V */ + MV_REG_BIT_SET(MPP_OUTPUT_DRIVE_REG,MPP_1_8_RGMII0_OUTPUT_DRIVE); + if ((mvBoardMppGroupTypeGet(devClass) == MV_BOARD_RGMII) || + (mvBoardMppGroupTypeGet(devClass) == MV_BOARD_GMII)) + MV_REG_BIT_SET(MPP_OUTPUT_DRIVE_REG,MPP_1_8_RGMII1_OUTPUT_DRIVE); + } +} + +/******************************************************************************* +* mvBoardMppGroupTypeGet +* +* DESCRIPTION: +* +* INPUT: +* mppGroupClass - MPP group number 0 for MPP[35:20] or 1 for MPP[49:36]. +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_BOARD_MPP_TYPE_CLASS mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardMppGet:Board unknown.\n"); + return MV_ERROR; + + } + + if (mppGroupClass == MV_BOARD_MPP_GROUP_1) + return BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup1; + else + return BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup2; +} + +/******************************************************************************* +* mvBoardMppGroupTypeSet +* +* DESCRIPTION: +* +* INPUT: +* mppGroupClass - MPP group number 0 for MPP[35:20] or 1 for MPP[49:36]. +* mppGroupType - MPP group type for MPP[35:20] or for MPP[49:36]. +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvBoardMppGroupTypeSet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass, + MV_BOARD_MPP_TYPE_CLASS mppGroupType) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardMppGet:Board unknown.\n"); + } + + if (mppGroupClass == MV_BOARD_MPP_GROUP_1) + BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup1 = mppGroupType; + else + BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup2 = mppGroupType; + +} + +/******************************************************************************* +* mvBoardMppMuxSet - Update MPP mux +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvBoardMppMuxSet(MV_VOID) +{ + + MV_BOARD_MPP_GROUP_CLASS devClass; + MV_BOARD_MPP_TYPE_CLASS mppGroupType; + MV_U32 devId; + MV_U8 muxVal = 0; + MV_U32 maxMppGrp = 1; + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + maxMppGrp = MV_6281_MPP_MAX_MODULE; + break; + case MV_6192_DEV_ID: + maxMppGrp = MV_6192_MPP_MAX_MODULE; + break; + case MV_6190_DEV_ID: + maxMppGrp = MV_6190_MPP_MAX_MODULE; + break; + case MV_6180_DEV_ID: + maxMppGrp = MV_6180_MPP_MAX_MODULE; + break; + } + + for (devClass = 0; devClass < maxMppGrp; devClass++) + { + mppGroupType = mvBoardMppGroupTypeGet(devClass); + + switch(mppGroupType) + { + case MV_BOARD_TDM: + muxVal &= ~(devClass ? (0x2 << (devClass * 2)):0); + break; + case MV_BOARD_AUDIO: + muxVal &= ~(devClass ? 0xd : 0); + break; + case MV_BOARD_TS: + muxVal &= ~(devClass ? (0x1 << (devClass * 2)):0); + break; + default: + muxVal |= (devClass ? 0xf : 0); + break; + } + } + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + DB(mvOsPrintf("Board: twsi exp set\n")); + twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(MV_BOARD_MUX_I2C_ADDR_ENTRY); + twsiSlave.slaveAddr.type = mvBoardTwsiExpAddrTypeGet(MV_BOARD_MUX_I2C_ADDR_ENTRY); + twsiSlave.validOffset = MV_TRUE; + /* Offset is the first command after the address which indicate the register number to be read + in next operation */ + twsiSlave.offset = 2; + twsiSlave.moreThen256 = MV_FALSE; + + + + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) ) + { + DB(mvOsPrintf("Board: twsi exp out val fail\n")); + return; + } + DB(mvOsPrintf("Board: twsi exp out val succeded\n")); + + /* Change twsi exp to output */ + twsiSlave.offset = 6; + muxVal = 0; + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) ) + { + DB(mvOsPrintf("Board: twsi exp change to out fail\n")); + return; + } + DB(mvOsPrintf("Board: twsi exp change to out succeded\n")); + +} + +/******************************************************************************* +* mvBoardTdmLifeLineSet - set life line control on TDM module +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvBoardTdmLifeLineSet(MV_VOID) +{ + + MV_BOARD_MPP_GROUP_CLASS devClass; + MV_BOARD_MPP_TYPE_CLASS mppGroupType; + MV_U32 devId; + MV_U8 muxVal = 1; + MV_U8 muxValMask = 1; + MV_U8 twsiVal; + MV_U32 maxMppGrp = 1; + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + maxMppGrp = MV_6281_MPP_MAX_MODULE; + break; + case MV_6192_DEV_ID: + maxMppGrp = MV_6192_MPP_MAX_MODULE; + break; + case MV_6190_DEV_ID: + maxMppGrp = MV_6190_MPP_MAX_MODULE; + break; + case MV_6180_DEV_ID: + maxMppGrp = MV_6180_MPP_MAX_MODULE; + break; + } + + for (devClass = 0; devClass < maxMppGrp; devClass++) + { + mppGroupType = mvBoardMppGroupTypeGet(devClass); + if(mppGroupType == MV_BOARD_TDM) + break; + } + + if(devClass == maxMppGrp) + return; /* TDM module not found */ + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + DB(mvOsPrintf("Board: twsi exp set\n")); + twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(0); + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + /* Offset is the first command after the address which indicate the register number to be read + in next operation */ + twsiSlave.offset = 3; + twsiSlave.moreThen256 = MV_FALSE; + + if(mvBoardIdGet() == RD_88F6281A_ID) { + muxVal = 0xc; + muxValMask = 0xf3; + } + + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + muxVal = (twsiVal & muxValMask) | muxVal; + + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) ) + { + mvOsPrintf("Board: twsi exp out val fail\n"); + return; + } + DB(mvOsPrintf("Board: twsi exp out val succeded\n")); + + /* Change twsi exp to output */ + twsiSlave.offset = 7; + muxVal = 0xfe; + if(mvBoardIdGet() == RD_88F6281A_ID) + muxVal = 0xf3; + + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + muxVal = (twsiVal & muxVal); + + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) ) + { + mvOsPrintf("Board: twsi exp change to out fail\n"); + return; + } + DB(mvOsPrintf("Board: twsi exp change to out succeded\n")); + /* reset the line to 0 */ + twsiSlave.offset = 3; + muxVal = 0; + muxValMask = 1; + + if(mvBoardIdGet() == RD_88F6281A_ID) { + muxVal = 0x0; + muxValMask = 0xf3; + } + + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + muxVal = (twsiVal & muxValMask) | muxVal; + + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) ) + { + mvOsPrintf("Board: twsi exp out val fail\n"); + return; + } + DB(mvOsPrintf("Board: twsi exp out val succeded\n")); + + mvOsDelay(20); + + /* set the line to 1 */ + twsiSlave.offset = 3; + muxVal = 1; + muxValMask = 1; + + if(mvBoardIdGet() == RD_88F6281A_ID) { + muxVal = 0xc; + muxValMask = 0xf3; + } + + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + muxVal = (twsiVal & muxValMask) | muxVal; + + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) ) + { + mvOsPrintf("Board: twsi exp out val fail\n"); + return; + } + DB(mvOsPrintf("Board: twsi exp out val succeded\n")); + + +} +/******************************************************************************* +* mvBoardVoiceAssembleModeGet - return SLIC/DAA assembly & interrupt modes +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ + +MV_VOID mvBoardVoiceAssemblyModeGet(MV_32* assmeblyMode, MV_32* irqMode) +{ + switch(mvBoardIdGet()) + { + case RD_88F6281A_ID: + *assmeblyMode = DAISY_CHAIN_MODE; + *irqMode = INTERRUPT_TO_TDM; + break; + case DB_88F6281A_BP_ID: + *assmeblyMode = DUAL_CHIP_SELECT_MODE; + *irqMode = INTERRUPT_TO_TDM; + break; + case RD_88F6192A_ID: + *assmeblyMode = DUAL_CHIP_SELECT_MODE; + *irqMode = INTERRUPT_TO_TDM; + break; + case DB_88F6192A_BP_ID: + *assmeblyMode = DUAL_CHIP_SELECT_MODE; + *irqMode = INTERRUPT_TO_TDM; + break; + default: + *assmeblyMode = *irqMode = -1; + mvOsPrintf("mvBoardVoiceAssembleModeGet: TDM not supported(boardId=0x%x)\n",mvBoardIdGet()); + } + return; + +} + +/******************************************************************************* +* mvBoardMppModuleTypePrint - print module detect +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvBoardMppModuleTypePrint(MV_VOID) +{ + + MV_BOARD_MPP_GROUP_CLASS devClass; + MV_BOARD_MPP_TYPE_CLASS mppGroupType; + MV_U32 devId; + MV_U32 maxMppGrp = 1; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + maxMppGrp = MV_6281_MPP_MAX_MODULE; + break; + case MV_6192_DEV_ID: + maxMppGrp = MV_6192_MPP_MAX_MODULE; + break; + case MV_6190_DEV_ID: + maxMppGrp = MV_6190_MPP_MAX_MODULE; + break; + case MV_6180_DEV_ID: + maxMppGrp = MV_6180_MPP_MAX_MODULE; + break; + } + + for (devClass = 0; devClass < maxMppGrp; devClass++) + { + mppGroupType = mvBoardMppGroupTypeGet(devClass); + + switch(mppGroupType) + { + case MV_BOARD_TDM: + if(devId != MV_6190_DEV_ID) + mvOsPrintf("Module %d is TDM\n", devClass); + break; + case MV_BOARD_AUDIO: + if(devId != MV_6190_DEV_ID) + mvOsPrintf("Module %d is AUDIO\n", devClass); + break; + case MV_BOARD_RGMII: + if(devId != MV_6190_DEV_ID) + mvOsPrintf("Module %d is RGMII\n", devClass); + break; + case MV_BOARD_GMII: + if(devId != MV_6190_DEV_ID) + mvOsPrintf("Module %d is GMII\n", devClass); + break; + case MV_BOARD_TS: + if(devId != MV_6190_DEV_ID) + mvOsPrintf("Module %d is TS\n", devClass); + break; + default: + break; + } + } +} + +/* Board devices API managments */ + +/******************************************************************************* +* mvBoardGetDeviceNumber - Get number of device of some type on the board +* +* DESCRIPTION: +* +* INPUT: +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* number of those devices else the function returns 0 +* +* +*******************************************************************************/ +MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass) +{ + MV_U32 foundIndex=0,devNum; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardGetDeviceNumber:Board unknown.\n"); + return 0xFFFFFFFF; + + } + + for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) + { + if (BOARD_INFO(boardId)->pDevCsInfo[devNum].devClass == devClass) + { + foundIndex++; + } + } + + return foundIndex; + +} + +/******************************************************************************* +* mvBoardGetDeviceBaseAddr - Get base address of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* Base address else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return mvCpuIfTargetWinBaseLowGet(DEV_TO_TARGET(devEntry->deviceCS)); + + } + + return 0xFFFFFFFF; +} + +/******************************************************************************* +* mvBoardGetDeviceBusWidth - Get Bus width of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* Bus width else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return 8; + } + + return 0xFFFFFFFF; + +} + +/******************************************************************************* +* mvBoardGetDeviceWidth - Get dev width of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* dev width else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("Board unknown.\n"); + return 0xFFFFFFFF; + } + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + return devEntry->devWidth; + + return MV_ERROR; + +} + +/******************************************************************************* +* mvBoardGetDeviceWinSize - Get the window size of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* window size else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("Board unknown.\n"); + return 0xFFFFFFFF; + } + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return mvCpuIfTargetWinSizeGet(DEV_TO_TARGET(devEntry->deviceCS)); + } + + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* boardGetDevEntry - returns the entry pointer of a device on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* dev number else the function returns 0x0 +* +* +*******************************************************************************/ +static MV_DEV_CS_INFO* boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_U32 foundIndex=0,devIndex; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("boardGetDevEntry: Board unknown.\n"); + return NULL; + + } + + for (devIndex = START_DEV_CS; devIndex < BOARD_INFO(boardId)->numBoardDeviceIf; devIndex++) + { + /* TBR */ + /*if (BOARD_INFO(boardId)->pDevCsInfo[devIndex].deviceCS == MV_BOOTDEVICE_INDEX) + continue;*/ + + if (BOARD_INFO(boardId)->pDevCsInfo[devIndex].devClass == devClass) + { + if (foundIndex == devNum) + { + return &(BOARD_INFO(boardId)->pDevCsInfo[devIndex]); + } + foundIndex++; + } + } + + /* device not found */ + return NULL; +} + +/* Get device CS number */ + +MV_U32 boardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("Board unknown.\n"); + return 0xFFFFFFFF; + + } + + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + return devEntry->deviceCS; + + return 0xFFFFFFFF; + +} + +/******************************************************************************* +* mvBoardRtcTwsiAddrTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardRtcTwsiAddrTypeGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_RTC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType; + return (MV_ERROR); +} + +/******************************************************************************* +* mvBoardRtcTwsiAddrGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardRtcTwsiAddrGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_RTC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr; + return (0xFF); +} + +/******************************************************************************* +* mvBoardA2DTwsiAddrTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardA2DTwsiAddrTypeGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_AUDIO_DEC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType; + return (MV_ERROR); +} + +/******************************************************************************* +* mvBoardA2DTwsiAddrGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardA2DTwsiAddrGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_AUDIO_DEC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr; + return (0xFF); +} + +/******************************************************************************* +* mvBoardTwsiExpAddrTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardTwsiExpAddrTypeGet(MV_U32 index) +{ + int i; + MV_U32 indexFound = 0; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_TWSI_EXP) + { + if (indexFound == index) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType; + else + indexFound++; + } + + return (MV_ERROR); +} + +/******************************************************************************* +* mvBoardTwsiExpAddrGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardTwsiExpAddrGet(MV_U32 index) +{ + int i; + MV_U32 indexFound = 0; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_TWSI_EXP) + { + if (indexFound == index) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr; + else + indexFound++; + } + + return (0xFF); +} + + +/******************************************************************************* +* mvBoardTwsiSatRAddrTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardTwsiSatRAddrTypeGet(MV_U32 index) +{ + int i; + MV_U32 indexFound = 0; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_TWSI_SATR) + { + if (indexFound == index) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType; + else + indexFound++; + } + + return (MV_ERROR); +} + +/******************************************************************************* +* mvBoardTwsiSatRAddrGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardTwsiSatRAddrGet(MV_U32 index) +{ + int i; + MV_U32 indexFound = 0; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_TWSI_SATR) + { + if (indexFound == index) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr; + else + indexFound++; + } + + return (0xFF); +} + +/******************************************************************************* +* mvBoardNandWidthGet - +* +* DESCRIPTION: Get the width of the first NAND device in byte. +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: 1, 2, 4 or MV_ERROR +* +* +*******************************************************************************/ +/* */ +MV_32 mvBoardNandWidthGet(void) +{ + MV_U32 devNum; + MV_U32 devWidth; + MV_U32 boardId= mvBoardIdGet(); + + for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) + { + devWidth = mvBoardGetDeviceWidth(devNum, BOARD_DEV_NAND_FLASH); + if (devWidth != MV_ERROR) + return (devWidth / 8); + } + + /* NAND wasn't found */ + return MV_ERROR; +} + +MV_U32 gBoardId = -1; + +/******************************************************************************* +* mvBoardIdGet - Get Board model +* +* DESCRIPTION: +* This function returns board ID. +* Board ID is 32bit word constructed of board model (16bit) and +* board revision (16bit) in the following way: 0xMMMMRRRR. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit board ID number, '-1' if board is undefined. +* +*******************************************************************************/ +MV_U32 mvBoardIdGet(MV_VOID) +{ + MV_U32 tmpBoardId = -1; + + if(gBoardId == -1) + { + #if defined(DB_88F6281A) + tmpBoardId = DB_88F6281A_BP_ID; + #elif defined(RD_88F6281A) + tmpBoardId = RD_88F6281A_ID; + #elif defined(DB_88F6192A) + tmpBoardId = DB_88F6192A_BP_ID; + #elif defined(DB_88F6190A) + tmpBoardId = DB_88F6190A_BP_ID; + #elif defined(RD_88F6192A) + tmpBoardId = RD_88F6192A_ID; + #elif defined(RD_88F6190A) + tmpBoardId = RD_88F6190A_ID; + #elif defined(DB_88F6180A) + tmpBoardId = DB_88F6180A_BP_ID; + #endif + gBoardId = tmpBoardId; + } + + return gBoardId; +} + + +/******************************************************************************* +* mvBoarModuleTypeGet - mvBoarModuleTypeGet +* +* DESCRIPTION: +* +* INPUT: +* group num - MV_BOARD_MPP_GROUP_CLASS enum +* +* OUTPUT: +* None. +* +* RETURN: +* module num - MV_BOARD_MODULE_CLASS enum +* +*******************************************************************************/ +MV_BOARD_MODULE_ID_CLASS mvBoarModuleTypeGet(MV_BOARD_MPP_GROUP_CLASS devClass) +{ + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + MV_U8 data; + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + DB(mvOsPrintf("Board: Read MPP module ID\n")); + twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(devClass); + twsiSlave.slaveAddr.type = mvBoardTwsiExpAddrTypeGet(devClass); + twsiSlave.validOffset = MV_TRUE; + /* Offset is the first command after the address which indicate the register number to be read + in next operation */ + twsiSlave.offset = 0; + twsiSlave.moreThen256 = MV_FALSE; + + + + if( MV_OK != mvTwsiRead (0, &twsiSlave, &data, 1) ) + { + DB(mvOsPrintf("Board: Read MPP module ID fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: Read MPP module ID succeded\n")); + + return data; +} + +/******************************************************************************* +* mvBoarTwsiSatRGet - +* +* DESCRIPTION: +* +* INPUT: +* device num - one of three devices +* reg num - 0 or 1 +* +* OUTPUT: +* None. +* +* RETURN: +* reg value +* +*******************************************************************************/ +MV_U8 mvBoarTwsiSatRGet(MV_U8 devNum, MV_U8 regNum) +{ + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + MV_U8 data; + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + DB(mvOsPrintf("Board: Read S@R device read\n")); + twsiSlave.slaveAddr.address = mvBoardTwsiSatRAddrGet(devNum); + twsiSlave.slaveAddr.type = mvBoardTwsiSatRAddrTypeGet(devNum); + twsiSlave.validOffset = MV_TRUE; + /* Use offset as command */ + twsiSlave.offset = regNum; + twsiSlave.moreThen256 = MV_FALSE; + + if( MV_OK != mvTwsiRead (0, &twsiSlave, &data, 1) ) + { + DB(mvOsPrintf("Board: Read S@R fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: Read S@R succeded\n")); + + return data; +} + +/******************************************************************************* +* mvBoarTwsiSatRSet - +* +* DESCRIPTION: +* +* INPUT: +* devNum - one of three devices +* regNum - 0 or 1 +* regVal - value +* +* +* OUTPUT: +* None. +* +* RETURN: +* reg value +* +*******************************************************************************/ +MV_STATUS mvBoarTwsiSatRSet(MV_U8 devNum, MV_U8 regNum, MV_U8 regVal) +{ + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + twsiSlave.slaveAddr.address = mvBoardTwsiSatRAddrGet(devNum); + twsiSlave.slaveAddr.type = mvBoardTwsiSatRAddrTypeGet(devNum); + twsiSlave.validOffset = MV_TRUE; + DB(mvOsPrintf("Board: Write S@R device addr %x, type %x, data %x\n", twsiSlave.slaveAddr.address,\ + twsiSlave.slaveAddr.type, regVal)); + /* Use offset as command */ + twsiSlave.offset = regNum; + twsiSlave.moreThen256 = MV_FALSE; + if( MV_OK != mvTwsiWrite (0, &twsiSlave, ®Val, 1) ) + { + DB(mvOsPrintf("Board: Write S@R fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: Write S@R succeded\n")); + + return MV_OK; +} + +/******************************************************************************* +* mvBoardSlicGpioPinGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_32 mvBoardSlicGpioPinGet(MV_U32 slicNum) +{ + MV_U32 boardId; + boardId = mvBoardIdGet(); + + switch (boardId) + { + case DB_88F6281A_BP_ID: + case RD_88F6281A_ID: + default: + return MV_ERROR; + break; + + } +} + +/******************************************************************************* +* mvBoardFanPowerControl - Turn on/off the fan power control on the RD-6281A +* +* DESCRIPTION: +* +* INPUT: +* mode - MV_TRUE = on ; MV_FALSE = off +* +* OUTPUT: +* MV_STATUS - MV_OK , MV_ERROR. +* +* RETURN: +* +*******************************************************************************/ +MV_STATUS mvBoardFanPowerControl(MV_BOOL mode) +{ + + MV_U8 val = 1, twsiVal; + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + + if(mvBoardIdGet() != RD_88F6281A_ID) + return MV_ERROR; + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + DB(mvOsPrintf("Board: twsi exp set\n")); + twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(0); + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + /* Offset is the first command after the address which indicate the register number to be read + in next operation */ + twsiSlave.offset = 3; + twsiSlave.moreThen256 = MV_FALSE; + if(mode == MV_TRUE) + val = 0x1; + else + val = 0; + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + val = (twsiVal & 0xfe) | val; + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) ) + { + DB(mvOsPrintf("Board: twsi exp out val fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: twsi exp out val succeded\n")); + + /* Change twsi exp to output */ + twsiSlave.offset = 7; + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + val = (twsiVal & 0xfe); + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) ) + { + DB(mvOsPrintf("Board: twsi exp change to out fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: twsi exp change to out succeded\n")); + return MV_OK; +} + +/******************************************************************************* +* mvBoardHDDPowerControl - Turn on/off the HDD power control on the RD-6281A +* +* DESCRIPTION: +* +* INPUT: +* mode - MV_TRUE = on ; MV_FALSE = off +* +* OUTPUT: +* MV_STATUS - MV_OK , MV_ERROR. +* +* RETURN: +* +*******************************************************************************/ +MV_STATUS mvBoardHDDPowerControl(MV_BOOL mode) +{ + + MV_U8 val = 1, twsiVal; + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + + if(mvBoardIdGet() != RD_88F6281A_ID) + return MV_ERROR; + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + DB(mvOsPrintf("Board: twsi exp set\n")); + twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(0); + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + /* Offset is the first command after the address which indicate the register number to be read + in next operation */ + twsiSlave.offset = 3; + twsiSlave.moreThen256 = MV_FALSE; + if(mode == MV_TRUE) + val = 0x2; + else + val = 0; + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + val = (twsiVal & 0xfd) | val; + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) ) + { + DB(mvOsPrintf("Board: twsi exp out val fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: twsi exp out val succeded\n")); + + /* Change twsi exp to output */ + twsiSlave.offset = 7; + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + val = (twsiVal & 0xfd); + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) ) + { + DB(mvOsPrintf("Board: twsi exp change to out fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: twsi exp change to out succeded\n")); + return MV_OK; +} + +/******************************************************************************* +* mvBoardSDioWPControl - Turn on/off the SDIO WP on the RD-6281A +* +* DESCRIPTION: +* +* INPUT: +* mode - MV_TRUE = on ; MV_FALSE = off +* +* OUTPUT: +* MV_STATUS - MV_OK , MV_ERROR. +* +* RETURN: +* +*******************************************************************************/ +MV_STATUS mvBoardSDioWPControl(MV_BOOL mode) +{ + + MV_U8 val = 1, twsiVal; + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + + if(mvBoardIdGet() != RD_88F6281A_ID) + return MV_ERROR; + + /* TWSI init */ + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0); + + /* Read MPP module ID */ + DB(mvOsPrintf("Board: twsi exp set\n")); + twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(0); + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + /* Offset is the first command after the address which indicate the register number to be read + in next operation */ + twsiSlave.offset = 3; + twsiSlave.moreThen256 = MV_FALSE; + if(mode == MV_TRUE) + val = 0x10; + else + val = 0; + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + val = (twsiVal & 0xef) | val; + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) ) + { + DB(mvOsPrintf("Board: twsi exp out val fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: twsi exp out val succeded\n")); + + /* Change twsi exp to output */ + twsiSlave.offset = 7; + mvTwsiRead(0, &twsiSlave, &twsiVal, 1); + val = (twsiVal & 0xef); + if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) ) + { + DB(mvOsPrintf("Board: twsi exp change to out fail\n")); + return MV_ERROR; + } + DB(mvOsPrintf("Board: twsi exp change to out succeded\n")); + return MV_OK; +} + +/******************************************************************************* +* Init the PHY or Switch of the board * + ***********************************************************/ +MV_VOID mvBoardEgigaPhySwitchInit(void) +{ + if ((DB_88F6281A_BP_ID == mvBoardIdGet()) || + (DB_88F6192A_BP_ID == mvBoardIdGet())) + { + if ( !(mvBoardIsPortInGmii())) + { + mvEthE1116PhyBasicInit(0); + mvEthE1116PhyBasicInit(1); + } + } + else if ((DB_88F6190A_BP_ID == mvBoardIdGet()) || + (DB_88F6180A_BP_ID == mvBoardIdGet()) || + (RD_88F6192A_ID == mvBoardIdGet()) || + (RD_88F6190A_ID == mvBoardIdGet())) + { + mvEthE1116PhyBasicInit(0); + } + else if (RD_88F6281A_ID == mvBoardIdGet()) + { + mvEthE6161SwitchBasicInit(0); + mvEthE1116PhyBasicInit(1); + } +} diff --git a/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.h b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.h new file mode 100644 index 0000000..32ae51c --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvLib.h @@ -0,0 +1,376 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvBoardEnvLibh +#define __INCmvBoardEnvLibh + +/* defines */ +/* The below constant macros defines the board I2C EEPROM data offsets */ + + + +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "mvSysHwConfig.h" +#include "boardEnv/mvBoardEnvSpec.h" + + +/* DUART stuff for Tclk detection only */ +#define DUART_BAUD_RATE 115200 +#define MAX_CLOCK_MARGINE 5000000 /* Maximum detected clock margine */ + +/* Voice devices assembly modes */ +#define DAISY_CHAIN_MODE 1 +#define DUAL_CHIP_SELECT_MODE 0 +#define INTERRUPT_TO_MPP 1 +#define INTERRUPT_TO_TDM 0 + + +#define BOARD_ETH_PORT_NUM MV_ETH_MAX_PORTS +#define BOARD_ETH_SWITCH_PORT_NUM 5 + +#define MV_BOARD_MAX_USB_IF 1 +#define MV_BOARD_MAX_MPP 7 +#define MV_BOARD_NAME_LEN 0x20 + +typedef struct _boardData +{ + MV_U32 magic; + MV_U16 boardId; + MV_U8 boardVer; + MV_U8 boardRev; + MV_U32 reserved1; + MV_U32 reserved2; + +}BOARD_DATA; + +typedef enum _devBoardMppGroupClass +{ + MV_BOARD_MPP_GROUP_1, + MV_BOARD_MPP_GROUP_2, + MV_BOARD_MAX_MPP_GROUP +}MV_BOARD_MPP_GROUP_CLASS; + +typedef enum _devBoardMppTypeClass +{ + MV_BOARD_AUTO, + MV_BOARD_TDM, + MV_BOARD_AUDIO, + MV_BOARD_RGMII, + MV_BOARD_GMII, + MV_BOARD_TS, + MV_BOARD_MII, + MV_BOARD_OTHER +}MV_BOARD_MPP_TYPE_CLASS; + +typedef enum _devBoardModuleIdClass +{ + MV_BOARD_MODULE_TDM_ID = 1, + MV_BOARD_MODULE_AUDIO_ID, + MV_BOARD_MODULE_RGMII_ID, + MV_BOARD_MODULE_GMII_ID, + MV_BOARD_MODULE_TS_ID, + MV_BOARD_MODULE_MII_ID, + MV_BOARD_MODULE_OTHER_ID +}MV_BOARD_MODULE_ID_CLASS; + +typedef struct _boardMppTypeInfo +{ + MV_BOARD_MPP_TYPE_CLASS boardMppGroup1; + MV_BOARD_MPP_TYPE_CLASS boardMppGroup2; + +}MV_BOARD_MPP_TYPE_INFO; + + +typedef enum _devBoardClass +{ + BOARD_DEV_NOR_FLASH, + BOARD_DEV_NAND_FLASH, + BOARD_DEV_SEVEN_SEG, + BOARD_DEV_FPGA, + BOARD_DEV_SRAM, + BOARD_DEV_SPI_FLASH, + BOARD_DEV_OTHER, +}MV_BOARD_DEV_CLASS; + +typedef enum _devTwsiBoardClass +{ + BOARD_TWSI_RTC, + BOARD_DEV_TWSI_EXP, + BOARD_DEV_TWSI_SATR, + BOARD_TWSI_AUDIO_DEC, + BOARD_TWSI_OTHER +}MV_BOARD_TWSI_CLASS; + +typedef enum _devGppBoardClass +{ + BOARD_GPP_RTC, + BOARD_GPP_MV_SWITCH, + BOARD_GPP_USB_VBUS, + BOARD_GPP_USB_VBUS_EN, + BOARD_GPP_USB_OC, + BOARD_GPP_USB_HOST_DEVICE, + BOARD_GPP_REF_CLCK, + BOARD_GPP_VOIP_SLIC, + BOARD_GPP_LIFELINE, + BOARD_GPP_BUTTON, + BOARD_GPP_TS_BUTTON_C, + BOARD_GPP_TS_BUTTON_U, + BOARD_GPP_TS_BUTTON_D, + BOARD_GPP_TS_BUTTON_L, + BOARD_GPP_TS_BUTTON_R, + BOARD_GPP_POWER_BUTTON, + BOARD_GPP_RESTOR_BUTTON, + BOARD_GPP_WPS_BUTTON, + BOARD_GPP_HDD0_POWER, + BOARD_GPP_HDD1_POWER, + BOARD_GPP_FAN_POWER, + BOARD_GPP_RESET, + BOARD_GPP_POWER_ON_LED, + BOARD_GPP_HDD_POWER, + BOARD_GPP_SDIO_POWER, + BOARD_GPP_SDIO_DETECT, + BOARD_GPP_SDIO_WP, + BOARD_GPP_SWITCH_PHY_INT, + BOARD_GPP_TSU_DIRCTION, + BOARD_GPP_OTHER +}MV_BOARD_GPP_CLASS; + + +typedef struct _devCsInfo +{ + MV_U8 deviceCS; + MV_U32 params; + MV_U32 devClass; /* MV_BOARD_DEV_CLASS */ + MV_U8 devWidth; + +}MV_DEV_CS_INFO; + + +#define MV_BOARD_PHY_FORCE_10MB 0x0 +#define MV_BOARD_PHY_FORCE_100MB 0x1 +#define MV_BOARD_PHY_FORCE_1000MB 0x2 +#define MV_BOARD_PHY_SPEED_AUTO 0x3 + +typedef struct _boardSwitchInfo +{ + MV_32 linkStatusIrq; + MV_32 qdPort[BOARD_ETH_SWITCH_PORT_NUM]; + MV_32 qdCpuPort; + MV_32 smiScanMode; /* 1 for SMI_MANUAL_MODE, 0 otherwise */ + MV_32 switchOnPort; + +}MV_BOARD_SWITCH_INFO; + +typedef struct _boardLedInfo +{ + MV_U8 activeLedsNumber; + MV_U8 ledsPolarity; /* '0' or '1' to turn on led */ + MV_U8* gppPinNum; /* Pointer to GPP values */ + +}MV_BOARD_LED_INFO; + +typedef struct _boardGppInfo +{ + MV_BOARD_GPP_CLASS devClass; + MV_U8 gppPinNum; + +}MV_BOARD_GPP_INFO; + + +typedef struct _boardTwsiInfo +{ + MV_BOARD_TWSI_CLASS devClass; + MV_U8 twsiDevAddr; + MV_U8 twsiDevAddrType; + +}MV_BOARD_TWSI_INFO; + + +typedef enum _boardMacSpeed +{ + BOARD_MAC_SPEED_10M, + BOARD_MAC_SPEED_100M, + BOARD_MAC_SPEED_1000M, + BOARD_MAC_SPEED_AUTO, + +}MV_BOARD_MAC_SPEED; + +typedef struct _boardMacInfo +{ + MV_BOARD_MAC_SPEED boardMacSpeed; + MV_U8 boardEthSmiAddr; + +}MV_BOARD_MAC_INFO; + +typedef struct _boardMppInfo +{ + MV_U32 mppGroup[MV_BOARD_MAX_MPP]; + +}MV_BOARD_MPP_INFO; + +typedef struct _boardInfo +{ + char boardName[MV_BOARD_NAME_LEN]; + MV_U8 numBoardMppTypeValue; + MV_BOARD_MPP_TYPE_INFO* pBoardMppTypeValue; + MV_U8 numBoardMppConfigValue; + MV_BOARD_MPP_INFO* pBoardMppConfigValue; + MV_U32 intsGppMaskLow; + MV_U32 intsGppMaskHigh; + MV_U8 numBoardDeviceIf; + MV_DEV_CS_INFO* pDevCsInfo; + MV_U8 numBoardTwsiDev; + MV_BOARD_TWSI_INFO* pBoardTwsiDev; + MV_U8 numBoardMacInfo; + MV_BOARD_MAC_INFO* pBoardMacInfo; + MV_U8 numBoardGppInfo; + MV_BOARD_GPP_INFO* pBoardGppInfo; + MV_U8 activeLedsNumber; + MV_U8* pLedGppPin; + MV_U8 ledsPolarity; /* '0' or '1' to turn on led */ + /* GPP values */ + MV_U32 gppOutEnValLow; + MV_U32 gppOutEnValHigh; + MV_U32 gppOutValLow; + MV_U32 gppOutValHigh; + MV_U32 gppPolarityValLow; + MV_U32 gppPolarityValHigh; + + /* Switch Configuration */ + MV_BOARD_SWITCH_INFO* pSwitchInfo; +}MV_BOARD_INFO; + + + +MV_VOID mvBoardEnvInit(MV_VOID); +MV_U32 mvBoardIdGet(MV_VOID); +MV_U16 mvBoardModelGet(MV_VOID); +MV_U16 mvBoardRevGet(MV_VOID); +MV_STATUS mvBoardNameGet(char *pNameBuff); +MV_32 mvBoardPhyAddrGet(MV_U32 ethPortNum); +MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum); +MV_32 mvBoardLinkStatusIrqGet(MV_U32 ethPortNum); +MV_32 mvBoardSwitchPortGet(MV_U32 ethPortNum, MV_U8 boardPortNum); +MV_32 mvBoardSwitchCpuPortGet(MV_U32 ethPortNum); +MV_32 mvBoardIsSwitchConnected(MV_U32 ethPortNum); +MV_32 mvBoardSmiScanModeGet(MV_U32 ethPortNum); +MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum); +MV_BOOL mvBoardIsPortInGmii(MV_VOID); +MV_U32 mvBoardTclkGet(MV_VOID); +MV_U32 mvBoardSysClkGet(MV_VOID); +MV_U32 mvBoardDebugLedNumGet(MV_U32 boardId); +MV_VOID mvBoardDebugLed(MV_U32 hexNum); +MV_32 mvBoardMppGet(MV_U32 mppGroupNum); + +MV_U8 mvBoardRtcTwsiAddrTypeGet(MV_VOID); +MV_U8 mvBoardRtcTwsiAddrGet(MV_VOID); + +MV_U8 mvBoardA2DTwsiAddrTypeGet(MV_VOID); +MV_U8 mvBoardA2DTwsiAddrGet(MV_VOID); + +MV_U8 mvBoardTwsiExpAddrGet(MV_U32 index); +MV_U8 mvBoardTwsiSatRAddrTypeGet(MV_U32 index); +MV_U8 mvBoardTwsiSatRAddrGet(MV_U32 index); +MV_U8 mvBoardTwsiExpAddrTypeGet(MV_U32 index); +MV_BOARD_MODULE_ID_CLASS mvBoarModuleTypeGet(MV_BOARD_MPP_GROUP_CLASS devClass); +MV_BOARD_MPP_TYPE_CLASS mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass); +MV_VOID mvBoardMppGroupTypeSet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass, + MV_BOARD_MPP_TYPE_CLASS mppGroupType); +MV_VOID mvBoardMppGroupIdUpdate(MV_VOID); +MV_VOID mvBoardMppMuxSet(MV_VOID); +MV_VOID mvBoardTdmLifeLineSet(MV_VOID); +MV_VOID mvBoardVoiceAssemblyModeGet(MV_32* assmeblyMode, MV_32* irqMode); + +MV_VOID mvBoardMppModuleTypePrint(MV_VOID); +MV_VOID mvBoardReset(MV_VOID); +MV_U8 mvBoarTwsiSatRGet(MV_U8 devNum, MV_U8 regNum); +MV_STATUS mvBoarTwsiSatRSet(MV_U8 devNum, MV_U8 regNum, MV_U8 regVal); +MV_BOOL mvBoardSpecInitGet(MV_U32* regOff, MV_U32* data); +/* Board devices API managments */ +MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_U32 boardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); + +/* Gpio Pin Connections API */ +MV_32 mvBoardUSBVbusGpioPinGet(int devId); +MV_32 mvBoardUSBVbusEnGpioPinGet(int devId); +MV_U32 mvBoardPexBridgeIntPinGet(MV_U32 devNum, MV_U32 intPin); + +MV_32 mvBoardResetGpioPinGet(MV_VOID); +MV_32 mvBoardRTCGpioPinGet(MV_VOID); +MV_32 mvBoardGpioIntMaskLowGet(MV_VOID); +MV_32 mvBoardGpioIntMaskHighGet(MV_VOID); +MV_32 mvBoardSlicGpioPinGet(MV_U32 slicNum); + +MV_32 mvBoardSDIOGpioPinGet(MV_VOID); +MV_32 mvBoarGpioPinNumGet(MV_BOARD_GPP_CLASS class, MV_U32 index); + +MV_32 mvBoardNandWidthGet(void); + +MV_STATUS mvBoardFanPowerControl(MV_BOOL mode); +MV_STATUS mvBoardHDDPowerControl(MV_BOOL mode); +MV_VOID mvBoardEgigaPhySwitchInit(void); +#endif /* __INCmvBoardEnvLibh */ diff --git a/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.c b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.c new file mode 100644 index 0000000..a352c0d --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.c @@ -0,0 +1,576 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#include "mvCommon.h" +#include "mvBoardEnvLib.h" +#include "mvBoardEnvSpec.h" +#include "twsi/mvTwsi.h" + +#define DB_88F6281A_BOARD_PCI_IF_NUM 0x0 +#define DB_88F6281A_BOARD_TWSI_DEF_NUM 0x7 +#define DB_88F6281A_BOARD_MAC_INFO_NUM 0x2 +#define DB_88F6281A_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F6281A_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F6281A_BOARD_MPP_GROUP_TYPE_NUM 0x1 +#if defined(MV_NAND) && defined(MV_NAND_BOOT) + #define DB_88F6281A_BOARD_DEVICE_CONFIG_NUM 0x1 +#elif defined(MV_NAND) && defined(MV_SPI_BOOT) + #define DB_88F6281A_BOARD_DEVICE_CONFIG_NUM 0x2 +#else + #define DB_88F6281A_BOARD_DEVICE_CONFIG_NUM 0x1 +#endif +#define DB_88F6281A_BOARD_DEBUG_LED_NUM 0x0 + + +MV_BOARD_TWSI_INFO db88f6281AInfoBoardTwsiDev[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + { + {BOARD_DEV_TWSI_EXP, 0x20, ADDR7_BIT}, + {BOARD_DEV_TWSI_EXP, 0x21, ADDR7_BIT}, + {BOARD_DEV_TWSI_EXP, 0x27, ADDR7_BIT}, + {BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT}, + {BOARD_DEV_TWSI_SATR, 0x4D, ADDR7_BIT}, + {BOARD_DEV_TWSI_SATR, 0x4E, ADDR7_BIT}, + {BOARD_TWSI_AUDIO_DEC, 0x4A, ADDR7_BIT} + }; + +MV_BOARD_MAC_INFO db88f6281AInfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + { + {BOARD_MAC_SPEED_AUTO, 0x8}, +//Patch by QNAP:Fix GE1 +#if defined(TS419) + {BOARD_MAC_SPEED_AUTO, 0x0} +#else + {BOARD_MAC_SPEED_AUTO, 0x9} +#endif +////////////////////////////////////////////////////// + }; + +MV_BOARD_MPP_TYPE_INFO db88f6281AInfoBoardMppTypeInfo[] = + /* {{MV_BOARD_MPP_TYPE_CLASS boardMppGroup1, + MV_BOARD_MPP_TYPE_CLASS boardMppGroup2}} */ + {{MV_BOARD_AUTO, MV_BOARD_AUTO} + }; + +MV_BOARD_GPP_INFO db88f6281AInfoBoardGppInfo[] = + /* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */ + { + {BOARD_GPP_TSU_DIRCTION, 33}, + {BOARD_GPP_SDIO_DETECT, 38}, + {BOARD_GPP_USB_VBUS, 49} + }; + +MV_DEV_CS_INFO db88f6281AInfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ +#if defined(MV_NAND) && defined(MV_NAND_BOOT) + {{0, N_A, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#elif defined(MV_NAND) && defined(MV_SPI_BOOT) + { + {0, N_A, BOARD_DEV_NAND_FLASH, 8}, /* NAND DEV */ + {2, N_A, BOARD_DEV_SPI_FLASH, 8}, /* SPI DEV */ + }; +#else + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ +#endif + +MV_BOARD_MPP_INFO db88f6281AInfoBoardMppConfigValue[] = + {{{ + DB_88F6281A_MPP0_7, + DB_88F6281A_MPP8_15, + DB_88F6281A_MPP16_23, + DB_88F6281A_MPP24_31, + DB_88F6281A_MPP32_39, + DB_88F6281A_MPP40_47, + DB_88F6281A_MPP48_55 + }}}; + + +MV_BOARD_INFO db88f6281AInfo = { + "DB-88F6281A-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6281A_BOARD_MPP_GROUP_TYPE_NUM, /* numBoardMppGroupType */ + db88f6281AInfoBoardMppTypeInfo, + DB_88F6281A_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6281AInfoBoardMppConfigValue, + 0, /* intsGppMaskLow */ + 0, /* intsGppMaskHigh */ + DB_88F6281A_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6281AInfoBoardDeCsInfo, + DB_88F6281A_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6281AInfoBoardTwsiDev, + DB_88F6281A_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f6281AInfoBoardMacInfo, + DB_88F6281A_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f6281AInfoBoardGppInfo, + DB_88F6281A_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + N_A, + N_A, /* ledsPolarity */ + DB_88F6281A_OE_LOW, /* gppOutEnLow */ + DB_88F6281A_OE_HIGH, /* gppOutEnHigh */ + DB_88F6281A_OE_VAL_LOW, /* gppOutValLow */ + DB_88F6281A_OE_VAL_HIGH, /* gppOutValHigh */ + 0, /* gppPolarityValLow */ + 0, /* gppPolarityValHigh */ + NULL /* pSwitchInfo */ +}; + + +#define RD_88F6281A_BOARD_PCI_IF_NUM 0x0 +#define RD_88F6281A_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F6281A_BOARD_MAC_INFO_NUM 0x2 +#define RD_88F6281A_BOARD_GPP_INFO_NUM 0x5 +#define RD_88F6281A_BOARD_MPP_GROUP_TYPE_NUM 0x1 +#define RD_88F6281A_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F6281A_BOARD_DEVICE_CONFIG_NUM 0x1 +#define RD_88F6281A_BOARD_DEBUG_LED_NUM 0x0 + +MV_BOARD_MAC_INFO rd88f6281AInfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_1000M, 0xa}, + {BOARD_MAC_SPEED_AUTO, 0xb} + }; + +MV_BOARD_SWITCH_INFO rd88f6281AInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode, MV_32 switchOnPort} */ + {{38, {0, 1, 2, 3}, 5, 1, 0}, + {-1, {-1}, -1, -1, -1}}; + +MV_BOARD_TWSI_INFO rd88f6281AInfoBoardTwsiDev[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + { + {BOARD_DEV_TWSI_EXP, 0x27, ADDR7_BIT} + }; + +MV_BOARD_MPP_TYPE_INFO rd88f6281AInfoBoardMppTypeInfo[] = + {{MV_BOARD_RGMII, MV_BOARD_TDM} + }; + +MV_DEV_CS_INFO rd88f6281AInfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ +#if defined(MV_NAND) || defined(MV_NAND_BOOT) + {{0, N_A, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* NAND DEV */ +#endif + +MV_BOARD_GPP_INFO rd88f6281AInfoBoardGppInfo[] = + /* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_GPP_SDIO_DETECT, 28}, + {BOARD_GPP_USB_OC, 29}, + {BOARD_GPP_WPS_BUTTON, 35}, + {BOARD_GPP_MV_SWITCH, 38}, + {BOARD_GPP_USB_VBUS, 49} + }; + +MV_BOARD_MPP_INFO rd88f6281AInfoBoardMppConfigValue[] = + {{{ + RD_88F6281A_MPP0_7, + RD_88F6281A_MPP8_15, + RD_88F6281A_MPP16_23, + RD_88F6281A_MPP24_31, + RD_88F6281A_MPP32_39, + RD_88F6281A_MPP40_47, + RD_88F6281A_MPP48_55 + }}}; + +MV_BOARD_INFO rd88f6281AInfo = { + "RD-88F6281A", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6281A_BOARD_MPP_GROUP_TYPE_NUM, /* numBoardMppGroupType */ + rd88f6281AInfoBoardMppTypeInfo, + RD_88F6281A_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6281AInfoBoardMppConfigValue, + 0, /* intsGppMaskLow */ + (1 << 3), /* intsGppMaskHigh */ + RD_88F6281A_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f6281AInfoBoardDeCsInfo, + RD_88F6281A_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f6281AInfoBoardTwsiDev, + RD_88F6281A_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6281AInfoBoardMacInfo, + RD_88F6281A_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6281AInfoBoardGppInfo, + RD_88F6281A_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + RD_88F6281A_OE_LOW, /* gppOutEnLow */ + RD_88F6281A_OE_HIGH, /* gppOutEnHigh */ + RD_88F6281A_OE_VAL_LOW, /* gppOutValLow */ + RD_88F6281A_OE_VAL_HIGH, /* gppOutValHigh */ + 0, /* gppPolarityValLow */ + BIT6, /* gppPolarityValHigh */ + rd88f6281AInfoBoardSwitchInfo /* pSwitchInfo */ +}; + + +#define DB_88F6192A_BOARD_PCI_IF_NUM 0x0 +#define DB_88F6192A_BOARD_TWSI_DEF_NUM 0x7 +#define DB_88F6192A_BOARD_MAC_INFO_NUM 0x2 +#define DB_88F6192A_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F6192A_BOARD_MPP_GROUP_TYPE_NUM 0x1 +#define DB_88F6192A_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F6192A_BOARD_DEVICE_CONFIG_NUM 0x1 +#define DB_88F6192A_BOARD_DEBUG_LED_NUM 0x0 + +MV_BOARD_TWSI_INFO db88f6192AInfoBoardTwsiDev[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + { + {BOARD_DEV_TWSI_EXP, 0x20, ADDR7_BIT}, + {BOARD_DEV_TWSI_EXP, 0x21, ADDR7_BIT}, + {BOARD_DEV_TWSI_EXP, 0x27, ADDR7_BIT}, + {BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT}, + {BOARD_DEV_TWSI_SATR, 0x4D, ADDR7_BIT}, + {BOARD_DEV_TWSI_SATR, 0x4E, ADDR7_BIT}, + {BOARD_TWSI_AUDIO_DEC, 0x4A, ADDR7_BIT} + }; + +MV_BOARD_MAC_INFO db88f6192AInfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + { + {BOARD_MAC_SPEED_AUTO, 0x8}, + {BOARD_MAC_SPEED_AUTO, 0x9} + }; + +MV_BOARD_MPP_TYPE_INFO db88f6192AInfoBoardMppTypeInfo[] = + /* {{MV_BOARD_MPP_TYPE_CLASS boardMppGroup1, + MV_BOARD_MPP_TYPE_CLASS boardMppGroup2}} */ + {{MV_BOARD_AUTO, MV_BOARD_OTHER} + }; + +MV_DEV_CS_INFO db88f6192AInfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ +#if defined(MV_NAND) || defined(MV_NAND_BOOT) + {{0, N_A, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* NAND DEV */ +#endif + +MV_BOARD_GPP_INFO db88f6192AInfoBoardGppInfo[] = + /* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */ + { + {BOARD_GPP_SDIO_WP, 20}, + {BOARD_GPP_USB_VBUS, 22}, + {BOARD_GPP_SDIO_DETECT, 23}, + }; + +MV_BOARD_MPP_INFO db88f6192AInfoBoardMppConfigValue[] = + {{{ + DB_88F6192A_MPP0_7, + DB_88F6192A_MPP8_15, + DB_88F6192A_MPP16_23, + DB_88F6192A_MPP24_31, + DB_88F6192A_MPP32_35 + }}}; + +MV_BOARD_INFO db88f6192AInfo = { + "DB-88F6192A-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6192A_BOARD_MPP_GROUP_TYPE_NUM, /* numBoardMppGroupType */ + db88f6192AInfoBoardMppTypeInfo, + DB_88F6192A_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6192AInfoBoardMppConfigValue, + 0, /* intsGppMaskLow */ + (1 << 3), /* intsGppMaskHigh */ + DB_88F6192A_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6192AInfoBoardDeCsInfo, + DB_88F6192A_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6192AInfoBoardTwsiDev, + DB_88F6192A_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f6192AInfoBoardMacInfo, + DB_88F6192A_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f6192AInfoBoardGppInfo, + DB_88F6192A_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + N_A, + N_A, /* ledsPolarity */ + DB_88F6192A_OE_LOW, /* gppOutEnLow */ + DB_88F6192A_OE_HIGH, /* gppOutEnHigh */ + DB_88F6192A_OE_VAL_LOW, /* gppOutValLow */ + DB_88F6192A_OE_VAL_HIGH, /* gppOutValHigh */ + 0, /* gppPolarityValLow */ + 0 /* gppPolarityValHigh */ +}; + +#define DB_88F6190A_BOARD_MAC_INFO_NUM 0x1 + +MV_BOARD_INFO db88f6190AInfo = { + "DB-88F6190A-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6192A_BOARD_MPP_GROUP_TYPE_NUM, /* numBoardMppGroupType */ + db88f6192AInfoBoardMppTypeInfo, + DB_88F6192A_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6192AInfoBoardMppConfigValue, + 0, /* intsGppMaskLow */ + (1 << 3), /* intsGppMaskHigh */ + DB_88F6192A_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6192AInfoBoardDeCsInfo, + DB_88F6192A_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6192AInfoBoardTwsiDev, + DB_88F6190A_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f6192AInfoBoardMacInfo, + DB_88F6192A_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f6192AInfoBoardGppInfo, + DB_88F6192A_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + N_A, + N_A, /* ledsPolarity */ + DB_88F6192A_OE_LOW, /* gppOutEnLow */ + DB_88F6192A_OE_HIGH, /* gppOutEnHigh */ + DB_88F6192A_OE_VAL_LOW, /* gppOutValLow */ + DB_88F6192A_OE_VAL_HIGH, /* gppOutValHigh */ + 0, /* gppPolarityValLow */ + 0 /* gppPolarityValHigh */ +}; + +#define RD_88F6192A_BOARD_PCI_IF_NUM 0x0 +#define RD_88F6192A_BOARD_TWSI_DEF_NUM 0x0 +#define RD_88F6192A_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F6192A_BOARD_GPP_INFO_NUM 0xE +#define RD_88F6192A_BOARD_MPP_GROUP_TYPE_NUM 0x1 +#define RD_88F6192A_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F6192A_BOARD_DEVICE_CONFIG_NUM 0x1 +#define RD_88F6192A_BOARD_DEBUG_LED_NUM 0x3 + +MV_U8 rd88f6192AInfoBoardDebugLedIf[] = + {17, 28, 29}; + +MV_BOARD_MAC_INFO rd88f6192AInfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8} + }; + +MV_BOARD_MPP_TYPE_INFO rd88f6192AInfoBoardMppTypeInfo[] = + /* {{MV_BOARD_MPP_TYPE_CLASS boardMppGroup1, + MV_BOARD_MPP_TYPE_CLASS boardMppGroup2}} */ + {{MV_BOARD_OTHER, MV_BOARD_OTHER} + }; + +MV_DEV_CS_INFO rd88f6192AInfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ + {{1, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ + +MV_BOARD_GPP_INFO rd88f6192AInfoBoardGppInfo[] = + /* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */ + { + {BOARD_GPP_USB_VBUS_EN, 10}, + {BOARD_GPP_USB_HOST_DEVICE, 11}, + {BOARD_GPP_RESET, 14}, + {BOARD_GPP_POWER_ON_LED, 15}, + {BOARD_GPP_HDD_POWER, 16}, + {BOARD_GPP_WPS_BUTTON, 24}, + {BOARD_GPP_TS_BUTTON_C, 25}, + {BOARD_GPP_USB_VBUS, 26}, + {BOARD_GPP_USB_OC, 27}, + {BOARD_GPP_TS_BUTTON_U, 30}, + {BOARD_GPP_TS_BUTTON_R, 31}, + {BOARD_GPP_TS_BUTTON_L, 32}, + {BOARD_GPP_TS_BUTTON_D, 34}, + {BOARD_GPP_FAN_POWER, 35} + }; + +MV_BOARD_MPP_INFO rd88f6192AInfoBoardMppConfigValue[] = + {{{ + RD_88F6192A_MPP0_7, + RD_88F6192A_MPP8_15, + RD_88F6192A_MPP16_23, + RD_88F6192A_MPP24_31, + RD_88F6192A_MPP32_35 + }}}; + +MV_BOARD_INFO rd88f6192AInfo = { + "RD-88F6192A-NAS", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6192A_BOARD_MPP_GROUP_TYPE_NUM, /* numBoardMppGroupType */ + rd88f6192AInfoBoardMppTypeInfo, + RD_88F6192A_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6192AInfoBoardMppConfigValue, + 0, /* intsGppMaskLow */ + (1 << 3), /* intsGppMaskHigh */ + RD_88F6192A_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f6192AInfoBoardDeCsInfo, + RD_88F6192A_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + NULL, + RD_88F6192A_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6192AInfoBoardMacInfo, + RD_88F6192A_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6192AInfoBoardGppInfo, + RD_88F6192A_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f6192AInfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + RD_88F6192A_OE_LOW, /* gppOutEnLow */ + RD_88F6192A_OE_HIGH, /* gppOutEnHigh */ + RD_88F6192A_OE_VAL_LOW, /* gppOutValLow */ + RD_88F6192A_OE_VAL_HIGH, /* gppOutValHigh */ + 0, /* gppPolarityValLow */ + 0 /* gppPolarityValHigh */ +}; + +MV_BOARD_INFO rd88f6190AInfo = { + "RD-88F6190A-NAS", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6192A_BOARD_MPP_GROUP_TYPE_NUM, /* numBoardMppGroupType */ + rd88f6192AInfoBoardMppTypeInfo, + RD_88F6192A_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6192AInfoBoardMppConfigValue, + 0, /* intsGppMaskLow */ + (1 << 3), /* intsGppMaskHigh */ + RD_88F6192A_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f6192AInfoBoardDeCsInfo, + RD_88F6192A_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + NULL, + RD_88F6192A_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6192AInfoBoardMacInfo, + RD_88F6192A_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6192AInfoBoardGppInfo, + RD_88F6192A_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f6192AInfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + RD_88F6192A_OE_LOW, /* gppOutEnLow */ + RD_88F6192A_OE_HIGH, /* gppOutEnHigh */ + RD_88F6192A_OE_VAL_LOW, /* gppOutValLow */ + RD_88F6192A_OE_VAL_HIGH, /* gppOutValHigh */ + 0, /* gppPolarityValLow */ + 0 /* gppPolarityValHigh */ +}; + +#define DB_88F6180A_BOARD_PCI_IF_NUM 0x0 +#define DB_88F6180A_BOARD_TWSI_DEF_NUM 0x2 +#define DB_88F6180A_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F6180A_BOARD_GPP_INFO_NUM 0x0 +#define DB_88F6180A_BOARD_MPP_GROUP_TYPE_NUM 0x1 +#define DB_88F6180A_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F6180A_BOARD_DEVICE_CONFIG_NUM 0x1 +#define DB_88F6180A_BOARD_DEBUG_LED_NUM 0x2 + +MV_U8 db88f6180AInfoBoardDebugLedIf[] = + {7, 10}; + +MV_BOARD_TWSI_INFO db88f6180AInfoBoardTwsiDev[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + { + {BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT}, + {BOARD_DEV_TWSI_SATR, 0x4E, ADDR7_BIT} + }; + +MV_BOARD_MAC_INFO db88f6180AInfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8} + }; + +MV_BOARD_GPP_INFO db88f6180AInfoBoardGppInfo[] = + /* {{MV_BOARD_GPP_CLASS devClass, MV_U8 gppPinNum}} */ + { + {BOARD_GPP_USB_VBUS, 6} + }; + +MV_BOARD_MPP_TYPE_INFO db88f6180AInfoBoardMppTypeInfo[] = + /* {{MV_BOARD_MPP_TYPE_CLASS boardMppGroup1, + MV_BOARD_MPP_TYPE_CLASS boardMppGroup2}} */ + {{MV_BOARD_OTHER, MV_BOARD_OTHER} + }; + +MV_DEV_CS_INFO db88f6180AInfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* NAND DEV */ + +MV_BOARD_MPP_INFO db88f6180AInfoBoardMppConfigValue[] = + {{{ + DB_88F6180A_MPP0_7, + DB_88F6180A_MPP8_15, + DB_88F6180A_MPP16_19, + DB_88F6180A_MPP35_39, + DB_88F6180A_MPP40_44 + }}}; + +MV_BOARD_INFO db88f6180AInfo = { + "DB-88F6180A-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6180A_BOARD_MPP_GROUP_TYPE_NUM, /* numBoardMppGroupType */ + db88f6180AInfoBoardMppTypeInfo, + DB_88F6180A_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6180AInfoBoardMppConfigValue, + 0, /* intsGppMaskLow */ + 0, /* intsGppMaskHigh */ + DB_88F6180A_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6180AInfoBoardDeCsInfo, + DB_88F6180A_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6180AInfoBoardTwsiDev, + DB_88F6180A_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f6180AInfoBoardMacInfo, + DB_88F6180A_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + NULL, + DB_88F6180A_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f6180AInfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + DB_88F6180A_OE_LOW, /* gppOutEnLow */ + DB_88F6180A_OE_HIGH, /* gppOutEnHigh */ + DB_88F6180A_OE_VAL_LOW, /* gppOutValLow */ + DB_88F6180A_OE_VAL_HIGH, /* gppOutValHigh */ + 0, /* gppPolarityValLow */ + 0 /* gppPolarityValHigh */ +}; + +MV_BOARD_INFO* boardInfoTbl[] = { + &db88f6281AInfo, + &rd88f6281AInfo, + &db88f6192AInfo, + &rd88f6192AInfo, + &db88f6180AInfo, + &db88f6190AInfo, + &rd88f6190AInfo + }; + + diff --git a/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.h b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.h new file mode 100644 index 0000000..4be39b2 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/boardEnv/mvBoardEnvSpec.h @@ -0,0 +1,219 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoardEnvSpech +#define __INCmvBoardEnvSpech + +#include "mvSysHwConfig.h" + + +/* For future use */ +#define BD_ID_DATA_START_OFFS 0x0 +#define BD_DETECT_SEQ_OFFS 0x0 +#define BD_SYS_NUM_OFFS 0x4 +#define BD_NAME_OFFS 0x8 + +/* I2C bus addresses */ +#define MV_BOARD_CTRL_I2C_ADDR 0x0 /* Controller slave addr */ +#define MV_BOARD_CTRL_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_DIMM0_I2C_ADDR 0x56 +#define MV_BOARD_DIMM0_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_DIMM1_I2C_ADDR 0x54 +#define MV_BOARD_DIMM1_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_EEPROM_I2C_ADDR 0x51 +#define MV_BOARD_EEPROM_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_MAIN_EEPROM_I2C_ADDR 0x50 +#define MV_BOARD_MAIN_EEPROM_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_MUX_I2C_ADDR_ENTRY 0x2 +#define MV_BOARD_DIMM_I2C_CHANNEL 0x0 + +#define BOOT_FLASH_INDEX 0 +#define MAIN_FLASH_INDEX 1 + +#define BOARD_ETH_START_PORT_NUM 0 + +/* Supported clocks */ +#define MV_BOARD_TCLK_100MHZ 100000000 +#define MV_BOARD_TCLK_125MHZ 125000000 +#define MV_BOARD_TCLK_133MHZ 133333333 +#define MV_BOARD_TCLK_150MHZ 150000000 +#define MV_BOARD_TCLK_166MHZ 166666667 +#define MV_BOARD_TCLK_200MHZ 200000000 + +#define MV_BOARD_SYSCLK_100MHZ 100000000 +#define MV_BOARD_SYSCLK_125MHZ 125000000 +#define MV_BOARD_SYSCLK_133MHZ 133333333 +#define MV_BOARD_SYSCLK_150MHZ 150000000 +#define MV_BOARD_SYSCLK_166MHZ 166666667 +#define MV_BOARD_SYSCLK_200MHZ 200000000 +#define MV_BOARD_SYSCLK_233MHZ 233333333 +#define MV_BOARD_SYSCLK_250MHZ 250000000 +#define MV_BOARD_SYSCLK_267MHZ 266666667 +#define MV_BOARD_SYSCLK_300MHZ 300000000 +#define MV_BOARD_SYSCLK_333MHZ 333333334 +#define MV_BOARD_SYSCLK_400MHZ 400000000 + +#define MV_BOARD_REFCLK_25MHZ 25000000 + +/* Board specific */ +/* =============================== */ + +/* boards ID numbers */ + +#define BOARD_ID_BASE 0x0 + +/* New board ID numbers */ +#define DB_88F6281A_BP_ID (BOARD_ID_BASE) +#define DB_88F6281_BP_MLL_ID 1680 +#define RD_88F6281A_ID (BOARD_ID_BASE+0x1) +#define RD_88F6281_MLL_ID 1682 +#define DB_88F6192A_BP_ID (BOARD_ID_BASE+0x2) +#define RD_88F6192A_ID (BOARD_ID_BASE+0x3) +#define RD_88F6192_MLL_ID 1681 +#define DB_88F6180A_BP_ID (BOARD_ID_BASE+0x4) +#define DB_88F6190A_BP_ID (BOARD_ID_BASE+0x5) +#define RD_88F6190A_ID (BOARD_ID_BASE+0x6) +#define MV_MAX_BOARD_ID (RD_88F6190A_ID + 1) + +/* DB-88F6281A-BP */ +//Patch by QNAP:Fix GPP mapping +//Patch by QNAP:Fix OnBoard SATA LED and Ethernet LED +#if defined(TS119) || defined(TS219) || defined(TS118) || defined(TS218) +//#define DB_88F6281A_MPP0_7 0x21111111 +//#define DB_88F6281A_MPP8_15 0x11113311 +//#define DB_88F6281A_MPP16_23 0x00551111 +#define DB_88F6281A_MPP0_7 0x11112222 +#define DB_88F6281A_MPP8_15 0x03303311 +#define DB_88F6281A_MPP16_23 0x55551100 +/////////////////////////////////////////////////////// +#define DB_88F6281A_MPP24_31 0x00000000 +#define DB_88F6281A_MPP32_39 0x00000000 +#define DB_88F6281A_MPP40_47 0x00000000 +#define DB_88F6281A_MPP48_55 0x00000000 +#define DB_88F6281A_OE_LOW 0x0 +//#define DB_88F6281A_OE_HIGH (~(BIT5)) +#define DB_88F6281A_OE_HIGH (~0x0) +#define DB_88F6281A_OE_VAL_LOW 0x0 +#define DB_88F6281A_OE_VAL_HIGH 0x0 +#elif defined(TS419) +#define DB_88F6281A_MPP0_7 0x11112222 +#define DB_88F6281A_MPP8_15 0x43303311 +#define DB_88F6281A_MPP16_23 0x33330004 +#define DB_88F6281A_MPP24_31 0x33003333 +#define DB_88F6281A_MPP32_39 0x00000033 +#define DB_88F6281A_MPP40_47 0x00000000 +#define DB_88F6281A_MPP48_55 0x00000000 +#define DB_88F6281A_OE_LOW (~0x0) +#define DB_88F6281A_OE_HIGH (~0x0) +#define DB_88F6281A_OE_VAL_LOW 0x0 +#define DB_88F6281A_OE_VAL_HIGH 0x0 +#endif +/* RD-88F6281A */ +#define RD_88F6281A_MPP0_7 0x21111111 +#define RD_88F6281A_MPP8_15 0x11113311 +#define RD_88F6281A_MPP16_23 0x33331111 +#define RD_88F6281A_MPP24_31 0x33003333 +#define RD_88F6281A_MPP32_39 0x20440533 +#define RD_88F6281A_MPP40_47 0x22202222 +#define RD_88F6281A_MPP48_55 0x00000002 +#define RD_88F6281A_OE_LOW 0x0 +#define RD_88F6281A_OE_HIGH (~((BIT2) | (BIT12))) +#define RD_88F6281A_OE_VAL_LOW 0x0 +#define RD_88F6281A_OE_VAL_HIGH 0x1000 + +/* DB-88F6192A-BP */ +#define DB_88F6192A_MPP0_7 0x21111111 +#define DB_88F6192A_MPP8_15 0x11113311 +#define DB_88F6192A_MPP16_23 0x00501111 +#define DB_88F6192A_MPP24_31 0x00000000 +#define DB_88F6192A_MPP32_35 0x00000000 +#define DB_88F6192A_OE_LOW (~(BIT20)) +#define DB_88F6192A_OE_HIGH 0x0 +#define DB_88F6192A_OE_VAL_LOW 0x0 +#define DB_88F6192A_OE_VAL_HIGH 0x0 + +/* RD-88F6192A */ +#define RD_88F6192A_MPP0_7 0x01222222 +#define RD_88F6192A_MPP8_15 0x00000011 +#define RD_88F6192A_MPP16_23 0x05550000 +#define RD_88F6192A_MPP24_31 0x0 +#define RD_88F6192A_MPP32_35 0x0 +#define RD_88F6192A_OE_LOW (~(BIT10 | BIT15 | BIT16 | BIT17 | BIT28 | BIT29)) +#define RD_88F6192A_OE_HIGH (~(BIT3)) +#define RD_88F6192A_OE_VAL_LOW 0x18400 +#define RD_88F6192A_OE_VAL_HIGH 0x8 + +/* DB-88F6180A-BP */ +#define DB_88F6180A_MPP0_7 0x21111111 +#define DB_88F6180A_MPP8_15 0x11113311 +#define DB_88F6180A_MPP16_19 0x00001111 +#define DB_88F6180A_MPP35_39 0x4444c000 +#define DB_88F6180A_MPP40_44 0x00044444 +#define DB_88F6180A_OE_LOW 0x0 +#define DB_88F6180A_OE_HIGH 0x0 +#define DB_88F6180A_OE_VAL_LOW 0x0 +#define DB_88F6180A_OE_VAL_HIGH 0x0 + +#endif /* __INCmvBoardEnvSpech */ diff --git a/board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.c b/board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.c new file mode 100644 index 0000000..3185fbc --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.c @@ -0,0 +1,319 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "cpu/mvCpu.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvRegs.h" +#include "ctrlEnv/sys/mvCpuIfRegs.h" + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* locals */ + +/******************************************************************************* +* mvCpuPclkGet - Get the CPU pClk (pipe clock) +* +* DESCRIPTION: +* This routine extract the CPU core clock. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in MHertz. +* +*******************************************************************************/ +/* 6180 have different clk reset sampling */ + +static MV_U32 mvCpu6180PclkGet(MV_VOID) +{ + MV_U32 tmpPClkRate=0; + MV_CPU_ARM_CLK cpu6180_ddr_l2_CLK[] = MV_CPU6180_DDR_L2_CLCK_TBL; + + tmpPClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET); + tmpPClkRate = tmpPClkRate & MSAR_CPUCLCK_MASK_6180; + tmpPClkRate = tmpPClkRate >> MSAR_CPUCLCK_OFFS_6180; + + tmpPClkRate = cpu6180_ddr_l2_CLK[tmpPClkRate].cpuClk; + + return tmpPClkRate; +} + + +MV_U32 mvCpuPclkGet(MV_VOID) +{ +#if defined(PCLCK_AUTO_DETECT) + MV_U32 tmpPClkRate=0; + MV_U32 cpuCLK[] = MV_CPU_CLCK_TBL; + + if(mvCtrlModelGet() == MV_6180_DEV_ID) + return mvCpu6180PclkGet(); + + tmpPClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET); + tmpPClkRate = MSAR_CPUCLCK_EXTRACT(tmpPClkRate); + tmpPClkRate = cpuCLK[tmpPClkRate]; + + return tmpPClkRate; +#else + return MV_DEFAULT_PCLK +#endif +} + +/******************************************************************************* +* mvCpuL2ClkGet - Get the CPU L2 (CPU bus clock) +* +* DESCRIPTION: +* This routine extract the CPU L2 clock. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +static MV_U32 mvCpu6180L2ClkGet(MV_VOID) +{ + MV_U32 L2ClkRate=0; + MV_CPU_ARM_CLK _cpu6180_ddr_l2_CLK[] = MV_CPU6180_DDR_L2_CLCK_TBL; + + L2ClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET); + L2ClkRate = L2ClkRate & MSAR_CPUCLCK_MASK_6180; + L2ClkRate = L2ClkRate >> MSAR_CPUCLCK_OFFS_6180; + + L2ClkRate = _cpu6180_ddr_l2_CLK[L2ClkRate].l2Clk; + + return L2ClkRate; + +} + +MV_U32 mvCpuL2ClkGet(MV_VOID) +{ +#ifdef L2CLK_AUTO_DETECT + MV_U32 L2ClkRate, tmp, pClkRate, indexL2Rtio; + MV_U32 L2Rtio[][2] = MV_L2_CLCK_RTIO_TBL; + + if(mvCtrlModelGet() == MV_6180_DEV_ID) + return mvCpu6180L2ClkGet(); + + pClkRate = mvCpuPclkGet(); + + tmp = MV_REG_READ(MPP_SAMPLE_AT_RESET); + indexL2Rtio = MSAR_L2CLCK_EXTRACT(tmp); + + L2ClkRate = ((pClkRate * L2Rtio[indexL2Rtio][1]) / L2Rtio[indexL2Rtio][0]); + + return L2ClkRate; +#else + return MV_BOARD_DEFAULT_L2CLK; +#endif +} + + +/******************************************************************************* +* mvCpuNameGet - Get CPU name +* +* DESCRIPTION: +* This function returns a string describing the CPU model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain board name string. Minimum size 32 chars. +* +* RETURN: +* None. +*******************************************************************************/ +MV_VOID mvCpuNameGet(char *pNameBuff) +{ + MV_U32 cpuModel; + + cpuModel = mvOsCpuPartGet(); + + /* The CPU module is indicated in the Processor Version Register (PVR) */ + switch(cpuModel) + { + case CPU_PART_MRVL131: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "Marvell Feroceon",mvOsCpuRevGet()); + break; + case CPU_PART_ARM926: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM926",mvOsCpuRevGet()); + break; + case CPU_PART_ARM946: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM946",mvOsCpuRevGet()); + break; + default: + mvOsSPrintf(pNameBuff,"??? (0x%04x) (Rev %d)",cpuModel,mvOsCpuRevGet()); + break; + } /* switch */ + + return; +} + +#if defined(MV88F6281) + +#define MV_PROC_STR_SIZE 50 + +static void mvCpuIfGetL2EccMode(MV_8 *buf) +{ + MV_U32 regVal = MV_REG_READ(CPU_L2_CONFIG_REG); + if (regVal & BIT2) + mvOsSPrintf(buf, "L2 ECC Enabled"); + else + mvOsSPrintf(buf, "L2 ECC Disabled"); +} + +static void mvCpuIfGetL2Mode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT22) + mvOsSPrintf(buf, "L2 Enabled"); + else + mvOsSPrintf(buf, "L2 Disabled"); +} + +static void mvCpuIfGetL2PrefetchMode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT24) + mvOsSPrintf(buf, "L2 Prefetch Disabled"); + else + mvOsSPrintf(buf, "L2 Prefetch Enabled"); +} + +static void mvCpuIfGetWriteAllocMode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT28) + mvOsSPrintf(buf, "Write Allocate Enabled"); + else + mvOsSPrintf(buf, "Write Allocate Disabled"); +} + +static void mvCpuIfGetCpuStreamMode(MV_8 *buf) +{ + MV_U32 regVal = 0; + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + if (regVal & BIT29) + mvOsSPrintf(buf, "CPU Streaming Enabled"); + else + mvOsSPrintf(buf, "CPU Streaming Disabled"); +} + +static void mvCpuIfPrintCpuRegs(void) +{ + MV_U32 regVal = 0; + + __asm volatile ("mrc p15, 1, %0, c15, c1, 0" : "=r" (regVal)); /* Read Marvell extra features register */ + mvOsPrintf("Extra Feature Reg = 0x%x\n",regVal); + + __asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (regVal)); /* Read Control register */ + mvOsPrintf("Control Reg = 0x%x\n",regVal); + + __asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (regVal)); /* Read ID Code register */ + mvOsPrintf("ID Code Reg = 0x%x\n",regVal); + + __asm volatile ("mrc p15, 0, %0, c0, c0, 1" : "=r" (regVal)); /* Read Cache Type register */ + mvOsPrintf("Cache Type Reg = 0x%x\n",regVal); + +} + +MV_U32 mvCpuIfPrintSystemConfig(MV_8 *buffer, MV_U32 index) +{ + MV_U32 count = 0; + + MV_8 L2_ECC_str[MV_PROC_STR_SIZE]; + MV_8 L2_En_str[MV_PROC_STR_SIZE]; + MV_8 L2_Prefetch_str[MV_PROC_STR_SIZE]; + MV_8 Write_Alloc_str[MV_PROC_STR_SIZE]; + MV_8 Cpu_Stream_str[MV_PROC_STR_SIZE]; + + mvCpuIfGetL2Mode(L2_En_str); + mvCpuIfGetL2EccMode(L2_ECC_str); + mvCpuIfGetL2PrefetchMode(L2_Prefetch_str); + mvCpuIfGetWriteAllocMode(Write_Alloc_str); + mvCpuIfGetCpuStreamMode(Cpu_Stream_str); + mvCpuIfPrintCpuRegs(); + + count += mvOsSPrintf(buffer + count + index, "%s\n", L2_En_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", L2_ECC_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", L2_Prefetch_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", Write_Alloc_str); + count += mvOsSPrintf(buffer + count + index, "%s\n", Cpu_Stream_str); + return count; +} + +#endif + + diff --git a/board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.h b/board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.h new file mode 100644 index 0000000..4f9ef06 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/cpu/mvCpu.h @@ -0,0 +1,103 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuh +#define __INCmvCpuh + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + +/* defines */ + +#define CPU_PART_MRVL131 0x131 +#define CPU_PART_ARM926 0x926 +#define CPU_PART_ARM946 0x946 +#define MV_CPU_ARM_CLK_ELM_SIZE 12 +#define MV_CPU_ARM_CLK_RATIO_OFF 8 +#define MV_CPU_ARM_CLK_DDR_OFF 4 + +#ifndef MV_ASMLANGUAGE +typedef struct _mvCpuArmClk +{ + MV_U32 cpuClk; /* CPU clock in MHz */ + MV_U32 ddrClk; /* DDR clock in MHz */ + MV_U32 l2Clk; /* CPU DDR clock ratio */ + +}MV_CPU_ARM_CLK; + +MV_U32 mvCpuPclkGet(MV_VOID); +MV_VOID mvCpuNameGet(char *pNameBuff); + +MV_U32 mvCpuL2ClkGet(MV_VOID); + +#if defined(MV88F6281) +MV_U32 mvCpuIfPrintSystemConfig(MV_8 *buffer, MV_U32 index); +#endif + +#endif + + +#endif /* __INCmvCpuh */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c new file mode 100644 index 0000000..6ab375c --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c @@ -0,0 +1,296 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvCtrlEnvAddrDec.h - Marvell controller address decode library +* +* DESCRIPTION: +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +/* includes */ +#include "ctrlEnv/mvCtrlEnvAddrDec.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" +#include "ddr2/mvDramIfRegs.h" +#include "pex/mvPexRegs.h" + +#define MV_DEBUG + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* Default Attributes array */ +MV_TARGET_ATTRIB mvTargetDefaultsArray[] = TARGETS_DEF_ARRAY; +extern MV_TARGET sampleAtResetTargetArray[]; +/* Dram\AHBToMbus\PEX share regsiter */ + +#define CTRL_DEC_BASE_OFFS 16 +#define CTRL_DEC_BASE_MASK (0xffff << CTRL_DEC_BASE_OFFS) +#define CTRL_DEC_BASE_ALIGNMENT 0x10000 + +#define CTRL_DEC_SIZE_OFFS 16 +#define CTRL_DEC_SIZE_MASK (0xffff << CTRL_DEC_SIZE_OFFS) +#define CTRL_DEC_SIZE_ALIGNMENT 0x10000 + +#define CTRL_DEC_WIN_EN BIT0 + + + +/******************************************************************************* +* mvCtrlAddrDecToReg - Get address decode register format values +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, MV_DEC_REGS *pAddrDecRegs) +{ + + MV_U32 baseToReg=0 , sizeToReg=0; + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->baseLow & CTRL_DEC_BASE_MASK; + + /* Write to address decode Base Address Register */ + pAddrDecRegs->baseReg &= ~CTRL_DEC_BASE_MASK; + pAddrDecRegs->baseReg |= baseToReg; + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->size, CTRL_DEC_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + return MV_BAD_PARAM; + } + + /* set size */ + pAddrDecRegs->sizeReg &= ~CTRL_DEC_SIZE_MASK; + pAddrDecRegs->sizeReg |= (sizeToReg << CTRL_DEC_SIZE_OFFS); + + + return MV_OK; + +} + +/******************************************************************************* +* mvCtrlRegToAddrDec - Extract address decode struct from registers. +* +* DESCRIPTION: +* This function extract address decode struct from address decode +* registers given as parameters. +* +* INPUT: +* pAddrDecRegs - Address decode register struct. +* +* OUTPUT: +* pAddrDecWin - Target window data structure. +* +* RETURN: +* MV_BAD_PARAM if address decode registers data is invalid. +* +*******************************************************************************/ +MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 sizeRegVal; + + sizeRegVal = (pAddrDecRegs->sizeReg & CTRL_DEC_SIZE_MASK) >> + CTRL_DEC_SIZE_OFFS; + + pAddrDecWin->size = ctrlRegToSize(sizeRegVal, CTRL_DEC_SIZE_ALIGNMENT); + + + /* Extract base address */ + /* Base register [31:16] ==> baseLow[31:16] */ + pAddrDecWin->baseLow = pAddrDecRegs->baseReg & CTRL_DEC_BASE_MASK; + + pAddrDecWin->baseHigh = 0; + + return MV_OK; + +} + +/******************************************************************************* +* mvCtrlAttribGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ + +MV_STATUS mvCtrlAttribGet(MV_TARGET target, + MV_TARGET_ATTRIB *targetAttrib) +{ + + targetAttrib->attrib = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].attrib; + targetAttrib->targetId = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].targetId; + + return MV_OK; + +} + +/******************************************************************************* +* mvCtrlGetAttrib - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib) +{ + MV_TARGET target; + MV_TARGET x; + for (target = SDRAM_CS0; target < MAX_TARGETS ; target ++) + { + x = MV_CHANGE_BOOT_CS(target); + if ((mvTargetDefaultsArray[x].attrib == targetAttrib->attrib) && + (mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].targetId == targetAttrib->targetId)) + { + /* found it */ + break; + } + } + + return target; +} + +MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, + MV_DEC_WIN_PARAMS *pWinParam) +{ + MV_U32 baseToReg=0, sizeToReg=0; + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->addrWin.baseLow & CTRL_DEC_BASE_MASK; + + /* Write to address decode Base Address Register */ + pWinParam->baseAddr &= ~CTRL_DEC_BASE_MASK; + pWinParam->baseAddr |= baseToReg; + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, CTRL_DEC_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvCtrlAddrDecToParams: ERR. ctrlSizeToReg failed.\n"); + return MV_BAD_PARAM; + } + pWinParam->size = sizeToReg; + + pWinParam->attrib = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].attrib; + pWinParam->targetId = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].targetId; + + return MV_OK; +} + +MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam, + MV_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttrib; + + pAddrDecWin->addrWin.baseLow = pWinParam->baseAddr; + + /* Upper 32bit address base is supported under PCI High Address remap */ + pAddrDecWin->addrWin.baseHigh = 0; + + /* Prepare sizeReg to ctrlRegToSize function */ + pAddrDecWin->addrWin.size = ctrlRegToSize(pWinParam->size, CTRL_DEC_SIZE_ALIGNMENT); + + if (-1 == pAddrDecWin->addrWin.size) + { + DB(mvOsPrintf("mvCtrlParamsToAddrDec: ERR. ctrlRegToSize failed.\n")); + return MV_BAD_PARAM; + } + targetAttrib.targetId = pWinParam->targetId; + targetAttrib.attrib = pWinParam->attrib; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + return MV_OK; +} + + + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h new file mode 100644 index 0000000..946737f --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h @@ -0,0 +1,203 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCtrlEnvAddrDech +#define __INCmvCtrlEnvAddrDech + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvRegs.h" + + +/* defines */ +/* DUnit attributes */ +#define ATMWCR_WIN_DUNIT_CS0_OFFS 0 +#define ATMWCR_WIN_DUNIT_CS0_MASK BIT0 +#define ATMWCR_WIN_DUNIT_CS0_REQ (0 << ATMWCR_WIN_DUNIT_CS0_OFFS) + +#define ATMWCR_WIN_DUNIT_CS1_OFFS 1 +#define ATMWCR_WIN_DUNIT_CS1_MASK BIT1 +#define ATMWCR_WIN_DUNIT_CS1_REQ (0 << ATMWCR_WIN_DUNIT_CS1_OFFS) + +#define ATMWCR_WIN_DUNIT_CS2_OFFS 2 +#define ATMWCR_WIN_DUNIT_CS2_MASK BIT2 +#define ATMWCR_WIN_DUNIT_CS2_REQ (0 << ATMWCR_WIN_DUNIT_CS2_OFFS) + +#define ATMWCR_WIN_DUNIT_CS3_OFFS 3 +#define ATMWCR_WIN_DUNIT_CS3_MASK BIT3 +#define ATMWCR_WIN_DUNIT_CS3_REQ (0 << ATMWCR_WIN_DUNIT_CS3_OFFS) + +/* RUnit (Device) attributes */ +#define ATMWCR_WIN_RUNIT_DEVCS0_OFFS 0 +#define ATMWCR_WIN_RUNIT_DEVCS0_MASK BIT0 +#define ATMWCR_WIN_RUNIT_DEVCS0_REQ (0 << ATMWCR_WIN_RUNIT_DEVCS0_OFFS) + +#define ATMWCR_WIN_RUNIT_DEVCS1_OFFS 1 +#define ATMWCR_WIN_RUNIT_DEVCS1_MASK BIT1 +#define ATMWCR_WIN_RUNIT_DEVCS1_REQ (0 << ATMWCR_WIN_RUNIT_DEVCS1_OFFS) + +#define ATMWCR_WIN_RUNIT_DEVCS2_OFFS 2 +#define ATMWCR_WIN_RUNIT_DEVCS2_MASK BIT2 +#define ATMWCR_WIN_RUNIT_DEVCS2_REQ (0 << ATMWCR_WIN_RUNIT_DEVCS2_OFFS) + +#define ATMWCR_WIN_RUNIT_BOOTCS_OFFS 4 +#define ATMWCR_WIN_RUNIT_BOOTCS_MASK BIT4 +#define ATMWCR_WIN_RUNIT_BOOTCS_REQ (0 << ATMWCR_WIN_RUNIT_BOOTCS_OFFS) + +/* LMaster (PCI) attributes */ +#define ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS 0 +#define ATMWCR_WIN_LUNIT_BYTE_SWP_MASK BIT0 +#define ATMWCR_WIN_LUNIT_BYTE_SWP (0 << ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS) +#define ATMWCR_WIN_LUNIT_BYTE_NO_SWP (1 << ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS) + + +#define ATMWCR_WIN_LUNIT_WORD_SWP_OFFS 1 +#define ATMWCR_WIN_LUNIT_WORD_SWP_MASK BIT1 +#define ATMWCR_WIN_LUNIT_WORD_SWP (0 << ATMWCR_WIN_LUNIT_WORD_SWP_OFFS) +#define ATMWCR_WIN_LUNIT_WORD_NO_SWP (1 << ATMWCR_WIN_LUNIT_WORD_SWP_OFFS) + +#define ATMWCR_WIN_LUNIT_NO_SNOOP BIT2 + +#define ATMWCR_WIN_LUNIT_TYPE_OFFS 3 +#define ATMWCR_WIN_LUNIT_TYPE_MASK BIT3 +#define ATMWCR_WIN_LUNIT_TYPE_IO (0 << ATMWCR_WIN_LUNIT_TYPE_OFFS) +#define ATMWCR_WIN_LUNIT_TYPE_MEM (1 << ATMWCR_WIN_LUNIT_TYPE_OFFS) + +#define ATMWCR_WIN_LUNIT_FORCE64_OFFS 4 +#define ATMWCR_WIN_LUNIT_FORCE64_MASK BIT4 +#define ATMWCR_WIN_LUNIT_FORCE64 (0 << ATMWCR_WIN_LUNIT_FORCE64_OFFS) + +#define ATMWCR_WIN_LUNIT_ORDERING_OFFS 6 +#define ATMWCR_WIN_LUNIT_ORDERING_MASK BIT6 +#define ATMWCR_WIN_LUNIT_ORDERING (1 << ATMWCR_WIN_LUNIT_FORCE64_OFFS) + +/* PEX Attributes */ +#define ATMWCR_WIN_PEX_TYPE_OFFS 3 +#define ATMWCR_WIN_PEX_TYPE_MASK BIT3 +#define ATMWCR_WIN_PEX_TYPE_IO (0 << ATMWCR_WIN_PEX_TYPE_OFFS) +#define ATMWCR_WIN_PEX_TYPE_MEM (1 << ATMWCR_WIN_PEX_TYPE_OFFS) + +/* typedefs */ + +/* Unsupported attributes for address decode: */ +/* 2) PCI0/1_REQ64n control */ + +typedef struct _mvDecRegs +{ + MV_U32 baseReg; + MV_U32 baseRegHigh; + MV_U32 sizeReg; + +}MV_DEC_REGS; + +typedef struct _mvTargetAttrib +{ + MV_U8 attrib; /* chip select attributes */ + MV_TARGET_ID targetId; /* Target Id of this MV_TARGET */ + +}MV_TARGET_ATTRIB; + + +/* This structure describes address decode window */ +typedef struct _mvDecWin +{ + MV_TARGET target; /* Target for addr decode window */ + MV_ADDR_WIN addrWin; /* Address window of target */ + MV_BOOL enable; /* Window enable/disable */ +}MV_DEC_WIN; + +typedef struct _mvDecWinParams +{ + MV_TARGET_ID targetId; /* Target ID field */ + MV_U8 attrib; /* Attribute field */ + MV_U32 baseAddr; /* Base address in register format */ + MV_U32 size; /* Size in register format */ +}MV_DEC_WIN_PARAMS; + + +/* mvCtrlEnvAddrDec API list */ + +MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, + MV_DEC_REGS *pAddrDecRegs); + +MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs, + MV_ADDR_WIN *pAddrDecWin); + +MV_STATUS mvCtrlAttribGet(MV_TARGET target, + MV_TARGET_ATTRIB *targetAttrib); + +MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib); + + +MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, + MV_DEC_WIN_PARAMS *pWinParam); + +MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam, + MV_DEC_WIN *pAddrDecWin); + + + + +#endif /* __INCmvCtrlEnvAddrDech */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAsm.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAsm.h new file mode 100644 index 0000000..6f6367a --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvAsm.h @@ -0,0 +1,98 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCtrlEnvAsmh +#define __INCmvCtrlEnvAsmh +#include "pex/mvPexRegs.h" + +#define CHIP_BOND_REG 0x10034 +#define PCKG_OPT_MASK_AS #3 +#define PXCCARI_REVID_MASK_AS #PXCCARI_REVID_MASK + +/* Read device ID into toReg bits 15:0 from 0xd0000000 */ +/* defines */ +#define MV_DV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + MV_DV_REG_READ_ASM(toReg, tmpReg, CHIP_BOND_REG);\ + and toReg, toReg, PCKG_OPT_MASK_AS /* Mask for package ID */ + +/* Read device ID into toReg bits 15:0 from 0xf1000000*/ +#define MV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + MV_REG_READ_ASM(toReg, tmpReg, CHIP_BOND_REG);\ + and toReg, toReg, PCKG_OPT_MASK_AS /* Mask for package ID */ + +/* Read Revision into toReg bits 7:0 0xd0000000*/ +#define MV_DV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + /* Read device revision */ \ + MV_DV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_CLASS_CODE_AND_REVISION_ID));\ + and toReg, toReg, PXCCARI_REVID_MASK_AS /* Mask for calss ID */ + +/* Read Revision into toReg bits 7:0 0xf1000000*/ +#define MV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + /* Read device revision */ \ + MV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_CLASS_CODE_AND_REVISION_ID));\ + and toReg, toReg, PXCCARI_REVID_MASK_AS /* Mask for calss ID */ + + +#endif /* __INCmvCtrlEnvAsmh */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.c new file mode 100644 index 0000000..a0b8cc6 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.c @@ -0,0 +1,1807 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "mvCommon.h" +#include "mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" + +#if defined(MV_INCLUDE_PEX) +#include "pex/mvPex.h" +#include "ctrlEnv/sys/mvSysPex.h" +#endif + +#if defined(MV_INCLUDE_GIG_ETH) +#include "ctrlEnv/sys/mvSysGbe.h" +#endif + +#if defined(MV_INCLUDE_XOR) +#include "ctrlEnv/sys/mvSysXor.h" +#endif + +#if defined(MV_INCLUDE_SATA) +#include "ctrlEnv/sys/mvSysSata.h" +#endif + +#if defined(MV_INCLUDE_USB) +#include "ctrlEnv/sys/mvSysUsb.h" +#endif + +#if defined(MV_INCLUDE_AUDIO) +#include "ctrlEnv/sys/mvSysAudio.h" +#endif + +#if defined(MV_INCLUDE_CESA) +#include "ctrlEnv/sys/mvSysCesa.h" +#endif + +#if defined(MV_INCLUDE_TS) +#include "ctrlEnv/sys/mvSysTs.h" +#endif + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/******************************************************************************* +* mvCtrlEnvInit - Initialize Marvell controller environment. +* +* DESCRIPTION: +* This function get environment information and initialize controller +* internal/external environment. For example +* 1) MPP settings according to board MPP macros. +* NOTE: It is the user responsibility to shut down all DMA channels +* in device and disable controller sub units interrupts during +* boot process. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvCtrlEnvInit(MV_VOID) +{ + MV_U32 mppGroup; + MV_U32 devId; + MV_U32 boardId; + MV_U32 i; + MV_U32 maxMppGrp = 1; + MV_U32 mppVal = 0; + MV_U32 bootVal = 0; + MV_U32 mppGroupType = 0; + MV_U32 mppGroup1[][3] = MPP_GROUP_1_TYPE; + MV_U32 mppGroup2[][3] = MPP_GROUP_2_TYPE; + + devId = mvCtrlModelGet(); + boardId= mvBoardIdGet(); + + switch(devId){ + case MV_6281_DEV_ID: + maxMppGrp = MV_6281_MPP_MAX_GROUP; + break; + case MV_6192_DEV_ID: + maxMppGrp = MV_6192_MPP_MAX_GROUP; + break; + case MV_6190_DEV_ID: + maxMppGrp = MV_6190_MPP_MAX_GROUP; + break; + case MV_6180_DEV_ID: + maxMppGrp = MV_6180_MPP_MAX_GROUP; + break; + } + + /* MPP Init */ + /* We split mpp init to 3 phases: + * 1. We init mpp[19:0] from the board info. mpp[23:20] will be over write + * in phase 2. + * 2. We detect the mpp group type and according the mpp values [35:20]. + * 3. We detect the mpp group type and according the mpp values [49:36]. + */ + /* Mpp phase 1 mpp[19:0] */ + /* Read MPP group from board level and assign to MPP register */ + for (mppGroup = 0; mppGroup < 3; mppGroup++) + { + mppVal = mvBoardMppGet(mppGroup); + if (mppGroup == 0) + { + bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup)); + if (mvCtrlIsBootFromSPI()) + { + mppVal &= ~0xffff; + bootVal &= 0xffff; + mppVal |= bootVal; + } + else if (mvCtrlIsBootFromSPIUseNAND()) + { + mppVal &= ~0xf0000000; + bootVal &= 0xf0000000; + mppVal |= bootVal; + } + else if (mvCtrlIsBootFromNAND()) + { + mppVal &= ~0xffffff; + bootVal &= 0xffffff; + mppVal |= bootVal; + } + } + + if (mppGroup == 2) + { + bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup)); + if (mvCtrlIsBootFromNAND()) + { + mppVal &= ~0xff00; + bootVal &= 0xff00; + mppVal |= bootVal; + } + } + + MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal); + } + + /* Identify MPPs group */ + mvBoardMppGroupIdUpdate(); + + /* Update MPPs mux relevent only on Marvell DB */ + if ((boardId == DB_88F6281A_BP_ID) || + (boardId == DB_88F6180A_BP_ID)) + mvBoardMppMuxSet(); + + mppGroupType = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_1); + + /* Mpp phase 2 */ + /* Read MPP group from board level and assign to MPP register */ + if (devId != MV_6180_DEV_ID) + { + i = 0; + for (mppGroup = 2; mppGroup < 5; mppGroup++) + { + if ((mppGroupType == MV_BOARD_OTHER) || + (boardId == RD_88F6281A_ID) || + (boardId == RD_88F6192A_ID) || + (boardId == RD_88F6190A_ID)) + mppVal = mvBoardMppGet(mppGroup); + else + { + mppVal = mppGroup1[mppGroupType][i]; + i++; + } + + /* Group 2 is shared mpp[23:16] */ + if (mppGroup == 2) + { + bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup)); + mppVal &= ~0xffff; + bootVal &= 0xffff; + mppVal |= bootVal; + } + + MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal); + } + } + + if ((devId == MV_6192_DEV_ID) || (devId == MV_6190_DEV_ID)) + return MV_OK; + + /* Mpp phase 3 */ + mppGroupType = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_2); + + /* Read MPP group from board level and assign to MPP register */ + i = 0; + for (mppGroup = 4; mppGroup < 7; mppGroup++) + { + if ((mppGroupType == MV_BOARD_OTHER) || + (boardId == RD_88F6281A_ID)) + mppVal = mvBoardMppGet(mppGroup); + else + { + mppVal = mppGroup2[mppGroupType][i]; + i++; + } + + /* Group 4 is sherd mpp[35:32] */ + if (mppGroup == 4) + { + bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup)); + mppVal &= ~0xffff; + bootVal &= 0xffff; + mppVal |= bootVal; + } + + MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal); + } + + return MV_OK; +} + +/******************************************************************************* +* mvCtrlMppRegGet - return reg address of mpp group +* +* DESCRIPTION: +* +* INPUT: +* mppGroup - MPP group. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_U32 - Register address. +* +*******************************************************************************/ +MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup) +{ + MV_U32 ret; + + switch(mppGroup){ + case (0): ret = MPP_CONTROL_REG0; + break; + case (1): ret = MPP_CONTROL_REG1; + break; + case (2): ret = MPP_CONTROL_REG2; + break; + case (3): ret = MPP_CONTROL_REG3; + break; + case (4): ret = MPP_CONTROL_REG4; + break; + case (5): ret = MPP_CONTROL_REG5; + break; + case (6): ret = MPP_CONTROL_REG6; + break; + default: ret = MPP_CONTROL_REG0; + break; + } + return ret; +} +#if defined(MV_INCLUDE_PEX) +/******************************************************************************* +* mvCtrlPexMaxIfGet - Get Marvell controller number of PEX interfaces. +* +* DESCRIPTION: +* This function returns Marvell controller number of PEX interfaces. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of PEX interfaces. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlPexMaxIfGet(MV_VOID) +{ + + return MV_PEX_MAX_IF; +} +#endif + +#if defined(MV_INCLUDE_GIG_ETH) +/******************************************************************************* +* mvCtrlEthMaxPortGet - Get Marvell controller number of etherent ports. +* +* DESCRIPTION: +* This function returns Marvell controller number of etherent port. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of etherent port. +* +*******************************************************************************/ +MV_U32 mvCtrlEthMaxPortGet(MV_VOID) +{ + MV_U32 devId; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + return MV_6281_ETH_MAX_PORTS; + break; + case MV_6192_DEV_ID: + return MV_6192_ETH_MAX_PORTS; + break; + case MV_6190_DEV_ID: + return MV_6190_ETH_MAX_PORTS; + break; + case MV_6180_DEV_ID: + return MV_6180_ETH_MAX_PORTS; + break; + } + return 0; + +} +#endif + +#if defined(MV_INCLUDE_XOR) +/******************************************************************************* +* mvCtrlXorMaxChanGet - Get Marvell controller number of XOR channels. +* +* DESCRIPTION: +* This function returns Marvell controller number of XOR channels. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of XOR channels. +* +*******************************************************************************/ +MV_U32 mvCtrlXorMaxChanGet(MV_VOID) +{ + return MV_XOR_MAX_CHAN; +} +#endif + +#if defined(MV_INCLUDE_USB) +/******************************************************************************* +* mvCtrlUsbHostMaxGet - Get number of Marvell Usb controllers +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* returns number of Marvell USB controllers. +* +*******************************************************************************/ +MV_U32 mvCtrlUsbMaxGet(void) +{ + return MV_USB_MAX_CHAN; +} +#endif + + +#if defined(MV_INCLUDE_NAND) +/******************************************************************************* +* mvCtrlNandSupport - Return if this controller has integrated NAND flash support +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if NAND is supported and MV_FALSE otherwise +* +*******************************************************************************/ +MV_U32 mvCtrlNandSupport(MV_VOID) +{ + MV_U32 devId; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + return MV_6281_NAND; + break; + case MV_6192_DEV_ID: + return MV_6192_NAND; + break; + case MV_6190_DEV_ID: + return MV_6190_NAND; + break; + case MV_6180_DEV_ID: + return MV_6180_NAND; + break; + } + return 0; + +} +#endif + +#if defined(MV_INCLUDE_SDIO) +/******************************************************************************* +* mvCtrlSdioSupport - Return if this controller has integrated SDIO flash support +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if SDIO is supported and MV_FALSE otherwise +* +*******************************************************************************/ +MV_U32 mvCtrlSdioSupport(MV_VOID) +{ + MV_U32 devId; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + return MV_6281_SDIO; + break; + case MV_6192_DEV_ID: + return MV_6192_SDIO; + break; + case MV_6190_DEV_ID: + return MV_6190_SDIO; + break; + case MV_6180_DEV_ID: + return MV_6180_SDIO; + break; + } + return 0; + +} +#endif + +#if defined(MV_INCLUDE_TS) +/******************************************************************************* +* mvCtrlTsSupport - Return if this controller has integrated TS flash support +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if TS is supported and MV_FALSE otherwise +* +*******************************************************************************/ +MV_U32 mvCtrlTsSupport(MV_VOID) +{ + MV_U32 devId; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + return MV_6281_TS; + break; + case MV_6192_DEV_ID: + return MV_6192_TS; + break; + case MV_6190_DEV_ID: + return MV_6190_TS; + break; + case MV_6180_DEV_ID: + return MV_6180_TS; + break; + } + return 0; +} +#endif + +#if defined(MV_INCLUDE_AUDIO) +/******************************************************************************* +* mvCtrlAudioSupport - Return if this controller has integrated AUDIO flash support +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if AUDIO is supported and MV_FALSE otherwise +* +*******************************************************************************/ +MV_U32 mvCtrlAudioSupport(MV_VOID) +{ + MV_U32 devId; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + return MV_6281_AUDIO; + break; + case MV_6192_DEV_ID: + return MV_6192_AUDIO; + break; + case MV_6190_DEV_ID: + return MV_6190_AUDIO; + break; + case MV_6180_DEV_ID: + return MV_6180_AUDIO; + break; + } + return 0; + +} +#endif + +#if defined(MV_INCLUDE_TDM) +/******************************************************************************* +* mvCtrlTdmSupport - Return if this controller has integrated TDM flash support +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if TDM is supported and MV_FALSE otherwise +* +*******************************************************************************/ +MV_U32 mvCtrlTdmSupport(MV_VOID) +{ + MV_U32 devId; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + return MV_6281_TDM; + break; + case MV_6192_DEV_ID: + return MV_6192_TDM; + break; + case MV_6190_DEV_ID: + return MV_6190_TDM; + break; + case MV_6180_DEV_ID: + return MV_6180_TDM; + break; + } + return 0; + +} +#endif + +/******************************************************************************* +* mvCtrlModelGet - Get Marvell controller device model (Id) +* +* DESCRIPTION: +* This function returns 16bit describing the device model (ID) as defined +* in PCI Device and Vendor ID configuration register offset 0x0. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit desscribing Marvell controller ID +* +*******************************************************************************/ +MV_U16 mvCtrlModelGet(MV_VOID) +{ + MV_U32 devId; + + devId = MV_REG_READ(CHIP_BOND_REG); + devId &= PCKG_OPT_MASK; + + switch(devId){ + case 2: + return MV_6281_DEV_ID; + break; + case 1: + if (((MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID))& 0xffff0000) >> 16) + == MV_6190_DEV_ID) + return MV_6190_DEV_ID; + else + return MV_6192_DEV_ID; + break; + case 0: + return MV_6180_DEV_ID; + break; + } + + return 0; +} +/******************************************************************************* +* mvCtrlRevGet - Get Marvell controller device revision number +* +* DESCRIPTION: +* This function returns 8bit describing the device revision as defined +* in PCI Express Class Code and Revision ID Register. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 8bit desscribing Marvell controller revision number +* +*******************************************************************************/ +MV_U8 mvCtrlRevGet(MV_VOID) +{ + MV_U8 revNum; +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + /* Check pex power state */ + MV_U32 pexPower; + pexPower = mvCtrlPwrClckGet(PEX_UNIT_ID,0); + if (pexPower == MV_FALSE) + mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_TRUE); +#endif + revNum = (MV_U8)MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0,PCI_CLASS_CODE_AND_REVISION_ID)); +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + /* Return to power off state */ + if (pexPower == MV_FALSE) + mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_FALSE); +#endif + return ((revNum & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS); +} + +/******************************************************************************* +* mvCtrlNameGet - Get Marvell controller name +* +* DESCRIPTION: +* This function returns a string describing the device model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain device name string. Minimum size 30 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ +MV_STATUS mvCtrlNameGet(char *pNameBuff) +{ + mvOsSPrintf (pNameBuff, "%s%x Rev %d", SOC_NAME_PREFIX, + mvCtrlModelGet(), mvCtrlRevGet()); + + return MV_OK; +} + +/******************************************************************************* +* mvCtrlModelRevGet - Get Controller Model (Device ID) and Revision +* +* DESCRIPTION: +* This function returns 32bit value describing both Device ID and Revision +* as defined in PCI Express Device and Vendor ID Register and device revision +* as defined in PCI Express Class Code and Revision ID Register. + +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing both controller device ID and revision number +* +*******************************************************************************/ +MV_U32 mvCtrlModelRevGet(MV_VOID) +{ + return ((mvCtrlModelGet() << 16) | mvCtrlRevGet()); +} + +/******************************************************************************* +* mvCtrlModelRevNameGet - Get Marvell controller name +* +* DESCRIPTION: +* This function returns a string describing the device model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain device name string. Minimum size 30 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ + +MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff) +{ + + switch (mvCtrlModelRevGet()) + { + case MV_6281_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6281_A0_NAME); + break; + case MV_6192_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6192_A0_NAME); + break; + case MV_6180_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6180_A0_NAME); + break; + case MV_6190_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6190_A0_NAME); + break; + default: + mvCtrlNameGet(pNameBuff); + break; + } + + return MV_OK; +} + + +/******************************************************************************* +* ctrlWinOverlapTest - Test address windows for overlaping. +* +* DESCRIPTION: +* This function checks the given two address windows for overlaping. +* +* INPUT: +* pAddrWin1 - Address window 1. +* pAddrWin2 - Address window 2. +* +* OUTPUT: +* None. +* +* RETURN: +* +* MV_TRUE if address window overlaps, MV_FALSE otherwise. +*******************************************************************************/ +MV_STATUS ctrlWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2) +{ + MV_U32 winBase1, winBase2; + MV_U32 winTop1, winTop2; + + /* check if we have overflow than 4G*/ + if (((0xffffffff - pAddrWin1->baseLow) < pAddrWin1->size-1)|| + ((0xffffffff - pAddrWin2->baseLow) < pAddrWin2->size-1)) + { + return MV_TRUE; + } + + winBase1 = pAddrWin1->baseLow; + winBase2 = pAddrWin2->baseLow; + winTop1 = winBase1 + pAddrWin1->size-1; + winTop2 = winBase2 + pAddrWin2->size-1; + + + if (((winBase1 <= winTop2 ) && ( winTop2 <= winTop1)) || + ((winBase1 <= winBase2) && (winBase2 <= winTop1))) + { + return MV_TRUE; + } + else + { + return MV_FALSE; + } +} + +/******************************************************************************* +* ctrlWinWithinWinTest - Test address windows for overlaping. +* +* DESCRIPTION: +* This function checks the given win1 boundries is within +* win2 boundries. +* +* INPUT: +* pAddrWin1 - Address window 1. +* pAddrWin2 - Address window 2. +* +* OUTPUT: +* None. +* +* RETURN: +* +* MV_TRUE if found win1 inside win2, MV_FALSE otherwise. +*******************************************************************************/ +MV_STATUS ctrlWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2) +{ + MV_U32 winBase1, winBase2; + MV_U32 winTop1, winTop2; + + winBase1 = pAddrWin1->baseLow; + winBase2 = pAddrWin2->baseLow; + winTop1 = winBase1 + pAddrWin1->size -1; + winTop2 = winBase2 + pAddrWin2->size -1; + + if (((winBase1 >= winBase2 ) && ( winBase1 <= winTop2)) || + ((winTop1 >= winBase2) && (winTop1 <= winTop2))) + { + return MV_TRUE; + } + else + { + return MV_FALSE; + } +} + +static const char* cntrlName[] = TARGETS_NAME_ARRAY; + +/******************************************************************************* +* mvCtrlTargetNameGet - Get Marvell controller target name +* +* DESCRIPTION: +* This function convert the trget enumeration to string. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Target name (const MV_8 *) +*******************************************************************************/ +const MV_8* mvCtrlTargetNameGet( MV_TARGET target ) +{ + + if (target >= MAX_TARGETS) + { + return "target unknown"; + } + + return cntrlName[target]; +} + +/******************************************************************************* +* mvCtrlAddrDecShow - Print the Controller units address decode map. +* +* DESCRIPTION: +* This function the Controller units address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvCtrlAddrDecShow(MV_VOID) +{ + mvCpuIfAddDecShow(); + mvAhbToMbusAddDecShow(); +#if defined(MV_INCLUDE_PEX) + mvPexAddrDecShow(); +#endif +#if defined(MV_INCLUDE_USB) + mvUsbAddrDecShow(); +#endif +#if defined(MV_INCLUDE_GIG_ETH) + mvEthAddrDecShow(); +#endif +#if defined(MV_INCLUDE_XOR) + mvXorAddrDecShow(); +#endif +#if defined(MV_INCLUDE_SATA) + mvSataAddrDecShow(); +#endif +#if defined(MV_INCLUDE_AUDIO) + mvAudioAddrDecShow(); +#endif +#if defined(MV_INCLUDE_TS) + mvTsuAddrDecShow(); +#endif +} + +/******************************************************************************* +* ctrlSizeToReg - Extract size value for register assignment. +* +* DESCRIPTION: +* Address decode size parameter must be programed from LSB to MSB as +* sequence of 1's followed by sequence of 0's. The number of 1's +* specifies the size of the window in 64 KB granularity (e.g. a +* value of 0x00ff specifies 256x64k = 16 MB). +* This function extract the size value from the size parameter according +* to given aligment paramter. For example for size 0x1000000 (16MB) and +* aligment 0x10000 (64KB) the function will return 0x00FF. +* +* INPUT: +* size - Size. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size register value correspond to size parameter. +* If value is '-1' size parameter or aligment are invalid. +*******************************************************************************/ +MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment) +{ + MV_U32 retVal; + + /* Check size parameter alignment */ + if ((0 == size) || (MV_IS_NOT_ALIGN(size, alignment))) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Size is zero or not aligned.\n")); + return -1; + } + + /* Take out the "alignment" portion out of the size parameter */ + alignment--; /* Now the alignmet is a sequance of '1' (e.g. 0xffff) */ + /* and size is 0x1000000 (16MB) for example */ + while(alignment & 1) /* Check that alignmet LSB is set */ + { + size = (size >> 1); /* If LSB is set, move 'size' one bit to right */ + alignment = (alignment >> 1); + } + + /* If after the alignment first '0' was met we still have '1' in */ + /* it then aligment is invalid (not power of 2) */ + if (alignment) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", + (MV_U32)alignment)); + return -1; + } + + /* Now the size is shifted right according to aligment: 0x0100 */ + size--; /* Now the size is a sequance of '1': 0x00ff */ + + retVal = size ; + + /* Check that LSB to MSB is sequence of 1's followed by sequence of 0's */ + while(size & 1) /* Check that LSB is set */ + { + size = (size >> 1); /* If LSB is set, move one bit to the right */ + } + + if (size) /* Sequance of 1's is over. Check that we have no other 1's */ + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Size parameter 0x%x invalid.\n", + size)); + return -1; + } + + return retVal; + +} + +/******************************************************************************* +* ctrlRegToSize - Extract size value from register value. +* +* DESCRIPTION: +* This function extract a size value from the register size parameter +* according to given aligment paramter. For example for register size +* value 0xff and aligment 0x10000 the function will return 0x01000000. +* +* INPUT: +* regSize - Size as in register format. See ctrlSizeToReg. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size. +* If value is '-1' size parameter or aligment are invalid. +*******************************************************************************/ +MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment) +{ + MV_U32 temp; + + /* Check that LSB to MSB is sequence of 1's followed by sequence of 0's */ + temp = regSize; /* Now the size is a sequance of '1': 0x00ff */ + + while(temp & 1) /* Check that LSB is set */ + { + temp = (temp >> 1); /* If LSB is set, move one bit to the right */ + } + + if (temp) /* Sequance of 1's is over. Check that we have no other 1's */ + { + DB(mvOsPrintf("ctrlRegToSize: ERR. Size parameter 0x%x invalid.\n", + regSize)); + return -1; + } + + + /* Check that aligment is a power of two */ + temp = alignment - 1;/* Now the alignmet is a sequance of '1' (0xffff) */ + + while(temp & 1) /* Check that alignmet LSB is set */ + { + temp = (temp >> 1); /* If LSB is set, move 'size' one bit to right */ + } + + /* If after the 'temp' first '0' was met we still have '1' in 'temp' */ + /* then 'temp' is invalid (not power of 2) */ + if (temp) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", + alignment)); + return -1; + } + + regSize++; /* Now the size is 0x0100 */ + + /* Add in the "alignment" portion to the register size parameter */ + alignment--; /* Now the alignmet is a sequance of '1' (e.g. 0xffff) */ + + while(alignment & 1) /* Check that alignmet LSB is set */ + { + regSize = (regSize << 1); /* LSB is set, move 'size' one bit left */ + alignment = (alignment >> 1); + } + + return regSize; +} + + +/******************************************************************************* +* ctrlSizeRegRoundUp - Round up given size +* +* DESCRIPTION: +* This function round up a given size to a size that fits the +* restrictions of size format given an aligment parameter. +* to given aligment paramter. For example for size parameter 0xa1000 and +* aligment 0x1000 the function will return 0xFF000. +* +* INPUT: +* size - Size. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size value correspond to size in register. +*******************************************************************************/ +MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment) +{ + MV_U32 msbBit = 0; + MV_U32 retSize; + + /* Check if size parameter is already comply with restriction */ + if (!(-1 == ctrlSizeToReg(size, alignment))) + { + return size; + } + + while(size) + { + size = (size >> 1); + msbBit++; + } + + retSize = (1 << msbBit); + + if (retSize < alignment) + { + return alignment; + } + else + { + return retSize; + } +} +/******************************************************************************* +* mvCtrlSysRstLengthCounterGet - Return number of milliseconds the reset button +* was pressed and clear counter +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: number of milliseconds the reset button was pressed +*******************************************************************************/ +MV_U32 mvCtrlSysRstLengthCounterGet(MV_VOID) +{ + static volatile MV_U32 Count = 0; + + if(!Count) { + Count = (MV_REG_READ(SYSRST_LENGTH_COUNTER_REG) & SLCR_COUNT_MASK); + Count = (Count / (MV_BOARD_REFCLK_25MHZ / 1000)); + /* clear counter for next boot */ + MV_REG_BIT_SET(SYSRST_LENGTH_COUNTER_REG, SLCR_CLR_MASK); + } + + DB(mvOsPrintf("mvCtrlSysRstLengthCounterGet: Reset button was pressed for %u milliseconds\n", Count)); + + return Count; +} + +MV_BOOL mvCtrlIsBootFromSPI(MV_VOID) +{ + MV_U32 satr = 0; + satr = MV_REG_READ(MPP_SAMPLE_AT_RESET); + if(mvCtrlModelGet() == MV_6180_DEV_ID) + { + if (MSAR_BOOT_MODE_6180(satr) == MSAR_BOOT_SPI_WITH_BOOTROM_6180) + return MV_TRUE; + else + return MV_FALSE; + } + satr = satr & MSAR_BOOT_MODE_MASK; + if (satr == MSAR_BOOT_SPI_WITH_BOOTROM) + return MV_TRUE; + else + return MV_FALSE; +} + +MV_BOOL mvCtrlIsBootFromSPIUseNAND(MV_VOID) +{ + MV_U32 satr = 0; + if(mvCtrlModelGet() == MV_6180_DEV_ID) + return MV_FALSE; + satr = MV_REG_READ(MPP_SAMPLE_AT_RESET); + satr = satr & MSAR_BOOT_MODE_MASK; + + if (satr == MSAR_BOOT_SPI_USE_NAND_WITH_BOOTROM) + return MV_TRUE; + else + return MV_FALSE; +} + +MV_BOOL mvCtrlIsBootFromNAND(MV_VOID) +{ + MV_U32 satr = 0; + satr = MV_REG_READ(MPP_SAMPLE_AT_RESET); + if(mvCtrlModelGet() == MV_6180_DEV_ID) + { + if (MSAR_BOOT_MODE_6180(satr) == MSAR_BOOT_NAND_WITH_BOOTROM_6180) + return MV_TRUE; + else + return MV_FALSE; + } + satr = satr & MSAR_BOOT_MODE_MASK; + if ((satr == MSAR_BOOT_NAND_WITH_BOOTROM)) + return MV_TRUE; + else + return MV_FALSE; +} + +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +/******************************************************************************* +* mvCtrlPwrSaveOn - Set Power save mode +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +*******************************************************************************/ +MV_VOID mvCtrlPwrSaveOn(MV_VOID) +{ + unsigned long old,temp; + /* Disable int */ + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + + /* Set SoC in power save */ + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, BIT11); + /* Wait for int */ + __asm__ __volatile__("mcr p15, 0, r0, c7, c0, 4"); + + /* Enabled int */ + __asm__ __volatile__("msr cpsr_c, %0" + : "=r" (old) + : + : "memory"); +} + +/******************************************************************************* +* mvCtrlPwrSaveOff - Go out of power save mode +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +*******************************************************************************/ +MV_VOID mvCtrlPwrSaveOff(MV_VOID) +{ + unsigned long old,temp; + /* Disable int */ + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + + /* Set SoC in power save */ + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, BIT11); + /* Wait for int */ + __asm__ __volatile__("mcr p15, 0, r0, c7, c0, 4"); + + /* Enabled int */ + __asm__ __volatile__("msr cpsr_c, %0" + : "=r" (old) + : + : "memory"); +} + +/******************************************************************************* +* mvCtrlPwrClckSet - Set Power State for specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +*******************************************************************************/ +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable) +{ + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index)); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_INTEG_SATA) + case SATA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SATASTOPCLOCK_MASK(index)); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SATASTOPCLOCK_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SESTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SESTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_USBSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_USBSTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_AUDIO) + case AUDIO_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_AUDIOSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_AUDIOSTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_TS) + case TS_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_TSSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_TSSTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_SDIO) + case SDIO_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SDIOSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SDIOSTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_TDM) + case TDM_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_TDMSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_TDMSTOPCLOCK_MASK); + } + break; +#endif + + default: + + break; + + } +} + +/******************************************************************************* +* mvCtrlPwrClckGet - Get Power State of specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +******************************************************************************/ +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index) +{ + MV_U32 reg = MV_REG_READ(POWER_MNG_CTRL_REG); + MV_BOOL state = MV_TRUE; + + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if ((reg & PMC_PEXSTOPCLOCK_MASK) == PMC_PEXSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if ((reg & PMC_GESTOPCLOCK_MASK(index)) == PMC_GESTOPCLOCK_STOP(index)) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_SATA) + case SATA_UNIT_ID: + if ((reg & PMC_SATASTOPCLOCK_MASK(index)) == PMC_SATASTOPCLOCK_STOP(index)) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if ((reg & PMC_SESTOPCLOCK_MASK) == PMC_SESTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if ((reg & PMC_USBSTOPCLOCK_MASK) == PMC_USBSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_AUDIO) + case AUDIO_UNIT_ID: + if ((reg & PMC_AUDIOSTOPCLOCK_MASK) == PMC_AUDIOSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_TS) + case TS_UNIT_ID: + if ((reg & PMC_TSSTOPCLOCK_MASK) == PMC_TSSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_SDIO) + case SDIO_UNIT_ID: + if ((reg & PMC_SDIOSTOPCLOCK_MASK)== PMC_SDIOSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_TDM) + case TDM_UNIT_ID: + if ((reg & PMC_TDMSTOPCLOCK_MASK) == PMC_TDMSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif + + default: + state = MV_TRUE; + break; + } + + + return state; +} +/******************************************************************************* +* mvCtrlPwrMemSet - Set Power State for memory on specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +*******************************************************************************/ +MV_VOID mvCtrlPwrMemSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable) +{ + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_PEXSTOPMEM_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_PEXSTOPMEM_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_GESTOPMEM_MASK(index)); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_GESTOPMEM_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_INTEG_SATA) + case SATA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_SATASTOPMEM_MASK(index)); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_SATASTOPMEM_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_SESTOPMEM_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_SESTOPMEM_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_USBSTOPMEM_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_USBSTOPMEM_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_AUDIO) + case AUDIO_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_AUDIOSTOPMEM_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_AUDIOSTOPMEM_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_XOR) + case XOR_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_XORSTOPMEM_MASK(index)); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_XORSTOPMEM_MASK(index)); + } + break; +#endif + default: + + break; + + } +} + +/******************************************************************************* +* mvCtrlPwrMemGet - Get Power State of memory on specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +******************************************************************************/ +MV_BOOL mvCtrlPwrMemGet(MV_UNIT_ID unitId, MV_U32 index) +{ + MV_U32 reg = MV_REG_READ(POWER_MNG_MEM_CTRL_REG); + MV_BOOL state = MV_TRUE; + + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if ((reg & PMC_PEXSTOPMEM_MASK) == PMC_PEXSTOPMEM_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if ((reg & PMC_GESTOPMEM_MASK(index)) == PMC_GESTOPMEM_STOP(index)) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_SATA) + case SATA_UNIT_ID: + if ((reg & PMC_SATASTOPMEM_MASK(index)) == PMC_SATASTOPMEM_STOP(index)) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if ((reg & PMC_SESTOPMEM_MASK) == PMC_SESTOPMEM_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if ((reg & PMC_USBSTOPMEM_MASK) == PMC_USBSTOPMEM_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_AUDIO) + case AUDIO_UNIT_ID: + if ((reg & PMC_AUDIOSTOPMEM_MASK) == PMC_AUDIOSTOPMEM_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_XOR) + case XOR_UNIT_ID: + if ((reg & PMC_XORSTOPMEM_MASK(index)) == PMC_XORSTOPMEM_STOP(index)) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif + + default: + state = MV_TRUE; + break; + } + + + return state; +} +#else +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable) {return;} +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index) {return MV_TRUE;} +#endif /* #if defined(MV_INCLUDE_CLK_PWR_CNTRL) */ + + +/******************************************************************************* +* mvMPPConfigToSPI - Change MPP[3:0] configuration to SPI mode +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +******************************************************************************/ +MV_VOID mvMPPConfigToSPI(MV_VOID) +{ + MV_U32 mppVal = 0; + MV_U32 bootVal = 0; + + if(!mvCtrlIsBootFromSPIUseNAND()) + return; + mppVal = 0x00002222; //Set MPP [3:0] to SPI mode + bootVal = MV_REG_READ(mvCtrlMppRegGet(0)); + { + mppVal &= ~0xffff0000; + bootVal &= 0xffff0000; + mppVal |= bootVal; + } + MV_REG_WRITE(mvCtrlMppRegGet(0), mppVal); +} + + +/******************************************************************************* +* mvMPPConfigToDefault - Change MPP[7:0] configuration to default configuration +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +******************************************************************************/ +MV_VOID mvMPPConfigToDefault(MV_VOID) +{ + MV_U32 mppVal = 0; + MV_U32 bootVal = 0; + + if(!mvCtrlIsBootFromSPIUseNAND()) + return; + mppVal = mvBoardMppGet(0); + bootVal = MV_REG_READ(mvCtrlMppRegGet(0)); + { + mppVal &= ~0xf0000000; + bootVal &= 0xf0000000; + mppVal |= bootVal; + } + MV_REG_WRITE(mvCtrlMppRegGet(0), mppVal); +} + + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.h new file mode 100644 index 0000000..092802b --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvLib.h @@ -0,0 +1,185 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCtrlEnvLibh +#define __INCmvCtrlEnvLibh + +/* includes */ +#include "mvSysHwConfig.h" +#include "mvCommon.h" +#include "mvTypes.h" +#include "mvOs.h" +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/mvCtrlEnvRegs.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + + +/* typedefs */ + +/* This enumerator describes the possible HW cache coherency policies the */ +/* controllers supports. */ +typedef enum _mvCachePolicy +{ + NO_COHERENCY, /* No HW cache coherency support */ + WT_COHERENCY, /* HW cache coherency supported in Write Through policy */ + WB_COHERENCY /* HW cache coherency supported in Write Back policy */ +}MV_CACHE_POLICY; + + +/* The swapping is referred to a 64-bit words (as this is the controller */ +/* internal data path width). This enumerator describes the possible */ +/* data swap types. Below is an example of the data 0x0011223344556677 */ +typedef enum _mvSwapType +{ + MV_BYTE_SWAP, /* Byte Swap 77 66 55 44 33 22 11 00 */ + MV_NO_SWAP, /* No swapping 00 11 22 33 44 55 66 77 */ + MV_BYTE_WORD_SWAP, /* Both byte and word swap 33 22 11 00 77 66 55 44 */ + MV_WORD_SWAP, /* Word swap 44 55 66 77 00 11 22 33 */ + SWAP_TYPE_MAX /* Delimiter for this enumerator */ +}MV_SWAP_TYPE; + +/* This structure describes access rights for Access protection windows */ +/* that can be found in IDMA, XOR, Ethernet and MPSC units. */ +/* Note that the permission enumerator coresponds to its register format. */ +/* For example, Read only premission is presented as "1" in register field. */ +typedef enum _mvAccessRights +{ + NO_ACCESS_ALLOWED = 0, /* No access allowed */ + READ_ONLY = 1, /* Read only permission */ + ACC_RESERVED = 2, /* Reserved access right */ + FULL_ACCESS = 3, /* Read and Write permission */ + MAX_ACC_RIGHTS +}MV_ACCESS_RIGHTS; + + +/* mcspLib.h API list */ + +MV_STATUS mvCtrlEnvInit(MV_VOID); +MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup); + +#if defined(MV_INCLUDE_PEX) +MV_U32 mvCtrlPexMaxIfGet(MV_VOID); +#else +#define mvCtrlPexMaxIfGet() (0) +#endif + +#define mvCtrlPciIfMaxIfGet() (mvCtrlPexMaxIfGet()) + +#if defined(MV_INCLUDE_GIG_ETH) +MV_U32 mvCtrlEthMaxPortGet(MV_VOID); +#endif +#if defined(MV_INCLUDE_XOR) +MV_U32 mvCtrlXorMaxChanGet(MV_VOID); +#endif +#if defined(MV_INCLUDE_USB) +MV_U32 mvCtrlUsbMaxGet(MV_VOID); +#endif +#if defined(MV_INCLUDE_NAND) +MV_U32 mvCtrlNandSupport(MV_VOID); +#endif +#if defined(MV_INCLUDE_SDIO) +MV_U32 mvCtrlSdioSupport(MV_VOID); +#endif +#if defined(MV_INCLUDE_TS) +MV_U32 mvCtrlTsSupport(MV_VOID); +#endif +#if defined(MV_INCLUDE_AUDIO) +MV_U32 mvCtrlAudioSupport(MV_VOID); +#endif +#if defined(MV_INCLUDE_TDM) +MV_U32 mvCtrlTdmSupport(MV_VOID); +#endif + +MV_U16 mvCtrlModelGet(MV_VOID); +MV_U8 mvCtrlRevGet(MV_VOID); +MV_STATUS mvCtrlNameGet(char *pNameBuff); +MV_U32 mvCtrlModelRevGet(MV_VOID); +MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff); +MV_VOID mvCtrlAddrDecShow(MV_VOID); +const MV_8* mvCtrlTargetNameGet(MV_TARGET target); +MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment); +MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment); +MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment); +MV_U32 mvCtrlSysRstLengthCounterGet(MV_VOID); +MV_STATUS ctrlWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2); +MV_STATUS ctrlWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2); + +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable); +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index); +MV_VOID mvCtrlPwrMemSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable); +MV_BOOL mvCtrlIsBootFromSPI(MV_VOID); +MV_BOOL mvCtrlIsBootFromSPIUseNAND(MV_VOID); +MV_BOOL mvCtrlIsBootFromNAND(MV_VOID); +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +MV_VOID mvCtrlPwrSaveOn(MV_VOID); +MV_VOID mvCtrlPwrSaveOff(MV_VOID); +#endif +MV_BOOL mvCtrlPwrMemGet(MV_UNIT_ID unitId, MV_U32 index); +MV_VOID mvMPPConfigToSPI(MV_VOID); +MV_VOID mvMPPConfigToDefault(MV_VOID); + + +#endif /* __INCmvCtrlEnvLibh */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvRegs.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvRegs.h new file mode 100644 index 0000000..c54872e --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvRegs.h @@ -0,0 +1,409 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCtrlEnvRegsh +#define __INCmvCtrlEnvRegsh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM +#define PCI0_MEM0 PEX0_MEM + +/* Controller revision info */ +#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define PCCRIR_REVID_OFFS 0 /* Revision ID */ +#define PCCRIR_REVID_MASK (0xff << PCCRIR_REVID_OFFS) + +/* Controler environment registers offsets */ + +/* Power Managment Control */ +#define POWER_MNG_MEM_CTRL_REG 0x20118 + +#define PMC_GESTOPMEM_OFFS(port) ((port)? 13 : 0) +#define PMC_GESTOPMEM_MASK(port) (1 << PMC_GESTOPMEM_OFFS(port)) +#define PMC_GESTOPMEM_EN(port) (0 << PMC_GESTOPMEM_OFFS(port)) +#define PMC_GESTOPMEM_STOP(port) (1 << PMC_GESTOPMEM_OFFS(port)) + +#define PMC_PEXSTOPMEM_OFFS 1 +#define PMC_PEXSTOPMEM_MASK (1 << PMC_PEXSTOPMEM_OFFS) +#define PMC_PEXSTOPMEM_EN (0 << PMC_PEXSTOPMEM_OFFS) +#define PMC_PEXSTOPMEM_STOP (1 << PMC_PEXSTOPMEM_OFFS) + +#define PMC_USBSTOPMEM_OFFS 2 +#define PMC_USBSTOPMEM_MASK (1 << PMC_USBSTOPMEM_OFFS) +#define PMC_USBSTOPMEM_EN (0 << PMC_USBSTOPMEM_OFFS) +#define PMC_USBSTOPMEM_STOP (1 << PMC_USBSTOPMEM_OFFS) + +#define PMC_DUNITSTOPMEM_OFFS 3 +#define PMC_DUNITSTOPMEM_MASK (1 << PMC_DUNITSTOPMEM_OFFS) +#define PMC_DUNITSTOPMEM_EN (0 << PMC_DUNITSTOPMEM_OFFS) +#define PMC_DUNITSTOPMEM_STOP (1 << PMC_DUNITSTOPMEM_OFFS) + +#define PMC_RUNITSTOPMEM_OFFS 4 +#define PMC_RUNITSTOPMEM_MASK (1 << PMC_RUNITSTOPMEM_OFFS) +#define PMC_RUNITSTOPMEM_EN (0 << PMC_RUNITSTOPMEM_OFFS) +#define PMC_RUNITSTOPMEM_STOP (1 << PMC_RUNITSTOPMEM_OFFS) + +#define PMC_XORSTOPMEM_OFFS(port) (5+(port*2)) +#define PMC_XORSTOPMEM_MASK(port) (1 << PMC_XORSTOPMEM_OFFS(port)) +#define PMC_XORSTOPMEM_EN(port) (0 << PMC_XORSTOPMEM_OFFS(port)) +#define PMC_XORSTOPMEM_STOP(port) (1 << PMC_XORSTOPMEM_OFFS(port)) + +#define PMC_SATASTOPMEM_OFFS(port) (6+(port*5)) +#define PMC_SATASTOPMEM_MASK(port) (1 << PMC_SATASTOPMEM_OFFS(port)) +#define PMC_SATASTOPMEM_EN(port) (0 << PMC_SATASTOPMEM_OFFS(port)) +#define PMC_SATASTOPMEM_STOP(port) (1 << PMC_SATASTOPMEM_OFFS(port)) + +#define PMC_SESTOPMEM_OFFS 8 +#define PMC_SESTOPMEM_MASK (1 << PMC_SESTOPMEM_OFFS) +#define PMC_SESTOPMEM_EN (0 << PMC_SESTOPMEM_OFFS) +#define PMC_SESTOPMEM_STOP (1 << PMC_SESTOPMEM_OFFS) + +#define PMC_AUDIOSTOPMEM_OFFS 9 +#define PMC_AUDIOSTOPMEM_MASK (1 << PMC_AUDIOSTOPMEM_OFFS) +#define PMC_AUDIOSTOPMEM_EN (0 << PMC_AUDIOSTOPMEM_OFFS) +#define PMC_AUDIOSTOPMEM_STOP (1 << PMC_AUDIOSTOPMEM_OFFS) + +#define POWER_MNG_CTRL_REG 0x2011C + +#define PMC_GESTOPCLOCK_OFFS(port) ((port)? 19 : 0) +#define PMC_GESTOPCLOCK_MASK(port) (1 << PMC_GESTOPCLOCK_OFFS(port)) +#define PMC_GESTOPCLOCK_EN(port) (1 << PMC_GESTOPCLOCK_OFFS(port)) +#define PMC_GESTOPCLOCK_STOP(port) (0 << PMC_GESTOPCLOCK_OFFS(port)) + +#define PMC_PEXPHYSTOPCLOCK_OFFS 1 +#define PMC_PEXPHYSTOPCLOCK_MASK (1 << PMC_PEXPHYSTOPCLOCK_OFFS) +#define PMC_PEXPHYSTOPCLOCK_EN (1 << PMC_PEXPHYSTOPCLOCK_OFFS) +#define PMC_PEXPHYSTOPCLOCK_STOP (0 << PMC_PEXPHYSTOPCLOCK_OFFS) + +#define PMC_PEXSTOPCLOCK_OFFS 2 +#define PMC_PEXSTOPCLOCK_MASK (1 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_EN (1 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_STOP (0 << PMC_PEXSTOPCLOCK_OFFS) + +#define PMC_USBSTOPCLOCK_OFFS 3 +#define PMC_USBSTOPCLOCK_MASK (1 << PMC_USBSTOPCLOCK_OFFS) +#define PMC_USBSTOPCLOCK_EN (1 << PMC_USBSTOPCLOCK_OFFS) +#define PMC_USBSTOPCLOCK_STOP (0 << PMC_USBSTOPCLOCK_OFFS) + +#define PMC_SDIOSTOPCLOCK_OFFS 4 +#define PMC_SDIOSTOPCLOCK_MASK (1 << PMC_SDIOSTOPCLOCK_OFFS) +#define PMC_SDIOSTOPCLOCK_EN (1 << PMC_SDIOSTOPCLOCK_OFFS) +#define PMC_SDIOSTOPCLOCK_STOP (0 << PMC_SDIOSTOPCLOCK_OFFS) + +#define PMC_TSSTOPCLOCK_OFFS 5 +#define PMC_TSSTOPCLOCK_MASK (1 << PMC_TSSTOPCLOCK_OFFS) +#define PMC_TSSTOPCLOCK_EN (1 << PMC_TSSTOPCLOCK_OFFS) +#define PMC_TSSTOPCLOCK_STOP (0 << PMC_TSSTOPCLOCK_OFFS) + +#define PMC_AUDIOSTOPCLOCK_OFFS 9 +#define PMC_AUDIOSTOPCLOCK_MASK (1 << PMC_AUDIOSTOPCLOCK_OFFS) +#define PMC_AUDIOSTOPCLOCK_EN (1 << PMC_AUDIOSTOPCLOCK_OFFS) +#define PMC_AUDIOSTOPCLOCK_STOP (0 << PMC_AUDIOSTOPCLOCK_OFFS) + +#define PMC_SATASTOPCLOCK_OFFS(port) (14+(port)) +#define PMC_SATASTOPCLOCK_MASK(port) (1 << PMC_SATASTOPCLOCK_OFFS(port)) +#define PMC_SATASTOPCLOCK_EN(port) (1 << PMC_SATASTOPCLOCK_OFFS(port)) +#define PMC_SATASTOPCLOCK_STOP(port) (0 << PMC_SATASTOPCLOCK_OFFS(port)) + +#define PMC_SESTOPCLOCK_OFFS 17 +#define PMC_SESTOPCLOCK_MASK (1 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_EN (1 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_STOP (0 << PMC_SESTOPCLOCK_OFFS) + +#define PMC_TDMSTOPCLOCK_OFFS 20 +#define PMC_TDMSTOPCLOCK_MASK (1 << PMC_TDMSTOPCLOCK_OFFS) +#define PMC_TDMSTOPCLOCK_EN (1 << PMC_TDMSTOPCLOCK_OFFS) +#define PMC_TDMSTOPCLOCK_STOP (0 << PMC_TDMSTOPCLOCK_OFFS) + + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10008 +#define MPP_CONTROL_REG3 0x1000C +#define MPP_CONTROL_REG4 0x10010 +#define MPP_CONTROL_REG5 0x10014 +#define MPP_CONTROL_REG6 0x10018 +#define MPP_SAMPLE_AT_RESET 0x10030 +#define CHIP_BOND_REG 0x10034 +#define SYSRST_LENGTH_COUNTER_REG 0x10050 +#define SLCR_COUNT_OFFS 0 +#define SLCR_COUNT_MASK (0x1FFFFFFF << SLCR_COUNT_OFFS) +#define SLCR_CLR_OFFS 31 +#define SLCR_CLR_MASK (1 << SLCR_CLR_OFFS) +#define PCKG_OPT_MASK 0x3 +#define MPP_OUTPUT_DRIVE_REG 0x100E0 +#define MPP_RGMII0_OUTPUT_DRIVE_OFFS 7 +#define MPP_3_3_RGMII0_OUTPUT_DRIVE (0x0 << MPP_RGMII0_OUTPUT_DRIVE_OFFS) +#define MPP_1_8_RGMII0_OUTPUT_DRIVE (0x1 << MPP_RGMII0_OUTPUT_DRIVE_OFFS) +#define MPP_RGMII1_OUTPUT_DRIVE_OFFS 15 +#define MPP_3_3_RGMII1_OUTPUT_DRIVE (0x0 << MPP_RGMII1_OUTPUT_DRIVE_OFFS) +#define MPP_1_8_RGMII1_OUTPUT_DRIVE (0x1 << MPP_RGMII1_OUTPUT_DRIVE_OFFS) + +#define MSAR_BOOT_MODE_OFFS 12 +#define MSAR_BOOT_MODE_MASK (0x7 << MSAR_BOOT_MODE_OFFS) +#define MSAR_BOOT_NAND_WITH_BOOTROM (0x5 << MSAR_BOOT_MODE_OFFS) +#define MSAR_BOOT_SPI_WITH_BOOTROM (0x4 << MSAR_BOOT_MODE_OFFS) +#define MSAR_BOOT_SPI_USE_NAND_WITH_BOOTROM (0x2 << MSAR_BOOT_MODE_OFFS) + +#define MSAR_BOOT_MODE_6180(X) (((X & 0x3000) >> 12) | \ + ((X & 0x2) << 1)) +#define MSAR_BOOT_SPI_WITH_BOOTROM_6180 0x1 +#define MSAR_BOOT_NAND_WITH_BOOTROM_6180 0x5 + +#define MSAR_TCLCK_OFFS 16 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_200 (0x2 << MSAR_TCLCK_OFFS) + + +#define MSAR_CPUCLCK_EXTRACT(X) (((X & 0x2) >> 1) | ((X & 0x400000) >> 21) | \ + ((X & 0x18) >> 1)) + +#define MSAR_CPUCLCK_OFFS_6180 2 +#define MSAR_CPUCLCK_MASK_6180 (0x7 << MSAR_CPUCLCK_OFFS_6180) + +#define MSAR_DDRCLCK_RTIO_OFFS 5 +#define MSAR_DDRCLCK_RTIO_MASK (0xF << MSAR_DDRCLCK_RTIO_OFFS) + +#define MSAR_L2CLCK_EXTRACT(X) (((X & 0x600) >> 9) | ((X & 0x80000) >> 17)) + +#ifndef MV_ASMLANGUAGE +/* CPU clock for 6281,6192 0->Resereved */ +#define MV_CPU_CLCK_TBL { 0, 0, 0, 0, \ + 600000000, 0, 800000000, 1000000000, \ + 0, 1200000000, 0, 0, \ + 1500000000, 0, 0, 0} +/* DDR clock RATIO for 6281,6192 {0,0}->Reserved */ +#define MV_DDR_CLCK_RTIO_TBL {\ + {0, 0}, {0, 0}, {2, 1}, {0, 0}, \ + {3, 1}, {0, 0}, {4, 1}, {9, 2}, \ + {5, 1}, {6, 1}, {0, 0}, {0, 0}, \ + {0, 0}, {0, 0}, {0, 0}, {0, 0} \ +} + +/* L2 clock RATIO for 6281,6192 {1,1}->Reserved */ +#define MV_L2_CLCK_RTIO_TBL {\ + {0, 0}, {2, 1}, {0, 0}, {3, 1}, \ + {0, 0}, {0, 0}, {0, 0}, {0, 0} \ +} + +/* 6180 have different clk reset sampling */ +/* ARM CPU, DDR, L2 clock for 6180 {0,0,0}->Reserved */ +#define MV_CPU6180_DDR_L2_CLCK_TBL { \ + {0, 0, 0 },\ + {0, 0, 0 },\ + {0, 0, 0 },\ + {0, 0, 0 },\ + {0, 0, 0 },\ + {600000000, 200000000, 300000000 },\ + {800000000, 200000000, 400000000 },\ + {0, 0, 0 }\ +} + + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS3)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) 0 + +#define MV_TARGET_IS_AS_BOOT(target) ((target) == (sampleAtResetTargetArray[ \ + (mvCtrlModelGet() == MV_6180_DEV_ID)? MSAR_BOOT_MODE_6180 \ + (MV_REG_READ(MPP_SAMPLE_AT_RESET)):((MV_REG_READ(MPP_SAMPLE_AT_RESET)\ + & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)])) + + +#define MV_CHANGE_BOOT_CS(target) (((target) == DEV_BOOCS)?\ + sampleAtResetTargetArray[(mvCtrlModelGet() == MV_6180_DEV_ID)? \ + MSAR_BOOT_MODE_6180(MV_REG_READ(MPP_SAMPLE_AT_RESET)): \ + ((MV_REG_READ(MPP_SAMPLE_AT_RESET) & MSAR_BOOT_MODE_MASK)\ + >> MSAR_BOOT_MODE_OFFS)]:(target)) + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ + +#define BOOT_TARGETS_NAME_ARRAY { \ + TBL_TERM, \ + TBL_TERM, \ + BOOT_ROM_CS, \ + TBL_TERM, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + TBL_TERM, \ + TBL_TERM \ +} + +#define BOOT_TARGETS_NAME_ARRAY_6180 { \ + TBL_TERM, \ + BOOT_ROM_CS, \ + TBL_TERM, \ + TBL_TERM, \ + TBL_TERM, \ + BOOT_ROM_CS, \ + TBL_TERM, \ + TBL_TERM \ +} + + +/* For old competability */ +#define DEVICE_CS0 NFLASH_CS +#define DEVICE_CS1 SPI_CS +#define DEVICE_CS2 BOOT_ROM_CS +#define DEVICE_CS3 DEV_BOOCS +#define MV_BOOTDEVICE_INDEX 0 + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> Nand/SPI */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + CRYPT_TARGET_ID = 3 , /* Port 3 --> Crypto Engine */ + SAGE_TARGET_ID = 12 , /* Port 12 -> SAGE Unit */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + INTER_REGS, /* Internal registers */ + NFLASH_CS, /* NFLASH_CS */ + SPI_CS, /* SPI_CS */ + BOOT_ROM_CS, /* BOOT_ROM_CS */ + DEV_BOOCS, /* DEV_BOOCS */ + CRYPT_ENG, /* Crypto Engine */ +#ifdef MV_INCLUDE_SAGE + SAGE_UNIT, /* SAGE Unit */ +#endif + MAX_TARGETS + +}MV_TARGET; + +#define TARGETS_DEF_ARRAY { \ + {0x0E, DRAM_TARGET_ID }, /* SDRAM_CS0 */ \ + {0x0D, DRAM_TARGET_ID }, /* SDRAM_CS1 */ \ + {0x0B, DRAM_TARGET_ID }, /* SDRAM_CS0 */ \ + {0x07, DRAM_TARGET_ID }, /* SDRAM_CS1 */ \ + {0xE8, PEX0_TARGET_ID }, /* PEX0_MEM */ \ + {0xE0, PEX0_TARGET_ID }, /* PEX0_IO */ \ + {0xFF, 0xFF }, /* INTER_REGS */ \ + {0x2F, DEV_TARGET_ID }, /* NFLASH_CS */ \ + {0x1E, DEV_TARGET_ID }, /* SPI_CS */ \ + {0x1D, DEV_TARGET_ID }, /* BOOT_ROM_CS */ \ + {0x1E, DEV_TARGET_ID }, /* DEV_BOOCS */ \ + {0x01, CRYPT_TARGET_ID}, /* CRYPT_ENG */ \ + {0x00, SAGE_TARGET_ID } \ +} + + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "NFLASH_CS", /* NFLASH_CS */ \ + "SPI_CS", /* SPI_CS */ \ + "BOOT_ROM_CS", /* BOOT_ROM_CS */ \ + "DEV_BOOTCS", /* DEV_BOOCS */ \ + "CRYPT_ENG", /* CRYPT_ENG */ \ + "SAGE_UNIT" /* SAGE_UNIT */ \ +} +#endif /* MV_ASMLANGUAGE */ + + +#endif diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvSpec.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvSpec.h new file mode 100644 index 0000000..7d7de2d --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/mvCtrlEnvSpec.h @@ -0,0 +1,249 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCtrlEnvSpech +#define __INCmvCtrlEnvSpech + +#include "mvDeviceId.h" +#include "mvSysHwConfig.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + + +/* units base and port numbers */ +#ifdef MV_ASMLANGUAGE +#define XOR_UNIT_BASE(unit) 0x60800 +#else +#define XOR_UNIT_BASE(unit) ((unit)? 0x60900:0x60800) +#endif + +#define TDM_REG_BASE 0xD0000 +#define USB_REG_BASE(dev) 0x50000 +#define AUDIO_REG_BASE 0xA0000 +#define SATA_REG_BASE 0x80000 +#define MV_CESA_REG_BASE 0x3D000 +#define MV_CESA_TDMA_REG_BASE 0x30000 +#define MV_SDIO_REG_BASE 0x90000 +#define MV_ETH_REG_BASE(port) (((port) == 0) ? 0x72000 : 0x76000) +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) +#define DRAM_BASE 0x0 +#define CNTMR_BASE 0x20300 +#define TWSI_SLAVE_BASE(chanNum) 0x11000 +#define PEX_IF_BASE(pexIf) 0x40000 + +#define INTER_REGS_SIZE _1M +/* This define describes the TWSI interrupt bit and location */ +#define TWSI_CPU_MAIN_INT_CAUSE_REG 0x20200 +#define TWSI0_CPU_MAIN_INT_BIT (1<<29) +#define TWSI_SPEED 100000 + +#define MV_GPP_MAX_GROUP 2 +#define MV_CNTMR_MAX_COUNTER 2 +#define MV_UART_MAX_CHAN 2 +#define MV_XOR_MAX_UNIT 2 +#define MV_XOR_MAX_CHAN 4 /* total channels for all units together*/ +#define MV_XOR_MAX_CHAN_PER_UNIT 2 /* channels for units */ +#define MV_SATA_MAX_CHAN 2 + +#define MV_6281_MPP_MAX_MODULE 2 +#define MV_6192_MPP_MAX_MODULE 1 +#define MV_6190_MPP_MAX_MODULE 1 +#define MV_6180_MPP_MAX_MODULE 1 +#define MV_6281_MPP_MAX_GROUP 7 +#define MV_6192_MPP_MAX_GROUP 4 +#define MV_6190_MPP_MAX_GROUP 4 +#define MV_6180_MPP_MAX_GROUP 3 + +#define MV_DRAM_MAX_CS 4 + +/* This define describes the maximum number of supported PCI\PCIX Interfaces*/ +#define MV_PCI_MAX_IF 0 +#define MV_PCI_START_IF 0 + +/* This define describes the maximum number of supported PEX Interfaces */ +#define MV_INCLUDE_PEX0 +#define MV_DISABLE_PEX_DEVICE_BAR +#define MV_PEX_MAX_IF 1 +#define MV_PEX_START_IF MV_PCI_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define MV_ETH_MAX_PORTS 2 +#define MV_6281_ETH_MAX_PORTS 2 +#define MV_6192_ETH_MAX_PORTS 2 +#define MV_6190_ETH_MAX_PORTS 1 +#define MV_6180_ETH_MAX_PORTS 1 + +#define MV_IDMA_MAX_CHAN 0 + +#define MV_USB_MAX_CHAN 1 + +#define MV_USB_VERSION 1 + + +#define MV_6281_NAND 1 +#define MV_6192_NAND 1 +#define MV_6190_NAND 1 +#define MV_6180_NAND 0 + +#define MV_6281_SDIO 1 +#define MV_6192_SDIO 1 +#define MV_6190_SDIO 1 +#define MV_6180_SDIO 0 + +#define MV_6281_TS 1 +#define MV_6192_TS 1 +#define MV_6190_TS 0 +#define MV_6180_TS 0 + +#define MV_6281_AUDIO 1 +#define MV_6192_AUDIO 1 +#define MV_6190_AUDIO 0 +#define MV_6180_AUDIO 0 + +#define MV_6281_TDM 1 +#define MV_6192_TDM 1 +#define MV_6190_TDM 0 +#define MV_6180_TDM 0 + +#define MV_DEVICE_MAX_CS 4 + +/* Others */ +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_IO(pciIf) (PEX0_IO) +#define PCI_MEM(pciIf, memNum) (PEX0_MEM0) +/* CESA version #2: One channel, 2KB SRAM, TDMA */ +#define MV_CESA_VERSION 2 +#define MV_CESA_SRAM_SIZE 2*1024 +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_VERSION 4 +#define MV_ETH_MAX_RXQ 8 +#define MV_ETH_MAX_TXQ 8 +#define MV_ETH_PORT_SGMII { MV_FALSE, MV_FALSE } +/* This define describes the the support of USB */ +#define MV_USB_VERSION 1 + +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 + +#define MPP_GROUP_1_TYPE {\ + {0, 0, 0}, /* Reserved for AUTO */ \ + {0x22220000, 0x22222222, 0x2222}, /* TDM */ \ + {0x44440000, 0x44444444, 0x0000}, /* AUDIO */ \ + {0x33330000, 0x33003333, 0x0033}, /* RGMII */ \ + {0x33330000, 0x03333333, 0x0033}, /* GMII */ \ + {0x11110000, 0x11111111, 0x0001}, /* TS */ \ + {0x33330000, 0x33333333, 0x3333} /* MII */ \ +} + +#define MPP_GROUP_2_TYPE {\ + {0, 0, 0}, /* Reserved for AUTO */ \ + {0x22220000, 0x22222222, 0x22}, /* TDM */ \ + {0x44440000, 0x00044444, 0x0}, /* AUDIO */ \ + {0, 0, 0}, /* N_A */ \ + {0, 0, 0}, /* N_A */ \ + {0x11110000, 0x1111111, 0x01} /* TS */ \ +} + +#ifndef MV_ASMLANGUAGE + +/* This enumerator defines the Marvell Units ID */ +typedef enum _mvUnitId +{ + DRAM_UNIT_ID, + PEX_UNIT_ID, + ETH_GIG_UNIT_ID, + USB_UNIT_ID, + IDMA_UNIT_ID, + XOR_UNIT_ID, + SATA_UNIT_ID, + TDM_UNIT_ID, + UART_UNIT_ID, + CESA_UNIT_ID, + SPI_UNIT_ID, + AUDIO_UNIT_ID, + SDIO_UNIT_ID, + TS_UNIT_ID, + MAX_UNITS_ID + +}MV_UNIT_ID; + +#endif + +#endif /* __INCmvCtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.c new file mode 100644 index 0000000..a54620e --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.c @@ -0,0 +1,1050 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "ctrlEnv/sys/mvAhbToMbus.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#undef MV_DEBUG +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* typedefs */ + + +/* CPU address remap registers offsets are inconsecutive. This struct */ +/* describes address remap register offsets */ +typedef struct _ahbToMbusRemapRegOffs +{ + MV_U32 lowRegOffs; /* Low 32-bit remap register offset */ + MV_U32 highRegOffs; /* High 32 bit remap register offset */ +}AHB_TO_MBUS_REMAP_REG_OFFS; + +/* locals */ +static MV_STATUS ahbToMbusRemapRegOffsGet (MV_U32 winNum, + AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs); + +/******************************************************************************* +* mvAhbToMbusInit - Initialize Ahb To Mbus Address Map ! +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK laways. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusInit(void) +{ + return MV_OK; + +} + +/******************************************************************************* +* mvAhbToMbusWinSet - Set CPU-to-peripheral winNum address window +* +* DESCRIPTION: +* This function sets +* address window, also known as address decode window. +* A new address decode window is set for specified winNum address window. +* If address decode window parameter structure enables the window, +* the routine will also enable the winNum window, allowing CPU to access +* the winNum window. +* +* INPUT: +* winNum - Windows number. +* pAddrDecWin - CPU winNum window data structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if CPU winNum window was set correctly, MV_ERROR in case of +* address window overlapps with other active CPU winNum window or +* trying to assign 36bit base address while CPU does not support that. +* The function returns MV_NOT_SUPPORTED, if the winNum is unsupported. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttribs; + MV_DEC_REGS decRegs; + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinSet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + + /* read base register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum)); + } + else + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG); + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvAhbToMbusWinSet:Error setting AHB to MBUS window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + /* read control register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); + } + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvAhbToMbusWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + /* enable\Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + decRegs.sizeReg |= ATMWCR_WIN_ENABLE; + } + else + { + decRegs.sizeReg &= ~ATMWCR_WIN_ENABLE; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~ATMWCR_WIN_ATTR_MASK; + decRegs.sizeReg |= targetAttribs.attrib << ATMWCR_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.sizeReg &= ~ATMWCR_WIN_TARGET_MASK; + decRegs.sizeReg |= targetAttribs.targetId << ATMWCR_WIN_TARGET_OFFS; + +#if !defined(MV_RUN_FROM_FLASH) + /* To be on the safe side we disable the window before writing the */ + /* new values. */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + mvAhbToMbusWinEnable(winNum,MV_FALSE); + } +#endif + + /* 3) Write to address decode Base Address Register */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), decRegs.baseReg); + } + else + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_INTEREG_REG, decRegs.baseReg); + } + + + /* Internal register space have no size */ + /* register. Do not perform size register assigment for those targets */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + /* Write to address decode Size Register */ + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), decRegs.sizeReg); + } + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusWinGet - Get CPU-to-peripheral winNum address window +* +* DESCRIPTION: +* Get the CPU peripheral winNum address window. +* +* INPUT: +* winNum - Peripheral winNum enumerator +* +* OUTPUT: +* pAddrDecWin - CPU winNum window information data structure. +* +* RETURN: +* MV_OK if winNum exist, MV_ERROR otherwise. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinGet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + + /* Internal register space size have no size register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); + } + else + { + decRegs.sizeReg = 0; + } + + + /* Read base and size */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum)); + } + else + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG); + } + + + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + { + pAddrDecWin->addrWin.size = INTER_REGS_SIZE; + pAddrDecWin->target = INTER_REGS; + pAddrDecWin->enable = MV_TRUE; + + return MV_OK; + } + + + if (decRegs.sizeReg & ATMWCR_WIN_ENABLE) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + + } + + + + if (-1 == pAddrDecWin->addrWin.size) + { + return MV_ERROR; + } + + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & ATMWCR_WIN_ATTR_MASK) >> + ATMWCR_WIN_ATTR_OFFS; + targetAttrib.targetId = (decRegs.sizeReg & ATMWCR_WIN_TARGET_MASK) >> + ATMWCR_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinTargetGet(MV_TARGET target) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + if (INTER_REGS == target) + { + return MV_AHB_TO_MBUS_INTREG_WIN; + } + + for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS ; winNum++) + { + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + continue; + + if (mvAhbToMbusWinGet(winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail\n"); + return 0xffffffff; + + } + + if (decWin.enable == MV_TRUE) + { + if (decWin.target == target) + { + return winNum; + } + + } + + } + + return 0xFFFFFFFF; + + +} + +/******************************************************************************* +* mvAhbToMbusWinAvailGet - Get First Available window number. +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinAvailGet(MV_VOID) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 winNum; + + for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS ; winNum++) + { + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + continue; + + if (mvAhbToMbusWinGet(winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail\n"); + return 0xffffffff; + + } + + if (decWin.enable == MV_FALSE) + { + return winNum; + } + + } + + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* mvAhbToMbusWinEnable - Enable/disable a CPU address decode window +* +* DESCRIPTION: +* This function enable/disable a CPU address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling CPU accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - Peripheral winNum enumerator. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if protection window number was wrong, or the window +* overlapps other winNum window. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinEnable(MV_U32 winNum, MV_BOOL enable) +{ + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinEnable: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + /* Internal registers bar can't be disable or enabled */ + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + { + return (enable ? MV_OK : MV_ERROR); + } + + if (enable == MV_TRUE) + { + /* enable the window */ + MV_REG_BIT_SET(AHB_TO_MBUS_WIN_CTRL_REG(winNum), ATMWCR_WIN_ENABLE); + } + else + { /* Disable address decode winNum window */ + MV_REG_BIT_RESET(AHB_TO_MBUS_WIN_CTRL_REG(winNum), ATMWCR_WIN_ENABLE); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvAhbToMbusWinRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* After a CPU address hits one of PCI address decode windows there is an +* option to remap the address to a different one. For example, CPU +* executes a read from PCI winNum window address 0x1200.0000. This +* can be modified so the address on the PCI bus would be 0x1400.0000 +* Using the PCI address remap mechanism. +* +* INPUT: +* winNum - Peripheral winNum enumerator. Must be a PCI winNum. +* pAddrDecWin - CPU winNum window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if winNum is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinRemap(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddr; + AHB_TO_MBUS_REMAP_REG_OFFS remapRegOffs; + + MV_U32 effectiveBaseAddress=0, + baseAddrValue=0,windowSizeValue=0; + + + /* Get registers offsets of given winNum */ + if (MV_NO_SUCH == ahbToMbusRemapRegOffsGet(winNum, &remapRegOffs)) + { + return 0xffffffff; + } + + /* 1) Set address remap low */ + baseAddr = pAddrWin->baseLow; + + /* Check base address aligment */ + /* + if (MV_IS_NOT_ALIGN(baseAddr, ATMWRLR_REMAP_LOW_ALIGNMENT)) + { + mvOsPrintf("mvAhbToMbusPciRemap: Warning. Target base 0x%x unaligned\n", + baseAddr); + return MV_ERROR; + } + */ + + /* BaseLow[31:16] => base register [31:16] */ + baseAddr = baseAddr & ATMWRLR_REMAP_LOW_MASK; + + MV_REG_WRITE(remapRegOffs.lowRegOffs, baseAddr); + + MV_REG_WRITE(remapRegOffs.highRegOffs, pAddrWin->baseHigh); + + + baseAddrValue = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum)); + windowSizeValue = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); + + baseAddrValue &= ATMWBR_BASE_MASK; + windowSizeValue &=ATMWCR_WIN_SIZE_MASK; + + /* Start calculating the effective Base Address */ + effectiveBaseAddress = baseAddrValue ; + + /* The effective base address will be combined from the chopped (if any) + remap value (according to the size value and remap mechanism) and the + window's base address */ + effectiveBaseAddress |= (((windowSizeValue) | 0xffff) & pAddrWin->baseLow); + /* If the effectiveBaseAddress exceed the window boundaries return an + invalid value. */ + + if (effectiveBaseAddress > (baseAddrValue + (windowSizeValue | 0xffff))) + { + mvOsPrintf("mvAhbToMbusPciRemap: Error\n"); + return 0xffffffff; + } + + return effectiveBaseAddress; + + +} +/******************************************************************************* +* mvAhbToMbusWinTargetSwap - Swap AhbToMbus windows between targets +* +* DESCRIPTION: +* +* INPUT: +* target1 - CPU Interface target 1 +* target2 - CPU Interface target 2 +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if targets are illigal, or if one of the targets is not +* associated to a valid window . +* MV_OK otherwise. +* +*******************************************************************************/ + + +MV_STATUS mvAhbToMbusWinTargetSwap(MV_TARGET target1,MV_TARGET target2) +{ + MV_U32 winNum1,winNum2; + MV_AHB_TO_MBUS_DEC_WIN winDec1,winDec2,winDecTemp; + AHB_TO_MBUS_REMAP_REG_OFFS remapRegs1,remapRegs2; + MV_U32 remapBaseLow1=0,remapBaseLow2=0; + MV_U32 remapBaseHigh1=0,remapBaseHigh2=0; + + + /* Check parameters */ + if (target1 >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is Illigal\n", target1); + return MV_ERROR; + } + + if (target2 >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is Illigal\n", target1); + return MV_ERROR; + } + + + /* get window associated with this target */ + winNum1 = mvAhbToMbusWinTargetGet(target1); + + if (winNum1 == 0xffffffff) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", + target1,winNum1); + return MV_ERROR; + + } + + /* get window associated with this target */ + winNum2 = mvAhbToMbusWinTargetGet(target2); + + if (winNum2 == 0xffffffff) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", + target2,winNum2); + return MV_ERROR; + + } + + /* now Get original values of both Windows */ + if (MV_OK != mvAhbToMbusWinGet(winNum1,&winDec1)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", + winNum1); + return MV_ERROR; + + } + if (MV_OK != mvAhbToMbusWinGet(winNum2,&winDec2)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", + winNum2); + return MV_ERROR; + + } + + + /* disable both windows */ + if (MV_OK != mvAhbToMbusWinEnable(winNum1,MV_FALSE)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable window %d\n", + winNum1); + return MV_ERROR; + + } + if (MV_OK != mvAhbToMbusWinEnable(winNum2,MV_FALSE)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable windo %d\n", + winNum2); + return MV_ERROR; + + } + + + /* now swap targets */ + + /* first save winDec2 values */ + winDecTemp.addrWin.baseHigh = winDec2.addrWin.baseHigh; + winDecTemp.addrWin.baseLow = winDec2.addrWin.baseLow; + winDecTemp.addrWin.size = winDec2.addrWin.size; + winDecTemp.enable = winDec2.enable; + winDecTemp.target = winDec2.target; + + /* winDec2 = winDec1 */ + winDec2.addrWin.baseHigh = winDec1.addrWin.baseHigh; + winDec2.addrWin.baseLow = winDec1.addrWin.baseLow; + winDec2.addrWin.size = winDec1.addrWin.size; + winDec2.enable = winDec1.enable; + winDec2.target = winDec1.target; + + + /* winDec1 = winDecTemp */ + winDec1.addrWin.baseHigh = winDecTemp.addrWin.baseHigh; + winDec1.addrWin.baseLow = winDecTemp.addrWin.baseLow; + winDec1.addrWin.size = winDecTemp.addrWin.size; + winDec1.enable = winDecTemp.enable; + winDec1.target = winDecTemp.target; + + + /* now set the new values */ + + + mvAhbToMbusWinSet(winNum1,&winDec1); + mvAhbToMbusWinSet(winNum2,&winDec2); + + + + + + /* now we will treat the remap windows if exist */ + + + /* now check if one or both windows has a remap window + as well after the swap ! */ + + /* if a window had a remap value differnt than the base value + before the swap , then after the swap the remap value will be + equal to the base value unless both windows has a remap windows*/ + + /* first get old values */ + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum1,&remapRegs1)) + { + remapBaseLow1 = MV_REG_READ(remapRegs1.lowRegOffs); + remapBaseHigh1 = MV_REG_READ(remapRegs1.highRegOffs); + + } + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2,&remapRegs2)) + { + remapBaseLow2 = MV_REG_READ(remapRegs2.lowRegOffs); + remapBaseHigh2 = MV_REG_READ(remapRegs2.highRegOffs); + + + } + + /* now do the swap */ + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum1,&remapRegs1)) + { + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2,&remapRegs2)) + { + /* Two windows has a remap !!! so swap */ + + MV_REG_WRITE(remapRegs2.highRegOffs,remapBaseHigh1); + MV_REG_WRITE(remapRegs2.lowRegOffs,remapBaseLow1); + + MV_REG_WRITE(remapRegs1.highRegOffs,remapBaseHigh2); + MV_REG_WRITE(remapRegs1.lowRegOffs,remapBaseLow2); + + + + } + else + { + /* remap == base */ + MV_REG_WRITE(remapRegs1.highRegOffs,winDec1.addrWin.baseHigh); + MV_REG_WRITE(remapRegs1.lowRegOffs,winDec1.addrWin.baseLow); + + } + + } + else if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2,&remapRegs2)) + { + /* remap == base */ + MV_REG_WRITE(remapRegs2.highRegOffs,winDec2.addrWin.baseHigh); + MV_REG_WRITE(remapRegs2.lowRegOffs,winDec2.addrWin.baseLow); + + } + + + + return MV_OK; + + +} + + + +#if defined(MV_88F1181) + +/******************************************************************************* +* mvAhbToMbusXbarCtrlSet - Set The CPU master Xbar arbitration. +* +* DESCRIPTION: +* This function sets CPU Mbus Arbiter +* +* INPUT: +* pPizzaArbArray - A priority Structure describing 16 "pizza slices". At +* each clock cycle, the crossbar arbiter samples all +* requests and gives the bus to the next agent according +* to the "pizza". +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if paramers to function invalid. +* +*******************************************************************************/ +MV_STATUS mvMbusArbSet(MV_MBUS_ARB_TARGET *pPizzaArbArray) +{ + MV_U32 sliceNum; + MV_U32 xbarCtrl = 0; + MV_MBUS_ARB_TARGET xbarTarget; + + /* 1) Set crossbar control low register */ + for (sliceNum = 0; sliceNum < MRLR_SLICE_NUM; sliceNum++) + { + xbarTarget = pPizzaArbArray[sliceNum]; + + /* sliceNum parameter check */ + if (xbarTarget > MAX_MBUS_ARB_TARGETS) + { + mvOsPrintf("mvAhbToMbusXbarCtrlSet: ERR. Can't set Target %d\n", + xbarTarget); + return MV_ERROR; + } + xbarCtrl |= (xbarTarget << MRLR_LOW_ARB_OFFS(sliceNum)); + } + /* Write to crossbar control low register */ + MV_REG_WRITE(MBUS_ARBITER_LOW_REG, xbarCtrl); + + xbarCtrl = 0; + + /* 2) Set crossbar control high register */ + for (sliceNum = MRLR_SLICE_NUM; + sliceNum < MRLR_SLICE_NUM+MRHR_SLICE_NUM; + sliceNum++) + { + + xbarTarget = pPizzaArbArray[sliceNum]; + + /* sliceNum parameter check */ + if (xbarTarget > MAX_MBUS_ARB_TARGETS) + { + mvOsPrintf("mvAhbToMbusXbarCtrlSet: ERR. Can't set Target %d\n", + xbarTarget); + return MV_ERROR; + } + xbarCtrl |= (xbarTarget << MRHR_HIGH_ARB_OFFS(sliceNum)); + } + /* Write to crossbar control high register */ + MV_REG_WRITE(MBUS_ARBITER_HIGH_REG, xbarCtrl); + + return MV_OK; +} + +/******************************************************************************* +* mvMbusArbCtrlSet - Set MBus Arbiter control register +* +* DESCRIPTION: +* +* INPUT: +* ctrl - pointer to MV_MBUS_ARB_CTRL register +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if paramers to function invalid. +* +*******************************************************************************/ +MV_STATUS mvMbusArbCtrlSet(MV_MBUS_ARB_CTRL *ctrl) +{ + + if (ctrl->highPrio == MV_FALSE) + { + MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_ARM_TOP); + } + else + { + MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_ARM_TOP); + } + + if (ctrl->fixedRoundRobin == MV_FALSE) + { + MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_TARGET_FIXED); + } + else + { + MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_TARGET_FIXED); + } + + if (ctrl->starvEn == MV_FALSE) + { + MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_REQ_CTRL_EN); + } + else + { + MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_REQ_CTRL_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* mvMbusArbCtrlGet - Get MBus Arbiter control register +* +* DESCRIPTION: +* +* INPUT: +* ctrl - pointer to MV_MBUS_ARB_CTRL register +* +* OUTPUT: +* ctrl - pointer to MV_MBUS_ARB_CTRL register +* +* RETURN: +* MV_ERROR if paramers to function invalid. +* +*******************************************************************************/ +MV_STATUS mvMbusArbCtrlGet(MV_MBUS_ARB_CTRL *ctrl) +{ + + MV_U32 ctrlReg = MV_REG_READ(MBUS_ARBITER_CTRL_REG); + + if (ctrlReg & MACR_ARB_ARM_TOP) + { + ctrl->highPrio = MV_TRUE; + } + else + { + ctrl->highPrio = MV_FALSE; + } + + if (ctrlReg & MACR_ARB_TARGET_FIXED) + { + ctrl->fixedRoundRobin = MV_TRUE; + } + else + { + ctrl->fixedRoundRobin = MV_FALSE; + } + + if (ctrlReg & MACR_ARB_REQ_CTRL_EN) + { + ctrl->starvEn = MV_TRUE; + } + else + { + ctrl->starvEn = MV_FALSE; + } + + + return MV_OK; +} + +#endif /* #if defined(MV_88F1181) */ + + + +/******************************************************************************* +* ahbToMbusRemapRegOffsGet - Get CPU address remap register offsets +* +* DESCRIPTION: +* CPU to PCI address remap registers offsets are inconsecutive. +* This function returns PCI address remap registers offsets. +* +* INPUT: +* winNum - Address decode window number. See MV_U32 enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if winNum is not a PCI one. +* +*******************************************************************************/ +static MV_STATUS ahbToMbusRemapRegOffsGet(MV_U32 winNum, + AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs) +{ + switch (winNum) + { + case 0: + case 1: + pRemapRegs->lowRegOffs = AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum); + pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum); + break; + case 2: + case 3: + if((mvCtrlModelGet() == MV_5281_DEV_ID) || + (mvCtrlModelGet() == MV_1281_DEV_ID) || + (mvCtrlModelGet() == MV_6183_DEV_ID) || + (mvCtrlModelGet() == MV_6183L_DEV_ID)) + { + pRemapRegs->lowRegOffs = AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum); + pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum); + break; + } + else + { + pRemapRegs->lowRegOffs = 0; + pRemapRegs->highRegOffs = 0; + + DB(mvOsPrintf("ahbToMbusRemapRegOffsGet: ERR. Invalid winNum %d\n", + winNum)); + return MV_NO_SUCH; + } + default: + { + pRemapRegs->lowRegOffs = 0; + pRemapRegs->highRegOffs = 0; + + DB(mvOsPrintf("ahbToMbusRemapRegOffsGet: ERR. Invalid winNum %d\n", + winNum)); + return MV_NO_SUCH; + } + } + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusAddDecShow - Print the AHB to MBus bridge address decode map. +* +* DESCRIPTION: +* This function print the CPU address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvAhbToMbusAddDecShow(MV_VOID) +{ + MV_AHB_TO_MBUS_DEC_WIN win; + MV_U32 winNum; + mvOsOutput( "\n" ); + mvOsOutput( "AHB To MBUS Bridge:\n" ); + mvOsOutput( "-------------------\n" ); + + for( winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++ ) + { + memset( &win, 0, sizeof(MV_AHB_TO_MBUS_DEC_WIN) ); + + mvOsOutput( "win%d - ", winNum ); + + if( mvAhbToMbusWinGet( winNum, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + + } + else + mvOsOutput( "disable\n" ); + } + } + +} + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.h new file mode 100644 index 0000000..1b352a1 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbus.h @@ -0,0 +1,130 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbush +#define __INCmvAhbToMbush + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* defines */ + +#if defined(MV_88F1181) +/* This enumerator defines the Marvell controller possible MBUS arbiter */ +/* target ports. It is used to define crossbar priority scheame (pizza) */ +typedef enum _mvMBusArbTargetId +{ + DRAM_MBUS_ARB_TARGET = 0, /* Port 0 -> DRAM interface */ + TWSI_MBUS_ARB_TARGET = 1, /* Port 1 -> TWSI */ + ARM_MBUS_ARB_TARGET = 2, /* Port 2 -> ARM */ + PEX1_MBUS_ARB_TARGET = 3, /* Port 3 -> PCI Express 1 */ + PEX0_MBUS_ARB_TARGET = 4, /* Port 4 -> PCI Express0 */ + MAX_MBUS_ARB_TARGETS +}MV_MBUS_ARB_TARGET; + +typedef struct _mvMBusArbCtrl +{ + MV_BOOL starvEn; + MV_BOOL highPrio; + MV_BOOL fixedRoundRobin; + +}MV_MBUS_ARB_CTRL; + +#endif /* #if defined(MV_88F1181) */ + +typedef struct _mvAhbtoMbusDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_AHB_TO_MBUS_DEC_WIN; + +/* mvAhbToMbus.h API list */ + +MV_STATUS mvAhbToMbusInit(MV_VOID); +MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin); +MV_STATUS mvAhbToMbusWinGet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin); +MV_STATUS mvAhbToMbusWinEnable(MV_U32 winNum,MV_BOOL enable); +MV_U32 mvAhbToMbusWinRemap(MV_U32 winNum, MV_ADDR_WIN *pAddrDecWin); +MV_U32 mvAhbToMbusWinTargetGet(MV_TARGET target); +MV_U32 mvAhbToMbusWinAvailGet(MV_VOID); +MV_STATUS mvAhbToMbusWinTargetSwap(MV_TARGET target1,MV_TARGET target2); + +#if defined(MV_88F1181) + +MV_STATUS mvMbusArbSet(MV_MBUS_ARB_TARGET *pPizzaArbArray); +MV_STATUS mvMbusArbCtrlSet(MV_MBUS_ARB_CTRL *ctrl); +MV_STATUS mvMbusArbCtrlGet(MV_MBUS_ARB_CTRL *ctrl); + +#endif /* #if defined(MV_88F1181) */ + + +MV_VOID mvAhbToMbusAddDecShow(MV_VOID); + + +#endif /* __INCmvAhbToMbush */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h new file mode 100644 index 0000000..97dc631 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h @@ -0,0 +1,143 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbusRegsh +#define __INCmvAhbToMbusRegsh + +/******************************/ +/* ARM Address Map Registers */ +/******************************/ + +#define MAX_AHB_TO_MBUS_WINS 9 +#define MV_AHB_TO_MBUS_INTREG_WIN 8 + + +#define AHB_TO_MBUS_WIN_CTRL_REG(winNum) (0x20000 + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_BASE_REG(winNum) (0x20004 + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum) (0x20008 + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum) (0x2000C + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_INTEREG_REG 0x20080 + +/* Window Control Register */ +/* AHB_TO_MBUS_WIN_CTRL_REG (ATMWCR)*/ +#define ATMWCR_WIN_ENABLE BIT0 /* Window Enable */ + +#define ATMWCR_WIN_TARGET_OFFS 4 /* The target interface associated + with this window*/ +#define ATMWCR_WIN_TARGET_MASK (0xf << ATMWCR_WIN_TARGET_OFFS) + +#define ATMWCR_WIN_ATTR_OFFS 8 /* The target interface attributes + Associated with this window */ +#define ATMWCR_WIN_ATTR_MASK (0xff << ATMWCR_WIN_ATTR_OFFS) + + +/* +Used with the Base register to set the address window size and location +Must be programed from LSB to MSB as sequence of 1’s followed +by sequence of 0’s. The number of 1’s specifies the size of the window +in 64 KB granularity (e.g. a value of 0x00FF specifies 256 = 16 MB). + +NOTE: A value of 0x0 specifies 64KB size. +*/ +#define ATMWCR_WIN_SIZE_OFFS 16 /* Window Size */ +#define ATMWCR_WIN_SIZE_MASK (0xffff << ATMWCR_WIN_SIZE_OFFS) +#define ATMWCR_WIN_SIZE_ALIGNMENT 0x10000 + +/* Window Base Register */ +/* AHB_TO_MBUS_WIN_BASE_REG (ATMWBR) */ + +/* +Used with the size field to set the address window size and location. +Corresponds to transaction address[31:16] +*/ +#define ATMWBR_BASE_OFFS 16 /* Base Address */ +#define ATMWBR_BASE_MASK (0xffff << ATMWBR_BASE_OFFS) +#define ATMWBR_BASE_ALIGNMENT 0x10000 + +/* Window Remap Low Register */ +/* AHB_TO_MBUS_WIN_REMAP_LOW_REG (ATMWRLR) */ + +/* +Used with the size field to specifies address bits[31:0] to be driven to +the target interface.: +target_addr[31:16] = (addr[31:16] & size[15:0]) | (remap[31:16] & ~size[15:0]) +*/ +#define ATMWRLR_REMAP_LOW_OFFS 16 /* Remap Address */ +#define ATMWRLR_REMAP_LOW_MASK (0xffff << ATMWRLR_REMAP_LOW_OFFS) +#define ATMWRLR_REMAP_LOW_ALIGNMENT 0x10000 + +/* Window Remap High Register */ +/* AHB_TO_MBUS_WIN_REMAP_HIGH_REG (ATMWRHR) */ + +/* +Specifies address bits[63:32] to be driven to the target interface. +target_addr[63:32] = (RemapHigh[31:0] +*/ +#define ATMWRHR_REMAP_HIGH_OFFS 0 /* Remap Address */ +#define ATMWRHR_REMAP_HIGH_MASK (0xffffffff << ATMWRHR_REMAP_HIGH_OFFS) + + +#endif /* __INCmvAhbToMbusRegsh */ + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.c new file mode 100644 index 0000000..95afefd --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.c @@ -0,0 +1,1064 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" +#include "cpu/mvCpu.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "mvSysHwConfig.h" +#include "mvSysDram.h" +//Patch by QNAP:Fix detect DRAM size +#include "gpp/mvGpp.h" +/////////////////////////////////////// +/*#define MV_DEBUG*/ +/* defines */ + +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +#if defined(MV_BRIDGE_SYNC_REORDER) /* used for sync write reordering in bridge */ +MV_U32 *mvUncachedParam = NULL; +#endif + + +/* locals */ +/* static functions */ +static MV_BOOL cpuTargetWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin); + +MV_TARGET * sampleAtResetTargetArray; +MV_TARGET sampleAtResetTargetArrayP[] = BOOT_TARGETS_NAME_ARRAY; +MV_TARGET sampleAtResetTargetArray6180P[] = BOOT_TARGETS_NAME_ARRAY_6180; +/******************************************************************************* +* mvCpuIfInit - Initialize Controller CPU interface +* +* DESCRIPTION: +* This function initialize Controller CPU interface: +* 1. Set CPU interface configuration registers. +* 2. Set CPU master Pizza arbiter control according to static +* configuration described in configuration file. +* 3. Opens CPU address decode windows. DRAM windows are assumed to be +* already set (auto detection). +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap) +{ + MV_U32 regVal; + MV_TARGET target; + MV_ADDR_WIN addrWin; + + if (cpuAddrWinMap == NULL) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. cpuAddrWinMap == NULL\n")); + return MV_ERROR; + } + + /*Initialize the boot target array according to device type*/ + if(mvCtrlModelGet() == MV_6180_DEV_ID) + sampleAtResetTargetArray = sampleAtResetTargetArray6180P; + else + sampleAtResetTargetArray = sampleAtResetTargetArrayP; + + /* Set ARM Configuration register */ + regVal = MV_REG_READ(CPU_CONFIG_REG); + regVal &= ~CPU_CONFIG_DEFAULT_MASK; + regVal |= CPU_CONFIG_DEFAULT; + MV_REG_WRITE(CPU_CONFIG_REG,regVal); + + /* First disable all CPU target windows */ + for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) + { + if ((MV_TARGET_IS_DRAM(target))||(target == INTER_REGS)) + { + continue; + } + +#if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PCI(target)) + { + continue; + } +#endif + +#if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PEX(target)) + { + continue; + } +#endif +#if defined(MV_RUN_FROM_FLASH) + /* Don't disable the boot device. */ + if (target == DEV_BOOCS) + { + continue; + } +#endif /* MV_RUN_FROM_FLASH */ + mvCpuIfTargetWinEnable(MV_CHANGE_BOOT_CS(target),MV_FALSE); + } + +#if defined(MV_RUN_FROM_FLASH) + /* Resize the bootcs windows before other windows, because this */ + /* window is enabled and will cause an overlap if not resized. */ + target = DEV_BOOCS; + + if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); + return MV_ERROR; + } + + addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; + addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; + if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) + { + DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", + cpuAddrWinMap[target].winNum)); + } + +#endif /* MV_RUN_FROM_FLASH */ + + /* Go through all targets in user table until table terminator */ + for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) + { + +#if defined(MV_RUN_FROM_FLASH) + if (target == DEV_BOOCS) + { + continue; + } +#endif /* MV_RUN_FROM_FLASH */ + + /* if DRAM auto sizing is used do not initialized DRAM target windows, */ + /* assuming this already has been done earlier. */ +#ifdef MV_DRAM_AUTO_SIZE + if (MV_TARGET_IS_DRAM(target)) + { +//Patch by QNAP:Fix detect DRAM size + if(target == 1){ + if(!mvGppValueGet(1,MV_GPP4)){ + MV_REG_WRITE(SDRAM_BASE_ADDR_REG(0,target), 0); + MV_REG_WRITE(SDRAM_SIZE_REG(0,target),0); + } + } +////////////////////////////////////////////////////////////////////// + continue; + } +#endif + +#if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PCI(target)) + { + continue; + } +#endif + +#if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PEX(target)) + { + continue; + } +#endif + /* If the target attribute is the same as the boot device attribute */ + /* then it's stays disable */ + if (MV_TARGET_IS_AS_BOOT(target)) + { + continue; + } + + if((0 == cpuAddrWinMap[target].addrWin.size) || + (DIS == cpuAddrWinMap[target].enable)) + + { + if (MV_OK != mvCpuIfTargetWinEnable(target, MV_FALSE)) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinEnable fail\n")); + return MV_ERROR; + } + + } + else + { + if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); + return MV_ERROR; + } + + addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; + addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; + if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) + { + DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", + cpuAddrWinMap[target].winNum)); + } + + + } + } + + return MV_OK; + + +} + +#if defined(MV_BRIDGE_SYNC_REORDER) +MV_STATUS mvCpuIfBridgeReorderWAInit(void) +{ + MV_ULONG tmpPhysAddress; + mvUncachedParam = mvOsIoUncachedMalloc(NULL, 4, &tmpPhysAddress, NULL); + if (mvUncachedParam == NULL) { + mvOsPrintf("Uncached memory allocation failed\n"); + return MV_ERROR; + } + return MV_OK; +} +#endif + + +/******************************************************************************* +* mvCpuIfTargetWinSet - Set CPU-to-peripheral target address window +* +* DESCRIPTION: +* This function sets a peripheral target (e.g. SDRAM bank0, PCI0_MEM0) +* address window, also known as address decode window. +* A new address decode window is set for specified target address window. +* If address decode window parameter structure enables the window, +* the routine will also enable the target window, allowing CPU to access +* the target window. +* +* INPUT: +* target - Peripheral target enumerator. +* pAddrDecWin - CPU target window data structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if CPU target window was set correctly, MV_ERROR in case of +* address window overlapps with other active CPU target window or +* trying to assign 36bit base address while CPU does not support that. +* The function returns MV_NOT_SUPPORTED, if the target is unsupported. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 existingWinNum; + MV_DRAM_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinSet: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* 2) Check if the requested window overlaps with current windows */ + if (MV_TRUE == cpuTargetWinOverlap(target, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvCpuIfTargetWinSet: ERR. Target %d overlap\n", target); + return MV_BAD_PARAM; + } + + if (MV_TARGET_IS_DRAM(target)) + { + /* copy relevant data to MV_DRAM_DEC_WIN structure */ + addrDecWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; + addrDecWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; + addrDecWin.addrWin.size = pAddrDecWin->addrWin.size; + addrDecWin.enable = pAddrDecWin->enable; + + + if (mvDramIfWinSet(target,&addrDecWin) != MV_OK); + { + mvOsPrintf("mvCpuIfTargetWinSet: mvDramIfWinSet Failed\n"); + return MV_ERROR; + } + + } + else + { + /* copy relevant data to MV_AHB_TO_MBUS_DEC_WIN structure */ + decWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; + decWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; + decWin.addrWin.size = pAddrDecWin->addrWin.size; + decWin.enable = pAddrDecWin->enable; + decWin.target = target; + + existingWinNum = mvAhbToMbusWinTargetGet(target); + + /* check if there is already another Window configured + for this target */ + if ((existingWinNum < MAX_AHB_TO_MBUS_WINS )&& + (existingWinNum != pAddrDecWin->winNum)) + { + /* if we want to enable the new winow number + passed by the user , then the old one should + be disabled */ + if (MV_TRUE == pAddrDecWin->enable) + { + /* be sure it is disabled */ + mvAhbToMbusWinEnable(existingWinNum , MV_FALSE); + } + } + + if (mvAhbToMbusWinSet(pAddrDecWin->winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinSet: mvAhbToMbusWinSet Failed\n"); + return MV_ERROR; + } + + } + + return MV_OK; +} + +/******************************************************************************* +* mvCpuIfTargetWinGet - Get CPU-to-peripheral target address window +* +* DESCRIPTION: +* Get the CPU peripheral target address window. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* pAddrDecWin - CPU target window information data structure. +* +* RETURN: +* MV_OK if target exist, MV_ERROR otherwise. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + + MV_U32 winNum=0xffffffff; + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_DRAM_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinGet: target %d is Illigal\n", target); + return MV_ERROR; + } + + if (MV_TARGET_IS_DRAM(target)) + { + if (mvDramIfWinGet(target,&addrDecWin) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", + target); + return MV_ERROR; + } + + /* copy relevant data to MV_CPU_DEC_WIN structure */ + pAddrDecWin->addrWin.baseLow = addrDecWin.addrWin.baseLow; + pAddrDecWin->addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pAddrDecWin->addrWin.size = addrDecWin.addrWin.size; + pAddrDecWin->enable = addrDecWin.enable; + pAddrDecWin->winNum = 0xffffffff; + + } + else + { + /* get the Window number associated with this target */ + + winNum = mvAhbToMbusWinTargetGet(target); + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + return MV_NO_SUCH; + + } + + if (mvAhbToMbusWinGet(winNum , &decWin) != MV_OK) + { + mvOsPrintf("%s: mvAhbToMbusWinGet Failed at winNum = %d\n", + __FUNCTION__, winNum); + return MV_ERROR; + + } + + /* copy relevant data to MV_CPU_DEC_WIN structure */ + pAddrDecWin->addrWin.baseLow = decWin.addrWin.baseLow; + pAddrDecWin->addrWin.baseHigh = decWin.addrWin.baseHigh; + pAddrDecWin->addrWin.size = decWin.addrWin.size; + pAddrDecWin->enable = decWin.enable; + pAddrDecWin->winNum = winNum; + + } + + + + + return MV_OK; +} + + +/******************************************************************************* +* mvCpuIfTargetWinEnable - Enable/disable a CPU address decode window +* +* DESCRIPTION: +* This function enable/disable a CPU address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling CPU accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* target - Peripheral target enumerator. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if protection window number was wrong, or the window +* overlapps other target window. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target,MV_BOOL enable) +{ + MV_U32 winNum, temp; + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinEnable: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* get the window and check if it exist */ + temp = mvCpuIfTargetWinGet(target, &addrDecWin); + if (MV_NO_SUCH == temp) + { + return (enable? MV_ERROR: MV_OK); + } + else if( MV_OK != temp) + { + mvOsPrintf("%s: ERR. Getting target %d failed.\n",__FUNCTION__, target); + return MV_ERROR; + } + + + /* check overlap */ + + if (MV_TRUE == enable) + { + if (MV_TRUE == cpuTargetWinOverlap(target, &addrDecWin.addrWin)) + { + DB(mvOsPrintf("%s: ERR. Target %d overlap\n",__FUNCTION__, target)); + return MV_ERROR; + } + + } + + + if (MV_TARGET_IS_DRAM(target)) + { + if (mvDramIfWinEnable(target , enable) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: mvDramIfWinEnable Failed at \n"); + return MV_ERROR; + + } + + } + else + { + /* get the Window number associated with this target */ + + winNum = mvAhbToMbusWinTargetGet(target); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + return (enable? MV_ERROR: MV_OK); + } + + if (mvAhbToMbusWinEnable(winNum , enable) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: Failed to enable window = %d\n", + winNum); + return MV_ERROR; + + } + + } + + return MV_OK; +} + + +/******************************************************************************* +* mvCpuIfTargetWinSizeGet - Get CPU target address window size +* +* DESCRIPTION: +* Get the size of CPU-to-peripheral target window. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit size. Function also returns '0' if window is closed. +* Function returns 0xFFFFFFFF in case of an error. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinSizeGet: target %d is Illigal\n", target); + return 0; + } + + /* Get the winNum window */ + if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinSizeGet:ERR. Getting target %d failed.\n", + target); + return 0; + } + + /* Check if window is enabled */ + if (addrDecWin.enable == MV_TRUE) + { + return (addrDecWin.addrWin.size); + } + else + { + return 0; /* Window disabled. return 0 */ + } +} + +/******************************************************************************* +* mvCpuIfTargetWinBaseLowGet - Get CPU target address window base low +* +* DESCRIPTION: +* CPU-to-peripheral target address window base is constructed of +* two parts: Low and high. +* This function gets the CPU peripheral target low base address. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit low base address. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + /* Get the target window */ + if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet:ERR. Getting target %d failed.\n", + target); + return 0xffffffff; + } + + if (MV_FALSE == addrDecWin.enable) + { + return 0xffffffff; + } + return (addrDecWin.addrWin.baseLow); +} + +/******************************************************************************* +* mvCpuIfTargetWinBaseHighGet - Get CPU target address window base high +* +* DESCRIPTION: +* CPU-to-peripheral target address window base is constructed of +* two parts: Low and high. +* This function gets the CPU peripheral target high base address. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit high base address. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + /* Get the target window */ + if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinBaseHighGet:ERR. Getting target %d failed.\n", + target); + return 0xffffffff; + } + + if (MV_FALSE == addrDecWin.enable) + { + return 0; + } + + return (addrDecWin.addrWin.baseHigh); +} + +#if defined(MV_INCLUDE_PEX) +/******************************************************************************* +* mvCpuIfPexRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* pexTarget - Peripheral target enumerator. Must be a PEX target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PEX one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 winNum; + + /* Check parameters */ + + if (mvCtrlPexMaxIfGet() > 1) + { + if ((!MV_TARGET_IS_PEX1(pexTarget))&&(!MV_TARGET_IS_PEX0(pexTarget))) + { + mvOsPrintf("mvCpuIfPexRemap: target %d is Illigal\n",pexTarget); + return 0xffffffff; + } + + } + else + { + if (!MV_TARGET_IS_PEX0(pexTarget)) + { + mvOsPrintf("mvCpuIfPexRemap: target %d is Illigal\n",pexTarget); + return 0xffffffff; + } + + } + + /* get the Window number associated with this target */ + winNum = mvAhbToMbusWinTargetGet(pexTarget); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvCpuIfPexRemap: mvAhbToMbusWinTargetGet Failed\n"); + return 0xffffffff; + + } + + return mvAhbToMbusWinRemap(winNum , pAddrDecWin); +} + +#endif + +#if defined(MV_INCLUDE_PCI) +/******************************************************************************* +* mvCpuIfPciRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* pciTarget - Peripheral target enumerator. Must be a PCI target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPciRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 winNum; + + /* Check parameters */ + if (!MV_TARGET_IS_PCI(pciTarget)) + { + mvOsPrintf("mvCpuIfPciRemap: target %d is Illigal\n",pciTarget); + return 0xffffffff; + } + + /* get the Window number associated with this target */ + winNum = mvAhbToMbusWinTargetGet(pciTarget); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvCpuIfPciRemap: mvAhbToMbusWinTargetGet Failed\n"); + return 0xffffffff; + + } + + return mvAhbToMbusWinRemap(winNum , pAddrDecWin); +} +#endif /* MV_INCLUDE_PCI */ + + +/******************************************************************************* +* mvCpuIfPciIfRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* pciTarget - Peripheral target enumerator. Must be a PCI target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciIfTarget, MV_ADDR_WIN *pAddrDecWin) +{ +#if defined(MV_INCLUDE_PEX) + if (MV_TARGET_IS_PEX(pciIfTarget)) + { + return mvCpuIfPexRemap(pciIfTarget,pAddrDecWin); + } +#endif +#if defined(MV_INCLUDE_PCI) + + if (MV_TARGET_IS_PCI(pciIfTarget)) + { + return mvCpuIfPciRemap(pciIfTarget,pAddrDecWin); + } +#endif + return 0; +} + + + +/******************************************************************************* +* mvCpuIfTargetOfBaseAddressGet - Get the target according to base address +* +* DESCRIPTION: +* +* INPUT: +* baseAddress - base address to be checked +* +* OUTPUT: +* None. +* +* RETURN: +* the target number that baseAddress belongs to or MAX_TARGETS is not +* found +* +*******************************************************************************/ + +MV_TARGET mvCpuIfTargetOfBaseAddressGet(MV_U32 baseAddress) +{ + MV_CPU_DEC_WIN win; + MV_U32 target; + + for( target = 0; target < MAX_TARGETS; target++ ) + { + if( mvCpuIfTargetWinGet( target, &win ) == MV_OK ) + { + if( win.enable ) + { + if ((baseAddress >= win.addrWin.baseLow) && + (baseAddress < win.addrWin.baseLow + win.addrWin.size)) break; + } + } + else return MAX_TARGETS; + + } + + return target; +} +/******************************************************************************* +* cpuTargetWinOverlap - Detect CPU address decode windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case CPU address decode +* windows overlapps. +* This function detects CPU address decode windows overlapping of a +* specified target. The function does not check the target itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* target - Peripheral target enumerator. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlaps current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL cpuTargetWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 targetNum; + MV_CPU_DEC_WIN addrDecWin; + MV_STATUS status; + + + for(targetNum = 0; targetNum < MAX_TARGETS; targetNum++) + { +#if defined(MV_RUN_FROM_FLASH) + if(MV_TARGET_IS_AS_BOOT(target)) + { + if (MV_CHANGE_BOOT_CS(targetNum) == target) + continue; + } +#endif /* MV_RUN_FROM_FLASH */ + + /* don't check our target or illegal targets */ + if (targetNum == target) + { + continue; + } + + /* Get window parameters */ + status = mvCpuIfTargetWinGet(targetNum, &addrDecWin); + if(MV_NO_SUCH == status) + { + continue; + } + if(MV_OK != status) + { + DB(mvOsPrintf("cpuTargetWinOverlap: ERR. TargetWinGet failed\n")); + return MV_TRUE; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + DB(mvOsPrintf( + "cpuTargetWinOverlap: Required target %d overlap current %d\n", + target, targetNum)); + return MV_TRUE; + } + } + + return MV_FALSE; + +} + +/******************************************************************************* +* mvCpuIfAddDecShow - Print the CPU address decode map. +* +* DESCRIPTION: +* This function print the CPU address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvCpuIfAddDecShow(MV_VOID) +{ + MV_CPU_DEC_WIN win; + MV_U32 target; + mvOsOutput( "\n" ); + mvOsOutput( "CPU Interface\n" ); + mvOsOutput( "-------------\n" ); + + for( target = 0; target < MAX_TARGETS; target++ ) + { + + memset( &win, 0, sizeof(MV_CPU_DEC_WIN) ); + + mvOsOutput( "%s ",mvCtrlTargetNameGet(target)); + mvOsOutput( "...." ); + + if( mvCpuIfTargetWinGet( target, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "base %08x, ", win.addrWin.baseLow ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + + } + else + mvOsOutput( "disable\n" ); + } + else if( mvCpuIfTargetWinGet( target, &win ) == MV_NO_SUCH ) + { + mvOsOutput( "no such\n" ); + } + } +} + +/******************************************************************************* +* mvCpuIfEnablePex - Enable PCI Express. +* +* DESCRIPTION: +* This function Enable PCI Express. +* +* INPUT: +* pexIf - PEX interface number. +* pexType - MV_PEX_ROOT_COMPLEX - root complex device +* MV_PEX_END_POINT - end point device +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +#if defined(MV_INCLUDE_PEX) +MV_VOID mvCpuIfEnablePex(MV_U32 pexIf, MV_PEX_TYPE pexType) +{ + /* Set pex mode incase S@R not exist */ + if( pexType == MV_PEX_END_POINT) + { + MV_REG_BIT_RESET(PEX_CTRL_REG(pexIf),PXCR_DEV_TYPE_CTRL_MASK); + /* Change pex mode in capability reg */ + MV_REG_BIT_RESET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_CAPABILITY_REG), BIT22); + MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_CAPABILITY_REG), BIT20); + + } + else + { + MV_REG_BIT_SET(PEX_CTRL_REG(pexIf),PXCR_DEV_TYPE_CTRL_MASK); + } + + /* CPU config register Pex enable */ + MV_REG_BIT_SET(CPU_CTRL_STAT_REG,CCSR_PCI_ACCESS_MASK); +} +#endif + + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.h new file mode 100644 index 0000000..224ed07 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIf.h @@ -0,0 +1,120 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfh +#define __INCmvCpuIfh + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIfRegs.h" +#include "ctrlEnv/sys/mvAhbToMbus.h" +#include "ddr2/mvDramIf.h" +#include "ctrlEnv/sys/mvSysDram.h" +#if defined(MV_INCLUDE_PEX) +#include "pex/mvPex.h" +#endif + +/* defines */ + +/* typedefs */ +/* This structure describes CPU interface address decode window */ +typedef struct _mvCpuIfDecWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_U32 winNum; /* Window Number in the AHB To Mbus bridge */ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_CPU_DEC_WIN; + + + +/* mvCpuIfLib.h API list */ + +/* mvCpuIfLib.h API list */ + +MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap); +MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target,MV_BOOL enable); +MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target); +MV_TARGET mvCpuIfTargetOfBaseAddressGet(MV_U32 baseAddress); +#if defined(MV_INCLUDE_PEX) +MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin); +MV_VOID mvCpuIfEnablePex(MV_U32 pexIf, MV_PEX_TYPE pexType); +#endif +#if defined(MV_INCLUDE_PCI) +MV_U32 mvCpuIfPciRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin); +#endif +MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin); + +MV_VOID mvCpuIfAddDecShow(MV_VOID); + +#if defined(MV88F6281) +MV_STATUS mvCpuIfBridgeReorderWAInit(void); +#endif + +#endif /* __INCmvCpuIfh */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfInit.S b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfInit.S new file mode 100644 index 0000000..b7efda0 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfInit.S @@ -0,0 +1,163 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define MV_ASMLANGUAGE +#include "mvOsAsm.h" +#include "mvDeviceId.h" +#include "mvCtrlEnvRegs.h" +#include "mvCpuIfRegs.h" +#include "mvCtrlEnvAsm.h" + + +/******************************************************************************* +* mvCpuIfPreInit - Make early initialization of CPU interface. +* +* DESCRIPTION: +* The function will initialize the CPU interface parameters that must +* be initialize before any BUS activity towards the DDR interface, +* which means it must be executed from ROM. Because of that, the function +* is implemented in assembly code. +* The function configure the following CPU config register parameters: +* 1) CPU2MbusLTickDrv +* 2) CPU2MbusLTickSample. +* NOTE: This function must be called AFTER the internal register +* base is modified to INTER_REGS_BASE. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +* r11 holds return function address. +*******************************************************************************/ +#define MV88F6281_PCKG_OPT 2 +#define MV88F6192_PCKG_OPT 1 +#define MV88F6180_PCKG_OPT 0 + + .globl _mvCpuIfPreInit +_mvCpuIfPreInit: + + mov r11, LR /* Save link register */ + + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r4, r5); + + /* goto calcConfigReg if device is 6281 */ + ldr r5, =MV88F6281_PCKG_OPT + cmp r4, r5 + beq calcConfigReg + + /* goto calcConfigReg if device is 6192/6190 */ + ldr r5, =MV88F6192_PCKG_OPT + cmp r4, r5 + beq calcConfigReg + + /* Else 6180 */ + /* Get the "sample on reset" register */ + MV_REG_READ_ASM (r4, r5, MPP_SAMPLE_AT_RESET) + ldr r5, =MSAR_CPUCLCK_MASK_6180 + and r5, r4, r5 + mov r5, r5, lsr #MSAR_CPUCLCK_OFFS_6180 + + ldr r4, =CPU_2_MBUSL_DDR_CLK_1x3 + cmp r5, #CPU_2_DDR_CLK_1x3_1 + beq setConfigReg + + ldr r4, =CPU_2_MBUSL_DDR_CLK_1x4 + cmp r5, #CPU_2_DDR_CLK_1x4_1 + beq setConfigReg + b setConfigReg + +calcConfigReg: + /* Get the "sample on reset" register */ + MV_REG_READ_ASM (r4, r5, MPP_SAMPLE_AT_RESET) + ldr r5, =MSAR_DDRCLCK_RTIO_MASK + and r5, r4, r5 + mov r5, r5, lsr #MSAR_DDRCLCK_RTIO_OFFS + + ldr r4, =CPU_2_MBUSL_DDR_CLK_1x3 + cmp r5, #CPU_2_DDR_CLK_1x3 + beq setConfigReg + + ldr r4, =CPU_2_MBUSL_DDR_CLK_1x4 + cmp r5, #CPU_2_DDR_CLK_1x4 + beq setConfigReg + + /* Else */ + ldr r4, =0 + +setConfigReg: + /* Read CPU Config register */ + MV_REG_READ_ASM (r7, r5, CPU_CONFIG_REG) + ldr r5, =~(CCR_CPU_2_MBUSL_TICK_DRV_MASK | CCR_CPU_2_MBUSL_TICK_SMPL_MASK) + and r7, r7, r5 /* Clear register fields */ + orr r7, r7, r4 /* Set the values according to the findings */ + MV_REG_WRITE_ASM (r7, r5, CPU_CONFIG_REG) + +done: + mov PC, r11 /* r11 is saved link register */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfRegs.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfRegs.h new file mode 100644 index 0000000..853b4c0 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvCpuIfRegs.h @@ -0,0 +1,298 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfRegsh +#define __INCmvCpuIfRegsh + +/****************************************/ +/* ARM Control and Status Registers Map */ +/****************************************/ + +#define CPU_CONFIG_REG 0x20100 +#define CPU_CTRL_STAT_REG 0x20104 +#define CPU_RSTOUTN_MASK_REG 0x20108 +#define CPU_SYS_SOFT_RST_REG 0x2010C +#define CPU_AHB_MBUS_CAUSE_INT_REG 0x20110 +#define CPU_AHB_MBUS_MASK_INT_REG 0x20114 +#define CPU_FTDLL_CONFIG_REG 0x20120 +#define CPU_L2_CONFIG_REG 0x20128 + + + +/* ARM Configuration register */ +/* CPU_CONFIG_REG (CCR) */ + + +/* Reset vector location */ +#define CCR_VEC_INIT_LOC_OFFS 1 +#define CCR_VEC_INIT_LOC_MASK BIT1 +/* reset at 0x00000000 */ +#define CCR_VEC_INIT_LOC_0000 (0 << CCR_VEC_INIT_LOC_OFFS) +/* reset at 0xFFFF0000 */ +#define CCR_VEC_INIT_LOC_FF00 (1 << CCR_VEC_INIT_LOC_OFFS) + + +#define CCR_AHB_ERROR_PROP_OFFS 2 +#define CCR_AHB_ERROR_PROP_MASK BIT2 +/* Erros are not propogated to AHB */ +#define CCR_AHB_ERROR_PROP_NO_INDICATE (0 << CCR_AHB_ERROR_PROP_OFFS) +/* Erros are propogated to AHB */ +#define CCR_AHB_ERROR_PROP_INDICATE (1 << CCR_AHB_ERROR_PROP_OFFS) + + +#define CCR_ENDIAN_INIT_OFFS 3 +#define CCR_ENDIAN_INIT_MASK BIT3 +#define CCR_ENDIAN_INIT_LITTLE (0 << CCR_ENDIAN_INIT_OFFS) +#define CCR_ENDIAN_INIT_BIG (1 << CCR_ENDIAN_INIT_OFFS) + + +#define CCR_INCR_EN_OFFS 4 +#define CCR_INCR_EN_MASK BIT4 +#define CCR_INCR_EN BIT4 + + +#define CCR_NCB_BLOCKING_OFFS 5 +#define CCR_NCB_BLOCKING_MASK (1 << CCR_NCB_BLOCKING_OFFS) +#define CCR_NCB_BLOCKING_NON (0 << CCR_NCB_BLOCKING_OFFS) +#define CCR_NCB_BLOCKING_EN (1 << CCR_NCB_BLOCKING_OFFS) + +#define CCR_CPU_2_MBUSL_TICK_DRV_OFFS 8 +#define CCR_CPU_2_MBUSL_TICK_DRV_MASK (0xF << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) +#define CCR_CPU_2_MBUSL_TICK_SMPL_OFFS 12 +#define CCR_CPU_2_MBUSL_TICK_SMPL_MASK (0xF << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS) +#define CCR_ICACH_PREF_BUF_ENABLE BIT16 +#define CCR_DCACH_PREF_BUF_ENABLE BIT17 + +/* Ratio options for CPU to DDR for 6281/6192/6190 */ +#define CPU_2_DDR_CLK_1x3 4 +#define CPU_2_DDR_CLK_1x4 6 + +/* Ratio options for CPU to DDR for 6281 only */ +#define CPU_2_DDR_CLK_2x9 7 +#define CPU_2_DDR_CLK_1x5 8 +#define CPU_2_DDR_CLK_1x6 9 + +/* Ratio options for CPU to DDR for 6180 only */ +#define CPU_2_DDR_CLK_1x3_1 0x5 +#define CPU_2_DDR_CLK_1x4_1 0x6 + +/* Default values for CPU to Mbus-L DDR Interface Tick Driver and */ +/* CPU to Mbus-L Tick Sample fields in CPU config register */ + +#define TICK_DRV_1x1 0 +#define TICK_DRV_1x2 0 +#define TICK_DRV_1x3 1 +#define TICK_DRV_1x4 2 +#define TICK_SMPL_1x1 0 +#define TICK_SMPL_1x2 1 +#define TICK_SMPL_1x3 0 +#define TICK_SMPL_1x4 0 + +#define CPU_2_MBUSL_DDR_CLK_1x2 \ + ((TICK_DRV_1x2 << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x2 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)) +#define CPU_2_MBUSL_DDR_CLK_1x3 \ + ((TICK_DRV_1x3 << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x3 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)) +#define CPU_2_MBUSL_DDR_CLK_1x4 \ + ((TICK_DRV_1x4 << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x4 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)) + +/* ARM Control and Status register */ +/* CPU_CTRL_STAT_REG (CCSR) */ + + +/* +This is used to block PCI express\PCI from access Socrates/Feroceon GP +while ARM boot is still in progress +*/ + +#define CCSR_PCI_ACCESS_OFFS 0 +#define CCSR_PCI_ACCESS_MASK BIT0 +#define CCSR_PCI_ACCESS_ENABLE (0 << CCSR_PCI_ACCESS_OFFS) +#define CCSR_PCI_ACCESS_DISBALE (1 << CCSR_PCI_ACCESS_OFFS) + +#define CCSR_ARM_RESET BIT1 +#define CCSR_SELF_INT BIT2 +#define CCSR_BIG_ENDIAN BIT15 + + +/* RSTOUTn Mask Register */ +/* CPU_RSTOUTN_MASK_REG (CRMR) */ + +#define CRMR_PEX_RST_OUT_OFFS 0 +#define CRMR_PEX_RST_OUT_MASK BIT0 +#define CRMR_PEX_RST_OUT_ENABLE (1 << CRMR_PEX_RST_OUT_OFFS) +#define CRMR_PEX_RST_OUT_DISABLE (0 << CRMR_PEX_RST_OUT_OFFS) + +#define CRMR_WD_RST_OUT_OFFS 1 +#define CRMR_WD_RST_OUT_MASK BIT1 +#define CRMR_WD_RST_OUT_ENABLE (1 << CRMR_WD_RST_OUT_OFFS) +#define CRMR_WD_RST_OUT_DISBALE (0 << CRMR_WD_RST_OUT_OFFS) + +#define CRMR_SOFT_RST_OUT_OFFS 2 +#define CRMR_SOFT_RST_OUT_MASK BIT2 +#define CRMR_SOFT_RST_OUT_ENABLE (1 << CRMR_SOFT_RST_OUT_OFFS) +#define CRMR_SOFT_RST_OUT_DISBALE (0 << CRMR_SOFT_RST_OUT_OFFS) + +/* System Software Reset Register */ +/* CPU_SYS_SOFT_RST_REG (CSSRR) */ + +#define CSSRR_SYSTEM_SOFT_RST BIT0 + +/* AHB to Mbus Bridge Interrupt Cause Register*/ +/* CPU_AHB_MBUS_CAUSE_INT_REG (CAMCIR) */ + +#define CAMCIR_ARM_SELF_INT BIT0 +#define CAMCIR_ARM_TIMER0_INT_REQ BIT1 +#define CAMCIR_ARM_TIMER1_INT_REQ BIT2 +#define CAMCIR_ARM_WD_TIMER_INT_REQ BIT3 + + +/* AHB to Mbus Bridge Interrupt Mask Register*/ +/* CPU_AHB_MBUS_MASK_INT_REG (CAMMIR) */ + +#define CAMCIR_ARM_SELF_INT_OFFS 0 +#define CAMCIR_ARM_SELF_INT_MASK BIT0 +#define CAMCIR_ARM_SELF_INT_EN (1 << CAMCIR_ARM_SELF_INT_OFFS) +#define CAMCIR_ARM_SELF_INT_DIS (0 << CAMCIR_ARM_SELF_INT_OFFS) + + +#define CAMCIR_ARM_TIMER0_INT_REQ_OFFS 1 +#define CAMCIR_ARM_TIMER0_INT_REQ_MASK BIT1 +#define CAMCIR_ARM_TIMER0_INT_REQ_EN (1 << CAMCIR_ARM_TIMER0_INT_REQ_OFFS) +#define CAMCIR_ARM_TIMER0_INT_REQ_DIS (0 << CAMCIR_ARM_TIMER0_INT_REQ_OFFS) + +#define CAMCIR_ARM_TIMER1_INT_REQ_OFFS 2 +#define CAMCIR_ARM_TIMER1_INT_REQ_MASK BIT2 +#define CAMCIR_ARM_TIMER1_INT_REQ_EN (1 << CAMCIR_ARM_TIMER1_INT_REQ_OFFS) +#define CAMCIR_ARM_TIMER1_INT_REQ_DIS (0 << CAMCIR_ARM_TIMER1_INT_REQ_OFFS) + +#define CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS 3 +#define CAMCIR_ARM_WD_TIMER_INT_REQ_MASK BIT3 +#define CAMCIR_ARM_WD_TIMER_INT_REQ_EN (1 << CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS) +#define CAMCIR_ARM_WD_TIMER_INT_REQ_DIS (0 << CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS) + +/* CPU FTDLL Config register (CFCR) fields */ +#define CFCR_FTDLL_ICACHE_TAG_OFFS 0 +#define CFCR_FTDLL_ICACHE_TAG_MASK (0x7F << CFCR_FTDLL_ICACHE_TAG_OFFS) +#define CFCR_FTDLL_DCACHE_TAG_OFFS 8 +#define CFCR_FTDLL_DCACHE_TAG_MASK (0x7F << CFCR_FTDLL_DCACHE_TAG_OFFS) +#define CFCR_FTDLL_OVERWRITE_ENABLE (1 << 15) +/* For Orion 2 D2 only */ +#define CFCR_MRVL_CPU_ID_OFFS 16 +#define CFCR_MRVL_CPU_ID_MASK (0x1 << CFCR_MRVL_CPU_ID_OFFS) +#define CFCR_ARM_CPU_ID (0x0 << CFCR_MRVL_CPU_ID_OFFS) +#define CFCR_MRVL_CPU_ID (0x1 << CFCR_MRVL_CPU_ID_OFFS) +#define CFCR_VFP_SUB_ARC_NUM_OFFS 7 +#define CFCR_VFP_SUB_ARC_NUM_MASK (0x1 << CFCR_VFP_SUB_ARC_NUM_OFFS) +#define CFCR_VFP_SUB_ARC_NUM_1 (0x0 << CFCR_VFP_SUB_ARC_NUM_OFFS) +#define CFCR_VFP_SUB_ARC_NUM_2 (0x1 << CFCR_VFP_SUB_ARC_NUM_OFFS) + +/* CPU_L2_CONFIG_REG fields */ +#define CL2CR_L2_ECC_EN_OFFS 2 +#define CL2CR_L2_ECC_EN_MASK (1 << CL2CR_L2_ECC_EN_OFFS) +#define CL2CR_L2_WT_MODE_OFFS 4 +#define CL2CR_L2_WT_MODE_MASK (1 << CL2CR_L2_WT_MODE_OFFS) + +/*******************************************/ +/* Main Interrupt Controller Registers Map */ +/*******************************************/ + +#define CPU_MAIN_INT_CAUSE_REG 0x20200 +#define CPU_MAIN_IRQ_MASK_REG 0x20204 +#define CPU_MAIN_FIQ_MASK_REG 0x20208 +#define CPU_ENPOINT_MASK_REG 0x2020C +#define CPU_MAIN_INT_CAUSE_HIGH_REG 0x20210 +#define CPU_MAIN_IRQ_MASK_HIGH_REG 0x20214 +#define CPU_MAIN_FIQ_MASK_HIGH_REG 0x20218 +#define CPU_ENPOINT_MASK_HIGH_REG 0x2021C + + +/*******************************************/ +/* ARM Doorbell Registers Map */ +/*******************************************/ + +#define CPU_HOST_TO_ARM_DRBL_REG 0x20400 +#define CPU_HOST_TO_ARM_MASK_REG 0x20404 +#define CPU_ARM_TO_HOST_DRBL_REG 0x20408 +#define CPU_ARM_TO_HOST_MASK_REG 0x2040C + + + +/* CPU control register map */ +/* Set bits means value is about to change according to new value */ +#define CPU_CONFIG_DEFAULT_MASK (CCR_VEC_INIT_LOC_MASK | CCR_AHB_ERROR_PROP_MASK) + +#define CPU_CONFIG_DEFAULT (CCR_VEC_INIT_LOC_FF00) + +/* CPU Control and status defaults */ +#define CPU_CTRL_STAT_DEFAULT_MASK (CCSR_PCI_ACCESS_MASK) + + +#define CPU_CTRL_STAT_DEFAULT (CCSR_PCI_ACCESS_ENABLE) + +#endif /* __INCmvCpuIfRegsh */ + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.c new file mode 100644 index 0000000..769475f --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.c @@ -0,0 +1,324 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#include "mvSysAudio.h" + +/******************************************************************************* +* mvAudioWinSet - Set AUDIO target address window +* +* DESCRIPTION: +* This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0) +* address window, also known as address decode window. +* After setting this target window, the AUDIO will be able to access the +* target within the address window. +* +* INPUT: +* winNum - AUDIO target address decode window number. +* pAddrDecWin - AUDIO target window data structure. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if address window overlapps with other address decode windows. +* MV_BAD_PARAM if base address is invalid parameter or target is +* unknown. +* +*******************************************************************************/ +MV_STATUS mvAudioWinSet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttribs; + MV_DEC_REGS decRegs; + + /* Parameter checking */ + if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvAudioWinSet:Error setting AUDIO window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = 0; + decRegs.sizeReg = 0; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~MV_AUDIO_WIN_ATTR_MASK; + decRegs.sizeReg |= (targetAttribs.attrib << MV_AUDIO_WIN_ATTR_OFFSET); + + /* set target ID */ + decRegs.sizeReg &= ~MV_AUDIO_WIN_TARGET_MASK; + decRegs.sizeReg |= (targetAttribs.targetId << MV_AUDIO_WIN_TARGET_OFFSET); + + if (pAddrDecWin->enable == MV_TRUE) + { + decRegs.sizeReg |= MV_AUDIO_WIN_ENABLE_MASK; + } + else + { + decRegs.sizeReg &= ~MV_AUDIO_WIN_ENABLE_MASK; + } + + MV_REG_WRITE( MV_AUDIO_WIN_CTRL_REG(winNum), decRegs.sizeReg); + MV_REG_WRITE( MV_AUDIO_WIN_BASE_REG(winNum), decRegs.baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvAudioWinGet - Get AUDIO peripheral target address window. +* +* DESCRIPTION: +* Get AUDIO peripheral target address window. +* +* INPUT: +* winNum - AUDIO target address decode window number. +* +* OUTPUT: +* pAddrDecWin - AUDIO target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvAudioWinGet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s : ERR. Invalid winNum %d\n", + __FUNCTION__, winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ( MV_AUDIO_WIN_BASE_REG(winNum) ); + decRegs.sizeReg = MV_REG_READ( MV_AUDIO_WIN_CTRL_REG(winNum) ); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) ) + { + mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & MV_AUDIO_WIN_ATTR_MASK) >> + MV_AUDIO_WIN_ATTR_OFFSET; + targetAttrib.targetId = (decRegs.sizeReg & MV_AUDIO_WIN_TARGET_MASK) >> + MV_AUDIO_WIN_TARGET_OFFSET; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if(decRegs.sizeReg & MV_AUDIO_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + return MV_OK; +} +/******************************************************************************* +* mvAudioAddrDecShow - Print the AUDIO address decode map. +* +* DESCRIPTION: +* This function print the AUDIO address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvAudioAddrDecShow(MV_VOID) +{ + + MV_AUDIO_DEC_WIN win; + int i; + + if (MV_FALSE == mvCtrlPwrClckGet(AUDIO_UNIT_ID, 0)) + return; + + + mvOsOutput( "\n" ); + mvOsOutput( "AUDIO:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < MV_AUDIO_MAX_ADDR_DECODE_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_AUDIO_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvAudioWinGet( i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + + +/******************************************************************************* +* mvAudioWinInit - Initialize the integrated AUDIO target address window. +* +* DESCRIPTION: +* Initialize the AUDIO peripheral target address window. +* +* INPUT: +* +* +* OUTPUT: +* +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvAudioInit(MV_VOID) +{ + int winNum; + MV_AUDIO_DEC_WIN audioWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_U32 status; + + mvAudioHalInit(); + + /* Initiate Audio address decode */ + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_AUDIO_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_U32 regVal = MV_REG_READ(MV_AUDIO_WIN_CTRL_REG(winNum)); + regVal &= ~MV_AUDIO_WIN_ENABLE_MASK; + MV_REG_WRITE(MV_AUDIO_WIN_CTRL_REG(winNum), regVal); + } + + for(winNum = 0; winNum < MV_AUDIO_MAX_ADDR_DECODE_WIN; winNum++) + { + + /* We will set the Window to DRAM_CS0 in default */ + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(SDRAM_CS0, + &cpuAddrDecWin); + + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + audioWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + audioWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + audioWin.addrWin.size = cpuAddrDecWin.addrWin.size; + audioWin.enable = MV_TRUE; + audioWin.target = SDRAM_CS0; + + if(MV_OK != mvAudioWinSet(winNum, &audioWin)) + { + return MV_ERROR; + } + } + } + + return MV_OK; +} + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.h new file mode 100644 index 0000000..f59eb9a --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysAudio.h @@ -0,0 +1,123 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVSysAudioH +#define __INCMVSysAudioH + +#include "mvCommon.h" +#include "audio/mvAudio.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/sys/mvCpuIf.h" + +/***********************************/ +/* Audio Address Decoding registers*/ +/***********************************/ + +#define MV_AUDIO_MAX_ADDR_DECODE_WIN 2 +#define MV_AUDIO_RECORD_WIN_NUM 0 +#define MV_AUDIO_PLAYBACK_WIN_NUM 1 + +#define MV_AUDIO_WIN_CTRL_REG(win) (AUDIO_REG_BASE + 0xA04 + ((win)<<3)) +#define MV_AUDIO_WIN_BASE_REG(win) (AUDIO_REG_BASE + 0xA00 + ((win)<<3)) + +#define MV_AUDIO_RECORD_WIN_CTRL_REG MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_RECORD_WIN_NUM) +#define MV_AUDIO_RECORD_WIN_BASE_REG MV_AUDIO_WIN_BASE_REG(MV_AUDIO_RECORD_WIN_NUM) +#define MV_AUDIO_PLAYBACK_WIN_CTRL_REG MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_PLAYBACK_WIN_NUM) +#define MV_AUDIO_PLAYBACK_WIN_BASE_REG MV_AUDIO_WIN_BASE_REG(MV_AUDIO_PLAYBACK_WIN_NUM) + + +/* BITs in Windows 0-3 Control and Base Registers */ +#define MV_AUDIO_WIN_ENABLE_BIT 0 +#define MV_AUDIO_WIN_ENABLE_MASK (1<= 2) +MV_TARGET tdmaAddrDecPrioTable[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif + + TBL_TERM +}; + +/******************************************************************************* +* mvCesaWinGet - Get TDMA target address window. +* +* DESCRIPTION: +* Get TDMA target address window. +* +* INPUT: +* winNum - TDMA target address decode window number. +* +* OUTPUT: +* pDecWin - TDMA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +static MV_STATUS mvCesaWinGet(MV_U32 winNum, MV_DEC_WIN *pDecWin) +{ + MV_DEC_WIN_PARAMS winParam; + MV_U32 sizeReg, baseReg; + + /* Parameter checking */ + if (winNum >= MV_CESA_TDMA_ADDR_DEC_WIN) + { + mvOsPrintf("%s : ERR. Invalid winNum %d\n", + __FUNCTION__, winNum); + return MV_NOT_SUPPORTED; + } + + baseReg = MV_REG_READ( MV_CESA_TDMA_BASE_ADDR_REG(winNum) ); + sizeReg = MV_REG_READ( MV_CESA_TDMA_WIN_CTRL_REG(winNum) ); + + /* Check if window is enabled */ + if(sizeReg & MV_CESA_TDMA_WIN_ENABLE_MASK) + { + pDecWin->enable = MV_TRUE; + + /* Extract window parameters from registers */ + winParam.targetId = (sizeReg & MV_CESA_TDMA_WIN_TARGET_MASK) >> MV_CESA_TDMA_WIN_TARGET_OFFSET; + winParam.attrib = (sizeReg & MV_CESA_TDMA_WIN_ATTR_MASK) >> MV_CESA_TDMA_WIN_ATTR_OFFSET; + winParam.size = (sizeReg & MV_CESA_TDMA_WIN_SIZE_MASK) >> MV_CESA_TDMA_WIN_SIZE_OFFSET; + winParam.baseAddr = (baseReg & MV_CESA_TDMA_WIN_BASE_MASK); + + /* Translate the decode window parameters to address decode struct */ + if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin)) + { + mvOsPrintf("Failed to translate register parameters to CESA address" \ + " decode window structure\n"); + return MV_ERROR; + } + } + else + { + pDecWin->enable = MV_FALSE; + } + return MV_OK; +} + +/******************************************************************************* +* cesaWinOverlapDetect - Detect CESA TDMA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case TDMA address decode +* windows overlapps. +* This function detects TDMA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - if the given address window overlap current address +* decode map, +* MV_FALSE - otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS cesaWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_CESA_TDMA_ADDR_DEC_WIN) + { + mvOsPrintf("mvCesaTdmaWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == cesaWinOverlapDetect(winNum, &pDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) + { + mvOsPrintf("mvCesaTdmaWinSet: Error setting CESA TDMA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pDecWin->target), + pDecWin->addrWin.baseLow, + pDecWin->addrWin.size); + return MV_ERROR; + } + + if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams)) + { + mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* set Size, Attributes and TargetID */ + sizeReg = (((winParams.targetId << MV_CESA_TDMA_WIN_TARGET_OFFSET) & MV_CESA_TDMA_WIN_TARGET_MASK) | + ((winParams.attrib << MV_CESA_TDMA_WIN_ATTR_OFFSET) & MV_CESA_TDMA_WIN_ATTR_MASK) | + ((winParams.size << MV_CESA_TDMA_WIN_SIZE_OFFSET) & MV_CESA_TDMA_WIN_SIZE_MASK)); + + if (pDecWin->enable == MV_TRUE) + { + sizeReg |= MV_CESA_TDMA_WIN_ENABLE_MASK; + } + else + { + sizeReg &= ~MV_CESA_TDMA_WIN_ENABLE_MASK; + } + + /* Update Base value */ + baseReg = (winParams.baseAddr & MV_CESA_TDMA_WIN_BASE_MASK); + + MV_REG_WRITE( MV_CESA_TDMA_WIN_CTRL_REG(winNum), sizeReg); + MV_REG_WRITE( MV_CESA_TDMA_BASE_ADDR_REG(winNum), baseReg); + + return MV_OK; +} + + +static MV_STATUS mvCesaTdmaAddrDecInit (void) +{ + MV_U32 winNum; + MV_STATUS status; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_DEC_WIN cesaWin; + MV_U32 winPrioIndex = 0; + + /* First disable all address decode windows */ + for(winNum=0; winNum= 2 */ + + + + +MV_STATUS mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle) +{ + MV_U32 cesaCryptEngBase; + MV_CPU_DEC_WIN addrDecWin; + + if(sizeof(MV_CESA_SRAM_MAP) > MV_CESA_SRAM_SIZE) + { + mvOsPrintf("mvCesaInit: Wrong SRAM map - %u > %d\n", + sizeof(MV_CESA_SRAM_MAP), MV_CESA_SRAM_SIZE); + return MV_FAIL; + } + + if (mvCpuIfTargetWinGet(CRYPT_ENG, &addrDecWin) == MV_OK) + cesaCryptEngBase = addrDecWin.addrWin.baseLow; + else + { + mvOsPrintf("mvCesaInit: ERR. mvCpuIfTargetWinGet failed\n"); + return MV_ERROR; + } + +#if (MV_CESA_VERSION >= 2) + mvCesaTdmaAddrDecInit(); +#endif /* MV_CESA_VERSION >= 2 */ + + return mvCesaHalInit(numOfSession, queueDepth, pSramBase, cesaCryptEngBase, + osHandle); + +} diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysCesa.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysCesa.h new file mode 100644 index 0000000..73bcdc5 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysCesa.h @@ -0,0 +1,100 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __mvSysCesa_h__ +#define __mvSysCesa_h__ + + +#include "mvCommon.h" +#include "cesa/mvCesa.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/sys/mvCpuIf.h" + +/***************************** TDMA Registers *************************************/ + +#define MV_CESA_TDMA_ADDR_DEC_WIN 4 + +#define MV_CESA_TDMA_BASE_ADDR_REG(win) (MV_CESA_TDMA_REG_BASE + 0xa00 + (win<<3)) + +#define MV_CESA_TDMA_WIN_CTRL_REG(win) (MV_CESA_TDMA_REG_BASE + 0xa04 + (win<<3)) + +#define MV_CESA_TDMA_WIN_ENABLE_BIT 0 +#define MV_CESA_TDMA_WIN_ENABLE_MASK (1 << MV_CESA_TDMA_WIN_ENABLE_BIT) + +#define MV_CESA_TDMA_WIN_TARGET_OFFSET 4 +#define MV_CESA_TDMA_WIN_TARGET_MASK (0xf << MV_CESA_TDMA_WIN_TARGET_OFFSET) + +#define MV_CESA_TDMA_WIN_ATTR_OFFSET 8 +#define MV_CESA_TDMA_WIN_ATTR_MASK (0xff << MV_CESA_TDMA_WIN_ATTR_OFFSET) + +#define MV_CESA_TDMA_WIN_SIZE_OFFSET 16 +#define MV_CESA_TDMA_WIN_SIZE_MASK (0xFFFF << MV_CESA_TDMA_WIN_SIZE_OFFSET) + +#define MV_CESA_TDMA_WIN_BASE_OFFSET 16 +#define MV_CESA_TDMA_WIN_BASE_MASK (0xFFFF << MV_CESA_TDMA_WIN_BASE_OFFSET) + + +MV_STATUS mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle); + +#endif diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.c new file mode 100644 index 0000000..6f76c2c --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.c @@ -0,0 +1,348 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ + +#include "ddr2/mvDramIf.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/sys/mvSysDram.h" + +/* #define MV_DEBUG */ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +static MV_BOOL sdramIfWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin); + +/******************************************************************************* +* mvDramIfWinSet - Set DRAM interface address decode window +* +* DESCRIPTION: +* This function sets DRAM interface address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* pAddrDecWin - SDRAM address window structure. +* +* OUTPUT: +* None +* +* RETURN: +* MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK +* otherwise. +*******************************************************************************/ +MV_STATUS mvDramIfWinSet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) +{ + MV_U32 baseReg=0,sizeReg=0; + MV_U32 baseToReg=0 , sizeToReg=0; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinSet: target %d is not SDRAM\n", target); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlaps with current enabled windows */ + if (MV_TRUE == sdramIfWinOverlap(target, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvDramIfWinSet: ERR. Target %d overlaps\n", target); + return MV_BAD_PARAM; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvDramIfWinSet:Error setting DRAM interface window %d."\ + "\nAddress 0x%08x is unaligned to size 0x%x.\n", + target, + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + /* read base register*/ + baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(0,target)); + + /* read size register */ + sizeReg = MV_REG_READ(SDRAM_SIZE_REG(0,target)); + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->addrWin.baseLow & SCBAR_BASE_MASK; + + /* Write to address decode Base Address Register */ + baseReg &= ~SCBAR_BASE_MASK; + baseReg |= baseToReg; + + /* Translate the given window size to register format */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, SCSR_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n",target); + return MV_BAD_PARAM; + } + + /* set size */ + sizeReg &= ~SCSR_SIZE_MASK; + /* Size is located at upper 16 bits */ + sizeReg |= (sizeToReg << SCSR_SIZE_OFFS); + + /* enable/Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + sizeReg |= SCSR_WIN_EN; + } + else + { + sizeReg &= ~SCSR_WIN_EN; + } + + /* 3) Write to address decode Base Address Register */ + MV_REG_WRITE(SDRAM_BASE_ADDR_REG(0,target), baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(SDRAM_SIZE_REG(0,target), sizeReg); + + return MV_OK; +} +/******************************************************************************* +* mvDramIfWinGet - Get DRAM interface address decode window +* +* DESCRIPTION: +* This function gets DRAM interface address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* +* OUTPUT: +* pAddrDecWin - SDRAM address window structure. +* +* RETURN: +* MV_BAD_PARAM if parameters are invalid or window is invalid, MV_OK +* otherwise. +*******************************************************************************/ +MV_STATUS mvDramIfWinGet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin) +{ + MV_U32 baseReg,sizeReg; + MV_U32 sizeRegVal; + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinGet: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* Read base and size registers */ + sizeReg = MV_REG_READ(SDRAM_SIZE_REG(0,target)); + baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(0,target)); + + sizeRegVal = (sizeReg & SCSR_SIZE_MASK) >> SCSR_SIZE_OFFS; + + pAddrDecWin->addrWin.size = ctrlRegToSize(sizeRegVal, + SCSR_SIZE_ALIGNMENT); + + /* Check if ctrlRegToSize returned OK */ + if (-1 == pAddrDecWin->addrWin.size) + { + mvOsPrintf("mvDramIfWinGet: size of target %d is Illigal\n", target); + return MV_ERROR; + } + + /* Extract base address */ + /* Base register [31:16] ==> baseLow[31:16] */ + pAddrDecWin->addrWin.baseLow = baseReg & SCBAR_BASE_MASK; + + pAddrDecWin->addrWin.baseHigh = 0; + + + if (sizeReg & SCSR_WIN_EN) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} +/******************************************************************************* +* mvDramIfWinEnable - Enable/Disable SDRAM address decode window +* +* DESCRIPTION: +* This function enable/Disable SDRAM address decode window. +* +* INPUT: +* target - System target. Use only SDRAM targets. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR in case function parameter are invalid, MV_OK otherewise. +* +*******************************************************************************/ +MV_STATUS mvDramIfWinEnable(MV_TARGET target, MV_BOOL enable) +{ + MV_DRAM_DEC_WIN addrDecWin; + + /* Check parameters */ + if (!MV_TARGET_IS_DRAM(target)) + { + mvOsPrintf("mvDramIfWinEnable: target %d is Illigal\n", target); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + if (MV_OK != mvDramIfWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvDramIfWinEnable:ERR. Getting target %d failed.\n", + target); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == sdramIfWinOverlap(target, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode winNum window */ + MV_REG_BIT_SET(SDRAM_SIZE_REG(0,target), SCSR_WIN_EN); + } + else + { /* Overlap detected */ + mvOsPrintf("mvDramIfWinEnable: ERR. Target %d overlap detect\n", + target); + return MV_ERROR; + } + } + else + { /* Disable address decode winNum window */ + MV_REG_BIT_RESET(SDRAM_SIZE_REG(0, target), SCSR_WIN_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* sdramIfWinOverlap - Check if an address window overlap an SDRAM address window +* +* DESCRIPTION: +* This function scan each SDRAM address decode window to test if it +* overlapps the given address windoow +* +* INPUT: +* target - SDRAM target where the function skips checking. +* pAddrDecWin - The tested address window for overlapping with +* SDRAM windows. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlaps any enabled address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL sdramIfWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin) +{ + MV_TARGET targetNum; + MV_DRAM_DEC_WIN addrDecWin; + + for(targetNum = SDRAM_CS0; targetNum < MV_DRAM_MAX_CS ; targetNum++) + { + /* don't check our winNum or illegal targets */ + if (targetNum == target) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvDramIfWinGet(targetNum, &addrDecWin)) + { + mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n"); + return MV_ERROR; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + mvOsPrintf( + "sdramIfWinOverlap: Required target %d overlap winNum %d\n", + target, targetNum); + return MV_TRUE; + } + } + + return MV_FALSE; +} + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.h new file mode 100644 index 0000000..7bd9c9d --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysDram.h @@ -0,0 +1,80 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __sysDram +#define __sysDram + +/* This structure describes CPU interface address decode window */ +typedef struct _mvDramIfDecWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ +}MV_DRAM_DEC_WIN; + +MV_STATUS mvDramIfWinSet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin); +MV_STATUS mvDramIfWinGet(MV_TARGET target, MV_DRAM_DEC_WIN *pAddrDecWin); +MV_STATUS mvDramIfWinEnable(MV_TARGET target, MV_BOOL enable); + +#endif diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysGbe.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysGbe.c new file mode 100644 index 0000000..7f6e4a5 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysGbe.c @@ -0,0 +1,658 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "ctrlEnv/sys/mvSysGbe.h" + + + +typedef struct _mvEthDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_ETH_DEC_WIN; + +MV_TARGET ethAddrDecPrioTap[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_DEVICE_CS0) + DEVICE_CS0, +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + DEVICE_CS1, +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + DEVICE_CS2, +#endif +#if defined(MV_INCLUDE_DEVICE_CS3) + DEVICE_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_IO, +#endif + TBL_TERM +}; + +static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin); +static MV_STATUS mvEthWinSet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); +static MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); + + +/******************************************************************************* +* mvEthWinInit - Initialize ETH address decode windows +* +* DESCRIPTION: +* This function initialize ETH window decode unit. It set the +* default address decode windows of the unit. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if setting fail. +*******************************************************************************/ +/* Configure EthDrv memory map registes. */ +MV_STATUS mvEthWinInit (int port) +{ + MV_U32 winNum, status, winPrioIndex=0, i, regVal=0; + MV_ETH_DEC_WIN ethWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + static MV_U32 accessProtReg = 0; + +#if (MV_ETH_VERSION <= 1) + static MV_BOOL isFirst = MV_TRUE; + + if(isFirst == MV_FALSE) + { + MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg); + return MV_OK; + } + isFirst = MV_FALSE; +#endif /* MV_GIGA_ETH_VERSION */ + + /* Initiate Ethernet address decode */ + + /* First disable all address decode windows */ + for(winNum=0; winNum= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == ethWinOverlapDetect(port, winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvEthWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvEthWinSet: Error setting Ethernet window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + + decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); + decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvEthWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.baseReg &= ~ETH_WIN_ATTR_MASK; + decRegs.baseReg |= targetAttribs.attrib << ETH_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.baseReg &= ~ETH_WIN_TARGET_MASK; + decRegs.baseReg |= targetAttribs.targetId << ETH_WIN_TARGET_OFFS; + + /* for the safe side we disable the window before writing the new + values */ + mvEthWinEnable(port, winNum, MV_FALSE); + MV_REG_WRITE(ETH_WIN_BASE_REG(port, winNum), decRegs.baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(ETH_WIN_SIZE_REG(port, winNum), decRegs.sizeReg); + + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvEthWinEnable(port, winNum, MV_TRUE); + } + + return MV_OK; +} + +/******************************************************************************* +* mvETHWinGet - Get dma peripheral target address window. +* +* DESCRIPTION: +* Get ETH peripheral target address window. +* +* INPUT: +* winNum - ETH to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - ETH target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); + decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (decRegs.baseReg & ETH_WIN_ATTR_MASK) >> ETH_WIN_ATTR_OFFS; + targetAttrib.targetId = + (decRegs.baseReg & ETH_WIN_TARGET_MASK) >> ETH_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (~(MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port))) & (1 << winNum) ) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvEthWinEnable - Enable/disable a ETH to target address window +* +* DESCRIPTION: +* This function enable/disable a ETH to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling ETH accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - ETH to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvEthWinEnable(int port, MV_U32 winNum,MV_BOOL enable) +{ + MV_ETH_DEC_WIN addrDecWin; + + /* Parameter checking */ + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthTargetWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvEthWinGet(port, winNum, &addrDecWin)) + { + mvOsPrintf("mvEthTargetWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == ethWinOverlapDetect(port, winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_RESET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); + } + else + { /* Overlap detected */ + mvOsPrintf("mvEthTargetWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { /* Disable address decode target window */ + MV_REG_BIT_SET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); + } + return MV_OK; +} + +/******************************************************************************* +* mvEthWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* window number +* +*******************************************************************************/ +MV_U32 mvEthWinTargetGet(int port, MV_TARGET target) +{ + MV_ETH_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + for (winNum=0; winNum= mvCtrlEthMaxPortGet()) + { + mvOsPrintf("mvEthProtWinSet:ERR. Invalid port number %d\n", portNo); + return MV_ERROR; + } + + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthProtWinSet:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) + { + mvOsPrintf("mvEthProtWinSet:ERR. Inv access param %d\n", access); + return MV_ERROR; + } + /* Read current protection register */ + protReg = MV_REG_READ(ETH_ACCESS_PROTECT_REG(portNo)); + + /* Clear protection window field */ + protReg &= ~(ETH_PROT_WIN_MASK(winNum)); + + /* Set new protection field value */ + protReg |= (access << (ETH_PROT_WIN_OFFS(winNum))); + + /* Write protection register back */ + MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(portNo), protReg); + + return MV_OK; +} + +/******************************************************************************* +* ethWinOverlapDetect - Detect ETH address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case ETH address decode +* windows overlapps. +* This function detects ETH address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex; + MV_ETH_DEC_WIN addrDecWin; + + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port)); + + for (winNumIndex=0; winNumIndex= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexInit: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + /* Enabled CPU access to PCI-Express */ + mvCpuIfEnablePex(pexIf, pexType); + + /* Start with bars */ + /* First disable all PEX bars*/ + for (bar = 0; bar < PEX_MAX_BARS; bar++) + { + if (PEX_INTER_REGS_BAR != bar) + { + if (MV_OK != mvPexBarEnable(pexIf, bar, MV_FALSE)) + { + mvOsPrintf("mvPexInit:mvPexBarEnable bar =%d failed \n",bar); + return MV_ERROR; + } + + } + + } + + /* and disable all PEX target windows */ + for (winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_FALSE)) + { + mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", + winNum); + return MV_ERROR; + + } + } + + /* Now, go through all bars*/ + + + +/******************************************************************************/ +/* Internal registers bar */ +/******************************************************************************/ + bar = PEX_INTER_REGS_BAR; + + /* we only open the bar , no need to open windows for this bar */ + + /* first get the CS attribute from the CPU Interface */ + if (MV_OK !=mvCpuIfTargetWinGet(INTER_REGS,&addrDecWin)) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",INTER_REGS); + return MV_ERROR; + } + + pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexBar.addrWin.size = addrDecWin.addrWin.size; + pexBar.enable = MV_TRUE; + + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + +/******************************************************************************/ +/* DRAM bar */ +/******************************************************************************/ + + bar = PEX_DRAM_BAR; + + pexBar.addrWin.size = 0; + + for (target = SDRAM_CS0;target < MV_DRAM_MAX_CS; target++ ) + { + + status = mvCpuIfTargetWinGet(target,&addrDecWin); + + if((MV_NO_SUCH == status)&&(target != SDRAM_CS0)) + { + continue; + } + + /* first get attributes from CPU If */ + if (MV_OK != status) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target); + return MV_ERROR; + } + if (addrDecWin.enable == MV_TRUE) + { + /* the base is the base of DRAM CS0 always */ + if (SDRAM_CS0 == target ) + { + pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + + } + + /* increment the bar size to be the sum of the size of all + DRAM chips selecs */ + pexBar.addrWin.size += addrDecWin.addrWin.size; + + /* set a Pex window for this target ! + DRAM CS always will have a Pex Window , and is not a + part of the priority table */ + pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexWin.addrWin.size = addrDecWin.addrWin.size; + + /* we disable the windows at first because we are not + sure that it is witihin bar boundries */ + pexWin.enable =MV_FALSE; + pexWin.target = target; + pexWin.targetBar = bar; + + if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++,&pexWin)) + { + mvOsPrintf("mvPexInit: ERR. mvPexTargetWinSet failed\n"); + return MV_ERROR; + } + } + } + + /* check if the size of the bar is illeggal */ + if (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT)) + { + /* try to get a good size */ + pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, + PXBCR_BAR_SIZE_ALIGNMENT); + } + + /* check if the size and base are valid */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,bar,&pexBar.addrWin)) + { + mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n",bar); + mvOsPrintf("it will be disabled\n"); + mvOsPrintf("please check Pex and CPU windows configuration\n"); + } + else + { + pexBar.enable = MV_TRUE; + + /* configure the bar */ + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + + /* after the bar was configured then we enable the Pex windows*/ + for (winNum = 0;winNum < pexCurrWin ;winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) + { + mvOsPrintf("mvPexInit: Can't enable window =%d\n",winNum); + return MV_ERROR; + } + + } + } + +/******************************************************************************/ +/* DEVICE bar */ +/******************************************************************************/ + +/* Open the Device BAR for non linux only */ +#ifndef MV_DISABLE_PEX_DEVICE_BAR + + /* then device bar*/ + bar = PEX_DEVICE_BAR; + + /* save the starting window */ + pexStartWindow = pexCurrWin; + pexBar.addrWin.size = 0; + pexBar.addrWin.baseLow = 0xffffffff; + pexBar.addrWin.baseHigh = 0; + maxBase = 0; + + for (target = DEV_TO_TARGET(START_DEV_CS);target < DEV_TO_TARGET(MV_DEV_MAX_CS); target++ ) + { + status = mvCpuIfTargetWinGet(target,&addrDecWin); + + if (MV_NO_SUCH == status) + { + continue; + } + + if (MV_OK != status) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target); + return MV_ERROR; + } + + if (addrDecWin.enable == MV_TRUE) + { + /* get the minimum base */ + if (addrDecWin.addrWin.baseLow < pexBar.addrWin.baseLow) + { + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + } + + /* get the maximum base */ + if (addrDecWin.addrWin.baseLow > maxBase) + { + maxBase = addrDecWin.addrWin.baseLow; + sizeOfMaxBase = addrDecWin.addrWin.size; + } + + /* search in the priority table for this target */ + for (winIndex = 0; pexDevBarPrioTable[winIndex] != TBL_TERM; + winIndex++) + { + if (pexDevBarPrioTable[winIndex] != target) + { + continue; + } + else if (pexDevBarPrioTable[winIndex] == target) + { + /*found it */ + + /* if the index of this target in the prio table is valid + then we set the Pex window for this target, a valid index is + an index that is lower than the number of the windows that + was not configured yet */ + + /* we subtract 2 always because the default and expantion + rom windows are always configured */ + if ( pexCurrWin < PEX_MAX_TARGET_WIN - 2) + { + /* set a Pex window for this target ! */ + pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexWin.addrWin.size = addrDecWin.addrWin.size; + + /* we disable the windows at first because we are not + sure that it is witihin bar boundries */ + pexWin.enable = MV_FALSE; + pexWin.target = target; + pexWin.targetBar = bar; + + if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++, + &pexWin)) + { + mvOsPrintf("mvPexInit: ERR. Window Set failed\n"); + return MV_ERROR; + } + } + } + } + } + } + + pexBar.addrWin.size = maxBase - pexBar.addrWin.baseLow + sizeOfMaxBase; + pexBar.enable = MV_TRUE; + + /* check if the size of the bar is illegal */ + if (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT)) + { + /* try to get a good size */ + pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, + PXBCR_BAR_SIZE_ALIGNMENT); + } + + /* check if the size and base are valid */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,bar,&pexBar.addrWin)) + { + mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n",bar); + mvOsPrintf("it will be disabled\n"); + mvOsPrintf("please check Pex and CPU windows configuration\n"); + } + else + { + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + + /* now enable the windows */ + for (winNum = pexStartWindow; winNum < pexCurrWin ; winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) + { + mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", + winNum); + return MV_ERROR; + } + } + } + +#endif + + return mvPexHalInit(pexIf, pexType); + +} + +/******************************************************************************* +* mvPexTargetWinSet - Set PEX to peripheral target address window BAR +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if PEX BAR target window was set correctly, +* MV_BAD_PARAM on bad params +* MV_ERROR otherwise +* (e.g. address window overlapps with other active PEX target window). +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin) +{ + + MV_DEC_REGS decRegs; + PEX_WIN_REG_INFO winRegInfo; + MV_TARGET_ATTRIB targetAttribs; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf,winNum,&winRegInfo); + + + if (MV_TRUE == pAddrDecWin->enable) + { + + /* 2) Check if the requested window overlaps with current windows */ + if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Target %d overlap\n", winNum); + return MV_BAD_PARAM; + } + + /* 2) Check if the requested window overlaps with current windows */ + if (MV_FALSE == pexIsWinWithinBar(pexIf,&pAddrDecWin->addrWin)) + { + mvOsPrintf("mvPexTargetWinSet: Win %d should be in bar boundries\n", + winNum); + return MV_BAD_PARAM; + } + + } + + + + /* read base register*/ + + if (winRegInfo.baseLowRegOffs) + { + decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs); + } + else + { + decRegs.baseReg = 0; + } + + if (winRegInfo.sizeRegOffs) + { + decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs); + } + else + { + decRegs.sizeReg =0; + } + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvPexTargetWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + /* enable\Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + decRegs.sizeReg |= PXWCR_WIN_EN; + } + else + { + decRegs.sizeReg &= ~PXWCR_WIN_EN; + } + + + /* clear bit location */ + decRegs.sizeReg &= ~PXWCR_WIN_BAR_MAP_MASK; + + /* set bar Mapping */ + if (pAddrDecWin->targetBar == 1) + { + decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR1; + } + else if (pAddrDecWin->targetBar == 2) + { + decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR2; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~PXWCR_ATTRIB_MASK; + decRegs.sizeReg |= targetAttribs.attrib << PXWCR_ATTRIB_OFFS; + /* set target ID */ + decRegs.sizeReg &= ~PXWCR_TARGET_MASK; + decRegs.sizeReg |= targetAttribs.targetId << PXWCR_TARGET_OFFS; + + + /* 3) Write to address decode Base Address Register */ + + if (winRegInfo.baseLowRegOffs) + { + MV_REG_WRITE(winRegInfo.baseLowRegOffs, decRegs.baseReg); + } + + /* write size reg */ + if (winRegInfo.sizeRegOffs) + { + if ((MV_PEX_WIN_DEFAULT == winNum)|| + (MV_PEX_WIN_EXP_ROM == winNum)) + { + /* clear size because there is no size field*/ + decRegs.sizeReg &= ~PXWCR_SIZE_MASK; + + /* clear enable because there is no enable field*/ + decRegs.sizeReg &= ~PXWCR_WIN_EN; + + } + + MV_REG_WRITE(winRegInfo.sizeRegOffs, decRegs.sizeReg); + } + + + return MV_OK; + +} + +/******************************************************************************* +* mvPexTargetWinGet - Get PEX to peripheral target address window +* +* DESCRIPTION: +* Get the PEX to peripheral target address window BAR. +* +* INPUT: +* pexIf - PEX interface number. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* pAddrBarWin - PEX target window information data structure. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttrib; + MV_DEC_REGS decRegs; + + PEX_WIN_REG_INFO winRegInfo; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf,winNum,&winRegInfo); + + /* read base register*/ + if (winRegInfo.baseLowRegOffs) + { + decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs); + } + else + { + decRegs.baseReg = 0; + } + + /* read size reg */ + if (winRegInfo.sizeRegOffs) + { + decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs); + } + else + { + decRegs.sizeReg =0; + } + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvPexTargetWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + + } + + if (decRegs.sizeReg & PXWCR_WIN_EN) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + + } + + + #if 0 + if (-1 == pAddrDecWin->addrWin.size) + { + return MV_ERROR; + } + #endif + + + /* get target bar */ + if ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) == PXWCR_WIN_BAR_MAP_BAR1 ) + { + pAddrDecWin->targetBar = 1; + } + else if ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) == + PXWCR_WIN_BAR_MAP_BAR2 ) + { + pAddrDecWin->targetBar = 2; + } + + /* attrib and targetId */ + pAddrDecWin->attrib = (decRegs.sizeReg & PXWCR_ATTRIB_MASK) >> + PXWCR_ATTRIB_OFFS; + pAddrDecWin->targetId = (decRegs.sizeReg & PXWCR_TARGET_MASK) >> + PXWCR_TARGET_OFFS; + + targetAttrib.attrib = pAddrDecWin->attrib; + targetAttrib.targetId = pAddrDecWin->targetId; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + return MV_OK; + +} + + +/******************************************************************************* +* mvPexTargetWinEnable - Enable/disable a PEX BAR window +* +* DESCRIPTION: +* This function enable/disable a PEX BAR window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling PEX accesses for that BAR (before enabling the +* window it is tested for overlapping). Otherwise, the window will +* be disabled. +* +* INPUT: +* pexIf - PEX interface number. +* bar - BAR to be accessed by slave. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf,MV_U32 winNum, MV_BOOL enable) +{ + PEX_WIN_REG_INFO winRegInfo; + MV_PEX_DEC_WIN addrDecWin; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinEnable: ERR. Invalid PEX If %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinEnable ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf,winNum,&winRegInfo); + + + /* if the address windows is disabled , we only disable the appropriare + pex window and ignore other settings */ + + if (MV_FALSE == enable) + { + + /* this is not relevant to default and expantion rom + windows */ + if (winRegInfo.sizeRegOffs) + { + if ((MV_PEX_WIN_DEFAULT != winNum)&& + (MV_PEX_WIN_EXP_ROM != winNum)) + { + MV_REG_BIT_RESET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN); + } + } + + } + else + { + if (MV_OK != mvPexTargetWinGet(pexIf,winNum, &addrDecWin)) + { + mvOsPrintf("mvPexTargetWinEnable: mvPexTargetWinGet Failed\n"); + return MV_ERROR; + } + + /* Check if the requested window overlaps with current windows */ + if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &addrDecWin.addrWin)) + { + mvOsPrintf("mvPexTargetWinEnable: ERR. Target %d overlap\n", winNum); + return MV_BAD_PARAM; + } + + if (MV_FALSE == pexIsWinWithinBar(pexIf,&addrDecWin.addrWin)) + { + mvOsPrintf("mvPexTargetWinEnable: Win %d should be in bar boundries\n", + winNum); + return MV_BAD_PARAM; + } + + + /* this is not relevant to default and expantion rom + windows */ + if (winRegInfo.sizeRegOffs) + { + if ((MV_PEX_WIN_DEFAULT != winNum)&& + (MV_PEX_WIN_EXP_ROM != winNum)) + { + MV_REG_BIT_SET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN); + } + } + + + } + + return MV_OK; + +} + + + +/******************************************************************************* +* mvPexTargetWinRemap - Set PEX to target address window remap. +* +* DESCRIPTION: +* The PEX interface supports remap of the BAR original address window. +* For each BAR it is possible to define a remap address. For example +* an address 0x12345678 that hits BAR 0x10 (SDRAM CS[0]) will be modified +* according to remap register but will also be targeted to the +* SDRAM CS[0]. +* +* INPUT: +* pexIf - PEX interface number. +* bar - Peripheral target enumerator accessed by slave. +* pAddrWin - Address window to be checked. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_REMAP_WIN *pAddrWin) +{ + + PEX_WIN_REG_INFO winRegInfo; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", + pexIf); + return MV_BAD_PARAM; + } + if (MV_PEX_WIN_DEFAULT == winNum) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", + winNum); + return MV_BAD_PARAM; + + } + + if (MV_IS_NOT_ALIGN(pAddrWin->addrWin.baseLow, PXWRR_REMAP_ALIGNMENT)) + { + mvOsPrintf("mvPexTargetWinRemap: Error remap PEX interface %d win %d."\ + "\nAddress 0x%08x is unaligned to size 0x%x.\n", + pexIf, + winNum, + pAddrWin->addrWin.baseLow, + pAddrWin->addrWin.size); + + return MV_ERROR; + } + + pexWinRegInfoGet(pexIf, winNum, &winRegInfo); + + /* Set remap low register value */ + MV_REG_WRITE(winRegInfo.remapLowRegOffs, pAddrWin->addrWin.baseLow); + + /* Skip base high settings if the BAR has only base low (32-bit) */ + if (0 != winRegInfo.remapHighRegOffs) + { + MV_REG_WRITE(winRegInfo.remapHighRegOffs, pAddrWin->addrWin.baseHigh); + } + + + if (pAddrWin->enable == MV_TRUE) + { + MV_REG_BIT_SET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + else + { + MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* mvPexTargetWinRemapEnable - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ + +MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, + MV_BOOL enable) +{ + PEX_WIN_REG_INFO winRegInfo; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", + pexIf); + return MV_BAD_PARAM; + } + if (MV_PEX_WIN_DEFAULT == winNum) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", + winNum); + return MV_BAD_PARAM; + + } + + + pexWinRegInfoGet(pexIf, winNum, &winRegInfo); + + if (enable == MV_TRUE) + { + MV_REG_BIT_SET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + else + { + MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + + return MV_OK; + +} + +/******************************************************************************* +* mvPexBarSet - Set PEX bar address and size +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexBarSet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin) +{ + MV_U32 regBaseLow; + MV_U32 regSize,sizeToReg; + + + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarSet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarSet: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + + if (pAddrWin->addrWin.size == 0) + { + mvOsPrintf("mvPexBarSet: Size zero is Illigal\n" ); + return MV_BAD_PARAM; + } + + + /* Check if the window complies with PEX spec */ + if (MV_TRUE != pexBarIsValid(pAddrWin->addrWin.baseLow, + pAddrWin->addrWin.size)) + { + mvOsPrintf("mvPexBarSet: ERR. Target %d window invalid\n", barNum); + return MV_BAD_PARAM; + } + + /* 2) Check if the requested bar overlaps with current bars */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,barNum, &pAddrWin->addrWin)) + { + mvOsPrintf("mvPexBarSet: ERR. Target %d overlap\n", barNum); + return MV_BAD_PARAM; + } + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrWin->addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); + + /* Read bar size */ + if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ + { + regSize = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvPexBarSet: ERR. Target BAR %d size invalid.\n",barNum); + return MV_BAD_PARAM; + } + + regSize &= ~PXBCR_BAR_SIZE_MASK; + regSize |= (sizeToReg << PXBCR_BAR_SIZE_OFFS) ; + + MV_REG_WRITE(PEX_BAR_CTRL_REG(pexIf,barNum),regSize); + + } + + /* set size */ + + + + /* Read base address low */ + regBaseLow = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, + PEX_MV_BAR_BASE(barNum))); + + /* clear current base */ + if (PEX_INTER_REGS_BAR == barNum) + { + regBaseLow &= ~PXBIR_BASE_MASK; + regBaseLow |= (pAddrWin->addrWin.baseLow & PXBIR_BASE_MASK); + } + else + { + regBaseLow &= ~PXBR_BASE_MASK; + regBaseLow |= (pAddrWin->addrWin.baseLow & PXBR_BASE_MASK); + } + + /* if we had a previous value that contain the bar type (MeM\IO), we want to + restore it */ + regBaseLow |= PEX_BAR_DEFAULT_ATTRIB; + + + + /* write base low */ + MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum)), + regBaseLow); + + if (pAddrWin->addrWin.baseHigh != 0) + { + /* Read base address high */ + MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum)), + pAddrWin->addrWin.baseHigh); + + } + + /* lastly enable the Bar */ + if (pAddrWin->enable == MV_TRUE) + { + if (PEX_INTER_REGS_BAR != barNum) /* internal registers + are enabled always */ + { + MV_REG_BIT_SET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + } + } + else if (MV_FALSE == pAddrWin->enable) + { + if (PEX_INTER_REGS_BAR != barNum) /* internal registers + are enabled always */ + { + MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + } + + } + + + + return MV_OK; +} + + +/******************************************************************************* +* mvPexBarGet - Get PEX bar address and size +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ + +MV_STATUS mvPexBarGet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin) +{ + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarGet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarGet: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + /* read base low */ + pAddrWin->addrWin.baseLow = + MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum))); + + + if (PEX_INTER_REGS_BAR == barNum) + { + pAddrWin->addrWin.baseLow &= PXBIR_BASE_MASK; + } + else + { + pAddrWin->addrWin.baseLow &= PXBR_BASE_MASK; + } + + + /* read base high */ + pAddrWin->addrWin.baseHigh = + MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum))); + + + /* Read bar size */ + if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ + { + pAddrWin->addrWin.size = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); + + /* check if enable or not */ + if (pAddrWin->addrWin.size & PXBCR_BAR_EN) + { + pAddrWin->enable = MV_TRUE; + } + else + { + pAddrWin->enable = MV_FALSE; + } + + /* now get the size */ + pAddrWin->addrWin.size &= PXBCR_BAR_SIZE_MASK; + pAddrWin->addrWin.size >>= PXBCR_BAR_SIZE_OFFS; + + pAddrWin->addrWin.size = ctrlRegToSize(pAddrWin->addrWin.size, + PXBCR_BAR_SIZE_ALIGNMENT); + + } + else /* PEX_INTER_REGS_BAR */ + { + pAddrWin->addrWin.size = INTER_REGS_SIZE; + pAddrWin->enable = MV_TRUE; + } + + + return MV_OK; +} + +/******************************************************************************* +* mvPexBarEnable - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ + + +MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable) +{ + + MV_PEX_BAR pexBar; + + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarEnable: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarEnable: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + if (PEX_INTER_REGS_BAR == barNum) + { + if (MV_TRUE == enable) + { + return MV_OK; + } + else + { + return MV_ERROR; + } + } + + + if (MV_FALSE == enable) + { + /* disable bar and quit */ + MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + return MV_OK; + } + + /* else */ + + if (mvPexBarGet(pexIf,barNum,&pexBar) != MV_OK) + { + mvOsPrintf("mvPexBarEnable: mvPexBarGet Failed\n"); + return MV_ERROR; + + } + + if (MV_TRUE == pexBar.enable) + { + /* it is already enabled !!! */ + return MV_OK; + } + + /* else enable the bar*/ + + pexBar.enable = MV_TRUE; + + if (mvPexBarSet(pexIf,barNum,&pexBar) != MV_OK) + { + mvOsPrintf("mvPexBarEnable: mvPexBarSet Failed\n"); + return MV_ERROR; + + } + + return MV_OK; +} + + +/******************************************************************************* +* pexWinOverlapDetect - Detect address windows overlapping +* +* DESCRIPTION: +* This function detects address window overlapping of a given address +* window in PEX BARs. +* +* INPUT: +* pAddrWin - Address window to be checked. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexWinOverlapDetect(MV_U32 pexIf, + MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 win; + MV_PEX_DEC_WIN addrDecWin; + + + for(win = 0; win < PEX_MAX_TARGET_WIN -2 ; win++) + { + /* don't check our target or illegal targets */ + if (winNum == win) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvPexTargetWinGet(pexIf, win, &addrDecWin)) + { + mvOsPrintf("pexWinOverlapDetect: ERR. TargetWinGet failed win=%x\n", + win); + return MV_ERROR; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + mvOsPrintf("pexWinOverlapDetect: winNum %d overlap current %d\n", + winNum, win); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* pexIsWinWithinBar - Detect if address is within PEX bar boundries +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexIsWinWithinBar(MV_U32 pexIf, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 bar; + MV_PEX_BAR addrDecWin; + + for(bar = 0; bar < PEX_MAX_BARS; bar++) + { + + /* Get window parameters */ + if (MV_OK != mvPexBarGet(pexIf, bar, &addrDecWin)) + { + mvOsPrintf("pexIsWinWithinBar: ERR. mvPexBarGet failed\n"); + return MV_ERROR; + } + + /* Do not check disabled bars */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + + if(MV_TRUE == ctrlWinWithinWinTest(pAddrWin, &addrDecWin.addrWin)) + { + return MV_TRUE; + } + } + + return MV_FALSE; + +} + +/******************************************************************************* +* pexBarOverlapDetect - Detect address windows overlapping +* +* DESCRIPTION: +* This function detects address window overlapping of a given address +* window in PEX BARs. +* +* INPUT: +* pAddrWin - Address window to be checked. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexBarOverlapDetect(MV_U32 pexIf, + MV_U32 barNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 bar; + MV_PEX_BAR barDecWin; + + + for(bar = 0; bar < PEX_MAX_BARS; bar++) + { + /* don't check our target or illegal targets */ + if (barNum == bar) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvPexBarGet(pexIf, bar, &barDecWin)) + { + mvOsPrintf("pexBarOverlapDetect: ERR. TargetWinGet failed\n"); + return MV_ERROR; + } + + /* don'nt check disabled bars */ + if (barDecWin.enable == MV_FALSE) + { + continue; + } + + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &barDecWin.addrWin)) + { + mvOsPrintf("pexBarOverlapDetect: winNum %d overlap current %d\n", + barNum, bar); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* pexBarIsValid - Check if the given address window is valid +* +* DESCRIPTION: +* PEX spec restrict BAR base to be aligned to BAR size. +* This function checks if the given address window is valid. +* +* INPUT: +* baseLow - 32bit low base address. +* size - Window size. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the address window is valid, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_STATUS pexBarIsValid(MV_U32 baseLow, MV_U32 size) +{ + + /* PCI spec restrict BAR base to be aligned to BAR size */ + if(MV_IS_NOT_ALIGN(baseLow, size)) + { + return MV_ERROR; + } + else + { + return MV_TRUE; + } + + return MV_TRUE; +} + +/******************************************************************************* +* pexBarRegInfoGet - Get BAR register information +* +* DESCRIPTION: +* PEX BARs registers offsets are inconsecutive. +* This function gets a PEX BAR register information like register offsets +* and function location of the BAR. +* +* INPUT: +* pexIf - PEX interface number. +* bar - The PEX BAR in question. +* +* OUTPUT: +* pBarRegInfo - BAR register info struct. +* +* RETURN: +* MV_BAD_PARAM when bad parameters ,MV_ERROR on error ,othewise MV_OK +* +*******************************************************************************/ +static MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, + MV_U32 winNum, + PEX_WIN_REG_INFO *pWinRegInfo) +{ + + if ((winNum >= 0)&&(winNum <=3)) + { + pWinRegInfo->baseLowRegOffs = PEX_WIN0_3_BASE_REG(pexIf,winNum); + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN0_3_CTRL_REG(pexIf,winNum); + pWinRegInfo->remapLowRegOffs = PEX_WIN0_3_REMAP_REG(pexIf,winNum); + pWinRegInfo->remapHighRegOffs = 0; + } + else if ((winNum >= 4)&&(winNum <=5)) + { + pWinRegInfo->baseLowRegOffs = PEX_WIN4_5_BASE_REG(pexIf,winNum); + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN4_5_CTRL_REG(pexIf,winNum); + pWinRegInfo->remapLowRegOffs = PEX_WIN4_5_REMAP_REG(pexIf,winNum); + pWinRegInfo->remapHighRegOffs = PEX_WIN4_5_REMAP_HIGH_REG(pexIf,winNum); + + } + else if (MV_PEX_WIN_DEFAULT == winNum) + { + pWinRegInfo->baseLowRegOffs = 0; + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN_DEFAULT_CTRL_REG(pexIf); + pWinRegInfo->remapLowRegOffs = 0; + pWinRegInfo->remapHighRegOffs = 0; + } + else if (MV_PEX_WIN_EXP_ROM == winNum) + { + pWinRegInfo->baseLowRegOffs = 0; + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN_EXP_ROM_CTRL_REG(pexIf); + pWinRegInfo->remapLowRegOffs = PEX_WIN_EXP_ROM_REMAP_REG(pexIf); + pWinRegInfo->remapHighRegOffs = 0; + + } + + return MV_OK; +} + +/******************************************************************************* +* pexBarNameGet - Get the string name of PEX BAR. +* +* DESCRIPTION: +* This function get the string name of PEX BAR. +* +* INPUT: +* bar - PEX bar number. +* +* OUTPUT: +* None. +* +* RETURN: +* pointer to the string name of PEX BAR. +* +*******************************************************************************/ +const MV_8* pexBarNameGet( MV_U32 bar ) +{ + switch( bar ) + { + case PEX_INTER_REGS_BAR: + return "Internal Regs Bar0...."; + case PEX_DRAM_BAR: + return "DRAM Bar1............."; + case PEX_DEVICE_BAR: + return "Devices Bar2.........."; + default: + return "Bar unknown"; + } +} +/******************************************************************************* +* mvPexAddrDecShow - Print the PEX address decode map (BARs and windows). +* +* DESCRIPTION: +* This function print the PEX address decode map (BARs and windows). +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvPexAddrDecShow(MV_VOID) +{ + MV_PEX_BAR pexBar; + MV_PEX_DEC_WIN win; + MV_U32 pexIf; + MV_U32 bar,winNum; + + for( pexIf = 0; pexIf < mvCtrlPexMaxIfGet(); pexIf++ ) + { + if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf)) continue; + mvOsOutput( "\n" ); + mvOsOutput( "PEX%d:\n", pexIf ); + mvOsOutput( "-----\n" ); + + mvOsOutput( "\nPex Bars \n\n"); + + for( bar = 0; bar < PEX_MAX_BARS; bar++ ) + { + memset( &pexBar, 0, sizeof(MV_PEX_BAR) ); + + mvOsOutput( "%s ", pexBarNameGet(bar) ); + + if( mvPexBarGet( pexIf, bar, &pexBar ) == MV_OK ) + { + if( pexBar.enable ) + { + mvOsOutput( "base %08x, ", pexBar.addrWin.baseLow ); + mvSizePrint( pexBar.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } + mvOsOutput( "\nPex Decode Windows\n\n"); + + for( winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) + { + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "win%d - ", winNum ); + + if ( mvPexTargetWinGet(pexIf,winNum,&win) == MV_OK) + { + if (win.enable) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + + + } + } + + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "default win - " ); + + if ( mvPexTargetWinGet(pexIf, MV_PEX_WIN_DEFAULT, &win) == MV_OK) + { + mvOsOutput( "%s ", + mvCtrlTargetNameGet(win.target) ); + mvOsOutput( "\n" ); + } + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "Expansion ROM - " ); + + if ( mvPexTargetWinGet(pexIf, MV_PEX_WIN_EXP_ROM, &win) == MV_OK) + { + mvOsOutput( "%s ", + mvCtrlTargetNameGet(win.target) ); + mvOsOutput( "\n" ); + } + + } +} + + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysPex.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysPex.h new file mode 100644 index 0000000..3505613 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysPex.h @@ -0,0 +1,348 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCSysPEXH +#define __INCSysPEXH + +#include "mvCommon.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* 4KB granularity */ +#define MINIMUM_WINDOW_SIZE 0x1000 +#define MINIMUM_BAR_SIZE 0x1000 +#define MINIMUM_BAR_SIZE_MASK 0xFFFFF000 +#define BAR_SIZE_OFFS 12 +#define BAR_SIZE_MASK (0xFFFFF << BAR_SIZE_OFFS) + + + +#define MV_PEX_WIN_DEFAULT 6 +#define MV_PEX_WIN_EXP_ROM 7 +#define PEX_MAX_TARGET_WIN 8 + + +#define PEX_MAX_BARS 3 +#define PEX_INTER_REGS_BAR 0 +#define PEX_DRAM_BAR 1 +#define PEX_DEVICE_BAR 2 + +/*************************************/ +/* PCI Express BAR Control Registers */ +/*************************************/ +#define PEX_BAR_CTRL_REG(pexIf,bar) (0x41804 + (bar-1)*4- (pexIf)*0x10000) +#define PEX_EXP_ROM_BAR_CTRL_REG(pexIf) (0x4180C - (pexIf)*0x10000) + + +/* PCI Express BAR Control Register */ +/* PEX_BAR_CTRL_REG (PXBCR) */ + +#define PXBCR_BAR_EN BIT0 +#define PXBCR_BAR_SIZE_OFFS 16 +#define PXBCR_BAR_SIZE_MASK (0xffff << PXBCR_BAR_SIZE_OFFS) +#define PXBCR_BAR_SIZE_ALIGNMENT 0x10000 + + + +/* PCI Express Expansion ROM BAR Control Register */ +/* PEX_EXP_ROM_BAR_CTRL_REG (PXERBCR) */ + +#define PXERBCR_EXPROM_EN BIT0 +#define PXERBCR_EXPROMSZ_OFFS 19 +#define PXERBCR_EXPROMSZ_MASK (0xf << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_512KB (0x0 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_1024KB (0x1 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_2048KB (0x3 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_4096KB (0x7 << PXERBCR_EXPROMSZ_OFFS) + +/************************************************/ +/* PCI Express Address Window Control Registers */ +/************************************************/ +#define PEX_WIN0_3_CTRL_REG(pexIf,winNum) \ + (0x41820 + (winNum) * 0x10 - (pexIf) * 0x10000) +#define PEX_WIN0_3_BASE_REG(pexIf,winNum) \ + (0x41824 + (winNum) * 0x10 - (pexIf) * 0x10000) +#define PEX_WIN0_3_REMAP_REG(pexIf,winNum) \ + (0x4182C + (winNum) * 0x10 - (pexIf) * 0x10000) +#define PEX_WIN4_5_CTRL_REG(pexIf,winNum) \ + (0x41860 + (winNum - 4) * 0x20 - (pexIf) * 0x10000) +#define PEX_WIN4_5_BASE_REG(pexIf,winNum) \ + (0x41864 + (winNum - 4) * 0x20 - (pexIf) * 0x10000) +#define PEX_WIN4_5_REMAP_REG(pexIf,winNum) \ + (0x4186C + (winNum - 4) * 0x20 - (pexIf) * 0x10000) +#define PEX_WIN4_5_REMAP_HIGH_REG(pexIf,winNum) \ + (0x41870 + (winNum - 4) * 0x20 - (pexIf) * 0x10000) + +#define PEX_WIN_DEFAULT_CTRL_REG(pexIf) (0x418B0 - (pexIf) * 0x10000) +#define PEX_WIN_EXP_ROM_CTRL_REG(pexIf) (0x418C0 - (pexIf) * 0x10000) +#define PEX_WIN_EXP_ROM_REMAP_REG(pexIf) (0x418C4 - (pexIf) * 0x10000) + +/* PCI Express Window Control Register */ +/* PEX_WIN_CTRL_REG (PXWCR) */ + +#define PXWCR_WIN_EN BIT0 /* Window Enable.*/ + +#define PXWCR_WIN_BAR_MAP_OFFS 1 /* Mapping to BAR.*/ +#define PXWCR_WIN_BAR_MAP_MASK BIT1 +#define PXWCR_WIN_BAR_MAP_BAR1 (0 << PXWCR_WIN_BAR_MAP_OFFS) +#define PXWCR_WIN_BAR_MAP_BAR2 (1 << PXWCR_WIN_BAR_MAP_OFFS) + +#define PXWCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWCR_TARGET_MASK (0xf << PXWCR_TARGET_OFFS) + +#define PXWCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWCR_ATTRIB_MASK (0xff << PXWCR_ATTRIB_OFFS) + +#define PXWCR_SIZE_OFFS 16 /* size */ +#define PXWCR_SIZE_MASK (0xffff << PXWCR_SIZE_OFFS) +#define PXWCR_SIZE_ALIGNMENT 0x10000 + +/* PCI Express Window Base Register */ +/* PEX_WIN_BASE_REG (PXWBR)*/ + +#define PXWBR_BASE_OFFS 16 /* address[31:16] */ +#define PXWBR_BASE_MASK (0xffff << PXWBR_BASE_OFFS) +#define PXWBR_BASE_ALIGNMENT 0x10000 + +/* PCI Express Window Remap Register */ +/* PEX_WIN_REMAP_REG (PXWRR)*/ + +#define PXWRR_REMAP_EN BIT0 +#define PXWRR_REMAP_OFFS 16 +#define PXWRR_REMAP_MASK (0xffff << PXWRR_REMAP_OFFS) +#define PXWRR_REMAP_ALIGNMENT 0x10000 + +/* PCI Express Window Remap (High) Register */ +/* PEX_WIN_REMAP_HIGH_REG (PXWRHR)*/ + +#define PXWRHR_REMAP_HIGH_OFFS 0 +#define PXWRHR_REMAP_HIGH_MASK (0xffffffff << PXWRHR_REMAP_HIGH_OFFS) + +/* PCI Express Default Window Control Register */ +/* PEX_WIN_DEFAULT_CTRL_REG (PXWDCR) */ + +#define PXWDCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWDCR_TARGET_MASK (0xf << PXWDCR_TARGET_OFFS) +#define PXWDCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWDCR_ATTRIB_MASK (0xff << PXWDCR_ATTRIB_OFFS) + +/* PCI Express Expansion ROM Window Control Register */ +/* PEX_WIN_EXP_ROM_CTRL_REG (PXWERCR)*/ + +#define PXWERCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWERCR_TARGET_MASK (0xf << PXWERCR_TARGET_OFFS) +#define PXWERCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWERCR_ATTRIB_MASK (0xff << PXWERCR_ATTRIB_OFFS) + +/* PCI Express Expansion ROM Window Remap Register */ +/* PEX_WIN_EXP_ROM_REMAP_REG (PXWERRR)*/ + +#define PXWERRR_REMAP_EN BIT0 +#define PXWERRR_REMAP_OFFS 16 +#define PXWERRR_REMAP_MASK (0xffff << PXWERRR_REMAP_OFFS) +#define PXWERRR_REMAP_ALIGNMENT 0x10000 + + + +/*PEX_MEMORY_BAR_BASE_ADDR(barNum) (PXMBBA)*/ +/* PCI Express BAR0 Internal Register*/ +/*PEX BAR0_INTER_REG (PXBIR)*/ + +#define PXBIR_IOSPACE BIT0 /* Memory Space Indicator */ + +#define PXBIR_TYPE_OFFS 1 /* BAR Type/Init Val. */ +#define PXBIR_TYPE_MASK (0x3 << PXBIR_TYPE_OFFS) +#define PXBIR_TYPE_32BIT_ADDR (0x0 << PXBIR_TYPE_OFFS) +#define PXBIR_TYPE_64BIT_ADDR (0x2 << PXBIR_TYPE_OFFS) + +#define PXBIR_PREFETCH_EN BIT3 /* Prefetch Enable */ + +#define PXBIR_BASE_OFFS 20 /* Base address. Address bits [31:20] */ +#define PXBIR_BASE_MASK (0xfff << PXBIR_BASE_OFFS) +#define PXBIR_BASE_ALIGNMET (1 << PXBIR_BASE_OFFS) + + +/* PCI Express BAR0 Internal (High) Register*/ +/*PEX BAR0_INTER_REG_HIGH (PXBIRH)*/ + +#define PXBIRH_BASE_OFFS 0 /* Base address. Bits [63:32] */ +#define PXBIRH_BASE_MASK (0xffffffff << PBBHR_BASE_OFFS) + + +#define PEX_BAR_DEFAULT_ATTRIB 0xc /* Memory - Prefetch - 64 bit address */ +#define PEX_BAR0_DEFAULT_ATTRIB PEX_BAR_DEFAULT_ATTRIB +#define PEX_BAR1_DEFAULT_ATTRIB PEX_BAR_DEFAULT_ATTRIB +#define PEX_BAR2_DEFAULT_ATTRIB PEX_BAR_DEFAULT_ATTRIB + + +/* PCI Express BAR1 Register */ +/* PCI Express BAR2 Register*/ +/*PEX BAR1_REG (PXBR)*/ +/*PEX BAR2_REG (PXBR)*/ + +#define PXBR_IOSPACE BIT0 /* Memory Space Indicator */ + +#define PXBR_TYPE_OFFS 1 /* BAR Type/Init Val. */ +#define PXBR_TYPE_MASK (0x3 << PXBR_TYPE_OFFS) +#define PXBR_TYPE_32BIT_ADDR (0x0 << PXBR_TYPE_OFFS) +#define PXBR_TYPE_64BIT_ADDR (0x2 << PXBR_TYPE_OFFS) + +#define PXBR_PREFETCH_EN BIT3 /* Prefetch Enable */ + +#define PXBR_BASE_OFFS 16 /* Base address. Address bits [31:16] */ +#define PXBR_BASE_MASK (0xffff << PXBR_BASE_OFFS) +#define PXBR_BASE_ALIGNMET (1 << PXBR_BASE_OFFS) + + +/* PCI Express BAR1 (High) Register*/ +/* PCI Express BAR2 (High) Register*/ +/*PEX BAR1_REG_HIGH (PXBRH)*/ +/*PEX BAR2_REG_HIGH (PXBRH)*/ + +#define PXBRH_BASE_OFFS 0 /* Base address. Address bits [63:32] */ +#define PXBRH_BASE_MASK (0xffffffff << PXBRH_BASE_OFFS) + +/* PCI Express Expansion ROM BAR Register*/ +/*PEX_EXPANSION_ROM_BASE_ADDR_REG (PXERBAR)*/ + +#define PXERBAR_EXPROMEN BIT0 /* Expansion ROM Enable */ + +#define PXERBAR_BASE_512K_OFFS 19 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_512K_MASK (0x1fff << PXERBAR_BASE_512K_OFFS) + +#define PXERBAR_BASE_1MB_OFFS 20 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_1MB_MASK (0xfff << PXERBAR_BASE_1MB_OFFS) + +#define PXERBAR_BASE_2MB_OFFS 21 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_2MB_MASK (0x7ff << PXERBAR_BASE_2MB_OFFS) + +#define PXERBAR_BASE_4MB_OFFS 22 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_4MB_MASK (0x3ff << PXERBAR_BASE_4MB_OFFS) + +/* PEX Bar attributes */ +typedef struct _mvPexBar +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_PEX_BAR; + +/* PEX Remap Window attributes */ +typedef struct _mvPexRemapWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_PEX_REMAP_WIN; + +/* PEX Remap Window attributes */ +typedef struct _mvPexDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_U32 targetBar; + MV_U8 attrib; /* chip select attributes */ + MV_TARGET_ID targetId; /* Target Id of this MV_TARGET */ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_PEX_DEC_WIN; + +/* Global Functions prototypes */ +/* mvPexHalInit - Initialize PEX interfaces*/ +MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType); + + +/* mvPexTargetWinSet - Set PEX to peripheral target address window BAR*/ +MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin); + +/* mvPexTargetWinGet - Get PEX to peripheral target address window*/ +MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin); + +/* mvPexTargetWinEnable - Enable/disable a PEX BAR window*/ +MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf,MV_U32 winNum, MV_BOOL enable); + +/* mvPexTargetWinRemap - Set PEX to target address window remap.*/ +MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_REMAP_WIN *pAddrWin); + +/* mvPexTargetWinRemapEnable -enable\disable a PEX Window remap.*/ +MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, + MV_BOOL enable); + +/* mvPexBarSet - Set PEX bar address and size */ +MV_STATUS mvPexBarSet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *addrWin); + +/* mvPexBarGet - Get PEX bar address and size */ +MV_STATUS mvPexBarGet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *addrWin); + +/* mvPexBarEnable - enable\disable a PEX bar*/ +MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable); + +/* mvPexAddrDecShow - Display address decode windows attributes */ +MV_VOID mvPexAddrDecShow(MV_VOID); + +#endif diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.c new file mode 100644 index 0000000..71aa8ae --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.c @@ -0,0 +1,430 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "mvTypes.h" +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "cpu/mvCpu.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "mvRegs.h" +#include "ctrlEnv/sys/mvSysSata.h" + +MV_TARGET sataAddrDecPrioTab[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif + TBL_TERM +}; + + +/******************************************************************************* +* sataWinOverlapDetect - Detect SATA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case SATA address decode +* windows overlapps. +* This function detects SATA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS sataWinOverlapDetect(int dev, MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_SATA_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_SATA_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == sataWinOverlapDetect(dev, winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvSataWinSet:Error setting SATA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = 0; + decRegs.sizeReg = 0; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~MV_SATA_WIN_ATTR_MASK; + decRegs.sizeReg |= (targetAttribs.attrib << MV_SATA_WIN_ATTR_OFFSET); + + /* set target ID */ + decRegs.sizeReg &= ~MV_SATA_WIN_TARGET_MASK; + decRegs.sizeReg |= (targetAttribs.targetId << MV_SATA_WIN_TARGET_OFFSET); + + if (pAddrDecWin->enable == MV_TRUE) + { + decRegs.sizeReg |= MV_SATA_WIN_ENABLE_MASK; + } + else + { + decRegs.sizeReg &= ~MV_SATA_WIN_ENABLE_MASK; + } + + MV_REG_WRITE( MV_SATA_WIN_CTRL_REG(dev, winNum), decRegs.sizeReg); + MV_REG_WRITE( MV_SATA_WIN_BASE_REG(dev, winNum), decRegs.baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvSataWinGet - Get SATA peripheral target address window. +* +* DESCRIPTION: +* Get SATA peripheral target address window. +* +* INPUT: +* winNum - SATA target address decode window number. +* +* OUTPUT: +* pAddrDecWin - SATA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSataWinGet(int dev, MV_U32 winNum, MV_SATA_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= MV_SATA_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", + __FUNCTION__, dev, winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ( MV_SATA_WIN_BASE_REG(dev, winNum) ); + decRegs.sizeReg = MV_REG_READ( MV_SATA_WIN_CTRL_REG(dev, winNum) ); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) ) + { + mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & MV_SATA_WIN_ATTR_MASK) >> + MV_SATA_WIN_ATTR_OFFSET; + targetAttrib.targetId = (decRegs.sizeReg & MV_SATA_WIN_TARGET_MASK) >> + MV_SATA_WIN_TARGET_OFFSET; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if(decRegs.sizeReg & MV_SATA_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + return MV_OK; +} +/******************************************************************************* +* mvSataAddrDecShow - Print the SATA address decode map. +* +* DESCRIPTION: +* This function print the SATA address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvSataAddrDecShow(MV_VOID) +{ + + MV_SATA_DEC_WIN win; + int i,j; + + + + for( j = 0; j < MV_SATA_MAX_CHAN; j++ ) + { + if (MV_FALSE == mvCtrlPwrClckGet(SATA_UNIT_ID, j)) + return; + + mvOsOutput( "\n" ); + mvOsOutput( "SATA %d:\n", j ); + mvOsOutput( "----\n" ); + + for( i = 0; i < MV_SATA_MAX_ADDR_DECODE_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_SATA_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvSataWinGet(j, i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } + } +} + + +/******************************************************************************* +* mvSataWinInit - Initialize the integrated SATA target address window. +* +* DESCRIPTION: +* Initialize the SATA peripheral target address window. +* +* INPUT: +* +* +* OUTPUT: +* +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSataWinInit(MV_VOID) +{ + int winNum; + MV_SATA_DEC_WIN sataWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_U32 status, winPrioIndex = 0; + + /* Initiate Sata address decode */ + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_SATA_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_U32 regVal = MV_REG_READ(MV_SATA_WIN_CTRL_REG(0, winNum)); + regVal &= ~MV_SATA_WIN_ENABLE_MASK; + MV_REG_WRITE(MV_SATA_WIN_CTRL_REG(0, winNum), regVal); + } + + winNum = 0; + while( (sataAddrDecPrioTab[winPrioIndex] != TBL_TERM) && + (winNum < MV_SATA_MAX_ADDR_DECODE_WIN) ) + { + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(sataAddrDecPrioTab[winPrioIndex], + &cpuAddrDecWin); + + if(MV_NO_SUCH == status) + { + winPrioIndex++; + continue; + } + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + sataWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + sataWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + sataWin.addrWin.size = cpuAddrDecWin.addrWin.size; + sataWin.enable = MV_TRUE; + sataWin.target = sataAddrDecPrioTab[winPrioIndex]; + + if(MV_OK != mvSataWinSet(0/*dev*/, winNum, &sataWin)) + { + return MV_ERROR; + } + winNum++; + } + winPrioIndex++; + } + return MV_OK; +} + + + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.h new file mode 100644 index 0000000..325fb8d --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSata.h @@ -0,0 +1,128 @@ + +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVSysSataAddrDech +#define __INCMVSysSataAddrDech + +#include "mvCommon.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _mvSataDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +} MV_SATA_DEC_WIN; + + +#define MV_SATA_MAX_ADDR_DECODE_WIN 4 + +#define MV_SATA_WIN_CTRL_REG(dev, win) (SATA_REG_BASE + 0x30 + ((win)<<4)) +#define MV_SATA_WIN_BASE_REG(dev, win) (SATA_REG_BASE + 0x34 + ((win)<<4)) + +/* BITs in Bridge Interrupt Cause and Mask registers */ +#define MV_SATA_ADDR_DECODE_ERROR_BIT 0 +#define MV_SATA_ADDR_DECODE_ERROR_MASK (1<= MV_SDMMC_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == sdmmcWinOverlapDetect(dev, winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvSdmmcWinSet:Error setting SDMMC window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = 0; + decRegs.sizeReg = 0; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~MV_SDMMC_WIN_ATTR_MASK; + decRegs.sizeReg |= (targetAttribs.attrib << MV_SDMMC_WIN_ATTR_OFFSET); + + /* set target ID */ + decRegs.sizeReg &= ~MV_SDMMC_WIN_TARGET_MASK; + decRegs.sizeReg |= (targetAttribs.targetId << MV_SDMMC_WIN_TARGET_OFFSET); + + if (pAddrDecWin->enable == MV_TRUE) + { + decRegs.sizeReg |= MV_SDMMC_WIN_ENABLE_MASK; + } + else + { + decRegs.sizeReg &= ~MV_SDMMC_WIN_ENABLE_MASK; + } + + MV_REG_WRITE( MV_SDMMC_WIN_CTRL_REG(dev, winNum), decRegs.sizeReg); + MV_REG_WRITE( MV_SDMMC_WIN_BASE_REG(dev, winNum), decRegs.baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvSdmmcWinGet - Get SDMMC peripheral target address window. +* +* DESCRIPTION: +* Get SDMMC peripheral target address window. +* +* INPUT: +* winNum - SDMMC target address decode window number. +*d +* OUTPUT: +* pAddrDecWin - SDMMC target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSdmmcWinGet(int dev, MV_U32 winNum, MV_SDMMC_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= MV_SDMMC_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", + __FUNCTION__, dev, winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ( MV_SDMMC_WIN_BASE_REG(dev, winNum) ); + decRegs.sizeReg = MV_REG_READ( MV_SDMMC_WIN_CTRL_REG(dev, winNum) ); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) ) + { + mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & MV_SDMMC_WIN_ATTR_MASK) >> + MV_SDMMC_WIN_ATTR_OFFSET; + targetAttrib.targetId = (decRegs.sizeReg & MV_SDMMC_WIN_TARGET_MASK) >> + MV_SDMMC_WIN_TARGET_OFFSET; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if(decRegs.sizeReg & MV_SDMMC_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + return MV_OK; +} +/******************************************************************************* +* mvSdmmcAddrDecShow - Print the SDMMC address decode map. +* +* DESCRIPTION: +* This function print the SDMMC address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvSdmmcAddrDecShow(MV_VOID) +{ + + MV_SDMMC_DEC_WIN win; + int i,j=0; + + + + if (MV_FALSE == mvCtrlPwrClckGet(SDIO_UNIT_ID, 0)) + return; + + mvOsOutput( "\n" ); + mvOsOutput( "SDMMC %d:\n", j ); + mvOsOutput( "----\n" ); + + for( i = 0; i < MV_SDMMC_MAX_ADDR_DECODE_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_SDMMC_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvSdmmcWinGet(j, i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + + +/******************************************************************************* +* mvSdmmcWinInit - Initialize the integrated SDMMC target address window. +* +* DESCRIPTION: +* Initialize the SDMMC peripheral target address window. +* +* INPUT: +* +* +* OUTPUT: +* +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSdmmcWinInit(MV_VOID) +{ + int winNum; + MV_SDMMC_DEC_WIN sdmmcWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_U32 status, winPrioIndex = 0; + + /* Initiate Sdmmc address decode */ + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_SDMMC_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_U32 regVal = MV_REG_READ(MV_SDMMC_WIN_CTRL_REG(0, winNum)); + regVal &= ~MV_SDMMC_WIN_ENABLE_MASK; + MV_REG_WRITE(MV_SDMMC_WIN_CTRL_REG(0, winNum), regVal); + } + + winNum = 0; + while( (sdmmcAddrDecPrioTab[winPrioIndex] != TBL_TERM) && + (winNum < MV_SDMMC_MAX_ADDR_DECODE_WIN) ) + { + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(sdmmcAddrDecPrioTab[winPrioIndex], + &cpuAddrDecWin); + + if(MV_NO_SUCH == status) + { + winPrioIndex++; + continue; + } + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + sdmmcWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + sdmmcWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + sdmmcWin.addrWin.size = cpuAddrDecWin.addrWin.size; + sdmmcWin.enable = MV_TRUE; + sdmmcWin.target = sdmmcAddrDecPrioTab[winPrioIndex]; + + if(MV_OK != mvSdmmcWinSet(0/*dev*/, winNum, &sdmmcWin)) + { + return MV_ERROR; + } + winNum++; + } + winPrioIndex++; + } + return MV_OK; +} + + + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSdmmc.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSdmmc.h new file mode 100644 index 0000000..4c50a2b --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysSdmmc.h @@ -0,0 +1,125 @@ + +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVSysSdmmcAddrDech +#define __INCMVSysSdmmcAddrDech + +#include "mvCommon.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _mvSdmmcDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +} MV_SDMMC_DEC_WIN; + + +#define MV_SDMMC_MAX_ADDR_DECODE_WIN 4 + +#define MV_SDMMC_WIN_CTRL_REG(dev, win) (MV_SDIO_REG_BASE + 0x108 + ((win)<<3)) +#define MV_SDMMC_WIN_BASE_REG(dev, win) (MV_SDIO_REG_BASE + 0x10c + ((win)<<3)) + + +/* BITs in Windows 0-3 Control and Base Registers */ +#define MV_SDMMC_WIN_ENABLE_BIT 0 +#define MV_SDMMC_WIN_ENABLE_MASK (1<= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == tdmWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvTdmWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvTdmWinSet: Error setting TDM window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum)); + decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvTdmWinSet: mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* for the safe side we disable the window before writing the new + values */ + mvTdmWinEnable(winNum, MV_FALSE); + + ctrlReg |= (targetAttribs.attrib << TDM_WIN_ATTRIB_OFFS); + ctrlReg |= (targetAttribs.targetId << TDM_WIN_TARGET_OFFS); + ctrlReg |= (decRegs.sizeReg << TDM_WIN_SIZE_OFFS); + + /* Write to address base and control registers */ + MV_REG_WRITE(TDM_WIN_BASE_REG(winNum), decRegs.baseReg); + MV_REG_WRITE(TDM_WIN_CTRL_REG(winNum), ctrlReg); + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvTdmWinEnable(winNum, MV_TRUE); + } + return MV_OK; +} + +/******************************************************************************* +* mvTdmWinGet - Get peripheral target address window. +* +* DESCRIPTION: +* Get TDM peripheral target address window. +* +* INPUT: +* winNum - TDM to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - TDM target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ + +MV_STATUS mvTdmWinGet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin) +{ + + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum)); + decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS; + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvTdmWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ATTRIB_MASK) >> TDM_WIN_ATTRIB_OFFS; + targetAttrib.targetId = + (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_TARGET_MASK) >> TDM_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvTdmWinEnable - Enable/disable a TDM to target address window +* +* DESCRIPTION: +* This function enable/disable a TDM to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling TDM accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - TDM to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvTdmWinEnable(int winNum, MV_BOOL enable) +{ + MV_TDM_DEC_WIN addrDecWin; + + if (MV_TRUE == enable) + { + if (winNum >= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvTdmWinGet(winNum, &addrDecWin)) + { + mvOsPrintf("mvTdmWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == tdmWinOverlapDetect(winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_SET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK); + } + else + { /* Overlap detected */ + mvOsPrintf("mvTdmWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { + MV_REG_BIT_RESET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK); + } + return MV_OK; +} + + +/******************************************************************************* +* tdmWinOverlapDetect - Detect TDM address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviour is expected in case TDM address decode +* windows overlapps. +* This function detects TDM address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS tdmWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_TDM_DEC_WIN addrDecWin; + + for (winNumIndex = 0; winNumIndex < TDM_MBUS_MAX_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + /* Do not check disabled windows */ + if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK) + { + /* Get window parameters */ + if (MV_OK != mvTdmWinGet(winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("dmaWinOverlapDetect: ERR. TargetWinGet failed\n")); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + } + return MV_FALSE; +} + +/******************************************************************************* +* mvTdmAddrDecShow - Print the TDM address decode map. +* +* DESCRIPTION: +* This function print the TDM address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvTdmAddrDecShow(MV_VOID) +{ + MV_TDM_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "TDM:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < TDM_MBUS_MAX_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_TDM_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if (mvTdmWinGet(i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTdm.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTdm.h new file mode 100644 index 0000000..00de28c --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTdm.h @@ -0,0 +1,92 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSysTdmh +#define __INCmvSysTdmh + +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define TDM_MBUS_MAX_WIN 4 +#define TDM_WIN_CTRL_REG(win) ((TDM_REG_BASE + 0x4030) + (win<<4)) +#define TDM_WIN_BASE_REG(win) ((TDM_REG_BASE +0x4034) + (win<<4)) + +/* TDM_WIN_CTRL_REG bits */ +#define TDM_WIN_ENABLE_OFFS 0 +#define TDM_WIN_ENABLE_MASK (1<= TSU_MAX_DECODE_WIN) + { + mvOsPrintf("mvTsuWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if(MV_TRUE == tsuWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvTsuWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow,pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvTsuWinSet: Error setting TSU window %d to target " + "%s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum)); + decRegs.sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)); + + if(MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvTsuWinSet: mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~TSU_WIN_CTRL_ATTR_MASK; + decRegs.sizeReg |= targetAttribs.attrib << TSU_WIN_CTRL_ATTR_OFFS; + /* set target ID */ + decRegs.sizeReg &= ~TSU_WIN_CTRL_TARGET_MASK; + decRegs.sizeReg |= targetAttribs.targetId << TSU_WIN_CTRL_TARGET_OFFS; + + /* for the safe side we disable the window before writing the new */ + /* values */ + mvTsuWinEnable(winNum, MV_FALSE); + MV_REG_WRITE(MV_TSU_WIN_CTRL_REG(winNum),decRegs.sizeReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(MV_TSU_WIN_BASE_REG(winNum), decRegs.baseReg); + + /* Enable address decode target window */ + if(pAddrDecWin->enable == MV_TRUE) + { + mvTsuWinEnable(winNum,MV_TRUE); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuWinGet +* +* DESCRIPTION: +* Get TSU peripheral target address window. +* +* INPUT: +* winNum - TSU to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - TSU target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvTsuWinGet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if(winNum >= TSU_MAX_DECODE_WIN) + { + mvOsPrintf("mvTsuWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum)); + decRegs.sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)); + + if(MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvTsuWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (decRegs.sizeReg & TSU_WIN_CTRL_ATTR_MASK) >> TSU_WIN_CTRL_ATTR_OFFS; + targetAttrib.targetId = + (decRegs.sizeReg & TSU_WIN_CTRL_TARGET_MASK) >> TSU_WIN_CTRL_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if((MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum)) & TSU_WIN_CTRL_EN_MASK)) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + + +/******************************************************************************* +* mvTsuWinEnable +* +* DESCRIPTION: +* This function enable/disable a TSU to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling TSU accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - TSU to target address decode window number. +* enable - Enable / disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvTsuWinEnable(MV_U32 winNum,MV_BOOL enable) +{ + MV_TSU_DEC_WIN addrDecWin; + + /* Parameter checking */ + if(winNum >= TSU_MAX_DECODE_WIN) + { + mvOsPrintf("mvTsuWinEnable: ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if(enable == MV_TRUE) + { + /* First check for overlap with other enabled windows */ + /* Get current window. */ + if(MV_OK != mvTsuWinGet(winNum,&addrDecWin)) + { + mvOsPrintf("mvTsuWinEnable: ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping. */ + if(MV_FALSE == tsuWinOverlapDetect(winNum,&(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_SET(MV_TSU_WIN_CTRL_REG(winNum), + TSU_WIN_CTRL_EN_MASK); + } + else + { + /* Overlap detected */ + mvOsPrintf("mvTsuWinEnable: ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { + /* Disable address decode target window */ + MV_REG_BIT_RESET(MV_TSU_WIN_CTRL_REG(winNum), + TSU_WIN_CTRL_EN_MASK); + } + return MV_OK; +} + +/******************************************************************************* +* mvTsuWinTargetGet +* +* DESCRIPTION: +* Get Window number associated with target +* +* INPUT: +* target - Target ID to get the window number for. +* OUTPUT: +* +* RETURN: +* window number or 0xFFFFFFFF on error. +* +*******************************************************************************/ +MV_U32 mvTsuWinTargetGet(MV_TARGET target) +{ + MV_TSU_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if(target >= MAX_TARGETS) + { + mvOsPrintf("mvTsuWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + for(winNum = 0; winNum < TSU_MAX_DECODE_WIN; winNum++) + { + if(mvTsuWinGet(winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvTsuWinGet: window returned error\n"); + return 0xffffffff; + } + + if (decWin.enable == MV_TRUE) + { + if(decWin.target == target) + { + return winNum; + } + } + } + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* tsuWinOverlapDetect +* +* DESCRIPTION: +* Detect TSU address windows overlapping +* An unpredicted behaviur is expected in case TSU address decode +* windows overlapps. +* This function detects TSU address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS tsuWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 ctrlReg; + MV_U32 winNumIndex; + MV_TSU_DEC_WIN addrDecWin; + + for(winNumIndex = 0; winNumIndex < TSU_MAX_DECODE_WIN; winNumIndex++) + { + /* Do not check window itself */ + if(winNumIndex == winNum) + { + continue; + } + + /* Do not check disabled windows */ + ctrlReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNumIndex)); + if((ctrlReg & TSU_WIN_CTRL_EN_MASK) == 0) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvTsuWinGet(winNumIndex, &addrDecWin)) + { + mvOsPrintf("tsuWinOverlapDetect: ERR. mvTsuWinGet failed\n"); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + return MV_FALSE; +} + + +/******************************************************************************* +* mvTsuAddrDecShow +* +* DESCRIPTION: +* Print the TSU address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +void mvTsuAddrDecShow(void) +{ + MV_TSU_DEC_WIN win; + int i; + + if (MV_FALSE == mvCtrlPwrClckGet(TS_UNIT_ID, 0)) + return; + + mvOsOutput( "\n" ); + mvOsOutput( "TSU:\n"); + mvOsOutput( "----\n" ); + + for(i = 0; i < TSU_MAX_DECODE_WIN; i++) + { + memset(&win, 0, sizeof(TSU_MAX_DECODE_WIN)); + mvOsOutput( "win%d - ", i ); + + if(mvTsuWinGet(i, &win ) == MV_OK ) + { + if(win.enable == MV_TRUE) + { + mvOsOutput("%s base %08x, ", + mvCtrlTargetNameGet(win.target), + win.addrWin.baseLow); + mvOsOutput( "...." ); + mvSizePrint(win.addrWin.size ); + mvOsOutput( "\n" ); + } + else + { + mvOsOutput( "disable\n" ); + } + } + } + return; +} + + +/******************************************************************************* +* mvTsuInit +* +* DESCRIPTION: +* Initialize the TSU unit, and get unit out of reset. +* +* INPUT: +* coreClock - The core clock at which the TSU should operate. +* mode - The mode on configure the unit into (serial/parallel). +* memHandle - Memory handle used for memory allocations. +* OUTPUT: +* None. +* RETURN: +* MV_OK - on success, +* +*******************************************************************************/ +MV_STATUS mvTsuInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode, + void *osHandle) +{ + MV_STATUS status; + + status = mvTsuWinInit(); + if(status == MV_OK) + status = mvTsuHalInit(coreClock,mode,osHandle); + + return status; +} diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTs.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTs.h new file mode 100644 index 0000000..4282589 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysTs.h @@ -0,0 +1,110 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSysTsh +#define __INCmvSysTsh + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ +#include "ts/mvTsu.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define TSU_MAX_DECODE_WIN 4 + + +/*******************************************/ +/* TSU Windows Registers */ +/*******************************************/ +#define MV_TSU_WIN_CTRL_REG(win) (TSU_GLOBAL_REG_BASE +0x30 + 0x10 * win) +#define MV_TSU_WIN_BASE_REG(win) (TSU_GLOBAL_REG_BASE +0x34 + 0x10 * win) + +/* TSU windows control register. */ +#define TSU_WIN_CTRL_EN_MASK (0x1 << 0) +#define TSU_WIN_CTRL_TARGET_OFFS 4 +#define TSU_WIN_CTRL_TARGET_MASK (0xF << TSU_WIN_CTRL_TARGET_OFFS) +#define TSU_WIN_CTRL_ATTR_OFFS 8 +#define TSU_WIN_CTRL_ATTR_MASK (0xFF << TSU_WIN_CTRL_ATTR_OFFS) +#define TSU_WIN_CTRL_SIZE_OFFS 16 +#define TSU_WIN_CTRL_SIZE_MASK (0xFFFF << TSU_WIN_CTRL_SIZE_OFFS) + +/* TSU windows base register. */ +#define TSU_WIN_BASE_OFFS 16 +#define TSU_WIN_BASE_MASK (0xFFFF << TSU_WIN_BASE_OFFS) + +MV_STATUS mvTsuWinInit(void); + +void mvTsuAddrDecShow(void); +MV_STATUS mvTsuInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode, + void *osHandle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INCmvTsh */ diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysUsb.c b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysUsb.c new file mode 100644 index 0000000..195b5e1 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysUsb.c @@ -0,0 +1,497 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "ctrlEnv/sys/mvSysUsb.h" + +MV_TARGET usbAddrDecPrioTab[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_CESA) && defined(USB_UNDERRUN_WA) + CRYPT_ENG, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif + TBL_TERM +}; + + + +MV_STATUS mvUsbInit(int dev, MV_BOOL isHost) +{ + MV_STATUS status; + + status = mvUsbWinInit(dev); + if(status != MV_OK) + return status; + + return mvUsbHalInit(dev, isHost); +} + + +/******************************************************************************* +* usbWinOverlapDetect - Detect USB address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case USB address decode +* windows overlapps. +* This function detects USB address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS usbWinOverlapDetect(int dev, MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_USB_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == usbWinOverlapDetect(dev, winNum, &pDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) + { + mvOsPrintf("mvUsbWinSet:Error setting USB window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pDecWin->target), + pDecWin->addrWin.baseLow, + pDecWin->addrWin.size); + return MV_ERROR; + } + + if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams)) + { + mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* set Size, Attributes and TargetID */ + sizeReg = (((winParams.targetId << MV_USB_WIN_TARGET_OFFSET) & MV_USB_WIN_TARGET_MASK) | + ((winParams.attrib << MV_USB_WIN_ATTR_OFFSET) & MV_USB_WIN_ATTR_MASK) | + ((winParams.size << MV_USB_WIN_SIZE_OFFSET) & MV_USB_WIN_SIZE_MASK)); + +#if defined(MV645xx) || defined(MV646xx) + /* If window is DRAM with HW cache coherency, make sure bit2 is set */ + sizeReg &= ~MV_USB_WIN_BURST_WR_LIMIT_MASK; + + if((MV_TARGET_IS_DRAM(pDecWin->target)) && + (pDecWin->addrWinAttr.cachePolicy != NO_COHERENCY)) + { + sizeReg |= MV_USB_WIN_BURST_WR_32BIT_LIMIT; + } + else + { + sizeReg |= MV_USB_WIN_BURST_WR_NO_LIMIT; + } +#endif /* MV645xx || MV646xx */ + + if (pDecWin->enable == MV_TRUE) + { + sizeReg |= MV_USB_WIN_ENABLE_MASK; + } + else + { + sizeReg &= ~MV_USB_WIN_ENABLE_MASK; + } + + /* Update Base value */ + baseReg = (winParams.baseAddr & MV_USB_WIN_BASE_MASK); + + MV_REG_WRITE( MV_USB_WIN_CTRL_REG(dev, winNum), sizeReg); + MV_REG_WRITE( MV_USB_WIN_BASE_REG(dev, winNum), baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvUsbWinGet - Get USB peripheral target address window. +* +* DESCRIPTION: +* Get USB peripheral target address window. +* +* INPUT: +* winNum - USB target address decode window number. +* +* OUTPUT: +* pDecWin - USB target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvUsbWinGet(int dev, MV_U32 winNum, MV_DEC_WIN *pDecWin) +{ + MV_DEC_WIN_PARAMS winParam; + MV_U32 sizeReg, baseReg; + + /* Parameter checking */ + if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", + __FUNCTION__, dev, winNum); + return MV_NOT_SUPPORTED; + } + + baseReg = MV_REG_READ( MV_USB_WIN_BASE_REG(dev, winNum) ); + sizeReg = MV_REG_READ( MV_USB_WIN_CTRL_REG(dev, winNum) ); + + /* Check if window is enabled */ + if(sizeReg & MV_USB_WIN_ENABLE_MASK) + { + pDecWin->enable = MV_TRUE; + + /* Extract window parameters from registers */ + winParam.targetId = (sizeReg & MV_USB_WIN_TARGET_MASK) >> MV_USB_WIN_TARGET_OFFSET; + winParam.attrib = (sizeReg & MV_USB_WIN_ATTR_MASK) >> MV_USB_WIN_ATTR_OFFSET; + winParam.size = (sizeReg & MV_USB_WIN_SIZE_MASK) >> MV_USB_WIN_SIZE_OFFSET; + winParam.baseAddr = (baseReg & MV_USB_WIN_BASE_MASK); + + /* Translate the decode window parameters to address decode struct */ + if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin)) + { + mvOsPrintf("Failed to translate register parameters to USB address" \ + " decode window structure\n"); + return MV_ERROR; + } + } + else + { + pDecWin->enable = MV_FALSE; + } + return MV_OK; +} + +/******************************************************************************* +* mvUsbWinInit - +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvUsbWinInit(int dev) +{ + MV_STATUS status; + MV_DEC_WIN usbWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + int winNum; + MV_U32 winPrioIndex = 0; + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_USB_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_REG_BIT_RESET(MV_USB_WIN_CTRL_REG(dev, winNum), MV_USB_WIN_ENABLE_MASK); + } + + /* Go through all windows in user table until table terminator */ + winNum = 0; + while( (usbAddrDecPrioTab[winPrioIndex] != TBL_TERM) && + (winNum < MV_USB_MAX_ADDR_DECODE_WIN) ) + { + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(usbAddrDecPrioTab[winPrioIndex], + &cpuAddrDecWin); + + if(MV_NO_SUCH == status) + { + winPrioIndex++; + continue; + } + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + usbWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + usbWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + usbWin.addrWin.size = cpuAddrDecWin.addrWin.size; + usbWin.enable = MV_TRUE; + usbWin.target = usbAddrDecPrioTab[winPrioIndex]; + +#if defined(MV645xx) || defined(MV646xx) + /* Get the default attributes for that target window */ + mvCtrlDefAttribGet(usbWin.target, &usbWin.addrWinAttr); +#endif /* MV645xx || MV646xx */ + + if(MV_OK != mvUsbWinSet(dev, winNum, &usbWin)) + { + return MV_ERROR; + } + winNum++; + } + winPrioIndex++; + } + return MV_OK; +} + +/******************************************************************************* +* mvUsbAddrDecShow - Print the USB address decode map. +* +* DESCRIPTION: +* This function print the USB address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvUsbAddrDecShow(MV_VOID) +{ + MV_DEC_WIN addrDecWin; + int i, winNum; + + mvOsOutput( "\n" ); + mvOsOutput( "USB:\n" ); + mvOsOutput( "----\n" ); + + for(i=0; i= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + if (pAddrDecWin == NULL) + { + DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + /* Check if the requested window overlaps with current windows */ + if (MV_TRUE == xorWinOverlapDetect(unit, winNum, &pAddrDecWin->addrWin)) + { + DB(mvOsPrintf("%s: ERR. Window %d overlap\n",__FUNCTION__,winNum)); + return MV_ERROR; + } + + xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum)); + xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum)); + + /* Get Base Address and size registers values */ + if(MV_OK != mvCtrlAddrDecToReg(&pAddrDecWin->addrWin, &xorDecRegs)) + { + DB(mvOsPrintf("%s: ERR. Invalid addr dec window\n",__FUNCTION__)); + return MV_BAD_PARAM; + } + + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + xorDecRegs.baseReg &= ~XEBARX_ATTR_MASK; + xorDecRegs.baseReg |= targetAttribs.attrib << XEBARX_ATTR_OFFS; + /* set target ID */ + xorDecRegs.baseReg &= ~XEBARX_TARGET_MASK; + xorDecRegs.baseReg |= targetAttribs.targetId << XEBARX_TARGET_OFFS; + + + /* Write to address decode Base Address Register */ + MV_REG_WRITE(XOR_BASE_ADDR_REG(unit,winNum), xorDecRegs.baseReg); + + /* Write to Size Register */ + MV_REG_WRITE(XOR_SIZE_MASK_REG(unit,winNum), xorDecRegs.sizeReg); + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + if (pAddrDecWin->enable) + { + MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + else + { + MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + } + return MV_OK; +} + +/******************************************************************************* +* mvXorTargetWinGet - Get xor peripheral target address window. +* +* DESCRIPTION: +* Get xor peripheral target address window. +* +* INPUT: +* winNum - One of the possible XOR memory decode windows. +* +* OUTPUT: +* base - Window base address. +* size - Window size. +* enable - window enable/disable. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorTargetWinGet(MV_U32 unit,MV_U32 winNum, MV_XOR_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS xorDecRegs; + MV_TARGET_ATTRIB targetAttrib; + MV_U32 chan=0,chanWinEn; + + /* Parameter checking */ + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__ , winNum)); + return MV_ERROR; + } + + if (NULL == pAddrDecWin) + { + DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + + chanWinEn = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,0)) & XEXWCR_WIN_EN_MASK(winNum); + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) /* we should scan here all channels per unit */ + { + /* Check if enable bit is equal for all channels */ + if ((MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)) & + XEXWCR_WIN_EN_MASK(winNum)) != chanWinEn) + { + mvOsPrintf("%s: ERR. Window enable field must be equal in " + "all channels(chan=%d)\n",__FUNCTION__, chan); + return MV_ERROR; + } + } + + + + xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum)); + xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&xorDecRegs, &pAddrDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. mvCtrlRegToAddrDec failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (xorDecRegs.baseReg & XEBARX_ATTR_MASK) >> XEBARX_ATTR_OFFS; + targetAttrib.targetId = + (xorDecRegs.baseReg & XEBARX_TARGET_MASK) >> XEBARX_TARGET_OFFS; + + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + if(chanWinEn) + { + pAddrDecWin->enable = MV_TRUE; + } + else pAddrDecWin->enable = MV_FALSE; + + return MV_OK; +} + +/******************************************************************************* +* mvXorTargetWinEnable - Enable/disable a Xor address decode window +* +* DESCRIPTION: +* This function enable/disable a XOR address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling XOR accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - Decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorTargetWinEnable(MV_U32 unit,MV_U32 winNum, MV_BOOL enable) +{ + MV_XOR_DEC_WIN addrDecWin; + MV_U32 chan; + + /* Parameter checking */ + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid winNum%d\n", __FUNCTION__, winNum)); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { + /* Get current window */ + if (MV_OK != mvXorTargetWinGet(unit,winNum, &addrDecWin)) + { + DB(mvOsPrintf("%s: ERR. targetWinGet fail\n", __FUNCTION__)); + return MV_ERROR; + } + + /* Check for overlapping */ + if (MV_TRUE == xorWinOverlapDetect(unit,winNum, &(addrDecWin.addrWin))) + { + /* Overlap detected */ + DB(mvOsPrintf("%s: ERR. Overlap detected\n", __FUNCTION__)); + return MV_ERROR; + } + + /* No Overlap. Enable address decode target window */ + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + + } + else + { + /* Disable address decode target window */ + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + + } + + return MV_OK; +} + +/******************************************************************************* +* mvXorSetProtWinSet - Configure access attributes of a XOR engine +* to one of the XOR memory windows. +* +* DESCRIPTION: +* Each engine can be configured with access attributes for each of the +* memory spaces. This function sets access attributes +* to a given window for the given engine +* +* INPUTS: +* chan - One of the possible engines. +* winNum - One of the possible XOR memory spaces. +* access - Protection access rights. +* write - Write rights. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorProtWinSet (MV_U32 unit,MV_U32 chan, MV_U32 winNum, MV_BOOL access, + MV_BOOL write) +{ + MV_U32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN_PER_UNIT) + { + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __FUNCTION__ , chan)); + return MV_BAD_PARAM; + } + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + + temp = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)) & + (~XEXWCR_WIN_ACC_MASK(winNum)); + + /* if access is disable */ + if (!access) + { + /* disable access */ + temp |= XEXWCR_WIN_ACC_NO_ACC(winNum); + } + /* if access is enable */ + else + { + /* if write is enable */ + if (write) + { + /* enable write */ + temp |= XEXWCR_WIN_ACC_RW(winNum); + } + /* if write is disable */ + else + { + /* disable write */ + temp |= XEXWCR_WIN_ACC_RO(winNum); + } + } + MV_REG_WRITE(XOR_WINDOW_CTRL_REG(unit,chan),temp); + return MV_OK; +} + +/******************************************************************************* +* mvXorPciRemap - Set XOR remap register for PCI address windows. +* +* DESCRIPTION: +* only Windows 0-3 can be remapped. +* +* INPUT: +* winNum - window number +* pAddrDecWin - pointer to address space window structure +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorPciRemap(MV_U32 unit,MV_U32 winNum, MV_U32 addrHigh) +{ + /* Parameter checking */ + if (winNum >= XOR_MAX_REMAP_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + + MV_REG_WRITE(XOR_HIGH_ADDR_REMAP_REG(unit,winNum), addrHigh); + + return MV_OK; +} + +/******************************************************************************* +* xorWinOverlapDetect - Detect XOR address windows overlaping +* +* DESCRIPTION: +* An unpredicted behaviour is expected in case XOR address decode +* windows overlaps. +* This function detects XOR address decode windows overlaping of a +* specified window. The function does not check the window itself for +* overlaping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS xorWinOverlapDetect(MV_U32 unit,MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex,chan; + MV_XOR_DEC_WIN addrDecWin; + + if (pAddrWin == NULL) + { + DB(mvOsPrintf("%s: ERR. pAddrWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)); + + for (winNumIndex = 0; winNumIndex < XOR_MAX_ADDR_DEC_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + + /* Do not check disabled windows */ + if ((baseAddrEnableReg & XEXWCR_WIN_EN_MASK(winNumIndex)) == 0) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvXorTargetWinGet(unit,winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__ )); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + } + + return MV_FALSE; +} + +static MV_VOID mvXorAddrDecShowUnit(MV_U32 unit) +{ + MV_XOR_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "XOR %d:\n", unit ); + mvOsOutput( "----\n" ); + + for( i = 0; i < XOR_MAX_ADDR_DEC_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_XOR_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvXorTargetWinGet(unit, i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + +/******************************************************************************* +* mvXorAddrDecShow - Print the XOR address decode map. +* +* DESCRIPTION: +* This function print the XOR address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvXorAddrDecShow(MV_VOID) +{ + int i; + + for( i = 0; i < MV_XOR_MAX_UNIT; i++ ) + mvXorAddrDecShowUnit(i); + +} diff --git a/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysXor.h b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysXor.h new file mode 100644 index 0000000..73b2d9e --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/ctrlEnv/sys/mvSysXor.h @@ -0,0 +1,140 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCMVSysXorh +#define __INCMVSysXorh + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ctrlEnv/sys/mvCpuIf.h" + +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define XOR_MAX_ADDR_DEC_WIN 8 /* Maximum address decode windows */ +#define XOR_MAX_REMAP_WIN 4 /* Maximum address arbiter windows */ + +/* XOR Engine Address Decoding Register Map */ +#define XOR_WINDOW_CTRL_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x240 + ((chan) * 4))) +#define XOR_BASE_ADDR_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x250 + ((winNum) * 4))) +#define XOR_SIZE_MASK_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x270 + ((winNum) * 4))) +#define XOR_HIGH_ADDR_REMAP_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x290 + ((winNum) * 4))) + +/* XOR Engine [0..1] Window Control Registers (XExWCR) */ +#define XEXWCR_WIN_EN_OFFS(winNum) (winNum) +#define XEXWCR_WIN_EN_MASK(winNum) (1 << (XEXWCR_WIN_EN_OFFS(winNum))) +#define XEXWCR_WIN_EN_ENABLE(winNum) (1 << (XEXWCR_WIN_EN_OFFS(winNum))) +#define XEXWCR_WIN_EN_DISABLE(winNum) (0 << (XEXWCR_WIN_EN_OFFS(winNum))) + +#define XEXWCR_WIN_ACC_OFFS(winNum) ((2 * winNum) + 16) +#define XEXWCR_WIN_ACC_MASK(winNum) (3 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_NO_ACC(winNum) (0 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_RO(winNum) (1 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_RW(winNum) (3 << (XEXWCR_WIN_ACC_OFFS(winNum))) + +/* XOR Engine Base Address Registers (XEBARx) */ +#define XEBARX_TARGET_OFFS (0) +#define XEBARX_TARGET_MASK (0xF << XEBARX_TARGET_OFFS) +#define XEBARX_ATTR_OFFS (8) +#define XEBARX_ATTR_MASK (0xFF << XEBARX_ATTR_OFFS) +#define XEBARX_BASE_OFFS (16) +#define XEBARX_BASE_MASK (0xFFFF << XEBARX_BASE_OFFS) + +/* XOR Engine Size Mask Registers (XESMRx) */ +#define XESMRX_SIZE_MASK_OFFS (16) +#define XESMRX_SIZE_MASK_MASK (0xFFFF << XESMRX_SIZE_MASK_OFFS) + +/* XOR Engine High Address Remap Register (XEHARRx1) */ +#define XEHARRX_REMAP_OFFS (0) +#define XEHARRX_REMAP_MASK (0xFFFFFFFF << XEHARRX_REMAP_OFFS) + +typedef struct _mvXorDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_XOR_DEC_WIN; + +MV_STATUS mvXorInit (MV_VOID); +MV_STATUS mvXorTargetWinSet(MV_U32 unit, MV_U32 winNum, + MV_XOR_DEC_WIN *pAddrDecWin); +MV_STATUS mvXorTargetWinGet(MV_U32 unit, MV_U32 winNum, + MV_XOR_DEC_WIN *pAddrDecWin); +MV_STATUS mvXorTargetWinEnable(MV_U32 unit, + MV_U32 winNum, MV_BOOL enable); +MV_STATUS mvXorProtWinSet (MV_U32 unit,MV_U32 chan, MV_U32 winNum, MV_BOOL access, + MV_BOOL write); +MV_STATUS mvXorPciRemap(MV_U32 unit, MV_U32 winNum, MV_U32 addrHigh); + +MV_VOID mvXorAddrDecShow(MV_VOID); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/mv_feroceon/mv_kw/kw_family/device/mvDevice.c b/board/mv_feroceon/mv_kw/kw_family/device/mvDevice.c new file mode 100644 index 0000000..80325fc --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/device/mvDevice.c @@ -0,0 +1,75 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "device/mvDevice.h" + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + + + diff --git a/board/mv_feroceon/mv_kw/kw_family/device/mvDevice.h b/board/mv_feroceon/mv_kw/kw_family/device/mvDevice.h new file mode 100644 index 0000000..9350779 --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/device/mvDevice.h @@ -0,0 +1,74 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDeviceH +#define __INCmvDeviceH + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "device/mvDeviceRegs.h" + + +#endif /* #ifndef __INCmvDeviceH */ diff --git a/board/mv_feroceon/mv_kw/kw_family/device/mvDeviceRegs.h b/board/mv_feroceon/mv_kw/kw_family/device/mvDeviceRegs.h new file mode 100644 index 0000000..80778ad --- /dev/null +++ b/board/mv_feroceon/mv_kw/kw_family/device/mvDeviceRegs.h @@ -0,0 +1,101 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDeviceRegsH +#define __INCmvDeviceRegsH + +#ifndef MV_ASMLANGUAGE +#include "ctrlEnv/mvCtrlEnvLib.h" +/* This enumerator describes the Marvell controller possible devices that */ +/* can be connected to its device interface. */ +typedef enum _mvDevice +{ +#if defined(MV_INCLUDE_DEVICE_CS0) + DEV_CS0 = 0, /* Device connected to dev CS[0] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + DEV_CS1 = 1, /* Device connected to dev CS[1] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + DEV_CS2 = 2, /* Device connected to dev CS[2] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS3) + DEV_CS3 = 3, /* Device connected to dev CS[2] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS4) + DEV_CS4 = 4, /* Device connected to BOOT dev */ +#endif + MV_DEV_MAX_CS = MV_DEVICE_MAX_CS +}MV_DEVICE; + + +#endif /* MV_ASMLANGUAGE */ + + +#define NAND_CTRL_REG 0x10470 + +#define NAND_ACTCEBOOT_BIT BIT1 + + +#endif /* #ifndef __INCmvDeviceRegsH */ diff --git a/board/mv_feroceon/mv_kw/mvSysHwConfig.h b/board/mv_feroceon/mv_kw/mvSysHwConfig.h new file mode 100644 index 0000000..bfa2a98 --- /dev/null +++ b/board/mv_feroceon/mv_kw/mvSysHwConfig.h @@ -0,0 +1,348 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmvSysHwConfigh +#define __INCmvSysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ +#undef MV_MEM_OVER_PEX_WA + +#define MV_INCLUDE_PEX +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_CESA +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART +#define MV_INCLUDE_SPI +#define MV_INCLUDE_TDM +#define MV_INCLUDE_XOR +#define MV_INCLUDE_TS +#define MV_INCLUDE_AUDIO +#define MV_INCLUDE_RTC +#define MV_INCLUDE_INTEG_SATA +#define MV_INCLUDE_CLK_PWR_CNTRL + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board SPI Flash support */ +#define MV_INC_BOARD_SPI_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + +/************************************************/ +/* U-Boot Specific */ +/************************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#endif + + +/************************************************/ +/* RD boards specifics */ +/************************************************/ + +#undef MV_INC_BOARD_DDIM + +#ifndef MV_BOOTROM +#define MV_STATIC_DRAM_ON_BOARD +#endif + +#if defined(RD_88F6281) +#define MV_INC_BOARD_QD_SWITCH +#endif + +#if defined(RD_88F6180) +#define MV_INC_BOARD_QD_SWITCH +#endif +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _256M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _16M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + +/* Device: CS0 - NAND, CS1 - SPI, CS2 - Boot ROM, CS3 - Boot device */ + +#define DEVICE_CS0_BASE 0xf9000000 +#define DEVICE_CS0_SIZE _8M + +#define DEVICE_SPI_BASE 0xf8000000 +#define DEVICE_CS1_BASE DEVICE_SPI_BASE +#define DEVICE_CS1_SIZE _16M + +#define DEVICE_CS2_BASE 0xf4000000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE BOOTDEV_CS_BASE +#define DEVICE_CS3_SIZE BOOTDEV_CS_SIZE + +#if !defined(MV_BOOTROM) && defined(MV_NAND_BOOT) +#define CFG_NAND_BASE BOOTDEV_CS_BASE +#else +#define CFG_NAND_BASE DEVICE_CS0_BASE +#endif + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define CRYPT_ENG_BASE 0xFB000000 +#define CRYPT_ENG_SIZE _64K + + +#if defined (MV_INCLUDE_PEX) +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE +#endif + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + +/* Board clock detection */ +#undef TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ +#define L2CLK_AUTO_DETECT /* Use L2 Clk auto detection */ + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" +#endif /* ETHER_DRAM_COHER */ + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x1 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x3 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x5 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x4 ,EN}, \ + {{CRYPT_ENG_BASE, 0, CRYPT_ENG_SIZE} ,0x7 ,EN}, \ + /* Table terminator */\ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +}; + +#define MV_CACHEABLE(address) ((address) | 0x80000000) + +/* includes */ +#define _1K 0x00000400 +#define _4K 0x00001000 +#define _8K 0x00002000 +#define _16K 0x00004000 +#define _32K 0x00008000 +#define _64K 0x00010000 +#define _128K 0x00020000 +#define _256K 0x00040000 +#define _512K 0x00080000 + +#define _1M 0x00100000 +#define _2M 0x00200000 +#define _4M 0x00400000 +#define _8M 0x00800000 +#define _16M 0x01000000 +#define _32M 0x02000000 +#define _64M 0x04000000 +#define _128M 0x08000000 +#define _256M 0x10000000 +#define _512M 0x20000000 + +#define _1G 0x40000000 +#define _2G 0x80000000 + + +#if defined(MV_BOOTSIZE_256K) + +#define BOOTDEV_CS_SIZE _256K + +#elif defined(MV_BOOTSIZE_512K) + +#define BOOTDEV_CS_SIZE _512K + +#elif defined(MV_BOOTSIZE_4M) + +#define BOOTDEV_CS_SIZE _4M + +#elif defined(MV_BOOTSIZE_8M) + +#define BOOTDEV_CS_SIZE _8M + +#elif defined(MV_BOOTSIZE_16M) + +#define BOOTDEV_CS_SIZE _16M + +#elif defined(MV_BOOTSIZE_32M) + +#define BOOTDEV_CS_SIZE _32M + +#elif defined(MV_BOOTSIZE_64M) + +#define BOOTDEV_CS_SIZE _64M + +#elif defined(MV_NAND_BOOT) + +#define BOOTDEV_CS_SIZE _512K + +#else + +#define Error MV_BOOTSIZE undefined + +#endif + +#define BOOTDEV_CS_BASE ((0xFFFFFFFF - BOOTDEV_CS_SIZE) + 1) + +/* We use the following registers to store DRAM interface pre configuration */ +/* auto-detection results */ +/* IMPORTANT: We are using mask register for that purpose. Before writing */ +/* to units mask register, make sure main maks register is set to disable */ +/* all interrupts. */ +#define DRAM_BUF_REG0 0x30810 /* sdram bank 0 size */ +#define DRAM_BUF_REG1 0x30820 /* sdram config */ +#define DRAM_BUF_REG2 0x30830 /* sdram mode */ +#define DRAM_BUF_REG3 0x60bb0 /* dunit control low */ +#define DRAM_BUF_REG4 0x60a90 /* sdram address control */ +#define DRAM_BUF_REG5 0x60a94 /* sdram timing control low */ +#define DRAM_BUF_REG6 0x60a98 /* sdram timing control high */ +#define DRAM_BUF_REG7 0x60a9c /* sdram ODT control low */ +#define DRAM_BUF_REG8 0x60b90 /* sdram ODT control high */ +#define DRAM_BUF_REG9 0x60b94 /* sdram Dunit ODT control */ +#define DRAM_BUF_REG10 0x60b98 /* sdram Extended Mode */ +#define DRAM_BUF_REG11 0x60b9c /* sdram Ddr2 Time Low Reg */ +#define DRAM_BUF_REG12 0x60bb4 /* sdram Ddr2 Time High Reg */ +#define DRAM_BUF_REG13 0x60ab0 /* dunit Ctrl High */ +#define DRAM_BUF_REG14 0x60ab4 /* sdram second DIMM exist */ + +/* Following the pre-configuration registers default values restored after */ +/* auto-detection is done */ +#define DRAM_BUF_REG_DV 0 + +#define ETH_DEF_TXQ 0 +#define ETH_DEF_RXQ 0 +#define MV_ETH_TX_Q_NUM 1 +#define MV_ETH_RX_Q_NUM 1 +#define ETH_NUM_OF_RX_DESCR 64 +#define ETH_NUM_OF_TX_DESCR ETH_NUM_OF_RX_DESCR*2 + +#define MV_CESA_MAX_BUF_SIZE 1600 + +#endif /* __INCmvSysHwConfigh */ diff --git a/board/mv_feroceon/mv_kw/mv_cmd.c b/board/mv_feroceon/mv_kw/mv_cmd.c new file mode 100644 index 0000000..82e036a --- /dev/null +++ b/board/mv_feroceon/mv_kw/mv_cmd.c @@ -0,0 +1,1524 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include +#include + +#include "mvTypes.h" +#include "mvCtrlEnvLib.h" + +#if defined(MV_INC_BOARD_NOR_FLASH) +#include "norflash/mvFlash.h" +#endif + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +#include "eth-phy/mvEthPhy.h" +#endif + +#if defined(MV_INCLUDE_PEX) +#include "pex/mvPex.h" +#endif + +#if defined(MV_INCLUDE_IDMA) +#include "idma/mvIdma.h" +#include "sys/mvSysIdma.h" +#endif + +#if defined(CFG_NAND_BOOT) || defined(CFG_CMD_NAND) +#include + +/* references to names in cmd_nand.c */ +#define NANDRW_READ 0x01 +#define NANDRW_WRITE 0x00 +#define NANDRW_JFFS2 0x02 +//extern struct nand_chip nand_dev_desc[]; +extern nand_info_t nand_info[]; /* info for NAND chips */ +/* int nand_rw (struct nand_chip* nand, int cmd, + size_t start, size_t len, + size_t * retlen, u_char * buf); + int nand_erase(struct nand_chip* nand, size_t ofs, + size_t len, int clean); +*/ +extern int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); +extern int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts); + + +#endif /* CFG_NAND_BOOT */ + +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) +#if !defined(CFG_NAND_BOOT) +static unsigned int flash_in_which_sec(flash_info_t *fl,unsigned int offset) +{ + unsigned int sec_num; + if(NULL == fl) + return 0xFFFFFFFF; + + for( sec_num = 0; sec_num < fl->sector_count ; sec_num++){ + /* If last sector*/ + if (sec_num == fl->sector_count -1) + { + if((offset >= fl->start[sec_num]) && + (offset <= (fl->size + fl->start[0] - 1)) ) + { + return sec_num; + } + + } + else + { + if((offset >= fl->start[sec_num]) && + (offset < fl->start[sec_num + 1]) ) + { + return sec_num; + } + + } + } + /* return illegal sector Number */ + return 0xFFFFFFFF; + +} + +#endif /* !defined(CFG_NAND_BOOT) */ + + +/******************************************************************************* +burn a u-boot.bin on the Boot Flash +********************************************************************************/ +extern flash_info_t flash_info[]; /* info for FLASH chips */ +#include +#include "bootstrap_def.h" +#if (CONFIG_COMMANDS & CFG_CMD_NET) +/* + * 8 bit checksum + */ +static u8 checksum8(u32 start, u32 len,u8 csum) +{ + register u8 sum = csum; + volatile u8* startp = (volatile u8*)start; + + if (len == 0) + return csum; + + do{ + sum += *startp; + startp++; + }while(--len); + + return (sum); +} + +/* + * Check the extended header and execute the image + */ +static MV_U32 verify_extheader(ExtBHR_t *extBHR) +{ + MV_U8 chksum; + + + /* Caclulate abd check the checksum to valid */ + chksum = checksum8((MV_U32)extBHR , EXT_HEADER_SIZE -1, 0); + if (chksum != (*(MV_U8*)((MV_U32)extBHR + EXT_HEADER_SIZE - 1))) + { + printf("Error! invalid extende header checksum\n"); + return MV_FAIL; + } + + return MV_OK; +} +/* + * Check the CSUM8 on the main header + */ +static MV_U32 verify_main_header(BHR_t *pBHR, MV_U8 headerID) +{ + MV_U8 chksum; + + /* Verify Checksum */ + chksum = checksum8((MV_U32)pBHR, sizeof(BHR_t) -1, 0); + + if (chksum != pBHR->checkSum) + { + printf("Error! invalid image header checksum\n"); + return MV_FAIL; + } + + /* Verify Header */ + if (pBHR->blockID != headerID) + { + printf("Error! invalid image header ID\n"); + return MV_FAIL; + } + + /* Verify Alignment */ + if (pBHR->blockSize & 0x3) + { + printf("Error! invalid image header alignment\n"); + return MV_FAIL; + } + + if ((cpu_to_le32(pBHR->destinationAddr) & 0x3) && (cpu_to_le32(pBHR->destinationAddr) != 0xffffffff)) + { + printf("Error! invalid image header destination\n"); + return MV_FAIL; + } + + if ((cpu_to_le32(pBHR->sourceAddr) & 0x3) && (pBHR->blockID != IBR_HDR_SATA_ID)) + { + printf("Error! invalid image header source\n"); + return MV_FAIL; + } + + return MV_OK; +} + +#if defined(CFG_NAND_BOOT) +/* Boot from NAND flash */ +/* Write u-boot image into the nand flash */ +int nand_burn_uboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 ret = 0; + extern char console_buffer[]; + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + nand_write_options_t wr_opts; + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "u-boot.bin", sizeof(BootFile)); + printf("using default file \"u-boot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + +#ifdef MV_BOOTROM + BHR_t* tmpBHR = (BHR_t*)load_addr; + ExtBHR_t* extBHR = (ExtBHR_t*)(load_addr + BHR_HDR_SIZE); + MV_U32 errCode=0; + + /* Verify Main header checksum */ + errCode = verify_main_header(tmpBHR, IBR_HDR_NAND_ID); + if (errCode) + return 0; + + /* Verify that the extended header is valid */ + errCode = verify_extheader(extBHR); + if (errCode) + return 0; +#endif + + printf("\n**Warning**\n"); + printf("If U-Boot Endiannes is going to change (LE->BE or BE->LE), Then Env parameters should be overriden..\n"); + printf("Override Env parameters? (y/n)"); + readline(" "); + if( strcmp(console_buffer,"Y") == 0 || + strcmp(console_buffer,"yes") == 0 || + strcmp(console_buffer,"y") == 0 ) { + + printf("Erase Env parameters sector %d... ",CFG_ENV_OFFSET); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_ENV_OFFSET; + er_opts.length = CFG_ENV_SECT_SIZE; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0); + printf("\n"); + } + + printf("Erase %d - %d ... ",CFG_MONITOR_BASE, CFG_MONITOR_LEN); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_MONITOR_BASE; + er_opts.length = CFG_MONITOR_LEN; + er_opts.quiet = 1; + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_MONITOR_BASE, CFG_MONITOR_LEN, 0); + + printf("\nCopy to Nand Flash... "); + memset(&wr_opts, 0, sizeof(wr_opts)); + wr_opts.buffer = (u_char*) load_addr; + wr_opts.length = CFG_MONITOR_LEN; + wr_opts.offset = CFG_MONITOR_BASE; + /* opts.forcejffs2 = 1; */ + wr_opts.pad = 1; + wr_opts.blockalign = 1; + wr_opts.quiet = 1; + ret = nand_write_opts(nand, &wr_opts); + /* ret = nand_rw(nand_dev_desc + 0, + NANDRW_WRITE | NANDRW_JFFS2, CFG_MONITOR_BASE, CFG_MONITOR_LEN, + &total, (u_char*)0x100000 + CFG_MONITOR_IMAGE_OFFSET); + */ + if (ret) + printf("Error - NAND burn faild!\n"); + else + printf("\ndone\n"); + + return 1; +} + +U_BOOT_CMD( + bubt, 2, 1, nand_burn_uboot_cmd, + "bubt - Burn an image on the Boot Nand Flash.\n", + " file-name \n" + "\tBurn a binary image on the Boot Nand Flash, default file-name is u-boot.bin .\n" +); + +/* Write nboot loader image into the nand flash */ +int nand_burn_nboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 ret = 0; + extern char console_buffer[]; + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + nand_write_options_t wr_opts; + + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "nboot.bin", sizeof(BootFile)); + printf("using default file \"nboot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + printf("Erase %d - %d ... ",CFG_NBOOT_BASE, CFG_NBOOT_LEN); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_NBOOT_BASE; + er_opts.length = CFG_NBOOT_LEN; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_NBOOT_BASE, CFG_NBOOT_LEN , 0); + + printf("\nCopy to Nand Flash... "); + memset(&wr_opts, 0, sizeof(wr_opts)); + wr_opts.buffer = (u_char*) load_addr; + wr_opts.length = CFG_NBOOT_LEN; + wr_opts.offset = CFG_NBOOT_BASE; + /* opts.forcejffs2 = 1; */ + wr_opts.pad = 1; + wr_opts.blockalign = 1; + wr_opts.quiet = 1; + ret = nand_write_opts(nand, &wr_opts); + /* ret = nand_rw(nand_dev_desc + 0, + NANDRW_WRITE | NANDRW_JFFS2, CFG_NBOOT_BASE, CFG_NBOOT_LEN, + &total, (u_char*)0x100000); + */ + if (ret) + printf("Error - NAND burn faild!\n"); + else + printf("\ndone\n"); + + return 1; +} + +U_BOOT_CMD( + nbubt, 2, 1, nand_burn_nboot_cmd, + "nbubt - Burn a boot loader image on the Boot Nand Flash.\n", + " file-name \n" + "\tBurn a binary boot loader image on the Boot Nand Flash, default file-name is nboot.bin .\n" +); + +#else +/* Boot from Nor flash */ +int nor_burn_uboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 s_first,s_end,env_sec; + extern char console_buffer[]; + + + s_first = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_MONITOR_BASE); + s_end = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_MONITOR_BASE + CFG_MONITOR_LEN -1); + + env_sec = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_ENV_ADDR); + + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "u-boot.bin", sizeof(BootFile)); + printf("using default file \"u-boot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + +#ifdef MV_BOOTROM + BHR_t* tmpBHR = (BHR_t*)load_addr; + ExtBHR_t* extBHR = (ExtBHR_t*)(load_addr + BHR_HDR_SIZE); + MV_U32 errCode=0; + + /* Verify Main header checksum */ + errCode = verify_main_header(tmpBHR, IBR_HDR_SPI_ID); + if (errCode) + return 0; + + /* Verify that the extended header is valid */ + errCode = verify_extheader(extBHR); + if (errCode) + return 0; +#endif + + printf("Un-Protect Flash Monitor space\n"); + flash_protect (FLAG_PROTECT_CLEAR, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[BOOT_FLASH_INDEX]); + + printf("\n**Warning**\n"); + printf("If U-Boot Endiannes is going to change (LE->BE or BE->LE), Then Env parameters should be overriden..\n"); + printf("Override Env parameters? (y/n)"); + readline(" "); + if( strcmp(console_buffer,"Y") == 0 || + strcmp(console_buffer,"yes") == 0 || + strcmp(console_buffer,"y") == 0 ) { + + flash_protect (FLAG_PROTECT_CLEAR, + flash_info[BOOT_FLASH_INDEX].start[env_sec], + flash_info[BOOT_FLASH_INDEX].start[env_sec] + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + + printf("Erase Env parameters sector %d... ",env_sec); + flash_erase(&flash_info[BOOT_FLASH_INDEX], env_sec, env_sec); + + if ((mvCtrlModelGet() != MV_6082_DEV_ID) && + (mvCtrlModelGet() != MV_6183_DEV_ID) && + (mvCtrlModelGet() != MV_6183L_DEV_ID) && + (mvCtrlModelGet() != MV_6281_DEV_ID) && + (mvCtrlModelGet() != MV_6192_DEV_ID) && + (mvCtrlModelGet() != MV_6190_DEV_ID) && + (mvCtrlModelGet() != MV_6180_DEV_ID)) + flash_protect (FLAG_PROTECT_SET, + flash_info[BOOT_FLASH_INDEX].start[env_sec], + flash_info[BOOT_FLASH_INDEX].start[env_sec] + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + + } + + printf("Erase %d - %d sectors... ",s_first,s_end); + flash_erase(&flash_info[BOOT_FLASH_INDEX], s_first, s_end); + + printf("Copy to Flash... "); + + flash_write ( (uchar *)(CFG_LOAD_ADDR + CFG_MONITOR_IMAGE_OFFSET), + (ulong)CFG_MONITOR_BASE, + (ulong)(filesize - CFG_MONITOR_IMAGE_OFFSET)); + + printf("done\nProtect Flash Monitor space\n"); + flash_protect (FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[BOOT_FLASH_INDEX]); + + return 1; +} + +U_BOOT_CMD( + bubt, 2, 1, nor_burn_uboot_cmd, + "bubt - Burn an image on the Boot Flash.\n", + " file-name \n" + "\tBurn a binary image on the Boot Flash, default file-name is u-boot.bin .\n" +); +#endif /* defined(CFG_NAND_BOOT) */ +#endif /* (CONFIG_COMMANDS & CFG_CMD_NET) */ + + + +/******************************************************************************* +Reset environment variables. +********************************************************************************/ +extern flash_info_t flash_info[]; /* info for FLASH chips */ +int resetenv_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(CFG_NAND_BOOT) + printf("Erase Env parameters offset 0x%x... ",CFG_ENV_OFFSET); + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_ENV_OFFSET; + er_opts.length = CFG_ENV_SECT_SIZE; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0); + printf("done"); +#else + MV_U32 env_sec = flash_in_which_sec(&flash_info[0], CFG_ENV_ADDR); + + if (env_sec == -1) + { + printf("Could not find ENV Sector\n"); + return 0; + } + + printf("Un-Protect ENV Sector\n"); + + flash_protect(FLAG_PROTECT_CLEAR, + CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[0]); + + + printf("Erase sector %d ... ",env_sec); + flash_erase(&flash_info[0], env_sec, env_sec); + printf("done\nProtect ENV Sector\n"); + + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[0]); + +#endif /* defined(CFG_NAND_BOOT) */ + printf("\nWarning: Default Environment Variables will take effect Only after RESET \n\n"); + return 1; +} + +U_BOOT_CMD( + resetenv, 1, 1, resetenv_cmd, + "resetenv - Return all environment variable to default.\n", + " \n" + "\t Erase the environemnt variable sector.\n" +); + +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FLASH) */ +#if CONFIG_COMMANDS & CFG_CMD_BSP + +/****************************************************************************** +* Category - General +* Functionality- The commands allows the user to view the contents of the MV +* internal registers and modify them. +* Need modifications (Yes/No) - no +*****************************************************************************/ +int ir_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +{ + MV_U32 regNum = 0x0, regVal, regValTmp, res; + MV_8 regValBin[40]; + MV_8 cmd[40]; + int i,j = 0, flagm = 0; + extern MV_8 console_buffer[]; + + if( argc == 2 ) { + regNum = simple_strtoul( argv[1], NULL, 16 ); + } + else { + printf( "Usage:\n%s\n", cmdtp->usage ); + return 0; + } + + regVal = MV_REG_READ( regNum ); + regValTmp = regVal; + printf( "Internal register 0x%x value : 0x%x\n ",regNum, regVal ); + printf( "\n 31 24 16 8 0" ); + printf( "\n | | | | |\nOLD: " ); + + for( i = 31 ; i >= 0 ; i-- ) { + if( regValTmp > 0 ) { + res = regValTmp % 2; + regValTmp = (regValTmp - res) / 2; + if( res == 0 ) + regValBin[i] = '0'; + else + regValBin[i] = '1'; + } + else + regValBin[i] = '0'; + } + + for( i = 0 ; i < 32 ; i++ ) { + printf( "%c", regValBin[i] ); + if( (((i+1) % 4) == 0) && (i > 1) && (i < 31) ) + printf( "-" ); + } + + readline( "\nNEW: " ); + strcpy(cmd, console_buffer); + if( (cmd[0] == '0') && (cmd[1] == 'x') ) { + regVal = simple_strtoul( cmd, NULL, 16 ); + flagm=1; + } + else { + for( i = 0 ; i < 40 ; i++ ) { + if(cmd[i] == '\0') + break; + if( i == 4 || i == 9 || i == 14 || i == 19 || i == 24 || i == 29 || i == 34 ) + continue; + if( cmd[i] == '1' ) { + regVal = regVal | (0x80000000 >> j); + flagm = 1; + } + else if( cmd[i] == '0' ) { + regVal = regVal & (~(0x80000000 >> j)); + flagm = 1; + } + j++; + } + } + + if( flagm == 1 ) { + MV_REG_WRITE( regNum, regVal ); + printf( "\nNew value = 0x%x\n\n", MV_REG_READ(regNum) ); + } + return 1; +} + +U_BOOT_CMD( + ir, 2, 1, ir_cmd, + "ir - reading and changing MV internal register values.\n", + " address\n" + "\tDisplays the contents of the internal register in 2 forms, hex and binary.\n" + "\tIt's possible to change the value by writing a hex value beginning with \n" + "\t0x or by writing 0 or 1 in the required place. \n" + "\tPressing enter without any value keeps the value unchanged.\n" +); + +/****************************************************************************** +* Category - General +* Functionality- Display the auto detect values of the TCLK and SYSCLK. +* Need modifications (Yes/No) - no +*****************************************************************************/ +int clk_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + printf( "TCLK %dMhz, SYSCLK %dMhz (UART baudrate %d)\n", + mvTclkGet()/1000000, mvSysClkGet()/1000000, CONFIG_BAUDRATE); + return 1; +} + +U_BOOT_CMD( + dclk, 1, 1, clk_cmd, + "dclk - Display the MV device CLKs.\n", + " \n" + "\tDisplay the auto detect values of the TCLK and SYSCLK.\n" +); + +/****************************************************************************** +* Functional only when using Lauterbach to load image into DRAM +* Category - DEBUG +* Functionality- Display the array of registers the u-boot write to. +* +*****************************************************************************/ +#if defined(REG_DEBUG) +int reg_arry[REG_ARRAY_SIZE][2]; +int reg_arry_index = 0; +int print_registers( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int i; + printf("Register display\n"); + + for (i=0; i < reg_arry_index; i++) + printf("Index %d 0x%x=0x%08x\n", i, (reg_arry[i][0] & 0x000fffff), reg_arry[i][1]); + + /* Print DRAM registers */ + printf("Index %d 0x%x=0x%08x\n", i++, 0x1500, MV_REG_READ(0x1500)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1504, MV_REG_READ(0x1504)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1508, MV_REG_READ(0x1508)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x150c, MV_REG_READ(0x150c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1510, MV_REG_READ(0x1510)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1514, MV_REG_READ(0x1514)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1518, MV_REG_READ(0x1518)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x151c, MV_REG_READ(0x151c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1400, MV_REG_READ(0x1400)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1404, MV_REG_READ(0x1404)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1408, MV_REG_READ(0x1408)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x140c, MV_REG_READ(0x140c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1410, MV_REG_READ(0x1410)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x141c, MV_REG_READ(0x141c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1420, MV_REG_READ(0x1420)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1424, MV_REG_READ(0x1424)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1428, MV_REG_READ(0x1428)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x147c, MV_REG_READ(0x147c)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1494, MV_REG_READ(0x1494)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x1498, MV_REG_READ(0x1498)); + printf("Index %d 0x%x=0x%08x\n", i++, 0x149c, MV_REG_READ(0x149c)); + + printf("Number of Reg %d \n", i); + + return 1; +} + +U_BOOT_CMD( + printreg, 1, 1, print_registers, + "printreg - Display the register array the u-boot write to.\n", + " \n" + "\tDisplay the register array the u-boot write to.\n" +); +#endif + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +/****************************************************************************** +* Category - Etherent +* Functionality- Display PHY ports status (using SMI access). +* Need modifications (Yes/No) - No +*****************************************************************************/ +int sg_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(MV_INC_BOARD_QD_SWITCH) + printf( "Switch status not supported\n"); +#else + MV_U32 port; + for( port = 0 ; port < mvCtrlEthMaxPortGet(); port++ ) { + + printf( "PHY %d :\n", port ); + printf( "---------\n" ); + + mvEthPhyPrintStatus( mvBoardPhyAddrGet(port) ); + + printf("\n"); + } +#endif + return 1; +} + +U_BOOT_CMD( + sg, 1, 1, sg_cmd, + "sg - scanning the PHYs status\n", + " \n" + "\tScan all the Gig port PHYs and display their Duplex, Link, Speed and AN status.\n" +); +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + +#if defined(MV_INCLUDE_IDMA) + +/****************************************************************************** +* Category - DMA +* Functionality- Perform a DMA transaction +* Need modifications (Yes/No) - No +*****************************************************************************/ +int mvDma_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +{ + MV_8 cmd[20], c; + extern MV_8 console_buffer[]; + MV_U32 chan, src, dst, byteCount, ctrlLo; + MV_DMA_DEC_WIN win; + MV_BOOL err; + + /* IDMA channel */ + if( argc == 2 ) + chan = simple_strtoul( argv[1], NULL, 16 ); + else + chan = 0; + + /* source address */ + while(1) { + readline( "Source Address: " ); + strcpy( cmd, console_buffer ); + src = simple_strtoul( cmd, NULL, 16 ); + if( src == 0xffffffff ) printf( "Bad address !!!\n" ); + else break; + } + + /* desctination address */ + while(1) { + readline( "Destination Address: " ); + strcpy(cmd, console_buffer); + dst = simple_strtoul( cmd, NULL, 16 ); + if( dst == 0xffffffff ) printf("Bad address !!!\n"); + else break; + } + + /* byte count */ + while(1) { + readline( "Byte Count (up to 16M (0xffffff-1)): " ); + strcpy( cmd, console_buffer ); + byteCount = simple_strtoul( cmd, NULL, 16 ); + if( (byteCount > 0xffffff) || (byteCount == 0) ) printf("Bad value !!!\n"); + else break; + } + + /* compose the command */ + ctrlLo = ICCLR_BLOCK_MODE | ICCLR_NON_CHAIN_MODE | ICCLR_SRC_INC | ICCLR_DST_INC; + + + if (byteCount > _64K) + { + ctrlLo |= ICCLR_DESC_MODE_16M; + } + + /* set data transfer limit */ + while(1) { + printf( "Data transfer limit:\n" ); + printf( "(1) 8 bytes at a time.\n" ); + printf( "(2) 16 bytes at a time.\n" ); + printf( "(3) 32 bytes at a time.\n" ); + printf( "(4) 64 bytes at a time.\n" ); + printf( "(5) 128 bytes at a time.\n" ); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + ctrlLo |= (ICCLR_DST_BURST_LIM_32BYTE | ICCLR_SRC_BURST_LIM_32BYTE); + printf( "32 bytes at a time.\n" ); + break; + case '1': + ctrlLo |= (ICCLR_DST_BURST_LIM_8BYTE | ICCLR_SRC_BURST_LIM_8BYTE); + break; + case '2': + ctrlLo |= (ICCLR_DST_BURST_LIM_16BYTE | ICCLR_SRC_BURST_LIM_16BYTE); + break; + case '3': + ctrlLo |= (ICCLR_DST_BURST_LIM_32BYTE | ICCLR_SRC_BURST_LIM_32BYTE); + break; + case '4': + ctrlLo |= (ICCLR_DST_BURST_LIM_64BYTE | ICCLR_SRC_BURST_LIM_64BYTE); + break; + case '5': + ctrlLo |= (ICCLR_DST_BURST_LIM_128BYTE | ICCLR_SRC_BURST_LIM_128BYTE); + break; + default: + printf( "Bad value !!!\n" ); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* set ovveride source option */ + while(1) { + printf( "Override Source:\n" ); + printf( "(0) - no override\n" ); + mvDmaWinGet( 1, &win ); + printf( "(1) - use Win1 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 2, &win ); + printf( "(2) - use Win2 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 3, &win ); + printf( "(3) - use Win3 (%s)\n",mvCtrlTargetNameGet(win.target)); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + case '0': + printf( "No override\n" ); + break; + case '1': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(1); + break; + case '2': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(2); + break; + case '3': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(3); + break; + default: + printf("Bad value !!!\n"); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* set override destination option */ + while(1) { + printf( "Override Destination:\n" ); + printf( "(0) - no override\n" ); + mvDmaWinGet( 1, &win ); + printf( "(1) - use Win1 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 2, &win ); + printf( "(2) - use Win2 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 3, &win ); + printf( "(3) - use Win3 (%s)\n",mvCtrlTargetNameGet(win.target)); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + case '0': + printf( "No override\n" ); + break; + case '1': + ctrlLo |= ICCLR_OVRRD_DST_BAR(1); + break; + case '2': + ctrlLo |= ICCLR_OVRRD_DST_BAR(2); + break; + case '3': + ctrlLo |= ICCLR_OVRRD_DST_BAR(3); + break; + default: + printf("Bad value !!!\n"); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* wait for previous transfer completion */ + while( mvDmaStateGet(chan) != MV_IDLE ); + + /* issue the transfer */ + mvDmaCtrlLowSet( chan, ctrlLo ); + mvDmaTransfer( chan, src, dst, byteCount, 0 ); + + /* wait for completion */ + while( mvDmaStateGet(chan) != MV_IDLE ); + + printf( "Done...\n" ); + return 1; +} + +U_BOOT_CMD( + dma, 2, 1, mvDma_cmd, + "dma - Perform DMA\n", + " \n" + "\tPerform DMA transaction with the parameters given by the user.\n" +); + +#endif /* #if defined(MV_INCLUDE_IDMA) */ + +/****************************************************************************** +* Category - Memory +* Functionality- Displays the MV's Memory map +* Need modifications (Yes/No) - Yes +*****************************************************************************/ +int displayMemoryMap_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvCtrlAddrDecShow(); + return 1; +} + +U_BOOT_CMD( + map, 1, 1, displayMemoryMap_cmd, + "map - Diasplay address decode windows\n", + " \n" + "\tDisplay controller address decode windows: CPU, PCI, Gig, DMA, XOR and COMM\n" +); + + + +#include "ddr2/spd/mvSpd.h" +#if defined(MV_INC_BOARD_DDIM) + +/****************************************************************************** +* Category - Memory +* Functionality- Displays the SPD information for a givven dimm +* Need modifications (Yes/No) - +*****************************************************************************/ + +int dimminfo_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int num = 0; + + if (argc > 1) { + num = simple_strtoul (argv[1], NULL, 10); + } + + printf("*********************** DIMM%d *****************************\n",num); + + dimmSpdPrint(num); + + printf("************************************************************\n"); + + return 1; +} + +U_BOOT_CMD( + ddimm, 2, 1, dimminfo_cmd, + "ddimm - Display SPD Dimm Info\n", + " [0/1]\n" + "\tDisplay Dimm 0/1 SPD information.\n" +); + +/****************************************************************************** +* Category - Memory +* Functionality- Copy the SPD information of dimm 0 to dimm 1 +* Need modifications (Yes/No) - +*****************************************************************************/ + +int spdcpy_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + printf("Copy DIMM 0 SPD data into DIMM 1 SPD..."); + + if (MV_OK != dimmSpdCpy()) + printf("\nDIMM SPD copy fail!\n"); + else + printf("Done\n"); + + return 1; +} + +U_BOOT_CMD( + spdcpy, 2, 1, spdcpy_cmd, + "spdcpy - Copy Dimm 0 SPD to Dimm 1 SPD \n", + "" + "" +); +#endif /* #if defined(MV_INC_BOARD_DDIM) */ + +/****************************************************************************** +* Functionality- Go to an address and execute the code there and return, +* defualt address is 0x40004 +*****************************************************************************/ +extern void cpu_dcache_flush_all(void); +extern void cpu_icache_flush_invalidate_all(void); + +void mv_go(unsigned long addr,int argc, char *argv[]) +{ + int rc; + addr = MV_CACHEABLE(addr); + char* envCacheMode = getenv("cacheMode"); + + /* + * pass address parameter as argv[0] (aka command name), + * and all remaining args + */ + + if(envCacheMode && (strcmp(envCacheMode,"write-through") == 0)) + { + int i=0; + + /* Flush Invalidate I-Cache */ + cpu_icache_flush_invalidate_all(); + + /* Drain write buffer */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); + + + } + else /*"write-back"*/ + { + int i=0; + + /* Flush Invalidate I-Cache */ + cpu_icache_flush_invalidate_all(); + + /* Drain write buffer */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); + + + /* Flush invalidate D-cache */ + cpu_dcache_flush_all(); + + + } + + + rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]); + + return; +} + +int g_cmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0; + } + + addr = 0x40000; + + if (argc > 1) { + addr = simple_strtoul(argv[1], NULL, 16); + } + mv_go(addr,argc,&argv[0]); + return 1; +} + +U_BOOT_CMD( + g, CFG_MAXARGS, 1, g_cmd, + "g - start application at cached address 'addr'(default addr 0x40000)\n", + " addr [arg ...] \n" + "\tStart application at address 'addr'cachable!!!(default addr 0x40004/0x240004)\n" + "\tpassing 'arg' as arguments\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/****************************************************************************** +* Functionality- Searches for a value +*****************************************************************************/ +int fi_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 s_address,e_address,value,i,tempData; + MV_BOOL error = MV_FALSE; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 4){ + value = simple_strtoul(argv[1], NULL, 16); + s_address = simple_strtoul(argv[2], NULL, 16); + e_address = simple_strtoul(argv[3], NULL, 16); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + if(s_address == 0xffffffff || e_address == 0xffffffff) error = MV_TRUE; + if(s_address%4 != 0 || e_address%4 != 0) error = MV_TRUE; + if(s_address > e_address) error = MV_TRUE; + if(error) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + for(i = s_address; i < e_address ; i+=4) + { + tempData = (*((volatile unsigned int *)i)); + if(tempData == value) + { + printf("Value: %x found at ",value); + printf("address: %x\n",i); + return 1; + } + } + printf("Value not found!!\n"); + return 1; +} + +U_BOOT_CMD( + fi, 4, 1, fi_cmd, + "fi - Find value in the memory.\n", + " value start_address end_address\n" + "\tSearch for a value 'value' in the memory from address 'start_address to\n" + "\taddress 'end_address'.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/****************************************************************************** +* Functionality- Compare the memory with Value. +*****************************************************************************/ +int cmpm_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 s_address,e_address,value,i,tempData; + MV_BOOL error = MV_FALSE; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 4){ + value = simple_strtoul(argv[1], NULL, 16); + s_address = simple_strtoul(argv[2], NULL, 16); + e_address = simple_strtoul(argv[3], NULL, 16); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + if(s_address == 0xffffffff || e_address == 0xffffffff) error = MV_TRUE; + if(s_address%4 != 0 || e_address%4 != 0) error = MV_TRUE; + if(s_address > e_address) error = MV_TRUE; + if(error) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + for(i = s_address; i < e_address ; i+=4) + { + tempData = (*((volatile unsigned int *)i)); + if(tempData != value) + { + printf("Value: %x found at address: %x\n",tempData,i); + } + } + return 1; +} + +U_BOOT_CMD( + cmpm, 4, 1, cmpm_cmd, + "cmpm - Compare Memory\n", + " value start_address end_address.\n" + "\tCompare the memory from address 'start_address to address 'end_address'.\n" + "\twith value 'value'\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + + + +#if 0 +/****************************************************************************** +* Category - Etherent +* Functionality- Display PHY ports status (using SMI access). +* Need modifications (Yes/No) - No +*****************************************************************************/ +int eth_show_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ethRegs(argv[1]); + ethPortRegs(argv[1]); + ethPortStatus(argv[1]); + ethPortQueues(argv[1],0,0,1); + return 1; +} + +U_BOOT_CMD( + ethShow, 2, 2, eth_show_cmd, + "ethShow - scanning the PHYs status\n", + " \n" + "\tScan all the Gig port PHYs and display their Duplex, Link, Speed and AN status.\n" +); +#endif + +#if defined(MV_INCLUDE_PEX) + +#include "pci/mvPci.h" + +int pcie_phy_read_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U16 phyReg; + + mvPexPhyRegRead(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16), &phyReg); + + printf ("0x%x\n", phyReg); + + return 1; +} + +U_BOOT_CMD( + pciePhyRead, 3, 3, pcie_phy_read_cmd, + "phyRead - Read PCI-E Phy register\n", + " PCI-E_interface Phy_offset. \n" + "\tRead the PCI-E Phy register. \n" +); + + +int pcie_phy_write_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvPexPhyRegWrite(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16 ), + simple_strtoul( argv[3], NULL, 16 )); + + return 1; +} + +U_BOOT_CMD( + pciePhyWrite, 4, 4, pcie_phy_write_cmd, + "pciePhyWrite - Write PCI-E Phy register\n", + " PCI-E_interface Phy_offset value.\n" + "\tWrite to the PCI-E Phy register.\n" +); + +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) + +#include "eth-phy/mvEthPhy.h" + +int phy_read_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U16 phyReg; + + mvEthPhyRegRead(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16), &phyReg); + + printf ("0x%x\n", phyReg); + + return 1; +} + +U_BOOT_CMD( + phyRead, 3, 3, phy_read_cmd, + "phyRead - Read Phy register\n", + " Phy_address Phy_offset. \n" + "\tRead the Phy register. \n" +); + + +int phy_write_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvEthPhyRegWrite(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16 ), + simple_strtoul( argv[3], NULL, 16 )); + + return 1; +} + +U_BOOT_CMD( + phyWrite, 4, 4, phy_write_cmd, + "phyWrite - Write Phy register\n", + " Phy_address Phy_offset value.\n" + "\tWrite to the Phy register.\n" +); + +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + +#endif /* MV_TINY */ + +int _4BitSwapArry[] = {0,8,4,0xc,2,0xa,6,0xe,1,9,5,0xd,3,0xb,7,0xf}; +int _3BitSwapArry[] = {0,4,2,6,1,5,3,7}; + +int do_satr(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + char *cmd, *s; + MV_U8 data0=0, data1=0, devNum0=0, devNum1=0; + MV_U8 moreThenOneDev=0, regNum = 0; + MV_U8 mask0=0, mask1=0, shift0=0, shift1=0; + MV_U8 val=0, width=0; + + /* at least two arguments please */ + if (argc < 2) + goto usage; + + cmd = argv[1]; + + if (strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0) + goto usage; + + /* read write */ + if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { + int read; + + + read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ + + /* In write mode we have additional value */ + if (!read) + { + if (argc < 3) + goto usage; + else + /* Value for write */ + val = (ulong)simple_strtoul(argv[2], NULL, 16); + } + + printf("\nS@R %s: ", read ? "read" : "write"); + s = strchr(cmd, '.'); + if ((s != NULL) && (strcmp(s, ".cpu") == 0)) + { +#ifdef DB_88F6180A + moreThenOneDev = 0; + regNum = 0; + devNum0 = 0; + mask0 = 0x7; + shift0 = 0; + mask1 = 0x0; + shift1 = 0; + width = 3; +#else + moreThenOneDev = 0; + regNum = 0; + devNum0 = 0; + mask0 = 0xf; + shift0 = 0; + mask1 = 0x0; + shift1 = 0; + width = 4; +#endif + } + + if ((s != NULL) && (strcmp(s, ".cpu2ddr") == 0)) + { + moreThenOneDev = 1; + regNum = 0; + devNum0 = 0; + devNum1 = 1; + mask0 = 0x10; + shift0 = 4; + mask1 = 0x7; + shift1 = 1; + width = 4; + } + + if ((s != NULL) && (strcmp(s, ".cpu2L2") == 0)) + { + moreThenOneDev = 1; + regNum = 0; + devNum0 = 1; + devNum1 = 2; + mask0 = 0x18; + shift0 = 3; + mask1 = 0x1; + shift1 = 2; + width = 3; + } + + if ((s != NULL) && (strcmp(s, ".SSCG") == 0)) + { +#ifdef DB_88F6180A + moreThenOneDev = 0; + regNum = 0; + devNum0 = 0; + mask0 = 0x8; + shift0 = 3; + mask1 = 0x0; + shift1 = 0; +#else + moreThenOneDev = 0; + regNum = 0; + devNum0 = 2; + mask0 = 0x4; + shift0 = 2; + mask1 = 0x0; + shift1 = 0; +#endif + } + + if ((s != NULL) && (strcmp(s, ".PEXCLK") == 0)) + { + moreThenOneDev = 0; + regNum = 0; + devNum0 = 2; + mask0 = 0x10; + shift0 = 4; + mask1 = 0x0; + shift1 = 0; + } + + if ((s != NULL) && (strcmp(s, ".MPP18") == 0)) + { + moreThenOneDev = 0; + regNum = 0; + devNum0 = 2; + mask0 = 0x8; + shift0 = 3; + mask1 = 0x0; + shift1 = 0; + } + + if (read) { + /* read */ + data0 = mvBoarTwsiSatRGet(devNum0, regNum); + if (moreThenOneDev) + data1 = mvBoarTwsiSatRGet(devNum1, regNum); + + data0 = ((data0 & mask0) >> shift0); + + if (moreThenOneDev) + { + data1 = ((data1 & mask1) << shift1); + data0 |= data1; + } + + /* Swap value */ + switch(width) + { + case 4: + data0 = _4BitSwapArry[data0]; + break; + case 3: + data0 = _3BitSwapArry[data0]; + break; + case 2: + data0 = (((data0 & 0x1) << 0x1) | ((data0 & 0x2) >> 0x1)); + break; + } + + printf("Read S@R val %x\n", data0); + + } else { + + /* Swap value */ + switch(width) + { + case 4: + val = _4BitSwapArry[val]; + break; + case 3: + val = _3BitSwapArry[val]; + break; + case 2: + val = (((val & 0x1) << 0x1) | ((val & 0x2) >> 0x1)); + break; + } + + /* read modify write */ + data0 = mvBoarTwsiSatRGet(devNum0, regNum); + data0 = (data0 & ~mask0); + data0 |= ((val << shift0) & mask0); + if (mvBoarTwsiSatRSet(devNum0, regNum, data0) != MV_OK) + { + printf("Write S@R first device val %x fail\n", data0); + return 1; + } + printf("Write S@R first device val %x succeded\n", data0); + + if (moreThenOneDev) + { + data1 = mvBoarTwsiSatRGet(devNum1, regNum); + data1 = (data1 & ~mask1); + data1 |= ((val >> shift1) & mask1); + if (mvBoarTwsiSatRSet(devNum1, regNum, data1) != MV_OK) + { + printf("Write S@R second device val %x fail\n", data1); + return 1; + } + printf("Write S@R second device val %x succeded\n", data1); + } + } + + return 0; + } + +usage: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +#ifdef DB_88F6180A +U_BOOT_CMD(SatR, 5, 1, do_satr, + "SatR - sample at reset sub-system, relevent for DB only\n", + "read.cpu - read cpu clock from S@R devices\n" + "SatR read.SSCG - read SSCG state from S@R devices [0 ~ en]\n" + "SatR write.cpu val - write cpu clock val to S@R devices [0,1,..,7]\n" + "SatR write.SSCG val - write SSCG state val to S@R devices [0 ~ en]\n" +); +#else +U_BOOT_CMD(SatR, 5, 1, do_satr, + "SatR - sample at reset sub-system, relevent for DB only\n", + "read.cpu - read cpu clock from S@R devices\n" + "SatR read.cpu2ddr - read cpu2ddr clock ratio from S@R devices\n" + "SatR read.cpu2L2 - read cpu2L2 clock ratio from S@R devices\n" + "SatR read.SSCG - read SSCG state from S@R devices [0 ~ en]\n" + "SatR read.PEXCLK - read PCI-E clock state from S@R devices [0 ~ input]\n" + "SatR read.MPP18 - reserved\n" + "SatR write.cpu val - write cpu clock val to S@R devices [0,1,..,F]\n" + "SatR write.cpu2ddr val - write cpu2ddr clock ratio val to S@R devices [0,1,..,F]\n" + "SatR write.cpu2L2 val - write cpu2L2 clock ratio val to S@R devices [0,1,..,7]\n" + "SatR write.SSCG val - write SSCG state val to S@R devices [0 ~ en]\n" + "SatR write.PEXCLK - write PCI-E clock state from S@R devices [0 ~ input]\n" + "SatR write.MPP18 - reserved\n" +); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) +extern void recoveryHandle(void); +int do_rcvr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + recoveryHandle(); + return 1; +} + +U_BOOT_CMD( + rcvr, 3, 1, do_rcvr, + "rcvr\t- Satrt recovery process (Distress Beacon with TFTP server)\n", + "\n" +); +#endif /* CFG_CMD_RCVR */ diff --git a/board/mv_feroceon/mv_kw/mv_dram.c b/board/mv_feroceon/mv_kw/mv_dram.c new file mode 100644 index 0000000..6b6652a --- /dev/null +++ b/board/mv_feroceon/mv_kw/mv_dram.c @@ -0,0 +1,322 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include "ddr2/mvDramIf.h" +#include "mvOs.h" +#include "mvBoardEnvLib.h" +#include "ddr2/mvDramIfRegs.h" +#include "mvCpuIfRegs.h" + +#ifdef DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +extern void i2c_init(int speed, int slaveaddr); +extern void _start(void); +extern unsigned int mvCpuPclkGet(void); +extern void reset_cpu(void); +extern int dramBoot; + + +#ifdef MV_INC_DRAM_MFG_TEST +static MV_VOID mvDramMfgTrst(void); +static MV_STATUS mv_mem_test(MV_U32* pMem, MV_U32 pattern, MV_U32 count); +static MV_STATUS mv_mem_cmp(MV_U32* pMem, MV_U32 pattern, MV_U32 count); +#endif + +MV_VOID mvIntrfaceWidthPrint(MV_VOID) +{ + printf(" 16bit width"); +} + +MV_VOID mvIntrfaceParamPrint(MV_VOID) +{ + MV_U32 temp; + + printf("DRAM"); + switch((MV_REG_READ(0x141c) >> 4) & 0x7) + { + case 0x3: printf(" CAS Latency = 3"); + break; + case 0x4: printf(" CAS Latency = 4"); + break; + case 0x5: printf(" CAS Latency = 5"); + break; + case 0x6: printf(" CAS Latency = 6"); + break; + default: printf(" unknown CAL "); + break; + } + + temp = MV_REG_READ(0x1408); + printf(" tRP = %d tRAS = %d tRCD=%d\n", + ((temp >> 8) & 0xf) + 1, ((temp >> 16) & 0x10) + (temp & 0xf) + 1, ((temp >> 4) & 0xf) + 1); +} + +int dram_init (void) +{ + + DECLARE_GLOBAL_DATA_PTR; + unsigned int i, dramTotalSize=0; + char name[15]; + MV_32 memBase; + + mvCtrlModelRevNameGet(name); + printf("\nSoc: %s", name); + printf(" (DDR2)\n", name); + + printf("CPU running @ %dMhz L2 running @ %dMhz\n", mvCpuPclkGet()/1000000, mvCpuL2ClkGet()/1000000); +#ifdef MV_TCLK_CALC + printf("SysClock = %dMhz , Calc TClock = %dMhz \n\n", CFG_BUS_CLK/1000000, CFG_TCLK/1000000); +#else + printf("SysClock = %dMhz , TClock = %dMhz \n\n", CFG_BUS_CLK/1000000, CFG_TCLK/1000000); +#endif +#if defined(MV_INC_BOARD_DDIM) + /* Call dramInit */ + if (0 == (dramTotalSize = initdram(0))) + { + printf("DRAM Initialization Failed\n"); + reset_cpu(); + return (1); + } +#endif + + mvIntrfaceParamPrint(); + + for(i = 0; i< MV_DRAM_MAX_CS; i++) + { +#if !defined(MV_88F6082L) && defined(MV_88F6082) + if (mvCtrlModelRevGet() == MV_6082_A0_ID) + { + gd->bd->bi_dram[i].start = (i)?_16M:0; + gd->bd->bi_dram[i].size = _8M; + } + else + { + memBase = mvDramIfBankBaseGet(i); + if (MV_ERROR == memBase) + gd->bd->bi_dram[i].start = 0; + else + gd->bd->bi_dram[i].start = memBase; + + gd->bd->bi_dram[i].size = mvDramIfBankSizeGet(i); + } +#else + memBase = mvDramIfBankBaseGet(i); + if (MV_ERROR == memBase) + gd->bd->bi_dram[i].start = 0; + else + gd->bd->bi_dram[i].start = memBase; + + gd->bd->bi_dram[i].size = mvDramIfBankSizeGet(i); +#endif + dramTotalSize += gd->bd->bi_dram[i].size; + if (gd->bd->bi_dram[i].size) + { + printf("DRAM CS[%d] base 0x%08x ",i, gd->bd->bi_dram[i].start); + mvSizePrint(gd->bd->bi_dram[i].size); + printf("\n"); + } + } + + printf("DRAM Total "); + mvSizePrint(dramTotalSize); + mvIntrfaceWidthPrint(); + printf("\n"); +#ifdef MV_INC_DRAM_MFG_TEST + mvDramMfgTrst(); +#endif + return 0; +} + +#if defined(MV_INC_BOARD_DDIM) + +/* u-boot interface function to SDRAM init - this is where all the + * controlling logic happens */ +long int initdram(int board_type) +{ + MV_VOIDFUNCPTR pRom; + MV_U32 forcedCl; /* Forced CAS Latency */ + MV_U32 totalSize; + char * env; + MV_TWSI_ADDR slave; + + /* r0 <- current position of code */ + /* test if we run from flash or RAM */ + if(dramBoot != 1) + { + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(CFG_I2C_SPEED, CFG_TCLK, &slave, 0); + + /* Calculating MIN/MAX CAS latency according to user settings */ + env = getenv("CASset"); + + if(env && (strcmp(env,"1.5") == 0)) + { + forcedCl = 15; + } + else if(env && (strcmp(env,"2") == 0)) + { + forcedCl = 20; + } + else if(env && (strcmp(env,"2.5") == 0)) + { + forcedCl = 25; + } + else if(env && (strcmp(env,"3") == 0)) + { + forcedCl = 30; + } + else if(env && (strcmp(env,"4") == 0)) + { + forcedCl = 40; + } + else if(env && (strcmp(env,"5") == 0)) + { + forcedCl = 50; + } + else if(env && (strcmp(env,"6") == 0)) + { + forcedCl = 60; + } + else + { + forcedCl = 0; + } + + /* detect the dram configuartion parameters */ + if (MV_OK != mvDramIfDetect(forcedCl,1)) + { + printf("DRAM Auto Detection Failed! System Halt!\n"); + return 0; + } + + /* set the dram configuration */ + /* Calculate jump address of _mvDramIfConfig() */ + +#if defined(MV_BOOTROM) + pRom = (MV_VOIDFUNCPTR)(((MV_VOIDFUNCPTR)_mvDramIfConfig - (MV_VOIDFUNCPTR)_start) + + (MV_VOIDFUNCPTR)CFG_MONITOR_BASE + (MV_VOIDFUNCPTR)MONITOR_HEADER_LEN); +#else + pRom = (MV_VOIDFUNCPTR)(((MV_VOIDFUNCPTR)_mvDramIfConfig - (MV_VOIDFUNCPTR)_start) + + (MV_VOIDFUNCPTR)CFG_MONITOR_BASE); +#endif + + + (*pRom) (); /* Jump to _mvDramIfConfig*/ + } + + totalSize = mvDramIfSizeGet(); + + + return(totalSize); +} + +#endif /* #if defined(MV_INC_BOARD_DDIM) */ + +#ifdef MV_INC_DRAM_MFG_TEST +static MV_VOID mvDramMfgTrst(void) +{ + + /* Memory test */ + DECLARE_GLOBAL_DATA_PTR; + unsigned int mem_len,i,j, pattern; + unsigned int *mem_start; + char *env; + + env = getenv("enaPost"); + if(!env || ( (strcmp(env,"Yes") == 0) || (strcmp(env,"yes") == 0) ) ) + { + printf("Memory test pattern: "); + + for (j = 0 ; j<2 ; j++) + { + + switch(j){ + case 0: + pattern=0x55555555; + printf("0x%X, ",pattern); + break; + case 1: + pattern=0xAAAAAAAA; + printf("0x%X, ",pattern); + break; + default: + pattern=0x0; + printf("0x%X, ",pattern); + break; + } + + for(i = 0; i< MV_DRAM_MAX_CS; i++) + { + mem_start = (unsigned int *)gd->bd->bi_dram[i].start; + mem_len = gd->bd->bi_dram[i].size; + if (i == 0) + { + mem_start+= _4M; + mem_len-= _4M; + } + mem_len/=4; + if (MV_OK != mv_mem_test(mem_start, pattern, mem_len)) + { + printf(" Fail!\n"); + while(1); + } + } + } + printf(" Pass\n"); + } +} + + +static MV_STATUS mv_mem_test(MV_U32* pMem, MV_U32 pattern, MV_U32 count) +{ + int i; + for (i=0 ; i< count ; i+=1) + *(pMem + i) = pattern; + + if (MV_OK != mv_mem_cmp(pMem, pattern, count)) + { + return MV_ERROR; + } + return MV_OK; +} + +static MV_STATUS mv_mem_cmp(MV_U32* pMem, MV_U32 pattern, MV_U32 count) +{ + int i; + for (i=0 ; i< count ; i+=1) + { + if (*(pMem + i) != pattern) + { + printf("Fail\n"); + printf("Test failed at 0x%x\n",(pMem + i)); + return MV_ERROR; + } + } + + return MV_OK; +} +#endif /* MV_INC_DRAM_MFG_TEST */ diff --git a/board/mv_feroceon/mv_kw/mv_main.c b/board/mv_feroceon/mv_kw/mv_main.c new file mode 100644 index 0000000..3bd0fe6 --- /dev/null +++ b/board/mv_feroceon/mv_kw/mv_main.c @@ -0,0 +1,1364 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include "mvTypes.h" +#include "mvBoardEnvLib.h" +#include "mvCpuIf.h" +#include "mvCtrlEnvLib.h" +#include "mv_mon_init.h" +#include "mvDebug.h" +#include "device/mvDevice.h" +#include "twsi/mvTwsi.h" +#include "eth/mvEth.h" +#include "pex/mvPex.h" +#include "gpp/mvGpp.h" +#include "sys/mvSysUsb.h" + +#ifdef MV_INCLUDE_RTC +#include "rtc/integ_rtc/mvRtc.h" +#elif CONFIG_RTC_DS1338_DS1339 +#include "rtc/ext_rtc/mvDS133x.h" +#endif + +#if defined(MV_INCLUDE_XOR) +#include "xor/mvXor.h" +#endif +#if defined(MV_INCLUDE_IDMA) +#include "sys/mvSysIdma.h" +#include "idma/mvIdma.h" +#endif +#if defined(MV_INCLUDE_USB) +#include "usb/mvUsb.h" +#endif + +#include "cpu/mvCpu.h" + +#ifdef CONFIG_PCI +# include +#endif +#include "pci/mvPciRegs.h" + +#include +#include + +#include "net.h" +#include + +/* #define MV_DEBUG */ +#ifdef MV_DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +/* CPU address decode table. */ +MV_CPU_DEC_WIN mvCpuAddrWinMap[] = MV_CPU_IF_ADDR_WIN_MAP_TBL; + +#if defined(RD_88F6281A) || defined(RD_88F6192A) || defined(RD_88F6190A) +static void mvHddPowerCtrl(void); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) +static void recoveryDetection(void); +void recoveryHandle(void); +static u32 rcvrflag = 0; +#endif +void mv_cpu_init(void); +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +int mv_set_power_scheme(void); +#endif + +#ifdef CFG_FLASH_CFI_DRIVER +MV_VOID mvUpdateNorFlashBaseAddrBank(MV_VOID); +int mv_board_num_flash_banks; +extern flash_info_t flash_info[]; /* info for FLASH chips */ +extern unsigned long flash_add_base_addr (uint flash_index, ulong flash_base_addr); +#endif /* CFG_FLASH_CFI_DRIVER */ + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +extern MV_VOID mvBoardEgigaPhySwitchInit(void); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +/* Define for SDK 2.0 */ +int __aeabi_unwind_cpp_pr0(int a,int b,int c) {return 0;} +int __aeabi_unwind_cpp_pr1(int a,int b,int c) {return 0;} +#endif + +MV_VOID mvMppModuleTypePrint(MV_VOID); + +/* Define for SDK 2.0 */ +int raise(void) {return 0;} + +void print_mvBanner(void) +{ +#ifdef CONFIG_SILENT_CONSOLE + DECLARE_GLOBAL_DATA_PTR; + gd->flags |= GD_FLG_SILENT; +#endif + printf("\n"); + printf(" __ __ _ _\n"); + printf(" | \\/ | __ _ _ ____ _____| | |\n"); + printf(" | |\\/| |/ _` | '__\\ \\ / / _ \\ | |\n"); + printf(" | | | | (_| | | \\ V / __/ | |\n"); + printf(" |_| |_|\\__,_|_| \\_/ \\___|_|_|\n"); + printf(" _ _ ____ _\n"); + printf("| | | | | __ ) ___ ___ | |_ \n"); + printf("| | | |___| _ \\ / _ \\ / _ \\| __| \n"); + printf("| |_| |___| |_) | (_) | (_) | |_ \n"); + printf(" \\___/ |____/ \\___/ \\___/ \\__| "); +#if !defined(MV_NAND_BOOT) +#if defined(MV_INCLUDE_MONT_EXT) + mvMPPConfigToSPI(); + if(!enaMonExt()) + printf(" ** LOADER **"); + else + printf(" ** MONITOR **"); + mvMPPConfigToDefault(); +#else + + printf(" ** Forcing LOADER mode only **"); +#endif /* MV_INCLUDE_MONT_EXT */ +#endif + return; +} + +void print_dev_id(void){ + static char boardName[30]; + + mvBoardNameGet(boardName); + +#if defined(MV_CPU_BE) + printf("\n ** MARVELL BOARD: %s BE ",boardName); +#else + printf("\n ** MARVELL BOARD: %s LE ",boardName); +#endif + + return; +} + + +void maskAllInt(void) +{ + /* mask all external interrupt sources */ + MV_REG_WRITE(CPU_MAIN_IRQ_MASK_REG, 0); + MV_REG_WRITE(CPU_MAIN_FIQ_MASK_REG, 0); + MV_REG_WRITE(CPU_ENPOINT_MASK_REG, 0); + MV_REG_WRITE(CPU_MAIN_IRQ_MASK_HIGH_REG, 0); + MV_REG_WRITE(CPU_MAIN_FIQ_MASK_HIGH_REG, 0); + MV_REG_WRITE(CPU_ENPOINT_MASK_HIGH_REG, 0); +} + +/* init for the Master*/ +void misc_init_r_dec_win(void) +{ +#if defined(MV_INCLUDE_USB) + { + char *env; + + env = getenv("usb0Mode"); + if((!env) || (strcmp(env,"device") == 0) || (strcmp(env,"Device") == 0) ) + { + printf("USB 0: device mode\n"); + mvUsbInit(0, MV_FALSE); + } + else + { + printf("USB 0: host mode\n"); + mvUsbInit(0, MV_TRUE); + } + } +#endif/* #if defined(MV_INCLUDE_USB) */ + +#if defined(MV_INCLUDE_XOR) + mvXorInit(); +#endif + +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + mv_set_power_scheme(); +#endif + + return; +} + + +/* + * Miscellaneous platform dependent initialisations + */ + +extern MV_STATUS mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data); +extern MV_STATUS mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data); + +/* golabal mac address for yukon EC */ +unsigned char yuk_enetaddr[6]; +extern int interrupt_init (void); +extern void i2c_init(int speed, int slaveaddr); + + +int board_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; +#if defined(MV_INCLUDE_TWSI) + MV_TWSI_ADDR slave; +#endif + unsigned int i; + + maskAllInt(); + + /* must initialize the int in order for udelay to work */ + interrupt_init(); + +#if defined(MV_INCLUDE_TWSI) + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(0, CFG_I2C_SPEED, CFG_TCLK, &slave, 0); +#endif + + /* Init the Board environment module (device bank params init) */ + mvBoardEnvInit(); + + /* Init the Controlloer environment module (MPP init) */ + mvCtrlEnvInit(); + + mvBoardDebugLed(3); + + /* Init the Controller CPU interface */ + mvCpuIfInit(mvCpuAddrWinMap); + + /* arch number of Integrator Board */ + gd->bd->bi_arch_number = 527; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + /* relocate the exception vectors */ + /* U-Boot is running from DRAM at this stage */ + for(i = 0; i < 0x100; i+=4) + { + *(unsigned int *)(0x0 + i) = *(unsigned int*)(TEXT_BASE + i); + } + + /* Update NOR flash base address bank for CFI driver */ +#ifdef CFG_FLASH_CFI_DRIVER + mvUpdateNorFlashBaseAddrBank(); +#endif /* CFG_FLASH_CFI_DRIVER */ + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) + /* Init the PHY or Switch of the board */ + mvBoardEgigaPhySwitchInit(); +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + + mvBoardDebugLed(4); + + return 0; +} + +void misc_init_r_env(void){ + char *env; + char tmp_buf[10]; + unsigned int malloc_len; + DECLARE_GLOBAL_DATA_PTR; + + unsigned int flashSize =0 , secSize =0, ubootSize =0; + char buff[256]; + +#if defined(MV_BOOTSIZE_4M) + flashSize = _4M; +#elif defined(MV_BOOTSIZE_8M) + flashSize = _8M; +#elif defined(MV_BOOTSIZE_16M) + flashSize = _16M; +#elif defined(MV_BOOTSIZE_32M) + flashSize = _32M; +#elif defined(MV_BOOTSIZE_64M) + flashSize = _64M; +#endif + +#if defined(MV_SEC_64K) + secSize = _64K; +#if defined(MV_TINY_IMAGE) + ubootSize = _256K; +#else + ubootSize = _512K; +#endif +#elif defined(MV_SEC_128K) + secSize = _128K; +#if defined(MV_TINY_IMAGE) + ubootSize = _128K * 3; +#else + ubootSize = _128K * 5; +#endif +#elif defined(MV_SEC_256K) + secSize = _256K; +#if defined(MV_TINY_IMAGE) + ubootSize = _256K * 3; +#else + ubootSize = _256K * 3; +#endif +#endif + + if ((0 == flashSize) || (0 == secSize) || (0 == ubootSize)) + { + env = getenv("console"); + if(!env) + setenv("console","console=ttyS0,115200"); + } + else + { + sprintf(buff,"console=ttyS0,115200 mtdparts=cfi_flash:0x%x(root),0x%x(uboot)ro", + flashSize - ubootSize, ubootSize); + env = getenv("console"); + if(!env) + setenv("console",buff); + } + + + /* Linux open port support */ + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + setenv("mainlineLinux","yes"); + else + setenv("mainlineLinux","no"); + + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + /* arch number for open port Linux */ + env = getenv("arcNumber"); + if(!env ) + { + /* arch number according to board ID */ + int board_id = mvBoardIdGet(); + switch(board_id){ + case(DB_88F6281A_BP_ID): + sprintf(tmp_buf,"%d", DB_88F6281_BP_MLL_ID); + board_id = DB_88F6281_BP_MLL_ID; + break; + case(RD_88F6192A_ID): + sprintf(tmp_buf,"%d", RD_88F6192_MLL_ID); + board_id = RD_88F6192_MLL_ID; + break; + case(RD_88F6281A_ID): + sprintf(tmp_buf,"%d", RD_88F6281_MLL_ID); + board_id = RD_88F6281_MLL_ID; + break; + default: + sprintf(tmp_buf,"%d", board_id); + board_id = board_id; + break; + } + gd->bd->bi_arch_number = board_id; + setenv("arcNumber", tmp_buf); + } + else + { + gd->bd->bi_arch_number = simple_strtoul(env, NULL, 10); + } + } + + /* update the CASset env parameter */ + env = getenv("CASset"); + if(!env ) + { +#ifdef MV_MIN_CAL + setenv("CASset","min"); +#else + setenv("CASset","max"); +#endif + } + /* Monitor extension */ +#ifdef MV_INCLUDE_MONT_EXT + env = getenv("enaMonExt"); + if(/* !env || */ ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + setenv("enaMonExt","yes"); + else +#endif + setenv("enaMonExt","no"); + +#if defined (MV_INC_BOARD_NOR_FLASH) + env = getenv("enaFlashBuf"); + if( ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("enaFlashBuf","no"); + else + setenv("enaFlashBuf","yes"); +#endif + + /* CPU streaming */ + env = getenv("enaCpuStream"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("enaCpuStream","no"); + else + setenv("enaCpuStream","yes"); + + /* Write allocation */ + env = getenv("enaWrAllo"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaWrAllo","no"); + else + setenv("enaWrAllo","yes"); + + /* Pex mode */ + env = getenv("pexMode"); + if( env && ( ((strcmp(env,"EP") == 0) || (strcmp(env,"ep") == 0) ))) + setenv("pexMode","EP"); + else + setenv("pexMode","RC"); + + env = getenv("disL2Cache"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("disL2Cache","no"); + else + setenv("disL2Cache","yes"); + + env = getenv("setL2CacheWT"); + if(!env || ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + setenv("setL2CacheWT","yes"); + else + setenv("setL2CacheWT","no"); + + env = getenv("disL2Prefetch"); + if(!env || ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + { + setenv("disL2Prefetch","yes"); + + /* ICache Prefetch */ + env = getenv("enaICPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaICPref","no"); + else + setenv("enaICPref","yes"); + + /* DCache Prefetch */ + env = getenv("enaDCPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaDCPref","no"); + else + setenv("enaDCPref","yes"); + } + else + { + setenv("disL2Prefetch","no"); + setenv("enaICPref","no"); + setenv("enaDCPref","no"); + } + + + env = getenv("sata_dma_mode"); + if( env && ((strcmp(env,"No") == 0) || (strcmp(env,"no") == 0) ) ) + setenv("sata_dma_mode","no"); + else + setenv("sata_dma_mode","yes"); + + + /* Malloc length */ + env = getenv("MALLOC_len"); + malloc_len = simple_strtoul(env, NULL, 10) << 20; + if(malloc_len == 0){ + sprintf(tmp_buf,"%d",CFG_MALLOC_LEN>>20); + setenv("MALLOC_len",tmp_buf); + } + + /* primary network interface */ + env = getenv("ethprime"); + if(!env) + { + if(mvBoardIdGet() == RD_88F6281A_ID) + setenv("ethprime","egiga1"); + else + setenv("ethprime",ENV_ETH_PRIME); + } + + /* netbsd boot arguments */ + env = getenv("netbsd_en"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("netbsd_en","no"); + else + { + setenv("netbsd_en","yes"); + env = getenv("netbsd_gw"); + if(!env) + setenv("netbsd_gw","192.168.0.254"); + + env = getenv("netbsd_mask"); + if(!env) + setenv("netbsd_mask","255.255.255.0"); + + env = getenv("netbsd_fs"); + if(!env) + setenv("netbsd_fs","nfs"); + + env = getenv("netbsd_server"); + if(!env) + setenv("netbsd_server","192.168.0.1"); + + env = getenv("netbsd_ip"); + if(!env) + { + env = getenv("ipaddr"); + setenv("netbsd_ip",env); + } + + env = getenv("netbsd_rootdev"); + if(!env) + setenv("netbsd_rootdev","mgi0"); + + env = getenv("netbsd_add"); + if(!env) + setenv("netbsd_add","0x800000"); + + env = getenv("netbsd_get"); + if(!env) + setenv("netbsd_get","tftpboot $(netbsd_add) $(image_name)"); + +#if defined(MV_INC_BOARD_QD_SWITCH) + env = getenv("netbsd_netconfig"); + if(!env) + setenv("netbsd_netconfig","mv_net_config=<((mgi0,00:00:11:22:33:44,0)(mgi1,00:00:11:22:33:55,1:2:3:4)),mtu=1500>"); +#endif + env = getenv("netbsd_set_args"); + if(!env) + setenv("netbsd_set_args","setenv bootargs nfsroot=$(netbsd_server):$(rootpath) fs=$(netbsd_fs) \ +ip=$(netbsd_ip) serverip=$(netbsd_server) mask=$(netbsd_mask) gw=$(netbsd_gw) rootdev=$(netbsd_rootdev) \ +ethaddr=$(ethaddr) $(netbsd_netconfig)"); + + env = getenv("netbsd_boot"); + if(!env) + setenv("netbsd_boot","bootm $(netbsd_add) $(bootargs)"); + + env = getenv("netbsd_bootcmd"); + if(!env) + setenv("netbsd_bootcmd","run netbsd_get ; run netbsd_set_args ; run netbsd_boot"); + } + + /* vxWorks boot arguments */ + env = getenv("vxworks_en"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("vxworks_en","no"); + else + { + char* buff = 0x1100; + setenv("vxworks_en","yes"); + + sprintf(buff,"mgi(0,0) host:vxWorks.st"); + env = getenv("serverip"); + strcat(buff, " h="); + strcat(buff,env); + env = getenv("ipaddr"); + strcat(buff, " e="); + strcat(buff,env); + strcat(buff, ":ffff0000 u=anonymous pw=target "); + + setenv("vxWorks_bootargs",buff); + } + + /* linux boot arguments */ + env = getenv("bootargs_root"); + if(!env) + setenv("bootargs_root","root=/dev/nfs rw"); + + /* For open Linux we set boot args differently */ + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + env = getenv("bootargs_end"); + if(!env) + setenv("bootargs_end",":::orion:eth0:none"); + } + else + { + env = getenv("bootargs_end"); + if(!env) +#if defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootargs_end",CFG_BOOTARGS_END_SWITCH); +#else + setenv("bootargs_end",CFG_BOOTARGS_END); +#endif + } + + env = getenv("image_name"); + if(!env) + setenv("image_name","uImage"); + + +#if (CONFIG_BOOTDELAY >= 0) + env = getenv("bootcmd"); + if(!env) +#if defined(MV_INCLUDE_TDM) && defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootcmd","tftpboot 0x2000000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig) $(mvPhoneConfig); bootm 0x2000000; "); +#elif defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootcmd","tftpboot 0x2000000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig); bootm 0x2000000; "); +#elif defined(MV_INCLUDE_TDM) + setenv("bootcmd","tftpboot 0x2000000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig) $(mvPhoneConfig); bootm 0x2000000; "); +#else + + setenv("bootcmd","tftpboot 0x2000000 $(image_name);\ +setenv bootargs $(console) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x2000000; "); +#endif +#endif /* (CONFIG_BOOTDELAY >= 0) */ + + env = getenv("standalone"); + if(!env) +#if defined(MV_INCLUDE_TDM) && defined(MV_INC_BOARD_QD_SWITCH) + setenv("standalone","fsload 0x2000000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig) $(mvPhoneConfig); bootm 0x2000000;"); +#elif defined(MV_INC_BOARD_QD_SWITCH) + setenv("standalone","fsload 0x2000000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig); bootm 0x2000000;"); +#elif defined(MV_INCLUDE_TDM) + setenv("standalone","fsload 0x2000000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvPhoneConfig); bootm 0x2000000;"); +#else + setenv("standalone","fsload 0x2000000 $(image_name);setenv bootargs $(console) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x2000000;"); +#endif + + /* Set boodelay to 3 sec, if Monitor extension are disabled */ + if(!enaMonExt()){ + setenv("bootdelay","3"); + setenv("disaMvPnp","no"); + } + + /* Disable PNP config of Marvel memory controller devices. */ + env = getenv("disaMvPnp"); + if(!env) + setenv("disaMvPnp","no"); + +#if (defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH)) + /* Generate random ip and mac address */ + /* Read DRAM FTDLL register to create random data for enc */ + unsigned int xi, xj, xk, xl, i; + char ethaddr_0[30]; + char ethaddr_1[30]; + + MV_U32 random[16]; + unsigned char digest[16]; + + MV_REG_BIT_SET(0x1478, BIT7); + for(i=0; i < 16;i++) + random[i] = MV_REG_READ(0x1470); + + /* Run MD5 over the ftdll buffer */ + mvMD5((unsigned char*)random, 64, digest); + + xi = (digest[0]%254); + /* No valid ip with one of the fileds has the value 0 */ + if (xi == 0) + xi+=2; + + xj = (digest[1]%254); + /* No valid ip with one of the fileds has the value 0 */ + if (xj == 0) + xj+=2; + + /* Check if the ip address is the same as the server ip */ + if ((xj == 1) && (xi == 11)) + xi+=2; + + xk = digest[2]; + xl = digest[3]; + + sprintf(ethaddr_0,"00:50:43:%02x:%02x:%02x",xk,xi,xj); + sprintf(ethaddr_1,"00:50:43:%02x:%02x:%02x",xl,xi,xj); + + /* MAC addresses */ + env = getenv("ethaddr"); + if(!env) + setenv("ethaddr",ethaddr_0); + +#if !defined(MV_INC_BOARD_QD_SWITCH) +/* ETH1ADDR not define in GWAP boards */ + if ((mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_1) == MV_BOARD_RGMII) || + (mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_2) == MV_BOARD_RGMII)) + { + env = getenv("eth1addr"); + if(!env) + setenv("eth1addr",ethaddr_1); + } +#endif +#if defined(MV_INCLUDE_TDM) + /* Set mvPhoneConfig env parameter */ + env = getenv("mvPhoneConfig"); + if(!env ) + setenv("mvPhoneConfig","mv_phone_config=dev0:fxs,dev1:fxo"); +#endif + /* Set mvNetConfig env parameter */ + env = getenv("mvNetConfig"); + if(!env ) + setenv("mvNetConfig","mv_net_config=(00:11:88:0f:62:81,0:1:2:3),mtu=1500"); +#endif /* (MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) */ + +#if defined(MV_INCLUDE_USB) + /* USB Host */ + env = getenv("usb0Mode"); + if(!env) + setenv("usb0Mode",ENV_USB0_MODE); +#endif /* (MV_INCLUDE_USB) */ + +#if defined(YUK_ETHADDR) + env = getenv("yuk_ethaddr"); + if(!env) + setenv("yuk_ethaddr",YUK_ETHADDR); + + { + int i; + char *tmp = getenv ("yuk_ethaddr"); + char *end; + + for (i=0; i<6; i++) { + yuk_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end+1 : end; + } + } +#endif /* defined(YUK_ETHADDR) */ + +#if defined(RD_88F6281A) || defined(RD_88F6192A) || defined(RD_88F6190A) + mvHddPowerCtrl(); +#endif +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + env = getenv("netretry"); + if (!env) + setenv("netretry","no"); + + env = getenv("rcvrip"); + if (!env) + setenv("rcvrip",RCVR_IP_ADDR); + + env = getenv("loadaddr"); + if (!env) + setenv("loadaddr",RCVR_LOAD_ADDR); + + env = getenv("autoload"); + if (!env) + setenv("autoload","no"); + + /* Check the recovery trigger */ + recoveryDetection(); +#endif + return; +} + +#ifdef BOARD_LATE_INIT +int board_late_init (void) +{ + /* Check if to use the LED's for debug or to use single led for init and Linux heartbeat */ + mvBoardDebugLed(0); + return 0; +} +#endif + +int misc_init_r (void) +{ + char name[128]; + + mvBoardDebugLed(5); + + mvCpuNameGet(name); + printf("\nCPU : %s\n", name); + + /* init special env variables */ + misc_init_r_env(); + + mv_cpu_init(); + +#if defined(MV_INCLUDE_MONT_EXT) + if(enaMonExt()){ + printf("\n Marvell monitor extension:\n"); + mon_extension_after_relloc(); + } + printf("\n"); +#endif /* MV_INCLUDE_MONT_EXT */ + + /* print detected modules */ + mvMppModuleTypePrint(); + + printf("\n"); + /* init the units decode windows */ + misc_init_r_dec_win(); + +#ifdef CONFIG_PCI +#if !defined(MV_MEM_OVER_PCI_WA) && !defined(MV_MEM_OVER_PEX_WA) + pci_init(); +#endif +#endif + + mvBoardDebugLed(6); + + mvBoardDebugLed(7); + + return 0; +} + +MV_U32 mvTclkGet(void) +{ + DECLARE_GLOBAL_DATA_PTR; + /* get it only on first time */ + if(gd->tclk == 0) + gd->tclk = mvBoardTclkGet(); + + return gd->tclk; +} + +MV_U32 mvSysClkGet(void) +{ + DECLARE_GLOBAL_DATA_PTR; + /* get it only on first time */ + if(gd->bus_clk == 0) + gd->bus_clk = mvBoardSysClkGet(); + + return gd->bus_clk; +} + +#ifndef MV_TINY_IMAGE +/* exported for EEMBC */ +MV_U32 mvGetRtcSec(void) +{ + MV_RTC_TIME time; +#ifdef MV_INCLUDE_RTC + mvRtcTimeGet(&time); +#elif CONFIG_RTC_DS1338_DS1339 + mvRtcDS133xTimeGet(&time); +#endif + return (time.minutes * 60) + time.seconds; +} +#endif + +void reset_cpu(void) +{ + mvBoardReset(); +} + +void mv_cpu_init(void) +{ + char *env; + volatile unsigned int temp; + + /*CPU streaming & write allocate */ + env = getenv("enaWrAllo"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp |= BIT28; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + + } + else + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp &= ~BIT28; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + } + + env = getenv("enaCpuStream"); + if(!env || (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp &= ~BIT29; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + } + else + { + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + temp |= BIT29; + __asm__ __volatile__("mcr p15, 1, %0, c15, c1, 0" :: "r" (temp)); + } + + /* Verifay write allocate and streaming */ + printf("\n"); + __asm__ __volatile__("mrc p15, 1, %0, c15, c1, 0" : "=r" (temp)); + if (temp & BIT29) + printf("Streaming enabled \n"); + else + printf("Streaming disabled \n"); + if (temp & BIT28) + printf("Write allocate enabled\n"); + else + printf("Write allocate disabled\n"); + + /* DCache Pref */ + env = getenv("enaDCPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + + /* ICache Pref */ + env = getenv("enaICPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + } + + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + } + + /* Set L2C WT mode - Set bit 4 */ + temp = MV_REG_READ(CPU_L2_CONFIG_REG); + env = getenv("setL2CacheWT"); + if(!env || ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + { + temp |= BIT4; + } + else + temp &= ~BIT4; + MV_REG_WRITE(CPU_L2_CONFIG_REG, temp); + + + /* L2Cache settings */ + asm ("mrc p15, 1, %0, c15, c1, 0":"=r" (temp)); + + /* Disable L2C pre fetch - Set bit 24 */ + env = getenv("disL2Prefetch"); + if(env && ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + temp &= ~BIT24; + else + temp |= BIT24; + + /* enable L2C - Set bit 22 */ + env = getenv("disL2Cache"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + temp |= BIT22; + else + temp &= ~BIT22; + + asm ("mcr p15, 1, %0, c15, c1, 0": :"r" (temp)); + + + /* Enable i cache */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (temp)); + temp |= BIT12; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (temp)); + + /* Change reset vector to address 0x0 */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (temp)); + temp &= ~BIT13; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (temp)); +} +/******************************************************************************* +* mvBoardMppModuleTypePrint - print module detect +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvMppModuleTypePrint(MV_VOID) +{ + + MV_BOARD_MPP_GROUP_CLASS devClass; + MV_BOARD_MPP_TYPE_CLASS mppGroupType; + MV_U32 devId; + MV_U32 maxMppGrp = 1; + + devId = mvCtrlModelGet(); + + switch(devId){ + case MV_6281_DEV_ID: + maxMppGrp = MV_6281_MPP_MAX_MODULE; + break; + case MV_6192_DEV_ID: + maxMppGrp = MV_6192_MPP_MAX_MODULE; + break; + case MV_6190_DEV_ID: + maxMppGrp = MV_6190_MPP_MAX_MODULE; + break; + case MV_6180_DEV_ID: + maxMppGrp = MV_6180_MPP_MAX_MODULE; + break; + } + + for (devClass = 0; devClass < maxMppGrp; devClass++) + { + mppGroupType = mvBoardMppGroupTypeGet(devClass); + + switch(mppGroupType) + { + case MV_BOARD_TDM: + if(devId != MV_6190_DEV_ID) + printf("Module %d is TDM\n", devClass); + break; + case MV_BOARD_AUDIO: + if(devId != MV_6190_DEV_ID) + printf("Module %d is AUDIO\n", devClass); + break; + case MV_BOARD_RGMII: + if(devId != MV_6190_DEV_ID) + printf("Module %d is RGMII\n", devClass); + break; + case MV_BOARD_GMII: + if(devId != MV_6190_DEV_ID) + printf("Module %d is GMII\n", devClass); + break; + case MV_BOARD_TS: + if(devId != MV_6190_DEV_ID) + printf("Module %d is TS\n", devClass); + break; + default: + break; + } + } +} + +/* Set unit in power off mode acording to the detection of MPP */ +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +int mv_set_power_scheme(void) +{ + int mppGroupType1 = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_1); + int mppGroupType2 = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_2); + MV_U32 devId = mvCtrlModelGet(); + MV_U32 boardId = mvBoardIdGet(); + + if (devId == MV_6180_DEV_ID) + { + /* Sata power down */ + mvCtrlPwrMemSet(SATA_UNIT_ID, 1, MV_FALSE); + mvCtrlPwrMemSet(SATA_UNIT_ID, 0, MV_FALSE); + mvCtrlPwrClckSet(SATA_UNIT_ID, 1, MV_FALSE); + mvCtrlPwrClckSet(SATA_UNIT_ID, 0, MV_FALSE); + /* Sdio power down */ + mvCtrlPwrMemSet(SDIO_UNIT_ID, 0, MV_FALSE); + mvCtrlPwrClckSet(SDIO_UNIT_ID, 0, MV_FALSE); + } + + if (boardId == RD_88F6281A_ID) + { + DB(printf("Warning: TS is Powered Off\n")); + mvCtrlPwrClckSet(TS_UNIT_ID, 0, MV_FALSE); + return MV_OK; + } + + /* Close egiga 1 */ + if ((mppGroupType1 != MV_BOARD_GMII) && (mppGroupType1 != MV_BOARD_RGMII) && (mppGroupType2 != MV_BOARD_RGMII)) + { + DB(printf("Warning: Giga1 is Powered Off\n")); +//Patch by QNAP:Fix GE1 +#if defined(TS119) || defined(TS219) || defined(TS118) || defined(TS218) + mvCtrlPwrMemSet(ETH_GIG_UNIT_ID, 1, MV_FALSE); + mvCtrlPwrClckSet(ETH_GIG_UNIT_ID, 1, MV_FALSE); +#endif + } + + /* Close TDM */ + if ((mppGroupType1 != MV_BOARD_TDM) && (mppGroupType2 != MV_BOARD_TDM)) + { + DB(printf("Warning: TDM is Powered Off\n")); + mvCtrlPwrClckSet(TDM_UNIT_ID, 0, MV_FALSE); + } + + /* Close AUDIO */ + if ((mppGroupType1 != MV_BOARD_AUDIO) && (mppGroupType2 != MV_BOARD_AUDIO)) + { + DB(printf("Warning: AUDIO is Powered Off\n")); + mvCtrlPwrMemSet(AUDIO_UNIT_ID, 0, MV_FALSE); + mvCtrlPwrClckSet(AUDIO_UNIT_ID, 0, MV_FALSE); + } + + /* Close TS */ + if ((mppGroupType1 != MV_BOARD_TS) && (mppGroupType2 != MV_BOARD_TS)) + { + DB(printf("Warning: TS is Powered Off\n")); + mvCtrlPwrClckSet(TS_UNIT_ID, 0, MV_FALSE); + } + + return MV_OK; +} + +#endif /* defined(MV_INCLUDE_CLK_PWR_CNTRL) */ + +/******************************************************************************* +* mvUpdateNorFlashBaseAddrBank - +* +* DESCRIPTION: +* This function update the CFI driver base address bank with on board NOR +* devices base address. +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* None +* +*******************************************************************************/ +#ifdef CFG_FLASH_CFI_DRIVER +MV_VOID mvUpdateNorFlashBaseAddrBank(MV_VOID) +{ + + MV_U32 devBaseAddr; + MV_U32 devNum = 0; + int i; + + /* Update NOR flash base address bank for CFI flash init driver */ + for (i = 0 ; i < CFG_MAX_FLASH_BANKS_DETECT; i++) + { + devBaseAddr = mvBoardGetDeviceBaseAddr(i,BOARD_DEV_NOR_FLASH); + if (devBaseAddr != 0xFFFFFFFF) + { + flash_add_base_addr (devNum, devBaseAddr); + devNum++; + } + } + mv_board_num_flash_banks = devNum; + + /* Update SPI flash count for CFI flash init driver */ + /* Assumption only 1 SPI flash on board */ + for (i = 0 ; i < CFG_MAX_FLASH_BANKS_DETECT; i++) + { + devBaseAddr = mvBoardGetDeviceBaseAddr(i,BOARD_DEV_SPI_FLASH); + if (devBaseAddr != 0xFFFFFFFF) + mv_board_num_flash_banks += 1; + } +} +#endif /* CFG_FLASH_CFI_DRIVER */ + + +/******************************************************************************* +* mvHddPowerCtrl - +* +* DESCRIPTION: +* This function set HDD power on/off acording to env or wait for button push +* INPUT: +* None +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +#if defined(RD_88F6281A) || defined(RD_88F6192A) || defined(RD_88F6190A) +static void mvHddPowerCtrl(void) +{ + + MV_32 hddPowerBit; + MV_32 fanPowerBit; + MV_32 hddHigh = 0; + MV_32 fanHigh = 0; + char* env; + + if(RD_88F6281A_ID == mvBoardIdGet()) + { + hddPowerBit = mvBoarGpioPinNumGet(BOARD_GPP_HDD_POWER, 0); + fanPowerBit = mvBoarGpioPinNumGet(BOARD_GPP_FAN_POWER, 0); + if (hddPowerBit > 31) + { + hddPowerBit = hddPowerBit % 32; + hddHigh = 1; + } + + if (fanPowerBit > 31) + { + fanPowerBit = fanPowerBit % 32; + fanHigh = 1; + } + } + + if ((RD_88F6281A_ID == mvBoardIdGet()) || (RD_88F6192A_ID == mvBoardIdGet()) || + (RD_88F6190A_ID == mvBoardIdGet())) + { + env = getenv("hddPowerCtrl"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("hddPowerCtrl","no"); + else + setenv("hddPowerCtrl","yes"); + + if(RD_88F6281A_ID == mvBoardIdGet()) + { + mvBoardFanPowerControl(MV_TRUE); + mvBoardHDDPowerControl(MV_TRUE); + } + else + { + /* FAN power on */ + MV_REG_BIT_SET(GPP_DATA_OUT_REG(fanHigh),(1< 31) + { + stateButtonBit = stateButtonBit % 32; + buttonHigh = 1; + } + + /* Set state input indication pin as input */ + MV_REG_BIT_SET(GPP_DATA_OUT_EN_REG(buttonHigh),(1<> 4)) +#define NAND_ADDR_PORT (0x2 << (NFLASH_DEV_WIDTH >> 4)) + +/* NAND Flash Chip Capability */ +#ifdef MV_LARGE_PAGE +#define NUM_BLOCKS 2048 +#define PAGES_PER_BLOCK 64 +#define PAGE_SIZE 2048 /* Bytes */ +#define SPARE_SIZE 64 +#define CFG_NAND_PAGE_SIZE (2048) /* NAND chip page size */ +#define CFG_NAND_BLOCK_SIZE (128 << 10) /* NAND chip block size */ +#define CFG_NAND_PAGE_COUNT (64) /* NAND chip page count */ +#define CFG_NAND_BAD_BLOCK_POS (0) /* Location of bad block marker */ + +#define CFG_NAND_U_BOOT_OFFS CFG_MONITOR_BASE /* Offset to U-Boot image */ +#define CFG_NAND_U_BOOT_SIZE CFG_MONITOR_LEN /* Size of RAM U-Boot image */ +#define CFG_NAND_U_BOOT_DST CFG_MONITOR_IMAGE_DST /* Load NUB to this addr */ +#define CFG_NAND_U_BOOT_START CFG_NAND_U_BOOT_DST /* Start NUB from this addr */ + +#else /* ! LARGE PAGE NAND */ +/* NAND Flash Chip Capability */ +#define NUM_BLOCKS 2048 +#define PAGES_PER_BLOCK 32 +#define PAGE_SIZE 512 /* Bytes */ +#define SPARE_SIZE 16 +#define CFG_NAND_PAGE_SIZE (512) /* NAND chip page size */ +#define CFG_NAND_BLOCK_SIZE (16 << 10) /* NAND chip block size */ +#define CFG_NAND_PAGE_COUNT (32) /* NAND chip page count */ +#define CFG_NAND_BAD_BLOCK_POS (5) /* Location of bad block marker */ + +#define CFG_NAND_U_BOOT_OFFS CFG_MONITOR_BASE /* Offset to U-Boot image */ +#define CFG_NAND_U_BOOT_SIZE CFG_MONITOR_LEN /* Size of RAM U-Boot image */ +#define CFG_NAND_U_BOOT_DST CFG_MONITOR_IMAGE_DST /* Load NUB to this addr */ +#define CFG_NAND_U_BOOT_START CFG_NAND_U_BOOT_DST /* Start NUB from this addr */ + +#endif + +/* NAND Flash Command. This appears to be generic across all NAND flash chips */ +#define CMD_READ 0x00 /* Read */ +#define CMD_READ1 0x01 /* Read1 */ +#define CMD_READ2 0x50 /* Read2 */ +#define CMD_START_READ 0x30 /* Read command after write addr */ +#define CMD_READID 0x90 /* ReadID */ +#define CMD_READID2 0x91 /* Read extended ID */ +#define CMD_WRITE 0x80 /* Write phase 1 */ +#define CMD_WRITE2 0x10 /* Write phase 2 */ +#define CMD_ERASE 0x60 /* Erase phase 1 */ +#define CMD_ERASE2 0xd0 /* Erase phase 2 */ +#define CMD_STATUS 0x70 /* Status read */ +#define CMD_RESET 0xff /* Reset */ + +/* Status bit pattern */ +#define STATUS_READY 0x40 /* Ready */ +#define STATUS_ERROR 0x01 /* Error */ + + +#define NFLASH_DEV_WIDTH 8 +#ifdef MV_LARGE_PAGE +#define BOOTER_PAGE_NUM 2 +#define BOOTER_BASE 0x00020000 + PAGE_SIZE +#else +#define BOOTER_PAGE_NUM 5 +#define BOOTER_BASE 0x00020000 + (3 * PAGE_SIZE) +#endif /* MV_LARGE_PAGE */ +#define BOOTER_END (BOOTER_BASE + (BOOTER_PAGE_NUM * PAGE_SIZE)) + +#undef INTER_REGS_BASE +#define INTER_REGS_BASE 0xd0000000 + + +#if defined(MV_BOOTROM) +#if defined(MV_88F6082) +#define NAND_FLASH_BASE 0xD8000000 +#endif +#if defined(MV_88F5182) +#define NAND_FLASH_BASE 0xf0000000 +#endif +#else +#define NAND_FLASH_BASE 0xffff0000 +#endif /* defined(MV_BOOTROM) */ + +#if 0 +#define NBOOT_UART_CHAN 0 +#define NBOOT_BAUDRATE 115200 +#define NBOOT_TIMER_NUM 0 + + +/* CPU config register (0x20100) bit[15:8] value for CPU to DDR clock ratio */ +#define CPU_2_MBUSL_DDR_CLK 0x0000 /* clock ratio 1x2 */ +/* #define CPU_2_MBUSL_DDR_CLK 0x2100 *//* clock ratio 1x3 */ +/* #define CPU_2_MBUSL_DDR_CLK 0x2200 *//* clock ratio 1x4 */ + +/* Load General Purpose Register (GPR) with 32-bit constant value */ +#define GPR_LOAD(reg, val) \ + mov reg, $(val & 0xFF) ;\ + orr reg, reg, $(val & 0xFF00) ;\ + orr reg, reg, $(val & 0xFF0000) ;\ + orr reg, reg, $(val & 0xFF000000) + +/* Register Read/Write */ +#define MV_REG_READ_ASM(toReg, baseReg, regOffs) \ + ldr toReg, [baseReg, $(regOffs & 0xFFF)] + +#define MV_REG_WRITE_ASM(fromReg, baseReg, regOffs) \ + str fromReg, [baseReg, $(regOffs & 0xFFF)] + + +/* 32bit byte swap. For example 0x11223344 -> 0x44332211 */ +#define MV_BYTE_SWAP_32BIT(X) ((((X)&0xff)<<24) | \ + (((X)&0xff00)<<8) | \ + (((X)&0xff0000)>>8) | \ + (((X)&0xff000000)>>24)) +/* Endianess macros. */ +#if defined(MV_CPU_LE) + #define MV_32BIT_LE(X) (X) + #define MV_32BIT_BE(X) MV_BYTE_SWAP_32BIT(X) +#elif defined(MV_CPU_BE) + #define MV_32BIT_LE(X) MV_BYTE_SWAP_32BIT(X) + #define MV_32BIT_BE(X) (X) +#else + #error "CPU endianess isn't defined!\n" +#endif +#endif + +#endif /* __INCnBootstraph */ diff --git a/board/mv_feroceon/mv_kw/platform.S b/board/mv_feroceon/mv_kw/platform.S new file mode 100644 index 0000000..94dc801 --- /dev/null +++ b/board/mv_feroceon/mv_kw/platform.S @@ -0,0 +1,106 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#define MV_ASMLANGUAGE +#include "mvOsAsm.h" +#include +#include +#include "mvBoardEnvSpec.h" +#include "mvCtrlEnvSpec.h" +#include "mvCpuIfRegs.h" +#include "ddr2/mvDramIfRegs.h" +#include "mvCtrlEnvAsm.h" +#if defined(MV_INC_BOARD_SPI_FLASH) +#include "spi/mvSpiSpec.h" +#endif + + +/* + get_board_id - get board id from twsi eeprom + input : r5 - board id data start offset in the eeprom + +*/ +.globl lowlevel_init + +/************************************************/ +/* lowlevel_init * +/************************************************/ + +lowlevel_init: + + /* change reg base to 0xf1000000 */ + ldr r4, =CFG_MV_REGS + MV_DV_REG_WRITE_ASM(r4, r1, 0x20080) + + /* save Link Registers */ + mov r2, lr + + /* Change L2 cache to exist */ + MV_REG_READ_ASM(r4, r1, 0x20128) + orr r4, r4, #0x18 + MV_REG_WRITE_ASM(r4, r1, 0x20128) + /* Read operation to make sure the L2 bit is set */ + MV_REG_READ_ASM(r4, r1, 0x20128) + + /* invalidate L2 cache */ + mov r0, #0 + mcr p15, 1, r0, c15, c11, 0 + + ldr r4, =0x1b1b1b9b + MV_REG_WRITE_ASM(r4, r1, 0x100e0) + ldr r4, =0xbbbbbbbb + MV_REG_WRITE_ASM(r4, r1, 0x20134) + ldr r4, =0x00bbbbbb + MV_REG_WRITE_ASM(r4, r1, 0x20138) + + bl _i2cInit + + /* Initialize BUS-L to DDR configuration parameters */ + /* Must be done prior to DDR operation */ +#if !defined(MV_BOOTROM) + bl _mvCpuIfPreInit +#endif + +#if defined(MV_INC_BOARD_SPI_FLASH) + /* configure the Prescale of SPI clk Tclk = 166MHz */ + MV_REG_READ_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) + and r6, r6, #~MV_SPI_CLK_PRESCALE_MASK + orr r6, r6, #0x14 + MV_REG_WRITE_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) +#endif + +#if !defined(MV_INC_BOARD_DDIM) +#if !defined(MV_BOOTROM) + + /* Call DRAM static initialization */ + bl _mvDramIfStaticInit +#else + b done +#endif +#else /* #if !defined(MV_INC_BOARD_DDIM) */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + b done +#endif /* #if !defined(MV_INC_BOARD_DDIM) */ +done: + mov lr, r2 + mov pc, lr diff --git a/board/mv_feroceon/mv_orion/mv_cmd.c b/board/mv_feroceon/mv_orion/mv_cmd.c new file mode 100644 index 0000000..b446c29 --- /dev/null +++ b/board/mv_feroceon/mv_orion/mv_cmd.c @@ -0,0 +1,1162 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include +#include + +#include "mvTypes.h" +#include "mvCtrlEnvLib.h" + +#if defined(MV_INC_BOARD_NOR_FLASH) +#include "norflash/mvFlash.h" +#endif + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +#include "eth-phy/mvEthPhy.h" +#endif + +#if defined(MV_INCLUDE_PEX) +#include "pex/mvPex.h" +#endif + +#if defined(MV_INCLUDE_IDMA) +#include "idma/mvIdma.h" +#include "sys/mvSysIdma.h" +#endif + +#if defined(CFG_NAND_BOOT) || defined(CFG_CMD_NAND) +#include + +/* references to names in cmd_nand.c */ +#define NANDRW_READ 0x01 +#define NANDRW_WRITE 0x00 +#define NANDRW_JFFS2 0x02 +//extern struct nand_chip nand_dev_desc[]; +extern nand_info_t nand_info[]; /* info for NAND chips */ +/* int nand_rw (struct nand_chip* nand, int cmd, + size_t start, size_t len, + size_t * retlen, u_char * buf); + int nand_erase(struct nand_chip* nand, size_t ofs, + size_t len, int clean); +*/ +extern int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); +extern int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts); + + +#endif /* CFG_NAND_BOOT */ + +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) +#if !defined(CFG_NAND_BOOT) +static unsigned int flash_in_which_sec(flash_info_t *fl,unsigned int offset) +{ + unsigned int sec_num; + if(NULL == fl) + return 0xFFFFFFFF; + + for( sec_num = 0; sec_num < fl->sector_count ; sec_num++){ + /* If last sector*/ + if (sec_num == fl->sector_count -1) + { + if((offset >= fl->start[sec_num]) && + (offset <= (fl->size + fl->start[0] - 1)) ) + { + return sec_num; + } + + } + else + { + if((offset >= fl->start[sec_num]) && + (offset < fl->start[sec_num + 1]) ) + { + return sec_num; + } + + } + } + /* return illegal sector Number */ + return 0xFFFFFFFF; + +} + +#endif /* !defined(CFG_NAND_BOOT) */ + + +/******************************************************************************* +burn a u-boot.bin on the Boot Flash +********************************************************************************/ +extern flash_info_t flash_info[]; /* info for FLASH chips */ +#include +#if (CONFIG_COMMANDS & CFG_CMD_NET) +#if defined(CFG_NAND_BOOT) +/* Boot from NAND flash */ +/* Write u-boot image into the nand flash */ +int nand_burn_uboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 ret = 0; + extern char console_buffer[]; + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + nand_write_options_t wr_opts; + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "u-boot.bin", sizeof(BootFile)); + printf("using default file \"u-boot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + printf("\n**Warning**\n"); + printf("If U-Boot Endiannes is going to change (LE->BE or BE->LE), Then Env parameters should be overriden..\n"); + printf("Override Env parameters? (y/n)"); + readline(" "); + if( strcmp(console_buffer,"Y") == 0 || + strcmp(console_buffer,"yes") == 0 || + strcmp(console_buffer,"y") == 0 ) { + + printf("Erase Env parameters sector %d... ",CFG_ENV_OFFSET); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_ENV_OFFSET; + er_opts.length = CFG_ENV_SECT_SIZE; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0); + printf("\n"); + } + + printf("Erase %d - %d ... ",CFG_MONITOR_BASE + CFG_ENV_SECT_SIZE, CFG_MONITOR_LEN - CFG_ENV_SECT_SIZE); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_MONITOR_BASE + CFG_ENV_SECT_SIZE; + er_opts.length = CFG_MONITOR_LEN - CFG_ENV_SECT_SIZE; + er_opts.quiet = 1; + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_MONITOR_BASE, CFG_MONITOR_LEN, 0); + + printf("\nCopy to Nand Flash... "); + memset(&wr_opts, 0, sizeof(wr_opts)); + wr_opts.buffer = (u_char*) load_addr + CFG_ENV_SECT_SIZE; + wr_opts.length = CFG_MONITOR_LEN - CFG_ENV_SECT_SIZE; + wr_opts.offset = CFG_MONITOR_BASE + CFG_ENV_SECT_SIZE; + /* opts.forcejffs2 = 1; */ + wr_opts.pad = 1; + wr_opts.blockalign = 1; + wr_opts.quiet = 1; + ret = nand_write_opts(nand, &wr_opts); + /* ret = nand_rw(nand_dev_desc + 0, + NANDRW_WRITE | NANDRW_JFFS2, CFG_MONITOR_BASE, CFG_MONITOR_LEN, + &total, (u_char*)0x100000 + CFG_MONITOR_IMAGE_OFFSET); + */ + if (ret) + printf("Error - NAND burn faild!\n"); + else + printf("\ndone\n"); + + return 1; +} + +U_BOOT_CMD( + bubt, 2, 1, nand_burn_uboot_cmd, + "bubt - Burn an image on the Boot Nand Flash.\n", + " file-name \n" + "\tBurn a binary image on the Boot Nand Flash, default file-name is u-boot.bin .\n" +); + +/* Write nboot loader image into the nand flash */ +int nand_burn_nboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 ret = 0; + extern char console_buffer[]; + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + nand_write_options_t wr_opts; + + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "nboot.bin", sizeof(BootFile)); + printf("using default file \"nboot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + printf("Erase %d - %d ... ",CFG_NBOOT_BASE, CFG_NBOOT_LEN); + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_NBOOT_BASE; + er_opts.length = CFG_NBOOT_LEN; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_NBOOT_BASE, CFG_NBOOT_LEN , 0); + + printf("\nCopy to Nand Flash... "); + memset(&wr_opts, 0, sizeof(wr_opts)); + wr_opts.buffer = (u_char*) load_addr; + wr_opts.length = CFG_NBOOT_LEN; + wr_opts.offset = CFG_NBOOT_BASE; + /* opts.forcejffs2 = 1; */ + wr_opts.pad = 1; + wr_opts.blockalign = 1; + wr_opts.quiet = 1; + ret = nand_write_opts(nand, &wr_opts); + /* ret = nand_rw(nand_dev_desc + 0, + NANDRW_WRITE | NANDRW_JFFS2, CFG_NBOOT_BASE, CFG_NBOOT_LEN, + &total, (u_char*)0x100000); + */ + if (ret) + printf("Error - NAND burn faild!\n"); + else + printf("\ndone\n"); + + return 1; +} + +U_BOOT_CMD( + nbubt, 2, 1, nand_burn_nboot_cmd, + "nbubt - Burn a boot loader image on the Boot Nand Flash.\n", + " file-name \n" + "\tBurn a binary boot loader image on the Boot Nand Flash, default file-name is nboot.bin .\n" +); + +#else +/* Boot from Nor flash */ +int nor_burn_uboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int filesize; + MV_U32 s_first,s_end,env_sec; + extern char console_buffer[]; + + + s_first = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_MONITOR_BASE); + s_end = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_MONITOR_BASE + CFG_MONITOR_LEN -1); + + env_sec = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_ENV_ADDR); + + + load_addr = CFG_LOAD_ADDR; + if(argc == 2) { + copy_filename (BootFile, argv[1], sizeof(BootFile)); + } + else { + copy_filename (BootFile, "u-boot.bin", sizeof(BootFile)); + printf("using default file \"u-boot.bin\" \n"); + } + + if ((filesize = NetLoop(TFTP)) < 0) + return 0; + + printf("Un-Protect Flash Monitor space\n"); + flash_protect (FLAG_PROTECT_CLEAR, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[BOOT_FLASH_INDEX]); + + printf("\n**Warning**\n"); + printf("If U-Boot Endiannes is going to change (LE->BE or BE->LE), Then Env parameters should be overriden..\n"); + printf("Override Env parameters? (y/n)"); + readline(" "); + if( strcmp(console_buffer,"Y") == 0 || + strcmp(console_buffer,"yes") == 0 || + strcmp(console_buffer,"y") == 0 ) { + + flash_protect (FLAG_PROTECT_CLEAR, + flash_info[BOOT_FLASH_INDEX].start[env_sec], + flash_info[BOOT_FLASH_INDEX].start[env_sec] + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + + printf("Erase Env parameters sector %d... ",env_sec); + flash_erase(&flash_info[BOOT_FLASH_INDEX], env_sec, env_sec); + + if ((mvCtrlModelGet() != MV_6082_DEV_ID) && + (mvCtrlModelGet() != MV_6183_DEV_ID) && + (mvCtrlModelGet() != MV_6183L_DEV_ID)) + flash_protect (FLAG_PROTECT_SET, + flash_info[BOOT_FLASH_INDEX].start[env_sec], + flash_info[BOOT_FLASH_INDEX].start[env_sec] + CFG_ENV_SECT_SIZE - 1, + &flash_info[BOOT_FLASH_INDEX]); + + } + + printf("Erase %d - %d sectors... ",s_first,s_end); + flash_erase(&flash_info[BOOT_FLASH_INDEX], s_first, s_end); + + printf("Copy to Flash... "); + + flash_write ( (uchar *)CFG_LOAD_ADDR + CFG_MONITOR_IMAGE_OFFSET, + CFG_MONITOR_BASE, + filesize - CFG_MONITOR_IMAGE_OFFSET); + + printf("done\nProtect Flash Monitor space\n"); + flash_protect (FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, + &flash_info[BOOT_FLASH_INDEX]); + + return 1; +} + +U_BOOT_CMD( + bubt, 2, 1, nor_burn_uboot_cmd, + "bubt - Burn an image on the Boot Flash.\n", + " file-name \n" + "\tBurn a binary image on the Boot Flash, default file-name is u-boot.bin .\n" +); +#endif /* defined(CFG_NAND_BOOT) */ +#endif /* (CONFIG_COMMANDS & CFG_CMD_NET) */ + + + +/******************************************************************************* +Reset environment variables. +********************************************************************************/ +extern flash_info_t flash_info[]; /* info for FLASH chips */ +int resetenv_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(CFG_NAND_BOOT) + printf("Erase Env parameters offset 0x%x... ",CFG_ENV_OFFSET); + nand_info_t *nand = &nand_info[0]; + nand_erase_options_t er_opts; + memset(&er_opts, 0, sizeof(er_opts)); + er_opts.offset = CFG_ENV_OFFSET; + er_opts.length = CFG_ENV_SECT_SIZE; + er_opts.quiet = 1; + + nand_erase_opts(nand, &er_opts); + //nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0); + printf("done"); +#else + MV_U32 env_sec = flash_in_which_sec(&flash_info[0], CFG_ENV_ADDR); + + if (env_sec == -1) + { + printf("Could not find ENV Sector\n"); + return 0; + } + + printf("Un-Protect ENV Sector\n"); + + flash_protect(FLAG_PROTECT_CLEAR, + CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[0]); + + + printf("Erase sector %d ... ",env_sec); + flash_erase(&flash_info[0], env_sec, env_sec); + printf("done\nProtect ENV Sector\n"); + + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[0]); + +#endif /* defined(CFG_NAND_BOOT) */ + printf("\nWarning: Default Environment Variables will take effect Only after RESET \n\n"); + return 1; +} + +U_BOOT_CMD( + resetenv, 1, 1, resetenv_cmd, + "resetenv - Return all environment variable to default.\n", + " \n" + "\t Erase the environemnt variable sector.\n" +); + +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FLASH) */ +#if CONFIG_COMMANDS & CFG_CMD_BSP + +/****************************************************************************** +* Category - General +* Functionality- The commands allows the user to view the contents of the MV +* internal registers and modify them. +* Need modifications (Yes/No) - no +*****************************************************************************/ +int ir_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +{ + MV_U32 regNum = 0x0, regVal, regValTmp, res; + MV_8 regValBin[40]; + MV_8 cmd[30]; + int i,j = 0, flagm = 0; + extern MV_8 console_buffer[]; + + if( argc == 2 ) { + regNum = simple_strtoul( argv[1], NULL, 16 ); + } + else { + printf( "Usage:\n%s\n", cmdtp->usage ); + return 0; + } + + regVal = MV_REG_READ( regNum ); + regValTmp = regVal; + printf( "Internal register 0x%x value : 0x%x\n ",regNum, regVal ); + printf( "\n 31 24 16 8 0" ); + printf( "\n | | | | |\nOLD: " ); + + for( i = 31 ; i >= 0 ; i-- ) { + if( regValTmp > 0 ) { + res = regValTmp % 2; + regValTmp = (regValTmp - res) / 2; + if( res == 0 ) + regValBin[i] = '0'; + else + regValBin[i] = '1'; + } + else + regValBin[i] = '0'; + } + + for( i = 0 ; i < 32 ; i++ ) { + printf( "%c", regValBin[i] ); + if( (((i+1) % 4) == 0) && (i > 1) && (i < 31) ) + printf( "-" ); + } + + readline( "\nNEW: " ); + strcpy(cmd, console_buffer); + if( (cmd[0] == '0') && (cmd[1] == 'x') ) { + regVal = simple_strtoul( cmd, NULL, 16 ); + flagm=1; + } + else { + for( i = 0 ; i < 40 ; i++ ) { + if(cmd[i] == '\0') + break; + if( i == 4 || i == 9 || i == 14 || i == 19 || i == 24 || i == 29 || i == 34 ) + continue; + if( cmd[i] == '1' ) { + regVal = regVal | (0x80000000 >> j); + flagm = 1; + } + else if( cmd[i] == '0' ) { + regVal = regVal & (~(0x80000000 >> j)); + flagm = 1; + } + j++; + } + } + + if( flagm == 1 ) { + MV_REG_WRITE( regNum, regVal ); + printf( "\nNew value = 0x%x\n\n", MV_REG_READ(regNum) ); + } + return 1; +} + +U_BOOT_CMD( + ir, 2, 1, ir_cmd, + "ir - reading and changing MV internal register values.\n", + " address\n" + "\tDisplays the contents of the internal register in 2 forms, hex and binary.\n" + "\tIt's possible to change the value by writing a hex value beginning with \n" + "\t0x or by writing 0 or 1 in the required place. \n" + "\tPressing enter without any value keeps the value unchanged.\n" +); + +/****************************************************************************** +* Category - General +* Functionality- Display the auto detect values of the TCLK and SYSCLK. +* Need modifications (Yes/No) - no +*****************************************************************************/ +int clk_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + printf( "TCLK %dMhz, SYSCLK %dMhz (UART baudrate %d)\n", + mvTclkGet()/1000000, mvSysClkGet()/1000000, CONFIG_BAUDRATE); + return 1; +} + +U_BOOT_CMD( + dclk, 1, 1, clk_cmd, + "dclk - Display the MV device CLKs.\n", + " \n" + "\tDisplay the auto detect values of the TCLK and SYSCLK.\n" +); + +/****************************************************************************** +* Functional only when using Lauterbach to load image into DRAM +* Category - DEBUG +* Functionality- Display the array of registers the u-boot write to. +* +*****************************************************************************/ +#if defined(REG_DEBUG) +int reg_arry[4096][2]; +int reg_arry_index = 0; +int print_registers( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int i; + printf("Register display\n"); + + for (i=0; i < reg_arry_index; i++) + printf("Reg no %d addr 0x%x = 0x%08x\n", i, reg_arry[i][0], reg_arry[i][1]); + + return 1; +} + +U_BOOT_CMD( + printreg, 1, 1, print_registers, + "printreg - Display the register array the u-boot write to.\n", + " \n" + "\tDisplay the register array the u-boot write to.\n" +); +#endif + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +/****************************************************************************** +* Category - Etherent +* Functionality- Display PHY ports status (using SMI access). +* Need modifications (Yes/No) - No +*****************************************************************************/ +int sg_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(MV_INC_BOARD_QD_SWITCH) + printf( "Switch status not supported\n"); +#else + MV_U32 port; + for( port = 0 ; port < mvCtrlEthMaxPortGet(); port++ ) { + + printf( "PHY %d :\n", port ); + printf( "---------\n" ); + + mvEthPhyPrintStatus( mvBoardPhyAddrGet(port) ); + + printf("\n"); + } +#endif + return 1; +} + +U_BOOT_CMD( + sg, 1, 1, sg_cmd, + "sg - scanning the PHYs status\n", + " \n" + "\tScan all the Gig port PHYs and display their Duplex, Link, Speed and AN status.\n" +); +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + +#if defined(MV_INCLUDE_IDMA) + +/****************************************************************************** +* Category - DMA +* Functionality- Perform a DMA transaction +* Need modifications (Yes/No) - No +*****************************************************************************/ +int mvDma_cmd( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ) +{ + MV_8 cmd[20], c; + extern MV_8 console_buffer[]; + MV_U32 chan, src, dst, byteCount, ctrlLo; + MV_DMA_DEC_WIN win; + MV_BOOL err; + + /* IDMA channel */ + if( argc == 2 ) + chan = simple_strtoul( argv[1], NULL, 16 ); + else + chan = 0; + + /* source address */ + while(1) { + readline( "Source Address: " ); + strcpy( cmd, console_buffer ); + src = simple_strtoul( cmd, NULL, 16 ); + if( src == 0xffffffff ) printf( "Bad address !!!\n" ); + else break; + } + + /* desctination address */ + while(1) { + readline( "Destination Address: " ); + strcpy(cmd, console_buffer); + dst = simple_strtoul( cmd, NULL, 16 ); + if( dst == 0xffffffff ) printf("Bad address !!!\n"); + else break; + } + + /* byte count */ + while(1) { + readline( "Byte Count (up to 16M (0xffffff-1)): " ); + strcpy( cmd, console_buffer ); + byteCount = simple_strtoul( cmd, NULL, 16 ); + if( (byteCount > 0xffffff) || (byteCount == 0) ) printf("Bad value !!!\n"); + else break; + } + + /* compose the command */ + ctrlLo = ICCLR_BLOCK_MODE | ICCLR_NON_CHAIN_MODE | ICCLR_SRC_INC | ICCLR_DST_INC; + + + if (byteCount > _64K) + { + ctrlLo |= ICCLR_DESC_MODE_16M; + } + + /* set data transfer limit */ + while(1) { + printf( "Data transfer limit:\n" ); + printf( "(1) 8 bytes at a time.\n" ); + printf( "(2) 16 bytes at a time.\n" ); + printf( "(3) 32 bytes at a time.\n" ); + printf( "(4) 64 bytes at a time.\n" ); + printf( "(5) 128 bytes at a time.\n" ); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + ctrlLo |= (ICCLR_DST_BURST_LIM_32BYTE | ICCLR_SRC_BURST_LIM_32BYTE); + printf( "32 bytes at a time.\n" ); + break; + case '1': + ctrlLo |= (ICCLR_DST_BURST_LIM_8BYTE | ICCLR_SRC_BURST_LIM_8BYTE); + break; + case '2': + ctrlLo |= (ICCLR_DST_BURST_LIM_16BYTE | ICCLR_SRC_BURST_LIM_16BYTE); + break; + case '3': + ctrlLo |= (ICCLR_DST_BURST_LIM_32BYTE | ICCLR_SRC_BURST_LIM_32BYTE); + break; + case '4': + ctrlLo |= (ICCLR_DST_BURST_LIM_64BYTE | ICCLR_SRC_BURST_LIM_64BYTE); + break; + case '5': + ctrlLo |= (ICCLR_DST_BURST_LIM_128BYTE | ICCLR_SRC_BURST_LIM_128BYTE); + break; + default: + printf( "Bad value !!!\n" ); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* set ovveride source option */ + while(1) { + printf( "Override Source:\n" ); + printf( "(0) - no override\n" ); + mvDmaWinGet( 1, &win ); + printf( "(1) - use Win1 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 2, &win ); + printf( "(2) - use Win2 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 3, &win ); + printf( "(3) - use Win3 (%s)\n",mvCtrlTargetNameGet(win.target)); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + case '0': + printf( "No override\n" ); + break; + case '1': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(1); + break; + case '2': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(2); + break; + case '3': + ctrlLo |= ICCLR_OVRRD_SRC_BAR(3); + break; + default: + printf("Bad value !!!\n"); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* set override destination option */ + while(1) { + printf( "Override Destination:\n" ); + printf( "(0) - no override\n" ); + mvDmaWinGet( 1, &win ); + printf( "(1) - use Win1 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 2, &win ); + printf( "(2) - use Win2 (%s)\n",mvCtrlTargetNameGet(win.target)); + mvDmaWinGet( 3, &win ); + printf( "(3) - use Win3 (%s)\n",mvCtrlTargetNameGet(win.target)); + + c = getc(); + printf( "%c\n", c ); + + err = MV_FALSE; + + switch( c ) { + case 13: /* Enter */ + case '0': + printf( "No override\n" ); + break; + case '1': + ctrlLo |= ICCLR_OVRRD_DST_BAR(1); + break; + case '2': + ctrlLo |= ICCLR_OVRRD_DST_BAR(2); + break; + case '3': + ctrlLo |= ICCLR_OVRRD_DST_BAR(3); + break; + default: + printf("Bad value !!!\n"); + err = MV_TRUE; + } + + if( !err ) break; + } + + /* wait for previous transfer completion */ + while( mvDmaStateGet(chan) != MV_IDLE ); + + /* issue the transfer */ + mvDmaCtrlLowSet( chan, ctrlLo ); + mvDmaTransfer( chan, src, dst, byteCount, 0 ); + + /* wait for completion */ + while( mvDmaStateGet(chan) != MV_IDLE ); + + printf( "Done...\n" ); + return 1; +} + +U_BOOT_CMD( + dma, 2, 1, mvDma_cmd, + "dma - Perform DMA\n", + " \n" + "\tPerform DMA transaction with the parameters given by the user.\n" +); + +#endif /* #if defined(MV_INCLUDE_IDMA) */ + +/****************************************************************************** +* Category - Memory +* Functionality- Displays the MV's Memory map +* Need modifications (Yes/No) - Yes +*****************************************************************************/ +int displayMemoryMap_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvCtrlAddrDecShow(); + return 1; +} + +U_BOOT_CMD( + map, 1, 1, displayMemoryMap_cmd, + "map - Diasplay address decode windows\n", + " \n" + "\tDisplay controller address decode windows: CPU, PCI, Gig, DMA, XOR and COMM\n" +); + + + +#include "ddr1_2/mvDram.h" +#if defined(MV_INC_BOARD_DDIM) + +/****************************************************************************** +* Category - Memory +* Functionality- Displays the SPD information for a givven dimm +* Need modifications (Yes/No) - +*****************************************************************************/ + +int dimminfo_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int num = 0; + + if (argc > 1) { + num = simple_strtoul (argv[1], NULL, 10); + } + + printf("*********************** DIMM%d *****************************\n",num); + + dimmSpdPrint(num); + + printf("************************************************************\n"); + + return 1; +} + +U_BOOT_CMD( + ddimm, 2, 1, dimminfo_cmd, + "ddimm - Display SPD Dimm Info\n", + " [0/1]\n" + "\tDisplay Dimm 0/1 SPD information.\n" +); + +/****************************************************************************** +* Category - Memory +* Functionality- Copy the SPD information of dimm 0 to dimm 1 +* Need modifications (Yes/No) - +*****************************************************************************/ + +int spdcpy_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + printf("Copy DIMM 0 SPD data into DIMM 1 SPD..."); + + if (MV_OK != dimmSpdCpy()) + printf("\nDIMM SPD copy fail!\n"); + else + printf("Done\n"); + + return 1; +} + +U_BOOT_CMD( + spdcpy, 2, 1, spdcpy_cmd, + "spdcpy - Copy Dimm 0 SPD to Dimm 1 SPD \n", + "" + "" +); +#endif /* #if defined(MV_INC_BOARD_DDIM) */ + +/****************************************************************************** +* Functionality- Go to an address and execute the code there and return, +* defualt address is 0x40004 +*****************************************************************************/ +extern void cpu_dcache_flush_all(void); +extern void cpu_icache_flush_invalidate_all(void); + +void mv_go(unsigned long addr,int argc, char *argv[]) +{ + int rc; + addr = MV_CACHEABLE(addr); + char* envCacheMode = getenv("cacheMode"); + + /* + * pass address parameter as argv[0] (aka command name), + * and all remaining args + */ + + if(envCacheMode && (strcmp(envCacheMode,"write-through") == 0)) + { + int i=0; + + /* Flush Invalidate I-Cache */ + cpu_icache_flush_invalidate_all(); + + /* Drain write buffer */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); + + + } + else /*"write-back"*/ + { + int i=0; + + /* Flush Invalidate I-Cache */ + cpu_icache_flush_invalidate_all(); + + /* Drain write buffer */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); + + + /* Flush invalidate D-cache */ + cpu_dcache_flush_all(); + + + } + + + rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]); + + return; +} + +int g_cmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0; + } + + addr = 0x40000; + + if (argc > 1) { + addr = simple_strtoul(argv[1], NULL, 16); + } + mv_go(addr,argc,&argv[0]); + return 1; +} + +U_BOOT_CMD( + g, CFG_MAXARGS, 1, g_cmd, + "g - start application at cached address 'addr'(default addr 0x40000)\n", + " addr [arg ...] \n" + "\tStart application at address 'addr'cachable!!!(default addr 0x40004/0x240004)\n" + "\tpassing 'arg' as arguments\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/****************************************************************************** +* Functionality- Searches for a value +*****************************************************************************/ +int fi_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 s_address,e_address,value,i,tempData; + MV_BOOL error = MV_FALSE; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 4){ + value = simple_strtoul(argv[1], NULL, 16); + s_address = simple_strtoul(argv[2], NULL, 16); + e_address = simple_strtoul(argv[3], NULL, 16); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + if(s_address == 0xffffffff || e_address == 0xffffffff) error = MV_TRUE; + if(s_address%4 != 0 || e_address%4 != 0) error = MV_TRUE; + if(s_address > e_address) error = MV_TRUE; + if(error) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + for(i = s_address; i < e_address ; i+=4) + { + tempData = (*((volatile unsigned int *)i)); + if(tempData == value) + { + printf("Value: %x found at ",value); + printf("address: %x\n",i); + return 1; + } + } + printf("Value not found!!\n"); + return 1; +} + +U_BOOT_CMD( + fi, 4, 1, fi_cmd, + "fi - Find value in the memory.\n", + " value start_address end_address\n" + "\tSearch for a value 'value' in the memory from address 'start_address to\n" + "\taddress 'end_address'.\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + +/****************************************************************************** +* Functionality- Compare the memory with Value. +*****************************************************************************/ +int cmpm_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U32 s_address,e_address,value,i,tempData; + MV_BOOL error = MV_FALSE; + + if(!enaMonExt()){ + printf("This command can be used only if enaMonExt is set!\n"); + return 0;} + + if(argc == 4){ + value = simple_strtoul(argv[1], NULL, 16); + s_address = simple_strtoul(argv[2], NULL, 16); + e_address = simple_strtoul(argv[3], NULL, 16); + }else{ printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + + if(s_address == 0xffffffff || e_address == 0xffffffff) error = MV_TRUE; + if(s_address%4 != 0 || e_address%4 != 0) error = MV_TRUE; + if(s_address > e_address) error = MV_TRUE; + if(error) + { + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + for(i = s_address; i < e_address ; i+=4) + { + tempData = (*((volatile unsigned int *)i)); + if(tempData != value) + { + printf("Value: %x found at address: %x\n",tempData,i); + } + } + return 1; +} + +U_BOOT_CMD( + cmpm, 4, 1, cmpm_cmd, + "cmpm - Compare Memory\n", + " value start_address end_address.\n" + "\tCompare the memory from address 'start_address to address 'end_address'.\n" + "\twith value 'value'\n" + "\t(This command can be used only if enaMonExt is set!)\n" +); + + + +#if 0 +/****************************************************************************** +* Category - Etherent +* Functionality- Display PHY ports status (using SMI access). +* Need modifications (Yes/No) - No +*****************************************************************************/ +int eth_show_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + ethRegs(argv[1]); + ethPortRegs(argv[1]); + ethPortStatus(argv[1]); + ethPortQueues(argv[1],0,0,1); + return 1; +} + +U_BOOT_CMD( + ethShow, 1, 1, eth_show_cmd, + "ethShow - scanning the PHYs status\n", + " \n" + "\tScan all the Gig port PHYs and display their Duplex, Link, Speed and AN status.\n" +); +#endif + +#if defined(MV_INCLUDE_PEX) + +#include "pci/mvPci.h" + +int pcie_phy_read_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U16 phyReg; + + mvPexPhyRegRead(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16), &phyReg); + + printf ("0x%x\n", phyReg); + + return 1; +} + +U_BOOT_CMD( + pciePhyRead, 3, 3, pcie_phy_read_cmd, + "phyRead - Read PCI-E Phy register\n", + " PCI-E_interface Phy_offset. \n" + "\tRead the PCI-E Phy register. \n" +); + + +int pcie_phy_write_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvPexPhyRegWrite(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16 ), + simple_strtoul( argv[3], NULL, 16 )); + + return 1; +} + +U_BOOT_CMD( + pciePhyWrite, 4, 4, pcie_phy_write_cmd, + "pciePhyWrite - Write PCI-E Phy register\n", + " PCI-E_interface Phy_offset value.\n" + "\tWrite to the PCI-E Phy register.\n" +); + +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) + +#include "eth-phy/mvEthPhy.h" + +int phy_read_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + MV_U16 phyReg; + + mvEthPhyRegRead(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16), &phyReg); + + printf ("0x%x\n", phyReg); + + return 1; +} + +U_BOOT_CMD( + phyRead, 3, 3, phy_read_cmd, + "phyRead - Read Phy register\n", + " Phy_address Phy_offset. \n" + "\tRead the Phy register. \n" +); + + +int phy_write_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + mvEthPhyRegWrite(simple_strtoul( argv[1], NULL, 16 ), + simple_strtoul( argv[2], NULL, 16 ), + simple_strtoul( argv[3], NULL, 16 )); + + return 1; +} + +U_BOOT_CMD( + phyWrite, 4, 4, phy_write_cmd, + "phyWrite - Write Phy register\n", + " Phy_address Phy_offset value.\n" + "\tWrite to the Phy register.\n" +); + +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + +#endif /* MV_TINY */ +#if 0 +#if defined(CFG_NAND_BOOT) +extern int doNandScrub(struct nand_chip* nand, size_t ofs); + +/* Erase bad blocks - for internal use only */ +int do_nand_scrub(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + extern char console_buffer[]; + + printf("\n**Warning**\n"); + printf("This command will erase NAND flash bad blocks ...\n"); + printf("Are you sure ? (y/n)"); + readline(" "); + + if( strcmp(console_buffer,"Y") == 0 || + strcmp(console_buffer,"yes") == 0 || + strcmp(console_buffer,"y") == 0 ) { + + doNandScrub(nand_dev_desc + 0, 0); + } + return 1; +} + +U_BOOT_CMD( + nandScrub, 4, 4, do_nand_scrub, + "", + " " + "" +); + +#endif /* defined(CFG_NAND_BOOT) */ +#endif diff --git a/board/mv_feroceon/mv_orion/mv_dram.c b/board/mv_feroceon/mv_orion/mv_dram.c new file mode 100644 index 0000000..3bd4321 --- /dev/null +++ b/board/mv_feroceon/mv_orion/mv_dram.c @@ -0,0 +1,395 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include "ddr1_2/mvDramIf.h" +#include "mvOs.h" +#include "mvBoardEnvLib.h" +#include "ddr1_2/mvDramIfRegs.h" +#include "mvCpuIfRegs.h" + +#ifdef DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +extern void i2c_init(int speed, int slaveaddr); +extern void _start(void); +extern unsigned int mvCpuPclkGet(void); +extern void reset_cpu(void); +extern int dramBoot; + + +#ifdef MV_INC_DRAM_MFG_TEST +static MV_VOID mvDramMfgTrst(void); +static MV_STATUS mv_mem_test(MV_U32* pMem, MV_U32 pattern, MV_U32 count); +static MV_STATUS mv_mem_cmp(MV_U32* pMem, MV_U32 pattern, MV_U32 count); +#endif + +MV_VOID mvIntrfaceWidthPrint(MV_VOID) +{ + + if ((MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_16BIT) + { + printf(" 16bit width"); + } + else + { + printf(" 32bit width"); + } +} + +MV_VOID sizePrint(MV_U32 size) +{ + printf("size "); + + if(size >= _1G) + { + printf("%3dGB ", size / _1G); + size %= _1G; + if(size) + printf("+"); + } + if(size >= _1M ) + { + printf("%3dMB ", size / _1M); + size %= _1M; + if(size) + printf("+"); + } + if(size >= _1K) + { + printf("%3dKB ", size / _1K); + size %= _1K; + if(size) + printf("+"); + } + if(size > 0) + { + printf("%3dB ", size); + } +} + + +int dram_init (void) +{ + + DECLARE_GLOBAL_DATA_PTR; + unsigned int i, dramTotalSize=0; + char name[15]; + MV_32 memBase; + + mvCtrlModelRevNameGet(name); + printf("\nSoc: %s", name); + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + printf(" (DDR2)\n", name); + } + else + { + printf(" (DDR1)\n", name); + } + + printf("CPU running @ %dMhz \n", mvCpuPclkGet()/1000000); +#ifdef MV_TCLK_CALC + printf("SysClock = %dMhz , Calc TClock = %dMhz \n\n", CFG_BUS_CLK/1000000, CFG_TCLK/1000000); +#else + printf("SysClock = %dMhz , TClock = %dMhz \n\n", CFG_BUS_CLK/1000000, CFG_TCLK/1000000); +#endif + +#if defined(MV_INC_BOARD_DDIM) + /* Call dramInit */ + if (0 == (dramTotalSize = initdram(0))) + { + printf("DRAM Initialization Failed\n"); + reset_cpu(); + return (1); + } + + for(i = 0; i< MV_DRAM_MAX_CS; i++) + { + memBase = mvDramIfBankBaseGet(i); + if (MV_ERROR == memBase) + gd->bd->bi_dram[i].start = 0; + else + gd->bd->bi_dram[i].start = memBase; + + gd->bd->bi_dram[i].size = mvDramIfBankSizeGet(i); + if (gd->bd->bi_dram[i].size) + { + printf("DRAM CS[%d] base 0x%08x ",i, gd->bd->bi_dram[i].start); + mvSizePrint(gd->bd->bi_dram[i].size); + printf("\n"); + } + } + + printf("DRAM Total "); + mvSizePrint(dramTotalSize); + mvIntrfaceWidthPrint(); + printf("\n"); + +#else /* MV_INC_BOARD_DDIM */ + + for(i = 0; i< MV_DRAM_MAX_CS; i++) + { +#if !defined(MV_88F6082L) && defined(MV_88F6082) + if (mvCtrlModelRevGet() == MV_6082_A0_ID) + { + gd->bd->bi_dram[i].start = (i)?_16M:0; + gd->bd->bi_dram[i].size = _8M; + } + else + { + memBase = mvDramIfBankBaseGet(i); + if (MV_ERROR == memBase) + gd->bd->bi_dram[i].start = 0; + else + gd->bd->bi_dram[i].start = memBase; + + gd->bd->bi_dram[i].size = mvDramIfBankSizeGet(i); + } +#else + memBase = mvDramIfBankBaseGet(i); + if (MV_ERROR == memBase) + gd->bd->bi_dram[i].start = 0; + else + gd->bd->bi_dram[i].start = memBase; + + gd->bd->bi_dram[i].size = mvDramIfBankSizeGet(i); +#endif + dramTotalSize += gd->bd->bi_dram[i].size; + if (gd->bd->bi_dram[i].size) + { + printf("DRAM CS[%d] base 0x%08x ",i, gd->bd->bi_dram[i].start); + mvSizePrint(gd->bd->bi_dram[i].size); + printf("\n"); + } + } + + printf("DRAM Total "); + sizePrint(dramTotalSize); + mvIntrfaceWidthPrint(); + printf("\n"); +#ifdef MV_INC_DRAM_MFG_TEST + mvDramMfgTrst(); +#endif +#endif + return 0; +} + +#if defined(MV_INC_BOARD_DDIM) + +/* u-boot interface function to SDRAM init - this is where all the + * controlling logic happens */ +long int initdram(int board_type) +{ + MV_VOIDFUNCPTR pRom; + MV_U32 forcedCl; /* Forced CAS Latency */ + MV_U32 totalSize; + MV_U32 temp; + char * env; + MV_TWSI_ADDR slave; + + /* r0 <- current position of code */ + /* test if we run from flash or RAM */ + if(dramBoot != 1) + { + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(CFG_I2C_SPEED, CFG_TCLK, &slave, 0); + + /* Calculating MIN/MAX CAS latency according to user settings */ + env = getenv("CASset"); + + if(env && (strcmp(env,"1.5") == 0)) + { + forcedCl = 15; + } + else if(env && (strcmp(env,"2") == 0)) + { + forcedCl = 20; + } + else if(env && (strcmp(env,"2.5") == 0)) + { + forcedCl = 25; + } + else if(env && (strcmp(env,"3") == 0)) + { + forcedCl = 30; + } + else if(env && (strcmp(env,"4") == 0)) + { + forcedCl = 40; + } + else + { + forcedCl = 0; + } + + /* detect the dram configuartion parameters */ + if (MV_OK != mvDramIfDetect(forcedCl)) + { + printf("DRAM Auto Detection Failed! System Halt!\n"); + return 0; + } + + /* set the dram configuration */ + /* Calculate jump address of _mvDramIfConfig() */ +#if defined(MV_BOOTROM) + pRom = (MV_VOIDFUNCPTR)((_mvDramIfConfig - _start) + CFG_MONITOR_BASE + MONITOR_HEADER_LEN); +#else + pRom = (MV_VOIDFUNCPTR)((_mvDramIfConfig - _start) + CFG_MONITOR_BASE); +#endif + + + (*pRom) (); /* Jump to _mvDramIfConfig*/ + } + + totalSize = mvDramIfSizeGet(); + + printf("DRAM"); + if(MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + switch((MV_REG_READ(0x141c) >> 4) & 0x7) + { + case 0x3: printf(" CAS Latency = 3"); + break; + case 0x4: printf(" CAS Latency = 4"); + break; + case 0x5: printf(" CAS Latency = 1.5"); + break; + default: printf(" unknown CAL "); + break; + } + } + else + { + switch((MV_REG_READ(0x141c) >> 4) & 0x7) + { + case 0x2: printf(" CAS Latency = 2"); + break; + case 0x3: printf(" CAS Latency = 3"); + break; + case 0x4: printf(" CAS Latency = 4"); + break; + case 0x5: printf(" CAS Latency = 1.5"); + break; + case 0x6: printf(" CAS Latency = 2.5"); + break; + default: printf(" unknown CAL "); + break; + } + } + + temp = MV_REG_READ(0x1408); + printf(" tRP = %d tRAS = %d tRCD=%d\n", + ((temp >> 8) & 0xf) + 1, ((temp >> 20) & 0xf) + 1, ((temp >> 4) & 0xf) + 1); + + return(totalSize); +} + +#endif /* #if defined(MV_INC_BOARD_DDIM) */ + +#ifdef MV_INC_DRAM_MFG_TEST +static MV_VOID mvDramMfgTrst(void) +{ + + /* Memory test */ + DECLARE_GLOBAL_DATA_PTR; + unsigned int mem_len,i,j, pattern; + unsigned int *mem_start; + char *env; + + env = getenv("enaPost"); + if(!env || ( (strcmp(env,"Yes") == 0) || (strcmp(env,"yes") == 0) ) ) + { + printf("Memory test pattern: "); + + for (j = 0 ; j<2 ; j++) + { + + switch(j){ + case 0: + pattern=0x55555555; + printf("0x%X, ",pattern); + break; + case 1: + pattern=0xAAAAAAAA; + printf("0x%X, ",pattern); + break; + default: + pattern=0x0; + printf("0x%X, ",pattern); + break; + } + + for(i = 0; i< MV_DRAM_MAX_CS; i++) + { + mem_start = (unsigned int *)gd->bd->bi_dram[i].start; + mem_len = gd->bd->bi_dram[i].size; + if (i == 0) + { + mem_start+= _4M; + mem_len-= _4M; + } + mem_len/=4; + if (MV_OK != mv_mem_test(mem_start, pattern, mem_len)) + { + printf(" Fail!\n"); + while(1); + } + } + } + printf(" Pass\n"); + } +} + + +static MV_STATUS mv_mem_test(MV_U32* pMem, MV_U32 pattern, MV_U32 count) +{ + int i; + for (i=0 ; i< count ; i+=1) + *(pMem + i) = pattern; + + if (MV_OK != mv_mem_cmp(pMem, pattern, count)) + { + return MV_ERROR; + } + return MV_OK; +} + +static MV_STATUS mv_mem_cmp(MV_U32* pMem, MV_U32 pattern, MV_U32 count) +{ + int i; + for (i=0 ; i< count ; i+=1) + { + if (*(pMem + i) != pattern) + { + printf("Fail\n"); + printf("Test failed at 0x%x\n",(pMem + i)); + return MV_ERROR; + } + } + + return MV_OK; +} +#endif /* MV_INC_DRAM_MFG_TEST */ diff --git a/board/mv_feroceon/mv_orion/mv_main.c b/board/mv_feroceon/mv_orion/mv_main.c new file mode 100644 index 0000000..ff4c468 --- /dev/null +++ b/board/mv_feroceon/mv_orion/mv_main.c @@ -0,0 +1,1781 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include "mvTypes.h" +#include "mvBoardEnvLib.h" +#include "mvCpuIf.h" +#include "mvCtrlEnvLib.h" +#include "mv_mon_init.h" +#include "rtc/ext_rtc/mvDS133x.h" +#include "mvDebug.h" +#include "cpu/mvCpuArm.h" +#include "device/mvDevice.h" +#include "twsi/mvTwsi.h" +#include "ethfp/mvEth.h" +#include "pex/mvPex.h" +#include "eth-phy/mvEthPhy.h" +#include "ethswitch/mvSwitch.h" +#include "gpp/mvGpp.h" +#include "sys/mvSysUsb.h" + +#if defined(MV_INCLUDE_XOR) +#include "xor/mvXor.h" +#endif +#if defined(MV_INCLUDE_IDMA) +#include "sys/mvSysIdma.h" +#include "idma/mvIdma.h" +#endif +#if defined(MV_INCLUDE_USB) +#include "usb/mvUsb.h" +#endif + +#include "cpu/mvCpu.h" + +#ifdef CONFIG_PCI +# include +#endif +#include "pci/mvPciRegs.h" + +#include +#include + +/* CPU address decode table. */ +MV_CPU_DEC_WIN mvCpuAddrWinMap[] = MV_CPU_IF_ADDR_WIN_MAP_TBL; + +static void mvStatusDebugLeds(char num); +#if defined(RD_88F6082NAS) || defined(RD_88F6082GE_SATA) || defined(RD_88F6082DAS_PLUS) || defined(RD_88F5182_3) +static void mvHddPowerCtrl(void); +#endif +#if defined(RD_88F6082MICRO_DAS_NAS) +static void bootDetection(void); +static void mv6082uDasNasSysPower(MV_BOOL enable); +#endif +void mv_cpu_init(void); +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +static int mv_set_power_scheme(void); +#endif + +#ifdef CFG_FLASH_CFI_DRIVER +MV_VOID mvUpdateNorFlashBaseAddrBank(MV_VOID); +int mv_board_num_flash_banks; +extern flash_info_t flash_info[]; /* info for FLASH chips */ +extern unsigned long flash_add_base_addr (uint flash_index, ulong flash_base_addr); +#endif /* CFG_FLASH_CFI_DRIVER */ + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) +extern MV_VOID mvBoardEgigaPhySwitchInit(void); +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +/* Define for SDK 2.0 */ +int __aeabi_unwind_cpp_pr0(int a,int b,int c) {return 0;} +int __aeabi_unwind_cpp_pr1(int a,int b,int c) {return 0;} +#endif + +/* Define for SDK 2.0 */ +int raise(void) {return 0;} + +/* Define only for open Linux support */ +#define RD_KUROBOX_PRO 0xFE +#define RD_KUROBOX_PRO_OPEN_LINUX_ID 1509 + +void print_mvBanner(void) +{ + printf("\n"); + printf(" __ __ _ _\n"); + printf(" | \\/ | __ _ _ ____ _____| | |\n"); + printf(" | |\\/| |/ _` | '__\\ \\ / / _ \\ | |\n"); + printf(" | | | | (_| | | \\ V / __/ | |\n"); + printf(" |_| |_|\\__,_|_| \\_/ \\___|_|_|\n"); + printf(" _ _ ____ _\n"); + printf("| | | | | __ ) ___ ___ | |_ \n"); + printf("| | | |___| _ \\ / _ \\ / _ \\| __| \n"); + printf("| |_| |___| |_) | (_) | (_) | |_ \n"); + printf(" \\___/ |____/ \\___/ \\___/ \\__| "); +#ifdef MV_INCLUDE_MONT_EXT + if(!enaMonExt()) + printf(" ** LOADER **"); + else + printf(" ** MONITOR **"); +#else + + printf(" ** Forcing LOADER mode only **"); +#endif /* MV_INCLUDE_MONT_EXT */ + + + return; +} + +void print_dev_id(void){ + static char boardName[30]; + + mvBoardNameGet(boardName); + +#if defined(MV_CPU_BE) + printf("\n ** MARVELL BOARD: %s BE ",boardName); +#else + printf("\n ** MARVELL BOARD: %s LE ",boardName); +#endif + + return; +} + + +extern MV_BOOL mvSataPhyShutdown(MV_U8 port); +MV_BOOL mvSataPhyPowerOn(MV_U8 port); + +#define CPU_MAIN_IRQ_MASK 0x20204 +#define CPU_MAIN_FIQ_MASK 0x20208 +#define CPU_END_POIN_MASK 0x2020c +void maskAllInt(void) +{ + /* mask all external interrupt sources */ + MV_REG_WRITE(CPU_MAIN_IRQ_MASK, 0); + MV_REG_WRITE(CPU_MAIN_FIQ_MASK, 0); + MV_REG_WRITE(CPU_END_POIN_MASK, 0); +} + +/* init for the Master*/ +void misc_init_r_dec_win(void) +{ + /* update all the windows BARS */ +#if defined(MV_INCLUDE_IDMA) + mvDmaInit(); +#endif + +#if defined(MV_INCLUDE_USB) + { + char *env; + + env = getenv("usb0Mode"); + if((!env) || (strcmp(env,"device") == 0) || (strcmp(env,"Device") == 0) ) + { + printf("USB 0: device mode\n"); + mvUsbInit(0, MV_FALSE); + } + else + { + printf("USB 0: host mode\n"); + mvUsbInit(0, MV_TRUE); + } + + + if (mvCtrlUsbMaxGet() == 2) + { + env = getenv("usb1Mode"); + if((!env) || (strcmp(env,"device") == 0) || (strcmp(env,"Device") == 0) ) + { + printf("USB 1: device mode\n"); + mvUsbInit(1, MV_FALSE); + } + else + { + printf("USB 1: host mode\n"); + mvUsbInit(1, MV_TRUE); + } + + + } + + } +#endif/* #if defined(MV_INCLUDE_USB) */ + + +#if defined(MV_INCLUDE_XOR) + mvXorInit(); +#endif + +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + mv_set_power_scheme(); +#endif + + return; +} + + +/* + * Miscellaneous platform dependent initialisations + */ + +extern MV_STATUS mvEthPhyRegRead(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 *data); +extern MV_STATUS mvEthPhyRegWrite(MV_U32 phyAddr, MV_U32 regOffs, MV_U16 data); + +/* golabal mac address for yukon EC */ +unsigned char yuk_enetaddr[6]; +extern int interrupt_init (void); +extern void i2c_init(int speed, int slaveaddr); + + +int board_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; +#if defined(MV_INCLUDE_TWSI) + MV_TWSI_ADDR slave; +#endif + unsigned int i; + + maskAllInt(); + /* must initialize the int in order for udelay to work */ + interrupt_init(); + +#if defined(MV_INCLUDE_TWSI) + slave.type = ADDR7_BIT; + slave.address = 0; + mvTwsiInit(CFG_I2C_SPEED, CFG_TCLK, &slave, 0); +#endif + + + /* Init the Board environment module (device bank params init) */ + mvBoardEnvInit(); + + /* Init the Controlloer environment module (MPP init) */ + mvCtrlEnvInit(); + +#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) + /* Init the PHY or Switch of the board */ + mvBoardEgigaPhySwitchInit(); +#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */ + + mvStatusDebugLeds(3); + + /* Init the Controller CPU interface */ + mvCpuIfInit(mvCpuAddrWinMap); + + /* arch number of Integrator Board */ + gd->bd->bi_arch_number = 526; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + /* relocate the exception vectors */ + /* U-Boot is running from DRAM at this stage */ + for(i = 0; i < 0x100; i+=4) + { + *(unsigned int *)(0x0 + i) = *(unsigned int*)(TEXT_BASE + i); + + } + + /* Enable i cache for DB_FPGA only */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); + i |= BIT12; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); + + /* i cache can work without MMU, + d cache can not work without MMU: + i cache already enable in start.S */ + /* Change reset vector to address 0x0 */ + asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + i &= ~BIT13; + asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + + /* Update NOR flash base address bank for CFI driver */ +#ifdef CFG_FLASH_CFI_DRIVER + mvUpdateNorFlashBaseAddrBank(); +#endif /* CFG_FLASH_CFI_DRIVER */ + + mvStatusDebugLeds(4); + + return 0; +} + +void misc_init_r_env(void){ + char *env; + char tmp_buf[10]; + unsigned int malloc_len, board_id; + DECLARE_GLOBAL_DATA_PTR; + +#if defined(RD_88F5181L_FE) || defined(RD_88F5181L_GE) || \ + defined(RD_88W8660) || defined(RD_88F5181L_FXO_GE) || \ + defined(RD_88F5181_GTWGE) || defined(RD_88F5181_GTWFE) || defined(RD_88W8660_AP82S) ||\ + defined(DB_88W8660) || defined(DB_88F5181L) + +#if defined(MV_NAND_BOOT) + env = getenv("bootargs"); + if(!env) + setenv("bootargs","console=ttyS0,115200 mtdparts=nand_mtd:1m(uboot)ro,2m(uImage),29m(rootfs)"); +#else + unsigned int flashSize =0 , secSize =0, ubootSize =0; + char buff[256]; + +#if defined(MV_BOOTSIZE_4M) + flashSize = _4M; +#elif defined(MV_BOOTSIZE_8M) + flashSize = _8M; +#elif defined(MV_BOOTSIZE_16M) + flashSize = _16M; +#elif defined(MV_BOOTSIZE_32M) + flashSize = _32M; +#elif defined(MV_BOOTSIZE_64M) + flashSize = _64M; +#endif + +#if defined(MV_SEC_64K) + secSize = _64K; +#if defined(MV_TINY_IMAGE) + ubootSize = _256K; +#else + ubootSize = _512K; +#endif +#elif defined(MV_SEC_128K) + secSize = _128K; +#if defined(MV_TINY_IMAGE) + ubootSize = _128K * 3; +#else + ubootSize = _128K * 5; +#endif +#elif defined(MV_SEC_256K) + secSize = _256K; +#if defined(MV_TINY_IMAGE) + ubootSize = _256K * 3; +#else + ubootSize = _256K * 3; +#endif +#endif + + if ((0 == flashSize) || (0 == secSize) || (0 == ubootSize)) + { + env = getenv("bootargs"); + if(!env) + setenv("bootargs","console=ttyS0,115200"); + } + else + { + sprintf(buff,"console=ttyS0,115200 mtdparts=cfi_flash:0x%x(root),0x%x(uboot)ro", + flashSize - ubootSize, ubootSize); + env = getenv("bootargs"); + if(!env) + setenv("bootargs",buff); + } +#endif /* defined(MV_NAND_BOOT) */ +#else + env = getenv("bootargs"); + if(!env) + setenv("bootargs","console=ttyS0,115200"); +#endif + + /* Check if to use the LED's for debug or to use single led for init and Linux heartbeat */ +#if defined(MV_INCLUDE_TDM) || defined(MV_INC_BOARD_QD_SWITCH) + env = getenv("enaDebugLed"); + if(!env || ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + setenv("enaDebugLed","no"); + else + setenv("enaDebugLed","yes"); +#else + env = getenv("enaDebugLed"); + if(!env || ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + setenv("enaDebugLed","yes"); + else + setenv("enaDebugLed","no"); +#endif + + /* Linux open port support */ + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + setenv("mainlineLinux","yes"); + else + setenv("mainlineLinux","no"); + + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + /* arch number for open port Linux */ + env = getenv("arcNumber"); + if(!env ) + { + /* arch number according to board ID */ + board_id = mvBoardIdGet(); + switch(board_id){ + case(DB_88F5X81_DDR2): + sprintf(tmp_buf,"%d", DB_88F5X81_DDR2_OPEN_LINUX_ID); + board_id = DB_88F5X81_DDR2_OPEN_LINUX_ID; + break; + case(RD_88F5182_2XSATA): + sprintf(tmp_buf,"%d", RD_88F5182_2XSATA_OPEN_LINUX_ID); + board_id = RD_88F5182_2XSATA_OPEN_LINUX_ID; + break; + case(RD_KUROBOX_PRO): + sprintf(tmp_buf,"%d", RD_KUROBOX_PRO_OPEN_LINUX_ID); + board_id = RD_KUROBOX_PRO_OPEN_LINUX_ID; + break; + default: + sprintf(tmp_buf,"%d", DB_88F5X81_DDR2_OPEN_LINUX_ID); + board_id = DB_88F5X81_DDR2_OPEN_LINUX_ID; + break; + } + gd->bd->bi_arch_number = board_id; + setenv("arcNumber", tmp_buf); + } + else + { + gd->bd->bi_arch_number = simple_strtoul(env, NULL, 10); + } + } + + /* update the CASset env parameter */ + env = getenv("CASset"); + if(!env ) + { +#ifdef MV_MIN_CAL + setenv("CASset","min"); +#else + setenv("CASset","max"); +#endif + } + /* Monitor extension */ +#ifdef MV_INCLUDE_MONT_EXT + env = getenv("enaMonExt"); + if(/* !env || */ ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + setenv("enaMonExt","yes"); + else +#endif + setenv("enaMonExt","no"); + + env = getenv("enaFlashBuf"); + if( ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("enaFlashBuf","no"); + else + setenv("enaFlashBuf","yes"); + + /* CPU streaming */ + env = getenv("enaCpuStream"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("enaCpuStream","no"); + else + setenv("enaCpuStream","yes"); + + if(mvCtrlModelGet() == MV_5281_DEV_ID) /* Orion 2 */ + { + /* VFP */ + env = getenv("enaVFP"); + if (mvCtrlRevGet() == MV_5281_C0_REV) /* Orion 2 == C0 */ + { + if( env && ( ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ))) + setenv("enaVFP","yes"); + else + setenv("enaVFP","no"); + } + else + { + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaVFP","no"); + else + setenv("enaVFP","yes"); + + } + + /* Orion 2 D2 VFP sub arch */ + if (mvCtrlRevGet() == MV_5281_D2_REV) /* Orion 2 == D2 */ + { + env = getenv("enaVFP"); + if( env && ( ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ))) + { + env = getenv("vfpSubArch2"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("vfpSubArch2","no"); + else + setenv("vfpSubArch2","yes"); + } + } + + /* Write allocation for all 5281 device set to no */ + env = getenv("enaWrAllo"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaWrAllo","no"); + else + setenv("enaWrAllo","yes"); + + if (mvCtrlRevGet() >= MV_5281_B0_REV) /* Orion 2 >= B0 */ + { + + /* ICache Prefetch */ + env = getenv("enaICPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaICPref","no"); + else + setenv("enaICPref","yes"); + + + /* DCache Prefetch */ + env = getenv("enaDCPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaDCPref","no"); + else + setenv("enaDCPref","yes"); + } + } + + if (mvCtrlModelGet() == MV_1281_DEV_ID) /* TC90 */ + { + /* VFP */ + env = getenv("enaVFP"); + if( env && ( ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ))) + setenv("enaVFP","yes"); + else + setenv("enaVFP","no"); + + /* Write allocation */ + env = getenv("enaWrAllo"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaWrAllo","no"); + else + { + setenv("enaWrAllo","yes"); + } + + /* ICache Prefetch */ + env = getenv("enaICPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaICPref","no"); + else + setenv("enaICPref","yes"); + + + /* DCache Prefetch */ + env = getenv("enaDCPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaDCPref","no"); + else + setenv("enaDCPref","yes"); + } + + if (mvCtrlModelGet() == MV_6183_DEV_ID || + mvCtrlModelGet() == MV_6183L_DEV_ID) /* MV88F6183 & MV88F6183L*/ + { + + /* Pex mode */ + env = getenv("pexMode"); + if( env && ( ((strcmp(env,"EP") == 0) || (strcmp(env,"ep") == 0) ))) + setenv("pexMode","EP"); + else + { + setenv("pexMode","RC"); + } + + /* Write allocation */ + env = getenv("enaWrAllo"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaWrAllo","no"); + else + { + setenv("enaWrAllo","yes"); + } + + /* ICache Prefetch */ + env = getenv("enaICPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaICPref","no"); + else + setenv("enaICPref","yes"); + + + /* DCache Prefetch */ + env = getenv("enaDCPref"); + if( env && ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("enaDCPref","no"); + else + setenv("enaDCPref","yes"); + } + + if (mvCtrlModelGet() == MV_6082_DEV_ID) /* MV88F6082 */ + { + + /* Pex mode */ + env = getenv("pexMode"); + if( env && ( ((strcmp(env,"EP") == 0) || (strcmp(env,"ep") == 0) ))) + setenv("pexMode","EP"); + else + { + setenv("pexMode","RC"); + } + } + + env = getenv("sata_dma_mode"); + if( env && ((strcmp(env,"No") == 0) || (strcmp(env,"no") == 0) ) ) + setenv("sata_dma_mode","no"); + else + setenv("sata_dma_mode","yes"); + + + /* Malloc length */ + env = getenv("MALLOC_len"); + malloc_len = simple_strtoul(env, NULL, 10) << 20; + if(malloc_len == 0){ + sprintf(tmp_buf,"%d",CFG_MALLOC_LEN>>20); + setenv("MALLOC_len",tmp_buf);} + + /* primary network interface */ + env = getenv("ethprime"); + + if(!env) + setenv("ethprime",ENV_ETH_PRIME); + + + /* netbsd boot arguments */ + env = getenv("netbsd_en"); + if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) + setenv("netbsd_en","no"); + else + { + + setenv("netbsd_en","yes"); + env = getenv("netbsd_gw"); + if(!env) + setenv("netbsd_gw","192.168.0.254"); + + env = getenv("netbsd_mask"); + if(!env) + setenv("netbsd_mask","255.255.255.0"); + + env = getenv("netbsd_fs"); + if(!env) + setenv("netbsd_fs","nfs"); + + env = getenv("netbsd_server"); + if(!env) + setenv("netbsd_server","192.168.0.1"); + + env = getenv("netbsd_ip"); + if(!env) + { + env = getenv("ipaddr"); + setenv("netbsd_ip",env); + } + + env = getenv("netbsd_rootdev"); + if(!env) + setenv("netbsd_rootdev","mgi0"); + + env = getenv("netbsd_add"); + if(!env) + setenv("netbsd_add","0x800000"); + + env = getenv("netbsd_get"); + if(!env) + setenv("netbsd_get","tftpboot $(netbsd_add) $(image_name)"); + + env = getenv("netbsd_set_args"); + if(!env) + setenv("netbsd_set_args","setenv bootargs nfsroot=$(netbsd_server):$(rootpath) fs=$(netbsd_fs) \ +ip=$(netbsd_ip) serverip=$(netbsd_server) mask=$(netbsd_mask) gw=$(netbsd_gw) rootdev=$(netbsd_rootdev) \ +ethaddr=$(ethaddr)"); + + env = getenv("netbsd_boot"); + if(!env) + setenv("netbsd_boot","bootm $(netbsd_add) $(bootargs)"); + + env = getenv("netbsd_bootcmd"); + if(!env) + setenv("netbsd_bootcmd","run netbsd_get ; run netbsd_set_args ; run netbsd_boot"); + } + + /* linux boot arguments */ + env = getenv("bootargs_root"); + if(!env) + setenv("bootargs_root","root=/dev/nfs rw"); + + /* For open Linux we set boot args differently */ + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + env = getenv("bootargs_end"); + if(!env) + setenv("bootargs_end",":::orion:eth0:none"); + } + else + { + env = getenv("bootargs_end"); + if(!env) + setenv("bootargs_end",CFG_BOOTARGS_END); + } + + + env = getenv("image_name"); + if(!env) + setenv("image_name","uImage"); + + +#if (CONFIG_BOOTDELAY >= 0) + env = getenv("bootcmd"); + if(!env) +#if defined(MV_INCLUDE_TDM) && defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(bootargs) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig) $(mvPhoneConfig); bootm 0x400000; "); +#elif defined(MV_INC_BOARD_QD_SWITCH) + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(bootargs) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig); bootm 0x400000; "); +#elif defined(MV_INCLUDE_TDM) + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(bootargs) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvPhoneConfig); bootm 0x400000; "); +#elif defined(RD_88F6082MICRO_DAS_NAS) + setenv("bootcmd","setenv bootargs $(bootargs) temp=$(minTemp),$(maxTemp); \ +bootext2 0:1,2 0x1000000 /boot/$(image_name) /dev/sda;"); +#else + + setenv("bootcmd","tftpboot 0x400000 $(image_name);\ +setenv bootargs $(bootargs) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x400000; "); +#endif +#endif /* (CONFIG_BOOTDELAY >= 0) */ + + env = getenv("standalone"); + if(!env) +#if defined(MV_INCLUDE_TDM) && defined(MV_INC_BOARD_QD_SWITCH) + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(bootargs) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig) $(mvPhoneConfig); bootm 0x400000;"); +#elif defined(MV_INC_BOARD_QD_SWITCH) + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(bootargs) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvNetConfig); bootm 0x400000;"); +#elif defined(MV_INCLUDE_TDM) + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(bootargs) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end) $(mvPhoneConfig); bootm 0x400000;"); +#else + setenv("standalone","fsload 0x400000 $(image_name);setenv bootargs $(bootargs) root=/dev/mtdblock0 rw \ +ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x400000;"); +#endif + +#if defined(DB_PRPMC) || defined(DB_MNG) + env = getenv("vx_boot"); + if(!env) + setenv("vx_boot","tftpboot $(default_load_addr) $(image_name);setenv bootargs sgi(0,0) host:VxWorks h=$(serverip) \ +e=$(ipaddr):FFFF0000 u=anonymous pw=target; setenv bootaddr 0x700; bootvx $(default_load_addr);"); + + env = getenv("dhcp_boot"); + if(!env) + setenv("dhcp_boot","dhcp;setenv bootargs $(bootargs) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ +ip=$(ipaddr):$(serverip)$(bootargs_end); bootm $(default_load_addr);"); +#endif /* DB_PRPMC || DB_MNG */ + + /* Set boodelay to 3 sec, if Monitor extension are disabled */ + if(!enaMonExt()){ +#if defined(RD_88F6082MICRO_DAS_NAS) + setenv("bootdelay","1"); +#else + setenv("bootdelay","3"); +#endif + setenv("disaMvPnp","no"); + } + + /* Disable PNP config of Marvel memory controller devices. */ + env = getenv("disaMvPnp"); + if(!env) + setenv("disaMvPnp","no"); + + + + +#if (defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH)) \ + && !defined(DB_PRPMC) && !defined(DB_88F1281) && !defined(DB_MNG) + + /* MAC addresses */ + env = getenv("ethaddr"); + if(!env) + setenv("ethaddr",ETHADDR); + +#if !defined(MV_INCLUDE_TDM) && !defined(MV_INC_BOARD_QD_SWITCH) +/* ETH1ADDR not define in GWAP boards */ + env = getenv("eth1addr"); + if(!env) + setenv("eth1addr",ETH1ADDR); +#endif + +#if defined(MV_INCLUDE_TDM) + /* Set mvPhoneConfig env parameter */ + env = getenv("mvPhoneConfig"); + if(!env ) + setenv("mvPhoneConfig","mv_phone_config=dev0:fxs,dev1:fxs"); +#endif + +#if defined(MV_INC_BOARD_QD_SWITCH) + /* Set mvNetConfig env parameter */ + env = getenv("mvNetConfig"); + if(!env ) + setenv("mvNetConfig","mv_net_config=(eth0,00:aa:bb:cc:dd:ee,0)(eth1,00:11:22:33:44:55,1:2:3:4)"); +#endif +#endif /* (MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) */ + +#if defined(MV_INCLUDE_PCI) + env = getenv("pciMode"); + if(!env) + { + setenv("pciMode",ENV_PCI_MODE); + } + + env = getenv("pciMode"); + if ( env && ( (strcmp(env,"device") == 0) || (strcmp(env,"Device") == 0) )) + MV_REG_WRITE(PCI_ARBITER_CTRL_REG(0),(MV_REG_READ(PCI_ARBITER_CTRL_REG(0) & BIT31))); + +#endif /* (MV_INCLUDE_PCI) */ + +#if defined(MV_INCLUDE_USB) + + /* USB Host */ + env = getenv("usb0Mode"); + + if(!env) + { + setenv("usb0Mode",ENV_USB0_MODE); + } + + if (mvCtrlUsbMaxGet() == 2) + { + env = getenv("usb1Mode"); + + if(!env) + { + setenv("usb1Mode",ENV_USB1_MODE); + } + + } + + +#endif /* (MV_INCLUDE_USB) */ + +#if defined(YUK_ETHADDR) + + env = getenv("yuk_ethaddr"); + if(!env) + setenv("yuk_ethaddr",YUK_ETHADDR); + + { + int i; + + char *tmp = getenv ("yuk_ethaddr"); + char *end; + + for (i=0; i<6; i++) { + yuk_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end+1 : end; + + } + + } + + +#endif /* defined(YUK_ETHADDR) */ + +#if defined(RD_88F6082NAS) || defined(RD_88F6082GE_SATA) || defined(RD_88F6082DAS_PLUS) || defined(RD_88F5182_3) + mvHddPowerCtrl(); +#endif + +#if defined(RD_88F6082MICRO_DAS_NAS) + env = getenv("serialNo"); + if(!env) + setenv("serialNo","AS100352999999"); + + env = getenv("fanPowerCtrl"); + if(!env) + setenv("fanPowerCtrl","Yes"); + + env = getenv("minTemp"); + if(!env) + setenv("minTemp","45"); + + env = getenv("maxTemp"); + if(!env) + setenv("maxTemp","50"); + + env = getenv("enaPost"); + if(!env) + setenv("enaPost","No"); + + bootDetection(); +#endif + return; +} + +#ifdef BOARD_LATE_INIT +int board_late_init (void) +{ + /* Check if to use the LED's for debug or to use single led for init and Linux heartbeat */ + mvStatusDebugLeds(0); + + return 0; +} +#endif + +int misc_init_r (void) +{ + char name[15]; + char *env; + volatile unsigned int temp; + + mvStatusDebugLeds(5); + + /* set as 946 */ + env = getenv("cpuName"); + if(!env) + setenv("cpuName","926"); + else + { + if (strcmp(env,"946") == 0) + { + /* set as 946 */ + unsigned int regVal; + + regVal = MV_REG_READ(CPU_CONFIG_REG); + regVal |= CCR_MMU_DISABLED; + MV_REG_WRITE(CPU_CONFIG_REG, regVal); + } + + } + + mvCpuNameGet(name); + printf("\nCPU : %s\n", name); + + /* init special env variables */ + misc_init_r_env(); + + mv_cpu_init(); + +#if defined(MV_INCLUDE_MONT_EXT) + if(enaMonExt()){ + printf("\n Marvell monitor extension:\n"); + mon_extension_after_relloc(); + } + printf("\n"); +#endif /* MV_INCLUDE_MONT_EXT */ + + /* init the units decode windows */ + misc_init_r_dec_win(); + +#ifdef CONFIG_PCI +#if !defined(MV_MEM_OVER_PCI_WA) + pci_init(); +#endif +#endif + + mvStatusDebugLeds(6); + + if((mvCtrlModelGet() == MV_5281_DEV_ID) || /* Orion 2 */ + (mvCtrlModelGet() == MV_1281_DEV_ID)) /* TC90 */ + { + + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + if (temp & 0x10000000) + { + printf("CPU: Write allocate enabled\n"); + } + else + { + printf("CPU: Write allocate Disabled\n"); + } + } + + mvStatusDebugLeds(7); + + return 0; +} + +MV_U32 mvTclkGet(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* get it only on first time */ + if(gd->tclk == 0) + gd->tclk = mvBoardTclkGet(); + + return gd->tclk; +} + +MV_U32 mvSysClkGet(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* get it only on first time */ + if(gd->bus_clk == 0) + gd->bus_clk = mvBoardSysClkGet(); + + return gd->bus_clk; +} + +#ifndef MV_TINY_IMAGE +/* exported for EEMBC */ +MV_U32 mvGetRtcSec(void) +{ + MV_RTC_TIME time; + mvRtcDS133xTimeGet(&time); + return (time.minutes * 60) + time.seconds; +} +#endif + +void reset_cpu(void) +{ + mvBoardReset(); +} + + +void mv_cpu_init(void) +{ + char *env; + char name[20]; + volatile unsigned int temp; + + /*CPU streaming */ + if( (mvCtrlModelGet() == MV_5181_DEV_ID) || + (mvCtrlModelGet() == MV_5182_DEV_ID) || + (mvCtrlModelGet() == MV_5180_DEV_ID) || + (mvCtrlModelGet() == MV_8660_DEV_ID) || + (mvCtrlModelGet() == MV_5082_DEV_ID) ) /* orion 1 */ + { + + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 0" : "=r" (temp):: "memory"); + + env = getenv("enaCpuStream"); + if(!env || (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) + { + mvCtrlModelRevNameGet(name); + printf("%s streaming disabled \n",name); + temp &= ~BIT28; + } + else + { + printf("Orion 1 streaming enabled \n"); + temp |= BIT28; + } + + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 0": :"r" (temp)); + + } + else if((mvCtrlModelGet() == MV_5281_DEV_ID) || /* Orion 2 */ + (mvCtrlModelGet() == MV_6183_DEV_ID) || /* Orion 6183 */ + (mvCtrlModelGet() == MV_6183L_DEV_ID) || /* Orion 6183L */ + (mvCtrlModelGet() == MV_1281_DEV_ID)) /* TC90 */ + { + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + + env = getenv("enaCpuStream"); + if(!env || (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) + { + printf("Streaming disabled \n"); + temp &= ~BIT29; + } + else + { + printf("Streaming enabled \n"); + temp |= BIT29; + } + + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + + + if (mvCtrlModelGet() == MV_5281_DEV_ID) /* Orion 2 */ + { + + env = getenv("mainlineLinux"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + if (mvCtrlRevGet() == MV_5281_D2_REV) /* Orion 2 D2 */ + { + /* Change CPU ID to Marvell */ + MV_REG_BIT_SET(CPU_FTDLL_CONFIG_REG, CFCR_FTDLL_OVERWRITE_ENABLE); + MV_REG_BIT_SET(CPU_FTDLL_CONFIG_REG, CFCR_MRVL_CPU_ID); + MV_REG_BIT_RESET(CPU_FTDLL_CONFIG_REG, CFCR_FTDLL_OVERWRITE_ENABLE); + + /* Change VFP ID to Marvell */ + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + temp |= BIT31; + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + } + + if (mvCtrlRevGet() == MV_5281_A0_REV) /* Orion 2 A0 */ + { +#ifndef DB_FPGA + env = getenv("enaVFP"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + /* init VFP to Run Fast Mode */ + printf("VFP initialized to Run Fast Mode.\n"); + temp = fmrx(FPSCR); + temp |= (FPSCR_DEFAULT_NAN | FPSCR_FLUSHTOZERO); + fmxr(FPSCR, temp); + } + else +#endif /* DB_FPGA */ + { + printf("VFP not initialized\n"); + } + + } + else if (mvCtrlRevGet() >= MV_5281_B0_REV)/* Orion 2 >= B0 */ + { +#ifndef DB_FPGA + env = getenv("enaVFP"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + /* Orion 2 D2 has VFP sub arch */ + if (mvCtrlRevGet() >= MV_5281_D2_REV)/* Orion 2 >= D2 */ + { + env = getenv("vfpSubArch2"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET(CPU_FTDLL_CONFIG_REG, CFCR_FTDLL_OVERWRITE_ENABLE); + MV_REG_BIT_SET(CPU_FTDLL_CONFIG_REG, CFCR_VFP_SUB_ARC_NUM_2); + MV_REG_BIT_RESET(CPU_FTDLL_CONFIG_REG, CFCR_FTDLL_OVERWRITE_ENABLE); + } + } + + /* init and Enable VFP to Run Fast Mode */ + printf("VFP initialized to Run Fast Mode.\n"); + /* Enable */ + temp = FPEXC_ENABLE; + fmxr(FPEXC, temp); + /* Run Fast Mode */ + temp = fmrx(FPSCR); + temp |= (FPSCR_DEFAULT_NAN | FPSCR_FLUSHTOZERO); + fmxr(FPSCR, temp); + } + else +#endif /* DB_FPGA */ + { + printf("VFP not initialized\n"); + /* Disable */ + temp = fmrx(FPEXC); + temp &= ~FPEXC_ENABLE; + fmxr(FPEXC, temp); + } + + /* DCache Pref */ + env = getenv("enaDCPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + + /* ICache Pref */ + env = getenv("enaICPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + } + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + + } + + } + + /* write allocate */ + env = getenv("enaWrAllo"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + temp |= BIT28; + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + else + { + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + temp &= ~BIT28; + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + } + + if (mvCtrlModelGet() == MV_6183_DEV_ID || + mvCtrlModelGet() == MV_6183L_DEV_ID) /* MV88F6183 & MV88F6183L*/ + { + /* DCache Pref */ + env = getenv("enaDCPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + + /* ICache Pref */ + env = getenv("enaICPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + } + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + + } + + /* write allocate */ + env = getenv("enaWrAllo"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + temp |= BIT28; + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + else + { + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + temp &= ~BIT28; + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + } + + if (mvCtrlModelGet() == MV_1281_DEV_ID) /* TC90 */ + { + env = getenv("enaVFP"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + /* init and Enable VFP to Run Fast Mode */ + printf("VFP initialized to Run Fast Mode.\n"); + /* Enable */ + temp = FPEXC_ENABLE; + fmxr(FPEXC, temp); + + /* Run Fast Mode */ + temp = fmrx(FPSCR); + temp |= (FPSCR_DEFAULT_NAN | FPSCR_FLUSHTOZERO); + + fmxr(FPSCR, temp); + } + else + { + printf("VFP not initialized\n"); + /* Disable */ + temp = fmrx(FPEXC); + temp &= ~FPEXC_ENABLE; + fmxr(FPEXC, temp); + } + + /* DCache Pref */ + env = getenv("enaDCPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_DCACH_PREF_BUF_ENABLE); + } + + /* ICache Pref */ + env = getenv("enaICPref"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + MV_REG_BIT_SET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + } + if(env && ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + MV_REG_BIT_RESET( CPU_CONFIG_REG , CCR_ICACH_PREF_BUF_ENABLE); + } + + /* write allocate */ + env = getenv("enaWrAllo"); + if(env && ((strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0))) + { + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + temp |= BIT28; + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + else + { + __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0" : "=r" (temp):: "memory"); + temp &= ~BIT28; + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0" :: "r" (temp)); + } + } +} + +/* Set unit in power off mode acording to the env powerOffUnit */ +/* Env powerOffUnit can has the following value: giga0, giga1, */ +/* pex0, pex1, usb0, usb1, sata0, sata1, cesa, none */ +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +static int mv_set_power_scheme(void) +{ + char *env; + env = getenv("powerOffUnit"); + if(!env || (strcmp(env,"none") == 0)) + { + setenv("powerOffUnit", "none"); + return MV_OK; + } + + env = getenv("powerOffUnit"); +#if defined(MV_INCLUDE_PEX) + if (strcmp(env,"pex0") == 0) + { + printf("Warning: Pex0 is Powered Off\n"); + mvPexPowerDown(0); + mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_FALSE); + } + else + if (strcmp(env,"pex1") == 0) + { + printf("Warning: Pex1 is Powered Off\n"); + mvPexPowerDown(1); + mvCtrlPwrClckSet(PEX_UNIT_ID, 1, MV_FALSE); + } + else +#endif /* #if defined(MV_INCLUDE_PEX) */ +#if defined(MV_INCLUDE_INTEG_SATA) + if (strcmp(env,"sata0") == 0) + { + printf("Warning: SATA0 is Powered Off\n"); + mvSataPhyShutdown(0); + mvCtrlPwrClckSet(SATA_UNIT_ID, 0, MV_FALSE); + } + else + if (strcmp(env,"sata1") == 0) + { + printf("Warning: SATA1 is Powered Off\n"); + mvSataPhyShutdown(1); + mvCtrlPwrClckSet(SATA_UNIT_ID, 1, MV_FALSE); + } + else +#endif/*#if defined(MV_INCLUDE_SATA) */ +#if defined(MV_INCLUDE_GIG_ETH) + if (strcmp(env,"giga0") == 0) + { + printf("Warning: Giga0 and Giga1 is Powered Off\n"); + mvEthPortPowerDown(0); + mvCtrlPwrClckSet(ETH_GIG_UNIT_ID, 0, MV_FALSE); + mvEthPortPowerDown(1); + mvCtrlPwrClckSet(ETH_GIG_UNIT_ID, 1, MV_FALSE); + } + else + if (strcmp(env,"giga1") == 0) + { + printf("Warning: Giga1 is Powered Off\n"); + mvEthPortPowerDown(1); + mvCtrlPwrClckSet(ETH_GIG_UNIT_ID, 1, MV_FALSE); + } + else +#endif /* #if defined(MV_INCLUDE_GIG_ETH) */ +#if defined(MV_INCLUDE_CESA) + if (strcmp(env,"cesa") == 0) + { + printf("Warning: CESA is Powered Off\n"); + mvCtrlPwrClckSet(CESA_UNIT_ID, 1, MV_FALSE); + } + else +#endif /* if defined(MV_INCLUDE_CESA) */ +#if defined(MV_INCLUDE_USB) + if (strcmp(env,"usb0") == 0) + { + printf("Warning: USB0 is Powered Off\n"); + mvUsbPowerDown(0); + mvCtrlPwrClckSet(USB_UNIT_ID, 0, MV_FALSE); + } + else + if (strcmp(env,"usb1") == 0) + { + printf("Warning: USB1 is Powered Off\n"); + mvUsbPowerDown(1); + mvCtrlPwrClckSet(USB_UNIT_ID, 1, MV_FALSE); + } +#endif/*#if defined(MV_INCLUDE_USB)*/ + + return MV_OK; +} + +#endif /* defined(MV_INCLUDE_CLK_PWR_CNTRL) */ + +/******************************************************************************* +* mvUpdateNorFlashBaseAddrBank - +* +* DESCRIPTION: +* This function update the CFI driver base address bank with on board NOR +* devices base address. +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* None +* +*******************************************************************************/ +#ifdef CFG_FLASH_CFI_DRIVER +MV_VOID mvUpdateNorFlashBaseAddrBank(MV_VOID) +{ + + MV_U32 devBaseAddr; + MV_U32 devNum = 0; + int i; + + /* Update NOR flash base address bank for CFI flash init driver */ + for (i = 0 ; i < CFG_MAX_FLASH_BANKS_DETECT; i++) + { + devBaseAddr = mvBoardGetDeviceBaseAddr(i,BOARD_DEV_NOR_FLASH); + if (devBaseAddr != 0xFFFFFFFF) + { + flash_add_base_addr (devNum, devBaseAddr); + devNum++; + } + } + mv_board_num_flash_banks = devNum; + + /* Update SPI flash count for CFI flash init driver */ + /* Assumption only 1 SPI flash on board */ + for (i = 0 ; i < CFG_MAX_FLASH_BANKS_DETECT; i++) + { + devBaseAddr = mvBoardGetDeviceBaseAddr(i,BOARD_DEV_SPI_FLASH); + if (devBaseAddr != 0xFFFFFFFF) + mv_board_num_flash_banks += 1; + } + + if (mvCtrlModelGet() == MV_6082_DEV_ID) + /* Add internal MFlash to NOR devices */ + mv_board_num_flash_banks += 1; + +} +#endif /* CFG_FLASH_CFI_DRIVER */ + +/******************************************************************************* +* mvStatusDebugLeds - +* +* DESCRIPTION: +* This function update the 7 segment or the debug/status LED +* +* +* INPUT: +* num - number to display over the 7 segment +* OUTPUT: +* +* RETURN: +* None +* +*******************************************************************************/ +static void mvStatusDebugLeds(char num) +{ + char* env; + + env = getenv("enaDebugLed"); + if(!env || ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + { + mvBoardStatusLed(MV_TRUE); + } + else + mvBoardDebug7Seg(num); +} + +/******************************************************************************* +* mvHddPowerCtrl - +* +* DESCRIPTION: +* This function set HDD power on/off acording to env or wait for button push +* INPUT: +* None +* OUTPUT: +* None +* RETURN: +* None +* +*******************************************************************************/ +#if defined(RD_88F6082NAS) || defined(RD_88F6082GE_SATA) || defined(RD_88F6082DAS_PLUS) || defined(RD_88F5182_3) +static void mvHddPowerCtrl(void) +{ + + MV_32 hddPowerBit = mvBoarGpioPinNumGet(BOARD_DEV_HDD0_POWER); + MV_32 extHddPowerBit = mvBoarGpioPinNumGet(BOARD_DEV_HDD1_POWER); + MV_32 hddBottenBit = mvBoarGpioPinNumGet(BOARD_DEV_POWER_BUTTON); + char* env; + + + if ((RD_88F6082_NAS == mvBoardIdGet()) || + (RD_88F5182_2XSATA3 == mvBoardIdGet())) + { + env = getenv("hddPowerCtrl"); + if(!env || ( (strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ) ) + setenv("hddPowerCtrl","no"); + else + setenv("hddPowerCtrl","yes"); + + /* #include "mvGpp.h" */ + /* GPIO / Leds / and Power button handling */ + + env = getenv("hddPowerCtrl"); + if(env && ( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ) ) + { + /* Set HDD input indication pin as input */ + MV_REG_BIT_SET(GPP_DATA_OUT_EN_REG(0),(1< 5) break; + + }while (1); + + + /* Clear Interrupt cause */ + MV_REG_BIT_RESET(GPP_INT_CAUSE_REG(0),(1 << powerBottenBit)); + + /* Disable interrupt */ + MV_REG_BIT_RESET(GPP_INT_MASK_REG(0),(1 << powerBottenBit) ); + + + /* Call system power up */ + mv6082uDasNasSysPower(MV_TRUE); + } + } + else + { + /* U-boot is running after power-up */ + /* Check restor botten push */ + /* Set restor input indication pin as input */ + MV_REG_BIT_SET(GPP_DATA_OUT_EN_REG(0),(1<> 4)) +#define NAND_ADDR_PORT (0x2 << (NFLASH_DEV_WIDTH >> 4)) + +/* NAND Flash Chip Capability */ +#ifdef MV_LARGE_PAGE +#define NUM_BLOCKS 2048 +#define PAGES_PER_BLOCK 64 +#define PAGE_SIZE 2048 /* Bytes */ +#define SPARE_SIZE 64 +#define CFG_NAND_PAGE_SIZE (2048) /* NAND chip page size */ +#define CFG_NAND_BLOCK_SIZE (128 << 10) /* NAND chip block size */ +#define CFG_NAND_PAGE_COUNT (64) /* NAND chip page count */ +#define CFG_NAND_BAD_BLOCK_POS (0) /* Location of bad block marker */ + +#define CFG_NAND_U_BOOT_OFFS CFG_MONITOR_BASE /* Offset to U-Boot image */ +#define CFG_NAND_U_BOOT_SIZE CFG_MONITOR_LEN /* Size of RAM U-Boot image */ +#define CFG_NAND_U_BOOT_DST CFG_MONITOR_IMAGE_DST /* Load NUB to this addr */ +#define CFG_NAND_U_BOOT_START CFG_NAND_U_BOOT_DST /* Start NUB from this addr */ + +#else /* ! LARGE PAGE NAND */ +/* NAND Flash Chip Capability */ +#define NUM_BLOCKS 2048 +#define PAGES_PER_BLOCK 32 +#define PAGE_SIZE 512 /* Bytes */ +#define SPARE_SIZE 16 +#define CFG_NAND_PAGE_SIZE (512) /* NAND chip page size */ +#define CFG_NAND_BLOCK_SIZE (16 << 10) /* NAND chip block size */ +#define CFG_NAND_PAGE_COUNT (32) /* NAND chip page count */ +#define CFG_NAND_BAD_BLOCK_POS (5) /* Location of bad block marker */ + +#define CFG_NAND_U_BOOT_OFFS CFG_MONITOR_BASE /* Offset to U-Boot image */ +#define CFG_NAND_U_BOOT_SIZE CFG_MONITOR_LEN /* Size of RAM U-Boot image */ +#define CFG_NAND_U_BOOT_DST CFG_MONITOR_IMAGE_DST /* Load NUB to this addr */ +#define CFG_NAND_U_BOOT_START CFG_NAND_U_BOOT_DST /* Start NUB from this addr */ + +#endif + +/* NAND Flash Command. This appears to be generic across all NAND flash chips */ +#define CMD_READ 0x00 /* Read */ +#define CMD_READ1 0x01 /* Read1 */ +#define CMD_READ2 0x50 /* Read2 */ +#define CMD_START_READ 0x30 /* Read command after write addr */ +#define CMD_READID 0x90 /* ReadID */ +#define CMD_READID2 0x91 /* Read extended ID */ +#define CMD_WRITE 0x80 /* Write phase 1 */ +#define CMD_WRITE2 0x10 /* Write phase 2 */ +#define CMD_ERASE 0x60 /* Erase phase 1 */ +#define CMD_ERASE2 0xd0 /* Erase phase 2 */ +#define CMD_STATUS 0x70 /* Status read */ +#define CMD_RESET 0xff /* Reset */ + +/* Status bit pattern */ +#define STATUS_READY 0x40 /* Ready */ +#define STATUS_ERROR 0x01 /* Error */ + + +#define NFLASH_DEV_WIDTH 8 +#ifdef MV_LARGE_PAGE +#define BOOTER_PAGE_NUM 2 +#define BOOTER_BASE 0x00020000 + PAGE_SIZE +#else +#define BOOTER_PAGE_NUM 5 +#define BOOTER_BASE 0x00020000 + (3 * PAGE_SIZE) +#endif /* MV_LARGE_PAGE */ +#define BOOTER_END (BOOTER_BASE + (BOOTER_PAGE_NUM * PAGE_SIZE)) + +#undef INTER_REGS_BASE +#define INTER_REGS_BASE 0xd0000000 + + +#if defined(MV_BOOTROM) +#if defined(MV_88F6082) +#define NAND_FLASH_BASE 0xD8000000 +#endif +#if defined(MV_88F5182) +#define NAND_FLASH_BASE 0xf0000000 +#endif +#else +#define NAND_FLASH_BASE 0xffff0000 +#endif /* defined(MV_BOOTROM) */ + +#if 0 +#if defined(MV_BOOTROM) +#define UBOOT_IMAGE_OFFS 0x4000 /* Uboot starts on block 1 */ +#define UBOOT_IMAGE_SIZE 0x80000 /* 1/2 MB of Uboot */ +#define UBOOT_IMAGE_DEST 0x200000 +#define UBOOT_IMAGE_ENV_OFFS 0x84000 /* Uboot starts on block 1 */ +#define UBOOT_IMAGE_ENV_SIZE 0x4000 +#define UBOOT_IMAGE_ENV_DEST 0x300000 - UBOOT_IMAGE_ENV_SIZE +#else +#define UBOOT_IMAGE_OFFS 0x24000 /* Uboot starts on block 1 */ +#define UBOOT_IMAGE_SIZE 0x80000 /* 1/2 MB of Uboot */ +#define UBOOT_IMAGE_DEST 0x200000 +#define UBOOT_IMAGE_ENV_OFFS UBOOT_IMAGE_OFFS - 0x20000 /* Uboot starts on block 1 */ +#define UBOOT_IMAGE_ENV_SIZE 0x4000 +#define UBOOT_IMAGE_ENV_DEST 0x300000 - UBOOT_IMAGE_ENV_SIZE +#endif /* defined(MV_BOOTROM) */ +#endif + +#define NBOOT_UART_CHAN 0 +#define NBOOT_BAUDRATE 115200 +#define NBOOT_TIMER_NUM 0 + + +/* CPU config register (0x20100) bit[15:8] value for CPU to DDR clock ratio */ +#define CPU_2_MBUSL_DDR_CLK 0x0000 /* clock ratio 1x2 */ +/* #define CPU_2_MBUSL_DDR_CLK 0x2100 *//* clock ratio 1x3 */ +/* #define CPU_2_MBUSL_DDR_CLK 0x2200 *//* clock ratio 1x4 */ + +/* Load General Purpose Register (GPR) with 32-bit constant value */ +#define GPR_LOAD(reg, val) \ + mov reg, $(val & 0xFF) ;\ + orr reg, reg, $(val & 0xFF00) ;\ + orr reg, reg, $(val & 0xFF0000) ;\ + orr reg, reg, $(val & 0xFF000000) + +/* Register Read/Write */ +#define MV_REG_READ_ASM(toReg, baseReg, regOffs) \ + ldr toReg, [baseReg, $(regOffs & 0xFFF)] + +#define MV_REG_WRITE_ASM(fromReg, baseReg, regOffs) \ + str fromReg, [baseReg, $(regOffs & 0xFFF)] + + +/* 32bit byte swap. For example 0x11223344 -> 0x44332211 */ +#define MV_BYTE_SWAP_32BIT(X) ((((X)&0xff)<<24) | \ + (((X)&0xff00)<<8) | \ + (((X)&0xff0000)>>8) | \ + (((X)&0xff000000)>>24)) +/* Endianess macros. */ +#if defined(MV_CPU_LE) + #define MV_32BIT_LE(X) (X) + #define MV_32BIT_BE(X) MV_BYTE_SWAP_32BIT(X) +#elif defined(MV_CPU_BE) + #define MV_32BIT_LE(X) MV_BYTE_SWAP_32BIT(X) + #define MV_32BIT_BE(X) (X) +#else + #error "CPU endianess isn't defined!\n" +#endif + +#endif /* __INCnBootstraph */ diff --git a/board/mv_feroceon/mv_orion/nBootstrap_LP.S b/board/mv_feroceon/mv_orion/nBootstrap_LP.S new file mode 100644 index 0000000..1769e95 --- /dev/null +++ b/board/mv_feroceon/mv_orion/nBootstrap_LP.S @@ -0,0 +1,335 @@ +#define MV_ASMLANGUAGE +#include "mvDramIfRegs.h" +#include "mvDramIfConfig.h" +#include "nBootstrap.h" + + +/* #define NAND_DEBUG */ +#if !defined(MV_BOOTROM) +.globl nbootStart +nbootStart: + /* + * set the cpu to SVC32 mode, I and F disabled. + */ + mov r1, #0xd3 + msr cpsr,r1 + + /* + * flush v4 I/D caches + */ + mcr p15, 0, r1, c7, c7, 0 /* invalidate v3/v4 cache */ + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r1, c1, c0, 0 + bic r1, r1, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r1, r1, #0x00000007 /* clear bits 2:0 (-CAM) */ + orr r1, r1, #0x00001000 /* set bit 12 (I) I-Cache */ + /* MUST BE PLACED AT END OF CACHE LINE!!!!!!!!!!!!!!! */ + mcr p15, 0, r1, c1, c0, 0 + + /* Add nop commands for cache flush operations */ + nop + nop + nop + nop + nop + /* here. MUST BE IN THE SAME CACHE LINE */ + + mov r0, #0 /* We use r0 as always '0' */ + +#ifdef NAND_CTRL_88F528x + + /* Load CPU controller base address 0xD0020000 */ + mov r2, #0xd0000000 + orr r2, r2, #0x20000 + + MV_REG_READ_ASM (r1, r2, 0x20120) + bic r1, r1, #MV_32BIT_LE(0x7F00) + orr r1, r1, #MV_32BIT_LE(0x8200) + bic r1, r1, #MV_32BIT_LE(0x007F) + orr r1, r1, #MV_32BIT_LE(0x001b) + MV_REG_WRITE_ASM(r1, r2, 0x20120) + + /* Set CPU to Mbus-L DDR Interface Tick Driver and Tick Sample */ + MV_REG_READ_ASM (r1, r2, 0x20100) + bic r1, r1, #MV_32BIT_LE(0xFF00) + orr r1, r1, #MV_32BIT_LE(CPU_2_MBUSL_DDR_CLK) + MV_REG_WRITE_ASM(r1, r2, 0x20100) + +#endif /* NAND_CTRL_88F528x */ + + /* lock I-Cache */ + mrc p15, 0, r8, c9, c0, 1 + orr r8, r8, #0xf + mcr p15, 0, r8, c9, c0, 1 + + /* Start load code into I-Cache */ + mov r2, #0x500 + mov r8, pc +.align 5 + bic r8, #0x1f + add r8, r8, #32 +load_loop: + mcr p15, 0, r8, c7, c13, 1 + add r8, r8, #32 /* 8 dwords * 4 bytes */ + sub r2, r2, #32 /* 8 dwords * 4 bytes */ + cmp r2, #0 /* check if we have read a full Page */ + bne load_loop + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0xf0ffffff + MV_REG_WRITE_ASM(r1, r2, 0x104) + mov r1, #0x1000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + + /* DRAM memory initialization */ + /* Load SDRAM controller base address 0xd0001000 */ + mov r2, #0xd0000000 + orr r2, r2, #0x1000 + + /* Write to SDRAM coniguration register */ +#ifndef MV_88W8660 + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_CONFIG_REG_DV)) +#else + GPR_LOAD(r1, MV_32BIT_LE((SDRAM_CONFIG_REG_DV & ~(0x40)))) +#endif /* MV_88W8660 */ + MV_REG_WRITE_ASM(r1, r2, SDRAM_CONFIG_REG) + + /* Write Dunit control low register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_DUNIT_CTRL_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_DUNIT_CTRL_REG) + + /* Write SDRAM address control register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_ADDR_CTRL_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_ADDR_CTRL_REG) + + /* Write SDRAM timing Low register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_TIMING_CTRL_LOW_REG_DVAL)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_TIMING_CTRL_LOW_REG) + + /* Write SDRAM timing High register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_TIMING_CTRL_HIGH_REG_DVAL)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_TIMING_CTRL_HIGH_REG) + + /* Write SDRAM mode register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_MODE_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_MODE_REG) + + /* Write SDRAM Extended mode register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_EXTENDED_MODE_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_EXTENDED_MODE_REG) + + /* Config DDR2 registers pad calibration */ + MV_REG_READ_ASM (r1, r2, SDRAM_CONFIG_REG) + tst r1, #SDRAM_DTYPE_DDR2 + beq ddr1PadCal + + /* Config DDR2 On Die Termination (ODT) registers */ + GPR_LOAD(r1, MV_32BIT_LE(DDR2_SDRAM_ODT_CTRL_LOW_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, DDR2_SDRAM_ODT_CTRL_LOW_REG) + + /* Write SDRAM DDR2 ODT control high register */ + GPR_LOAD(r1, MV_32BIT_LE(DDR2_SDRAM_ODT_CTRL_HIGH_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, DDR2_SDRAM_ODT_CTRL_HIGH_REG) + + /* Write SDRAM DDR2 Dunit ODT control register */ + GPR_LOAD(r1, MV_32BIT_LE(DDR2_DUNIT_ODT_CTRL_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, DDR2_DUNIT_ODT_CONTROL_REG) + + mov r3, #MV_32BIT_LE(DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV) + mov r4, #MV_32BIT_LE(DDR2_DATA_PAD_STRENGTH_TYPICAL_DV) + b next + +ddr1PadCal: + mov r3, #MV_32BIT_LE(DDR1_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV) + mov r4, #MV_32BIT_LE(DDR1_DATA_PAD_STRENGTH_TYPICAL_DV) + +next: + /* Implement Guideline (GL# MEM-3) Drive Strength Value */ + /* Relevant for: 88F5181-A1/B0/B1 and 88F5281-A0/B0 */ + /* DDR SDRAM Address/Control Pads Calibration */ + MV_REG_READ_ASM (r1, r2, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + orr r5, r1, #MV_32BIT_LE(SDRAM_WR_EN) /* Make register writeable */ + + MV_REG_WRITE_ASM (r5, r2, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + orr r1, r3, r1 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r1, r2, SDRAM_ADDR_CTRL_PADS_CAL_REG) + + + /* DDR SDRAM Data Pads Calibration */ + MV_REG_READ_ASM (r1, r2, SDRAM_DATA_PADS_CAL_REG) + + orr r5, r1, #MV_32BIT_LE(SDRAM_WR_EN) /* Make register writeable */ + + MV_REG_WRITE_ASM (r5, r2, SDRAM_DATA_PADS_CAL_REG) + + orr r1, r4, r1 /* Set default value for DDR */ + + MV_REG_WRITE_ASM (r1, r2, SDRAM_DATA_PADS_CAL_REG) + +#ifndef MV_88W8660 + /* Write Dunit FTDLL Configuration Register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_FTDLL_CONFIG_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_FTDLL_CONFIG_REG) +#endif /* MV_88W8660 */ + + /* DDR SDRAM Initialization Control Register. Init enable */ + mov r1, #MV_32BIT_LE(DSICR_INIT_EN) + MV_REG_WRITE_ASM (r1, r2, DDR_SDRAM_INIT_CTRL_REG) + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0x2000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + +ddrInitLoop: + MV_REG_READ_ASM (r1, r2, DDR_SDRAM_INIT_CTRL_REG) + cmp r1, #0 + bne ddrInitLoop + + /* Load back SDRAM controller base address 0xd0001000 */ + mov r2, #0xd0000000 + orr r2, r2, #0x1000 + + /* Open SDRAM bank 0 size register */ + GPR_LOAD(r1, MV_32BIT_LE(SDRAM_SIZE_REG_DV)) + MV_REG_WRITE_ASM(r1, r2, SDRAM_SIZE_REG(0)) + + /* Close SDRAM bank 1,2,3 */ + MV_REG_WRITE_ASM(r0, r2, SDRAM_SIZE_REG(1)) + MV_REG_WRITE_ASM(r0, r2, SDRAM_SIZE_REG(2)) + MV_REG_WRITE_ASM(r0, r2, SDRAM_SIZE_REG(3)) + + /* Prepare the address where to find the nandBoot function pointer */ + mov lr, #BOOTER_BASE + +#ifdef DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0x2000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + + /* init */ + mov r2, #0x1 /* start with page 1 */ + mov r3, #BOOTER_BASE /* start of DRAM buffer */ + GPR_LOAD(r5, NAND_FLASH_BASE) + +cp_page_loop: + mov r0, #0 + mov r6, #CMD_READ + mov r7, #CMD_START_READ + mov r9, #CMD_RESET + mov r4, #PAGE_SIZE /* Byte counter */ + + +startRead: + /* issue reset command */ + strb r9, [r5, #NAND_CMD_PORT] + + mov r9, #0x1000000 +loop_delay1: + sub r9, r9, #1 + cmp r9, #0 + bne loop_delay1 + + /* issue read command */ + strb r6, [r5, #NAND_CMD_PORT] + + /* issue address */ + strb r0, [r5, #NAND_ADDR_PORT] + strb r0, [r5, #NAND_ADDR_PORT] + strb r2, [r5, #NAND_ADDR_PORT] /* page address */ + strb r0, [r5, #NAND_ADDR_PORT] + strb r0, [r5, #NAND_ADDR_PORT] + strb r7, [r5, #NAND_CMD_PORT] + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r6, #0xd0000000 + orr r6, r6, #0x10000 + mov r1, #0x3000000 + MV_REG_WRITE_ASM(r1, r6, 0x100) +#endif + /* Delay of at least 25uSec (NAND flash tR) */ + mov r9, #0x1000000 +loop_delay3: + sub r9, r9, #1 + cmp r9, #0 + bne loop_delay3 + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r6, #0xd0000000 + orr r6, r6, #0x10000 + mov r1, #0x4000000 + MV_REG_WRITE_ASM(r1, r6, 0x100) +#endif + + /* now perform reading */ + mov r0, r5 + +copy_loop1: + sub r4, r4, #16 /* 4 dwords * 4 bytes */ + ldmia r0!, {r6-r9} + stmia r3!, {r6-r9} + + cmp r4, #0 /* check if we have read a full Page */ + bne copy_loop1 + +nextPage: + add r2, r2, #1 /* increment page number */ + cmp r2, #BOOTER_PAGE_NUM + bne cp_page_loop + +#ifdef NAND_DEBUG + /* GPP initialization */ + mov r2, #0xd0000000 + orr r2, r2, #0x10000 + mov r1, #0x5000000 + MV_REG_WRITE_ASM(r1, r2, 0x100) +#endif + + /* Set up the stack */ +stack_setup: + mov r0, #BOOTER_BASE + sub sp, r0, #12 /* leave 3 words for abort-stack */ + /* jump to new code */ + mov pc, lr + +.align 10 +/* This is known to be address (BOOTER_BASE + 2 * PAGE_SIZE) */ +_nandBootPtr: + .word nand_boot + +#else /* MV_BOOTROM */ + +.globl nbootStart +nbootStart: + /* Enable I-Cache */ + mrc p15, 0, r1, c1, c0, 0 + orr r1, r1, #0x00001000 /* set bit 12 (I) I-Cache */ + /* MUST BE PLACED AT END OF CACHE LINE!!!!!!!!!!!!!!! */ + mcr p15, 0, r1, c1, c0, 0 + + /* Set up the stack */ + mov r0, #BOOTER_BASE + sub sp, r0, #12 /* leave 3 words for abort-stack */ + + /* jump to new code */ + + ldr lr, =nandBoot + mov pc, lr +#endif /* !defined(MV_BOOTROM) */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.c new file mode 100644 index 0000000..a013cb8 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.c @@ -0,0 +1,132 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#define DB_88F1281_BOARD_PCI_IF_NUM 0x0 +#define DB_88F1281_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F1281_BOARD_MAC_INFO_NUM 0x0 +#define DB_88F1281_BOARD_GPP_INFO_NUM 0x1 +#define DB_88F1281_BOARD_DEBUG_LED_NUM 0x4 +#define DB_88F1281_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F1281_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 db88f1281ddr2InfoBoardDebugLedIf[DB_88F1281_BOARD_DEBUG_LED_NUM] = + {2, 3, 6, 7}; + +MV_BOARD_TWSI_INFO db88f1281ddr2InfoBoardTwsiDev[DB_88F1281_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_GPP_INFO db88f1281ddr2InfoBoardGppInfo[DB_88F1281_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 1}}; + +MV_BOARD_MPP_INFO db88f1281ddr2InfoBoardMppConfigValue[DB_88F1281_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F1281_DDR2_MPP0_7, /* mpp0_7 */ + DB_88F1281_DDR2_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +#if defined(MV_NAND) +MV_DEV_CS_INFO db88f1281ddr2InfoBoardDeCsInfo[DB_88F1281_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}, /* devCs2/NandCs */ + { 1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ +#else +MV_DEV_CS_INFO db88f1281ddr2InfoBoardDeCsInfo[DB_88F1281_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 0, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs2/flashCs */ + { 1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ +#endif /* defined(MV_NAND) */ + +MV_BOARD_INFO db88f1281ddr2Info = { + "DB-88F1281-DDR2", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F1281_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f1281ddr2InfoBoardMppConfigValue, + ((1 << 1)), /* intsGppMask */ + DB_88F1281_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f1281ddr2InfoBoardDeCsInfo, + DB_88F1281_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + DB_88F1281_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f1281ddr2InfoBoardTwsiDev, + DB_88F1281_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + NULL, + DB_88F1281_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f1281ddr2InfoBoardGppInfo, + DB_88F1281_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f1281ddr2InfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + DB_88F1281_DDR2_OE, /* gppOutEnVal */ + DB_88F1281_DDR2_OE_VAL, /* gppOutVal */ + 0x1 /* gppPolarityVal */ +}; + + +MV_BOARD_INFO* boardInfoTbl[1] = {&db88f1281ddr2Info, + }; + + +#define BOARD_ID_BASE BOARD_ID_88F1281_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F1281_MAX diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.h new file mode 100644 index 0000000..28c0e80 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F1281BoardEnv.h @@ -0,0 +1,85 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F1281EnvSpech +#define __INCmvBoard88F1281EnvSpech + + +/* 88F1281 based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88F1281_BASE 0x60 + +/* New board ID numbers */ +#define DB_88F1281_DDR2 (BOARD_ID_88F1281_BASE+0x0) +#define BOARD_ID_88F1281_MAX (BOARD_ID_88F1281_BASE+0x1) + + + +#define DB_88F1281_DDR2_MPP0_7 0x00110011 +#define DB_88F1281_DDR2_MPP8_15 0x11111111 +#define DB_88F1281_DDR2_OE 0xFFFFFF33 +#define DB_88F1281_DDR2_OE_VAL 0x0 + +#endif /* __INCmvBoard88F1281EnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.c new file mode 100644 index 0000000..372b6bd --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.c @@ -0,0 +1,272 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#define DB_88F5082_BOARD_PCI_IF_NUM 0x0 +#define DB_88F5082_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5082_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5082_BOARD_GPP_INFO_NUM 0x4 +#define DB_88F5082_BOARD_DEBUG_LED_NUM 0x0 +#define DB_88F5082_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5082_BOARD_DEVICE_CONFIG_NUM 0x4 + +MV_BOARD_TWSI_INFO db88f5082ddr2InfoBoardTwsiDev[DB_88F5082_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5082ddr2InfoBoardMacInfo[DB_88F5082_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5082ddr2InfoBoardGppInfo[DB_88F5082_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 8}, + {BOARD_DEV_USB_VBUS, 9}, + {BOARD_DEV_REF_CLCK, 11}}; + +MV_BOARD_MPP_INFO db88f5082ddr2InfoBoardMppConfigValue[DB_88F5082_BOARD_MPP_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5082_DDR2_MPP0_7, /* mpp0_7 */ + DB_88F5082_DDR2_MPP8_15, /* mpp8_15 */ + DB_88F5082_DDR2_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#else + {{DB_88F5082_DDR2_MPP0_7NB, /* mpp0_7 */ + DB_88F5082_DDR2_MPP8_15NB, /* mpp8_15 */ + DB_88F5082_DDR2_MPP16_23NB, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#endif + +MV_DEV_CS_INFO db88f5082ddr2InfoBoardDeCsInfo[DB_88F5082_BOARD_DEVICE_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + { 1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + { 2, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}, /* devCs2/flashCs */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ +#else + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + { 1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + { 2, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs2/flashCs */ + { 3, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* bootCs */ +#endif + +MV_BOARD_INFO db88f5082ddr2Info = { + "DB-88F5082-DDR2", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5082_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5082ddr2InfoBoardMppConfigValue, + (1<<10), /* intsGppMask */ + DB_88F5082_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5082ddr2InfoBoardDeCsInfo, + DB_88F5082_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + DB_88F5082_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5082ddr2InfoBoardTwsiDev, + DB_88F5082_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5082ddr2InfoBoardMacInfo, + DB_88F5082_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5082ddr2InfoBoardGppInfo, + DB_88F5082_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5082_DDR2_OE, /* gppOutEn */ + DB_88F5082_DDR2_OE_VAL, /* gppOutVal */ + 0x403, /* gppPolarityVal */ +}; + + + +#define RD_88F5082_2XSATA_BOARD_PCI_IF_NUM 0x0 +#define RD_88F5082_2XSATA_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5082_2XSATA_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5082_2XSATA_BOARD_GPP_INFO_NUM 0x1 +#define RD_88F5082_2XSATA_BOARD_DEBUG_LED_NUM 0x1 +#define RD_88F5082_2XSATA_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5082_2XSATA_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 rd88f5082sataX2InfoBoardDebugLedIf[RD_88F5082_2XSATA_BOARD_DEBUG_LED_NUM] = + {0}; + +MV_BOARD_TWSI_INFO rd88f5082sataX2InfoBoardTwsiDev[RD_88F5082_2XSATA_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5082sataX2InfoBoardMacInfo[RD_88F5082_2XSATA_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO rd88f5082sataX2InfoBoardGppInfo[RD_88F5082_2XSATA_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 3}}; + +MV_BOARD_MPP_INFO rd88f5082sataX2InfoBoardMppConfigValue[RD_88F5082_2XSATA_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5082_2XSATA_MPP0_7, /* mpp0_7 */ + RD_88F5082_2XSATA_MPP8_15, /* mpp8_15 */ + RD_88F5082_2XSATA_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5082sataX2InfoBoardDeCsInfo[RD_88F5082_2XSATA_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs1 */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5082sataX2Info = { + "RD-88F5082-NAS-2", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5082_2XSATA_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5082sataX2InfoBoardMppConfigValue, + ((1<<3)|(1 << 6)|(1<<7)), /* intsGppMask */ + RD_88F5082_2XSATA_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5082sataX2InfoBoardDeCsInfo, + RD_88F5082_2XSATA_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + RD_88F5082_2XSATA_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5082sataX2InfoBoardTwsiDev, + RD_88F5082_2XSATA_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5082sataX2InfoBoardMacInfo, + RD_88F5082_2XSATA_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5082sataX2InfoBoardGppInfo, + RD_88F5082_2XSATA_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5082sataX2InfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5082_2XSATA_OE, /* gppOutEnVal */ + RD_88F5082_2XSATA_VAL, /* gppOutVal */ + RD_88F5082_2XSATA_POL, /* gppPolarityVal */ +}; + + + +#define RD_88F5082_2XSATA3_BOARD_PCI_IF_NUM 0x0 +#define RD_88F5082_2XSATA3_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5082_2XSATA3_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5082_2XSATA3_BOARD_GPP_INFO_NUM 0x1 +#define RD_88F5082_2XSATA3_BOARD_DEBUG_LED_NUM 0x2 +#define RD_88F5082_2XSATA3_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5082_2XSATA3_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 rd88f5082sataX23InfoBoardDebugLedIf[RD_88F5082_2XSATA3_BOARD_DEBUG_LED_NUM] = + {0, 7}; + +MV_BOARD_TWSI_INFO rd88f5082sataX23InfoBoardTwsiDev[RD_88F5082_2XSATA3_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5082sataX23InfoBoardMacInfo[RD_88F5082_2XSATA3_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO rd88f5082sataX23InfoBoardGppInfo[RD_88F5082_2XSATA3_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 3}}; + +MV_BOARD_MPP_INFO rd88f5082sataX23InfoBoardMppConfigValue[RD_88F5082_2XSATA3_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5082_2XSATA3_MPP0_7, /* mpp0_7 */ + RD_88F5082_2XSATA3_MPP8_15, /* mpp8_15 */ + RD_88F5082_2XSATA3_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5082sataX23InfoBoardDeCsInfo[RD_88F5082_2XSATA3_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs1 */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5082sataX23Info = { + "RD-88F5082-NAS-3", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5082_2XSATA3_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5082sataX23InfoBoardMppConfigValue, + ((1<<3)|(1 << 6)|(1<<7)), /* intsGppMask */ + RD_88F5082_2XSATA3_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5082sataX23InfoBoardDeCsInfo, + RD_88F5082_2XSATA3_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + RD_88F5082_2XSATA3_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5082sataX23InfoBoardTwsiDev, + RD_88F5082_2XSATA3_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5082sataX23InfoBoardMacInfo, + RD_88F5082_2XSATA3_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5082sataX23InfoBoardGppInfo, + RD_88F5082_2XSATA3_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5082sataX23InfoBoardDebugLedIf, + 1, /* ledsPolarity */ + RD_88F5082_2XSATA3_OE, /* gppOutEn */ + RD_88F5082_2XSATA3_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ +}; + + +MV_BOARD_INFO* boardInfoTbl[3] = {&db88f5082ddr2Info, + &rd88f5082sataX2Info, + &rd88f5082sataX23Info + }; + +#define BOARD_ID_BASE BOARD_ID_88F5082_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F5082_MAX diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.h new file mode 100644 index 0000000..f479cec --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5082BoardEnv.h @@ -0,0 +1,112 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F5082EnvSpech +#define __INCmvBoard88F5082EnvSpech + + +/* 88F5082 based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88F5082_BASE 0x80 + +/* Old board ID numbers for backward compatability */ +#define DB_88F5082_DDR2_OLD 0xA +#define RD_88F5082_2XSATA_OLD 0xB +#define RD_88F5082_2XSATA3_OLD 0xF + +/* New board ID numbers */ +#define DB_88F5082_DDR2 (BOARD_ID_88F5082_BASE+0x0) +#define RD_88F5082_2XSATA (BOARD_ID_88F5082_BASE+0x1) +#define RD_88F5082_2XSATA3 (BOARD_ID_88F5082_BASE+0x2) + +#define BOARD_ID_88F5082_MAX (BOARD_ID_88F5082_BASE+0x3) + + + +#define DB_88F5082_DDR2_MPP0_7 0x55222203 +#define DB_88F5082_DDR2_MPP8_15 0x44550000 +#define DB_88F5082_DDR2_MPP16_23 0x0 + +#define DB_88F5082_DDR2_MPP0_7NB 0x55442203 +#define DB_88F5082_DDR2_MPP8_15NB 0x00050000 +#define DB_88F5082_DDR2_MPP16_23NB 0x0 + +#define DB_88F5082_DDR2_OE 0xFFF5FFD7 +#define DB_88F5082_DDR2_OE_VAL 0x0 + +#define RD_88F5082_2XSATA_MPP0_7 0x00000003 +#define RD_88F5082_2XSATA_MPP8_15 0x55550000 +#define RD_88F5082_2XSATA_MPP16_23 0x5555 +#define RD_88F5082_2XSATA_OE 0xFFF0F0C8 +#define RD_88F5082_2XSATA_VAL 0x402 +#define RD_88F5082_2XSATA_POL 0xC8 + +#define RD_88F5082_2XSATA3_MPP0_7 0x00000003 +#define RD_88F5082_2XSATA3_MPP8_15 0x05050000 +#define RD_88F5082_2XSATA3_MPP16_23 0x5555 +#define RD_88F5082_2XSATA3_OE 0xFFCF0EF8 +#define RD_88F5082_2XSATA3_VAL 0x402 + +#endif /* __INCmvBoard88F5082EnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.c new file mode 100644 index 0000000..8a52097 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.c @@ -0,0 +1,161 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#define DB_88F5180N_BOARD_PCI_IF_NUM 0x3 +#define DB_88F5180N_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5180N_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5180N_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F5180N_BOARD_DEBUG_LED_NUM 0x0 +#define DB_88F5180N_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5180N_BOARD_DEVICE_CONFIG_NUM 0x4 + +MV_BOARD_PCI_IF db88f5180NddrxInfoBoardPciIf[DB_88F5180N_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {12, 12, 12, 12}}, /* pciSlot0 */ + {8, {13, 13, 13, 13}}, /* pciSlot1 */ + {9, {13, 13, 13, 13}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5180NddrxInfoBoardTwsiDev[DB_88F5180N_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5180NddrxInfoBoardMacInfo[DB_88F5180N_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5180NddrxInfoBoardGppInfo[DB_88F5180N_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 1}, + {BOARD_DEV_REF_CLCK,11}}; + +MV_BOARD_MPP_INFO db88f5180NddrxInfoBoardMppConfigValue[DB_88F5180N_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5180N_DDRX_MPP0_7, /* mpp0_7 */ + DB_88F5180N_DDRX_MPP8_15, /* mpp8_15 */ + DB_88F5180N_DDRX_MPP16_23, /* mpp16_23 */ + DB_88F5180N_DDRX_MPP_DEV}} /* mppDev */ + }; + +MV_DEV_CS_INFO db88f5180NddrxInfoBoardDeCsInfo[DB_88F5180N_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + { 1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + { 2, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}, /* devCs2/flashCs */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5180Nddr2Info = { + "DB-88F5180N-DDR2-A", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5180N_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5180NddrxInfoBoardMppConfigValue, + ((1<<10)|(1 << 12)|(1<<13)), /* intsGppMask */ + DB_88F5180N_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5180NddrxInfoBoardDeCsInfo, + DB_88F5180N_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5180NddrxInfoBoardPciIf, + DB_88F5180N_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5180NddrxInfoBoardTwsiDev, + DB_88F5180N_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5180NddrxInfoBoardMacInfo, + DB_88F5180N_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5180NddrxInfoBoardGppInfo, + DB_88F5180N_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5180N_DDRX_OE, /* gppOutEn */ + DB_88F5180N_DDRX_OE_VAL, /* gppOutVal */ + 0x3400 /* gppPolarityVal */ +}; + +MV_BOARD_INFO db88f5180Nddr1Info = { + "DB-88F5180N-DDR1-A", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5180N_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5180NddrxInfoBoardMppConfigValue, + ((1<<10)|(1 << 12)|(1<<13)), /* intsGppMask */ + DB_88F5180N_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5180NddrxInfoBoardDeCsInfo, + DB_88F5180N_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5180NddrxInfoBoardPciIf, + DB_88F5180N_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5180NddrxInfoBoardTwsiDev, + DB_88F5180N_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5180NddrxInfoBoardMacInfo, + DB_88F5180N_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5180NddrxInfoBoardGppInfo, + DB_88F5180N_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + N_A, /* gppOutEnVal */ + N_A /* gppPolarityVal */ +}; + + +MV_BOARD_INFO* boardInfoTbl[2] = {&db88f5180Nddr1Info, + &db88f5180Nddr2Info + }; + +#define BOARD_ID_BASE BOARD_ID_88F5180N_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F5180N_MAX + diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.h new file mode 100644 index 0000000..8ffe265 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5180NBoardEnv.h @@ -0,0 +1,87 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F5180NEnvSpech +#define __INCmvBoard88F5180NEnvSpech + + + +/* 88F5180N boards ID numbers */ +/* =========================================== */ + +#define BOARD_ID_88F5180N_BASE 0x50 +/* New board ID numbers */ +#define DB_88F5180N_DDR1 (BOARD_ID_88F5180N_BASE+0x0) +#define DB_88F5180N_DDR2 (BOARD_ID_88F5180N_BASE+0x1) +#define BOARD_ID_88F5180N_MAX (BOARD_ID_88F5180N_BASE+0x2) + +#define DB_88F5180N_DDRX_MPP0_7 0x33222203 +#define DB_88F5180N_DDRX_MPP8_15 0x44000033 +#define DB_88F5180N_DDRX_MPP16_23 0x0 +#define DB_88F5180N_DDRX_MPP_DEV 0x0 +#define DB_88F5180N_DDRX_OE 0xFFFDFF17 +#define DB_88F5180N_DDRX_OE_VAL 0x0 + +#endif /* __INCmvBoard88F5180NEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.c new file mode 100644 index 0000000..b5df4f4 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.c @@ -0,0 +1,858 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + + +#define DB_88F5X81_BOARD_PCI_IF_NUM 0x3 +#define DB_88F5X81_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5X81_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5X81_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F5X81_BOARD_DEBUG_LED_NUM 0x0 +#define DB_88F5X81_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5X81_BOARD_DEVICE_CONFIG_NUM 0x4 + +MV_BOARD_PCI_IF db88f5x81ddr2InfoBoardPciIf[DB_88F5X81_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {12, 12, 12, 12}}, /* pciSlot0 */ + {8, {13, 13, 13, 13}}, /* pciSlot1 */ + {9, {13, 13, 13, 13}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5x81ddr2InfoBoardTwsiDev[DB_88F5X81_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5x81ddr2InfoBoardMacInfo[DB_88F5X81_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5x81ddr2InfoBoardGppInfo[DB_88F5X81_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 1}, + {BOARD_DEV_REF_CLCK,11}}; + +MV_BOARD_MPP_INFO db88f5x81ddr2InfoBoardMppConfigValue[DB_88F5X81_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ +#ifndef MV_NAND_BOOT + {{{DB_88F5X81_DDRX_MPP0_7, /* mpp0_7 */ + DB_88F5X81_DDRX_MPP8_15, /* mpp8_15 */ + DB_88F5X81_DDRX_MPP16_23, /* mpp16_23 */ + DB_88F5X81_DDRX_MPP_DEV}} /* mppDev */ + }; +#else + {{{DB_88F5X81_DDRX_MPP0_7_NB, /* mpp0_7 */ + DB_88F5X81_DDRX_MPP8_15_NB, /* mpp8_15 */ + DB_88F5X81_DDRX_MPP16_23_NB, /* mpp16_23 */ + DB_88F5X81_DDRX_MPP_DEV_NB}} /* mppDev */ + }; +#endif + +MV_DEV_CS_INFO db88f5x81ddr2InfoBoardDeCsInfo[DB_88F5X81_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ +#ifndef MV_NAND_BOOT + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + { 1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + { 2, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}, /* devCs2/flashCs */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ +#else + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + { 1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + { 2, 0x8fcfffff, BOARD_DEV_OTHER, 8}, /* devCs2/flashCs */ + { 3, 0x8fdfffff, BOARD_DEV_NAND_FLASH, 16}}; /* bootCs */ +#endif + +MV_BOARD_INFO db88f5x81ddr2Info = { + "DB-88F5X81-DDR2-A/B", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5X81_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5x81ddr2InfoBoardMppConfigValue, + ((1<<10)|(1 << 12)|(1<<13)), /* intsGppMask */ + DB_88F5X81_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5x81ddr2InfoBoardDeCsInfo, + DB_88F5X81_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5x81ddr2InfoBoardPciIf, + DB_88F5X81_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5x81ddr2InfoBoardTwsiDev, + DB_88F5X81_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5x81ddr2InfoBoardMacInfo, + DB_88F5X81_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5x81ddr2InfoBoardGppInfo, + DB_88F5X81_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5X81_DDRX_OE, /* gppOutEnVal */ + DB_88F5X81_DDRX_OUT_VAL, /* gppOutVal */ + 0x3400, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +MV_BOARD_INFO db88f5x81ddr1Info = { + "DB-88F5X81-DDR1-A", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5X81_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5x81ddr2InfoBoardMppConfigValue, + ((1<<10)|(1 << 12)|(1<<13)), /* intsGppMask */ + DB_88F5X81_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5x81ddr2InfoBoardDeCsInfo, + DB_88F5X81_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5x81ddr2InfoBoardPciIf, + DB_88F5X81_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5x81ddr2InfoBoardTwsiDev, + DB_88F5X81_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5x81ddr2InfoBoardMacInfo, + DB_88F5X81_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5x81ddr2InfoBoardGppInfo, + DB_88F5X81_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5X81_DDRX_OE, /* gppOutEnVal */ + DB_88F5X81_DDRX_OUT_VAL, /* gppOutVal */ + 0x3400, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +MV_BOARD_INFO db88f1181ddr1Info = { + "DB-88F1181-DDR1" /* boardName[MAX_BOARD_NAME_LEN] */ +}; + +MV_BOARD_INFO db88f1181ddr2Info = { + "DB-88F1181-DDR2" /* boardName[MAX_BOARD_NAME_LEN] */ +}; + +#define DB_PRPMC_BOARD_PCI_IF_NUM 0x1 +#define DB_PRPMC_BOARD_TWSI_DEF_NUM 0x1 +#define DB_PRPMC_BOARD_MAC_INFO_NUM 0x1 +#define DB_PRPMC_BOARD_GPP_INFO_NUM 0x1 +#define DB_PRPMC_BOARD_DEBUG_LED_NUM 0x3 +#define DB_PRPMC_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_PRPMC_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 db88f5181prpmcInfoBoardDebugLedIf[DB_PRPMC_BOARD_DEBUG_LED_NUM] = + {12, 13, 14}; +MV_BOARD_PCI_IF db88f5181prpmcInfoBoardPciIf[DB_PRPMC_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{0, {12, 12, 12, 12}}}; /* pciSlot0 */ +MV_BOARD_TWSI_INFO db88f5181prpmcInfoBoardTwsiDev[DB_PRPMC_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5181prpmcInfoBoardMacInfo[DB_PRPMC_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x1F}}; + +MV_BOARD_GPP_INFO db88f5181prpmcInfoBoardGppInfo[DB_PRPMC_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_REF_CLCK, 0}}; + +MV_BOARD_MPP_INFO db88f5181prpmcInfoBoardMppConfigValue[DB_PRPMC_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5181_DDR1_PRPMC_MPP0_7, /* mpp0_7 */ + DB_88F5181_DDR1_PRPMC_MPP8_15, /* mpp8_15 */ + DB_88F5181_DDR1_PRPMC_MPP16_23, /* mpp16_23 */ + DB_88F5181_DDR1_PRPMC_MPP_DEV}} /* mppDev */ + }; + +MV_DEV_CS_INFO db88f5181prpmcInfoBoardDeCsInfo[DB_PRPMC_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5181prpmcInfo = { + "DB-88F5181-DDR1-PRPMC", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_PRPMC_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5181prpmcInfoBoardMppConfigValue, + ((1 << 4)|(1 << 5)|(1 << 6)|(1 << 7)), /* intsGppMask */ + DB_PRPMC_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5181prpmcInfoBoardDeCsInfo, + DB_PRPMC_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5181prpmcInfoBoardPciIf, + DB_PRPMC_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5181prpmcInfoBoardTwsiDev, + DB_PRPMC_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5181prpmcInfoBoardMacInfo, + DB_PRPMC_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5181prpmcInfoBoardGppInfo, + DB_PRPMC_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f5181prpmcInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + DB_88F5181_DDR1_PRPMC_OE, /* gppOutEnVal */ + DB_88F5181_DDR1_PRPMC_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +#define DB_PEXPCI_BOARD_PCI_IF_NUM 0x1 +#define DB_PEXPCI_BOARD_TWSI_DEF_NUM 0x1 +#define DB_PEXPCI_BOARD_MAC_INFO_NUM 0x1 +#define DB_PEXPCI_BOARD_GPP_INFO_NUM 0x1 +#define DB_PEXPCI_BOARD_DEBUG_LED_NUM 0x4 +#define DB_PEXPCI_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_PEXPCI_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 db88f5181pexPciInfoBoardDebugLedIf[DB_PEXPCI_BOARD_DEBUG_LED_NUM] = + {12, 13, 14, 15}; + +MV_BOARD_PCI_IF db88f5181pexPciInfoBoardPciIf[DB_PEXPCI_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{0, {3, 6, 7, 7}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO db88f5181pexPciInfoBoardTwsiDev[DB_PEXPCI_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5181pexPciInfoBoardMacInfo[DB_PEXPCI_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5181pexPciInfoBoardGppInfo[DB_PEXPCI_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_REF_CLCK, 0}}; + +MV_BOARD_MPP_INFO db88f5181pexPciInfoBoardMppConfigValue[DB_PEXPCI_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5181_DDR1_PRPMC_MPP0_7, /* mpp0_7 */ + DB_88F5181_DDR1_PRPMC_MPP8_15, /* mpp8_15 */ + DB_88F5181_DDR1_PRPMC_MPP16_23, /* mpp16_23 */ + DB_88F5181_DDR1_PRPMC_MPP_DEV}} /* mppDev */ + }; + +MV_DEV_CS_INFO db88f5181pexPciInfoBoardDeCsInfo[DB_PEXPCI_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5181pexPciInfo = { + "DB-88F5181-DDR1-PEX_PCI", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_PEXPCI_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5181pexPciInfoBoardMppConfigValue, + ((1 << 4)|(1 << 5)|(1 << 6)|(1 << 7)), /* intsGppMask */ + DB_PEXPCI_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5181pexPciInfoBoardDeCsInfo, + DB_PEXPCI_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5181pexPciInfoBoardPciIf, + DB_PEXPCI_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5181pexPciInfoBoardTwsiDev, + DB_PEXPCI_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5181pexPciInfoBoardMacInfo, + DB_PEXPCI_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5181pexPciInfoBoardGppInfo, + DB_PEXPCI_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f5181pexPciInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + DB_88F5181_DDR1_PRPMC_OE, /* gppOutEnVal */ + DB_88F5181_DDR1_PRPMC_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +#define RD_88F5181_POS_NAS_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5181_POS_NAS_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5181_POS_NAS_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5181_POS_NAS_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F5181_POS_NAS_BOARD_DEBUG_LED_NUM 0x4 +#define RD_88F5181_POS_NAS_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5181_POS_NAS_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 rd88f5181posNasInfoBoardDebugLedIf[RD_88F5181_POS_NAS_BOARD_DEBUG_LED_NUM] = + {12, 13, 14, 15}; + +MV_BOARD_PCI_IF rd88f5181posNasInfoBoardPciIf[RD_88F5181_POS_NAS_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {6, 4, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5181posNasInfoBoardTwsiDev[RD_88F5181_POS_NAS_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5181posNasInfoBoardMacInfo[RD_88F5181_POS_NAS_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO rd88f5181posNasInfoBoardGppInfo[RD_88F5181_POS_NAS_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 8}, + {BOARD_DEV_USB_VBUS, 9}, + {BOARD_DEV_REF_CLCK,0}}; + +MV_BOARD_MPP_INFO rd88f5181posNasInfoBoardMppConfigValue[RD_88F5181_POS_NAS_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181_POS_NAS_MPP0_7, /* mpp0_7 */ + RD_88F5181_POS_NAS_MPP8_15, /* mpp8_15 */ + RD_88F5181_POS_NAS_MPP16_23, /* mpp16_23 */ + RD_88F5181_POS_NAS_MPP_DEV}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5181posNasInfoBoardDeCsInfo[RD_88F5181_POS_NAS_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs1 */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181posNasInfo = { + "RD-88F5181-88SX7042-2xSATA", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5181_POS_NAS_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181posNasInfoBoardMppConfigValue, + ((1 << 4)|(1 << 6)|(1 << 8)), /* intsGppMask */ + RD_88F5181_POS_NAS_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181posNasInfoBoardDeCsInfo, + RD_88F5181_POS_NAS_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5181posNasInfoBoardPciIf, + RD_88F5181_POS_NAS_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5181posNasInfoBoardTwsiDev, + RD_88F5181_POS_NAS_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181posNasInfoBoardMacInfo, + RD_88F5181_POS_NAS_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5181posNasInfoBoardGppInfo, + RD_88F5181_POS_NAS_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181posNasInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5181_POS_NAS_OE, /* gppOutEnVal */ + RD_88F5181_POS_NAS_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + + +#define RD_88F5181_VOIP_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5181_VOIP_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5181_VOIP_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5181_VOIP_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F5181_VOIP_BOARD_DEBUG_LED_NUM 0x3 +#define RD_88F5181_VOIP_BOARD_MPP_CONFIG_NUM 0x3 +#define RD_88F5181_VOIP_BOARD_DEVICE_CONFIG_NUM 0x4 + +MV_U8 rd88f5181voipInfoBoardDebugLedIf[RD_88F5181_VOIP_BOARD_DEBUG_LED_NUM] = + {13, 14, 15}; + +MV_BOARD_PCI_IF rd88f5181voipInfoBoardPciIf[RD_88F5181_VOIP_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{1, {4, 4, 4, 4}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5181voipInfoBoardTwsiDev[RD_88F5181_VOIP_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5181voipInfoBoardMacInfo[RD_88F5181_VOIP_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_100M, 0x0}}; + +MV_BOARD_GPP_INFO rd88f5181voipInfoBoardGppInfo[RD_88F5181_VOIP_BOARD_MPP_CONFIG_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 7}, + {BOARD_DEV_USB_VBUS, 2}, + {BOARD_DEV_MV_SWITCH,6}}; + +MV_BOARD_MPP_INFO rd88f5181voipInfoBoardMppConfigValue[RD_88F5181_VOIP_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181_VOIP_MPP0_7, /* mpp0_7 */ + RD_88F5181_VOIP_MPP8_15}} /* mpp8_15 */ + }; + +MV_DEV_CS_INFO rd88f5181voipInfoBoardDeCsInfo[RD_88F5181_VOIP_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 0, 0x8fdfffff, BOARD_DEV_FPGA, N_A}, /* devCs0 */ + { 1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs1 */ + { 2, 0x8fdfffff, BOARD_DEV_FPGA, N_A}, /* devCs2/flashCs */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181voipInfo = { + "RD-88F5181-VOIP-RD1", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5181_VOIP_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181voipInfoBoardMppConfigValue, + ((1 << 3)|(1 << 4)|(1 << 6)|(1 << 7)), /* intsGppMask */ + RD_88F5181_VOIP_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181voipInfoBoardDeCsInfo, + RD_88F5181_VOIP_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5181voipInfoBoardPciIf, + RD_88F5181_VOIP_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5181voipInfoBoardTwsiDev, + RD_88F5181_VOIP_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181voipInfoBoardMacInfo, + RD_88F5181_VOIP_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5181voipInfoBoardGppInfo, + RD_88F5181_VOIP_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181voipInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5181_VOIP_OE, /* gppOutEnVal */ + RD_88F5181_VOIP_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +#define RD_88F5181_GTW_FE_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5181_GTW_FE_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5181_GTW_FE_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5181_GTW_FE_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F5181_GTW_FE_BOARD_DEBUG_LED_NUM 0x3 +#define RD_88F5181_GTW_FE_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5181_GTW_FE_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 rd88f5181GtwFeInfoBoardDebugLedIf[RD_88F5181_GTW_FE_BOARD_DEBUG_LED_NUM] = + {13, 14, 15}; + +MV_BOARD_PCI_IF rd88f5181GtwFeInfoBoardPciIf[RD_88F5181_GTW_FE_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {4, 3, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5181GtwFeInfoBoardTwsiDev[RD_88F5181_GTW_FE_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5181GtwFeInfoBoardMacInfo[RD_88F5181_GTW_FE_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_100M, 0x0}}; + +MV_BOARD_SWITCH_INFO rd88f5181GtwFeInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{-1, {0, 1, 2, 3, 4}, 5, 0}}; + +MV_BOARD_GPP_INFO rd88f5181GtwFeInfoBoardGppInfo[RD_88F5181_GTW_FE_BOARD_MPP_CONFIG_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 11} + }; + +MV_BOARD_MPP_INFO rd88f5181GtwFeInfoBoardMppConfigValue[RD_88F5181_GTW_FE_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181_GTW_FE_MPP0_7, /* mpp0_7 */ + RD_88F5181_GTW_FE_MPP8_15}} /* mpp8_15 */ + }; + +MV_DEV_CS_INFO rd88f5181GtwFeInfoBoardDeCsInfo[RD_88F5181_GTW_FE_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181GtwFeInfo = { + "RD-88F5181-GTW-FE", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5181_GTW_FE_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181GtwFeInfoBoardMppConfigValue, + ((1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 9)|(1 << 11)),/* intsGppMask */ + RD_88F5181_GTW_FE_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181GtwFeInfoBoardDeCsInfo, + RD_88F5181_GTW_FE_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5181GtwFeInfoBoardPciIf, + RD_88F5181_GTW_FE_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5181GtwFeInfoBoardTwsiDev, + RD_88F5181_GTW_FE_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181GtwFeInfoBoardMacInfo, + RD_88F5181_GTW_FE_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5181GtwFeInfoBoardGppInfo, + RD_88F5181_GTW_FE_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181GtwFeInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5181_GTW_FE_OE, /* gppOutEnVal */ + RD_88F5181_GTW_FE_OUT_VAL, /* gppOutVal */ + 0xA3C, /* gppPolarity */ + rd88f5181GtwFeInfoBoardSwitchInfo /* pSwitchInfo */ + +}; + +#define RD_88F5181_GTW_GE_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5181_GTW_GE_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5181_GTW_GE_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5181_GTW_GE_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F5181_GTW_GE_BOARD_DEBUG_LED_NUM 0x4 +#define RD_88F5181_GTW_GE_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5181_GTW_GE_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 rd88f5181GtwGeInfoBoardDebugLedIf[RD_88F5181_GTW_GE_BOARD_DEBUG_LED_NUM] = + {1, 2, 3,0}; + +MV_BOARD_PCI_IF rd88f5181GtwGeInfoBoardPciIf[RD_88F5181_GTW_GE_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {4, 10, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5181GtwGeInfoBoardTwsiDev[RD_88F5181_GTW_GE_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5181GtwGeInfoBoardMacInfo[RD_88F5181_GTW_GE_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_1000M, 0x0}}; + +MV_BOARD_SWITCH_INFO rd88f5181GtwGeInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{8, {2, 1, 0, 7, 5}, 3, 1}}; + +MV_BOARD_GPP_INFO rd88f5181GtwGeInfoBoardGppInfo[RD_88F5181_GTW_GE_BOARD_MPP_CONFIG_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 7} + }; + +MV_BOARD_MPP_INFO rd88f5181GtwGeInfoBoardMppConfigValue[RD_88F5181_GTW_GE_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181_GTW_GE_MPP0_7, /* mpp0_7 */ + RD_88F5181_GTW_GE_MPP8_15, + RD_88F5181_GTW_GE_MPP16_23}} /* mpp8_15 */ + }; + +MV_DEV_CS_INFO rd88f5181GtwGeInfoBoardDeCsInfo[RD_88F5181_GTW_GE_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{ 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181GtwGeInfo = { + "RD-88F5181-GTW-GE", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5181_GTW_GE_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181GtwGeInfoBoardMppConfigValue, + ((1 << 4)|(1 << 5)|(1 << 8)), /* intsGppMask */ + RD_88F5181_GTW_GE_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181GtwGeInfoBoardDeCsInfo, + RD_88F5181_GTW_GE_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5181GtwGeInfoBoardPciIf, + RD_88F5181_GTW_GE_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5181GtwGeInfoBoardTwsiDev, + RD_88F5181_GTW_GE_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181GtwGeInfoBoardMacInfo, + RD_88F5181_GTW_GE_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5181GtwGeInfoBoardGppInfo, + RD_88F5181_GTW_GE_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181GtwGeInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5181_GTW_GE_OE, /* gppOutEnVal */ + RD_88F5181_GTW_GE_OUT_VAL, /* gppOutVal */ + 0x530, /* gppPolarity */ + rd88f5181GtwGeInfoBoardSwitchInfo /* pSwitchInfo */ +}; + + + + +#define DB_88F5181_5281_DDR1_BOARD_PCI_IF_NUM 0x3 +#define DB_88F5181_5281_DDR1_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5181_5281_DDR1_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5181_5281_DDR1_BOARD_GPP_INFO_NUM 0x1 +#define DB_88F5181_5281_DDR1_BOARD_DEBUG_LED_NUM 0x0 +#define DB_88F5181_5281_DDR1_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5181_5281_DDR1_BOARD_DEVICE_CONFIG_NUM 0x3 + +MV_BOARD_PCI_IF db88f5181_5281ddr1InfoBoardPciIf[DB_88F5181_5281_DDR1_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {7, 7, 7, 7}}, /* pciSlot0 */ + {8, {6, 6, 6, 6}}, /* pciSlot1 */ + {9, {6, 6, 6, 6}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5181_5281ddr1InfoBoardTwsiDev[DB_88F5181_5281_DDR1_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5181_5281ddr1InfoBoardMacInfo[DB_88F5181_5281_DDR1_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5181_5281ddr1InfoBoardGppInfo[DB_88F5181_5281_DDR1_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_USB_VBUS, 5}}; + +MV_BOARD_MPP_INFO db88f5181_5281ddr1InfoBoardMppConfigValue[DB_88F5181_5281_DDR1_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5181_5281_DDR1_MPP0_7, /* mpp0_7 */ + DB_88F5181_5281_DDR1_MPP8_15, /* mpp8_15 */ + DB_88F5181_5281_DDR1_MPP16_23, /* mpp16_23 */ + DB_88F5181_5281_DDR1_MPP_DEV}}}; /* mppDev */ + +MV_DEV_CS_INFO db88f5181_5281ddr1InfoBoardDeCsInfo[DB_88F5181_5281_DDR1_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {2, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs2 */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5181_5281ddr1Info = { + "DB-88F5181-DDR1", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5181_5281_DDR1_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5181_5281ddr1InfoBoardMppConfigValue, + ((1 << 6)|(1 << 7)), /* intsGppMask */ + DB_88F5181_5281_DDR1_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5181_5281ddr1InfoBoardDeCsInfo, + DB_88F5181_5281_DDR1_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5181_5281ddr1InfoBoardPciIf, + DB_88F5181_5281_DDR1_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5181_5281ddr1InfoBoardTwsiDev, + DB_88F5181_5281_DDR1_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5181_5281ddr1InfoBoardMacInfo, + DB_88F5181_5281_DDR1_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5181_5281ddr1InfoBoardGppInfo, + DB_88F5181_5281_DDR1_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5181_5281_DDR1_OE, /* gppOutEnVal */ + DB_88F5181_5281_DDR1_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + + + +#define DB_88F5181_5281_DDR2_BOARD_PCI_IF_NUM 0x3 +#define DB_88F5181_5281_DDR2_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5181_5281_DDR2_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5181_5281_DDR2_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F5181_5281_DDR2_BOARD_DEBUG_LED_NUM 0x4 +#define DB_88F5181_5281_DDR2_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5181_5281_DDR2_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 db88f5181_5281ddr2InfoBoardDebugLedIf[DB_88F5181_5281_DDR2_BOARD_DEBUG_LED_NUM] = + {14, 15, 6, 7}; + +MV_BOARD_PCI_IF db88f5181_5281ddr2InfoBoardPciIf[DB_88F5181_5281_DDR2_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {12, 12, 12, 12}}, /* pciSlot0 */ + {8, {13, 13, 13, 13}}, /* pciSlot1 */ + {9, {13, 13, 13, 13}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5181_5281ddr2InfoBoardTwsiDev[DB_88F5181_5281_DDR2_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5181_5281ddr2InfoBoardMacInfo[DB_88F5181_5281_DDR2_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5181_5281ddr2InfoBoardGppInfo[DB_88F5181_5281_DDR2_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 1}, + {BOARD_DEV_REF_CLCK,11}}; + +MV_BOARD_MPP_INFO db88f5181_5281ddr2InfoBoardMppConfigValue[DB_88F5181_5281_DDR2_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5181_5281_DDR2_MPP0_7, /* mpp0_7 */ + DB_88F5181_5281_DDR2_MPP8_15, /* mpp8_15 */ + DB_88F5181_5281_DDR2_MPP16_23, /* mpp16_23 */ + DB_88F5181_5281_DDR2_MPP_DEV}}}; /* mppDev */ + +MV_DEV_CS_INFO db88f5181_5281ddr2InfoBoardDeCsInfo[DB_88F5181_5281_DDR2_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5181_5281ddr2Info = { + "DB-88F5181-DDR2", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5181_5281_DDR2_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5181_5281ddr2InfoBoardMppConfigValue, + ((1 << 10)|(1 << 12)|(1 << 13)), /* intsGppMask */ + DB_88F5181_5281_DDR2_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5181_5281ddr2InfoBoardDeCsInfo, + DB_88F5181_5281_DDR2_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5181_5281ddr2InfoBoardPciIf, + DB_88F5181_5281_DDR2_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5181_5281ddr2InfoBoardTwsiDev, + DB_88F5181_5281_DDR2_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5181_5281ddr2InfoBoardMacInfo, + DB_88F5181_5281_DDR2_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5181_5281ddr2InfoBoardGppInfo, + DB_88F5181_5281_DDR2_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f5181_5281ddr2InfoBoardDebugLedIf, + 1, /* ledsPolarity */ + DB_88F5181_5281_DDR2_OE, /* gppOutEnVal */ + DB_88F5181_5281_DDR2_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + + +#define DB_88F5181_DDR1_MNG_BOARD_PCI_IF_NUM 0x1 +#define DB_88F5181_DDR1_MNG_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5181_DDR1_MNG_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5181_DDR1_MNG_BOARD_GPP_INFO_NUM 0x1 +#define DB_88F5181_DDR1_MNG_BOARD_DEBUG_LED_NUM 0x3 +#define DB_88F5181_DDR1_MNG_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5181_DDR1_MNG_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_BOARD_PCI_IF db88f5181ddr1MngInfoBoardPciIf[] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{2, {7, 7, 7, 7}}}; /* pciSlot0 */ + +MV_U8 db88f5181ddr1MngInfoBoardDebugLedIf[DB_88F5181_DDR1_MNG_BOARD_DEBUG_LED_NUM] = + {12, 13, 14}; + +MV_BOARD_TWSI_INFO db88f5181ddr1MngInfoBoardTwsiDev[DB_88F5181_DDR1_MNG_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5181ddr1MngInfoBoardMacInfo[DB_88F5181_DDR1_MNG_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x1F}}; + +MV_BOARD_GPP_INFO db88f5181ddr1MngInfoBoardGppInfo[DB_88F5181_DDR1_MNG_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_REF_CLCK,0}}; + +MV_BOARD_MPP_INFO db88f5181ddr1MngInfoBoardMppConfigValue[DB_88F5181_DDR1_MNG_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5181_DDR1_MNG_MPP0_7, /* mpp0_7 */ + DB_88F5181_DDR1_MNG_MPP8_15, /* mpp8_15 */ + DB_88F5181_DDR1_MNG_MPP16_23, /* mpp16_23 */ + DB_88F5181_DDR1_MNG_MPP_DEV}}}; /* mppDev */ + +MV_DEV_CS_INFO db88f5181ddr1MngInfoBoardDeCsInfo[DB_88F5181_DDR1_MNG_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{1, 0x8fefffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5181ddr1MngInfo = { + "DB-88F5181-DDR1-MNG", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5181_DDR1_MNG_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5181ddr1MngInfoBoardMppConfigValue, + ((1 << 3)|(1 << 6)|(1 << 7)), /* intsGppMask */ + DB_88F5181_DDR1_MNG_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5181ddr1MngInfoBoardDeCsInfo, + DB_88F5181_DDR1_MNG_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5181ddr1MngInfoBoardPciIf, + DB_88F5181_DDR1_MNG_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5181ddr1MngInfoBoardTwsiDev, + DB_88F5181_DDR1_MNG_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5181ddr1MngInfoBoardMacInfo, + DB_88F5181_DDR1_MNG_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5181ddr1MngInfoBoardGppInfo, + DB_88F5181_DDR1_MNG_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f5181ddr1MngInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + DB_88F5181_DDR1_MNG_GPP_OE, /* gppOutEnVal */ + DB_88F5181_DDR1_MNG_GPP_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +#define DB_88F5X8X_BOARD_PCI_IF_NUM 0x0 +#define DB_88F5X8X_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5X8X_BOARD_MAC_INFO_NUM 0x0 +#define DB_88F5X8X_BOARD_GPP_INFO_NUM 0x1 +#define DB_88F5X8X_BOARD_DEBUG_LED_NUM 0x4 +#define DB_88F5X8X_BOARD_MPP_CONFIG_NUM 0x0 +#define DB_88F5X8X_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_BOARD_PCI_IF db88f5x8xddr2InfoBoardPciIf[] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {6, 6, 6, 6}}, /* pciSlot0 */ + {8, {7, 7, 7, 7}}, /* pciSlot1 */ + {9, {7, 7, 7, 7}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5x8xddr2InfoBoardTwsiDev[DB_88F5X8X_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5x8xddr2InfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5x8xddr2InfoBoardGppInfo[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 1}, + {BOARD_DEV_REF_CLCK,11}}; + +MV_BOARD_MPP_INFO db88f5x8xddr2InfoBoardMppConfigValue[] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5X8X_DDRX_MPP0_7, /* mpp0_7 */ + DB_88F5X8X_DDRX_MPP8_15, /* mpp8_15 */ + DB_88F5X8X_DDRX_MPP16_23, /* mpp16_23 */ + DB_88F5X8X_DDRX_MPP_DEV}} /* mppDev */ + }; + +MV_DEV_CS_INFO db88f5x8xddr2InfoBoardDeCsInfo[DB_88F5X8X_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs0 */ + { 3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5x8xFpgaddr2Info = { + "DB-88F5X8X-FPGA-DDR1-A", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5X8X_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + NULL, + ((1<<6)|(1 << 7)), /* intsGppMask */ + DB_88F5X8X_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5x8xddr2InfoBoardDeCsInfo, + DB_88F5X8X_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + DB_88F5X8X_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5x8xddr2InfoBoardTwsiDev, + DB_88F5X8X_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + NULL, + DB_88F5X8X_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5x8xddr2InfoBoardGppInfo, + DB_88F5X8X_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5X8X_DDRX_OE, /* gppOutEnVal */ + DB_88F5X8X_DDRX_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +MV_BOARD_INFO* boardInfoTbl[] = {NULL, /* DB_88F1181_DDR1 - OBSOLETE */ + NULL, /* DB_88F1181_DDR2 - OBSOLETE */ + &db88f5181_5281ddr1Info, /* DB_88F5181_5281_DDR1 */ + &db88f5181_5281ddr2Info, /* DB_88F5181_5281_DDR2 */ + &db88f5181prpmcInfo, /* DB_88F5181_DDR1_PRPMC */ + &db88f5181pexPciInfo, /* DB_88F5181_DDR1_PEXPCI */ + &rd88f5181posNasInfo, /* RD_88F5181_POS_NAS */ + &db88f5x81ddr2Info, /* DB_88F5X81_DDR2 */ + &db88f5x81ddr1Info, /* DB_88F5X81_DDR1 */ + &rd88f5181voipInfo, /* RD_88F5181_VOIP - OBSOLETE */ + &db88f5181ddr1MngInfo, /* DB_88F5181_DDR1_MNG */ + &rd88f5181GtwFeInfo, /* RD_88F5181_GTW_FE */ + &rd88f5181GtwGeInfo, /* RD_88F5181_GTW_GE */ + &db88f5x8xFpgaddr2Info /* DB_88F5X8X_FPGA_DDR2 */ + }; + +#define BOARD_ID_BASE BOARD_ID_88F5181_5281_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F5181_5281_MAX + diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.h new file mode 100644 index 0000000..17a34a5 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181BoardEnv.h @@ -0,0 +1,182 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F5181EnvSpech +#define __INCmvBoard88F5181EnvSpech + + + +/* 88F5181 and 88F5281 based boards ID numbers */ +/* =========================================== */ +#define BOARD_ID_88F5181_5281_BASE 0x0 + +#define RD_88F5181_GTW_FE_OLD 0xd +#define RD_88F5181_GTW_GE_OLD 0xe +#define RD_88F5181_POS_NAS_OLD 0xab +#define DB_88F5X81_DDR2_OLD 0xcd +#define DB_88F5X81_DDR1_OLD 0xce + +#define DB_88F1181_DDR1 (BOARD_ID_88F5181_5281_BASE+0x0) /* obsolete */ +#define DB_88F1181_DDR2 (BOARD_ID_88F5181_5281_BASE+0x1) /* obsolete */ +#define DB_88F5181_5281_DDR1 (BOARD_ID_88F5181_5281_BASE+0x2) +#define DB_88F5181_5281_DDR2 (BOARD_ID_88F5181_5281_BASE+0x3) +#define DB_88F5181_DDR1_PRPMC (BOARD_ID_88F5181_5281_BASE+0x4) +#define DB_88F5181_DDR1_PEXPCI (BOARD_ID_88F5181_5281_BASE+0x5) +#define RD_88F5181_POS_NAS (BOARD_ID_88F5181_5281_BASE+0x6) +#define DB_88F5X81_DDR2 (BOARD_ID_88F5181_5281_BASE+0x7) +#define DB_88F5X81_DDR2_OPEN_LINUX_ID 1358 +#define DB_88F5X81_DDR1 (BOARD_ID_88F5181_5281_BASE+0x8) +#define RD_88F5181_VOIP (BOARD_ID_88F5181_5281_BASE+0x9) /* obsolete */ +#define DB_88F5181_DDR1_MNG (BOARD_ID_88F5181_5281_BASE+0xA) +#define RD_88F5181_GTW_FE (BOARD_ID_88F5181_5281_BASE+0xB) +#define RD_88F5181_GTW_GE (BOARD_ID_88F5181_5281_BASE+0xC) +#define DB_88F5X8X_FPGA_DDR1 (BOARD_ID_88F5181_5281_BASE+0xD) + +#define BOARD_ID_88F5181_5281_MAX (BOARD_ID_88F5181_5281_BASE+0xE) + +#define DB_88F5181_5281_DDR1_MPP0_7 0x00032222 +#define DB_88F5181_5281_DDR1_MPP8_15 0x11111111 +#define DB_88F5181_5281_DDR1_MPP16_23 0x1111 +#define DB_88F5181_5281_DDR1_MPP_DEV 0x0 +#define DB_88F5181_5281_DDR1_OE 0xFFFFFFFF +#define DB_88F5181_5281_DDR1_OUT_VAL 0x0 + +#define DB_88F5181_5281_DDR2_MPP0_7 0x00222203 +#define DB_88F5181_5281_DDR2_MPP8_15 0x00001133 +#define DB_88F5181_5281_DDR2_MPP16_23 0x0 +#define DB_88F5181_5281_DDR2_MPP_DEV 0x0 +#define DB_88F5181_5281_DDR2_OE 0xFFFF3F17 +#define DB_88F5181_5281_DDR2_OUT_VAL BIT15 + +#define DB_88F5X81_DDRX_MPP0_7 0x33222203 +#define DB_88F5X81_DDRX_MPP8_15 0x44000033 +#define DB_88F5X81_DDRX_MPP16_23 0x0 +#define DB_88F5X81_DDRX_MPP_DEV 0x0 +#define DB_88F5X81_DDRX_OE 0xFFFDFF17 +#define DB_88F5X81_DDRX_OUT_VAL 0x0 + +#define DB_88F5181_DDR1_PRPMC_MPP0_7 0x00000003 +#define DB_88F5181_DDR1_PRPMC_MPP8_15 0x10001111 +#define DB_88F5181_DDR1_PRPMC_MPP16_23 0x00001111 +#define DB_88F5181_DDR1_PRPMC_MPP_DEV 0x0 +#define DB_88F5181_DDR1_PRPMC_OE 0xFFFF0FFF +#define DB_88F5181_DDR1_PRPMC_OUT_VAL 0x0 + +#define RD_88F5181_POS_NAS_MPP0_7 0x0 +#define RD_88F5181_POS_NAS_MPP8_15 0x0 +#define RD_88F5181_POS_NAS_MPP16_23 0x0 +#define RD_88F5181_POS_NAS_MPP_DEV 0x0 +#define RD_88F5181_POS_NAS_OE 0x00000BDF +#define RD_88F5181_POS_NAS_OUT_VAL 0x0 + +#define RD_88F5181_VOIP_MPP0_7 0x00000003 +#define RD_88F5181_VOIP_MPP8_15 0x00000101 +#define RD_88F5181_VOIP_MPP16_23 0x0 +#define RD_88F5181_VOIP_MPP_DEV 0x0 +#define RD_88F5181_VOIP_OE 0x000005F5 +#define RD_88F5181_VOIP_OUT_VAL 0x0 + + +#define DB_88F5X81_DDRX_MPP0_7_NB 0x33442203 +#define DB_88F5X81_DDRX_MPP8_15_NB 0x44000033 +#define DB_88F5X81_DDRX_MPP16_23_NB 0x0 +#define DB_88F5X81_DDRX_MPP_DEV_NB 0x0 + +#define DB_88F5181_DDR1_MNG_MPP0_7 0x00000003 +#define DB_88F5181_DDR1_MNG_MPP8_15 0x10001111 +#define DB_88F5181_DDR1_MNG_MPP16_23 0x00001111 +#define DB_88F5181_DDR1_MNG_MPP_DEV 0x0 +#define DB_88F5181_DDR1_MNG_GPP_OE 0xFFFF8FF8 +#define DB_88F5181_DDR1_MNG_GPP_OUT_VAL 0x0 + +#define DB_88F5181_DDR1_PEXPCI_MPP0_7 0x00330000 +#define DB_88F5181_DDR1_PEXPCI_MPP8_15 0x0 +#define DB_88F5181_DDR1_PEXPCI_MPP16_23 0x0 +#define DB_88F5181_DDR1_PEXPCI_MPP_DEV 0x0 +#define DB_88F5181_DDR1_PEXPCI_OE 0xFFFDFF17 +#define DB_88F5181_DDR1_PEXPCI_OUT_VAL 0x0 + +#define RD_88F5181_GTW_FE_MPP0_7 0x55000003 +#define RD_88F5181_GTW_FE_MPP8_15 0x00000101 +#define RD_88F5181_GTW_FE_MPP16_23 0x0 +#define RD_88F5181_GTW_FE_MPP_DEV 0x0 +#define RD_88F5181_GTW_FE_OE 0xFFFF0FFC +#define RD_88F5181_GTW_FE_OUT_VAL 0xF001 + +#define RD_88F5181_GTW_GE_MPP0_7 0x55000003 +#define RD_88F5181_GTW_GE_MPP8_15 0x11110010 +#define RD_88F5181_GTW_GE_MPP16_23 0x1111 +#define RD_88F5181_GTW_GE_MPP_DEV 0x0 +#define RD_88F5181_GTW_GE_OE 0xFFFF07F0 +#define RD_88F5181_GTW_GE_OUT_VAL 0x80F + +#define DB_88F5X8X_DDRX_MPP0_7 0x00222222 +#define DB_88F5X8X_DDRX_MPP8_15 0x33330000 +#define DB_88F5X8X_DDRX_MPP16_23 0x0 +#define DB_88F5X8X_DDRX_MPP_DEV 0x0 +#define DB_88F5X8X_DDRX_OE 0xFFFF0330 +#define DB_88F5X8X_DDRX_OUT_VAL 0x0 + +#endif /* __INCmvBoard88F5181EnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.c new file mode 100644 index 0000000..b6d3bb3 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.c @@ -0,0 +1,354 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + + + +#define DB_88F5181L_BOARD_PCI_IF_NUM 0x3 +#define DB_88F5181L_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5181L_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5181L_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F5181L_BOARD_DEBUG_LED_NUM 0x0 +#define DB_88F5181L_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5181L_BOARD_DEVICE_CONFIG_NUM 0x4 + +MV_BOARD_PCI_IF db88f5181Lddr2InfoBoardPciIf[DB_88F5181L_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {12, 12, 12, 12}}, /* pciSlot0 */ + {8, {13, 13, 13, 13}}, /* pciSlot1 */ + {9, {13, 13, 13, 13}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5181Lddr2InfoBoardTwsiDev[DB_88F5181L_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5181Lddr2InfoBoardMacInfo[DB_88F5181L_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5181Lddr2InfoBoardGppInfo[DB_88F5181L_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 1}, + {BOARD_DEV_REF_CLCK, 11}}; + +MV_BOARD_MPP_INFO db88f5181Lddr2InfoBoardMppConfigValue[DB_88F5181L_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5181L_DDR2_2XTDM_MPP0_7, /* mpp0_7 */ + DB_88F5181L_DDR2_2XTDM_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO db88f5181Lddr2InfoBoardDeCsInfo[DB_88F5181L_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + {1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {2, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}, /* devCs2/flashCs */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5181Lddr2Info = { + "DB-88F5181L-DDR2-2xTDM", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5181L_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5181Lddr2InfoBoardMppConfigValue, + ((1<<8)|(1 << 9)|(1<<10)|(1<<12)|(1<<13)), /* intsGppMask */ + DB_88F5181L_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5181Lddr2InfoBoardDeCsInfo, + DB_88F5181L_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5181Lddr2InfoBoardPciIf, + DB_88F5181L_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5181Lddr2InfoBoardTwsiDev, + DB_88F5181L_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5181Lddr2InfoBoardMacInfo, + DB_88F5181L_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5181Lddr2InfoBoardGppInfo, + DB_88F5181L_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5181L_DDR2_2XTDM_OE, /* gppOutEnVal */ + DB_88F5181L_DDR2_2XTDM_OUT_VAL, /* gppOutVal */ + 0x3700, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + + + +#define RD_88F5181L_VOIP_FE_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5181L_VOIP_FE_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5181L_VOIP_FE_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5181L_VOIP_FE_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F5181L_VOIP_FE_BOARD_DEBUG_LED_NUM 0x3 +#define RD_88F5181L_VOIP_FE_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5181L_VOIP_FE_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 rd88f5181LvoipFeInfoBoardDebugLedIf[RD_88F5181L_VOIP_FE_BOARD_DEBUG_LED_NUM] = + {13, 14, 15}; + +MV_BOARD_PCI_IF rd88f5181LvoipFeInfoBoardPciIf[RD_88F5181L_VOIP_FE_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {4, 3, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5181LvoipFeInfoBoardTwsiDev[RD_88F5181L_VOIP_FE_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5181LvoipFeInfoBoardMacInfo[RD_88F5181L_VOIP_FE_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_100M, 0x0}}; + +MV_BOARD_SWITCH_INFO rd88f5181LvoipFeInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{-1, {0, 1, 2, 3, 4}, 5, 0}}; + +MV_BOARD_GPP_INFO rd88f5181LvoipFeInfoBoardGppInfo[RD_88F5181L_VOIP_FE_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 11}}; + +MV_BOARD_MPP_INFO rd88f5181LvoipFeInfoBoardMppConfigValue[RD_88F5181L_VOIP_FE_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181L_VOIP_FE_MPP0_7, /* mpp0_7 */ + RD_88F5181L_VOIP_FE_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5181LvoipFeInfoBoardDeCsInfo[RD_88F5181L_VOIP_FE_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181LvoipFeInfo = { + "RD-88F5181L-VOIP-FE", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5181L_VOIP_FE_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181LvoipFeInfoBoardMppConfigValue, + ((1<<2)|(1 << 3)|(1<<4)|(1<<5)|(1<<9)|(1<<11)), /* intsGppMask */ + RD_88F5181L_VOIP_FE_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181LvoipFeInfoBoardDeCsInfo, + RD_88F5181L_VOIP_FE_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5181LvoipFeInfoBoardPciIf, + RD_88F5181L_VOIP_FE_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5181LvoipFeInfoBoardTwsiDev, + RD_88F5181L_VOIP_FE_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181LvoipFeInfoBoardMacInfo, + RD_88F5181L_VOIP_FE_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5181LvoipFeInfoBoardGppInfo, + RD_88F5181L_VOIP_FE_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181LvoipFeInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5181L_VOIP_FE_GPP_OE, /* gppOutEnVal */ + RD_88F5181L_VOIP_FE_GPP_IO, /* gppOutVal */ + N_A, /* gppPolarityVal */ + rd88f5181LvoipFeInfoBoardSwitchInfo /* pSwitchInfo */ +}; + + + +#define RD_88F5181L_VOIP_GE_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5181L_VOIP_GE_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5181L_VOIP_GE_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5181L_VOIP_GE_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F5181L_VOIP_GE_BOARD_DEBUG_LED_NUM 0x4 +#define RD_88F5181L_VOIP_GE_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5181L_VOIP_GE_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 rd88f5181LvoipGeInfoBoardDebugLedIf[RD_88F5181L_VOIP_GE_BOARD_DEBUG_LED_NUM] = + {1, 2, 3, 0}; + +MV_BOARD_PCI_IF rd88f5181LvoipGeInfoBoardPciIf[RD_88F5181L_VOIP_GE_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {4, 10, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5181LvoipGeInfoBoardTwsiDev[RD_88F5181L_VOIP_GE_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5181LvoipGeInfoBoardMacInfo[RD_88F5181L_VOIP_GE_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_1000M, 0x0}}; + +MV_BOARD_SWITCH_INFO rd88f5181LvoipGeInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{8, {2, 1, 0, 7, 5}, 3, 1}}; + +MV_BOARD_GPP_INFO rd88f5181LvoipGeInfoBoardGppInfo[RD_88F5181L_VOIP_GE_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 5}}; + +MV_BOARD_MPP_INFO rd88f5181LvoipGeInfoBoardMppConfigValue[RD_88F5181L_VOIP_GE_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181L_VOIP_GE_MPP0_7, /* mpp0_7 */ + RD_88F5181L_VOIP_GE_MPP8_15, /* mpp8_15 */ + RD_88F5181L_VOIP_GE_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5181LvoipGeInfoBoardDeCsInfo[RD_88F5181L_VOIP_GE_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181LvoipGeInfo = { + "RD-88F5181L-VOIP-GE", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5181L_VOIP_GE_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181LvoipGeInfoBoardMppConfigValue, + ((1<<4)|(1 << 5)|(1<<8)), /* intsGppMask */ + RD_88F5181L_VOIP_GE_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181LvoipGeInfoBoardDeCsInfo, + RD_88F5181L_VOIP_GE_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5181LvoipGeInfoBoardPciIf, + RD_88F5181L_VOIP_GE_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5181LvoipGeInfoBoardTwsiDev, + RD_88F5181L_VOIP_GE_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181LvoipGeInfoBoardMacInfo, + RD_88F5181L_VOIP_GE_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5181LvoipGeInfoBoardGppInfo, + RD_88F5181L_VOIP_GE_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181LvoipGeInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5181L_VOIP_GE_GPP_OE, /* gppOutEnVal */ + RD_88F5181L_VOIP_GE_GPP_IO, /* gppOutVal */ + N_A, /* gppPolarityVal */ + rd88f5181LvoipGeInfoBoardSwitchInfo /* pSwitchInfo */ +}; + + +#define RD_88F5181L_FXO_GE_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5181L_FXO_GE_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5181L_FXO_GE_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5181L_FXO_GE_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F5181L_FXO_GE_BOARD_DEBUG_LED_NUM 0x1 +#define RD_88F5181L_FXO_GE_BOARD_MPP_CONFIG_NUM 0x3 +#define RD_88F5181L_FXO_GE_BOARD_DEVICE_CONFIG_NUM 0x1 + +/* Note the last LED's will be use for init and Linux heartbeat */ +MV_U8 rd88f5181LFXOGeInfoBoardDebugLedIf[RD_88F5181L_FXO_GE_BOARD_DEBUG_LED_NUM] = + {0}; + +MV_BOARD_PCI_IF rd88f5181LFXOGeInfoBoardPciIf[RD_88F5181L_FXO_GE_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {1, 1, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5181LFXOGeInfoBoardTwsiDev[RD_88F5181L_FXO_GE_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5181LFXOGeInfoBoardMacInfo[RD_88F5181L_FXO_GE_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_1000M, 0x0}}; + +MV_BOARD_SWITCH_INFO rd88f5181LFXOGeInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{-1, {2, 1, 0, 7, 5}, 3, 1}}; + +MV_BOARD_GPP_INFO rd88f5181LFXOGeInfoBoardGppInfo[RD_88F5181L_FXO_GE_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 5}}; + +MV_BOARD_MPP_INFO rd88f5181LFXOGeInfoBoardMppConfigValue[RD_88F5181L_FXO_GE_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181L_FXO_GE_MPP0_7, /* mpp0_7 */ + RD_88F5181L_FXO_GE_MPP8_15, /* mpp8_15 */ + RD_88F5181L_FXO_GE_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5181LFXOGeInfoBoardDeCsInfo[RD_88F5181L_FXO_GE_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{3,0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181LFXOGeInfo = { + "RD-88F5181L-VOIP-FXO-GE", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5181L_FXO_GE_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181LFXOGeInfoBoardMppConfigValue, + ((1 << 1)|(1 << 3)|(1 << 8)|(1 << 11)), /* intsGppMask */ + RD_88F5181L_FXO_GE_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181LFXOGeInfoBoardDeCsInfo, + RD_88F5181L_FXO_GE_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5181LFXOGeInfoBoardPciIf, + RD_88F5181L_FXO_GE_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5181LFXOGeInfoBoardTwsiDev, + RD_88F5181L_FXO_GE_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181LFXOGeInfoBoardMacInfo, + RD_88F5181L_FXO_GE_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5181LFXOGeInfoBoardGppInfo, /* pBoardGppInfo */ + RD_88F5181L_FXO_GE_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181LFXOGeInfoBoardDebugLedIf, /* ledsPolarity */ + 0, /* ledsPolarity */ + RD_88F5181L_FXO_GE_GPP_OE, /* gppOutEnVal */ + RD_88F5181L_FXO_GE_GPP_IO, /* gppOutVal */ + 0x2, /* gppPolarityVal */ + rd88f5181LFXOGeInfoBoardSwitchInfo /* pSwitchInfo */ +}; + +MV_BOARD_INFO* boardInfoTbl[4] = {&db88f5181Lddr2Info, + &rd88f5181LvoipFeInfo, + &rd88f5181LvoipGeInfo, + &rd88f5181LFXOGeInfo + }; + +#define BOARD_ID_BASE BOARD_ID_88F5181L_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F5181L_MAX + + diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.h new file mode 100644 index 0000000..ce7852a --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5181LBoardEnv.h @@ -0,0 +1,115 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F5181LEnvSpech +#define __INCmvBoard88F5181LEnvSpech + + + +/* 88F5181L based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88F5181L_BASE 0x30 + +/* Old board ID numbers for backward compatability */ +#define DB_88F5181L_DDR2_2XTDM_OLD 0xC +#define RD_88F5181L_VOIP_FE_OLD 0xD +#define RD_88F5181L_VOIP_GE_OLD 0xE +/* New board ID numbers */ +#define DB_88F5181L_DDR2_2XTDM (BOARD_ID_88F5181L_BASE+0x0) +#define RD_88F5181L_VOIP_FE (BOARD_ID_88F5181L_BASE+0x1) +#define RD_88F5181L_VOIP_GE (BOARD_ID_88F5181L_BASE+0x2) +#define RD_88F5181L_VOIP_FXO_GE (BOARD_ID_88F5181L_BASE+0x3) + +#define BOARD_ID_88F5181L_MAX (BOARD_ID_88F5181L_BASE+0x4) + +#define DB_88F5181L_DDR2_2XTDM_MPP0_7 0x00222203 +#define DB_88F5181L_DDR2_2XTDM_MPP8_15 0x44000000 +#define DB_88F5181L_DDR2_2XTDM_MPP16_23 0x0 +#define DB_88F5181L_DDR2_2XTDM_MPP_DEV 0x0 +#define DB_88F5181L_DDR2_2XTDM_OE 0xFFFDFFD7 +#define DB_88F5181L_DDR2_2XTDM_OUT_VAL 0x0 + +#define RD_88F5181L_VOIP_FE_MPP0_7 0x55000003 +#define RD_88F5181L_VOIP_FE_MPP8_15 0x00000101 +#define RD_88F5181L_VOIP_FE_MPP16_23 0x0 +#define RD_88F5181L_VOIP_FE_MPP_DEV 0x0 +#define RD_88F5181L_VOIP_FE_GPP_OE 0xFFFF0FFC +#define RD_88F5181L_VOIP_FE_GPP_IO 0xF001 + +#define RD_88F5181L_VOIP_GE_MPP0_7 0x55000003 +#define RD_88F5181L_VOIP_GE_MPP8_15 0x11110010 +#define RD_88F5181L_VOIP_GE_MPP16_23 0x1111 +#define RD_88F5181L_VOIP_GE_MPP_DEV 0x0 +#define RD_88F5181L_VOIP_GE_GPP_OE 0xFFFF07F0 +#define RD_88F5181L_VOIP_GE_GPP_IO 0x80F + +#define RD_88F5181L_FXO_GE_MPP0_7 0x55000003 +#define RD_88F5181L_FXO_GE_MPP8_15 0x11110010 +#define RD_88F5181L_FXO_GE_MPP16_23 0x1111 +#define RD_88F5181L_FXO_GE_MPP_DEV 0x80000000 +#define RD_88F5181L_FXO_GE_GPP_OE 0x7FFFF2C2 +#define RD_88F5181L_FXO_GE_GPP_IO 0xBFF + +#endif /* __INCmvBoard88F5181LEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.c new file mode 100644 index 0000000..e0e57be --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.c @@ -0,0 +1,355 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#define DB_88F5182_BOARD_PCI_IF_NUM 0x3 +#define DB_88F5182_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F5182_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F5182_BOARD_GPP_INFO_NUM 0x4 +#define DB_88F5182_BOARD_DEBUG_LED_NUM 0x0 +#define DB_88F5182_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F5182_BOARD_DEVICE_CONFIG_NUM 0x4 + +MV_BOARD_PCI_IF db88f5182ddr2InfoBoardPciIf[DB_88F5182_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {0, 0, 0, 0}}, /* pciSlot0 */ + {8, {1, 1, 1, 1}}, /* pciSlot1 */ + {9, {1, 1, 1, 1}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5182ddr2InfoBoardTwsiDev[DB_88F5182_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5182ddr2InfoBoardMacInfo[DB_88F5182_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5182ddr2InfoBoardGppInfo[DB_88F5182_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 8}, + {BOARD_DEV_USB_VBUS, 9}, + {BOARD_DEV_REF_CLCK, 11}}; + +MV_BOARD_MPP_INFO db88f5182ddr2InfoBoardMppConfigValue[DB_88F5182_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5182_DDR2_MPP0_7, /* mpp0_7 */ + DB_88F5182_DDR2_MPP8_15, /* mpp8_15 */ + DB_88F5182_DDR2_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO db88f5182ddr2InfoBoardDeCsInfo[DB_88F5182_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + {1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {2, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}, /* devCs2/flashCs */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO db88f5182ddr2Info = { + "DB-88F5182-DDR2", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5182_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5182ddr2InfoBoardMppConfigValue, + ((1<<0)|(1 << 1)|(1<<10)), /* intsGppMask */ + DB_88F5182_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5182ddr2InfoBoardDeCsInfo, + DB_88F5182_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5182ddr2InfoBoardPciIf, + DB_88F5182_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5182ddr2InfoBoardTwsiDev, + DB_88F5182_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5182ddr2InfoBoardMacInfo, + DB_88F5182_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5182ddr2InfoBoardGppInfo, + DB_88F5182_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5182_DDR2_OE, /* gppOutEnVal */ + DB_88F5182_DDR2_OUT_VAL, /* gppOutVal */ + 0x403, /* gppPolarityVal */ +}; + +#define DB_88F5182_BOARD_A_PCI_IF_NUM 0x2 +#define DB_88F5182_BOARD_A_TWSI_DEF_NUM 0x1 +#define DB_88F5182_BOARD_A_MAC_INFO_NUM 0x1 +#define DB_88F5182_BOARD_A_GPP_INFO_NUM 0x4 +#define DB_88F5182_BOARD_A_DEBUG_LED_NUM 0x0 +#define DB_88F5182_BOARD_A_MPP_CONFIG_NUM 0x1 +#define DB_88F5182_BOARD_A_DEVICE_CONFIG_NUM 0x4 + +MV_BOARD_PCI_IF db88f5182ddr2AInfoBoardPciIf[DB_88F5182_BOARD_A_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{8, {1, 1, 1, 1}}, /* pciSlot1 */ + {9, {1, 1, 1, 1}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88f5182ddr2AInfoBoardTwsiDev[DB_88F5182_BOARD_A_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f5182ddr2AInfoBoardMacInfo[DB_88F5182_BOARD_A_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88f5182ddr2AInfoBoardGppInfo[DB_88F5182_BOARD_A_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}, + {BOARD_DEV_USB_VBUS, 8}, + {BOARD_DEV_USB_VBUS, 9}, + {BOARD_DEV_REF_CLCK, 11}}; + +MV_BOARD_MPP_INFO db88f5182ddr2AInfoBoardMppConfigValue[DB_88F5182_BOARD_A_MPP_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F5182_DDR2_A_MPP0_7, /* mpp0_7 */ + DB_88F5182_DDR2_A_MPP8_15, /* mpp8_15 */ + DB_88F5182_DDR2_A_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#else + {{{DB_88F5182_DDR2_A_MPP0_7NB, /* mpp0_7 */ + DB_88F5182_DDR2_A_MPP8_15NB, /* mpp8_15 */ + DB_88F5182_DDR2_A_MPP16_23NB, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#endif + +MV_DEV_CS_INFO db88f5182ddr2AInfoBoardDeCsInfo[DB_88F5182_BOARD_A_DEVICE_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + {1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {2, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}, /* devCs2/flashCs */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ +#else + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + {1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {2, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs2/flashCs */ + {3, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* bootCs */ +#endif + +MV_BOARD_INFO db88f5182ddr2AInfo = { + "DB-88F5182-DDR2-NAND-SUPPORT", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F5182_BOARD_A_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f5182ddr2AInfoBoardMppConfigValue, + ((1 << 1)|(1<<10)), /* intsGppMask */ + DB_88F5182_BOARD_A_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f5182ddr2AInfoBoardDeCsInfo, + DB_88F5182_BOARD_A_PCI_IF_NUM, /* numBoardPciIf */ + db88f5182ddr2AInfoBoardPciIf, + DB_88F5182_BOARD_A_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f5182ddr2AInfoBoardTwsiDev, + DB_88F5182_BOARD_A_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f5182ddr2AInfoBoardMacInfo, + DB_88F5182_BOARD_A_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f5182ddr2AInfoBoardGppInfo, + DB_88F5182_BOARD_A_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88F5182_DDR2_A_OE, /* gppOutEnVal */ + DB_88F5182_DDR2_A_OUT_VAL, /* gppOutVal */ + 0x403, /* gppPolarityVal */ +}; + + +#define RD_88F5182_2XSATA_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5182_2XSATA_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5182_2XSATA_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5182_2XSATA_BOARD_GPP_INFO_NUM 0x1 +#define RD_88F5182_2XSATA_BOARD_DEBUG_LED_NUM 0x1 +#define RD_88F5182_2XSATA_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5182_2XSATA_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 rd88f5182sataX2InfoBoardDebugLedIf[RD_88F5182_2XSATA_BOARD_DEBUG_LED_NUM] = + {0}; + +MV_BOARD_PCI_IF rd88f5182sataX2InfoBoardPciIf[RD_88F5182_2XSATA_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {7, 6, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88f5182sataX2InfoBoardTwsiDev[RD_88F5182_2XSATA_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5182sataX2InfoBoardMacInfo[RD_88F5182_2XSATA_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO rd88f5182sataX2InfoBoardGppInfo[RD_88F5182_2XSATA_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 3}}; + +MV_BOARD_MPP_INFO rd88f5182sataX2InfoBoardMppConfigValue[RD_88F5182_2XSATA_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5182_2XSATA_MPP0_7, /* mpp0_7 */ + RD_88F5182_2XSATA_MPP8_15, /* mpp8_15 */ + RD_88F5182_2XSATA_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5182sataX2InfoBoardDeCsInfo[RD_88F5182_2XSATA_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs1 */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5182sataX2Info = { + "RD-88F5182-NAS-2", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5182_2XSATA_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5182sataX2InfoBoardMppConfigValue, + ((1<<3)|(1 << 6)|(1<<7)), /* intsGppMask */ + RD_88F5182_2XSATA_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5182sataX2InfoBoardDeCsInfo, + RD_88F5182_2XSATA_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5182sataX2InfoBoardPciIf, + RD_88F5182_2XSATA_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5182sataX2InfoBoardTwsiDev, + RD_88F5182_2XSATA_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5182sataX2InfoBoardMacInfo, + RD_88F5182_2XSATA_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5182sataX2InfoBoardGppInfo, + RD_88F5182_2XSATA_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5182sataX2InfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5182_2XSATA_OE, /* gppOutEnVal */ + RD_88F5182_2XSATA_OUT_VAL, /* gppOutVal */ + RD_88F5182_2XSATA_POL, /* gppPolarityVal */ +}; + + +#define RD_88F5182_2XSATA3_BOARD_PCI_IF_NUM 0x1 +#define RD_88F5182_2XSATA3_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F5182_2XSATA3_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F5182_2XSATA3_BOARD_GPP_INFO_NUM 0x4 +#define RD_88F5182_2XSATA3_BOARD_DEBUG_LED_NUM 0x2 +#define RD_88F5182_2XSATA3_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F5182_2XSATA3_BOARD_DEVICE_CONFIG_NUM 0x2 + +MV_U8 rd88f5182sataX23InfoBoardDebugLedIf[RD_88F5182_2XSATA3_BOARD_DEBUG_LED_NUM] = + {0, 1}; + +MV_BOARD_PCI_IF rd88f5182sataX23InfoBoardPciIf[RD_88F5182_2XSATA3_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {7, N_A, N_A, N_A}}}; + +MV_BOARD_TWSI_INFO rd88f5182sataX23InfoBoardTwsiDev[RD_88F5182_2XSATA3_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f5182sataX23InfoBoardMacInfo[RD_88F5182_2XSATA3_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO rd88f5182sataX23InfoBoardGppInfo[RD_88F5182_2XSATA3_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 3}, + {BOARD_DEV_POWER_BUTTON, 6}, + {BOARD_DEV_HDD0_POWER, 2}, + {BOARD_DEV_HDD1_POWER, 8} + }; + +MV_BOARD_MPP_INFO rd88f5182sataX23InfoBoardMppConfigValue[RD_88F5182_2XSATA3_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5182_2XSATA3_MPP0_7, /* mpp0_7 */ + RD_88F5182_2XSATA3_MPP8_15, /* mpp8_15 */ + RD_88F5182_2XSATA3_MPP16_23, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + +MV_DEV_CS_INFO rd88f5182sataX23InfoBoardDeCsInfo[RD_88F5182_2XSATA3_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{1, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}, /* devCs1 */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88f5182sataX23Info = { + "RD-88F5182-NAS-3", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F5182_2XSATA3_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5182sataX23InfoBoardMppConfigValue, + ((1<<3) | (1<<7)), /* intsGppMask */ + RD_88F5182_2XSATA3_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5182sataX23InfoBoardDeCsInfo, + RD_88F5182_2XSATA3_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88f5182sataX23InfoBoardPciIf, + RD_88F5182_2XSATA3_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f5182sataX23InfoBoardTwsiDev, + RD_88F5182_2XSATA3_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5182sataX23InfoBoardMacInfo, + RD_88F5182_2XSATA3_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f5182sataX23InfoBoardGppInfo, + RD_88F5182_2XSATA3_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5182sataX23InfoBoardDebugLedIf, + 1, /* ledsPolarity */ + RD_88F5182_2XSATA3_OE, /* gppOutEnVal */ + RD_88F5182_2XSATA3_OUT_VAL, /* gppOutVal */ + N_A, /* gppPolarityVal */ +}; + +MV_BOARD_INFO* boardInfoTbl[] = {&db88f5182ddr2Info, + &rd88f5182sataX2Info, + &rd88f5182sataX23Info, + &db88f5182ddr2AInfo + }; + + +#define BOARD_ID_BASE BOARD_ID_88F5182_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F5182_MAX diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.h new file mode 100644 index 0000000..d833b8e --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F5182BoardEnv.h @@ -0,0 +1,117 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F5182EnvSpech +#define __INCmvBoard88F5182EnvSpech + + +/* 88F5182 based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88F5182_BASE 0x20 + +/* Old board ID numbers for backward compatability */ +#define DB_88F5182_DDR2_OLD 0xA +#define RD_88F5182_2XSATA_OLD 0xB +#define RD_88F5182_2XSATA3_OLD 0xF +/* New board ID numbers */ +#define DB_88F5182_DDR2 (BOARD_ID_88F5182_BASE+0x0) +#define RD_88F5182_2XSATA (BOARD_ID_88F5182_BASE+0x1) +#define RD_88F5182_2XSATA_OPEN_LINUX_ID 1508 +#define RD_88F5182_2XSATA3 (BOARD_ID_88F5182_BASE+0x2) +#define DB_88F5182_DDR2_A (BOARD_ID_88F5182_BASE+0x3) + +#define BOARD_ID_88F5182_MAX (BOARD_ID_88F5182_BASE+0x4) + + + +#define DB_88F5182_DDR2_MPP0_7 0x55222203 +#define DB_88F5182_DDR2_MPP8_15 0x44550000 +#define DB_88F5182_DDR2_MPP16_23 0x0 +#define DB_88F5182_DDR2_OE 0xFFF5FFD7 +#define DB_88F5182_DDR2_OUT_VAL 0x0 + +#define DB_88F5182_DDR2_A_MPP0_7 0x55222203 +#define DB_88F5182_DDR2_A_MPP8_15 0x44550000 +#define DB_88F5182_DDR2_A_MPP16_23 0x0 +#define DB_88F5182_DDR2_A_MPP0_7NB 0x55442203 +#define DB_88F5182_DDR2_A_MPP8_15NB 0x44550000 +#define DB_88F5182_DDR2_A_MPP16_23NB 0x0 +#define DB_88F5182_DDR2_A_OE 0xFFF5FFD7 +#define DB_88F5182_DDR2_A_OUT_VAL 0x0 + +#define RD_88F5182_2XSATA_MPP0_7 0x00000003 +#define RD_88F5182_2XSATA_MPP8_15 0x55550000 +#define RD_88F5182_2XSATA_MPP16_23 0x5555 +#define RD_88F5182_2XSATA_OE 0xFFF0F0C8 +#define RD_88F5182_2XSATA_OUT_VAL 0x402 +#define RD_88F5182_2XSATA_POL 0xC8 + +#define RD_88F5182_2XSATA3_MPP0_7 0x00000003 +#define RD_88F5182_2XSATA3_MPP8_15 0x55550000 +#define RD_88F5182_2XSATA3_MPP16_23 0x5555 +#define RD_88F5182_2XSATA3_OE 0xFFCF0EF8 +#define RD_88F5182_2XSATA3_OUT_VAL 0x104 /* Enable the power for HD-0 on MPP_2 and HD-1 on MPP_8 */ + +#endif /* __INCmvBoard88F5182EnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.c new file mode 100644 index 0000000..1305252 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.c @@ -0,0 +1,441 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define DB_88F6082BP_BOARD_PCI_IF_NUM 0x0 +#define DB_88F6082BP_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F6082BP_BOARD_MAC_INFO_NUM 0x2 +#define DB_88F6082BP_BOARD_GPP_INFO_NUM 0x1 +#define DB_88F6082BP_BOARD_DEBUG_LED_NUM 0x1 +#define DB_88F6082BP_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F6082BP_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 db88f6082BpInfoBoardDebugLedIf[DB_88F6082BP_BOARD_DEBUG_LED_NUM] = + {2}; + +MV_BOARD_TWSI_INFO db88f6082BpInfoBoardTwsiDev[DB_88F6082BP_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f6082BpInfoBoardMacInfo[DB_88F6082BP_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}, + {BOARD_MAC_SPEED_AUTO, 0x9}, + }; + +MV_BOARD_GPP_INFO db88f6082BpInfoBoardGppInfo[DB_88F6082BP_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RESET, 7}}; + +MV_BOARD_MPP_INFO db88f6082BpInfoBoardMppConfigValue[DB_88F6082BP_BOARD_MPP_CONFIG_NUM] = +#if !defined(MV_NAND) && !defined(MV_NAND_BOOT) + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F6082_BP_MPP0_7, /* mpp0_7 */ + DB_88F6082_BP_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#else + {{{DB_88F6082_BP_MPP0_7_NB, /* mpp0_7 */ + DB_88F6082_BP_MPP8_15_NB, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#endif + +#if defined(MV_NAND) || defined(MV_NAND_BOOT) +MV_DEV_CS_INFO db88f6082BpInfoBoardDeCsInfo[DB_88F6082BP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else +MV_DEV_CS_INFO db88f6082BpInfoBoardDeCsInfo[DB_88F6082BP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ +#endif + +MV_BOARD_INFO db88f6082BpInfo = { + "DB-88F6082-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6082BP_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6082BpInfoBoardMppConfigValue, + 0, /* intsGppMask */ + DB_88F6082BP_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6082BpInfoBoardDeCsInfo, + DB_88F6082BP_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + DB_88F6082BP_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6082BpInfoBoardTwsiDev, + DB_88F6082BP_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f6082BpInfoBoardMacInfo, + DB_88F6082BP_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f6082BpInfoBoardGppInfo, + DB_88F6082BP_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f6082BpInfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + DB_88F6082_BP_OE, /* gppOutEnVal */ + DB_88F6082_BP_OE_VAL, /* gppOutVal */ + 0x1 /* gppPolarityVal */ +}; + + +#define DB_88F6082LBP_BOARD_PCI_IF_NUM 0x0 +#define DB_88F6082LBP_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88F6082LBP_BOARD_MAC_INFO_NUM 0x2 +#define DB_88F6082LBP_BOARD_GPP_INFO_NUM 0x1 +#define DB_88F6082LBP_BOARD_DEBUG_LED_NUM 0x2 +#define DB_88F6082LBP_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F6082LBP_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 db88f6082LBpInfoBoardDebugLedIf[DB_88F6082LBP_BOARD_DEBUG_LED_NUM] = + {1, 2}; + +MV_BOARD_TWSI_INFO db88f6082LBpInfoBoardTwsiDev[DB_88F6082LBP_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88f6082LBpInfoBoardMacInfo[DB_88F6082LBP_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}, + {BOARD_MAC_SPEED_AUTO, 0x9}, + }; + +MV_BOARD_GPP_INFO db88f6082LBpInfoBoardGppInfo[DB_88F6082LBP_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RESET, 7}}; + +MV_BOARD_MPP_INFO db88f6082LBpInfoBoardMppConfigValue[DB_88F6082LBP_BOARD_MPP_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F6082L_BP_MPP0_7, /* mpp0_7 */ + DB_88F6082L_BP_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#else + {{{DB_88F6082L_BP_MPP0_7_NB, /* mpp0_7 */ + DB_88F6082L_BP_MPP8_15_NB, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#endif + +#if defined(MV_NAND) || defined(MV_NAND_BOOT) +MV_DEV_CS_INFO db88f6082LBpInfoBoardDeCsInfo[DB_88F6082LBP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else +MV_DEV_CS_INFO db88f6082LBpInfoBoardDeCsInfo[DB_88F6082LBP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ +#endif + +MV_BOARD_INFO db88f6082LBpInfo = { + "DB-88F6082L-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6082LBP_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6082LBpInfoBoardMppConfigValue, + 0, /* intsGppMask */ + DB_88F6082LBP_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6082LBpInfoBoardDeCsInfo, + DB_88F6082LBP_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + DB_88F6082LBP_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6082LBpInfoBoardTwsiDev, + DB_88F6082LBP_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f6082LBpInfoBoardMacInfo, + DB_88F6082LBP_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f6082LBpInfoBoardGppInfo, + DB_88F6082LBP_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f6082LBpInfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + DB_88F6082L_BP_OE, /* gppOutEnVal */ + DB_88F6082L_BP_OE_VAL, /* gppOutVal */ + 0x1 /* gppPolarityVal */ +}; + + +#define RD_88F6082NAS_BOARD_PCI_IF_NUM 0x0 +#define RD_88F6082NAS_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F6082NAS_BOARD_MAC_INFO_NUM 0x2 +#define RD_88F6082NAS_BOARD_GPP_INFO_NUM 0x6 +#define RD_88F6082NAS_BOARD_DEBUG_LED_NUM 0x0 +#define RD_88F6082NAS_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F6082NAS_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_BOARD_TWSI_INFO rd88f6082NasInfoBoardTwsiDev[RD_88F6082NAS_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f6082NasInfoBoardMacInfo[RD_88F6082NAS_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}, + {BOARD_MAC_SPEED_AUTO, 0x9}, + }; + +MV_BOARD_GPP_INFO rd88f6082NasInfoBoardGppInfo[RD_88F6082NAS_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RESET, 0}, + {BOARD_DEV_POWER_BUTTON, 2}, + {BOARD_DEV_RTC, 7}, + {BOARD_DEV_USB_VBUS, 10}, + {BOARD_DEV_HDD_POWER, 11}, + {BOARD_DEV_HDD0_POWER, 11} + }; + +MV_BOARD_MPP_INFO rd88f6082NasInfoBoardMppConfigValue[RD_88F6082NAS_BOARD_MPP_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F6082_NAS_MPP0_7, /* mpp0_7 */ + RD_88F6082_NAS_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}}, /* mppDev */ + }; +#else + {{{RD_88F6082_NAS_MPP0_7_NB, /* mpp0_7 */ + RD_88F6082_NAS_MPP8_15_NB, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#endif + +MV_DEV_CS_INFO rd88f6082NasInfoBoardDeCsInfo[RD_88F6082NAS_BOARD_DEVICE_CONFIG_NUM] = +#if defined(MV_NAND) || defined(MV_NAND_BOOT) + /*{params, devType, devWidth}*/ + {{ 0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ +#endif + +MV_BOARD_INFO rd88f6082NasInfo = { + "RD-88F6082-NAS-B", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6082NAS_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6082NasInfoBoardMppConfigValue, + 0, /* intsGppMask */ + RD_88F6082NAS_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f6082NasInfoBoardDeCsInfo, + RD_88F6082NAS_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + RD_88F6082NAS_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f6082NasInfoBoardTwsiDev, + RD_88F6082NAS_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6082NasInfoBoardMacInfo, + RD_88F6082NAS_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6082NasInfoBoardGppInfo, + RD_88F6082NAS_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + RD_88F6082_NAS_OE, /* gppOutEnVal */ + RD_88F6082_NAS_OE_VAL, /* gppOutVal */ + 0x0 /* gppPolarityVal */ +}; + + +#define RD_88F6082MICRO_DAS_NAS_BOARD_PCI_IF_NUM 0x0 +#define RD_88F6082MICRO_DAS_NAS_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F6082MICRO_DAS_NAS_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F6082MICRO_DAS_NAS_BOARD_GPP_INFO_NUM 0x8 +#define RD_88F6082MICRO_DAS_NAS_BOARD_DEBUG_LED_NUM 0x0 +#define RD_88F6082MICRO_DAS_NAS_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F6082MICRO_DAS_NAS_BOARD_DEVICE_CONFIG_NUM 0x0 + +MV_BOARD_TWSI_INFO rd88f6082uDasNasInfoBoardTwsiDev[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f6082uDasNasInfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8} + }; + +MV_BOARD_GPP_INFO rd88f6082uDasNasInfoBoardGppInfo[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RESET, 0}, + {BOARD_DEV_POWER_BUTTON, 15}, + {BOARD_DEV_RESTOR_BUTTON, 5}, + {BOARD_DEV_RTC, 7}, + {BOARD_DEV_USB_VBUS, 11}, + {BOARD_DEV_HDD0_POWER, 13}, + {BOARD_DEV_FAN_POWER, 12}, + {BOARD_DEV_POWER_ON_LED, 6} + }; + +MV_BOARD_MPP_INFO rd88f6082uDasNasInfoBoardMppConfigValue[] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F6082_MICRO_DAS_NAS_MPP0_7, /* mpp0_7 */ + RD_88F6082_MICRO_DAS_NAS_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; + + +MV_BOARD_INFO rd88f6082uDasNasInfo = { + "RD-88F6082-MICRO-DAS-NAS", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6082MICRO_DAS_NAS_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6082uDasNasInfoBoardMppConfigValue, + 0, /* intsGppMask */ + RD_88F6082MICRO_DAS_NAS_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + NULL, + RD_88F6082MICRO_DAS_NAS_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + RD_88F6082MICRO_DAS_NAS_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f6082uDasNasInfoBoardTwsiDev, + RD_88F6082MICRO_DAS_NAS_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6082uDasNasInfoBoardMacInfo, + RD_88F6082MICRO_DAS_NAS_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6082uDasNasInfoBoardGppInfo, + RD_88F6082MICRO_DAS_NAS_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + RD_88F6082_MICRO_DAS_NAS_OE, /* gppOutEnVal */ + RD_88F6082_MICRO_DAS_NAS_OE_VAL, /* gppOutVal */ + BIT15 /* gppPolarityVal */ +}; + +#define RD_88F6082_DX243_BOARD_PCI_IF_NUM 0x0 +#define RD_88F6082_DX243_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F6082_DX243_BOARD_MAC_INFO_NUM 0x2 +#define RD_88F6082_DX243_BOARD_GPP_INFO_NUM 0x2 +#define RD_88F6082_DX243_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F6082_DX243_BOARD_DEVICE_CONFIG_NUM 0x1 +#define RD_88F6082_DX243_BOARD_DEBUG_LED_NUM 0x2 + +MV_U8 rd88f6082Dx243InfoBoardDebugLedIf[] = + {1, 2}; + +MV_BOARD_TWSI_INFO rd88f6082Dx243InfoBoardTwsiDev[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f6082Dx243InfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}, + {BOARD_MAC_SPEED_AUTO, 0x9} + }; + +MV_BOARD_GPP_INFO rd88f6082Dx243InfoBoardGppInfo[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RESET, 0}, + {BOARD_DEV_RTC, 7}}; + +MV_BOARD_MPP_INFO rd88f6082Dx243InfoBoardMppConfigValue[] = +#ifndef MV_NAND_BOOT + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F6082_DX243_MPP0_7, /* mpp0_7 */ + RD_88F6082_DX243_MPP8_15, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#else + {{{RD_88F6082_DX243_MPP0_7_NB, /* mpp0_7 */ + RD_88F6082_DX243_MPP8_15_NB, /* mpp8_15 */ + N_A, /* mpp16_23 */ + N_A}} /* mppDev */ + }; +#endif + +#if defined(MV_NAND) || defined(MV_NAND_BOOT) +MV_DEV_CS_INFO rd88f6082Dx243InfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else +MV_DEV_CS_INFO rd88f6082Dx243InfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ +#endif + +MV_BOARD_INFO rd88f6082Dx243Info = { + "RD-DX243-6082-24G", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6082_DX243_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6082Dx243InfoBoardMppConfigValue, + ((1 << 10) | (1 << 11) | (1 << 7)), /* intsGppMask */ + RD_88F6082_DX243_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f6082Dx243InfoBoardDeCsInfo, + RD_88F6082_DX243_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + RD_88F6082_DX243_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f6082Dx243InfoBoardTwsiDev, + RD_88F6082_DX243_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6082Dx243InfoBoardMacInfo, + RD_88F6082_DX243_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6082Dx243InfoBoardGppInfo, + RD_88F6082_DX243_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f6082Dx243InfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + RD_88F6082_DX243_OE, /* gppOutEnVal */ + RD_88F6082_DX243_OE_VAL, /* gppOutVal */ + (BIT1 | BIT2) /* gppPolarityVal */ +}; + +MV_BOARD_INFO* boardInfoTbl[] = {&db88f6082BpInfo, + NULL, + &rd88f6082NasInfo, + NULL, + &db88f6082LBpInfo, + NULL, + &rd88f6082uDasNasInfo, + &rd88f6082Dx243Info + }; + + + +#define BOARD_ID_BASE BOARD_ID_88F6082_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F6082_MAX diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.h new file mode 100644 index 0000000..16efb46 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6082BoardEnv.h @@ -0,0 +1,119 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F6082BoardEnvSpech +#define __INCmvBoard88F6082BoardEnvSpech + + +/* 88F6082 based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88F6082_BASE 0x70 + +/* New board ID numbers */ +#define DB_88F6082_BP (BOARD_ID_88F6082_BASE+0x0) +#define RD_88F6082_NAS (BOARD_ID_88F6082_BASE+0x2) +#define DB_88F6082L_BP (BOARD_ID_88F6082_BASE+0x4) +#define RD_88F6082_MICRO_DAS_NAS (BOARD_ID_88F6082_BASE+0x6) +#define RD_88F6082_DX243_24G (BOARD_ID_88F6082_BASE+0x7) +#define BOARD_ID_88F6082_MAX (BOARD_ID_88F6082_BASE+0x8) + + +#define RD_88F6082_NAS_MPP0_7 0x01111300 +#define RD_88F6082_NAS_MPP8_15 0x11110011 +#define RD_88F6082_NAS_MPP0_7_NB 0x01111300 +#define RD_88F6082_NAS_MPP8_15_NB 0x11110011 +#define RD_88F6082_NAS_OE 0xFFFFF7FF +#define RD_88F6082_NAS_OE_VAL 0x0 + +#define DB_88F6082_BP_MPP0_7 0x01111000 +#define DB_88F6082_BP_MPP8_15 0x22221111 +#define DB_88F6082_BP_MPP0_7_NB 0x01111000 +#define DB_88F6082_BP_MPP8_15_NB 0x11111111 +#define DB_88F6082_BP_OE 0xFFFFFF79 +#define DB_88F6082_BP_OE_VAL 0x86 + +#define DB_88F6082L_BP_MPP0_7 0x01111000 +#define DB_88F6082L_BP_MPP8_15 0x22221111 +#define DB_88F6082L_BP_MPP0_7_NB 0x01111000 +#define DB_88F6082L_BP_MPP8_15_NB 0x11111111 +#define DB_88F6082L_BP_OE 0xFFFFFF79 +#define DB_88F6082L_BP_OE_VAL BIT7 + +/* The MPP config and output enable is delibarate done for input. + The change from input to output for example on the HDD power MPP + is done inside the code when setting the power enable. */ +#define RD_88F6082_MICRO_DAS_NAS_MPP0_7 0x00001000 +#define RD_88F6082_MICRO_DAS_NAS_MPP8_15 0x00000011 +#define RD_88F6082_MICRO_DAS_NAS_OE 0xFFFFFFFF +#define RD_88F6082_MICRO_DAS_NAS_OE_VAL 0x0 + +#define RD_88F6082_DX243_MPP0_7 0x01110000 +#define RD_88F6082_DX243_MPP8_15 0x22220011 +#define RD_88F6082_DX243_MPP0_7_NB 0x01110000 +#define RD_88F6082_DX243_MPP8_15_NB 0x11110011 +#define RD_88F6082_DX243_OE 0xFFFFFFF9 +#define RD_88F6082_DX243_OE_VAL 0x0 + +#endif /* __INCmvBoard88F6082EnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.c new file mode 100644 index 0000000..676a6a1 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.c @@ -0,0 +1,275 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define DB_88F6183BP_BOARD_PCI_IF_NUM 0x0 +#define DB_88F6183BP_BOARD_TWSI_DEF_NUM 0x2 +#define DB_88F6183BP_BOARD_MAC_INFO_NUM 0x1 +#define DB_88F6183BP_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F6183BP_BOARD_DEBUG_LED_NUM 0x4 +#define DB_88F6183BP_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F6183BP_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 db88f6183BpInfoBoardDebugLedIf[DB_88F6183BP_BOARD_DEBUG_LED_NUM] = + {24,25,26,27}; + +MV_BOARD_TWSI_INFO db88f6183BpInfoBoardTwsiDev[DB_88F6183BP_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}, + {BOARD_DEV_AUDIO_DEC, 0x4B, ADDR7_BIT} + }; + +MV_BOARD_MAC_INFO db88f6183BpInfoBoardMacInfo[DB_88F6183BP_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}, + }; + +MV_BOARD_GPP_INFO db88f6183BpInfoBoardGppInfo[DB_88F6183BP_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_USB_VBUS, 14}, + {BOARD_DEV_RESET, 20}, + {BOARD_DEV_SDIO_DETECT, 15} + }; + +MV_BOARD_MPP_INFO db88f6183BpInfoBoardMppConfigValue[DB_88F6183BP_BOARD_MPP_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F6183_BP_MPP0_7, /* mpp0_7 */ + DB_88F6183_BP_MPP8_15, /* mpp8_15 */ + DB_88F6183_BP_MPP16_23, /* mpp16_23 */ + DB_88F6183_BP_MPP24_31}} /* mpp24_31 */ + }; +#else + {{{DB_88F6183_BP_MPP0_7_NB, /* mpp0_7 */ + DB_88F6183_BP_MPP8_15_NB, /* mpp8_15 */ + DB_88F6183_BP_MPP16_23_NB, /* mpp16_23 */ + DB_88F6183_BP_MPP24_31_NB}} /* mpp24_31 */ + }; +#endif + +#if defined(MV_NAND) || defined(MV_NAND_BOOT) +MV_DEV_CS_INFO db88f6183BpInfoBoardDeCsInfo[DB_88F6183BP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else +MV_DEV_CS_INFO db88f6183BpInfoBoardDeCsInfo[DB_88F6183BP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ +#endif + +MV_BOARD_INFO db88f6183BpInfo = { + "DB-88F6183-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6183BP_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6183BpInfoBoardMppConfigValue, + 0, /* intsGppMask */ + DB_88F6183BP_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6183BpInfoBoardDeCsInfo, + DB_88F6183BP_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + DB_88F6183BP_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6183BpInfoBoardTwsiDev, + DB_88F6183BP_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88f6183BpInfoBoardMacInfo, + DB_88F6183BP_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f6183BpInfoBoardGppInfo, + DB_88F6183BP_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f6183BpInfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + DB_88F6183_BP_OE, /* gppOutEnVal */ + DB_88F6183_BP_OE_VAL, /* gppOutVal */ + 0x1, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +#define RD_88F6183GP_BOARD_PCI_IF_NUM 0x0 +#define RD_88F6183GP_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F6183GP_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F6183GP_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F6183GP_BOARD_DEBUG_LED_NUM 0x0 +#define RD_88F6183GP_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F6183GP_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_BOARD_TWSI_INFO rd88f6183GpInfoBoardTwsiDev[RD_88F6183GP_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f6183GpInfoBoardMacInfo[RD_88F6183GP_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8} + }; + +MV_BOARD_GPP_INFO rd88f6183GpInfoBoardGppInfo[RD_88F6183GP_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RESET, 20}, + {BOARD_DEV_RTC, 31}, + {BOARD_DEV_SDIO_DETECT, 9} + }; + +MV_BOARD_MPP_INFO rd88f6183GpInfoBoardMppConfigValue[RD_88F6183GP_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F6183_GP_MPP0_7, /* mpp0_7 */ + RD_88F6183_GP_MPP8_15, /* mpp8_15 */ + RD_88F6183_GP_MPP16_23, /* mpp16_23 */ + RD_88F6183_GP_MPP24_31}} /* mpp24_31 */ + }; + +MV_DEV_CS_INFO rd88f6183GpInfoBoardDeCsInfo[RD_88F6183GP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ + +MV_BOARD_INFO rd88f6183GpInfo = { + "RD-88F6183-GP", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6183GP_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6183GpInfoBoardMppConfigValue, + 0, /* intsGppMask */ + RD_88F6183GP_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f6183GpInfoBoardDeCsInfo, + RD_88F6183GP_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + RD_88F6183GP_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f6183GpInfoBoardTwsiDev, + RD_88F6183GP_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6183GpInfoBoardMacInfo, + RD_88F6183GP_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6183GpInfoBoardGppInfo, + RD_88F6183GP_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + RD_88F6183_GP_OE, /* gppOutEnVal */ + RD_88F6183_GP_OE_VAL, /* gppOutVal */ + BIT15, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +#define RD_88F6183AP_BOARD_PCI_IF_NUM 0x0 +#define RD_88F6183AP_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88F6183AP_BOARD_MAC_INFO_NUM 0x1 +#define RD_88F6183AP_BOARD_GPP_INFO_NUM 0x3 +#define RD_88F6183AP_BOARD_DEBUG_LED_NUM 0x0 +#define RD_88F6183AP_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88F6183AP_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_BOARD_TWSI_INFO rd88f6183ApInfoBoardTwsiDev[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88f6183ApInfoBoardMacInfo[] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_1000M, 0x0} + }; + +MV_BOARD_SWITCH_INFO rd88f6183ApInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{-1, {4, 3, 2, 1, 0}, 5, 1}}; + +MV_BOARD_GPP_INFO rd88f6183ApInfoBoardGppInfo[] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RESET, 20}, + {BOARD_DEV_RTC, 1}, + {BOARD_DEV_SWITCH_PHY_INT, 3} + }; + +MV_BOARD_MPP_INFO rd88f6183ApInfoBoardMppConfigValue[] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F6183_AP_MPP0_7, /* mpp0_7 */ + RD_88F6183_AP_MPP8_15, /* mpp8_15 */ + RD_88F6183_AP_MPP16_23, /* mpp16_23 */ + RD_88F6183_AP_MPP24_31}} /* mpp24_31 */ + }; + +MV_DEV_CS_INFO rd88f6183ApInfoBoardDeCsInfo[] = + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ + +MV_BOARD_INFO rd88f6183ApInfo = { + "RD-88F6183-AP-GE", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88F6183AP_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f6183ApInfoBoardMppConfigValue, + 0, /* intsGppMask */ + RD_88F6183AP_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f6183ApInfoBoardDeCsInfo, + RD_88F6183AP_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + RD_88F6183AP_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88f6183ApInfoBoardTwsiDev, + RD_88F6183AP_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f6183ApInfoBoardMacInfo, + RD_88F6183AP_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88f6183ApInfoBoardGppInfo, + RD_88F6183AP_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + RD_88F6183_AP_OE, /* gppOutEnVal */ + RD_88F6183_AP_OE_VAL, /* gppOutVal */ + BIT15, /* gppPolarityVal */ + rd88f6183ApInfoBoardSwitchInfo /* pSwitchInfo */ +}; +MV_BOARD_INFO* boardInfoTbl[] = {&db88f6183BpInfo, + &rd88f6183GpInfo, + &rd88f6183ApInfo + }; + + +#define BOARD_ID_BASE BOARD_ID_88F6183_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F6183_MAX diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.h new file mode 100644 index 0000000..68a9b89 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183BoardEnv.h @@ -0,0 +1,104 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F6183BoardEnvSpech +#define __INCmvBoard88F6183BoardEnvSpech + + +/* 88F6183 based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88F6183_BASE 0x90 + +/* New board ID numbers */ +#define DB_88F6183_BP (BOARD_ID_88F6183_BASE+0x0) +#define RD_88F6183_GP (BOARD_ID_88F6183_BASE+0x1) +#define RD_88F6183_AP (BOARD_ID_88F6183_BASE+0x2) +#define BOARD_ID_88F6183_MAX (BOARD_ID_88F6183_BASE+0x3) + +#define DB_88F6183_BP_MPP0_7 0x00111111 +#define DB_88F6183_BP_MPP8_15 0x00222200 +#define DB_88F6183_BP_MPP16_23 0x00010000 +#define DB_88F6183_BP_MPP24_31 0x00000000 +#define DB_88F6183_BP_MPP0_7_NB 0x00111111 +#define DB_88F6183_BP_MPP8_15_NB 0x00111100 +#define DB_88F6183_BP_MPP16_23_NB 0x00010000 +#define DB_88F6183_BP_MPP24_31_NB 0x00000000 +#define DB_88F6183_BP_OE 0x00A0C03B +#define DB_88F6183_BP_OE_VAL 0xF2BFFFFF + +#define RD_88F6183_GP_MPP0_7 0x00111111 +#define RD_88F6183_GP_MPP8_15 0x00111100 +#define RD_88F6183_GP_MPP16_23 0x00000011 +#define RD_88F6183_GP_MPP24_31 0x00000011 +#define RD_88F6183_GP_OE 0xFFFFFFFF +#define RD_88F6183_GP_OE_VAL 0x0 + +#define RD_88F6183_AP_MPP0_7 0x00000000 +#define RD_88F6183_AP_MPP8_15 0x00222200 +#define RD_88F6183_AP_MPP16_23 0x00000000 +#define RD_88F6183_AP_MPP24_31 0x00000000 +#define RD_88F6183_AP_OE 0x00003C1F +#define RD_88F6183_AP_OE_VAL BIT20 +#endif /* __INCmvBoard88F6183EnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.c new file mode 100644 index 0000000..2d7c4ac --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.c @@ -0,0 +1,143 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define DB_88F6183LBP_BOARD_PCI_IF_NUM 0x0 +#define DB_88F6183LBP_BOARD_TWSI_DEF_NUM 0x2 +#define DB_88F6183LBP_BOARD_MAC_INFO_NUM 0x0 +#define DB_88F6183LBP_BOARD_GPP_INFO_NUM 0x3 +#define DB_88F6183LBP_BOARD_DEBUG_LED_NUM 0x4 +#define DB_88F6183LBP_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_88F6183LBP_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 db88f6183LBpInfoBoardDebugLedIf[DB_88F6183LBP_BOARD_DEBUG_LED_NUM] = + {24,25,26,27}; + +MV_BOARD_TWSI_INFO db88f6183LBpInfoBoardTwsiDev[DB_88F6183LBP_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}, + {BOARD_DEV_AUDIO_DEC, 0x4B, ADDR7_BIT} + }; + +MV_BOARD_GPP_INFO db88f6183LBpInfoBoardGppInfo[DB_88F6183LBP_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_USB_VBUS, 14}, + {BOARD_DEV_RESET, 20}, + {BOARD_DEV_SDIO_DETECT, 15} + }; + +MV_BOARD_MPP_INFO db88f6183LBpInfoBoardMppConfigValue[DB_88F6183LBP_BOARD_MPP_CONFIG_NUM] = +#ifndef MV_NAND_BOOT + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88F6183_BP_MPP0_7, /* mpp0_7 */ + DB_88F6183_BP_MPP8_15, /* mpp8_15 */ + DB_88F6183_BP_MPP16_23, /* mpp16_23 */ + DB_88F6183_BP_MPP24_31}} /* mpp24_31 */ + }; +#else + {{{DB_88F6183_BP_MPP0_7_NB, /* mpp0_7 */ + DB_88F6183_BP_MPP8_15_NB, /* mpp8_15 */ + DB_88F6183_BP_MPP16_23_NB, /* mpp16_23 */ + DB_88F6183_BP_MPP24_31_NB}} /* mpp24_31 */ + }; +#endif + +#if defined(MV_NAND) || defined(MV_NAND_BOOT) +MV_DEV_CS_INFO db88f6183LBpInfoBoardDeCsInfo[DB_88F6183LBP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* NAND DEV */ +#else +MV_DEV_CS_INFO db88f6183LBpInfoBoardDeCsInfo[DB_88F6183LBP_BOARD_DEVICE_CONFIG_NUM] = + /*{deviceCS, params, devType, devWidth}*/ + {{2, N_A, BOARD_DEV_SPI_FLASH, 8}}; /* SPI DEV */ +#endif + +MV_BOARD_INFO db88f6183LBpInfo = { + "DB-88F6183L-BP", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88F6183LBP_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88f6183LBpInfoBoardMppConfigValue, + 0, /* intsGppMask */ + DB_88F6183LBP_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88f6183LBpInfoBoardDeCsInfo, + DB_88F6183LBP_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + NULL, + DB_88F6183LBP_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88f6183LBpInfoBoardTwsiDev, + DB_88F6183LBP_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + NULL, + DB_88F6183LBP_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88f6183LBpInfoBoardGppInfo, + DB_88F6183LBP_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + db88f6183LBpInfoBoardDebugLedIf, + N_A, /* ledsPolarity */ + DB_88F6183L_BP_OE, /* gppOutEnVal */ + DB_88F6183L_BP_OE_VAL, /* gppOutVal */ + 0x1, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +MV_BOARD_INFO* boardInfoTbl[] = {&db88f6183LBpInfo}; + + +#define BOARD_ID_BASE BOARD_ID_88F6183L_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88F6183L_MAX diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.h new file mode 100644 index 0000000..df5475b --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88F6183LBoardEnv.h @@ -0,0 +1,88 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88F6183LBoardEnvSpech +#define __INCmvBoard88F6183LBoardEnvSpech + + +/* 88F6183L based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88F6183L_BASE 0xa0 + +/* New board ID numbers */ +#define DB_88F6183L_BP (BOARD_ID_88F6183L_BASE+0x0) +#define BOARD_ID_88F6183L_MAX (BOARD_ID_88F6183L_BASE+0x1) + +#define DB_88F6183L_BP_MPP0_7 0x00000000 +#define DB_88F6183L_BP_MPP8_15 0x00222200 +#define DB_88F6183L_BP_MPP16_23 0x00010000 +#define DB_88F6183L_BP_MPP24_31 0x00000000 +#define DB_88F6183L_BP_MPP0_7_NB 0x00000000 +#define DB_88F6183L_BP_MPP8_15_NB 0x00111100 +#define DB_88F6183L_BP_MPP16_23_NB 0x00010000 +#define DB_88F6183L_BP_MPP24_31_NB 0x00000000 +#define DB_88F6183L_BP_OE 0x00A0C000 +#define DB_88F6183L_BP_OE_VAL 0xF2BFFFFF +#endif /* __INCmvBoard88F6183LEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.c new file mode 100644 index 0000000..5b18031 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.c @@ -0,0 +1,297 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#define DB_88W8660_BOARD_PCI_IF_NUM 0x3 +#define DB_88W8660_BOARD_TWSI_DEF_NUM 0x1 +#define DB_88W8660_BOARD_MAC_INFO_NUM 0x1 +#define DB_88W8660_BOARD_GPP_INFO_NUM 0x1 +#define DB_88W8660_BOARD_DEBUG_LED_NUM 0x0 +#define DB_88W8660_BOARD_MPP_CONFIG_NUM 0x2 +#define DB_88W8660_BOARD_DEVICE_CONFIG_NUM 0x4 + +MV_BOARD_PCI_IF db88w8660ddr2InfoBoardPciIf[DB_88W8660_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {0, 0, 0, 0}}, /* pciSlot0 */ + {8, {9, 9, 9, 9}}, /* pciSlot1 */ + {9, {11, 11, 11, 11}}}; /* pciSlot2 */ + +MV_BOARD_TWSI_INFO db88w8660ddr2InfoBoardTwsiDev[DB_88W8660_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO db88w8660ddr2InfoBoardMacInfo[DB_88W8660_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +MV_BOARD_GPP_INFO db88w8660ddr2InfoBoardGppInfo[DB_88W8660_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 10}}; + +MV_BOARD_MPP_INFO db88w8660ddr2InfoBoardMppConfigValue[DB_88W8660_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{DB_88W8660_DDR2_MPP0_7, /* mpp0_7 */ + DB_88W8660_DDR2_MPP8_15, /* mpp8_15 */ + N_A, + N_A}}, + {{DB_88W8660_DDR2_MPP0_7NB, /* mpp0_7 */ + DB_88W8660_DDR2_MPP8_15NB, /* mpp8_15 */ + N_A, + N_A}} + }; + +MV_DEV_CS_INFO db88w8660ddr2InfoBoardDeCsInfo[DB_88W8660_BOARD_DEVICE_CONFIG_NUM] = +#if defined(MV_NAND_BOOT) + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + {1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {2, N_A, N_A}, + {3,0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* bootCs */ +#else + /*{params, devType, devWidth}*/ + {{0, 0x8fcfffff, BOARD_DEV_SEVEN_SEG, N_A}, /* devCs0 */ + {1, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}, /* devCs1 */ + {2, N_A, N_A}, /* devCs2/flashCs */ + {3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ +#endif +MV_BOARD_INFO db88w8660ddr2Info = { + "DB-88W8660-DDR2", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_88W8660_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + db88w8660ddr2InfoBoardMppConfigValue, + ((1<<9)|(1 << 10)|(1<<11)), /* intsGppMask */ + DB_88W8660_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + db88w8660ddr2InfoBoardDeCsInfo, + DB_88W8660_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88w8660ddr2InfoBoardPciIf, + DB_88W8660_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + db88w8660ddr2InfoBoardTwsiDev, + DB_88W8660_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + db88w8660ddr2InfoBoardMacInfo, + DB_88W8660_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + db88w8660ddr2InfoBoardGppInfo, + DB_88W8660_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + NULL, + N_A, /* ledsPolarity */ + DB_88W8660_DDR2_OUT_EN, /* gppOutEnVal */ + DB_88W8660_DDR2_OUT_VAL, /* gppOutVal */ + 0xA00, /* gppPolarityVal */ + NULL /* pSwitchInfo */ +}; + +#define RD_88W8660_BOARD_PCI_IF_NUM 0x1 +#define RD_88W8660_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88W8660_BOARD_MAC_INFO_NUM 0x1 +#define RD_88W8660_BOARD_GPP_INFO_NUM 0x1 +#define RD_88W8660_BOARD_DEBUG_LED_NUM 0x3 +#define RD_88W8660_BOARD_MPP_CONFIG_NUM 0x1 +#define RD_88W8660_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 rd88w8660InfoBoardDebugLedIf[RD_88W8660_BOARD_DEBUG_LED_NUM] = + {6, 5, 7}; + +MV_BOARD_PCI_IF rd88w8660InfoBoardPciIf[RD_88W8660_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {4, 3, N_A, N_A}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88w8660InfoBoardTwsiDev[RD_88W8660_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88w8660InfoBoardMacInfo[RD_88W8660_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_100M, 0x0}}; + +MV_BOARD_SWITCH_INFO rd88w8660InfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{9, {0, 1, 2, 3, 4}, 5, 0}}; + +MV_BOARD_GPP_INFO rd88w8660InfoBoardGppInfo[RD_88W8660_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 11}}; + +MV_BOARD_MPP_INFO rd88w8660ddr1InfoBoardMppConfigValue[RD_88W8660_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88W8660_MPP0_7, /* mpp0_7 */ + RD_88W8660_MPP8_15, /* mpp8_15 */ + N_A, + N_A}}}; + + +MV_DEV_CS_INFO rd88w8660InfoBoardDeCsInfo[RD_88W8660_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ + +MV_BOARD_INFO rd88w8660Info = { + "RD-88W8660", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88W8660_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88w8660ddr1InfoBoardMppConfigValue, + ((1<<3)|(1<<4)|(1<<9)|(1<<11)), /* intsGppMask */ + RD_88W8660_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88w8660InfoBoardDeCsInfo, + RD_88W8660_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88w8660InfoBoardPciIf, + RD_88W8660_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88w8660InfoBoardTwsiDev, + RD_88W8660_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88w8660InfoBoardMacInfo, + RD_88W8660_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88w8660InfoBoardGppInfo, + RD_88W8660_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88w8660InfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88W8660_BOARD_OUT_EN, /* gppOutEnVal */ + RD_88W8660_BOARD_OUT_VAL, /* gppOutVal */ + RD_88W8660_BOARD_MPP_POLAR, /* gppPolarityVal */ + rd88w8660InfoBoardSwitchInfo /* pSwitchInfo */ +}; + + +#define RD_88W8660_AP82S_BOARD_PCI_IF_NUM 0x1 +#define RD_88W8660_AP82S_BOARD_TWSI_DEF_NUM 0x1 +#define RD_88W8660_AP82S_BOARD_MAC_INFO_NUM 0x1 +#define RD_88W8660_AP82S_BOARD_GPP_INFO_NUM 0x1 +#define RD_88W8660_AP82S_BOARD_DEBUG_LED_NUM 0x1 +#define RD_88W8660_AP82S_BOARD_MPP_CONFIG_NUM 0x2 +#define RD_88W8660_AP82S_BOARD_DEVICE_CONFIG_NUM 0x1 + +MV_U8 rd88w8660Ap82sInfoBoardDebugLedIf[RD_88W8660_BOARD_DEBUG_LED_NUM] = + {6}; + +MV_BOARD_PCI_IF rd88w8660Ap82sInfoBoardPciIf[RD_88W8660_AP82S_BOARD_PCI_IF_NUM] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {8, 3, 8, 8}}}; /* pciSlot0 */ + +MV_BOARD_TWSI_INFO rd88w8660Ap82sInfoBoardTwsiDev[RD_88W8660_AP82S_BOARD_TWSI_DEF_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 twsiDevAddr, MV_U8 twsiDevAddrType}} */ + {{BOARD_DEV_RTC, 0x68, ADDR7_BIT}}; + +MV_BOARD_MAC_INFO rd88w8660Ap82sInfoBoardMacInfo[RD_88W8660_AP82S_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_100M, 0x0}}; + +MV_BOARD_SWITCH_INFO rd88w8660Ap82sInfoBoardSwitchInfo[] = + /* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4}, + MV_32 qdCpuPort, MV_32 smiScanMode} */ + {{-1, {0, 1, 2, 3, 4}, 5, 0}}; + +MV_BOARD_GPP_INFO rd88w8660Ap82sInfoBoardGppInfo[RD_88W8660_AP82S_BOARD_GPP_INFO_NUM] = + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ + {{BOARD_DEV_RTC, 11}}; + +MV_BOARD_MPP_INFO rd88w8660Ap82sInfoBoardMppConfigValue[RD_88W8660_AP82S_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88W8660_AP82S_MPP0_7, /* mpp0_7 */ + RD_88W8660_AP82S_MPP8_15, + N_A, + N_A}}, + {{RD_88W8660_AP82S_MPP0_7NB, /* mpp0_7 */ + N_A, + N_A, + N_A}} + }; + +MV_DEV_CS_INFO rd88w8660Ap82sInfoBoardDeCsInfo[RD_88W8660_AP82S_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ +#if defined(MV_NAND_BOOT) + {{3, 0x8fcfffff, BOARD_DEV_NAND_FLASH, 8}}; /* bootCs */ +#else + {{3, 0x8fcfffff, BOARD_DEV_NOR_FLASH, 8}}; /* bootCs */ +#endif + + +MV_BOARD_INFO rd88w8660Ap82sInfo = { + "RD-88W8660-AP82S", /* boardName[MAX_BOARD_NAME_LEN] */ + RD_88W8660_AP82S_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88w8660Ap82sInfoBoardMppConfigValue, + ((1<<2)|(1<<3)|(1<<8)|(1<<9)|(1<<11)), /* intsGppMask */ + RD_88W8660_AP82S_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88w8660Ap82sInfoBoardDeCsInfo, + RD_88W8660_AP82S_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + rd88w8660Ap82sInfoBoardPciIf, + RD_88W8660_AP82S_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + rd88w8660Ap82sInfoBoardTwsiDev, + RD_88W8660_AP82S_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88w8660Ap82sInfoBoardMacInfo, + RD_88W8660_AP82S_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + rd88w8660Ap82sInfoBoardGppInfo, + RD_88W8660_AP82S_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88w8660Ap82sInfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88W8660_AP82S_OUT_EN, /* gppOutEnVal */ + RD_88W8660_AP82S_OUT_VAL, /* gppOutVal */ + RD_88W8660_AP82S_MPP_POLAR, /* gppPolarityVal */ + rd88w8660Ap82sInfoBoardSwitchInfo /* pSwitchInfo */ + +}; + +MV_BOARD_INFO* boardInfoTbl[3] = {&db88w8660ddr2Info, + &rd88w8660Info, + &rd88w8660Ap82sInfo + }; + + +#define BOARD_ID_BASE BOARD_ID_88W8660_BASE +#define MV_MAX_BOARD_ID BOARD_ID_88W8660_MAX + diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.h new file mode 100644 index 0000000..e2df113 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mv88W8660BoardEnv.h @@ -0,0 +1,106 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoard88W8660EnvSpech +#define __INCmvBoard88W8660EnvSpech + + +/* 88W8660 based boards ID numbers */ +/* =============================== */ +#define BOARD_ID_88W8660_BASE 0x40 +/* Old board ID numbers for backward compatability */ +#define DB_88W8660_DDR2_OLD 0x10 +#define RD_88W8660_DDR1_OLD 0x11 +#define RD_88W8660_AP82S_DDR1_OLD 0x12 +/* New board ID numbers */ +#define DB_88W8660_DDR2 (BOARD_ID_88W8660_BASE+0x0) +#define RD_88W8660_DDR1 (BOARD_ID_88W8660_BASE+0x1) +#define RD_88W8660_AP82S_DDR1 (BOARD_ID_88W8660_BASE+0x2) +#define BOARD_ID_88W8660_MAX (BOARD_ID_88W8660_BASE+0x3) + + + +#define RD_88W8660_MPP0_7 0x0 +#define RD_88W8660_MPP8_15 0x0 +#define RD_88W8660_BOARD_OUT_EN 0xFFF1C +#define RD_88W8660_BOARD_OUT_VAL 0xE3 +#define RD_88W8660_BOARD_MPP_POLAR 0xA18 + +#define DB_88W8660_DDR2_MPP0_7 0x00002222 +#define DB_88W8660_DDR2_MPP8_15 0x00000002 +#define DB_88W8660_DDR2_MPP0_7NB 0x00442222 +#define DB_88W8660_DDR2_MPP8_15NB 0x00000002 +#define DB_88W8660_DDR2_OUT_EN 0xFFF5 +#define DB_88W8660_DDR2_OUT_VAL 0x0 + + +#define RD_88W8660_AP82S_MPP0_7 0x22 +#define RD_88W8660_AP82S_MPP8_15 0x0 +#define RD_88W8660_AP82S_MPP0_7NB 0x440022 +#define RD_88W8660_AP82S_OUT_EN 0xBBF +#define RD_88W8660_AP82S_OUT_VAL (BIT10 | BIT7) +#define RD_88W8660_AP82S_MPP_POLAR 0xB04 + +#endif /* __INCmvBoard88W8660EnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.c new file mode 100644 index 0000000..a31a85d --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.c @@ -0,0 +1,2053 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "cpu/mvCpu.h" +#include "cntmr/mvCntmr.h" +#include "gpp/mvGpp.h" +#include "twsi/mvTwsi.h" +#include "pci-if/mvPciIf.h" +#include "device/mvDevice.h" + +#if defined(DB_CUSTOMER) +#include "boardEnv/mvCustomerBoardEnv.c" +#elif defined(MV_88F5180N) +#include "boardEnv/mv88F5180NBoardEnv.c" +#elif defined(MV_88F5181) +#include "boardEnv/mv88F5181BoardEnv.c" +#elif defined(MV_88F5181L) +#include "boardEnv/mv88F5181LBoardEnv.c" +#elif defined(MV_88F5182) +#include "boardEnv/mv88F5182BoardEnv.c" +#elif defined(MV_88F5082) +#include "boardEnv/mv88F5082BoardEnv.c" +#elif defined(MV_88W8660) +#include "boardEnv/mv88W8660BoardEnv.c" +#elif defined(MV_88F1281) +#include "boardEnv/mv88F1281BoardEnv.c" +#elif defined(MV_88F6082) +#include "boardEnv/mv88F6082BoardEnv.c" +#elif defined(MV_88F6183) +#include "boardEnv/mv88F6183BoardEnv.c" +#elif defined(MV_88F6183L) +#include "boardEnv/mv88F6183LBoardEnv.c" +#endif + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +extern MV_CPU_ARM_CLK _cpuARMDDRCLK[]; + +#define CODE_IN_ROM MV_FALSE +#define CODE_IN_RAM MV_TRUE + +#define BOARD_INFO(boardId) boardInfoTbl[boardId - BOARD_ID_BASE] + +/* Locals */ +static MV_DEV_CS_INFO* boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); + +MV_U32 tClkRate = -1; + + +/******************************************************************************* +* mvBoardEnvInit - Init board +* +* DESCRIPTION: +* In this function the board environment take care of device bank +* initialization. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardEnvInit(MV_VOID) +{ + MV_U32 devNum; + MV_U32 csNum; + MV_U32 devBankParam=0; + MV_U32 boardId= mvBoardIdGet(); + +#if defined(MV_INCLUDE_GIG_ETH) + MV_U32 regVal; +#endif + + + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardEnvInit:Board unknown.\n"); + return; + + } + + /* Set GPP Out value */ + MV_REG_WRITE(GPP_DATA_OUT_REG(0), BOARD_INFO(boardId)->gppOutVal); + + /* set GPP polarity */ + mvGppPolaritySet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityVal); + + /* Set GPP Out Enable*/ + mvGppTypeSet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnVal); + + + for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) + { + devBankParam = BOARD_INFO(boardId)->pDevCsInfo[devNum].params; + csNum = BOARD_INFO(boardId)->pDevCsInfo[devNum].deviceCS; + + if (devBankParam == N_A) continue; + + if (devNum != MV_BOOTDEVICE_INDEX) + { + MV_REG_WRITE(DEV_BANK_PARAM_REG(csNum), devBankParam); + } + else + { + MV_U32 bootDevBankParam; + + /* for BootCS Only device width should be as in sample at + reset */ + bootDevBankParam = MV_REG_READ(DEV_BANK_PARAM_REG(devNum)); + bootDevBankParam &= DBP_DEVWIDTH_MASK; + devBankParam &= ~DBP_DEVWIDTH_MASK; + devBankParam |= bootDevBankParam; + + MV_REG_WRITE(DEV_BANK_PARAM_REG(csNum) , devBankParam); + } + } + +#if defined(MV_INCLUDE_NAND) + + if (mvCtrlNandSupport()) + { + /* If we are booting from NAND MPPs should be modified */ + /* Check NAND connected to boot device */ +#if defined(MV_88F6082) + if (((MV_REG_READ(MPP_SAMPLE_AT_RESET) & MSAR_DBOOT_MODE_MASK) == MSAR_DBOOT_NAND) || + ((MV_REG_READ(MPP_SAMPLE_AT_RESET) & MSAR_DBOOT_MODE_MASK) == MSAR_IDBOOT_NAND)) + { + } +#else + if (MV_REG_READ(DEV_NAND_CTRL_REG) & 0x1) + { + } +#endif + else + { + + for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) + { + if (boardGetDevEntry(devNum, BOARD_DEV_NAND_FLASH) != NULL) + { + /* We always use don't care mode. */ + mvDevNandSet((boardGetDevEntry(devNum, BOARD_DEV_NAND_FLASH))->deviceCS, 0); + } + } + } + + } +#endif /* MV_INCLUDE_NAND */ + +#if defined(MV_INCLUDE_GIG_ETH) + + /* Guideline (GL# ETH-3) RGMII Output Delay Tuning*/ + + /* Read if we are in RGMII mode */ + regVal = MV_REG_READ(MPP_SAMPLE_AT_RESET); + + /* Check if we are in RGMII mode */ + if (MSAR_GIGA_PORT_MODE_RGMII == (regVal & MSAR_GIGA_PORT_MODE_MASK)) + { + + regVal = MV_REG_READ(DEV_RGMII_AC_TIMING_REG); + regVal &= ~0x3; + regVal |= 0x2; + MV_REG_WRITE(DEV_RGMII_AC_TIMING_REG, regVal); + } + +#endif /* MV_INCLUDE_GIG_ETH */ + +} + +/******************************************************************************* +* mvBoardModelGet - Get Board model +* +* DESCRIPTION: +* This function returns 16bit describing board model. +* Board model is constructed of one byte major and minor numbers in the +* following manner: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* String describing board model. +* +*******************************************************************************/ +MV_U16 mvBoardModelGet(MV_VOID) +{ + return (mvBoardIdGet() >> 16); +} + +/******************************************************************************* +* mbBoardRevlGet - Get Board revision +* +* DESCRIPTION: +* This function returns a 32bit describing the board revision. +* Board revision is constructed of 4bytes. 2bytes describes major number +* and the other 2bytes describes minor munber. +* For example for board revision 3.4 the function will return +* 0x00030004. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* String describing board model. +* +*******************************************************************************/ +MV_U16 mvBoardRevGet(MV_VOID) +{ + return (mvBoardIdGet() & 0xFFFF); +} + +/******************************************************************************* +* mvBoardNameGet - Get Board name +* +* DESCRIPTION: +* This function returns a string describing the board model and revision. +* String is extracted from board I2C EEPROM. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain board name string. Minimum size 32 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ +MV_STATUS mvBoardNameGet(char *pNameBuff) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsSPrintf (pNameBuff, "Board unknown.\n"); + return MV_ERROR; + + } + + mvOsSPrintf (pNameBuff, "%s",BOARD_INFO(boardId)->boardName); + + return MV_OK; +} +#if defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) +/******************************************************************************* +* mvBoardIsPortInSgmii - +* +* DESCRIPTION: +* This routine returns MV_TRUE for port number works in SGMII or MV_FALSE +* For all other options. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - port in SGMII. +* MV_FALSE - other. +* +*******************************************************************************/ +MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum) +{ + MV_BOOL ethPortSgmiiSupport[BOARD_ETH_PORT_NUM] = MV_ETH_PORT_SGMII; + + if(ethPortNum >= BOARD_ETH_PORT_NUM) + { + mvOsPrintf ("Invalid portNo=%d\n", ethPortNum); + return MV_FALSE; + } + return ethPortSgmiiSupport[ethPortNum]; +} +#endif /* MV_INCLUDE_GIG_ETH || MV_INCLUDE_UNM_ETH */ + +/******************************************************************************* +* mvBoardPhyAddrGet - Get the phy address +* +* DESCRIPTION: +* This routine returns the Phy address of a given ethernet port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing Phy address, -1 if the port number is wrong. +* +*******************************************************************************/ +MV_32 mvBoardPhyAddrGet(MV_U32 ethPortNum) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardPhyAddrGet: Board unknown.\n"); + return MV_ERROR; + + } + + return BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardEthSmiAddr; +} + +/******************************************************************************* +* mvBoardMacSpeedGet - Get the Mac speed +* +* DESCRIPTION: +* This routine returns the Mac speed if pre define of a given ethernet port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BOARD_MAC_SPEED, -1 if the port number is wrong. +* +*******************************************************************************/ +MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardMacSpeedGet: Board unknown.\n"); + return MV_ERROR; + + } + + return BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardMacSpeed; +} + +/******************************************************************************* +* mvBoardLinkStatusIrqGet - Get the IRQ number for the link status indication +* +* DESCRIPTION: +* This routine returns the IRQ number for the link status indication. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* the number of the IRQ for the link status indication, -1 if the port +* number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardLinkStatusIrqGet(MV_U32 ethPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardLinkStatusIrqGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].linkStatusIrq; +} + +/******************************************************************************* +* mvBoardSwitchPortGet - Get the mapping between the board connector and the +* Ethernet Switch port +* +* DESCRIPTION: +* This routine returns the matching Switch port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* boardPortNum - logical number of the connector on the board +* +* OUTPUT: +* None. +* +* RETURN: +* the matching Switch port, -1 if the port number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardSwitchPortGet(MV_U32 ethPortNum, MV_U8 boardPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardSwitchPortGet: Board unknown.\n"); + return MV_ERROR; + } + if (boardPortNum >= BOARD_ETH_SWITCH_PORT_NUM) + { + mvOsPrintf("mvBoardSwitchPortGet: Illegal board port number.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].qdPort[boardPortNum]; +} + +/******************************************************************************* +* mvBoardSwitchCpuPortGet - Get the the Ethernet Switch CPU port +* +* DESCRIPTION: +* This routine returns the Switch CPU port. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* the Switch CPU port, -1 if the port number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardSwitchCpuPortGet(MV_U32 ethPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardSwitchCpuPortGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].qdCpuPort; +} + +/******************************************************************************* +* mvBoardSmiScanModeGet - Get Switch SMI scan mode +* +* DESCRIPTION: +* This routine returns Switch SMI scan mode. +* +* INPUT: +* ethPortNum - Ethernet port number. +* +* OUTPUT: +* None. +* +* RETURN: +* 1 for SMI_MANUAL_MODE, -1 if the port number is wrong or if not relevant. +* +*******************************************************************************/ +MV_32 mvBoardSmiScanModeGet(MV_U32 ethPortNum) +{ + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardSmiScanModeGet: Board unknown.\n"); + return MV_ERROR; + } + + return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].smiScanMode; +} + +/******************************************************************************* +* mvBoardTclkGet - Get the board Tclk (Controller clock) +* +* DESCRIPTION: +* This routine extract the controller core clock. +* This function uses the controller counters to make identification. +* Note: In order to avoid interference, make sure task context switch +* and interrupts will not occure during this function operation +* +* INPUT: +* countNum - Counter number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +MV_U32 mvBoardTclkGet(MV_VOID) +{ + + MV_U32 tmpTClkRate=0; + + if (-1 == tClkRate) + { + /* Auto calc Tclk using counters */ +#ifdef MV_TCLK_CALC + MV_U32 ticks; + MV_U32 refClkDevBitRate; + MV_U32 refClkDevBit; + MV_U32 countNum= MV_TCLK_CNTR; /* Counter 1 is used for Tclk measurment */ + + refClkDevBit = MV_REF_CLK_DEV_BIT; + refClkDevBitRate = MV_REF_CLK_BIT_RATE; + + /* Stop counter activity */ + mvCntmrDisable(countNum); + + /* load value onto counter\timer */ + mvCntmrLoad(countNum,0xffffffff); + + /* set the counter to load in the first time */ + mvCntmrWrite(countNum,0xffffffff); + + /* Set input indication pin as input */ + MV_REG_BIT_SET(GPP_DATA_OUT_EN_REG(0),(1 << MV_REF_CLK_INPUT_GPP)); + + /* Enable interrupt as edge */ + MV_REG_BIT_SET(GPP_INT_MASK_REG(0),(1 << MV_REF_CLK_INPUT_GPP) ); + + /* This function is blocking. It returns only when reference clock is rising */ + /* Clear Interrupt cause */ + MV_REG_WRITE(GPP_INT_CAUSE_REG(0),0); + + do + { + if ( MV_REG_READ(GPP_INT_CAUSE_REG(0)) & (1 << MV_REF_CLK_INPUT_GPP)) break; + }while (1); + + + /* set control for timer \ cunter and enable */ + mvCntmrEnable(countNum); + + /* This function is blocking. It returns only when reference clock is rising */ + /* Clear Interrupt cause */ + MV_REG_WRITE(GPP_INT_CAUSE_REG(0),0); + + do + { + do + { + if ( MV_REG_READ(GPP_INT_CAUSE_REG(0)) & (1 << MV_REF_CLK_INPUT_GPP)) break; + }while (1); + MV_REG_WRITE(GPP_INT_CAUSE_REG(0),0); + }while (refClkDevBit--); + + /* Timer counts back. We need total num of ticks from count begin */ + ticks = ~MV_REG_READ(CNTMR_VAL_REG(countNum)); + + /* Disable interrupt */ + MV_REG_BIT_RESET(GPP_INT_MASK_REG(0),(1 << MV_REF_CLK_INPUT_GPP) ); + + /* Clear Interrupt cause */ + MV_REG_BIT_RESET(GPP_INT_CAUSE_REG(0),(1 << MV_REF_CLK_INPUT_GPP)); + + /* Release the reference clock device and stop timer */ + mvCntmrDisable(countNum); + + tmpTClkRate = (ticks/MV_REF_CLK_DEV_BIT) * refClkDevBitRate; + +#elif defined(DB_FPGA) + tmpTClkRate = MV_DB_FPGA_TCLK; +#elif defined(TCLK_AUTO_DETECT) + + tmpTClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET); + + tmpTClkRate &= MSAR_TCLCK_MASK; + + switch (tmpTClkRate) + { + case MSAR_TCLCK_133: + tmpTClkRate = MV_BOARD_TCLK_133MHZ; + break; +#if !defined(MV_88F6082) && !defined(MV_88F6183) && !defined(MV_88F6183L) + case MSAR_TCLCK_150: + tmpTClkRate = MV_BOARD_TCLK_150MHZ; + break; +#endif + case MSAR_TCLCK_166: + tmpTClkRate = MV_BOARD_TCLK_166MHZ; + break; + } + +#else + + tmpTClkRate = MV_BOARD_DEFAULT_TCLK; + +#endif + + tClkRate = tmpTClkRate; + } + else + tmpTClkRate = tClkRate; + + return tmpTClkRate; + +} +/******************************************************************************* +* mvBoardSysClkGet - Get the board SysClk (CPU bus clock) +* +* DESCRIPTION: +* This routine extract the CPU bus clock. +* +* INPUT: +* countNum - Counter number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ +MV_U32 mvBoardSysClkGet(MV_VOID) +{ + MV_U32 tmpSysClkRate=0; +#ifndef DB_FPGA + MV_U32 tmp; +#endif + +#ifdef DB_FPGA + tmpSysClkRate = MV_DB_FPGA_CPU_CLK; +#else +#ifdef SYSCLK_AUTO_DETECT + tmp = MV_REG_READ(MPP_SAMPLE_AT_RESET); + tmpSysClkRate = tmp & MSAR_ARMDDRCLCK_MASK; + tmpSysClkRate = tmpSysClkRate >> MSAR_ARMDDRCLCK_OFFS; + if ((mvCtrlModelGet() == MV_5281_DEV_ID) || (mvCtrlModelGet() == MV_1281_DEV_ID)) + if(tmp & MSAR_ARMDDRCLCK_H_MASK) + tmpSysClkRate |= BIT4; + + tmpSysClkRate = _cpuARMDDRCLK[tmpSysClkRate].ddrClk; + +#else + tmpSysClkRate = MV_BOARD_DEFAULT_SYSCLK; +#endif +#endif /* DB_FPGA */ + return tmpSysClkRate; +} + + +/******************************************************************************* +* mvBoardPexBridgeIntPinGet - Get PEX to PCI bridge interrupt pin number +* +* DESCRIPTION: +* Multi-ported PCI Express bridges that is implemented on the board +* collapse interrupts across multiple conventional PCI/PCI-X buses. +* A dual-headed PCI Express bridge would map (or "swizzle") the +* interrupts per the following table (in accordance with the respective +* logical PCI/PCI-X bridge's Device Number), collapse the INTA#-INTD# +* signals from its two logical PCI/PCI-X bridges, collapse the +* INTA#-INTD# signals from any internal sources, and convert the +* signals to in-band PCI Express messages. 10 +* This function returns the upstream interrupt as it was converted by +* the bridge, according to board configuration and the following table: +* PCI dev num +* Interrupt pin 7, 8, 9 +* A -> A D C +* B -> B A D +* C -> C B A +* D -> D C B +* +* +* INPUT: +* devNum - PCI/PCIX device number. +* intPin - PCI Int pin +* +* OUTPUT: +* None. +* +* RETURN: +* Int pin connected to the Interrupt controller +* +*******************************************************************************/ +MV_U32 mvBoardPexBridgeIntPinGet(MV_U32 devNum, MV_U32 intPin) +{ + MV_U32 realIntPin = ((intPin + (3 - (devNum % 4))) %4 ); + + if (realIntPin == 0) return 4; + else return realIntPin; + +} + +/******************************************************************************* +* mvBoardDebug7Seg - Set the board debug 7Seg +* +* DESCRIPTION: +* +* INPUT: +* hexNum - Number to be displied in hex by 7Seg. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvBoardDebug7Seg(MV_U32 hexNum) +{ + MV_U32 boardId, addr,val = 0,totalMask, currentBitMask = 1,i; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardDebug7Seg:Board unknown.\n"); + return; + + } + + /* Check if 7Segments is wired to CS */ + addr = mvBoardGetDeviceBaseAddr(0, BOARD_DEV_SEVEN_SEG); + + if (addr != 0xFFFFFFFF) + { + hexNum = *(volatile MV_U32*)((MV_U32)CPU_MEMIO_UNCACHED_ADDR(addr) + (MV_U32)((hexNum & 0xf) << 4)); + + return; + + } + else + { + + /* the 7seg is wired to GPPs */ + totalMask = (1 << BOARD_INFO(boardId)->activeLedsNumber) -1; + hexNum &= totalMask; + totalMask = 0; + + for (i = 0 ; i < BOARD_INFO(boardId)->activeLedsNumber ; i++) + { + if (hexNum & currentBitMask) + { + val |= (1 << BOARD_INFO(boardId)->pLedGppPin[i]); + } + + totalMask |= (1 << BOARD_INFO(boardId)->pLedGppPin[i]); + + currentBitMask = (currentBitMask << 1); + } + + if (BOARD_INFO(boardId)->ledsPolarity) + { + mvGppValueSet(0, totalMask, val); + } + else + { + mvGppValueSet(0, totalMask, ~val); + } + } +} + +#if defined(MV_INCLUDE_PCI) + +/******************************************************************************* +* mvBoardPciGpioPinGet - Get board PCI interrupt level. +* +* DESCRIPTION: +* This function returns the value of Gpp Pin that is connected +* to the specified IDSEL and interrupt pin (A,B,C,D). For example, If +* IDSEL 8 (device 8) interrupt A is connected to GPIO pin 4 the function +* will return the value 4. +* This function supports multiple PCI interfaces. +* +* INPUT: +* pciIf - PCI interface number. +* devNum - device number (IDSEL). +* intPin - Interrupt pin (A=1, B=2, C=3, D=4). +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardPciGpioPinGet(MV_U32 pciIf, MV_U32 devNum, MV_U32 intPin) +{ + int i; + MV_U32 boardId; + + /* Convert PciIf to the real PCi Interface number */ + pciIf = mvPciRealIfNumGet(pciIf); + + boardId = mvBoardIdGet(); + + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardPciGpioPinGet:Board ID %d unknown.\n", boardId); + return MV_ERROR; + + } + + if ((DB_88F5181_DDR1_PRPMC == boardId) || + (DB_88F5181_DDR1_PEXPCI == boardId) || + (DB_88F5181_DDR1_MNG == boardId)) + { + /* These boards are NOT backplans. PCI interrupt connectivity */ + /* information of a specifc user backplain, which to install */ + /* those boards, is unknown. */ + /* Marvell general HAL provides default PCI definition for */ + /* these add-in cards. Each user should modify this */ + /* configuration according to the backplain in use. */ + for (i = 0; i < BOARD_INFO(boardId)->numBoardPciIf; i++) + if (BOARD_INFO(boardId)->pBoardPciIf[i].pciDevNum == devNum) + return (MV_U32)BOARD_INFO(boardId)->pBoardPciIf[i].pciGppIntMap[intPin - 1]; + } + + if (BOARD_INFO(boardId)->pBoardPciIf[pciIf].pciDevNum == (MV_U8)N_A) + { + mvOsPrintf("mvBoardPciGpioPinGet: ERR. Could not find GPP pin " \ + "assignment for pciIf %d devNum %d intPin %d\n", + pciIf, devNum, intPin); + return N_A; + } + + + for (i = 0; i < BOARD_INFO(boardId)->numBoardPciIf; i++) + if (BOARD_INFO(boardId)->pBoardPciIf[i].pciDevNum == devNum) + return (MV_U32)BOARD_INFO(boardId)->pBoardPciIf[i].pciGppIntMap[intPin - 1]; + + mvOsPrintf("mvBoardPciGpioPinGet:Illigal device number %d\n", devNum); + return N_A; +} +#endif + +/******************************************************************************* +* mvBoardRTCGpioPinGet - mvBoardRTCGpioPinGet +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardRTCGpioPinGet(MV_VOID) +{ + MV_U32 boardId, i; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardRTCGpioPinGet:Board unknown.\n"); + return MV_ERROR; + + } + + for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) + if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == BOARD_DEV_RTC) + return (MV_U32)BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum; + + return MV_ERROR; +} + +/******************************************************************************* +* mvBoarGpioPinGet - mvBoarGpioPinGet +* +* DESCRIPTION: +* +* INPUT: +* class - MV_BOARD_DEV_CLASS enum. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoarGpioPinNumGet(MV_BOARD_DEV_CLASS class) +{ + MV_U32 boardId, i; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardRTCGpioPinGet:Board unknown.\n"); + return MV_ERROR; + + } + + for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) + if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == class) + return (MV_U32)BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum; + + return MV_ERROR; +} + + +/******************************************************************************* +* mvBoardReset - mvBoardReset +* +* DESCRIPTION: +* Reset the board +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None +* +*******************************************************************************/ +#define WAIT_DELAY \ + { volatile int dummy; int i; for (i=0; i<500; i++) dummy = i; } + +MV_VOID mvBoardReset(MV_VOID) +{ + MV_32 resetPin,boardId = mvBoardIdGet(); + + /* Get gpp reset pin if define */ + resetPin = mvBoardResetGpioPinGet(); + if (resetPin != MV_ERROR) + { + if ((boardId == RD_88F6082_NAS) + || (boardId == RD_88F6082_MICRO_DAS_NAS) + || (boardId == RD_88F6082_DX243_24G)) + { + /* Set DRAM into self refresh mode */ + MV_REG_WRITE(SDRAM_CONFIG_REG, 0xfa14410); + MV_REG_WRITE(SDRAM_OPERATION_REG, 0x7); + + /* wait 500 clock cycles */ + WAIT_DELAY + + MV_REG_BIT_SET( GPP_DATA_OUT_REG(0) ,(1 << resetPin)); + MV_REG_BIT_RESET( GPP_DATA_OUT_EN_REG(0) ,(1 << resetPin)); + } + + MV_REG_BIT_RESET( GPP_DATA_OUT_REG(0) ,(1 << resetPin)); + MV_REG_BIT_RESET( GPP_DATA_OUT_EN_REG(0) ,(1 << resetPin)); + + } + else + { + /* No gpp reset pin was found, try to reset ussing + system reset out */ + MV_REG_BIT_SET( CPU_RSTOUTN_MASK_REG , BIT2); + MV_REG_BIT_SET( CPU_SYS_SOFT_RST_REG , BIT0); + } + + while(1); +} + +/******************************************************************************* +* mvBoardResetGpioPinGet - mvBoardResetGpioPinGet +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardResetGpioPinGet(MV_VOID) +{ + MV_U32 boardId, i; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardRTCGpioPinGet:Board unknown.\n"); + return MV_ERROR; + + } + + for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) + if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == BOARD_DEV_RESET) + return (MV_U32)BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum; + + return MV_ERROR; +} +#if defined(MV_INCLUDE_SDIO) +/******************************************************************************* +* mvBoardSDIOGpioPinGet - mvBoardSDIOGpioPinGet +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardSDIOGpioPinGet(MV_VOID) +{ + MV_U32 boardId, i; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardRTCGpioPinGet:Board unknown.\n"); + return MV_ERROR; + + } + + for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) + if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == BOARD_DEV_SDIO_DETECT) + return (MV_U32)BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum; + + return MV_ERROR; +} +#endif + +/******************************************************************************* +* mvBoardUSBVbusGpioPinGet - return Vbus input GPP +* +* DESCRIPTION: +* +* INPUT: +* int devNo. +* +* OUTPUT: +* None. +* +* RETURN: +* GPIO pin number. The function return -1 for bad parameters. +* +*******************************************************************************/ +MV_32 mvBoardUSBVbusGpioPinGet(int devId) +{ + MV_U32 boardId, i, indexFound = 0; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardUSBVbusGpioPinGet:Board unknown.\n"); + return MV_ERROR; + + } + + for (i = 0; i < BOARD_INFO(boardId)->numBoardGppInfo; i++) + if (BOARD_INFO(boardId)->pBoardGppInfo[i].devClass == BOARD_DEV_USB_VBUS) + { + if (indexFound == devId) + return (MV_U32)BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum; + else + indexFound++; + } + + return MV_ERROR; +} + + +/******************************************************************************* +* mvBoardGpioIntMaskGet - Get GPIO mask for interrupt pins +* +* DESCRIPTION: +* This function returns a 32-bit mask of GPP pins that connected to +* interrupt generating sources on board. +* For example if UART channel A is hardwired to GPP pin 8 and +* UART channel B is hardwired to GPP pin 4 the fuinction will return +* the value 0x000000110 +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* See description. The function return -1 if board is not identified. +* +*******************************************************************************/ +MV_32 mvBoardGpioIntMaskGet(MV_VOID) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardGpioIntMaskGet:Board unknown.\n"); + return MV_ERROR; + + } + + return BOARD_INFO(boardId)->intsGppMask; +} + +/******************************************************************************* +* mvBoardMppGet - Get board dependent MPP register value +* +* DESCRIPTION: +* MPP settings are derived from board design. +* MPP group consist of 8 MPPs. An MPP group represent MPP +* control register. +* This function retrieves board dependend MPP register value. +* +* INPUT: +* mppGroupNum - MPP group number. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit value describing MPP control register value. +* +*******************************************************************************/ +MV_32 mvBoardMppGet(MV_U32 mppGroupNum) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardMppGet:Board unknown.\n"); + return MV_ERROR; + + } + + return BOARD_INFO(boardId)->pBoardMppConfigValue[0].mppGroup[mppGroupNum]; +} + + +/* Board devices API managments */ + +/******************************************************************************* +* mvBoardGetDeviceNumber - Get number of device of some type on the board +* +* DESCRIPTION: +* +* INPUT: +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* number of those devices else the function returns 0 +* +* +*******************************************************************************/ +MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass) +{ + MV_U32 foundIndex=0,devNum; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardGetDeviceNumber:Board unknown.\n"); + return 0xFFFFFFFF; + + } + + for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) + { + if (BOARD_INFO(boardId)->pDevCsInfo[devNum].devClass == devClass) + { + foundIndex++; + } + } + + return foundIndex; + +} + +/******************************************************************************* +* mvBoardGetDeviceBaseAddr - Get base address of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* Base address else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return mvCpuIfTargetWinBaseLowGet(DEV_TO_TARGET(devEntry->deviceCS)); + + } + + return 0xFFFFFFFF; +} + +/******************************************************************************* +* mvBoardGetDeviceBusWidth - Get Bus width of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* Bus width else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return mvDevWidthGet(devEntry->deviceCS); + + } + + return 0xFFFFFFFF; + +} + +/******************************************************************************* +* mvBoardGetDeviceWidth - Get dev width of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* dev width else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("Board unknown.\n"); + return 0xFFFFFFFF; + + } + + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + return devEntry->devWidth; + + return MV_ERROR; + +} + +/******************************************************************************* +* mvBoardGetDeviceWinSize - Get the window size of a device existing on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* window size else the function returns 0xffffffff +* +* +*******************************************************************************/ +MV_32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + MV_U32 boardId = mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("Board unknown.\n"); + return 0xFFFFFFFF; + } + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + { + return mvCpuIfTargetWinSizeGet(DEV_TO_TARGET(devEntry->deviceCS)); + } + + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* boardGetDevEntry - returns the entry pointer of a device on the board +* +* DESCRIPTION: +* +* INPUT: +* devIndex - The device sequential number on the board +* devType - The device type ( Flash,RTC , etc .. ) +* +* OUTPUT: +* None. +* +* RETURN: +* If the device is found on the board the then the functions returns the +* dev number else the function returns 0x0 +* +* +*******************************************************************************/ +static MV_DEV_CS_INFO* boardGetDevEntry(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_U32 foundIndex=0,devIndex; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("boardGetDevEntry: Board unknown.\n"); + return NULL; + + } + + /* because some restrictions like in U-boot that always expect the BootFlash to be + the first flash - we want always the Boot CS to be the first device of its kind , + so we always will start searching from there and then search the other */ + + for (devIndex = START_DEV_CS; devIndex < BOARD_INFO(boardId)->numBoardDeviceIf; devIndex++) + { + if ((BOARD_INFO(boardId)->pDevCsInfo[devIndex].devClass == devClass) && + (BOARD_INFO(boardId)->pDevCsInfo[devIndex].deviceCS == MV_BOOTDEVICE_INDEX)) + { + if (foundIndex == devNum) + return &(BOARD_INFO(boardId)->pDevCsInfo[devIndex]); + else + foundIndex++; + } + } + + + for (devIndex = START_DEV_CS; devIndex < BOARD_INFO(boardId)->numBoardDeviceIf; devIndex++) + { + + if (BOARD_INFO(boardId)->pDevCsInfo[devIndex].deviceCS == MV_BOOTDEVICE_INDEX) + continue; + + if (BOARD_INFO(boardId)->pDevCsInfo[devIndex].devClass == devClass) + { + if (foundIndex == devNum) + { + return &(BOARD_INFO(boardId)->pDevCsInfo[devIndex]); + } + foundIndex++; + } + } + + /* device not found */ + return NULL; +} + + +MV_U32 boardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass) +{ + MV_DEV_CS_INFO* devEntry; + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("Board unknown.\n"); + return 0xFFFFFFFF; + + } + + + devEntry = boardGetDevEntry(devNum,devClass); + if (devEntry != NULL) + return devEntry->deviceCS; + + return 0xFFFFFFFF; + +} + +/******************************************************************************* +* mvBoardRtcTwsiAddrTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardRtcTwsiAddrTypeGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_RTC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType; + return (MV_ERROR); +} + +/******************************************************************************* +* mvBoardRtcTwsiAddrGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardRtcTwsiAddrGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_RTC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr; + return (0xFF); +} + +/******************************************************************************* +* mvBoardA2DTwsiAddrTypeGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardA2DTwsiAddrTypeGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_AUDIO_DEC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType; + return (MV_ERROR); +} + +/******************************************************************************* +* mvBoardA2DTwsiAddrGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_U8 mvBoardA2DTwsiAddrGet() +{ + int i; + MV_U32 boardId= mvBoardIdGet(); + + for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++) + if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_DEV_AUDIO_DEC) + return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr; + return (0xFF); +} + + +#if defined(MV_INCLUDE_PCI) + +/******************************************************************************* +* mvBoardFirstPciSlotDevNumGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_32 mvBoardFirstPciSlotDevNumGet(MV_U32 pciIf) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + return BOARD_INFO(boardId)->pBoardPciIf[pciIf].pciDevNum; +} + +/******************************************************************************* +* mvBoardPciSlotsNumGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_32 mvBoardPciSlotsNumGet(MV_U32 pciIf) +{ + MV_U32 boardId; + + boardId = mvBoardIdGet(); + return BOARD_INFO(boardId)->numBoardPciIf; +} + +/******************************************************************************* +* mvBoardIsOurPciSlot - Return true for lot number which is defined under +* the bus number. +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_BOOL mvBoardIsOurPciSlot(MV_U32 busNum, MV_U32 slotNum) +{ + MV_U32 boardId= mvBoardIdGet(); + MV_U32 localBusNum= mvPciLocalBusNumGet(PCI_DEFAULT_IF); + int i; + + /* Our device number */ + if (slotNum == mvPciLocalDevNumGet(PCI_DEFAULT_IF)) + { + return MV_TRUE; + } + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardIsOurPciSlot: Board unknown.\n"); + return MV_FALSE; + } + + if (localBusNum != busNum) + { + mvOsPrintf("mvBoardIsOurPciSlot: localBusNum %x != busNum %x.\n", localBusNum, busNum); + return MV_FALSE; + } + + for (i = 0; i < BOARD_INFO(boardId)->numBoardPciIf; i++) + if (BOARD_INFO(boardId)->pBoardPciIf[i].pciDevNum == slotNum) + return MV_TRUE; + + return MV_FALSE; +} +/******************************************************************************* +* mvBoardPciIsMonarch - +* +* DESCRIPTION: +* This function is target to PRPMC type boards. In those boards there is + +* Check according to PCI arbiter control register if run with monarch +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* MV_TRUE if the PRPMC is monarch, MV_FALSE otherwise. +* +*******************************************************************************/ +MV_BOOL mvBoardPciIsMonarch(void) +{ +#if defined(DB_MNG) + /* the u-boot set the arbitter for DB_88F5181_DDR1_MNG boards */ + if((MV_REG_READ(PCI_ARBITER_CTRL_REG(0)) & PACR_ARB_ENABLE) == 0) + return MV_TRUE; +#endif + + return MV_FALSE; +} +#endif /* #if defined(MV_INCLUDE_PCI) */ +/******************************************************************************* +* mvBoardSlicGpioPinGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +* +*******************************************************************************/ +MV_32 mvBoardSlicGpioPinGet(MV_U32 slicNum) +{ + MV_U32 boardId; + boardId = mvBoardIdGet(); + + switch (boardId) + { + case DB_88F5181L_DDR2_2XTDM: + if (0 == slicNum) + { + return 8; + } + else if (1 == slicNum) + { + return 9; + } + else return MV_ERROR; + break; + case RD_88F5181L_VOIP_FE: + if (0 == slicNum) + { + return 2; + } + else if (1 == slicNum) + { + return 5; + } + else return MV_ERROR; + break; + default: + return MV_ERROR; + break; + + } +} + +/******************************************************************************* +* mvBoardVoiceAssembleModeGet - return SLIC/DAA assembly & interrupt modes +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvBoardVoiceAssemblyModeGet(MV_32* assmeblyMode, MV_32* irqMode) +{ + switch(mvBoardIdGet()) + { + case RD_88F5181L_VOIP_GE: + case RD_88F5181L_VOIP_FE: + *assmeblyMode = DAISY_CHAIN_MODE; + *irqMode = INTERRUPT_TO_TDM; + break; + case DB_88F5181L_DDR2_2XTDM: + *assmeblyMode = DUAL_CHIP_SELECT_MODE; + *irqMode = INTERRUPT_TO_MPP; + break; + case RD_88F5181L_VOIP_FXO_GE: + *assmeblyMode = DUAL_CHIP_SELECT_MODE; + *irqMode = INTERRUPT_TO_TDM; + break; + default: + *assmeblyMode = *irqMode = -1; + mvOsPrintf("mvBoardVoiceAssembleModeGet: TDM not supported(boardId=0x%x)\n",mvBoardIdGet()); + } + + return; + +} + +/******************************************************************************* +* mvBoardTdmLifeLineSet - set life line control on TDM module +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_VOID mvBoardTdmLifeLineSet(MV_VOID) +{ + return; +} +/******************************************************************************* +* mvBoardStatusLedPinNumGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: Return the last debug led in the board info +* +* +*******************************************************************************/ +MV_U8 mvBoardStatusLedPinNumGet(MV_VOID) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardIsOurPciSlot: Board unknown.\n"); + return MV_FALSE; + } + + return BOARD_INFO(boardId)->pLedGppPin[BOARD_INFO(boardId)->activeLedsNumber-1]; +} +/******************************************************************************* +* mvBoardSpecInitGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: Return MV_TRUE and parameters in case board need spesific phy init, +* otherwise return MV_FALSE. +* +* +*******************************************************************************/ + +MV_BOOL mvBoardSpecInitGet(MV_U32* regOff, MV_U32* data) +{ + switch(mvBoardIdGet()) + { + case RD_88F5181_POS_NAS: + *regOff = 0x18; + *data = 0x4151; + return MV_TRUE; + + default: + return MV_FALSE; + } +} +/******************************************************************************* +* mvBoardLedNumGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: Return the last debug led in the board info +* +* +*******************************************************************************/ + +MV_U8 mvBoardLedNumGet(MV_VOID) +{ + MV_U32 boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardIsOurPciSlot: Board unknown.\n"); + return MV_FALSE; + } + + return BOARD_INFO(boardId)->activeLedsNumber; +} + + +/******************************************************************************* +* mvBoardStatusLed - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: MV_STATUS +* +* +*******************************************************************************/ +MV_STATUS mvBoardStatusLed(MV_BOOL status) +{ + int val; + int mask; + MV_U32 boardId; + + /* Check first that there are debug leds on the board */ + if (mvBoardLedNumGet() == 0) + return MV_TRUE; + + boardId= mvBoardIdGet(); + + if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID))) + { + mvOsPrintf("mvBoardIsOurPciSlot: Board unknown.\n"); + return MV_FALSE; + } + + mask = val = (1 << mvBoardStatusLedPinNumGet()); + + if (status) + val = ~val; + + if (0 == BOARD_INFO(boardId)->ledsPolarity) + { + return mvGppValueSet(0, mask, val); + } + else + { + return mvGppValueSet(0, mask, ~val); + } + +} + + +/******************************************************************************* +* mvBoardNandWidthGet - +* +* DESCRIPTION: Get the width of the first NAND device in byte. +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: 1, 2, 4 or MV_ERROR +* +* +*******************************************************************************/ +/* */ +MV_32 mvBoardNandWidthGet(void) +{ + MV_U32 devNum; + MV_U32 devWidth; + MV_U32 boardId= mvBoardIdGet(); + + for (devNum = START_DEV_CS; devNum < BOARD_INFO(boardId)->numBoardDeviceIf; devNum++) + { + devWidth = mvBoardGetDeviceWidth(devNum, BOARD_DEV_NAND_FLASH); + if (devWidth != MV_ERROR) + return (devWidth / 8); + } + + /* NAND wasn't found */ + return MV_ERROR; +} + +/*********************************************************** +* Init the PHY or Switch of the board * + ***********************************************************/ +MV_VOID mvBoardEgigaPhySwitchInit(void) +{ + if (RD_88F6183_AP == mvBoardIdGet()) + { + mvEthE6161SwitchBasicInit(); + } + else if ((DB_88F5181_5281_DDR2 == mvBoardIdGet())|| + (DB_88F5X81_DDR1 == mvBoardIdGet()) || + (DB_88F5181_DDR1_PEXPCI == mvBoardIdGet()) || + (RD_88F5181_POS_NAS == mvBoardIdGet()) || + (DB_88F5182_DDR2 == mvBoardIdGet())|| + (DB_88F5182_DDR2_A == mvBoardIdGet())|| + (DB_88F5082_DDR2 == mvBoardIdGet())|| + (RD_88F5182_2XSATA == mvBoardIdGet())|| + (DB_88F5181L_DDR2_2XTDM == mvBoardIdGet()) || + (DB_88F5180N_DDR1 == mvBoardIdGet()) || + (DB_88F5180N_DDR2 == mvBoardIdGet()) || + (DB_88W8660_DDR2 == mvBoardIdGet()) ) + { + mvEthE1111PhyBasicInit(0); + + }else if ((RD_88F5182_2XSATA3 == mvBoardIdGet()) || + (RD_88F5182_2XSATA == mvBoardIdGet()) || + (RD_88F5082_2XSATA == mvBoardIdGet()) || + (RD_88F5082_2XSATA3 == mvBoardIdGet()) || + (DB_88F5X81_DDR2 == mvBoardIdGet()) || + (RD_88F6183_GP == mvBoardIdGet()) || + (DB_88F6183_BP == mvBoardIdGet())) + { + /* 1118 is identical to 1116 */ + mvEthE1116PhyBasicInit(0); + + }else if (DB_88F5181_5281_DDR1 == mvBoardIdGet()) + { + mvEthE1011PhyBasicInit(0); + + }else if ((RD_88F5181_VOIP == mvBoardIdGet()) || (RD_88F5181L_VOIP_FE == mvBoardIdGet()) || + (RD_88F5181_GTW_FE == mvBoardIdGet())) + { + mvEthE6063SwitchBasicInit(0); + + }else if ((RD_88W8660_DDR1 == mvBoardIdGet()) || (RD_88W8660_AP82S_DDR1 == mvBoardIdGet())) + { + mvEthE6065_61SwitchBasicInit(0); + + }else if ( (RD_88F5181L_VOIP_GE == mvBoardIdGet()) || + (RD_88F5181_GTW_GE == mvBoardIdGet()) || + (RD_88F5181L_VOIP_FXO_GE == mvBoardIdGet())) + { + mvEthE6131SwitchBasicInit(0); + + }else if (RD_88F6082_MICRO_DAS_NAS == mvBoardIdGet()) + { + mvEthE1112PhyBasicInit(0); + } + else if ((DB_88F6082_BP == mvBoardIdGet()) || + (DB_88F6082L_BP == mvBoardIdGet())) + { + mvEthE1112PhyBasicInit(0); + mvEthE1112PhyBasicInit(1); + } + else if (RD_88F6082_DX243_24G == mvBoardIdGet()) + { + mvEthE1112PhyBasicInit(0); + mvEthE1111PhyBasicInit(1); + } + else if (RD_88F6082_NAS == mvBoardIdGet()) + { + /* Power down phy in case we enter power down mode */ + mvEthE1112PhyPowerDown(0); + mvEthE1112PhyPowerDown(1); + } + else if (RD_88F6183_AP == mvBoardIdGet()) + { + mvEthE6161SwitchBasicInit(); + } +} diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.h new file mode 100644 index 0000000..b9cfab2 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvLib.h @@ -0,0 +1,308 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvBoardEnvLibh +#define __INCmvBoardEnvLibh + +/* defines */ +/* The below constant macros defines the board I2C EEPROM data offsets */ + + + +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "mvSysHwConfig.h" +#include "boardEnv/mvBoardEnvSpec.h" + + +/* DUART stuff for Tclk detection only */ +#define DUART_BAUD_RATE 115200 +#define MAX_CLOCK_MARGINE 5000000 /* Maximum detected clock margine */ + +/* Voice devices assembly modes */ +#define DAISY_CHAIN_MODE 1 +#define DUAL_CHIP_SELECT_MODE 0 +#define INTERRUPT_TO_MPP 1 +#define INTERRUPT_TO_TDM 0 + + +#define BOARD_ETH_PORT_NUM MV_ETH_MAX_PORTS +#define BOARD_ETH_SWITCH_PORT_NUM 5 + +#define MV_BOARD_MAX_USB_IF 2 +#define MV_BOARD_MAX_MPP 4 +#define MV_BOARD_NAME_LEN 0x20 + +typedef struct _boardData +{ + MV_U32 magic; + MV_U16 boardId; + MV_U8 boardVer; + MV_U8 boardRev; + MV_U32 reserved1; + MV_U32 reserved2; + +}BOARD_DATA; + +typedef enum _devBoardClass +{ + BOARD_DEV_NOR_FLASH, + BOARD_DEV_NAND_FLASH, + BOARD_DEV_SEVEN_SEG, + BOARD_DEV_FPGA, + BOARD_DEV_SRAM, + BOARD_DEV_RTC, + BOARD_DEV_PEX_TO_PCI_BRIDGE, + BOARD_DEV_MV_SWITCH, + BOARD_DEV_USB_VBUS, + BOARD_DEV_REF_CLCK, + BOARD_DEV_VOIP_SLIC, + BOARD_DEV_BUTTON, + BOARD_DEV_POWER_BUTTON, + BOARD_DEV_RESTOR_BUTTON, + BOARD_DEV_HDD0_POWER, + BOARD_DEV_HDD1_POWER, + BOARD_DEV_FAN_POWER, + BOARD_DEV_SPI_FLASH, + BOARD_DEV_RESET, + BOARD_DEV_POWER_ON_LED, + BOARD_DEV_HDD_POWER, + BOARD_DEV_AUDIO_DEC, + BOARD_DEV_SDIO_DETECT, + BOARD_DEV_SWITCH_PHY_INT, + BOARD_DEV_OTHER, +}MV_BOARD_DEV_CLASS; + + +typedef struct _pciBoardSlot +{ + MV_U8 pciSlotGppIntMap[4]; + +}MV_BOARD_PCI_SLOT; + + +typedef struct _pciBoardIf +{ + MV_U8 pciDevNum; + MV_U8 pciGppIntMap[4]; +}MV_BOARD_PCI_IF; + + +typedef struct _devCsInfo +{ + MV_U8 deviceCS; + MV_U32 params; + MV_U32 devClass; /* MV_BOARD_DEV_CLASS */ + MV_U8 devWidth; + +}MV_DEV_CS_INFO; + + +#define MV_BOARD_PHY_FORCE_10MB 0x0 +#define MV_BOARD_PHY_FORCE_100MB 0x1 +#define MV_BOARD_PHY_FORCE_1000MB 0x2 +#define MV_BOARD_PHY_SPEED_AUTO 0x3 + +typedef struct _boardSwitchInfo +{ + MV_32 linkStatusIrq; + MV_32 qdPort[BOARD_ETH_SWITCH_PORT_NUM]; + MV_32 qdCpuPort; + MV_32 smiScanMode; /* 1 for SMI_MANUAL_MODE, 0 otherwise */ + +}MV_BOARD_SWITCH_INFO; + +typedef struct _boardLedInfo +{ + MV_U8 activeLedsNumber; + MV_U8 ledsPolarity; /* '0' or '1' to turn on led */ + MV_U8* gppPinNum; /* Pointer to GPP values */ + +}MV_BOARD_LED_INFO; + +typedef struct _boardGppInfo +{ + MV_BOARD_DEV_CLASS devClass; + MV_U8 gppPinNum; + +}MV_BOARD_GPP_INFO; + + +typedef struct _boardTwsiInfo +{ + MV_BOARD_DEV_CLASS devClass; + MV_U8 twsiDevAddr; + MV_U8 twsiDevAddrType; + +}MV_BOARD_TWSI_INFO; + + +typedef enum _boardMacSpeed +{ + BOARD_MAC_SPEED_10M, + BOARD_MAC_SPEED_100M, + BOARD_MAC_SPEED_1000M, + BOARD_MAC_SPEED_AUTO, + +}MV_BOARD_MAC_SPEED; + +typedef struct _boardMacInfo +{ + MV_BOARD_MAC_SPEED boardMacSpeed; + MV_U8 boardEthSmiAddr; + +}MV_BOARD_MAC_INFO; + +typedef struct _boardMppInfo +{ + MV_U32 mppGroup[MV_BOARD_MAX_MPP]; + +}MV_BOARD_MPP_INFO; + +typedef struct _boardInfo +{ + char boardName[MV_BOARD_NAME_LEN]; + MV_U8 numBoardMppConfigValue; + MV_BOARD_MPP_INFO* pBoardMppConfigValue; + MV_U32 intsGppMask; + MV_U8 numBoardDeviceIf; + MV_DEV_CS_INFO* pDevCsInfo; + MV_U8 numBoardPciIf; + MV_BOARD_PCI_IF* pBoardPciIf; + MV_U8 numBoardTwsiDev; + MV_BOARD_TWSI_INFO* pBoardTwsiDev; + MV_U8 numBoardMacInfo; + MV_BOARD_MAC_INFO* pBoardMacInfo; + MV_U8 numBoardGppInfo; + MV_BOARD_GPP_INFO* pBoardGppInfo; + MV_U8 activeLedsNumber; + MV_U8* pLedGppPin; + MV_U8 ledsPolarity; /* '0' or '1' to turn on led */ + /* GPP values */ + MV_U32 gppOutEnVal; + MV_U32 gppOutVal; + MV_U32 gppPolarityVal; + /* Switch Configuration */ + MV_BOARD_SWITCH_INFO* pSwitchInfo; +}MV_BOARD_INFO; + + + +MV_VOID mvBoardEnvInit(MV_VOID); +MV_U32 mvBoardIdGet(MV_VOID); +MV_U16 mvBoardModelGet(MV_VOID); +MV_U16 mvBoardRevGet(MV_VOID); +MV_STATUS mvBoardNameGet(char *pNameBuff); +MV_32 mvBoardPhyAddrGet(MV_U32 ethPortNum); +MV_BOARD_MAC_SPEED mvBoardMacSpeedGet(MV_U32 ethPortNum); +MV_32 mvBoardLinkStatusIrqGet(MV_U32 ethPortNum); +MV_32 mvBoardSwitchPortGet(MV_U32 ethPortNum, MV_U8 boardPortNum); +MV_32 mvBoardSwitchCpuPortGet(MV_U32 ethPortNum); +MV_32 mvBoardSmiScanModeGet(MV_U32 ethPortNum); +MV_BOOL mvBoardIsPortInSgmii(MV_U32 ethPortNum); +MV_U32 mvBoardTclkGet(MV_VOID); +MV_U32 mvBoardSysClkGet(MV_VOID); +MV_VOID mvBoardDebug7Seg(MV_U32 hexNum); +MV_32 mvBoardMppGet(MV_U32 mppGroupNum); +MV_U32 boardGetDevCSNum(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_U8 mvBoardRtcTwsiAddrTypeGet(MV_VOID); +MV_U8 mvBoardRtcTwsiAddrGet(MV_VOID); +MV_U8 mvBoardA2DTwsiAddrTypeGet(MV_VOID); +MV_U8 mvBoardA2DTwsiAddrGet(MV_VOID); +MV_VOID mvBoardReset(MV_VOID); +MV_BOOL mvBoardSpecInitGet(MV_U32* regOff, MV_U32* data); +MV_U8 mvBoardLedNumGet(MV_VOID); + +/* Board devices API managments */ +MV_32 mvBoardGetDevicesNumber(MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceBaseAddr(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceBusWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceWidth(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); +MV_32 mvBoardGetDeviceWinSize(MV_32 devNum, MV_BOARD_DEV_CLASS devClass); + +/* Gpio Pic Connections API */ +MV_32 mvBoarGpioPinNumGet(MV_BOARD_DEV_CLASS class); +MV_U8 mvBoardStatusLedPinNumGet(MV_VOID); +MV_STATUS mvBoardStatusLed(MV_BOOL status); +MV_32 mvBoardUSBVbusGpioPinGet(int devId); +MV_U32 mvBoardPexBridgeIntPinGet(MV_U32 devNum, MV_U32 intPin); +MV_32 mvBoardResetGpioPinGet(MV_VOID); +MV_32 mvBoardRTCGpioPinGet(MV_VOID); +MV_32 mvBoardGpioIntMaskGet(MV_VOID); +MV_32 mvBoardSlicGpioPinGet(MV_U32 slicNum); +MV_VOID mvBoardVoiceAssemblyModeGet(MV_32* assmeblyMode, MV_32* irqMode); +MV_VOID mvBoardTdmLifeLineSet(MV_VOID); +#if defined(MV_INCLUDE_SDIO) +MV_32 mvBoardSDIOGpioPinGet(MV_VOID); +#endif +#if defined(MV_INCLUDE_PCI) +MV_32 mvBoardPciGpioPinGet(MV_U32 pciIf, MV_U32 idSel, MV_U32 intPin); +/* Misc */ +MV_32 mvBoardFirstPciSlotDevNumGet(MV_U32 pciIf); +MV_32 mvBoardPciSlotsNumGet(MV_U32 pciIf); +MV_BOOL mvBoardIsOurPciSlot(MV_U32 busNum, MV_U32 slotNum); +MV_BOOL mvBoardPciIsMonarch(void); +#endif /* defined(MV_INCLUDE_PCI) */ +#if defined(MV_INCLUDE_NAND) +MV_32 mvBoardNandWidthGet(void); +#endif /* defined(MV_INCLUDE_NAND) */ +#endif /* __INCmvBoardEnvLibh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.c new file mode 100644 index 0000000..075d656 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.c @@ -0,0 +1,502 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "cntmr/mvCntmr.h" +#include "device/mvDevice.h" +#include "ddr1_2/mvDramIfRegs.h" +#include "twsi/mvTwsi.h" + + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +MV_STATUS boardEepromGet(BOARD_DATA *boardData); + +MV_U32 gBoardId = -1; + +#ifdef MV_INCLUDE_EARLY_PRINTK +extern void mv_early_printk(char *fmt,...); +#endif +/******************************************************************************* +* mvBoardIdGet - Get Board model +* +* DESCRIPTION: +* This function returns board ID. +* Board ID is 32bit word constructed of board model (16bit) and +* board revision (16bit) in the following way: 0xMMMMRRRR. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit board ID number, '-1' if board is undefined. +* +*******************************************************************************/ +MV_U32 mvBoardIdGet(MV_VOID) +{ + MV_U32 tmpBoardId = -1; + BOARD_DATA boardData; + +#if defined(DB_FPGA) + tmpBoardId = DB_88F5X8X_FPGA_DDR1; + gBoardId = tmpBoardId; + return tmpBoardId; +#endif + + if(gBoardId != -1) + { + #if defined(MV_88F5182) + switch(gBoardId) + { + case DB_88F5182_DDR2_OLD: + gBoardId = DB_88F5182_DDR2; + break; + case RD_88F5182_2XSATA_OLD: + gBoardId = RD_88F5182_2XSATA; + break; + case RD_88F5182_2XSATA3_OLD: + gBoardId = RD_88F5182_2XSATA3; + break; + default: + break; + } + #elif defined(MV_88F5082) + switch(gBoardId) + { + case DB_88F5082_DDR2_OLD: + gBoardId = DB_88F5082_DDR2; + break; + case RD_88F5082_2XSATA_OLD: + gBoardId = RD_88F5082_2XSATA; + break; + case RD_88F5082_2XSATA3_OLD: + gBoardId = RD_88F5082_2XSATA3; + break; + default: + break; + } + #elif defined(MV_88F5181L) + if (gBoardId == DB_88F5181L_DDR2_2XTDM_OLD) + { + gBoardId = DB_88F5181L_DDR2_2XTDM; + } + else if(gBoardId == RD_88F5181L_VOIP_FE_OLD) + { + gBoardId = RD_88F5181L_VOIP_FE; + } + else if(gBoardId == RD_88F5181L_VOIP_GE_OLD) + { + gBoardId = RD_88F5181L_VOIP_GE; + } + #elif defined(MV_88W8660) + if (gBoardId == DB_88W8660_DDR2_OLD) + { + gBoardId = DB_88W8660_DDR2; + } + else if (gBoardId == RD_88W8660_DDR1_OLD) + { + gBoardId = RD_88W8660_DDR1; + } + else if(gBoardId == RD_88W8660_AP82S_DDR1_OLD) + { + gBoardId = RD_88W8660_AP82S_DDR1; + } + #elif defined(MV_88F5181) + if (gBoardId == RD_88F5181_GTW_FE_OLD) + { + gBoardId = RD_88F5181_GTW_FE; + } + else if (gBoardId == RD_88F5181_GTW_GE_OLD) + { + gBoardId = RD_88F5181_GTW_GE; + } + else if (gBoardId == RD_88F5181_POS_NAS_OLD) + { + gBoardId = RD_88F5181_POS_NAS; + } + else if (gBoardId == DB_88F5X81_DDR2_OLD) + { + gBoardId = DB_88F5X81_DDR2; + } + else if (gBoardId == DB_88F5X81_DDR1_OLD) + { + gBoardId = DB_88F5X81_DDR1; + } + else if (gBoardId == 0) /* In case that the U-Boot did not pass the baord ID like in DB-88F5181-DDR1-BP */ + { + gBoardId = -1; + } + #endif + if(gBoardId != -1) + return gBoardId; + } + + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + #if defined(DB_88F1281) + tmpBoardId = DB_88F1281_DDR2; + #elif defined(DB_88F6183BP) + tmpBoardId = DB_88F6183_BP; + #elif defined(RD_88F6183GP) + tmpBoardId = RD_88F6183_GP; + #elif defined(RD_88F6183AP) + tmpBoardId = RD_88F6183_AP; + #elif defined(DB_88F6183LBP) + tmpBoardId = DB_88F6183L_BP; + #elif defined(DB_88F5181L) + tmpBoardId = DB_88F5181L_DDR2_2XTDM; + #elif defined(DB_88W8660) + tmpBoardId = DB_88W8660_DDR2; + #elif defined(DB_88F5082) + tmpBoardId = DB_88F5082_DDR2; + #elif defined(DB_88F5182) + tmpBoardId = DB_88F5182_DDR2; + #elif defined(DB_88F5182_A) + tmpBoardId = DB_88F5182_DDR2_A; + #elif defined(DB_88F5181) + tmpBoardId = DB_88F5X81_DDR2; + #elif defined(DB_88F5181_OLD) + tmpBoardId = DB_88F5181_5281_DDR2; + #elif defined(DB_FPGA) + tmpBoardId = DB_88F5X8X_FPGA_DDR1; + #elif defined(DB_88F6082LBP) + tmpBoardId = DB_88F6082L_BP; + #elif defined(DB_CUSTOMER) + tmpBoardId = DB_CUSTOMER1_ID; + #endif + } + else /* DDR1 */ + { + #if defined(RD_88F5182) + tmpBoardId = RD_88F5182_2XSATA; + #elif defined(RD_88F5182_3) + tmpBoardId = RD_88F5182_2XSATA3; + #elif defined(RD_88F5082) + tmpBoardId = RD_88F5082_2XSATA; + #elif defined(RD_88F5082_3) + tmpBoardId = RD_88F5082_2XSATA3; + #elif defined(RD_88W8660) + tmpBoardId = RD_88W8660_DDR1; + #elif defined(RD_88W8660_AP82S) + tmpBoardId = RD_88W8660_AP82S_DDR1; + #elif defined(RD_88F5181L_FE) + tmpBoardId = RD_88F5181L_VOIP_FE; + #elif defined(RD_88F5181L_GE) + tmpBoardId = RD_88F5181L_VOIP_GE; + #elif defined(RD_88F5181_GTWGE) + tmpBoardId = RD_88F5181_GTW_GE; + #elif defined(RD_88F5181_GTWFE) + tmpBoardId = RD_88F5181_GTW_FE; + #elif defined(RD_88F5181L_FXO_GE) + tmpBoardId = RD_88F5181L_VOIP_FXO_GE; + #elif defined(MV_POS_NAS) + tmpBoardId = RD_88F5181_POS_NAS; + #elif defined(MV_VOIP) + tmpBoardId = RD_88F5181_VOIP; + #elif defined(DB_PRPMC) + tmpBoardId = DB_88F5181_DDR1_PRPMC; + #elif defined(DB_MNG) + tmpBoardId = DB_88F5181_DDR1_MNG; + #elif defined(DB_PEX_PCI) + tmpBoardId = DB_88F5181_DDR1_PEXPCI; + #elif defined(DB_88F6082BP) + tmpBoardId = DB_88F6082_BP; + #elif defined(DB_88F6082LBP) + tmpBoardId = DB_88F6082L_BP; + #elif defined(DB_88F6082SA) + tmpBoardId = DB_88F6082_SA; + #elif defined(RD_88F6082NAS) + tmpBoardId = RD_88F6082_NAS; + #elif defined(RD_88F6082DAS_PLUS) + tmpBoardId = RD_88F6082_DAS_PLUS; + #elif defined(RD_88F6082MICRO_DAS_NAS) + tmpBoardId = RD_88F6082_MICRO_DAS_NAS; + #elif defined(RD_88F6082GE_SATA) + tmpBoardId = RD_88F6082_GE_SATA; + #elif defined(RD_88F6082_DX243) + tmpBoardId = RD_88F6082_DX243_24G; + #elif defined(DB_88F5181) + tmpBoardId = DB_88F5X81_DDR1; + #elif defined(DB_88F5181_OLD) + tmpBoardId = DB_88F5181_5281_DDR1; + #endif + } + if(tmpBoardId != -1) { + gBoardId = tmpBoardId; + return tmpBoardId; + } + + + if(boardEepromGet(&boardData) == MV_OK) + { + tmpBoardId = (MV_U32)boardData.boardId; + } + else + { + /* until we have relevant data in twsi then we + will detect the board type from sdram config reg */ + if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2) + { + if((mvCtrlModelGet() == MV_5281_DEV_ID)&& + (mvCtrlRevGet() >= MV_5281_B0_REV)) + { + tmpBoardId = DB_88F5X81_DDR2; + } + else if(mvCtrlModelGet() == MV_8660_DEV_ID) + { + tmpBoardId = DB_88W8660_DDR2; + } + else if(mvCtrlModelGet() == MV_5082_DEV_ID) + { + tmpBoardId = DB_88F5082_DDR2; + } + else if(mvCtrlModelGet() == MV_5182_DEV_ID) + { + tmpBoardId = DB_88F5182_DDR2; + } + else if(mvCtrlModelGet() == MV_5180_DEV_ID) + { + tmpBoardId = DB_88F5180N_DDR2; + } + else if(mvCtrlModelGet() == MV_6183_DEV_ID) + { + tmpBoardId = DB_88F6183_BP; + } + else if(mvCtrlModelGet() == MV_6183L_DEV_ID) + { + tmpBoardId = DB_88F6183L_BP; + } + else + { + tmpBoardId = DB_88F5181_5281_DDR2; + } + } + else /* DDR1 */ + { + if((mvCtrlModelGet() == MV_5281_DEV_ID)&& + (mvCtrlRevGet() >= MV_5281_B0_REV)) + { + tmpBoardId = DB_88F5X81_DDR1; + } + else if(mvCtrlModelGet() == MV_5180_DEV_ID) + { + tmpBoardId = DB_88F5180N_DDR1; + } + else + { + tmpBoardId = DB_88F5181_5281_DDR1; + } + } + + } + + gBoardId = tmpBoardId; + +#ifdef MV_INCLUDE_EARLY_PRINTK + if (tmpBoardId == -1) + { + mv_early_printk("%s FATAL ERROR: Failed to detect Board ID\n", __FUNCTION__); + } +#endif + + return tmpBoardId; + + +} + +/******************************************************************************* +* boardEepromGet - Get board identification from the EEPROM +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* +*******************************************************************************/ +MV_STATUS boardEepromGet(BOARD_DATA *boardData) +{ + MV_TWSI_SLAVE twsiSlave; + MV_TWSI_ADDR slave; + + MV_U32 tclk; + + tclk = mvBoardTclkGet(); + + /* Init TWSI first */ + slave.type = ADDR7_BIT; + slave.address = 0x0; + mvTwsiInit(100000, tclk, &slave, 0); + + twsiSlave.slaveAddr.address = MV_BOARD_ID_EEPROM; + twsiSlave.slaveAddr.type = ADDR7_BIT; + twsiSlave.validOffset = MV_TRUE; + twsiSlave.offset = MV_BOARD_ID_EEPROM_OFFSET0; + twsiSlave.moreThen256 = MV_FALSE; + + if(MV_OK != mvTwsiRead (&twsiSlave, (MV_U8*)boardData, sizeof(BOARD_DATA))) + { + /*mvOsOutput("Fail to read Board EEPROM from offset0");*/ + return MV_FAIL; + } + +#if defined(MV_CPU_LE) + boardData->magic = MV_BYTE_SWAP_32BIT(boardData->magic); + boardData->boardId = MV_BYTE_SWAP_16BIT(boardData->boardId); + boardData->reserved1 = MV_BYTE_SWAP_32BIT(boardData->reserved1); + boardData->reserved2 = MV_BYTE_SWAP_32BIT(boardData->reserved2); +#endif + + if(boardData->magic == MV_BOARD_I2C_MAGIC) + { + /* Backward compatability */ + #if defined(MV_88F5182) + if (boardData->boardId == DB_88F5182_DDR2_OLD) + { + boardData->boardId = DB_88F5182_DDR2; + } + #elif defined(MV_88F5181L) + if (boardData->boardId == DB_88F5181L_DDR2_2XTDM_OLD) + { + boardData->boardId = DB_88F5181L_DDR2_2XTDM; + } + else if(boardData->boardId == RD_88F5181L_VOIP_FE_OLD) + { + boardData->boardId = RD_88F5181L_VOIP_FE; + } + + #elif defined(MV_88W8660) + if (boardData->boardId == DB_88W8660_DDR2_OLD) + { + boardData->boardId = DB_88W8660_DDR2; + } + #endif + return MV_OK; + } + + twsiSlave.offset = MV_BOARD_ID_EEPROM_OFFSET1; + twsiSlave.moreThen256 = MV_TRUE; + + if(MV_OK != mvTwsiRead (&twsiSlave, (MV_U8*)boardData, sizeof(BOARD_DATA))) + { + /*mvOsOutput("Fail to read Board EEPROM from offset1");*/ + return MV_FAIL; + } + + + +#if defined(MV_CPU_LE) + boardData->magic = MV_BYTE_SWAP_32BIT(boardData->magic); + boardData->boardId = MV_BYTE_SWAP_16BIT(boardData->boardId); + boardData->reserved1 = MV_BYTE_SWAP_32BIT(boardData->reserved1); + boardData->reserved2 = MV_BYTE_SWAP_32BIT(boardData->reserved2); +#endif + + if(boardData->magic == MV_BOARD_I2C_MAGIC) + { + /* Backward compatability */ + /* Backward compatability */ + #if defined(MV_88F5182) + if (boardData->boardId == DB_88F5182_DDR2_OLD) + { + boardData->boardId = DB_88F5182_DDR2; + } + #elif defined(MV_88F5181L) + if (boardData->boardId == DB_88F5181L_DDR2_2XTDM_OLD) + { + boardData->boardId = DB_88F5181L_DDR2_2XTDM; + } + else if(boardData->boardId == RD_88F5181L_VOIP_FE_OLD) + { + boardData->boardId = RD_88F5181L_VOIP_FE; + } + + #elif defined(MV_88W8660) + if (boardData->boardId == DB_88W8660_DDR2_OLD) + { + boardData->boardId = DB_88W8660_DDR2; + } + #endif + return MV_OK; + } + + return MV_FAIL; +} + + + diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.h new file mode 100644 index 0000000..c2bf441 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvBoardEnvSpec.h @@ -0,0 +1,167 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoardEnvSpech +#define __INCmvBoardEnvSpech + +#include "mvSysHwConfig.h" + + +/* For future use */ +#define BD_ID_DATA_START_OFFS 0x0 +#define BD_DETECT_SEQ_OFFS 0x0 +#define BD_SYS_NUM_OFFS 0x4 +#define BD_NAME_OFFS 0x8 + + + +/* MPP possible values in the remarks should be updated from the board + sheet or taken from HW team */ + + +/* I2C bus addresses */ +#define MV_BOARD_CTRL_I2C_ADDR 0x0 /* Controller slave addr */ +#define MV_BOARD_CTRL_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_DIMM0_I2C_ADDR 0x56 +#define MV_BOARD_DIMM0_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_DIMM1_I2C_ADDR 0x54 +#define MV_BOARD_DIMM1_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_EEPROM_I2C_ADDR 0x51 +#define MV_BOARD_EEPROM_I2C_ADDR_TYPE ADDR7_BIT +#define MV_BOARD_MAIN_EEPROM_I2C_ADDR 0x50 +#define MV_BOARD_MAIN_EEPROM_I2C_ADDR_TYPE ADDR7_BIT + +/* Eeprom board data */ +#define MV_BOARD_ID_EEPROM MV_BOARD_MAIN_EEPROM_I2C_ADDR +#define MV_BOARD_ID_EEPROM_OFFSET0 0x1F0 /* last 16byte in 0.5KByte EEPROMS */ +#define MV_BOARD_ID_EEPROM_OFFSET1 0x1FF0 /* last 16byte in 8KByte EEPROMS */ +#define MV_BOARD_I2C_MAGIC 0xFEEDFEED + + +#define BOOT_FLASH_INDEX 0 +#define MAIN_FLASH_INDEX 1 + +/* Boot Flash definitions */ +#define MV_BOARD_BOOT_FLASH_BASE_ADRS mvBoardGetDeviceBaseAddr(BOOT_FLASH_INDEX, \ + BOARD_DEV_NOR_FLASH) +#define MV_BOARD_BOOT_FLASH_BUS_WIDTH mvBoardGetDeviceBusWidth(BOOT_FLASH_INDEX, \ + BOARD_DEV_NOR_FLASH) +#define MV_BOARD_BOOT_FLASH_DEVICE_WIDTH mvBoardGetDeviceWidth(BOOT_FLASH_INDEX, \ + BOARD_DEV_NOR_FLASH) + +/* Board main flash */ +#define MV_BOARD_FLASH_BASE_ADRS mvBoardGetDeviceBaseAddr(MAIN_FLASH_INDEX, \ + BOARD_DEV_NOR_FLASH) +#define MV_BOARD_FLASH_BUS_WIDTH mvBoardGetDeviceBusWidth(MAIN_FLASH_INDEX, \ + BOARD_DEV_NOR_FLASH) +#define MV_BOARD_FLASH_DEVICE_WIDTH mvBoardGetDeviceWidth(MAIN_FLASH_INDEX, \ + BOARD_DEV_NOR_FLASH) + + +/* Clocks stuff */ +#define MV_BOARD_DEFAULT_TCLK 166666667 /* Default Tclk 166MHz */ +#define MV_BOARD_DEFAULT_SYSCLK 200000000 /* Default SysClk 200MHz */ +#define MV_BOARD_DEFAULT_PCLK 400000000 /* Default Pclock 400 MHZ*/ +#define MV_DB_FPGA_CPU_CLK 25000000 +#define MV_DB_FPGA_TCLK 25000000 +#define MV_BOARD_REF_CLOCK 3686400 /* Refrence Clock 3.6864MHz */ + + +/* Supported clocks */ +#define MV_BOARD_TCLK_100MHZ 100000000 +#define MV_BOARD_TCLK_125MHZ 125000000 +#define MV_BOARD_TCLK_133MHZ 133333333 +#define MV_BOARD_TCLK_150MHZ 150000000 +#define MV_BOARD_TCLK_166MHZ 166666667 +#define MV_BOARD_TCLK_200MHZ 200000000 + +#define MV_BOARD_SYSCLK_100MHZ 100000000 +#define MV_BOARD_SYSCLK_125MHZ 125000000 +#define MV_BOARD_SYSCLK_133MHZ 133333333 +#define MV_BOARD_SYSCLK_150MHZ 150000000 +#define MV_BOARD_SYSCLK_166MHZ 166666667 +#define MV_BOARD_SYSCLK_200MHZ 200000000 +#define MV_BOARD_SYSCLK_233MHZ 233333333 +#define MV_BOARD_SYSCLK_250MHZ 250000000 +#define MV_BOARD_SYSCLK_266MHZ 266666667 + + + + + +#include "mv88F1281BoardEnv.h" +#include "mv88F5082BoardEnv.h" +#include "mv88F5182BoardEnv.h" +#include "mv88F5181LBoardEnv.h" +#include "mv88W8660BoardEnv.h" +#include "mv88F5181BoardEnv.h" +#include "mv88F5180NBoardEnv.h" +#include "mv88F6082BoardEnv.h" +#include "mv88F6183BoardEnv.h" +#include "mv88F6183LBoardEnv.h" +#include "mvCustomerBoardEnv.h" + + +#endif /* __INCmvBoardEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.c b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.c new file mode 100644 index 0000000..1b61e2a --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.c @@ -0,0 +1,132 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define DB_CUS1_BOARD_PCI_IF_NUM 0x1 +#define DB_CUS1_BOARD_TWSI_DEF_NUM 0x0 +#define DB_CUS1_BOARD_MAC_INFO_NUM 0x1 +#define DB_CUS1_BOARD_GPP_INFO_NUM 0x0 +#define DB_CUS1_BOARD_DEBUG_LED_NUM 0x2 +#define DB_CUS1_BOARD_MPP_CONFIG_NUM 0x1 +#define DB_CUS1_BOARD_DEVICE_CONFIG_NUM 0x1 + + +MV_BOARD_PCI_IF db88f5181Cus1InfoBoardPciIf[] = + /* {pciDevNum, {intAGppPin, intBGppPin, intCGppPin, intDGppPin}} */ + {{7, {N_A, N_A, N_A, N_A}} /* pciSlot0 */ + }; + + +MV_U8 rd88f5181Cus1InfoBoardDebugLedIf[DB_CUS1_BOARD_DEBUG_LED_NUM] = + {0, 11}; + +MV_BOARD_MAC_INFO rd88f5181Cus1InfoBoardMacInfo[DB_CUS1_BOARD_MAC_INFO_NUM] = + /* {{MV_BOARD_MAC_SPEED boardMacSpeed, MV_U8 boardEthSmiAddr}} */ + {{BOARD_MAC_SPEED_AUTO, 0x8}}; + +/*MV_BOARD_GPP_INFO rd88f5181Cus1InfoBoardGppInfo[DB_CUS1_BOARD_GPP_INFO_NUM] = +*/ + /* {{MV_BOARD_DEV_CLASS devClass, MV_U8 gppPinNum}} */ +/* {{BOARD_DEV_RTC, 8}, + {BOARD_DEV_USB_VBUS, 9}, + {BOARD_DEV_REF_CLCK,0}}; +*/ + +MV_BOARD_MPP_INFO rd88f5181Cus1InfoBoardMppConfigValue[DB_CUS1_BOARD_MPP_CONFIG_NUM] = + /* {{MV_U32 mpp0_7, MV_U32 mpp8_15, MV_U32 mpp16_23, MV_U32 mppDev}} */ + {{{RD_88F5181L_CUS1_MPP0_7, /* mpp0_7 */ + RD_88F5181L_CUS1_MPP8_15, /* mpp8_15 */ + RD_88F5181L_CUS1_MPP16_23, /* mpp16_23 */ + RD_88F5181L_CUS1_MPP_DEV}}}; /* mppDev */ + +MV_DEV_CS_INFO rd88f5181Cus1InfoBoardDeCsInfo[DB_CUS1_BOARD_DEVICE_CONFIG_NUM] = + /*{params, devType, devWidth}*/ + {{3, 0x8fdfffff, BOARD_DEV_NOR_FLASH, 16}}; /* bootCs */ + +MV_BOARD_INFO rd88f5181Cus1Info = { + "RD-88F5181L-Customer 1", /* boardName[MAX_BOARD_NAME_LEN] */ + DB_CUS1_BOARD_MPP_CONFIG_NUM, /* numBoardMppConfig */ + rd88f5181Cus1InfoBoardMppConfigValue, + ((1 << 4)|(1 << 6)|(1 << 8)), /* intsGppMask */ + DB_CUS1_BOARD_DEVICE_CONFIG_NUM, /* numBoardDevIf */ + rd88f5181Cus1InfoBoardDeCsInfo, + DB_CUS1_BOARD_PCI_IF_NUM, /* numBoardPciIf */ + db88f5181Cus1InfoBoardPciIf, + DB_CUS1_BOARD_TWSI_DEF_NUM, /* numBoardTwsiDev */ + NULL, + DB_CUS1_BOARD_MAC_INFO_NUM, /* numBoardMacInfo */ + rd88f5181Cus1InfoBoardMacInfo, + DB_CUS1_BOARD_GPP_INFO_NUM, /* numBoardGppInfo */ + NULL, + DB_CUS1_BOARD_DEBUG_LED_NUM, /* activeLedsNumber */ + rd88f5181Cus1InfoBoardDebugLedIf, + 0, /* ledsPolarity */ + RD_88F5181L_CUS1_GPP_OE, /* gppOutEnVal */ + N_A, /* gppPolarityVal */ +}; + + +MV_BOARD_INFO* boardInfoTbl[] = {&rd88f5181Cus1Info}; + +#define BOARD_ID_BASE BOARD_ID_CUSTOMER_BASE +#define MV_MAX_BOARD_ID BOARD_ID_CUSTOMER_MAX diff --git a/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.h b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.h new file mode 100644 index 0000000..326ed80 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/boardEnv/mvCustomerBoardEnv.h @@ -0,0 +1,87 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvBoardCustomerEnvSpech +#define __INCmvBoardCustomerEnvSpech + + +/* Customer based boards ID numbers */ +/* =============================== */ + + +#define RD_88F5181L_CUS1_MPP0_7 0x55000000 +#define RD_88F5181L_CUS1_MPP8_15 0x0 +#define RD_88F5181L_CUS1_MPP16_23 0x0 +#define RD_88F5181L_CUS1_MPP_DEV 0x0 +#define RD_88F5181L_CUS1_GPP_OE 0xffff7fff +#define RD_88F5181L_CUS1_GPP_VAL 0x0 + +#define BOARD_ID_CUSTOMER_BASE 0xF0 +#define DB_CUSTOMER1_ID (BOARD_ID_CUSTOMER_BASE+0x0) + +#define BOARD_ID_CUSTOMER_MAX (BOARD_ID_CUSTOMER_BASE+0x1) + + +#endif /* __INCmvBoardCustomerEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpu.h b/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpu.h new file mode 100644 index 0000000..3740f93 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpu.h @@ -0,0 +1,88 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuh +#define __INCmvCpuh + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" + +#if defined(MV_MIPS) + #include "mvCpuMips.h" +#elif defined (MV_PPC) + #include "mvCpuPpc.h" +#elif defined (MV_ARM) + #include "mvCpuArm.h" +#else + #error "CPU type not selected" +#endif + +MV_U32 mvCpuPclkGet(MV_VOID); +MV_VOID mvCpuNameGet(char *pNameBuff); + + + +#endif /* __INCmvCpuh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.c b/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.c new file mode 100644 index 0000000..f8a6d0a --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.c @@ -0,0 +1,166 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "cpu/mvCpu.h" +#include "ctrlEnv/mvCtrlEnvLib.h" + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* locals */ + +/******************************************************************************* +* mvCpuPclkGet - Get the CPU pClk (pipe clock) +* +* DESCRIPTION: +* This routine extract the CPU core clock. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit clock cycles in Hertz. +* +*******************************************************************************/ + +MV_CPU_ARM_CLK _cpuARMDDRCLK[] = MV_CPU_IF_ARMDDRCLCK_TBL; + +MV_U32 mvCpuPclkGet(MV_VOID) +{ + MV_U32 tmpPClkRate=0; +#ifndef DB_FPGA + MV_U32 tmp; +#endif + +#ifdef DB_FPGA + tmpPClkRate = MV_DB_FPGA_CPU_CLK; +#else +#ifdef SYSCLK_AUTO_DETECT + tmp = MV_REG_READ(MPP_SAMPLE_AT_RESET); + tmpPClkRate = tmp & MSAR_ARMDDRCLCK_MASK; + tmpPClkRate = tmpPClkRate >> MSAR_ARMDDRCLCK_OFFS; + + if ((mvCtrlModelGet() == MV_5281_DEV_ID) || (mvCtrlModelGet() == MV_1281_DEV_ID)) + if(tmp & MSAR_ARMDDRCLCK_H_MASK) + tmpPClkRate |= BIT4; + + tmpPClkRate = _cpuARMDDRCLK[tmpPClkRate].cpuClk; + +#else + tmpPClkRate = MV_BOARD_DEFAULT_PCLK; +#endif +#endif /* DB_FPGA */ + + + return tmpPClkRate; +} + +/******************************************************************************* +* mvCpuNameGet - Get CPU name +* +* DESCRIPTION: +* This function returns a string describing the CPU model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain board name string. Minimum size 32 chars. +* +* RETURN: +* None. +*******************************************************************************/ +MV_VOID mvCpuNameGet(char *pNameBuff) +{ + MV_U32 cpuModel; + + cpuModel = mvOsCpuPartGet(); + + /* The CPU module is indicated in the Processor Version Register (PVR) */ + switch(cpuModel) + { + case CPU_PART_ARM926: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM926",mvOsCpuRevGet()); + break; + case CPU_PART_ARM946: + mvOsSPrintf(pNameBuff, "%s (Rev %d)", "ARM946",mvOsCpuRevGet()); + break; + default: + mvOsSPrintf(pNameBuff,"??? (0x%04x) (Rev %d)",cpuModel,mvOsCpuRevGet()); + break; + } /* switch */ + + return; +} + + + diff --git a/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.h b/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.h new file mode 100644 index 0000000..1457193 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/cpu/mvCpuArm.h @@ -0,0 +1,88 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuArmh +#define __INCmvCpuArmh + +/* defines */ + +#define CPU_PART_MRVL131 0x131 +#define CPU_PART_ARM926 0x926 +#define CPU_PART_ARM946 0x946 +#define MV_CPU_ARM_CLK_ELM_SIZE 12 +#define MV_CPU_ARM_CLK_RATIO_OFF 8 +#define MV_CPU_ARM_CLK_DDR_OFF 4 + +#ifndef MV_ASMLANGUAGE +typedef struct _mvCpuArmClk +{ + MV_U32 cpuClk; /* CPU clock in MHz */ + MV_U32 ddrClk; /* DDR clock in MHz */ + MV_U32 clkRatio; /* CPU DDR clock ratio */ + +}MV_CPU_ARM_CLK; + +#endif /* MV_ASMLANGUAGE */ +#endif /* __INCmvCpuArmh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1281EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1281EnvSpec.h new file mode 100644 index 0000000..d5f16d7 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1281EnvSpec.h @@ -0,0 +1,326 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F1281CtrlEnvSpech +#define __IN88F1281CtrlEnvSpech + + +#define MV_ARM_SOC + +#define SOC_NAME_PREFIX "MV88F" + +#define INTER_REGS_SIZE _1M + +#define MV_ETH_REG_BASE(port) 0 +#define USB_REG_BASE(dev) 0 + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 2 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_BOOTDEVICE_INDEX 1 + + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ +#define MV_MPP_MAX_GROUP 2 + +/* This define describes the maximum number of supported PCI\PCIX Interfaces*/ +#define MV_PCI_MAX_IF 0 +#define MV_PCI_START_IF 0 + +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 2 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF MV_PCI_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_MAX_PORTS 0 +#define MV_ETH_PORT_SGMII {} + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 0 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 0 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x80000 + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 10 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ +/* ARM CPU clock vs. DDR clock */ +#define MV_CPU_IF_ARMDDRCLCK_TBL {\ + /* CPU FREQ, DDR FREQ, RATIO */\ + {333333333, 166666667, 2},\ + {500000000, 166666667, 3},\ + {666666666, 166666667, 4},\ + {833333333, 166666667, 5},\ + {1000000000, 166666667, 6},\ + {1166666666, 166666667, 7},\ + {400000000, 200000000, 2},\ + {600000000, 200000000, 3},\ + {800000000, 200000000, 4},\ + {1000000000, 200000000, 5},\ + {1050000000, 150000000, 10},\ + {466666666, 233333334, 2},\ + {700000000, 233333334, 3},\ + {933333333, 233333334, 4},\ + {1166666666, 233333334, 5},\ + {500000000, 250000000, 2},\ + {750000000, 250000000, 3},\ + {1000000000, 250000000, 4},\ + {1250000000, 250000000, 5},\ + {533333333, 266666667, 2},\ + {800000000, 266666667, 3},\ + {1066666666, 266666667, 4},\ + {700000000, 100000000, 7},\ + {400000000, 133333334, 3},\ + {533333333, 133333334, 4},\ + {666666666, 133333334, 5},\ + {800000000, 133333334, 6},\ + {933333333, 133333334, 7},\ + {1, 4, 4},\ + {1, 3, 3},\ + {1, 2, 2},\ + {1, 1, 1}\ +}; + +#define MSAR_ARMDDRCLCK_OFFS 6 + +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT19 + + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + + + +#define MV_TARGET_IS_PEX1(target) \ + ((target >= PEX1_MEM) && (target <= PEX1_IO)) + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS1)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) 0 + + +#define MV_TARGET_IS_AS_BOOT(target) 0 +#define BOOT_TARGETS_NAME_ARRAY {} +#define MV_CHANGE_BOOT_CS(target) (target) + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + PEX1_MEM, /* PCI Express 1 Memory */ + PEX1_IO, /* PCI Express 1 IO */ + INTER_REGS, /* Internal registers */ + FLASH_CS, /* Flash chip select */ + DEV_BOOCS, /* Flash Boot chip select */ + MAX_TARGETS + +}MV_TARGET; + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM +#define PEX1_MEM0 PEX1_MEM + +/* For old competability */ +#define DEVICE_CS0 FLASH_CS +#define DEVICE_CS1 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* Device Interface registers offsets */ +#define DEV_BANK_PARAM_REG(num) ((num) ? 0x1046C : 0x10464) + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1 << (((csNum)+3) * 2)) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2 << (((csNum)+3) * 2)) + + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PEX1_MEM +#define PCI_IF1_IO PEX1_IO + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PEX1_TARGET_ID = 3 , /* Port 4 -> PCI Express0 */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ \ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0x59,PEX1_TARGET_ID}, /* PEX1_MEM */ \ + {0x51,PEX1_TARGET_ID}, /* PEX1_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1B,DEV_TARGET_ID}, /* FLASH_CS */ \ + {0x0F,DEV_TARGET_ID} /* DEV_BOOCS*/ \ +} + + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "PEX1_MEM", /* PEX1_MEM */ \ + "PEX1_IO", /* PEX1_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "FLASH_CS", /* FLASH_CS */ \ + "DEV_BOOCS" /* DEV_BOOCS*/ \ +} + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F1281CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1X81EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1X81EnvSpec.h new file mode 100644 index 0000000..3aa732f --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F1X81EnvSpec.h @@ -0,0 +1,291 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F1X81CtrlEnvSpech +#define __IN88F1X81CtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ +#define MV_MPP_MAX_GROUP 2 + +/* This define describes the maximum number of supported PCI\PCIX Interfaces*/ +#define MV_PCI_MAX_IF 0 +#define MV_PCI_START_IF 0 + +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 2 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF MV_PCI_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_MAX_PORTS 0 +#define MV_ETH_PORT_SGMII {} + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 0 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 0 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 0 + + +#define SATA_REG_BASE 0x80000 + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 10 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + + +#define MSAR_ARMDDRCLCK_OFFS 6 + + +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + +#define MSAR_ARMDDRCLCK_333_167 (0x0 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_400_200 (0x1 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_400_133 (0x2 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_500_167 (0x3 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_533_133 (0x4 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_600_200 (0x5 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_667_167 (0x6 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_800_200 (0x7 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_480_160 (0xc << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_550_183 (0xd << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_525_175 (0xe << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_466_233 (0x11 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_500_250 (0x12 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_533_266 (0x13 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_600_300 (0x14 << MSAR_ARMDDRCLCK_OFFS) + +#define MSAR_ARMDDRCLCK_450_150 (0x15 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_533_178 (0x16 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_575_192 (0x17 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_700_175 (0x18 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_733_183 (0x19 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_750_187 (0x1A << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_775_194 (0x1B << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_500_125 (0x1C << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_500_100 (0x1D << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_600_150 (0x1E << MSAR_ARMDDRCLCK_OFFS) + + +#define MSAR_GIGA_PORT_MODE_OFFS 15 +#define MSAR_GIGA_PORT_MODE_MASK (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_GMII (0x2 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x3 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MV_TARGET_IS_AS_BOOT(target) 0 + +#define BOOT_TARGETS_NAME_ARRAY {} + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + + + +#define MV_TARGET_IS_PEX1(target) \ + ((target >= PEX1_MEM) && (target <= PEX1_IO)) + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= FLASH_CS) && (target <= DEV_BOOCS)) + + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + PEX1_MEM, /* PCI Express 1 Memory */ + PEX1_IO, /* PCI Express 1 IO */ + INTER_REGS, /* Internal registers */ + FLASH_CS, /* Flash chip select */ + DEV_BOOCS, /* Flash Boot chip select */ + MAX_TARGETS + +}MV_TARGET; + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM +#define PEX1_MEM0 PEX1_MEM + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PEX1_MEM +#define PCI_IF1_IO PEX1_IO + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PEX1_TARGET_ID = 3 , /* Port 4 -> PCI Express0 */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ \ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0x59,PEX1_TARGET_ID}, /* PEX1_MEM */ \ + {0x51,PEX1_TARGET_ID}, /* PEX1_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1B,DEV_TARGET_ID}, /* FLASH_CS */ \ + {0x0F,DEV_TARGET_ID} /* DEV_BOOCS*/ \ +} + + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "PEX1_MEM", /* PEX1_MEM */ \ + "PEX1_IO", /* PEX1_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "FLASH_CS", /* FLASH_CS */ \ + "DEV_BOOCS" /* DEV_BOOCS*/ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F1X81CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5082EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5082EnvSpec.h new file mode 100644 index 0000000..1e3e003 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5082EnvSpec.h @@ -0,0 +1,372 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F5082CtrlEnvSpech +#define __IN88F5082CtrlEnvSpech + + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +#define MV_ETH_REG_BASE(port) (0x72000 + ((port) << 0)) +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 4 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 +#define MV_BOOTDEVICE_INDEX 3 + + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + +/* This define describes the maximum number of available SATA channels. */ +#define MV_SATA_MAX_CHAN 1 + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ + +#define MV_MPP_MAX_GROUP 3 + +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF 0 + +/* This define describes the maximum number of supported PCI/PCIX Interfaces */ +#if defined(MV_INCLUDE_PCI) +#define MV_PCI_MAX_IF 1 +#else +#define MV_PCI_MAX_IF 0 +#endif +#define MV_PCI_START_IF MV_PEX_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 2 +#define MV_USB_VERSION 0 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x80000 + + +/* CESA version #2: One channel, 2KB SRAM, TDMA */ +#define MV_CESA_VERSION 0 +#define MV_CESA_REG_BASE 0x9D000 +#define MV_CESA_SRAM_SIZE 8*1024 + + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 8 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + +/* ARM CPU clock vs. DDR clock */ +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ + +#define MV_CPU_IF_ARMDDRCLCK_TBL { \ + /* CPU FREQ, DDR FREQ, RATIO */ \ + {333333333, 166666667, 2}, \ + {400000000, 200000000, 2}, \ + {400000000, 133333334, 3}, \ + {500000000, 166666667, 3}, \ + {533333333, 133333334, 4}, \ + {600000000, 200000000, 3}, \ + {666666666, 166666667, 5}, \ + {800000000, 200000000, 4}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {480000000, 160000000, 3}, \ + {550000000, 183333334, 3}, \ + {525000000, 175000000, 3}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {466666666, 233333334, 2}, \ + {500000000, 250000000, 2}, \ + {533333333, 266666667, 2}, \ + {600000000, 300000000, 2}, \ + {450000000, 150000000, 3}, \ + {533333333, 178000000, 3}, \ + {575000000, 192000000, 3}, \ + {700000000, 175000000, 4}, \ + {733333333, 183333334, 4}, \ + {750000000, 187000000, 4}, \ + {775000000, 194000000, 4}, \ + {500000000, 125000000, 4}, \ + {500000000, 100000000, 5}, \ + {600000000, 150000000, 4}, \ + {1, 1, 1} \ +}; + + +#define MSAR_ARMDDRCLCK_OFFS 4 + +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + + +#define MSAR_GIGA_PORT_MODE_OFFS 15 +#define MSAR_GIGA_PORT_MODE_MASK (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_GMII (0x2 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x3 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + + + + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + + + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS3)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) \ + ((MV_TARGET)((MV_U32)(bar - CS0_BAR) + (MV_U32)SDRAM_CS0)) + + +#define MV_TARGET_IS_AS_BOOT(target) 0 +#define BOOT_TARGETS_NAME_ARRAY {} +#define MV_CHANGE_BOOT_CS(target) (target) + + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + INTER_REGS, /* Internal registers */ + DEVICE_CS0, /* Device chip select 0 */ + DEVICE_CS1, /* Device chip select 0 */ + DEVICE_CS2, /* Device chip select 0 */ + DEV_BOOCS, /* Flash Boot chip select */ + CRYPT_ENG, /* Crypto Engine */ + MAX_TARGETS + +}MV_TARGET; + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM + +/* For old competability */ +#define DEVICE_CS3 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* Device Interface registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num) == MV_BOOTDEVICE_INDEX) ? 0x1046C : (((num) * 4) + 0x1045C)) + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PCI0_MEM +#define PCI_IF1_IO PCI0_IO + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0 PCI0_MEM +#define PCI_IF0_IO PCI0_IO + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO + +#endif + + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + CRYPT_TARGET_ID =9 , /* Port 9 --> Crypto Engine */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ \ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1E,DEV_TARGET_ID}, /* DEVICE_CS0 */ \ + {0x1D,DEV_TARGET_ID}, /* DEVICE_CS1 */ \ + {0x1B,DEV_TARGET_ID}, /* DEVICE_CS2 */ \ + {0x0F,DEV_TARGET_ID}, /* DEV_BOOCS*/ \ + {0x00,CRYPT_TARGET_ID} /* CRYPT_ENG */ \ +} + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "DEVICE_CS0", /* DEVICE_CS0 */ \ + "DEVICE_CS1", /* DEVICE_CS1 */ \ + "DEVICE_CS2", /* DEVICE_CS2 */ \ + "DEV_BOOTCS", /* DEV_BOOTCS*/ \ + "CRYPT_ENG" /* CRYPT_ENG */ \ +} + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F5082CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5180NEnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5180NEnvSpec.h new file mode 100644 index 0000000..702f521 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5180NEnvSpec.h @@ -0,0 +1,349 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F5180NCtrlEnvSpech +#define __IN88F5180NCtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +/* includes */ + + +#define MV_ETH_REG_BASE(port) 0x72000 +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) + + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 4 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 +#define MV_BOOTDEVICE_INDEX 3 + + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ + +#define MV_MPP_MAX_GROUP 4 +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF 0 + +/* This define describes the maximum number of supported PCI/PCIX Interfaces */ +#if defined(MV_INCLUDE_PCI) +#define MV_PCI_MAX_IF 1 +#else +#define MV_PCI_MAX_IF 0 +#endif +#define MV_PCI_START_IF MV_PEX_MAX_IF + + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 1 +#define MV_USB_VERSION 0 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x80000 + + + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 8 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + +/* ARM CPU clock vs. DDR clock */ +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ +#define MV_CPU_IF_ARMDDRCLCK_TBL { \ + /* CPU FREQ, DDR FREQ, RATIO */ \ + {333333333, 166666667, 2}, \ + {400000000, 200000000, 2}, \ + {400000000, 133333334, 3}, \ + {500000000, 166666667, 3}, \ + {533333333, 133333334, 4}, \ + {600000000, 200000000, 3}, \ + {666666666, 166666667, 5}, \ + {800000000, 200000000, 4}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {480000000, 160000000, 3}, \ + {550000000, 183333334, 3}, \ + {525000000, 175000000, 3}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {466666666, 233333334, 2}, \ + {500000000, 250000000, 2}, \ + {533333333, 266666667, 2}, \ + {600000000, 300000000, 2}, \ + {450000000, 150000000, 3}, \ + {533333333, 178000000, 3}, \ + {575000000, 192000000, 3}, \ + {700000000, 175000000, 4}, \ + {733333333, 183333334, 4}, \ + {750000000, 187000000, 4}, \ + {775000000, 194000000, 4}, \ + {500000000, 125000000, 4}, \ + {500000000, 100000000, 5}, \ + {600000000, 150000000, 4}, \ + {1, 1, 1} \ +}; + + +#define MSAR_ARMDDRCLCK_OFFS 4 + +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + + + +#define MSAR_GIGA_PORT_MODE_OFFS 15 +#define MSAR_GIGA_PORT_MODE_MASK (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_GMII (0x2 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x3 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + + + + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS3)) + +#define MV_TARGET_IS_PCI(target) \ + ((target >= PCI0_MEM) && (target <= PCI0_IO)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) \ + ((MV_TARGET)((MV_U32)(bar - CS0_BAR) + (MV_U32)SDRAM_CS0)) + + +#define MV_TARGET_IS_AS_BOOT(target) 0 +#define BOOT_TARGETS_NAME_ARRAY {} +#define MV_CHANGE_BOOT_CS(target) (target) + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PCI0_MEM, /* PCI Memory */ + PCI0_IO, /* PCI IO */ + INTER_REGS, /* Internal registers */ + DEVICE_CS0, /* Device chip select 0 */ + DEVICE_CS1, /* Device chip select 0 */ + DEVICE_CS2, /* Device chip select 0 */ + DEV_BOOCS, /* Flash Boot chip select */ + MAX_TARGETS + +}MV_TARGET; + +/* CV Support */ +#define PCI0_MEM0 PCI0_MEM + + +/* For old competability */ +#define DEVICE_CS3 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* Device Interface registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num) == MV_BOOTDEVICE_INDEX) ? 0x1046C : (((num) * 4) + 0x1045C)) + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) + +#define PCI_IF0_MEM0 PCI0_MEM +#define PCI_IF0_IO PCI0_IO + + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PCI_TARGET_ID = 3 , /* Port 3 -> PCI */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ \ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ \ + {0x59,PCI_TARGET_ID}, /* PCI0_MEM */ \ + {0x51,PCI_TARGET_ID}, /* PCI0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1E,DEV_TARGET_ID}, /* DEVICE_CS0 */ \ + {0x1D,DEV_TARGET_ID}, /* DEVICE_CS1 */ \ + {0x1B,DEV_TARGET_ID}, /* DEVICE_CS2 */ \ + {0x0F,DEV_TARGET_ID} /* DEV_BOOCS*/ \ +} + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PCI0_MEM", /* PCI0_MEM */ \ + "PCI0_IO", /* PCI0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "DEVICE_CS0", /* DEVICE_CS0 */ \ + "DEVICE_CS1", /* DEVICE_CS1 */ \ + "DEVICE_CS2", /* DEVICE_CS2 */ \ + "DEV_BOOCS" /* DEV_BOOCS*/ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F5180NCtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5181LEnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5181LEnvSpec.h new file mode 100644 index 0000000..e6e17a6 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5181LEnvSpec.h @@ -0,0 +1,380 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F5181LCtrlEnvSpech +#define __IN88F5181LCtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +/* includes */ +#define MV_ETH_VERSION 0 +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_REG_BASE(port) 0x72000 +#define MV_ETH_PORT_SGMII { MV_FALSE } +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) + + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 4 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 +#define MV_BOOTDEVICE_INDEX 3 + + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ + +#define MV_MPP_MAX_GROUP 4 +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF 0 + +/* This define describes the maximum number of supported PCI/PCIX Interfaces */ +#if defined(MV_INCLUDE_PCI) +#define MV_PCI_MAX_IF 1 +#else +#define MV_PCI_MAX_IF 0 +#endif +#define MV_PCI_START_IF MV_PEX_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 1 +#define MV_USB_VERSION 0 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x80000 +#define TDM_REG_BASE 0xB0000 + +/* CESA version #2: One channel, 2KB SRAM, TDMA */ +#define MV_CESA_VERSION 0 +#define MV_CESA_REG_BASE 0x9D000 +#define MV_CESA_SRAM_SIZE 8*1024 + + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 8 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + +/* ARM CPU clock vs. DDR clock */ +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ + +#define MV_CPU_IF_ARMDDRCLCK_TBL { \ + /* CPU FREQ, DDR FREQ, RATIO */ \ + {333333333, 166666667, 2}, \ + {400000000, 200000000, 2}, \ + {400000000, 133333334, 3}, \ + {500000000, 166666667, 3}, \ + {533333333, 133333334, 4}, \ + {600000000, 200000000, 3}, \ + {666666666, 166666667, 5}, \ + {800000000, 200000000, 4}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {480000000, 160000000, 3}, \ + {550000000, 183333334, 3}, \ + {525000000, 175000000, 3}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {466666666, 233333334, 2}, \ + {500000000, 250000000, 2}, \ + {533333333, 266666667, 2}, \ + {600000000, 300000000, 2}, \ + {450000000, 150000000, 3}, \ + {533333333, 178000000, 3}, \ + {575000000, 192000000, 3}, \ + {700000000, 175000000, 4}, \ + {733333333, 183333334, 4}, \ + {750000000, 187000000, 4}, \ + {775000000, 194000000, 4}, \ + {500000000, 125000000, 4}, \ + {500000000, 100000000, 5}, \ + {600000000, 150000000, 4}, \ + {1, 1, 1} \ +}; + +#define MSAR_ARMDDRCLCK_OFFS 4 +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + + +#define MSAR_GIGA_PORT_MODE_OFFS 15 +#define MSAR_GIGA_PORT_MODE_MASK (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_GMII (0x2 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x3 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + + + + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + + + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS3)) + +#define MV_TARGET_IS_PCI(target) \ + ((target >= PCI0_MEM) && (target <= PCI0_IO)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) \ + ((MV_TARGET)((MV_U32)(bar - CS0_BAR) + (MV_U32)SDRAM_CS0)) + + +#define MV_TARGET_IS_AS_BOOT(target) 0 +#define BOOT_TARGETS_NAME_ARRAY {} +#define MV_CHANGE_BOOT_CS(target) (target) + + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + PCI0_MEM, /* PCI Memory */ + PCI0_IO, /* PCI IO */ + INTER_REGS, /* Internal registers */ + DEVICE_CS0, /* Device chip select 0 */ + DEVICE_CS1, /* Device chip select 0 */ + DEVICE_CS2, /* Device chip select 0 */ + DEV_BOOCS, /* Flash Boot chip select */ + CRYPT_ENG, /* Crypto Engine */ + MAX_TARGETS + +}MV_TARGET; + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM +#define PCI0_MEM0 PCI0_MEM + + +/* For old competability */ +#define DEVICE_CS3 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* Device Interface registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num) == MV_BOOTDEVICE_INDEX) ? 0x1046C : (((num) * 4) + 0x1045C)) + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PCI0_MEM +#define PCI_IF1_IO PCI0_IO + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0 PCI0_MEM +#define PCI_IF0_IO PCI0_IO + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO + +#endif + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PCI_TARGET_ID = 3 , /* Port 3 -> PCI */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + CRYPT_TARGET_ID =9 , /* Port 9 --> Crypto Engine */ + MAX_TARGETS_ID +}MV_TARGET_ID; + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ \ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0x59,PCI_TARGET_ID}, /* PCI0_MEM */ \ + {0x51,PCI_TARGET_ID}, /* PCI0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1E,DEV_TARGET_ID}, /* DEVICE_CS0 */ \ + {0x1D,DEV_TARGET_ID}, /* DEVICE_CS1 */ \ + {0x1B,DEV_TARGET_ID}, /* DEVICE_CS2 */ \ + {0x0F,DEV_TARGET_ID}, /* DEV_BOOCS*/ \ + {0x00,CRYPT_TARGET_ID} /* CRYPT_ENG */ \ +} + + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "PCI0_MEM", /* PCI0_MEM */ \ + "PCI0_IO", /* PCI0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "DEVICE_CS0", /* DEVICE_CS0 */ \ + "DEVICE_CS1", /* DEVICE_CS1 */ \ + "DEVICE_CS2", /* DEVICE_CS2 */ \ + "DEV_BOOCS", /* DEV_BOOCS*/ \ + "CRYPT_ENG" /* CRYPT_ENG */ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F5181LCtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5182EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5182EnvSpec.h new file mode 100644 index 0000000..c3651b6 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5182EnvSpec.h @@ -0,0 +1,386 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F5182CtrlEnvSpech +#define __IN88F5182CtrlEnvSpech + + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 4 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 +#define MV_BOOTDEVICE_INDEX 3 + + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + +/* This define describes the maximum number of available SATA channels. */ +#define MV_SATA_MAX_CHAN 2 + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ + +#define MV_MPP_MAX_GROUP 3 + +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF 0 + +/* This define describes the maximum number of supported PCI/PCIX Interfaces */ +#if defined(MV_INCLUDE_PCI) +#define MV_PCI_MAX_IF 1 +#else +#define MV_PCI_MAX_IF 0 +#endif +#define MV_PCI_START_IF MV_PEX_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_VERSION 1 +#define MV_ETH_REG_BASE(port) (0x72000 + ((port) << 0)) +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 2 +#define MV_USB_VERSION 0 + + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x80000 + +/* CESA version #2: One channel, 2KB SRAM, TDMA */ +#define MV_CESA_VERSION 0 +#define MV_CESA_REG_BASE 0x9D000 +#define MV_CESA_SRAM_SIZE 8*1024 + + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 8 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + +/* ARM CPU clock vs. DDR clock */ +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ + +#define MV_CPU_IF_ARMDDRCLCK_TBL { \ + /* CPU FREQ, DDR FREQ, RATIO */ \ + {333333333, 166666667, 2}, \ + {400000000, 200000000, 2}, \ + {400000000, 133333334, 3}, \ + {500000000, 166666667, 3}, \ + {533333333, 133333334, 4}, \ + {600000000, 200000000, 3}, \ + {666666666, 166666667, 5}, \ + {800000000, 200000000, 4}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {480000000, 160000000, 3}, \ + {550000000, 183333334, 3}, \ + {525000000, 175000000, 3}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {466666666, 233333334, 2}, \ + {500000000, 250000000, 2}, \ + {533333333, 266666667, 2}, \ + {600000000, 300000000, 2}, \ + {450000000, 150000000, 3}, \ + {533333333, 178000000, 3}, \ + {575000000, 192000000, 3}, \ + {700000000, 175000000, 4}, \ + {733333333, 183333334, 4}, \ + {750000000, 187000000, 4}, \ + {775000000, 194000000, 4}, \ + {500000000, 125000000, 4}, \ + {500000000, 100000000, 5}, \ + {600000000, 150000000, 4}, \ + {1, 1, 1} \ +}; + +#define MSAR_ARMDDRCLCK_OFFS 4 + +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + + +#define MSAR_GIGA_PORT_MODE_OFFS 15 +#define MSAR_GIGA_PORT_MODE_MASK (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_GMII (0x2 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x3 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + + + + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + + + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS3)) + +#define MV_TARGET_IS_PCI(target) \ + ((target >= PCI0_MEM) && (target <= PCI0_IO)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) \ + ((MV_TARGET)((MV_U32)(bar - CS0_BAR) + (MV_U32)SDRAM_CS0)) + +#define MV_TARGET_IS_AS_BOOT(target) 0 + +#define MV_CHANGE_BOOT_CS(target) (target) + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + PCI0_MEM, /* PCI Memory */ + PCI0_IO, /* PCI IO */ + INTER_REGS, /* Internal registers */ + DEVICE_CS0, /* Device chip select 0 */ + DEVICE_CS1, /* Device chip select 0 */ + DEVICE_CS2, /* Device chip select 0 */ + DEV_BOOCS, /* Flash Boot chip select */ + CRYPT_ENG, /* Crypto Engine */ + MAX_TARGETS + +}MV_TARGET; + + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM +#define PCI0_MEM0 PCI0_MEM + + +#define BOOT_TARGETS_NAME_ARRAY {} + +/* For old competability */ +#define DEVICE_CS3 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* Device Interface registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num) == MV_BOOTDEVICE_INDEX) ? 0x1046C : (((num) * 4) + 0x1045C)) + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PCI0_MEM +#define PCI_IF1_IO PCI0_IO + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0 PCI0_MEM +#define PCI_IF0_IO PCI0_IO + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO + +#endif + + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PCI_TARGET_ID = 3 , /* Port 3 -> PCI */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + CRYPT_TARGET_ID =9 , /* Port 9 --> Crypto Engine */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ \ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0x59,PCI_TARGET_ID}, /* PCI0_MEM */ \ + {0x51,PCI_TARGET_ID}, /* PCI0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1E,DEV_TARGET_ID}, /* DEVICE_CS0 */ \ + {0x1D,DEV_TARGET_ID}, /* DEVICE_CS1 */ \ + {0x1B,DEV_TARGET_ID}, /* DEVICE_CS2 */ \ + {0x0F,DEV_TARGET_ID}, /* DEV_BOOCS*/ \ + {0x00,CRYPT_TARGET_ID} /* CRYPT_ENG */ \ +} + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "PCI0_MEM", /* PCI0_MEM */ \ + "PCI0_IO", /* PCI0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "DEVICE_CS0", /* DEVICE_CS0 */ \ + "DEVICE_CS1", /* DEVICE_CS1 */ \ + "DEVICE_CS2", /* DEVICE_CS2 */ \ + "DEV_BOOCS", /* DEV_BOOCS*/ \ + "CRYPT_ENG" /* CRYPT_ENG */ \ +} + + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F5182CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5X81EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5X81EnvSpec.h new file mode 100644 index 0000000..25459a5 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F5X81EnvSpec.h @@ -0,0 +1,377 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F5X81CtrlEnvSpech +#define __IN88F5X81CtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +/* includes */ + + +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) + + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 4 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 +#define MV_INCLUDE_SDRAM_CS2 +#define MV_INCLUDE_SDRAM_CS3 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 4 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 +#define MV_BOOTDEVICE_INDEX 3 + + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ + +#define MV_MPP_MAX_GROUP 4 +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_DISABLE_PEX_DEVICE_BAR +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF 0 + +/* This define describes the maximum number of supported PCI/PCIX Interfaces */ +#if defined(MV_INCLUDE_PCI) +#define MV_PCI_MAX_IF 1 +#else +#define MV_PCI_MAX_IF 0 +#endif +#define MV_PCI_START_IF MV_PEX_MAX_IF + + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_VERSION 1 +#define MV_ETH_REG_BASE(port) (0x72000 + ((port) << 0)) +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 1 +#define MV_USB_VERSION 0 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x80000 + + + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 8 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + +/* ARM CPU clock vs. DDR clock */ +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ + +#define MV_CPU_IF_ARMDDRCLCK_TBL { \ + /* CPU FREQ, DDR FREQ, RATIO */ \ + {333333333, 166666667, 2}, \ + {400000000, 200000000, 2}, \ + {400000000, 133333334, 3}, \ + {500000000, 166666667, 3}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {500000000, 250000000, 2}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0} \ +}; + +#define MSAR_ARMDDRCLCK_OFFS 4 + +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + + +#define MSAR_GIGA_PORT_MODE_OFFS 15 +#define MSAR_GIGA_PORT_MODE_MASK (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_GMII (0x2 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x3 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + + + + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS3)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS3)) + +#define MV_TARGET_IS_PCI(target) \ + ((target >= PCI0_MEM) && (target <= PCI0_IO)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) \ + ((MV_TARGET)((MV_U32)(bar - CS0_BAR) + (MV_U32)SDRAM_CS0)) + + +#define MV_TARGET_IS_AS_BOOT(target) 0 +#define BOOT_TARGETS_NAME_ARRAY {} +#define MV_CHANGE_BOOT_CS(target) (target) + + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + SDRAM_CS2, /* SDRAM chip select 2 */ + SDRAM_CS3, /* SDRAM chip select 3 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + PCI0_MEM, /* PCI Memory */ + PCI0_IO, /* PCI IO */ + INTER_REGS, /* Internal registers */ + DEVICE_CS0, /* Device chip select 0 */ + DEVICE_CS1, /* Device chip select 0 */ + DEVICE_CS2, /* Device chip select 0 */ + DEV_BOOCS, /* Flash Boot chip select */ + MAX_TARGETS + +}MV_TARGET; + + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM +#define PCI0_MEM0 PCI0_MEM + + +/* For old competability */ +#define DEVICE_CS3 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* Device Interface registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num) == MV_BOOTDEVICE_INDEX) ? 0x1046C : (((num) * 4) + 0x1045C)) + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) + + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PCI0_MEM +#define PCI_IF1_IO PCI0_IO + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0 PCI0_MEM +#define PCI_IF0_IO PCI0_IO + +#elif defined (MV_INCLUDE_PEX) + + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO + +#endif + + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PCI_TARGET_ID = 3 , /* Port 3 -> PCI */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + MAX_TARGETS_ID +}MV_TARGET_ID; + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x0B,DRAM_TARGET_ID}, /* SDRAM_CS2 */ \ + {0x07,DRAM_TARGET_ID}, /* SDRAM_CS3 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0x59,PCI_TARGET_ID}, /* PCI0_MEM */ \ + {0x51,PCI_TARGET_ID}, /* PCI0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1E,DEV_TARGET_ID}, /* DEVICE_CS0 */ \ + {0x1D,DEV_TARGET_ID}, /* DEVICE_CS1 */ \ + {0x1B,DEV_TARGET_ID}, /* DEVICE_CS2 */ \ + {0x0F,DEV_TARGET_ID} /* DEV_BOOCS*/ \ +} + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "SDRAM_CS2", /* SDRAM_CS2 */ \ + "SDRAM_CS3", /* SDRAM_CS3 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "PCI0_MEM", /* PCI0_MEM */ \ + "PCI0_IO", /* PCI0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "DEVICE_CS0", /* DEVICE_CS0 */ \ + "DEVICE_CS1", /* DEVICE_CS1 */ \ + "DEVICE_CS2", /* DEVICE_CS2 */ \ + "DEV_BOOCS" /* DEV_BOOCS*/ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F5X81CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6082EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6082EnvSpec.h new file mode 100644 index 0000000..e021ab4 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6082EnvSpec.h @@ -0,0 +1,394 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F6082CtrlEnvSpech +#define __IN88F6082CtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 2 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 5 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 +#define MV_INCLUDE_DEVICE_CS4 +#define MV_BOOTDEVICE_INDEX 0 + + +#define MV_INCLUDE_CLK_PWR_CNTRL + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + +/* This define describes the maximum number of available SATA channels. */ +#define MV_SATA_MAX_CHAN 1 + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ +#define MV_MPP_MAX_GROUP 2 + +/* This define describes the maximum number of supported PCI\PCIX Interfaces*/ +#define MV_PCI_MAX_IF 0 +#define MV_PCI_START_IF 0 + +/* This define describes the maximum number of supported PEX Interfaces */ +#define MV_INCLUDE_PEX0 +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF MV_PCI_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + +/* CESA version #2: One channel, 2KB SRAM, TDMA */ +#define MV_CESA_VERSION 2 +#define MV_CESA_REG_BASE 0x3D000 +#define MV_CESA_TDMA_REG_BASE 0x30000 +#define MV_CESA_SRAM_SIZE 2*1024 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_VERSION 2 + +#define MV_ETH_REG_BASE(port) (((port) == 0) ? 0x72000 : 0x82000) +#define MV_ETH_MAX_PORTS 2 +#define MV_ETH_PORT_SGMII { MV_TRUE, MV_TRUE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 0 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 1 +#define MV_USB_VERSION 1 + + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x60000 + +/* Controler environment registers offsets */ + +/* Power Managment Control */ +#define POWER_MNG_CTRL_REG 0x2011C + +#define PMC_GESTOPCLOCK_OFFS(port) (port) +#define PMC_GESTOPCLOCK_MASK(port) (1 << PMC_GESTOPCLOCK_OFFS(port)) +#define PMC_GESTOPCLOCK_EN(port) (0 << PMC_GESTOPCLOCK_OFFS(port)) +#define PMC_GESTOPCLOCK_STOP(port) (1 << PMC_GESTOPCLOCK_OFFS(port)) + +#define PMC_PEXSTOPCLOCK_OFFS 2 +#define PMC_PEXSTOPCLOCK_MASK (1 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_EN (0 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_STOP (1 << PMC_PEXSTOPCLOCK_OFFS) + +#define PMC_USBSTOPCLOCK_OFFS 3 +#define PMC_USBSTOPCLOCK_MASK (1 << PMC_USBSTOPCLOCK_OFFS) +#define PMC_USBSTOPCLOCK_EN (0 << PMC_USBSTOPCLOCK_OFFS) +#define PMC_USBSTOPCLOCK_STOP (1 << PMC_USBSTOPCLOCK_OFFS) + +#define PMC_SATASTOPCLOCK_OFFS 4 +#define PMC_SATASTOPCLOCK_MASK (1 << PMC_SATASTOPCLOCK_OFFS) +#define PMC_SATASTOPCLOCK_EN (0 << PMC_SATASTOPCLOCK_OFFS) +#define PMC_SATASTOPCLOCK_STOP (1 << PMC_SATASTOPCLOCK_OFFS) + +#define PMC_SESTOPCLOCK_OFFS 5 +#define PMC_SESTOPCLOCK_MASK (1 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_EN (0 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_STOP (1 << PMC_SESTOPCLOCK_OFFS) + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +/* #define MPP_CONTROL_REG2 0x10050 */ +/* #define DEV_MULTI_CONTROL 0x10008 */ +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_BOOT_MODE_OFFS 0 +#define MSAR_DBOOT_MODE_MASK (0xF << MSAR_BOOT_MODE_OFFS) +#define MSAR_DBOOT_EMB_PMFLASH (0x0 << MSAR_BOOT_MODE_OFFS) +#define MSAR_DBOOT_EMB_SMFLASH (0x1 << MSAR_BOOT_MODE_OFFS) +#define MSAR_DBOOT_EXT_SPI (0x2 << MSAR_BOOT_MODE_OFFS) +#define MSAR_CPU_RST_EXT_SPI_PROG (0x3 << MSAR_BOOT_MODE_OFFS) +#define MSAR_DBOOT_NAND (0x4 << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_EMB_PMFLASH (0x5 << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_EMB_SMFLASH (0x6 << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_EXT_SPI (0x7 << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_EXT_SPI_REG (0x8 << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_EXT_SPI_PROG (0x9 << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_UART (0xA << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_SATA (0xB << MSAR_BOOT_MODE_OFFS) +#define MSAR_IDBOOT_NAND (0xC << MSAR_BOOT_MODE_OFFS) + +#define MSAR_TCLCK_OFFS 14 +#define MSAR_TCLCK_MASK (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x1 << MSAR_TCLCK_OFFS) + +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ +/* ARM CPU clock vs. DDR clock */ +#define MV_CPU_IF_ARMDDRCLCK_TBL {\ + /* CPU FREQ, DDR FREQ, RATIO */\ + {333333333, 166666667, 2},\ + {300000000, 150000000, 2},\ + {400000000, 200000000, 2},\ + {400000000, 133333334, 3},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0}\ +}; + +/* Both giga ports actes as SGMII only */ +#define MSAR_GIGA_PORT_MODE_OFFS 0 +#define MSAR_GIGA_PORT_MODE_MASK (0x0 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_SGMII (0x0 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_GMII (0x1 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x1 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x1 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_ARMDDRCLCK_OFFS 4 +#define MSAR_ARMDDRCLCK_MASK (0x7 << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS1)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS4)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) 0 + +#define MV_TARGET_IS_AS_BOOT(target) ((target) == (sampleAtResetTargetArray[((MV_REG_READ(MPP_SAMPLE_AT_RESET)\ + & MSAR_DBOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)])) + + +#define MV_CHANGE_BOOT_CS(target) ((target) == DEV_BOOCS)?\ + sampleAtResetTargetArray[((MV_REG_READ(MPP_SAMPLE_AT_RESET)\ + & MSAR_DBOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)]\ + :(target) + + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + INTER_REGS, /* Internal registers */ + NFLASH_CS, /* NFLASH_CS */ + MFLASH_CS, /* MFLASH_CS */ + SPI_CS, /* SPI_CS */ + BOOT_ROM_CS, /* BOOT_ROM_CS */ + DEV_BOOCS, /* DEV_BOOCS */ + CRYPT_ENG, /* Crypto Engine */ + MAX_TARGETS + +}MV_TARGET; + + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM + + +#define BOOT_TARGETS_NAME_ARRAY { \ + MFLASH_CS, \ + MFLASH_CS, \ + SPI_CS, \ + TBL_TERM, \ + NFLASH_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS, \ + BOOT_ROM_CS \ +} + +/* For old competability */ +#define DEVICE_CS0 NFLASH_CS +#define DEVICE_CS1 MFLASH_CS +#define DEVICE_CS2 SPI_CS +#define DEVICE_CS3 BOOT_ROM_CS +#define DEVICE_CS4 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num)==0) ? 0x1046C : (((num)==1) ? 0x10500 : 0x10600)) +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2) + + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PEX1_MEM +#define PCI_IF1_IO PEX1_IO + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + CRYPT_TARGET_ID =3 , /* Port 3 --> Crypto Engine */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1B,DEV_TARGET_ID}, /* NFLASH_CS */ \ + {0xF,DEV_TARGET_ID}, /* MFLASH_CS */ \ + {0x1E,DEV_TARGET_ID}, /* SPI_CS */ \ + {0x1D,DEV_TARGET_ID}, /* BOOT_ROM_CS */ \ + {0xF,DEV_TARGET_ID}, /* DEV_BOOCS */ \ + {0x00,CRYPT_TARGET_ID} /* CRYPT_ENG */ \ +} + + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "NFLASH_CS", /* NFLASH_CS */ \ + "MFLASH_CS", /* MFLASH_CS */ \ + "SPI_CS", /* SPI_CS */ \ + "BOOT_ROM_CS", /* BOOT_ROM_CS */ \ + "DEV_BOOTCS", /* DEV_BOOCS */ \ + "CRYPT_ENG" /* CRYPT_ENG */ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F6082CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183EnvSpec.h new file mode 100644 index 0000000..70f0aa3 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183EnvSpec.h @@ -0,0 +1,368 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F6183CtrlEnvSpech +#define __IN88F6183CtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) +#define AUDIO_REG_BASE 0xB0000 + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 2 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 2 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_BOOTDEVICE_INDEX 0 + + +#define MV_INCLUDE_CLK_PWR_CNTRL + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + +/* This define describes the maximum number of available SATA channels. */ +#define MV_SATA_MAX_CHAN 0 + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ +#define MV_MPP_MAX_GROUP 2 + +/* This define describes the maximum number of supported PCI\PCIX Interfaces*/ +#define MV_PCI_MAX_IF 0 +#define MV_PCI_START_IF 0 + +/* This define describes the maximum number of supported PEX Interfaces */ +#define MV_INCLUDE_PEX0 +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF MV_PCI_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + +/* CESA version #2: One channel, 2KB SRAM, TDMA */ +#define MV_CESA_VERSION 2 +#define MV_CESA_REG_BASE 0x3D000 +#define MV_CESA_SRAM_SIZE 2*1024 +#define MV_CESA_TDMA_REG_BASE 0x30000 + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_VERSION 2 + +#define MV_ETH_REG_BASE(port) (((port) == 0) ? 0x72000 : 0x82000) +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 1 +#define MV_USB_VERSION 1 + + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x60000 + +/* Controler environment registers offsets */ + +/* Power Managment Control */ +#define POWER_MNG_CTRL_REG 0x2011C + +#define PMC_GESTOPCLOCK_OFFS(port) (port) +#define PMC_GESTOPCLOCK_MASK(port) (1 << PMC_GESTOPCLOCK_OFFS(port)) +#define PMC_GESTOPCLOCK_EN(port) (0 << PMC_GESTOPCLOCK_OFFS(port)) +#define PMC_GESTOPCLOCK_STOP(port) (1 << PMC_GESTOPCLOCK_OFFS(port)) + +#define PMC_PEXSTOPCLOCK_OFFS 2 +#define PMC_PEXSTOPCLOCK_MASK (1 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_EN (0 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_STOP (1 << PMC_PEXSTOPCLOCK_OFFS) + +#define PMC_USBSTOPCLOCK_OFFS 3 +#define PMC_USBSTOPCLOCK_MASK (1 << PMC_USBSTOPCLOCK_OFFS) +#define PMC_USBSTOPCLOCK_EN (0 << PMC_USBSTOPCLOCK_OFFS) +#define PMC_USBSTOPCLOCK_STOP (1 << PMC_USBSTOPCLOCK_OFFS) + +#define PMC_SATASTOPCLOCK_OFFS 4 +#define PMC_SATASTOPCLOCK_MASK (1 << PMC_SATASTOPCLOCK_OFFS) +#define PMC_SATASTOPCLOCK_EN (0 << PMC_SATASTOPCLOCK_OFFS) +#define PMC_SATASTOPCLOCK_STOP (1 << PMC_SATASTOPCLOCK_OFFS) + +#define PMC_SESTOPCLOCK_OFFS 5 +#define PMC_SESTOPCLOCK_MASK (1 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_EN (0 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_STOP (1 << PMC_SESTOPCLOCK_OFFS) + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10008 +#define MPP_CONTROL_REG3 0x1000C +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_BOOT_MODE_OFFS 0 +#define MSAR_BOOT_MODE_MASK (0x1 << MSAR_BOOT_MODE_OFFS) +#define MSAR_BOOT_NAND (0x0 << MSAR_BOOT_MODE_OFFS) +#define MSAR_BOOT_EXT_SPI (0x1 << MSAR_BOOT_MODE_OFFS) + +#define MSAR_TCLCK_OFFS 9 +#define MSAR_TCLCK_MASK (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x1 << MSAR_TCLCK_OFFS) + +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ +/* ARM CPU clock vs. DDR clock */ +#define MV_CPU_IF_ARMDDRCLCK_TBL {\ + /* CPU FREQ, DDR FREQ, RATIO */\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {333333333, 166666667, 2},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {400000000, 200000000, 2},\ +}; + +/* Both giga ports actes as SGMII only */ +#define MSAR_GIGA_PORT_MODE_OFFS 0 +#define MSAR_GIGA_PORT_MODE_MASK (0x0 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_SGMII (0x0 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_GMII (0x1 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x1 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x1 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_ARMDDRCLCK_OFFS 1 +#define MSAR_ARMDDRCLCK_MASK (0x3F << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK 0 + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS1)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS1)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) 0 + +#define MV_TARGET_IS_AS_BOOT(target) ((target) == (sampleAtResetTargetArray[((MV_REG_READ(MPP_SAMPLE_AT_RESET)\ + & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)])) + + +#define MV_CHANGE_BOOT_CS(target) ((target) == DEV_BOOCS)?\ + sampleAtResetTargetArray[((MV_REG_READ(MPP_SAMPLE_AT_RESET)\ + & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)]\ + :(target) + +#define MV_CPU_ADDRESS_DECODE_WA +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + INTER_REGS, /* Internal registers */ + NFLASH_CS, /* NFLASH_CS */ + SPI_CS, /* SPI_CS */ + DEV_BOOCS, /* DEV_BOOCS */ + CRYPT_ENG, /* Crypto Engine */ + MAX_TARGETS + +}MV_TARGET; + + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM + + +#define BOOT_TARGETS_NAME_ARRAY { \ + NFLASH_CS, \ + SPI_CS, \ + TBL_TERM, \ +} + +/* For old competability */ +#define DEVICE_CS0 NFLASH_CS +#define DEVICE_CS1 SPI_CS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num)==0) ? 0x1046C : 0x10604) +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2) + + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PEX1_MEM +#define PCI_IF1_IO PEX1_IO + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + CRYPT_TARGET_ID =3 , /* Port 3 --> Crypto Engine */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1B,DEV_TARGET_ID}, /* NFLASH_CS */ \ + {0x1E,DEV_TARGET_ID}, /* SPI_CS */ \ + {0x1E,DEV_TARGET_ID}, /* DEV_BOOCS */ \ + {0x00,CRYPT_TARGET_ID} /* CRYPT_ENG */ \ +} + + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "NFLASH_CS", /* NFLASH_CS */ \ + "SPI_CS", /* SPI_CS */ \ + "DEV_BOOTCS", /* DEV_BOOCS */ \ + "CRYPT_ENG" /* CRYPT_ENG */ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F6183CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183LEnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183LEnvSpec.h new file mode 100644 index 0000000..bba220d --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88F6183LEnvSpec.h @@ -0,0 +1,330 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88F6183LCtrlEnvSpech +#define __IN88F6183LCtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88F" + +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) +#define AUDIO_REG_BASE 0xB0000 + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 2 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 2 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_BOOTDEVICE_INDEX 0 + + +#define MV_INCLUDE_CLK_PWR_CNTRL + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + +/* This define describes the maximum number of available SATA channels. */ +#define MV_SATA_MAX_CHAN 0 + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ +#define MV_MPP_MAX_GROUP 2 + +/* This define describes the maximum number of supported PCI\PCIX Interfaces*/ +#define MV_PCI_MAX_IF 0 +#define MV_PCI_START_IF 0 + +/* This define describes the maximum number of supported PEX Interfaces */ +#define MV_INCLUDE_PEX0 +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF MV_PCI_MAX_IF + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_MAX_PORTS 0 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +#define SATA_REG_BASE 0x60000 + +/* Controler environment registers offsets */ + +/* Power Managment Control */ +#define POWER_MNG_CTRL_REG 0x2011C + +#define PMC_PEXSTOPCLOCK_OFFS 2 +#define PMC_PEXSTOPCLOCK_MASK (1 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_EN (0 << PMC_PEXSTOPCLOCK_OFFS) +#define PMC_PEXSTOPCLOCK_STOP (1 << PMC_PEXSTOPCLOCK_OFFS) + +#define PMC_SATASTOPCLOCK_OFFS 4 +#define PMC_SATASTOPCLOCK_MASK (1 << PMC_SATASTOPCLOCK_OFFS) +#define PMC_SATASTOPCLOCK_EN (0 << PMC_SATASTOPCLOCK_OFFS) +#define PMC_SATASTOPCLOCK_STOP (1 << PMC_SATASTOPCLOCK_OFFS) + +#define PMC_SESTOPCLOCK_OFFS 5 +#define PMC_SESTOPCLOCK_MASK (1 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_EN (0 << PMC_SESTOPCLOCK_OFFS) +#define PMC_SESTOPCLOCK_STOP (1 << PMC_SESTOPCLOCK_OFFS) + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10008 +#define MPP_CONTROL_REG3 0x1000C +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_BOOT_MODE_OFFS 0 +#define MSAR_BOOT_MODE_MASK (0x1 << MSAR_BOOT_MODE_OFFS) +#define MSAR_BOOT_NAND (0x0 << MSAR_BOOT_MODE_OFFS) +#define MSAR_BOOT_EXT_SPI (0x1 << MSAR_BOOT_MODE_OFFS) + +#define MSAR_TCLCK_OFFS 9 +#define MSAR_TCLCK_MASK (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x1 << MSAR_TCLCK_OFFS) + +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ +/* ARM CPU clock vs. DDR clock */ +#define MV_CPU_IF_ARMDDRCLCK_TBL {\ + /* CPU FREQ, DDR FREQ, RATIO */\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {333333333, 166666667, 2},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ + {0, 0, 0},\ +}; + +#define MSAR_ARMDDRCLCK_OFFS 1 +#define MSAR_ARMDDRCLCK_MASK (0x3F << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK 0 + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS1)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS1)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) 0 + +#define MV_TARGET_IS_AS_BOOT(target) ((target) == (sampleAtResetTargetArray[((MV_REG_READ(MPP_SAMPLE_AT_RESET)\ + & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)])) + + +#define MV_CHANGE_BOOT_CS(target) ((target) == DEV_BOOCS)?\ + sampleAtResetTargetArray[((MV_REG_READ(MPP_SAMPLE_AT_RESET)\ + & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)]\ + :(target) + +#define MV_CPU_ADDRESS_DECODE_WA +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + INTER_REGS, /* Internal registers */ + NFLASH_CS, /* NFLASH_CS */ + SPI_CS, /* SPI_CS */ + DEV_BOOCS, /* DEV_BOOCS */ + MAX_TARGETS + +}MV_TARGET; + + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM + + +#define BOOT_TARGETS_NAME_ARRAY { \ + NFLASH_CS, \ + SPI_CS, \ + TBL_TERM, \ +} + +/* For old competability */ +#define DEVICE_CS0 NFLASH_CS +#define DEVICE_CS1 SPI_CS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num)==0) ? 0x1046C : 0x10604) +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2) + + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PEX1_MEM +#define PCI_IF1_IO PEX1_IO + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1B,DEV_TARGET_ID}, /* NFLASH_CS */ \ + {0x1E,DEV_TARGET_ID}, /* SPI_CS */ \ + {0x1E,DEV_TARGET_ID}, /* DEV_BOOCS */ \ +} + + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "NFLASH_CS", /* NFLASH_CS */ \ + "SPI_CS", /* SPI_CS */ \ + "DEV_BOOTCS", /* DEV_BOOCS */ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88F6183LCtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88w8660EnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88w8660EnvSpec.h new file mode 100644 index 0000000..3978b13 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mv88w8660EnvSpec.h @@ -0,0 +1,367 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __IN88W8660CtrlEnvSpech +#define __IN88W8660CtrlEnvSpech + +#define MV_ARM_SOC +#define SOC_NAME_PREFIX "MV88W" +/* includes */ + + +/* defines */ + + +#define MV_ETH_REG_BASE(port) 0x72000 +#define USB_REG_BASE(dev) (((dev) == 0) ? 0x50000 : 0xA0000) + + +#define INTER_REGS_SIZE _1M + + +/* This define describes the maximum controller supported DRAM chip select */ +/* also known as banks */ +#define MV_DRAM_MAX_CS 2 +#define MV_INCLUDE_SDRAM_CS0 +#define MV_INCLUDE_SDRAM_CS1 + +/* This define describes the maximum controller supported DEVICE chip select */ +/* also known as banks */ +#define MV_DEVICE_MAX_CS 4 +#define MV_INCLUDE_DEVICE_CS0 +#define MV_INCLUDE_DEVICE_CS1 +#define MV_INCLUDE_DEVICE_CS2 +#define MV_INCLUDE_DEVICE_CS3 +#define MV_BOOTDEVICE_INDEX 3 + + + +/* This define describes maximum of GPP groups supported by controller. */ +#define MV_GPP_MAX_GROUP 1 + + +/* This define describes the maximum number of available Timer/counters. */ +#define MV_CNTMR_MAX_COUNTER 2 + +/* This define describes the maximum number of available UART channels. */ +#define MV_UART_MAX_CHAN 2 + + + +/* This define describes maximum number of MPP groups. */ +/* Each group describes an MPP register. */ + +#define MV_MPP_MAX_GROUP 2 +/* This define describes the maximum number of supported PEX Interfaces */ +#if defined(MV_INCLUDE_PEX) +#define MV_PEX_MAX_IF 1 +#else +#define MV_PEX_MAX_IF 0 +#endif +#define MV_PEX_START_IF 0 + +/* This define describes the maximum number of supported PCI/PCIX Interfaces */ +#if defined(MV_INCLUDE_PCI) +#define MV_PCI_MAX_IF 1 +#else +#define MV_PCI_MAX_IF 0 +#endif +#define MV_PCI_START_IF MV_PEX_MAX_IF + + +/* This define describes the maximum number of supported PCI Interfaces */ +#define MV_PCI_IF_MAX_IF (MV_PEX_MAX_IF+MV_PCI_MAX_IF) + + +#define PEX_HOST_BUS_NUM(pciIf) (pciIf) +#define PEX_HOST_DEV_NUM(pciIf) 0 + +#define PCI_HOST_BUS_NUM(pciIf) MV_PEX_MAX_IF + (pciIf) +#define PCI_HOST_DEV_NUM(pciIf) 0 + + +/* This define describes the maximum number of supported Ethernet ports */ +#define MV_ETH_MAX_PORTS 1 +#define MV_ETH_PORT_SGMII { MV_FALSE } + +/* This define describes the maximum number of supported IDMA channels. */ +#define MV_IDMA_MAX_CHAN 4 + +/* This define describes the the support of USB */ +#define MV_USB_MAX 1 +#define MV_USB_VERSION 0 + +/* This define describes the support of the NAND -Flash */ +#define MV_NAND_MAX 1 + + +#define SATA_REG_BASE 0x80000 + + + +/* Controler environment registers offsets */ +#define MPP_CONTROL_REG0 0x10000 +#define MPP_CONTROL_REG1 0x10004 +#define MPP_CONTROL_REG2 0x10050 +#define DEV_MULTI_CONTROL 0x10008 +#define MPP_SAMPLE_AT_RESET 0x10010 +#define MV_UART_CHAN_BASE(chanNum) (0x12000 + (chanNum * 0x100)) + +#define MSAR_TCLCK_OFFS 8 +#define MSAR_TCLCK_MASK (0x3 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_133 (0x0 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_150 (0x1 << MSAR_TCLCK_OFFS) +#define MSAR_TCLCK_166 (0x2 << MSAR_TCLCK_OFFS) + +/* ARM CPU clock vs. DDR clock */ +/* This array is beening call from several files. + mvCpuArm.c, mvBoardEnvLib.c, mvCpuIfInit.S */ + +#define MV_CPU_IF_ARMDDRCLCK_TBL { \ + /* CPU FREQ, DDR FREQ, RATIO */ \ + {333333333, 166666667, 2}, \ + {400000000, 200000000, 2}, \ + {400000000, 133333334, 3}, \ + {500000000, 166666667, 3}, \ + {533333333, 133333334, 4}, \ + {600000000, 200000000, 3}, \ + {666666666, 166666667, 5}, \ + {800000000, 200000000, 4}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {480000000, 160000000, 3}, \ + {550000000, 183333334, 3}, \ + {525000000, 175000000, 3}, \ + {0, 0, 0}, \ + {0, 0, 0}, \ + {466666666, 233333334, 2}, \ + {500000000, 250000000, 2}, \ + {533333333, 266666667, 2}, \ + {600000000, 300000000, 2}, \ + {450000000, 150000000, 3}, \ + {533333333, 178000000, 3}, \ + {575000000, 192000000, 3}, \ + {700000000, 175000000, 4}, \ + {733333333, 183333334, 4}, \ + {750000000, 187000000, 4}, \ + {775000000, 194000000, 4}, \ + {500000000, 125000000, 4}, \ + {500000000, 100000000, 5}, \ + {600000000, 150000000, 4}, \ + {1, 1, 1} \ +}; + +#define MSAR_ARMDDRCLCK_OFFS 4 + +#define MSAR_ARMDDRCLCK_MASK (0xf << MSAR_ARMDDRCLCK_OFFS) +#define MSAR_ARMDDRCLCK_H_MASK BIT23 + +#define MSAR_GIGA_PORT_MODE_OFFS 15 +#define MSAR_GIGA_PORT_MODE_MASK (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +#define MSAR_GIGA_PORT_MODE_GMII (0x2 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_MII (0x3 << MSAR_GIGA_PORT_MODE_OFFS) +#define MSAR_GIGA_PORT_MODE_RGMII (0x7 << MSAR_GIGA_PORT_MODE_OFFS) + +/* These macros help units to identify a target Mbus Arbiter group */ +#define MV_TARGET_IS_DRAM(target) \ + ((target >= SDRAM_CS0) && (target <= SDRAM_CS1)) + +#define MV_TARGET_IS_PEX0(target) \ + ((target >= PEX0_MEM) && (target <= PEX0_IO)) + + +#define MV_TARGET_IS_PEX1(target) 0 + +#define MV_TARGET_IS_PEX(target) (MV_TARGET_IS_PEX0(target) || MV_TARGET_IS_PEX1(target)) + +#define MV_TARGET_IS_DEVICE(target) \ + ((target >= DEVICE_CS0) && (target <= DEVICE_CS3)) + +#define MV_TARGET_IS_PCI(target) \ + ((target >= PCI0_MEM) && (target <= PCI0_IO)) + +#define MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar) \ + ((MV_TARGET)((MV_U32)(bar - CS0_BAR) + (MV_U32)SDRAM_CS0)) + + +#define MV_TARGET_IS_AS_BOOT(target) 0 + +#define MV_CHANGE_BOOT_CS(target) (target) + +#define TCLK_TO_COUNTER_RATIO 1 /* counters running in Tclk */ +/* typedefs */ + + +#ifndef MV_ASMLANGUAGE +/* This enumerator described the possible Controller paripheral targets. */ +/* Controller peripherals are designated memory/IO address spaces that the */ +/* controller can access. They are also refered as "targets" */ +typedef enum _mvTarget +{ + TBL_TERM = -1, /* none valid target, used as targets list terminator*/ + SDRAM_CS0, /* SDRAM chip select 0 */ + SDRAM_CS1, /* SDRAM chip select 1 */ + PEX0_MEM, /* PCI Express 0 Memory */ + PEX0_IO, /* PCI Express 0 IO */ + PCI0_MEM, /* PCI Memory */ + PCI0_IO, /* PCI IO */ + INTER_REGS, /* Internal registers */ + DEVICE_CS0, /* Device chip select 0 */ + DEVICE_CS1, /* Device chip select 0 */ + DEVICE_CS2, /* Device chip select 0 */ + DEV_BOOCS, /* Flash Boot chip select */ + MAX_TARGETS + +}MV_TARGET; + +/* CV Support */ +#define PEX0_MEM0 PEX0_MEM +#define PCI0_MEM0 PCI0_MEM + + +#define BOOT_TARGETS_NAME_ARRAY {} + +/* For old competability */ +#define DEVICE_CS3 DEV_BOOCS + +#define START_DEV_CS DEV_CS0 +#define DEV_TO_TARGET(dev) ((dev) + DEVICE_CS0) + +/* Device Interface registers offsets */ +#define DEV_BANK_PARAM_REG(num) (((num) == MV_BOOTDEVICE_INDEX) ? 0x1046C : (((num) * 4) + 0x1045C)) + +/* Device Interface NAND Flash Control Register (DINFCR) */ +#define DINFCR_NF_CS_MASK(csNum) (0x1 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) +#define DINFCR_NF_ACT_CE_MASK(csNum) (0x2 << ((((csNum)+1) % MV_DEVICE_MAX_CS) * 2)) + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO +#define PCI_IF1_MEM0 PCI0_MEM +#define PCI_IF1_IO PCI0_IO + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0 PCI0_MEM +#define PCI_IF0_IO PCI0_IO + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0 PEX0_MEM +#define PCI_IF0_IO PEX0_IO + +#endif + + + +/* This enumerator defines the Marvell controller target ID */ +typedef enum _mvTargetId +{ + DRAM_TARGET_ID = 0 , /* Port 0 -> DRAM interface */ + DEV_TARGET_ID = 1, /* Port 1 -> PCI Express */ + PCI_TARGET_ID = 3 , /* Port 3 -> PCI */ + PEX0_TARGET_ID = 4 , /* Port 4 -> PCI Express0 */ + MAX_TARGETS_ID +}MV_TARGET_ID; + + +#define TARGETS_DEF_ARRAY { \ + {0x0E,DRAM_TARGET_ID}, /* SDRAM_CS0 */ \ + {0x0D,DRAM_TARGET_ID}, /* SDRAM_CS1 */ \ + {0x59,PEX0_TARGET_ID}, /* PEX0_MEM */ \ + {0x51,PEX0_TARGET_ID}, /* PEX0_IO */ \ + {0x59,PCI_TARGET_ID}, /* PCI0_MEM */ \ + {0x51,PCI_TARGET_ID}, /* PCI0_IO */ \ + {0xFF, 0xFF}, /* INTER_REGS */ \ + {0x1E,DEV_TARGET_ID}, /* DEVICE_CS0 */ \ + {0x1D,DEV_TARGET_ID}, /* DEVICE_CS1 */ \ + {0x1B,DEV_TARGET_ID}, /* DEVICE_CS2 */ \ + {0x0F,DEV_TARGET_ID} /* DEV_BOOCS*/ \ +} + +#define TARGETS_NAME_ARRAY { \ + "SDRAM_CS0", /* SDRAM_CS0 */ \ + "SDRAM_CS1", /* SDRAM_CS1 */ \ + "PEX0_MEM", /* PEX0_MEM */ \ + "PEX0_IO", /* PEX0_IO */ \ + "PCI0_MEM", /* PCI0_MEM */ \ + "PCI0_IO", /* PCI0_IO */ \ + "INTER_REGS", /* INTER_REGS */ \ + "DEVICE_CS0", /* DEVICE_CS0 */ \ + "DEVICE_CS1", /* DEVICE_CS1 */ \ + "DEVICE_CS2", /* DEVICE_CS2 */ \ + "DEV_BOOCS" /* DEV_BOOCS*/ \ +} + + +#endif /* MV_ASMLANGUAGE */ + + +#endif /* __IN88W8660CtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.c new file mode 100644 index 0000000..9325db9 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.c @@ -0,0 +1,296 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/******************************************************************************* +* mvCtrlEnvAddrDec.h - Marvell controller address decode library +* +* DESCRIPTION: +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +/* includes */ +#include "ctrlEnv/mvCtrlEnvAddrDec.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" +#include "ddr1_2/mvDramIfRegs.h" +#include "pex/mvPexRegs.h" + +#define MV_DEBUG + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* Default Attributes array */ +MV_TARGET_ATTRIB mvTargetDefaultsArray[] = TARGETS_DEF_ARRAY; +extern MV_TARGET sampleAtResetTargetArray[]; +/* Dram\AHBToMbus\PEX share regsiter */ + +#define CTRL_DEC_BASE_OFFS 16 +#define CTRL_DEC_BASE_MASK (0xffff << CTRL_DEC_BASE_OFFS) +#define CTRL_DEC_BASE_ALIGNMENT 0x10000 + +#define CTRL_DEC_SIZE_OFFS 16 +#define CTRL_DEC_SIZE_MASK (0xffff << CTRL_DEC_SIZE_OFFS) +#define CTRL_DEC_SIZE_ALIGNMENT 0x10000 + +#define CTRL_DEC_WIN_EN BIT0 + + + +/******************************************************************************* +* mvCtrlAddrDecToReg - Get address decode register format values +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, MV_DEC_REGS *pAddrDecRegs) +{ + + MV_U32 baseToReg=0 , sizeToReg=0; + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->baseLow & CTRL_DEC_BASE_MASK; + + /* Write to address decode Base Address Register */ + pAddrDecRegs->baseReg &= ~CTRL_DEC_BASE_MASK; + pAddrDecRegs->baseReg |= baseToReg; + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->size, CTRL_DEC_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + return MV_BAD_PARAM; + } + + /* set size */ + pAddrDecRegs->sizeReg &= ~CTRL_DEC_SIZE_MASK; + pAddrDecRegs->sizeReg |= (sizeToReg << CTRL_DEC_SIZE_OFFS); + + + return MV_OK; + +} + +/******************************************************************************* +* mvCtrlRegToAddrDec - Extract address decode struct from registers. +* +* DESCRIPTION: +* This function extract address decode struct from address decode +* registers given as parameters. +* +* INPUT: +* pAddrDecRegs - Address decode register struct. +* +* OUTPUT: +* pAddrDecWin - Target window data structure. +* +* RETURN: +* MV_BAD_PARAM if address decode registers data is invalid. +* +*******************************************************************************/ +MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 sizeRegVal; + + sizeRegVal = (pAddrDecRegs->sizeReg & CTRL_DEC_SIZE_MASK) >> + CTRL_DEC_SIZE_OFFS; + + pAddrDecWin->size = ctrlRegToSize(sizeRegVal, CTRL_DEC_SIZE_ALIGNMENT); + + + /* Extract base address */ + /* Base register [31:16] ==> baseLow[31:16] */ + pAddrDecWin->baseLow = pAddrDecRegs->baseReg & CTRL_DEC_BASE_MASK; + + pAddrDecWin->baseHigh = 0; + + return MV_OK; + +} + +/******************************************************************************* +* mvCtrlAttribGet - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ + +MV_STATUS mvCtrlAttribGet(MV_TARGET target, + MV_TARGET_ATTRIB *targetAttrib) +{ + + targetAttrib->attrib = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].attrib; + targetAttrib->targetId = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].targetId; + + return MV_OK; + +} + +/******************************************************************************* +* mvCtrlGetAttrib - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib) +{ + MV_TARGET target; + MV_TARGET x; + for (target = SDRAM_CS0; target < MAX_TARGETS ; target ++) + { + x = MV_CHANGE_BOOT_CS(target); + if ((mvTargetDefaultsArray[x].attrib == targetAttrib->attrib) && + (mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(target)].targetId == targetAttrib->targetId)) + { + /* found it */ + break; + } + } + + return target; +} + +MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, + MV_DEC_WIN_PARAMS *pWinParam) +{ + MV_U32 baseToReg=0, sizeToReg=0; + + /* BaseLow[31:16] => base register [31:16] */ + baseToReg = pAddrDecWin->addrWin.baseLow & CTRL_DEC_BASE_MASK; + + /* Write to address decode Base Address Register */ + pWinParam->baseAddr &= ~CTRL_DEC_BASE_MASK; + pWinParam->baseAddr |= baseToReg; + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, CTRL_DEC_SIZE_ALIGNMENT); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvCtrlAddrDecToParams: ERR. ctrlSizeToReg failed.\n"); + return MV_BAD_PARAM; + } + pWinParam->size = sizeToReg; + + pWinParam->attrib = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].attrib; + pWinParam->targetId = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].targetId; + + return MV_OK; +} + +MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam, + MV_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttrib; + + pAddrDecWin->addrWin.baseLow = pWinParam->baseAddr; + + /* Upper 32bit address base is supported under PCI High Address remap */ + pAddrDecWin->addrWin.baseHigh = 0; + + /* Prepare sizeReg to ctrlRegToSize function */ + pAddrDecWin->addrWin.size = ctrlRegToSize(pWinParam->size, CTRL_DEC_SIZE_ALIGNMENT); + + if (-1 == pAddrDecWin->addrWin.size) + { + DB(mvOsPrintf("mvCtrlParamsToAddrDec: ERR. ctrlRegToSize failed.\n")); + return MV_BAD_PARAM; + } + targetAttrib.targetId = pWinParam->targetId; + targetAttrib.attrib = pWinParam->attrib; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + return MV_OK; +} + + + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.h new file mode 100644 index 0000000..54be842 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAddrDec.h @@ -0,0 +1,201 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCtrlEnvAddrDech +#define __INCmvCtrlEnvAddrDech + +/* includes */ +#include "mvCtrlEnvLib.h" + +/* defines */ +/* DUnit attributes */ +#define ATMWCR_WIN_DUNIT_CS0_OFFS 0 +#define ATMWCR_WIN_DUNIT_CS0_MASK BIT0 +#define ATMWCR_WIN_DUNIT_CS0_REQ (0 << ATMWCR_WIN_DUNIT_CS0_OFFS) + +#define ATMWCR_WIN_DUNIT_CS1_OFFS 1 +#define ATMWCR_WIN_DUNIT_CS1_MASK BIT1 +#define ATMWCR_WIN_DUNIT_CS1_REQ (0 << ATMWCR_WIN_DUNIT_CS1_OFFS) + +#define ATMWCR_WIN_DUNIT_CS2_OFFS 2 +#define ATMWCR_WIN_DUNIT_CS2_MASK BIT2 +#define ATMWCR_WIN_DUNIT_CS2_REQ (0 << ATMWCR_WIN_DUNIT_CS2_OFFS) + +#define ATMWCR_WIN_DUNIT_CS3_OFFS 3 +#define ATMWCR_WIN_DUNIT_CS3_MASK BIT3 +#define ATMWCR_WIN_DUNIT_CS3_REQ (0 << ATMWCR_WIN_DUNIT_CS3_OFFS) + +/* RUnit (Device) attributes */ +#define ATMWCR_WIN_RUNIT_DEVCS0_OFFS 0 +#define ATMWCR_WIN_RUNIT_DEVCS0_MASK BIT0 +#define ATMWCR_WIN_RUNIT_DEVCS0_REQ (0 << ATMWCR_WIN_RUNIT_DEVCS0_OFFS) + +#define ATMWCR_WIN_RUNIT_DEVCS1_OFFS 1 +#define ATMWCR_WIN_RUNIT_DEVCS1_MASK BIT1 +#define ATMWCR_WIN_RUNIT_DEVCS1_REQ (0 << ATMWCR_WIN_RUNIT_DEVCS1_OFFS) + +#define ATMWCR_WIN_RUNIT_DEVCS2_OFFS 2 +#define ATMWCR_WIN_RUNIT_DEVCS2_MASK BIT2 +#define ATMWCR_WIN_RUNIT_DEVCS2_REQ (0 << ATMWCR_WIN_RUNIT_DEVCS2_OFFS) + +#define ATMWCR_WIN_RUNIT_BOOTCS_OFFS 4 +#define ATMWCR_WIN_RUNIT_BOOTCS_MASK BIT4 +#define ATMWCR_WIN_RUNIT_BOOTCS_REQ (0 << ATMWCR_WIN_RUNIT_BOOTCS_OFFS) + +/* LMaster (PCI) attributes */ +#define ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS 0 +#define ATMWCR_WIN_LUNIT_BYTE_SWP_MASK BIT0 +#define ATMWCR_WIN_LUNIT_BYTE_SWP (0 << ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS) +#define ATMWCR_WIN_LUNIT_BYTE_NO_SWP (1 << ATMWCR_WIN_LUNIT_BYTE_SWP_OFFS) + + +#define ATMWCR_WIN_LUNIT_WORD_SWP_OFFS 1 +#define ATMWCR_WIN_LUNIT_WORD_SWP_MASK BIT1 +#define ATMWCR_WIN_LUNIT_WORD_SWP (0 << ATMWCR_WIN_LUNIT_WORD_SWP_OFFS) +#define ATMWCR_WIN_LUNIT_WORD_NO_SWP (1 << ATMWCR_WIN_LUNIT_WORD_SWP_OFFS) + +#define ATMWCR_WIN_LUNIT_NO_SNOOP BIT2 + +#define ATMWCR_WIN_LUNIT_TYPE_OFFS 3 +#define ATMWCR_WIN_LUNIT_TYPE_MASK BIT3 +#define ATMWCR_WIN_LUNIT_TYPE_IO (0 << ATMWCR_WIN_LUNIT_TYPE_OFFS) +#define ATMWCR_WIN_LUNIT_TYPE_MEM (1 << ATMWCR_WIN_LUNIT_TYPE_OFFS) + +#define ATMWCR_WIN_LUNIT_FORCE64_OFFS 4 +#define ATMWCR_WIN_LUNIT_FORCE64_MASK BIT4 +#define ATMWCR_WIN_LUNIT_FORCE64 (0 << ATMWCR_WIN_LUNIT_FORCE64_OFFS) + +#define ATMWCR_WIN_LUNIT_ORDERING_OFFS 6 +#define ATMWCR_WIN_LUNIT_ORDERING_MASK BIT6 +#define ATMWCR_WIN_LUNIT_ORDERING (1 << ATMWCR_WIN_LUNIT_FORCE64_OFFS) + +/* PEX Attributes */ +#define ATMWCR_WIN_PEX_TYPE_OFFS 3 +#define ATMWCR_WIN_PEX_TYPE_MASK BIT3 +#define ATMWCR_WIN_PEX_TYPE_IO (0 << ATMWCR_WIN_PEX_TYPE_OFFS) +#define ATMWCR_WIN_PEX_TYPE_MEM (1 << ATMWCR_WIN_PEX_TYPE_OFFS) + +/* typedefs */ + +/* Unsupported attributes for address decode: */ +/* 2) PCI0/1_REQ64n control */ + +typedef struct _mvDecRegs +{ + MV_U32 baseReg; + MV_U32 baseRegHigh; + MV_U32 sizeReg; + +}MV_DEC_REGS; + +typedef struct _mvTargetAttrib +{ + MV_U8 attrib; /* chip select attributes */ + MV_TARGET_ID targetId; /* Target Id of this MV_TARGET */ + +}MV_TARGET_ATTRIB; + + +/* This structure describes address decode window */ +typedef struct _mvDecWin +{ + MV_TARGET target; /* Target for addr decode window */ + MV_ADDR_WIN addrWin; /* Address window of target */ + MV_BOOL enable; /* Window enable/disable */ +}MV_DEC_WIN; + +typedef struct _mvDecWinParams +{ + MV_TARGET_ID targetId; /* Target ID field */ + MV_U8 attrib; /* Attribute field */ + MV_U32 baseAddr; /* Base address in register format */ + MV_U32 size; /* Size in register format */ +}MV_DEC_WIN_PARAMS; + + +/* mvCtrlEnvAddrDec API list */ + +MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, + MV_DEC_REGS *pAddrDecRegs); + +MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs, + MV_ADDR_WIN *pAddrDecWin); + +MV_STATUS mvCtrlAttribGet(MV_TARGET target, + MV_TARGET_ATTRIB *targetAttrib); + +MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib); + + +MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin, + MV_DEC_WIN_PARAMS *pWinParam); + +MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam, + MV_DEC_WIN *pAddrDecWin); + + + + +#endif /* __INCmvCtrlEnvAddrDech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAsm.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAsm.h new file mode 100644 index 0000000..4a04374 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvAsm.h @@ -0,0 +1,217 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCtrlEnvAsmh +#define __INCmvCtrlEnvAsmh +#include "pci/mvPciRegs.h" + +/* Read device ID into toReg bits 15:0 from 0xd0000000 */ +/* defines */ +#if defined(MV_88F5180N) +#define MV_DV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + ldr toReg, =MV_5180_DEV_ID +#elif defined(MV_88F5082) +#define MV_DV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + ldr toReg, =MV_5082_DEV_ID +#else +#if defined(MV_INCLUDE_PEX) +#define MV_DV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + MV_DV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID));\ + mov toReg, toReg, LSR #PXDAVI_DEV_ID_OFFS /* toReg = toReg >> 16 */ + +#elif defined(MV_INCLUDE_PCI) +#define MV_DV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + /* Read bus number */ \ + MV_DV_REG_READ_ASM(toReg, tmpReg, PCI_P2P_CONFIG_REG(0));\ + mov tmpReg, toReg; \ + and toReg, toReg, #PPCR_BUS_NUM_MASK; \ + /* Read dev number */ \ + and tmpReg, tmpReg, #PPCR_DEV_NUM_MASK; \ + orr toReg, tmpReg, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */\ + /* Set PCI config enable BIT31 */ \ + orr toReg, toReg, #PCAR_CONFIG_EN; \ + /* Write the address to the PCI configuration address register */\ + MV_DV_REG_WRITE_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0));\ + /* In order to let the PCI controller absorbed the address of the read */\ + /* transaction we perform a validity check that the address was written */\ + MV_DV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0)); \ + /* Read the Data returned in the PCI Data register */\ + MV_DV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_DATA_REG(0)); \ + mov toReg, toReg, LSR #PDVIR_DEV_ID_OFFS /* toReg = toReg >> 16 */ +#else + #error "No Way to get Device ID" +#endif /* MV_INCLUDE_PEX */ +#endif /* MV_88F5180N */ + +/* Read device ID into toReg bits 15:0 from 0xf1000000*/ + +#if defined(MV_88F5180N) +#define MV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + ldr toReg, =MV_5180_DEV_ID +#elif defined(MV_88F5082) +#define MV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + ldr toReg, =MV_5082_DEV_ID +#else +#if defined(MV_INCLUDE_PEX) +#define MV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + MV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID));\ + mov toReg, toReg, LSR #PXDAVI_DEV_ID_OFFS /* toReg = toReg >> 16 */ + +#elif defined(MV_INCLUDE_PCI) +#define MV_CTRL_MODEL_GET_ASM(toReg, tmpReg) \ + /* Read bus number */ \ + MV_REG_READ_ASM(toReg, tmpReg, PCI_P2P_CONFIG_REG(0));\ + mov tmpReg, toReg; \ + and toReg, toReg, #PPCR_BUS_NUM_MASK; \ + /* Read dev number */ \ + and tmpReg, tmpReg, #PPCR_DEV_NUM_MASK; \ + orr toReg, tmpReg, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */\ + /* Set PCI config enable BIT31 */ \ + orr toReg, toReg, #PCAR_CONFIG_EN; \ + /* Write the address to the PCI configuration address register */\ + MV_REG_WRITE_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0));\ + /* In order to let the PCI controller absorbed the address of the read */\ + /* transaction we perform a validity check that the address was written */\ + MV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0)); \ + /* Read the Data returned in the PCI Data register */\ + MV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_DATA_REG(0)); \ + mov toReg, toReg, LSR #PDVIR_DEV_ID_OFFS /* toReg = toReg >> 16 */ +#else + #error "No Way to get Device ID" +#endif /* MV_INCLUDE_PEX */ +#endif /* MV_88F5180N */ + + +/* Read Revision into toReg bits 7:0 0xd0000000*/ +#if defined(MV_88F5180N) +#define MV_DV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + ldr toReg, =MV_5180N_B1_REV +#else +#if defined(MV_INCLUDE_PEX) +#define MV_DV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + /* Read device revision */ \ + MV_DV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_CLASS_CODE_AND_REVISION_ID));\ + and toReg, toReg, #PXCCARI_REVID_MASK /* Mask for calss ID */ +#elif defined(MV_INCLUDE_PCI) +#define MV_DV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + /* Read bus number */ \ + MV_DV_REG_READ_ASM(toReg, tmpReg, PCI_P2P_CONFIG_REG(0));\ + mov tmpReg, toReg; \ + and toReg, toReg, #PPCR_BUS_NUM_MASK; \ + /* Read dev number */ \ + and tmpReg, tmpReg, #PPCR_DEV_NUM_MASK; \ + orr toReg, tmpReg, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */\ + /* Set PCI config enable BIT31 */ \ + orr toReg, toReg, #PCAR_CONFIG_EN; \ + orr toReg, toReg, #(PCI_CLASS_CODE_AND_REVISION_ID);\ + /* Write the address to the PCI configuration address register */\ + MV_DV_REG_WRITE_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0));\ + /* In order to let the PCI controller absorbed the address of the read */\ + /* transaction we perform a validity check that the address was written */\ + MV_DV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0));\ + /* Read the Data returned in the PCI Data register */\ + MV_DV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_DATA_REG(0));\ + and toReg, toReg, #PCCRIR_REVID_MASK +#else + #error "No Way to get Revision ID" +#endif /* MV_INCLUDE_PEX */ +#endif /* MV_88F5180N */ + +/* Read Revision into toReg bits 7:0 0xf1000000*/ +#if defined(MV_88F5180N) +#define MV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + ldr toReg, =MV_5180N_B1_REV +#else +#if defined(MV_INCLUDE_PEX) +#define MV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + /* Read device revision */ \ + MV_REG_READ_ASM(toReg, tmpReg, PEX_CFG_DIRECT_ACCESS(0,PEX_CLASS_CODE_AND_REVISION_ID));\ + and toReg, toReg, #PXCCARI_REVID_MASK /* Mask for calss ID */ +#elif defined(MV_INCLUDE_PCI) +#define MV_CTRL_REV_GET_ASM(toReg, tmpReg) \ + /* Read bus number */ \ + MV_REG_READ_ASM(toReg, tmpReg, PCI_P2P_CONFIG_REG(0));\ + mov tmpReg, toReg; \ + and toReg, toReg, #PPCR_BUS_NUM_MASK; \ + /* Read dev number */ \ + and tmpReg, tmpReg, #PPCR_DEV_NUM_MASK; \ + orr toReg, tmpReg, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */\ + /* Set PCI config enable BIT31 */ \ + orr toReg, toReg, #PCAR_CONFIG_EN; \ + orr toReg, toReg, #(PCI_CLASS_CODE_AND_REVISION_ID);\ + /* Write the address to the PCI configuration address register */\ + MV_REG_WRITE_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0));\ + /* In order to let the PCI controller absorbed the address of the read */\ + /* transaction we perform a validity check that the address was written */\ + MV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_ADDR_REG(0));\ + /* Read the Data returned in the PCI Data register */\ + MV_REG_READ_ASM(toReg, tmpReg, PCI_CONFIG_DATA_REG(0));\ + and toReg, toReg, #PCCRIR_REVID_MASK +#else + #error "No Way to get Revision ID" +#endif /* MV_INCLUDE_PEX */ +#endif /* MV_88F5180N */ + +#endif /* __INCmvCtrlEnvAsmh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.c new file mode 100644 index 0000000..9cc4fa5 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.c @@ -0,0 +1,1266 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "mvCommon.h" +#include "mvCtrlEnvLib.h" +#include "mvCtrlEnvPadCalibration.h" +#include "ctrlEnv/sys/mvCpuIf.h" + +#if defined(MV_INCLUDE_PCI) || defined(MV_INCLUDE_PEX) +#include "pci-if/mvPciIf.h" +#endif + +#if defined(MV_INCLUDE_PCI) +#include "pci/mvPci.h" +#include "ctrlEnv/sys/mvSysPci.h" +#endif + +#if defined(MV_INCLUDE_PEX) +#include "ctrlEnv/sys/mvSysPex.h" +#endif + +#if defined(MV_INCLUDE_IDMA) +#include "ctrlEnv/sys/mvSysIdma.h" +#endif + +#if defined(MV_INCLUDE_GIG_ETH) +#include "ctrlEnv/sys/mvSysGbe.h" +#endif + +#if defined(MV_INCLUDE_XOR) +#include "ctrlEnv/sys/mvSysXor.h" +#endif + +#if defined (MV_INCLUDE_INTEG_MFLASH) +#include "mflash/mvPMFlashSpec.h" +#endif + +#if defined(MV_INCLUDE_SATA) +#include "ctrlEnv/sys/mvSysSata.h" +#endif + +#if defined(MV_INCLUDE_USB) +#include "ctrlEnv/sys/mvSysUsb.h" +#endif + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* Global paramters initial value '-1' to indicate they are uninitialized. */ +/* In case of data section is located in ROM, this value will not be able */ +/* to change. */ +MV_U32 ctrlDevModel = -1; +MV_U32 ctrlDevRev = -1; + + +/******************************************************************************* +* mv64xxxInit - Initialize Marvell controller environment. +* +* DESCRIPTION: +* This function get environment information and initialize controller +* internal/external environment. For example +* 1) MPP settings according to board MPP macros. +* NOTE: It is the user responsibility to shut down all DMA channels +* in device and disable controller sub units interrupts during +* boot process. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvCtrlEnvInit(MV_VOID) +{ +#if defined(MV_88F6183L) + /* Updating initial value of power control register for 6183L according to FS*/ + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, (BIT0 | BIT3 | BIT4)); +#endif + MV_U32 mppGroup; + /* Read MPP group from board level and assign to MPP register */ + for (mppGroup = 0; mppGroup < MV_MPP_MAX_GROUP; mppGroup++) + { + MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mvBoardMppGet(mppGroup)); + } + +#if defined(MV_88F6183) + /* Add pad calibration for 6183 */ + mvCtrlEnvPadCalibrationInit(); +#endif + + return MV_OK; +} + +/******************************************************************************* +* mvCtrlMppRegGet - return reg address of mpp group +* +* DESCRIPTION: +* +* INPUT: +* mppGroup - MPP group. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_U32 - Register address. +* +*******************************************************************************/ +MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup) +{ + MV_U32 ret; + + switch(mppGroup){ + case (0): ret = MPP_CONTROL_REG0; + break; + case (1): ret = MPP_CONTROL_REG1; + break; +#if !defined(MV_88F6082) + case (2): ret = MPP_CONTROL_REG2; + break; +#if defined(MV_88F6183) || defined(MV_88F6183L) + case (3): ret = MPP_CONTROL_REG3; + break; +#else + case (3): ret = DEV_MULTI_CONTROL; + break; +#endif +#endif + default: ret = MPP_CONTROL_REG0; + break; + } + return ret; +} +#if defined(MV_INCLUDE_PCI) +/******************************************************************************* +* mvCtrlPciMaxIfGet - Get Marvell controller number of PCI interfaces. +* +* DESCRIPTION: +* This function returns Marvell controller number of PCI interfaces. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of PCI interfaces. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlPciMaxIfGet(MV_VOID) +{ + + return MV_PCI_MAX_IF; +} +#endif + +#if defined(MV_INCLUDE_PCI) || defined(MV_INCLUDE_PEX) +/******************************************************************************* +* mvCtrlPciIfiMaxIfGet - Get Marvell controller number of PCI interfaces. +* +* DESCRIPTION: +* This function returns Marvell controller number of PCI interfaces. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of PCI interfaces. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlPciIfMaxIfGet(MV_VOID) +{ + + return MV_PCI_IF_MAX_IF; +} +#endif + +#if defined(MV_INCLUDE_PEX) +/******************************************************************************* +* mvCtrlPexMaxIfGet - Get Marvell controller number of PEX interfaces. +* +* DESCRIPTION: +* This function returns Marvell controller number of PEX interfaces. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of PEX interfaces. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlPexMaxIfGet(MV_VOID) +{ + + return MV_PEX_MAX_IF; +} +#endif + +#if defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) +/******************************************************************************* +* mvCtrlEthMaxPortGet - Get Marvell controller number of etherent ports. +* +* DESCRIPTION: +* This function returns Marvell controller number of etherent port. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of etherent port. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlEthMaxPortGet(MV_VOID) +{ + return MV_ETH_MAX_PORTS; +} +#endif + +#if defined(MV_INCLUDE_IDMA) +/******************************************************************************* +* mvCtrlIdmaMaxChanGet - Get Marvell controller number of IDMA channels. +* +* DESCRIPTION: +* This function returns Marvell controller number of IDMA channels. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Marvell controller number of IDMA channels. If controller +* ID is undefined the function returns '0'. +* +*******************************************************************************/ +MV_U32 mvCtrlIdmaMaxChanGet(MV_VOID) +{ + return MV_IDMA_MAX_CHAN; +} +#endif + +#if defined(MV_INCLUDE_USB) +/******************************************************************************* +* mvCtrlUsbHostMaxGet - Get number of Marvell Usb controllers +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* returns number of Marvell USB controllers. +* +*******************************************************************************/ +MV_U32 mvCtrlUsbMaxGet(void) +{ + return MV_USB_MAX; + +} +#endif + + +#if defined(MV_INCLUDE_NAND) + +/******************************************************************************* +* mvCtrlNandSupport - Return if this controller has integrated NAND flash support +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if NAND is supported and MV_FALSE otherwise +* +*******************************************************************************/ + +MV_U32 mvCtrlNandSupport(MV_VOID) +{ +#if defined(MV_88F5181) + if (mvCtrlModelGet() == MV_5281_DEV_ID) + { + return MV_NAND_MAX; + } + else + { + return 0; + } +#else + return MV_NAND_MAX; +#endif +} +#endif + +/******************************************************************************* +* mvCtrlModelGet - Get Marvell controller device model (Id) +* +* DESCRIPTION: +* This function returns 16bit describing the device model (ID) as defined +* in PCI Device and Vendor ID configuration register offset 0x0. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 16bit desscribing Marvell controller ID +* +*******************************************************************************/ +MV_U16 mvCtrlModelGet(MV_VOID) +{ +#if defined(MV_88F5180N) + return MV_5180_DEV_ID; +#elif defined(MV_88F5082) + return MV_5082_DEV_ID; +#else +#if defined(MV_INCLUDE_PEX) + MV_U32 devId; + +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + /* Check pex power state */ + MV_U32 pexPower; + pexPower = mvCtrlPwrClckGet(PEX_UNIT_ID,0); + if (pexPower == MV_FALSE) + { + mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_TRUE); + mvPexPowerUp(0); + } +#endif + + devId = ((MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0,PCI_DEVICE_AND_VENDOR_ID)) + & PDVIR_DEV_ID_MASK) >> PDVIR_DEV_ID_OFFS); + +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + /* Return to power off state */ + if (pexPower == MV_FALSE) + { + mvPexPowerDown(0); + mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_FALSE); + } +#endif + + return devId; + +#elif defined(MV_INCLUDE_PCI) + MV_U32 pciData = 0; + MV_U32 dev = mvPciIfLocalDevNumGet(0); + MV_U32 bus = mvPciIfLocalBusNumGet(0); + + pciData = mvPciIfConfigRead(0, bus, dev, 0, PCI_DEVICE_AND_VENDOR_ID); + + return ((pciData & PDVIR_DEV_ID_MASK) >> PDVIR_DEV_ID_OFFS); +#else + #error "No Way to get Device ID" +#endif +#endif /* MV_88F5082 */ +} +/******************************************************************************* +* mvCtrlRevGet - Get Marvell controller device revision number +* +* DESCRIPTION: +* This function returns 8bit describing the device revision as defined +* in PCI Express Class Code and Revision ID Register. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 8bit desscribing Marvell controller revision number +* +*******************************************************************************/ +MV_U8 mvCtrlRevGet(MV_VOID) +{ + MV_U8 revNum; +#if defined(MV_INCLUDE_PEX) +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + /* Check pex power state */ + MV_U32 pexPower; + pexPower = mvCtrlPwrClckGet(PEX_UNIT_ID,0); + if (pexPower == MV_FALSE) + mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_TRUE); +#endif + revNum = (MV_U8)MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0,PCI_CLASS_CODE_AND_REVISION_ID)); +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) + /* Return to power off state */ + if (pexPower == MV_FALSE) + mvCtrlPwrClckSet(PEX_UNIT_ID, 0, MV_FALSE); +#endif +#elif defined(MV_INCLUDE_PCI) + MV_U32 dev = mvPciIfLocalDevNumGet(0); + MV_U32 bus = mvPciIfLocalBusNumGet(0); + + revNum = mvPciIfConfigRead(0, bus, dev, 0, PCI_CLASS_CODE_AND_REVISION_ID); +#endif +#if defined(MV_INCLUDE_PEX) || defined(MV_INCLUDE_PCI) + return ((revNum & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS); +#else + #error "No Way to get Revision ID" +#endif +} + +/******************************************************************************* +* mvCtrlNameGet - Get Marvell controller name +* +* DESCRIPTION: +* This function returns a string describing the device model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain device name string. Minimum size 30 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ +MV_STATUS mvCtrlNameGet(char *pNameBuff) +{ + mvOsSPrintf (pNameBuff, "%s%x Rev %d", SOC_NAME_PREFIX, + mvCtrlModelGet(), mvCtrlRevGet()); + + return MV_OK; +} + +/******************************************************************************* +* mvCtrlModelRevGet - Get Controller Model (Device ID) and Revision +* +* DESCRIPTION: +* This function returns 32bit value describing both Device ID and Revision +* as defined in PCI Express Device and Vendor ID Register and device revision +* as defined in PCI Express Class Code and Revision ID Register. + +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing both controller device ID and revision number +* +*******************************************************************************/ +MV_U32 mvCtrlModelRevGet(MV_VOID) +{ + return ((mvCtrlModelGet() << 16) | mvCtrlRevGet()); +} + +/******************************************************************************* +* mvCtrlNameGet - Get Marvell controller name +* +* DESCRIPTION: +* This function returns a string describing the device model and revision. +* +* INPUT: +* None. +* +* OUTPUT: +* pNameBuff - Buffer to contain device name string. Minimum size 30 chars. +* +* RETURN: +* +* MV_ERROR if informantion can not be read. +*******************************************************************************/ + +MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff) +{ + + switch (mvCtrlModelRevGet()) + { + case MV_5181_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5181_A0_NAME); + break; + case MV_5181_A1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5181_A1_NAME); + break; + case MV_5181_B0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5181_B0_NAME); + break; + case MV_5181_B1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5181_B1_NAME); + break; + case MV_5281_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5281_A0_NAME); + break; + case MV_5281_B0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5281_B0_NAME); + break; + case MV_5281_C0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5281_C0_NAME); + break; + case MV_5281_C1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5281_C1_NAME); + break; + case MV_5281_D0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5281_D0_NAME); + break; + case MV_5281_D1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5281_D1_NAME); + break; + case MV_5281_D2_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5281_D2_NAME); + break; + case MV_5082_A2_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5082_A2_NAME); + break; + case MV_5182_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5182_A0_NAME); + break; + case MV_5182_A1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5182_A1_NAME); + break; + case MV_5182_A2_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5182_A2_NAME); + break; + case MV_5181L_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5181L_A0_NAME); + break; + case MV_5181L_A1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_5181L_A1_NAME); + break; + case MV_8660_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_8660_A0_NAME); + break; + case MV_8660_A1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_8660_A1_NAME); + break; + case MV_1281_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_1281_A0_NAME); + break; + case MV_6183_A0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6183_A0_NAME); + break; + case MV_6183_1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6183_1_NAME); + break; + case MV_6183_A1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6183_A1_NAME); + break; + case MV_6183_B0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6183_B0_NAME); + break; + case MV_6183L_B0_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6183L_B0_NAME); + break; + case MV_6082_A0_ID: + if( (MV_REG_READ(0x10018) & BIT3) == 0) + mvOsSPrintf (pNameBuff, "%s",MV_6082_A0_NAME); + else + mvOsSPrintf (pNameBuff, "%s",MV_6082L_A0_NAME); + break; + case MV_6082_A1_ID: + mvOsSPrintf (pNameBuff, "%s",MV_6082_A1_NAME); + break; + default: + mvCtrlNameGet(pNameBuff); + break; + } + + + return MV_OK; +} + +/******************************************************************************* +* ctrlWinOverlapTest - Test address windows for overlaping. +* +* DESCRIPTION: +* This function checks the given two address windows for overlaping. +* +* INPUT: +* pAddrWin1 - Address window 1. +* pAddrWin2 - Address window 2. +* +* OUTPUT: +* None. +* +* RETURN: +* +* MV_TRUE if address window overlaps, MV_FALSE otherwise. +*******************************************************************************/ +MV_STATUS ctrlWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2) +{ + MV_U32 winBase1, winBase2; + MV_U32 winTop1, winTop2; + + /* check if we have overflow than 4G*/ + if (((0xffffffff - pAddrWin1->baseLow) < pAddrWin1->size-1)|| + ((0xffffffff - pAddrWin2->baseLow) < pAddrWin2->size-1)) + { + return MV_TRUE; + } + + winBase1 = pAddrWin1->baseLow; + winBase2 = pAddrWin2->baseLow; + winTop1 = winBase1 + pAddrWin1->size-1; + winTop2 = winBase2 + pAddrWin2->size-1; + + + if (((winBase1 <= winTop2 ) && ( winTop2 <= winTop1)) || + ((winBase1 <= winBase2) && (winBase2 <= winTop1))) + { + return MV_TRUE; + } + else + { + return MV_FALSE; + } +} + +/******************************************************************************* +* ctrlWinWithinWinTest - Test address windows for overlaping. +* +* DESCRIPTION: +* This function checks the given win1 boundries is within +* win2 boundries. +* +* INPUT: +* pAddrWin1 - Address window 1. +* pAddrWin2 - Address window 2. +* +* OUTPUT: +* None. +* +* RETURN: +* +* MV_TRUE if found win1 inside win2, MV_FALSE otherwise. +*******************************************************************************/ +MV_STATUS ctrlWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2) +{ + MV_U32 winBase1, winBase2; + MV_U32 winTop1, winTop2; + + winBase1 = pAddrWin1->baseLow; + winBase2 = pAddrWin2->baseLow; + winTop1 = winBase1 + pAddrWin1->size -1; + winTop2 = winBase2 + pAddrWin2->size -1; + + if (((winBase1 >= winBase2 ) && ( winBase1 <= winTop2)) || + ((winTop1 >= winBase2) && (winTop1 <= winTop2))) + { + return MV_TRUE; + } + else + { + return MV_FALSE; + } +} + +static const char* cntrlName[] = TARGETS_NAME_ARRAY; + +/******************************************************************************* +* mvCtrlTargetNameGet - Get Marvell controller target name +* +* DESCRIPTION: +* This function convert the trget enumeration to string. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* Target name (const MV_8 *) +*******************************************************************************/ +const MV_8* mvCtrlTargetNameGet( MV_TARGET target ) +{ + + if (target >= MAX_TARGETS) + { + return "target unknown"; + } + + return cntrlName[target]; +} + +/******************************************************************************* +* mvCtrlAddrDecShow - Print the Controller units address decode map. +* +* DESCRIPTION: +* This function the Controller units address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvCtrlAddrDecShow(MV_VOID) +{ + mvCpuIfAddDecShow(); + mvAhbToMbusAddDecShow(); +#if defined(MV_INCLUDE_PEX) + mvPexAddrDecShow(); +#endif +#if defined(MV_INCLUDE_PCI) + mvPciAddrDecShow(); +#endif +#if defined(MV_INCLUDE_IDMA) + mvDmaAddrDecShow(); +#endif +#if defined(MV_INCLUDE_USB) + mvUsbAddrDecShow(); +#endif +#if defined(MV_INCLUDE_GIG_ETH) + mvEthAddrDecShow(); +#endif +#if defined(MV_INCLUDE_XOR) + mvXorAddrDecShow(); +#endif +#if defined(MV_INCLUDE_SATA) + mvSataAddrDecShow(); +#endif +} + +/******************************************************************************* +* ctrlSizeToReg - Extract size value for register assignment. +* +* DESCRIPTION: +* Address decode size parameter must be programed from LSB to MSB as +* sequence of 1's followed by sequence of 0's. The number of 1's +* specifies the size of the window in 64 KB granularity (e.g. a +* value of 0x00ff specifies 256x64k = 16 MB). +* This function extract the size value from the size parameter according +* to given aligment paramter. For example for size 0x1000000 (16MB) and +* aligment 0x10000 (64KB) the function will return 0x00FF. +* +* INPUT: +* size - Size. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size register value correspond to size parameter. +* If value is '-1' size parameter or aligment are invalid. +*******************************************************************************/ +MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment) +{ + MV_U32 retVal; + + /* Check size parameter alignment */ + if ((0 == size) || (MV_IS_NOT_ALIGN(size, alignment))) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Size is zero or not aligned.\n")); + return -1; + } + + /* Take out the "alignment" portion out of the size parameter */ + alignment--; /* Now the alignmet is a sequance of '1' (e.g. 0xffff) */ + /* and size is 0x1000000 (16MB) for example */ + while(alignment & 1) /* Check that alignmet LSB is set */ + { + size = (size >> 1); /* If LSB is set, move 'size' one bit to right */ + alignment = (alignment >> 1); + } + + /* If after the alignment first '0' was met we still have '1' in */ + /* it then aligment is invalid (not power of 2) */ + if (alignment) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", + (MV_U32)alignment)); + return -1; + } + + /* Now the size is shifted right according to aligment: 0x0100 */ + size--; /* Now the size is a sequance of '1': 0x00ff */ + + retVal = size ; + + /* Check that LSB to MSB is sequence of 1's followed by sequence of 0's */ + while(size & 1) /* Check that LSB is set */ + { + size = (size >> 1); /* If LSB is set, move one bit to the right */ + } + + if (size) /* Sequance of 1's is over. Check that we have no other 1's */ + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Size parameter 0x%x invalid.\n", + size)); + return -1; + } + + return retVal; + +} + +/******************************************************************************* +* ctrlRegToSize - Extract size value from register value. +* +* DESCRIPTION: +* This function extract a size value from the register size parameter +* according to given aligment paramter. For example for register size +* value 0xff and aligment 0x10000 the function will return 0x01000000. +* +* INPUT: +* regSize - Size as in register format. See ctrlSizeToReg. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size. +* If value is '-1' size parameter or aligment are invalid. +*******************************************************************************/ +MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment) +{ + MV_U32 temp; + + /* Check that LSB to MSB is sequence of 1's followed by sequence of 0's */ + temp = regSize; /* Now the size is a sequance of '1': 0x00ff */ + + while(temp & 1) /* Check that LSB is set */ + { + temp = (temp >> 1); /* If LSB is set, move one bit to the right */ + } + + if (temp) /* Sequance of 1's is over. Check that we have no other 1's */ + { + DB(mvOsPrintf("ctrlRegToSize: ERR. Size parameter 0x%x invalid.\n", + regSize)); + return -1; + } + + + /* Check that aligment is a power of two */ + temp = alignment - 1;/* Now the alignmet is a sequance of '1' (0xffff) */ + + while(temp & 1) /* Check that alignmet LSB is set */ + { + temp = (temp >> 1); /* If LSB is set, move 'size' one bit to right */ + } + + /* If after the 'temp' first '0' was met we still have '1' in 'temp' */ + /* then 'temp' is invalid (not power of 2) */ + if (temp) + { + DB(mvOsPrintf("ctrlSizeToReg: ERR. Alignment parameter 0x%x invalid.\n", + alignment)); + return -1; + } + + regSize++; /* Now the size is 0x0100 */ + + /* Add in the "alignment" portion to the register size parameter */ + alignment--; /* Now the alignmet is a sequance of '1' (e.g. 0xffff) */ + + while(alignment & 1) /* Check that alignmet LSB is set */ + { + regSize = (regSize << 1); /* LSB is set, move 'size' one bit left */ + alignment = (alignment >> 1); + } + + return regSize; +} + + +/******************************************************************************* +* ctrlSizeRegRoundUp - Round up given size +* +* DESCRIPTION: +* This function round up a given size to a size that fits the +* restrictions of size format given an aligment parameter. +* to given aligment paramter. For example for size parameter 0xa1000 and +* aligment 0x1000 the function will return 0xFF000. +* +* INPUT: +* size - Size. +* alignment - Size alignment. Note that alignment must be power of 2! +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit describing size value correspond to size in register. +*******************************************************************************/ +MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment) +{ + MV_U32 msbBit = 0; + MV_U32 retSize; + + /* Check if size parameter is already comply with restriction */ + if (!(-1 == ctrlSizeToReg(size, alignment))) + { + return size; + } + + while(size) + { + size = (size >> 1); + msbBit++; + } + + retSize = (1 << msbBit); + + if (retSize < alignment) + { + return alignment; + } + else + { + return retSize; + } +} + +#if defined(MV_INCLUDE_CLK_PWR_CNTRL) +/******************************************************************************* +* mvCtrlPwrClckSet - Set Power State for specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +*******************************************************************************/ +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable) +{ + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index)); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_GESTOPCLOCK_MASK(index)); + } + break; +#endif +#if defined(MV_INCLUDE_INTEG_SATA) + case SATA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SATASTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SATASTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SESTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_SESTOPCLOCK_MASK); + } + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if (enable == MV_FALSE) + { + MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_USBSTOPCLOCK_MASK); + } + else + { + MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_USBSTOPCLOCK_MASK); + } + break; +#endif + default: + + break; + + } +} + +/******************************************************************************* +* mvCtrlPwrClckGet - Get Power State of specific Unit +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +******************************************************************************/ +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index) +{ + MV_U32 reg = MV_REG_READ(POWER_MNG_CTRL_REG); + MV_BOOL state = MV_TRUE; + + switch (unitId) + { +#if defined(MV_INCLUDE_PEX) + case PEX_UNIT_ID: + if (reg & PMC_PEXSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + + break; +#endif +#if defined(MV_INCLUDE_GIG_ETH) + case ETH_GIG_UNIT_ID: + if (reg & PMC_GESTOPCLOCK_STOP(index)) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_SATA) + case SATA_UNIT_ID: + if (reg & PMC_SATASTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_CESA) + case CESA_UNIT_ID: + if (reg & PMC_SESTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif +#if defined(MV_INCLUDE_USB) + case USB_UNIT_ID: + if (reg & PMC_USBSTOPCLOCK_STOP) + { + state = MV_FALSE; + } + else state = MV_TRUE; + break; +#endif + default: + state = MV_TRUE; + break; + } + + + return state; +} +#else +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable) {return;} +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index) {return MV_TRUE;} +#endif /* #if defined(MV_INCLUDE_CLK_PWR_CNTRL) */ + +#if defined(MV_INCLUDE_INTEG_MFLASH) || defined (MV_INCLUDE_SPI) +/******************************************************************************* +* mvCtrlSpiBusModeSet - set the connectivity of the SPI bus +* +* DESCRIPTION: +* configure the MFlash controller to one of the 4 options +* +* INPUT: +* spiMode: SPI bus mode +* +* OUTPUT: +* None. +* +* RETURN: +* Success or Error code. +* +* +*******************************************************************************/ +MV_STATUS mvCtrlSpiBusModeSet(MV_SPI_CONN_MODE spiMode) +{ +#if defined (MV_INCLUDE_INTEG_MFLASH) && defined (MV_INCLUDE_SPI) + + /* Read and clear the 3 bits related to the SPI mode */ + MV_U32 reg = (MV_REG_READ(MV_PMFLASH_IF_CFG_REG) & ~MV_PMFLASH_SPI_BUS_MODE_MASK); + + switch (spiMode) + { + case MV_SPI_CONN_TO_MFLASH: + reg |= MV_PMFLASH_SPI_BUS_TO_MFLASH; + break; + + case MV_SPI_CONN_TO_EXT_FLASH: + reg |= MV_PMFLASH_SPI_BUS_TO_EXT_SFLASH; + break; + + case MV_SPI_CONN_MFLASH_TO_EXT_PROG: + reg |= MV_PMFLASH_SPI_BUS_EXT_PROGRAMER; + break; + + default: + return MV_BAD_PARAM; + } + + /* write back the register with the updated 3 bits */ + MV_REG_WRITE(MV_PMFLASH_IF_CFG_REG, reg); +#endif + return MV_OK; +} + +/******************************************************************************* +* mvCtrlSpiBusModeDetect - Detect the configuration of the SPI interface in the +* hardware. +* +* DESCRIPTION: +* Detect the SPI connectivity. Whether the SPI is used to access the +* internal MFlash or to access an external device. +* +* INPUT: +* None +* +* OUTPUT: +* None +* +* RETURN: +* SPI mode +* +* +*******************************************************************************/ +MV_SPI_CONN_MODE mvCtrlSpiBusModeDetect(void) +{ +#if defined (MV_INCLUDE_INTEG_MFLASH) && defined (MV_INCLUDE_SPI) + /* Read the regiater and mask away all bits except the 3 relevant bits */ + MV_U32 reg = (MV_REG_READ(MV_PMFLASH_IF_CFG_REG) & MV_PMFLASH_SPI_BUS_MODE_MASK); + + /* check all possibilities */ + switch (reg) + { + case MV_PMFLASH_SPI_BUS_TO_MFLASH: + return MV_SPI_CONN_TO_MFLASH; + + case MV_PMFLASH_SPI_BUS_TO_EXT_SFLASH: + return MV_SPI_CONN_TO_EXT_FLASH; + + case MV_PMFLASH_SPI_BUS_EXT_PROGRAMER: + return MV_SPI_CONN_MFLASH_TO_EXT_PROG; + } + + return MV_SPI_CONN_UNKNOWN; +#elif defined (MV_INCLUDE_SPI) + return MV_SPI_CONN_TO_EXT_FLASH; +#else + return MV_SPI_CONN_UNKNOWN; +#endif +} +#endif /* #if defined (MV_INCLUDE_INTEG_MFLASH) */ + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.h new file mode 100644 index 0000000..e931694 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvLib.h @@ -0,0 +1,182 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCtrlEnvLibh +#define __INCmvCtrlEnvLibh + +/* includes */ +#include "mvCommon.h" +#include "mvTypes.h" +#include "mvOs.h" +#include "boardEnv/mvBoardEnvLib.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + + +/* typedefs */ + +/* This enumerator describes the possible HW cache coherency policies the */ +/* controllers supports. */ +typedef enum _mvCachePolicy +{ + NO_COHERENCY, /* No HW cache coherency support */ + WT_COHERENCY, /* HW cache coherency supported in Write Through policy */ + WB_COHERENCY /* HW cache coherency supported in Write Back policy */ +}MV_CACHE_POLICY; + + +/* The swapping is referred to a 64-bit words (as this is the controller */ +/* internal data path width). This enumerator describes the possible */ +/* data swap types. Below is an example of the data 0x0011223344556677 */ +typedef enum _mvSwapType +{ + MV_BYTE_SWAP, /* Byte Swap 77 66 55 44 33 22 11 00 */ + MV_NO_SWAP, /* No swapping 00 11 22 33 44 55 66 77 */ + MV_BYTE_WORD_SWAP, /* Both byte and word swap 33 22 11 00 77 66 55 44 */ + MV_WORD_SWAP, /* Word swap 44 55 66 77 00 11 22 33 */ + SWAP_TYPE_MAX /* Delimiter for this enumerator */ +}MV_SWAP_TYPE; + +/* This structure describes access rights for Access protection windows */ +/* that can be found in IDMA, XOR, Ethernet and MPSC units. */ +/* Note that the permission enumerator coresponds to its register format. */ +/* For example, Read only premission is presented as "1" in register field. */ +typedef enum _mvAccessRights +{ + NO_ACCESS_ALLOWED = 0, /* No access allowed */ + READ_ONLY = 1, /* Read only permission */ + ACC_RESERVED = 2, /* Reserved access right */ + FULL_ACCESS = 3, /* Read and Write permission */ + MAX_ACC_RIGHTS +}MV_ACCESS_RIGHTS; + +#if (defined (MV_INCLUDE_SPI) || defined (MV_INCLUDE_INTEG_MFLASH)) +typedef enum +{ + MV_SPI_CONN_UNKNOWN, /* Unknown SPI mode */ + MV_SPI_CONN_TO_MFLASH, /* spi is connected to the integrated MFlash */ + MV_SPI_CONN_TO_EXT_FLASH, /* SPI is connected to an external serial flash */ + MV_SPI_CONN_MFLASH_TO_EXT_PROG, /* SPI pins are input to the MFlash - external SPI programmer is connected */ + MV_SPI_CONN_TRI_STATE /* SPI pins are tri-stated - external flash is managed externally */ +}MV_SPI_CONN_MODE; +#endif + + +/* mcspLib.h API list */ + +MV_STATUS mvCtrlEnvInit(MV_VOID); +MV_U32 mvCtrlMppRegGet(MV_U32 mppGroup); + +#if defined(MV_INCLUDE_PCI) +MV_U32 mvCtrlPciMaxIfGet(MV_VOID); +#else +#define mvCtrlPciMaxIfGet() (0) +#endif +#if defined(MV_INCLUDE_PEX) +MV_U32 mvCtrlPexMaxIfGet(MV_VOID); +#else +#define mvCtrlPexMaxIfGet() (0) +#endif +#if defined(MV_INCLUDE_PCI) || defined(MV_INCLUDE_PEX) +MV_U32 mvCtrlPciIfMaxIfGet(MV_VOID); +#else +#define mvCtrlPciIfMaxIfGet() (0) +#endif +#if defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) +MV_U32 mvCtrlEthMaxPortGet(MV_VOID); +#endif +#if defined(MV_INCLUDE_IDMA) +MV_U32 mvCtrlIdmaMaxChanGet(MV_VOID); +#endif +#if defined(MV_INCLUDE_USB) +MV_U32 mvCtrlUsbMaxGet(MV_VOID); +#endif +#if defined(MV_INCLUDE_NAND) +MV_U32 mvCtrlNandSupport(MV_VOID); +#endif +MV_U16 mvCtrlModelGet(MV_VOID); +MV_U8 mvCtrlRevGet(MV_VOID); +MV_STATUS mvCtrlNameGet(char *pNameBuff); +MV_U32 mvCtrlModelRevGet(MV_VOID); +MV_STATUS mvCtrlModelRevNameGet(char *pNameBuff); +MV_VOID mvCtrlAddrDecShow(MV_VOID); +const MV_8* mvCtrlTargetNameGet(MV_TARGET target); +MV_U32 ctrlSizeToReg(MV_U32 size, MV_U32 alignment); +MV_U32 ctrlRegToSize(MV_U32 regSize, MV_U32 alignment); +MV_U32 ctrlSizeRegRoundUp(MV_U32 size, MV_U32 alignment); +MV_STATUS ctrlWinOverlapTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2); +MV_STATUS ctrlWinWithinWinTest(MV_ADDR_WIN *pAddrWin1, MV_ADDR_WIN *pAddrWin2); + +#if (defined (MV_INCLUDE_SPI) || defined (MV_INCLUDE_INTEG_MFLASH)) +/* Set and Detect the SPI mode configuration inside the MFlash controller */ +MV_STATUS mvCtrlSpiBusModeSet (MV_SPI_CONN_MODE spiMode); +MV_SPI_CONN_MODE mvCtrlSpiBusModeDetect (void); +#endif + +MV_VOID mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable); +MV_BOOL mvCtrlPwrClckGet(MV_UNIT_ID unitId, MV_U32 index); + + +#endif /* __INCmvCtrlEnvLibh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.c new file mode 100644 index 0000000..5bb0245 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.c @@ -0,0 +1,463 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ddr1_2/mvDramIfRegs.h" +#include "eth/mvEth.h" +#include "ctrlEnv/mvCtrlEnvPadCalibration.h" + +#define ENABLE_ETHERNET_PAD_CALIBRATION +#undef DEBUG_ETHERNET_PAD_CALIBRATION + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +#define MAX_LockN 31 +#define R_NA 0 + + +/* Local */ + +static MV_CTRL_ENV_DEVICE_PROCESS_TYPE deviceProcessType2_5V[MAX_LockN+1]={ +{ R_NA, R_NA, R_NA }, /* LockN = 0 */ +{ R_NA, R_NA, R_NA }, /* LockN = 1 */ +{ R_NA, R_NA, R_NA }, /* LockN = 2 */ +{ R_NA, R_NA, R_NA }, /* LockN = 3 */ +{ R_NA, R_NA, R_NA }, /* LockN = 4 */ +{ R_NA, R_NA, 5447 }, /* LockN = 5 */ +{ R_NA, R_NA, 4539 }, /* LockN = 6 */ +{ 5295, R_NA, 3890 }, /* LockN = 7 */ +{ 4633, R_NA, 3404 }, /* LockN = 8 */ +{ 4118, R_NA, 3026 }, /* LockN = 9 */ +{ 3706, 5338, 2723 }, /* LockN = 10 */ +{ 3369, 4853, 2476 }, /* LockN = 11 */ +{ 3089, 4448, 2269 }, /* LockN = 12 */ +{ 2851, 4106, 2095 }, /* LockN = 13 */ +{ 2647, 3813, R_NA }, /* LockN = 14 */ +{ 2471, 3559, R_NA }, /* LockN = 15 */ +{ 2317, 3336, R_NA }, /* LockN = 16 */ +{ 2180, 3140, R_NA }, /* LockN = 17 */ +{ 2059, 2966, R_NA }, /* LockN = 18 */ +{ R_NA, 2810, -1 }, /* LockN = 19 */ +{ R_NA, 2669, -1 }, /* LockN = 20 */ +{ R_NA, 2542, -1 }, /* LockN = 21 */ +{ R_NA, 2426, -1 }, /* LockN = 22 */ +{ R_NA, 2321, -1 }, /* LockN = 23 */ +{ R_NA, 2224, -1 }, /* LockN = 24 */ +{ R_NA, 2135, -1 }, /* LockN = 25 */ +{ R_NA, R_NA, R_NA }, /* LockN = 26 */ +{ R_NA, R_NA, R_NA }, /* LockN = 27 */ +{ R_NA, R_NA, R_NA }, /* LockN = 28 */ +{ R_NA, R_NA, R_NA }, /* LockN = 29 */ +{ R_NA, R_NA, R_NA }, /* LockN = 30 */ +{ R_NA, R_NA, R_NA }, /* LockN = 31 */ +}; + +static MV_CTRL_ENV_DEVICE_PROCESS_TYPE deviceProcessType1_8V[MAX_LockN+1]={ +{ R_NA, R_NA, R_NA }, /* LockN = 0 */ +{ R_NA, R_NA, R_NA }, /* LockN = 1 */ +{ R_NA, R_NA, R_NA }, /* LockN = 2 */ +{ R_NA, R_NA, R_NA }, /* LockN = 3 */ +{ R_NA, R_NA, R_NA }, /* LockN = 4 */ +{ R_NA, R_NA, R_NA }, /* LockN = 5 */ +{ R_NA, R_NA, 5617 }, /* LockN = 6 */ +{ R_NA, R_NA, 4815 }, /* LockN = 7 */ +{ R_NA, R_NA, 4213 }, /* LockN = 8 */ +{ 5564, R_NA, 3745 }, /* LockN = 9 */ +{ 5008, R_NA, 3370 }, /* LockN = 10 */ +{ 4553, R_NA, 3064 }, /* LockN = 11 */ +{ 4173, R_NA, 2808 }, /* LockN = 12 */ +{ 3852, R_NA, 2592 }, /* LockN = 13 */ +{ 3577, 5699, 2407 }, /* LockN = 14 */ +{ 3339, 5319, 2247 }, /* LockN = 15 */ +{ 3130, 4987, 2106 }, /* LockN = 16 */ +{ 2946, 4693, R_NA }, /* LockN = 17 */ +{ 2782, 4432, R_NA }, /* LockN = 18 */ +{ 2636, 4199, -1 }, /* LockN = 19 */ +{ 2504, 3989, -1 }, /* LockN = 20 */ +{ 2385, 3799, -1 }, /* LockN = 21 */ +{ 2276, 3627, -1 }, /* LockN = 22 */ +{ 2177, 3469, -1 }, /* LockN = 23 */ +{ R_NA, 3324, -1 }, /* LockN = 24 */ +{ R_NA, 3191, -1 }, /* LockN = 25 */ +{ R_NA, 3069, R_NA }, /* LockN = 26 */ +{ R_NA, 2955, R_NA }, /* LockN = 27 */ +{ R_NA, 2849, R_NA }, /* LockN = 28 */ +{ R_NA, 2751, R_NA }, /* LockN = 29 */ +{ R_NA, 2659, R_NA }, /* LockN = 30 */ +{ R_NA, 2574, R_NA }, /* LockN = 31 */ +}; + + +static MV_CTRL_ENV_ETHERNET_PAD_CALIBRATION EthPadCalibrationTableHSTL_1_8V[]={ +{11,12}, /* type 1 */ +{18,20}, /* type 2 */ +{ 7, 8} /* type 3 */ +}; + +static MV_CTRL_ENV_ETHERNET_PAD_CALIBRATION EthPadCalibrationTable3_3V[]={ +{ 8, 9}, /* type 1 */ +{13,13}, /* type 2 */ +{ 6, 6} /* type 3 */ +}; + +static MV_CTRL_ENV_ETHERNET_PAD_CALIBRATION EthPadCalibrationTable2_5V[]={ /* Marvel RD board */ +{ 7, 7}, /* type 1 */ +{11,11}, /* type 2 */ +{ 5, 5} /* type 3 */ +}; + + + +int CpuPadCalibrationV = MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_1_8V; +int EthInterfaceDrivingStrength = MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_2_5V; + +static void ctrlEnvEthPadCalibrationSet(int port,MV_U32 drvN, MV_U32 drvP); +static MV_STATUS ctrlEnvCalculatePadCalibration(MV_U32 *pdrvN, MV_U32 *pdrvP); + +/******************************************************************************* +* mvCtrlEnvPadCalibrationInit - Initialize the Ethernet Pad Calibration Value +* +* DESCRIPTION: +* This function is Initialize the Ethernet Pad Calibration +* +* INPUT: +* Non +* OUTPUT: +* +* RETURN: +* None. +* +*******************************************************************************/ +void mvCtrlEnvPadCalibrationInit(void) +{ + int port; + MV_U32 drvN,drvP; + + if (MV_ERROR == ctrlEnvCalculatePadCalibration (&drvN, &drvP)) + return; + + /* Init static data structures */ + for (port=0; port>SDRAM_LOCKN_OFFS; +#ifdef DEBUG_ETHERNET_PAD_CALIBRATION + mvOsPrintf("CPU PadCalibration: LockN = 0x%X\n", LockN); +#endif + + if ((LockN < 0) || (LockN>MAX_LockN)) + { + return MV_ERROR; + } + if (CpuPadCalibrationV == MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_1_8V) + { + type1 = deviceProcessType1_8V[LockN].ResistorType1; + type2 = deviceProcessType1_8V[LockN].ResistorType2; + type3 = deviceProcessType1_8V[LockN].ResistorType3; + } + else + { + type1 = deviceProcessType2_5V[LockN].ResistorType1; + type2 = deviceProcessType2_5V[LockN].ResistorType2; + type3 = deviceProcessType2_5V[LockN].ResistorType3; + } + if ((type1 == R_NA) && (type2 == R_NA) && (type3 == R_NA)) /* all the types out of range? */ + { + return MV_ERROR; + } + /* find the lower diffrent type and Resitor */ + Difftype1 = (type1 > MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR)? + type1 - MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR:MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR - type1; + Difftype2 = (type2 > MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR)? + type2 - MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR:MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR - type2; + Difftype3 = (type3 > MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR)? + type3 - MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR:MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR - type3; +#ifdef DEBUG_ETHERNET_PAD_CALIBRATION + mvOsPrintf("Ethernet Pad Calibration: type1=%d, type2=%d, type3=%d Diff1=%d, Diff2=%d, Diff3=%d \n", + type1,type2,type3,Difftype1,Difftype2,Difftype3); +#endif + /* find the minimum from Difftype1, Difftype2 and Difftype3 */ + if (Difftype1 <= Difftype2) + { + if (Difftype1 <= Difftype3) + { + SelectedType = MV_CTRL_ENV_DEVICE_PROCESS_TYPE1; + } + else + { + SelectedType = MV_CTRL_ENV_DEVICE_PROCESS_TYPE3; + + } + } + else + { + if (Difftype2 <= Difftype3) + { + SelectedType = MV_CTRL_ENV_DEVICE_PROCESS_TYPE2; + } + else + { + SelectedType = MV_CTRL_ENV_DEVICE_PROCESS_TYPE3; + + } + } + + /* load the correct drvN and drvP from the selected type table. */ + if (EthInterfaceDrivingStrength == MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_HSTL_1_8V) + { + *pdrvN = EthPadCalibrationTableHSTL_1_8V[SelectedType].padCalibrationDrvN; + *pdrvP = EthPadCalibrationTableHSTL_1_8V[SelectedType].padCalibrationDrvP; + } + if (EthInterfaceDrivingStrength == MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_3_3V) + { + *pdrvN = EthPadCalibrationTable3_3V[SelectedType].padCalibrationDrvN; + *pdrvP = EthPadCalibrationTable3_3V[SelectedType].padCalibrationDrvP; + } + if (EthInterfaceDrivingStrength == MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_2_5V) + { + *pdrvN = EthPadCalibrationTable2_5V[SelectedType].padCalibrationDrvN; + *pdrvP = EthPadCalibrationTable2_5V[SelectedType].padCalibrationDrvP; + } + +#ifdef DEBUG_ETHERNET_PAD_CALIBRATION + mvOsPrintf("mvEthPadCalibration: SelectedType=%d, drvN=0x%X,drvP=0x%X, \n", + SelectedType+1,*pdrvN,*pdrvP); +#endif + return MV_OK; +#endif +} + + +/******************************************************************************* +* mvCtrlEnvEthInterfaceDrivingStrengthSet +* +* DESCRIPTION: +* This function set the interface driving strength voltage +* +* INPUT: +* None +* +* OUTPUT: +* +* RETURN: +* None. +* +*******************************************************************************/ +void mvCtrlEnvEthInterfaceDrivingStrengthSet(int Value) +{ + if (Value >MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_MAX) + { + return; + } + EthInterfaceDrivingStrength = Value; +} +/******************************************************************************* +* mvCtrlEnvEthInterfaceDrivingStrengthGet +* +* DESCRIPTION: +* This function replay the interface driving strength voltage +* +* INPUT: +* None +* +* OUTPUT: +* +* RETURN: +* the interface driving strength voltage +* +*******************************************************************************/ +int mvCtrlEnvEthInterfaceDrivingStrengthGet(void) +{ + return EthInterfaceDrivingStrength; +} + +/******************************************************************************* +* mvCtrlEnvEthCpuPadCalibrationVoltSet +* +* DESCRIPTION: +* This function set the ethernet cpu pad calibration voltage +* +* INPUT: +* None +* +* OUTPUT: +* +* RETURN: +* None. +* +*******************************************************************************/ +void mvCtrlEnvEthCpuPadCalibrationVoltSet(int Value) +{ + if (Value >MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_MAX) + { + return; + } + CpuPadCalibrationV = Value; +} +/******************************************************************************* +* mvCtrlEnvEthCpuPadCalibrationVoltGet +* +* DESCRIPTION: +* This function replay the CPU pad calibration voltage +* +* INPUT: +* None +* +* OUTPUT: +* +* RETURN: +* ethernet cpu pad calibration voltage +* +*******************************************************************************/ +int mvCtrlEnvEthCpuPadCalibrationVoltGet(void) +{ + return CpuPadCalibrationV; +} + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.h new file mode 100644 index 0000000..fed094e --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvPadCalibration.h @@ -0,0 +1,162 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +/****************************************************************************** +* mvcltrlEnvPadCalibration.h - Header File for : MV-MV64560 Setting the Ethernet * +* Pad Calibration Value * +* * +* DESCRIPTION: * +* This header file contains macros typedefs and the ethernet pad * +* calibration Value tables * +* * +* DEPENDENCIES: * +* None. * +* * +*******************************************************************************/ + +#ifndef __mvCtrlEnvEthPad_Calibration_h__ +#define __mvCtrlEnvEthPad_Calibration_h__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ + +/* defines */ +/* CPU interface voltage in use. */ + +typedef enum __mvethcpuinterfacevoltage__ +{ + MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_1_8V, + MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_2_5, + +}MV_CTRL_ENV_CPU_VOLTAGE; + +#define MV_ETH_CPU_INTERFACE_VOLTAGE MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_1_8V +#define MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_MAX MV_CTRL_ENV_CPU_INTERFACE_VOLTAGE_2_5 + + +/* The Ethernet interface driving strength (Table 33 in Doc. No. MV-S300848-00, Rev. A) */ +#undef MV_CTRL_ENV_ETHERNET_INTERFACE_DRIVING_STRENGTH_HSTL_1_8V +#undef MV_CTRL_ENV_ETHERNET_INTERFACE_DRIVING_STRENGTH_3_3V +#define MV_CTRL_ENV_ETHERNET_INTERFACE_DRIVING_STRENGTH_2_5V /* Marvel RD board */ + +typedef enum __mvCtrlEnvInterface_driving_strengthvoltage__ +{ + MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_HSTL_1_8V, + MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_3_3V, + MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_2_5V /* Marvel RD board */ +}MV_ETH_DRIVING_STRENGTH_VOLTAGE_ENUM; + +#define MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_MAX MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_2_5V + +#define MV_CTRL_ENV_DRIVING_STRENGTH_VOLTAGE MV_CTRL_ENV_INTERFACE_DRIVING_STRENGTH_2_5V + +#define MV_CTRL_ENV_CPU_PAD_CALIBRATION_RESISTOR (50*100) /* 50ohm is for single CPU */ + +/* CPU INTERFACE VOLTAGE */ +typedef struct _mvEthDeviceProcessType +{ + int ResistorType1; + int ResistorType2; + int ResistorType3; +} MV_CTRL_ENV_DEVICE_PROCESS_TYPE; + + +/* The Ethernet interface driving strength table */ + +typedef struct _EthernetPadCalibration +{ + int padCalibrationDrvN; + int padCalibrationDrvP; +} MV_CTRL_ENV_ETHERNET_PAD_CALIBRATION; + + +typedef enum __mvethEthernetPadCalibrationType_ +{ + MV_CTRL_ENV_DEVICE_PROCESS_TYPE1, + MV_CTRL_ENV_DEVICE_PROCESS_TYPE2, + MV_CTRL_ENV_DEVICE_PROCESS_TYPE3, + +}MV_CTRL_ENV_ETHERNET_PAD_CALIBRATION_TYPE; + + +/* function */ + +void mvCtrlEnvPadCalibrationInit(void); +void mvCtrlEnvEthInterfaceDrivingStrengthSet(int Value); +int mvCtrlEnvEthInterfaceDrivingStrengthGet(void); +void mvCtrlEnvEthCpuPadCalibrationVoltSet(int Value); +int mvCtrlEnvEthCpuPadCalibrationVoltGet(void); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __mvCtrlEnvEthPad_Calibration_h__ */ + + + + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvSpec.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvSpec.h new file mode 100644 index 0000000..7688e51 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/mvCtrlEnvSpec.h @@ -0,0 +1,243 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvCtrlEnvSpech +#define __INCmvCtrlEnvSpech + +#include "mvDeviceId.h" +#include "mvSysHwConfig.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* includes */ + + +/* defines */ +/* This define describes the TWSI interrupt bit and location */ +#define TWSI_CPU_MAIN_INT_CAUSE_REG 0x20200 +#define TWSI_CPU_MAIN_INT_BIT 0x20 + +/* 0x5181 revisions*/ +#define MV_5181_A0_REV 0x0 +#define MV_5181_A0_ID ((MV_5181_DEV_ID << 16) | MV_5181_A0_REV) +#define MV_5181_A0_NAME "88F5181 A0" +#define MV_5181_A1_REV 0x1 +#define MV_5181_A1_ID ((MV_5181_DEV_ID << 16) | MV_5181_A1_REV) +#define MV_5181_A1_NAME "88F5181 A1" +#define MV_5181_B0_REV 0x2 +#define MV_5181_B0_ID ((MV_5181_DEV_ID << 16) | MV_5181_B0_REV) +#define MV_5181_B0_NAME "88F5181 B0" +#define MV_5181_B1_REV 0x3 +#define MV_5181_B1_ID ((MV_5181_DEV_ID << 16) | MV_5181_B1_REV) +#define MV_5181_B1_NAME "88F5181 B1" +/* 0x5281 revisions*/ +#define MV_5281_A0_REV 0x0 +#define MV_5281_A0_ID ((MV_5281_DEV_ID << 16) | MV_5281_A0_REV) +#define MV_5281_A0_NAME "88F5281 A0" +#define MV_5281_B0_REV 0x1 +#define MV_5281_B0_ID ((MV_5281_DEV_ID << 16) | MV_5281_B0_REV) +#define MV_5281_B0_NAME "88F5281 B0" +#define MV_5281_C0_REV 0x2 +#define MV_5281_C0_ID ((MV_5281_DEV_ID << 16) | MV_5281_C0_REV) +#define MV_5281_C0_NAME "88F5281 C0" +#define MV_5281_C1_REV 0x3 +#define MV_5281_C1_ID ((MV_5281_DEV_ID << 16) | MV_5281_C1_REV) +#define MV_5281_C1_NAME "88F5281 C1" +#define MV_5281_D0_REV 0x4 +#define MV_5281_D0_ID ((MV_5281_DEV_ID << 16) | MV_5281_D0_REV) +#define MV_5281_D0_NAME "88F5281 D0" +#define MV_5281_D1_REV 0x5 +#define MV_5281_D1_ID ((MV_5281_DEV_ID << 16) | MV_5281_D1_REV) +#define MV_5281_D1_NAME "88F5281 D1" +#define MV_5281_D2_REV 0x6 +#define MV_5281_D2_ID ((MV_5281_DEV_ID << 16) | MV_5281_D2_REV) +#define MV_5281_D2_NAME "88F5281 D2" +/* 0x5182 revisions*/ +#define MV_5182_A0_REV 0x0 +#define MV_5182_A0_ID ((MV_5182_DEV_ID << 16) | MV_5182_A0_REV) +#define MV_5182_A0_NAME "88F5182 A0" +#define MV_5182_A1_REV 0x1 +#define MV_5182_A1_ID ((MV_5182_DEV_ID << 16) | MV_5182_A1_REV) +#define MV_5182_A1_NAME "88F5182 A1" +#define MV_5182_A2_REV 0x2 +#define MV_5182_A2_ID ((MV_5182_DEV_ID << 16) | MV_5182_A2_REV) +#define MV_5182_A2_NAME "88F5182 A2" +/* 0x5181L revisions*/ +#define MV_5181L_A0_REV 0x8 +#define MV_5181L_A0_ID ((MV_5181_DEV_ID << 16) | MV_5181L_A0_REV) +#define MV_5181L_A0_NAME "88F5181L A0" +#define MV_5181L_A1_REV 0x9 +#define MV_5181L_A1_ID ((MV_5181_DEV_ID << 16) | MV_5181L_A1_REV) +#define MV_5181L_A1_NAME "88F5181L A1" + +/* 0x8660 revisions */ +#define MV_8660_A0_REV 0x0 +#define MV_8660_A0_ID ((MV_8660_DEV_ID << 16) | MV_8660_A0_REV) +#define MV_8660_A0_NAME "88W8660 A0" +#define MV_8660_A1_REV 0x1 +#define MV_8660_A1_ID ((MV_8660_DEV_ID << 16) | MV_8660_A1_REV) +#define MV_8660_A1_NAME "88W8660 A1" + +/* 0x5180N revisions */ +#define MV_5180N_B1_REV 0x3 +#define MV_5180N_B1_ID ((MV_5180_DEV_ID << 16) | MV_5180N_B1_REV) +#define MV_5180N_B1_NAME "88F5180N B1" + +/* 0x5082 revisions*/ +#define MV_5082_A2_REV 0x2 +#define MV_5082_A2_ID ((MV_5082_DEV_ID << 16) | MV_5082_A2_REV) +#define MV_5082_A2_NAME "88F5082 A2" + +/* 0x1282 revisions*/ +#define MV_1281_A0_REV 0x0 +#define MV_1281_A0_ID ((MV_1281_DEV_ID << 16) | MV_1281_A0_REV) +#define MV_1281_A0_NAME "88F1281 A0" + +/* 0x6082 revisions*/ +#define MV_6082_A0_REV 0x0 +#define MV_6082_A0_ID ((MV_6082_DEV_ID << 16) | MV_6082_A0_REV) +#define MV_6082_A0_NAME "88F6082 A0" +#define MV_6082L_A0_NAME "88F6082L A0" +#define MV_6082_A1_REV 0x1 +#define MV_6082_A1_ID ((MV_6082_DEV_ID << 16) | MV_6082_A1_REV) +#define MV_6082_A1_NAME "88F6082 A1" + +/* 0x6183 revisions*/ +#define MV_6183_A0_REV 0x0 +#define MV_6183_A0_ID ((MV_6183_DEV_ID << 16) | MV_6183_A0_REV) +#define MV_6183_A0_NAME "88F6183 A0" +#define MV_6183_1_REV 0x1 +#define MV_6183_1_ID ((MV_6183_DEV_ID << 16) | MV_6183_1_REV) +#define MV_6183_1_NAME "88F6183 1" +#define MV_6183_A1_REV 0x2 +#define MV_6183_A1_ID ((MV_6183_DEV_ID << 16) | MV_6183_A1_REV) +#define MV_6183_A1_NAME "88F6183 A1" +#define MV_6183_B0_REV 0x3 +#define MV_6183_B0_ID ((MV_6183_DEV_ID << 16) | MV_6183_B0_REV) +#define MV_6183_B0_NAME "88F6183 B0" + +/* 0x6183L revisions*/ +#define MV_6183L_B0_REV 0x3 +#define MV_6183L_B0_ID ((MV_6183L_DEV_ID << 16) | MV_6183L_B0_REV) +#define MV_6183L_B0_NAME "88F6183L B0" + +#define XOR_UNIT_BASE(unit) 0x60900 +#define MV_XOR_MAX_UNIT 1 +#define MV_XOR_MAX_CHAN 2 /* totol channels for all units together*/ +#define MV_XOR_MAX_CHAN_PER_UNIT 2 /* channels for units */ + + +#if defined(MV_88F1181) +#include "mv88F1X81EnvSpec.h" +#elif defined(MV_88F1281) +#include "mv88F1281EnvSpec.h" +#elif defined(MV_88F5182) +#include "mv88F5182EnvSpec.h" +#elif defined(MV_88F5082) +#include "mv88F5082EnvSpec.h" +#elif defined(MV_88F5181L) +#include "mv88F5181LEnvSpec.h" +#elif defined(MV_88W8660) +#include "mv88w8660EnvSpec.h" +#elif defined(MV_88F5181) +#include "mv88F5X81EnvSpec.h" +#elif defined(MV_88F5180N) +#include "mv88F5180NEnvSpec.h" +#elif defined(MV_88F6082) +#include "mv88F6082EnvSpec.h" +#elif defined(MV_88F6183) +#include "mv88F6183EnvSpec.h" +#elif defined(MV_88F6183L) +#include "mv88F6183LEnvSpec.h" +#else +#error "No Soc defined" +#endif + +#ifndef MV_ASMLANGUAGE + +/* This enumerator defines the Marvell Units ID */ +typedef enum _mvUnitId +{ + DRAM_UNIT_ID, + PEX_UNIT_ID, + PCI_UNIT_ID, + ETH_GIG_UNIT_ID, + ETH_UNM_UNIT_ID, + USB_UNIT_ID, + IDMA_UNIT_ID, + XOR_UNIT_ID, + SATA_UNIT_ID, + TDM_UNIT_ID, + UART_UNIT_ID, + CESA_UNIT_ID, + SPI_UNIT_ID, + AUDIO_UNIT_ID, + MAX_UNITS_ID, + +}MV_UNIT_ID; + +#endif +#endif /* __INCmvCtrlEnvSpech */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.c new file mode 100644 index 0000000..759dfdb --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.c @@ -0,0 +1,1051 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "ctrlEnv/sys/mvAhbToMbus.h" +#include "ctrlEnv/sys/mvAhbToMbusConfig.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#undef MV_DEBUG +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + +/* typedefs */ + + +/* CPU address remap registers offsets are inconsecutive. This struct */ +/* describes address remap register offsets */ +typedef struct _ahbToMbusRemapRegOffs +{ + MV_U32 lowRegOffs; /* Low 32-bit remap register offset */ + MV_U32 highRegOffs; /* High 32 bit remap register offset */ +}AHB_TO_MBUS_REMAP_REG_OFFS; + +/* locals */ +static MV_STATUS ahbToMbusRemapRegOffsGet (MV_U32 winNum, + AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs); + +/******************************************************************************* +* mvAhbToMbusInit - Initialize Ahb To Mbus Address Map ! +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK laways. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusInit(void) +{ + return MV_OK; + +} + +/******************************************************************************* +* mvAhbToMbusWinSet - Set CPU-to-peripheral winNum address window +* +* DESCRIPTION: +* This function sets +* address window, also known as address decode window. +* A new address decode window is set for specified winNum address window. +* If address decode window parameter structure enables the window, +* the routine will also enable the winNum window, allowing CPU to access +* the winNum window. +* +* INPUT: +* winNum - Windows number. +* pAddrDecWin - CPU winNum window data structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if CPU winNum window was set correctly, MV_ERROR in case of +* address window overlapps with other active CPU winNum window or +* trying to assign 36bit base address while CPU does not support that. +* The function returns MV_NOT_SUPPORTED, if the winNum is unsupported. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttribs; + MV_DEC_REGS decRegs; + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinSet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + + /* read base register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum)); + } + else + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG); + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvAhbToMbusWinSet:Error setting AHB to MBUS window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + /* read control register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); + } + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvAhbToMbusWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + /* enable\Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + decRegs.sizeReg |= ATMWCR_WIN_ENABLE; + } + else + { + decRegs.sizeReg &= ~ATMWCR_WIN_ENABLE; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~ATMWCR_WIN_ATTR_MASK; + decRegs.sizeReg |= targetAttribs.attrib << ATMWCR_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.sizeReg &= ~ATMWCR_WIN_TARGET_MASK; + decRegs.sizeReg |= targetAttribs.targetId << ATMWCR_WIN_TARGET_OFFS; + +#if !defined(MV_RUN_FROM_FLASH) + /* To be on the safe side we disable the window before writing the */ + /* new values. */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + mvAhbToMbusWinEnable(winNum,MV_FALSE); + } +#endif + + /* 3) Write to address decode Base Address Register */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_BASE_REG(winNum), decRegs.baseReg); + } + else + { + MV_REG_WRITE(AHB_TO_MBUS_WIN_INTEREG_REG, decRegs.baseReg); + } + + + /* Internal register space have no size */ + /* register. Do not perform size register assigment for those targets */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + /* Write to address decode Size Register */ + MV_REG_WRITE(AHB_TO_MBUS_WIN_CTRL_REG(winNum), decRegs.sizeReg); + } + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusWinGet - Get CPU-to-peripheral winNum address window +* +* DESCRIPTION: +* Get the CPU peripheral winNum address window. +* +* INPUT: +* winNum - Peripheral winNum enumerator +* +* OUTPUT: +* pAddrDecWin - CPU winNum window information data structure. +* +* RETURN: +* MV_OK if winNum exist, MV_ERROR otherwise. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinGet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + + /* Internal register space size have no size register*/ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.sizeReg = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); + } + else + { + decRegs.sizeReg = 0; + } + + + /* Read base and size */ + if (winNum != MV_AHB_TO_MBUS_INTREG_WIN) + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum)); + } + else + { + decRegs.baseReg = MV_REG_READ(AHB_TO_MBUS_WIN_INTEREG_REG); + } + + + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + { + pAddrDecWin->addrWin.size = INTER_REGS_SIZE; + pAddrDecWin->target = INTER_REGS; + pAddrDecWin->enable = MV_TRUE; + + return MV_OK; + } + + + if (decRegs.sizeReg & ATMWCR_WIN_ENABLE) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + + } + + + + if (-1 == pAddrDecWin->addrWin.size) + { + return MV_ERROR; + } + + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & ATMWCR_WIN_ATTR_MASK) >> + ATMWCR_WIN_ATTR_OFFS; + targetAttrib.targetId = (decRegs.sizeReg & ATMWCR_WIN_TARGET_MASK) >> + ATMWCR_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinTargetGet(MV_TARGET target) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + if (INTER_REGS == target) + { + return MV_AHB_TO_MBUS_INTREG_WIN; + } + + for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS ; winNum++) + { + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + continue; + + if (mvAhbToMbusWinGet(winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail\n"); + return 0xffffffff; + + } + + if (decWin.enable == MV_TRUE) + { + if (decWin.target == target) + { + return winNum; + } + + } + + } + + return 0xFFFFFFFF; + + +} + +/******************************************************************************* +* mvAhbToMbusWinAvailGet - Get First Available window number. +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinAvailGet(MV_VOID) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 winNum; + + for (winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS ; winNum++) + { + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + continue; + + if (mvAhbToMbusWinGet(winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: mvAhbToMbusWinGet fail\n"); + return 0xffffffff; + + } + + if (decWin.enable == MV_FALSE) + { + return winNum; + } + + } + + return 0xFFFFFFFF; +} + + +/******************************************************************************* +* mvAhbToMbusWinEnable - Enable/disable a CPU address decode window +* +* DESCRIPTION: +* This function enable/disable a CPU address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling CPU accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - Peripheral winNum enumerator. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if protection window number was wrong, or the window +* overlapps other winNum window. +* +*******************************************************************************/ +MV_STATUS mvAhbToMbusWinEnable(MV_U32 winNum, MV_BOOL enable) +{ + + /* Parameter checking */ + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvAhbToMbusWinEnable: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + /* Internal registers bar can't be disable or enabled */ + if (winNum == MV_AHB_TO_MBUS_INTREG_WIN) + { + return (enable ? MV_OK : MV_ERROR); + } + + if (enable == MV_TRUE) + { + /* enable the window */ + MV_REG_BIT_SET(AHB_TO_MBUS_WIN_CTRL_REG(winNum), ATMWCR_WIN_ENABLE); + } + else + { /* Disable address decode winNum window */ + MV_REG_BIT_RESET(AHB_TO_MBUS_WIN_CTRL_REG(winNum), ATMWCR_WIN_ENABLE); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvAhbToMbusWinRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* After a CPU address hits one of PCI address decode windows there is an +* option to remap the address to a different one. For example, CPU +* executes a read from PCI winNum window address 0x1200.0000. This +* can be modified so the address on the PCI bus would be 0x1400.0000 +* Using the PCI address remap mechanism. +* +* INPUT: +* winNum - Peripheral winNum enumerator. Must be a PCI winNum. +* pAddrDecWin - CPU winNum window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if winNum is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvAhbToMbusWinRemap(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddr; + AHB_TO_MBUS_REMAP_REG_OFFS remapRegOffs; + + MV_U32 effectiveBaseAddress=0, + baseAddrValue=0,windowSizeValue=0; + + + /* Get registers offsets of given winNum */ + if (MV_NO_SUCH == ahbToMbusRemapRegOffsGet(winNum, &remapRegOffs)) + { + return 0xffffffff; + } + + /* 1) Set address remap low */ + baseAddr = pAddrWin->baseLow; + + /* Check base address aligment */ + /* + if (MV_IS_NOT_ALIGN(baseAddr, ATMWRLR_REMAP_LOW_ALIGNMENT)) + { + mvOsPrintf("mvAhbToMbusPciRemap: Warning. Target base 0x%x unaligned\n", + baseAddr); + return MV_ERROR; + } + */ + + /* BaseLow[31:16] => base register [31:16] */ + baseAddr = baseAddr & ATMWRLR_REMAP_LOW_MASK; + + MV_REG_WRITE(remapRegOffs.lowRegOffs, baseAddr); + + MV_REG_WRITE(remapRegOffs.highRegOffs, pAddrWin->baseHigh); + + + baseAddrValue = MV_REG_READ(AHB_TO_MBUS_WIN_BASE_REG(winNum)); + windowSizeValue = MV_REG_READ(AHB_TO_MBUS_WIN_CTRL_REG(winNum)); + + baseAddrValue &= ATMWBR_BASE_MASK; + windowSizeValue &=ATMWCR_WIN_SIZE_MASK; + + /* Start calculating the effective Base Address */ + effectiveBaseAddress = baseAddrValue ; + + /* The effective base address will be combined from the chopped (if any) + remap value (according to the size value and remap mechanism) and the + window's base address */ + effectiveBaseAddress |= (((windowSizeValue) | 0xffff) & pAddrWin->baseLow); + /* If the effectiveBaseAddress exceed the window boundaries return an + invalid value. */ + + if (effectiveBaseAddress > (baseAddrValue + (windowSizeValue | 0xffff))) + { + mvOsPrintf("mvAhbToMbusPciRemap: Error\n"); + return 0xffffffff; + } + + return effectiveBaseAddress; + + +} +/******************************************************************************* +* mvAhbToMbusWinTargetSwap - Swap AhbToMbus windows between targets +* +* DESCRIPTION: +* +* INPUT: +* target1 - CPU Interface target 1 +* target2 - CPU Interface target 2 +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if targets are illigal, or if one of the targets is not +* associated to a valid window . +* MV_OK otherwise. +* +*******************************************************************************/ + + +MV_STATUS mvAhbToMbusWinTargetSwap(MV_TARGET target1,MV_TARGET target2) +{ + MV_U32 winNum1,winNum2; + MV_AHB_TO_MBUS_DEC_WIN winDec1,winDec2,winDecTemp; + AHB_TO_MBUS_REMAP_REG_OFFS remapRegs1,remapRegs2; + MV_U32 remapBaseLow1=0,remapBaseLow2=0; + MV_U32 remapBaseHigh1=0,remapBaseHigh2=0; + + + /* Check parameters */ + if (target1 >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is Illigal\n", target1); + return MV_ERROR; + } + + if (target2 >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is Illigal\n", target1); + return MV_ERROR; + } + + + /* get window associated with this target */ + winNum1 = mvAhbToMbusWinTargetGet(target1); + + if (winNum1 == 0xffffffff) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", + target1,winNum1); + return MV_ERROR; + + } + + /* get window associated with this target */ + winNum2 = mvAhbToMbusWinTargetGet(target2); + + if (winNum2 == 0xffffffff) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d has illigal win %d\n", + target2,winNum2); + return MV_ERROR; + + } + + /* now Get original values of both Windows */ + if (MV_OK != mvAhbToMbusWinGet(winNum1,&winDec1)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", + winNum1); + return MV_ERROR; + + } + if (MV_OK != mvAhbToMbusWinGet(winNum2,&winDec2)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: mvAhbToMbusWinGet failed win %d\n", + winNum2); + return MV_ERROR; + + } + + + /* disable both windows */ + if (MV_OK != mvAhbToMbusWinEnable(winNum1,MV_FALSE)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable window %d\n", + winNum1); + return MV_ERROR; + + } + if (MV_OK != mvAhbToMbusWinEnable(winNum2,MV_FALSE)) + { + mvOsPrintf("mvAhbToMbusWinTargetSwap: failed to enable windo %d\n", + winNum2); + return MV_ERROR; + + } + + + /* now swap targets */ + + /* first save winDec2 values */ + winDecTemp.addrWin.baseHigh = winDec2.addrWin.baseHigh; + winDecTemp.addrWin.baseLow = winDec2.addrWin.baseLow; + winDecTemp.addrWin.size = winDec2.addrWin.size; + winDecTemp.enable = winDec2.enable; + winDecTemp.target = winDec2.target; + + /* winDec2 = winDec1 */ + winDec2.addrWin.baseHigh = winDec1.addrWin.baseHigh; + winDec2.addrWin.baseLow = winDec1.addrWin.baseLow; + winDec2.addrWin.size = winDec1.addrWin.size; + winDec2.enable = winDec1.enable; + winDec2.target = winDec1.target; + + + /* winDec1 = winDecTemp */ + winDec1.addrWin.baseHigh = winDecTemp.addrWin.baseHigh; + winDec1.addrWin.baseLow = winDecTemp.addrWin.baseLow; + winDec1.addrWin.size = winDecTemp.addrWin.size; + winDec1.enable = winDecTemp.enable; + winDec1.target = winDecTemp.target; + + + /* now set the new values */ + + + mvAhbToMbusWinSet(winNum1,&winDec1); + mvAhbToMbusWinSet(winNum2,&winDec2); + + + + + + /* now we will treat the remap windows if exist */ + + + /* now check if one or both windows has a remap window + as well after the swap ! */ + + /* if a window had a remap value differnt than the base value + before the swap , then after the swap the remap value will be + equal to the base value unless both windows has a remap windows*/ + + /* first get old values */ + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum1,&remapRegs1)) + { + remapBaseLow1 = MV_REG_READ(remapRegs1.lowRegOffs); + remapBaseHigh1 = MV_REG_READ(remapRegs1.highRegOffs); + + } + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2,&remapRegs2)) + { + remapBaseLow2 = MV_REG_READ(remapRegs2.lowRegOffs); + remapBaseHigh2 = MV_REG_READ(remapRegs2.highRegOffs); + + + } + + /* now do the swap */ + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum1,&remapRegs1)) + { + if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2,&remapRegs2)) + { + /* Two windows has a remap !!! so swap */ + + MV_REG_WRITE(remapRegs2.highRegOffs,remapBaseHigh1); + MV_REG_WRITE(remapRegs2.lowRegOffs,remapBaseLow1); + + MV_REG_WRITE(remapRegs1.highRegOffs,remapBaseHigh2); + MV_REG_WRITE(remapRegs1.lowRegOffs,remapBaseLow2); + + + + } + else + { + /* remap == base */ + MV_REG_WRITE(remapRegs1.highRegOffs,winDec1.addrWin.baseHigh); + MV_REG_WRITE(remapRegs1.lowRegOffs,winDec1.addrWin.baseLow); + + } + + } + else if (MV_NO_SUCH != ahbToMbusRemapRegOffsGet(winNum2,&remapRegs2)) + { + /* remap == base */ + MV_REG_WRITE(remapRegs2.highRegOffs,winDec2.addrWin.baseHigh); + MV_REG_WRITE(remapRegs2.lowRegOffs,winDec2.addrWin.baseLow); + + } + + + + return MV_OK; + + +} + + + +#if defined(MV_88F1181) + +/******************************************************************************* +* mvAhbToMbusXbarCtrlSet - Set The CPU master Xbar arbitration. +* +* DESCRIPTION: +* This function sets CPU Mbus Arbiter +* +* INPUT: +* pPizzaArbArray - A priority Structure describing 16 "pizza slices". At +* each clock cycle, the crossbar arbiter samples all +* requests and gives the bus to the next agent according +* to the "pizza". +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if paramers to function invalid. +* +*******************************************************************************/ +MV_STATUS mvMbusArbSet(MV_MBUS_ARB_TARGET *pPizzaArbArray) +{ + MV_U32 sliceNum; + MV_U32 xbarCtrl = 0; + MV_MBUS_ARB_TARGET xbarTarget; + + /* 1) Set crossbar control low register */ + for (sliceNum = 0; sliceNum < MRLR_SLICE_NUM; sliceNum++) + { + xbarTarget = pPizzaArbArray[sliceNum]; + + /* sliceNum parameter check */ + if (xbarTarget > MAX_MBUS_ARB_TARGETS) + { + mvOsPrintf("mvAhbToMbusXbarCtrlSet: ERR. Can't set Target %d\n", + xbarTarget); + return MV_ERROR; + } + xbarCtrl |= (xbarTarget << MRLR_LOW_ARB_OFFS(sliceNum)); + } + /* Write to crossbar control low register */ + MV_REG_WRITE(MBUS_ARBITER_LOW_REG, xbarCtrl); + + xbarCtrl = 0; + + /* 2) Set crossbar control high register */ + for (sliceNum = MRLR_SLICE_NUM; + sliceNum < MRLR_SLICE_NUM+MRHR_SLICE_NUM; + sliceNum++) + { + + xbarTarget = pPizzaArbArray[sliceNum]; + + /* sliceNum parameter check */ + if (xbarTarget > MAX_MBUS_ARB_TARGETS) + { + mvOsPrintf("mvAhbToMbusXbarCtrlSet: ERR. Can't set Target %d\n", + xbarTarget); + return MV_ERROR; + } + xbarCtrl |= (xbarTarget << MRHR_HIGH_ARB_OFFS(sliceNum)); + } + /* Write to crossbar control high register */ + MV_REG_WRITE(MBUS_ARBITER_HIGH_REG, xbarCtrl); + + return MV_OK; +} + +/******************************************************************************* +* mvMbusArbCtrlSet - Set MBus Arbiter control register +* +* DESCRIPTION: +* +* INPUT: +* ctrl - pointer to MV_MBUS_ARB_CTRL register +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if paramers to function invalid. +* +*******************************************************************************/ +MV_STATUS mvMbusArbCtrlSet(MV_MBUS_ARB_CTRL *ctrl) +{ + + if (ctrl->highPrio == MV_FALSE) + { + MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_ARM_TOP); + } + else + { + MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_ARM_TOP); + } + + if (ctrl->fixedRoundRobin == MV_FALSE) + { + MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_TARGET_FIXED); + } + else + { + MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_TARGET_FIXED); + } + + if (ctrl->starvEn == MV_FALSE) + { + MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_REQ_CTRL_EN); + } + else + { + MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_REQ_CTRL_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* mvMbusArbCtrlGet - Get MBus Arbiter control register +* +* DESCRIPTION: +* +* INPUT: +* ctrl - pointer to MV_MBUS_ARB_CTRL register +* +* OUTPUT: +* ctrl - pointer to MV_MBUS_ARB_CTRL register +* +* RETURN: +* MV_ERROR if paramers to function invalid. +* +*******************************************************************************/ +MV_STATUS mvMbusArbCtrlGet(MV_MBUS_ARB_CTRL *ctrl) +{ + + MV_U32 ctrlReg = MV_REG_READ(MBUS_ARBITER_CTRL_REG); + + if (ctrlReg & MACR_ARB_ARM_TOP) + { + ctrl->highPrio = MV_TRUE; + } + else + { + ctrl->highPrio = MV_FALSE; + } + + if (ctrlReg & MACR_ARB_TARGET_FIXED) + { + ctrl->fixedRoundRobin = MV_TRUE; + } + else + { + ctrl->fixedRoundRobin = MV_FALSE; + } + + if (ctrlReg & MACR_ARB_REQ_CTRL_EN) + { + ctrl->starvEn = MV_TRUE; + } + else + { + ctrl->starvEn = MV_FALSE; + } + + + return MV_OK; +} + +#endif /* #if defined(MV_88F1181) */ + + + +/******************************************************************************* +* ahbToMbusRemapRegOffsGet - Get CPU address remap register offsets +* +* DESCRIPTION: +* CPU to PCI address remap registers offsets are inconsecutive. +* This function returns PCI address remap registers offsets. +* +* INPUT: +* winNum - Address decode window number. See MV_U32 enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if winNum is not a PCI one. +* +*******************************************************************************/ +static MV_STATUS ahbToMbusRemapRegOffsGet(MV_U32 winNum, + AHB_TO_MBUS_REMAP_REG_OFFS *pRemapRegs) +{ + switch (winNum) + { + case 0: + case 1: + pRemapRegs->lowRegOffs = AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum); + pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum); + break; + case 2: + case 3: + if((mvCtrlModelGet() == MV_5281_DEV_ID) || + (mvCtrlModelGet() == MV_1281_DEV_ID) || + (mvCtrlModelGet() == MV_6183_DEV_ID) || + (mvCtrlModelGet() == MV_6183L_DEV_ID)) + { + pRemapRegs->lowRegOffs = AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum); + pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum); + break; + } + else + { + pRemapRegs->lowRegOffs = 0; + pRemapRegs->highRegOffs = 0; + + DB(mvOsPrintf("ahbToMbusRemapRegOffsGet: ERR. Invalid winNum %d\n", + winNum)); + return MV_NO_SUCH; + } + default: + { + pRemapRegs->lowRegOffs = 0; + pRemapRegs->highRegOffs = 0; + + DB(mvOsPrintf("ahbToMbusRemapRegOffsGet: ERR. Invalid winNum %d\n", + winNum)); + return MV_NO_SUCH; + } + } + + return MV_OK; +} + +/******************************************************************************* +* mvAhbToMbusAddDecShow - Print the AHB to MBus bridge address decode map. +* +* DESCRIPTION: +* This function print the CPU address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvAhbToMbusAddDecShow(MV_VOID) +{ + MV_AHB_TO_MBUS_DEC_WIN win; + MV_U32 winNum; + mvOsOutput( "\n" ); + mvOsOutput( "AHB To MBUS Bridge:\n" ); + mvOsOutput( "-------------------\n" ); + + for( winNum = 0; winNum < MAX_AHB_TO_MBUS_WINS; winNum++ ) + { + memset( &win, 0, sizeof(MV_AHB_TO_MBUS_DEC_WIN) ); + + mvOsOutput( "win%d - ", winNum ); + + if( mvAhbToMbusWinGet( winNum, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + + } + else + mvOsOutput( "disable\n" ); + } + } + +} + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.h new file mode 100644 index 0000000..1b352a1 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbus.h @@ -0,0 +1,130 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbush +#define __INCmvAhbToMbush + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvAhbToMbusRegs.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* defines */ + +#if defined(MV_88F1181) +/* This enumerator defines the Marvell controller possible MBUS arbiter */ +/* target ports. It is used to define crossbar priority scheame (pizza) */ +typedef enum _mvMBusArbTargetId +{ + DRAM_MBUS_ARB_TARGET = 0, /* Port 0 -> DRAM interface */ + TWSI_MBUS_ARB_TARGET = 1, /* Port 1 -> TWSI */ + ARM_MBUS_ARB_TARGET = 2, /* Port 2 -> ARM */ + PEX1_MBUS_ARB_TARGET = 3, /* Port 3 -> PCI Express 1 */ + PEX0_MBUS_ARB_TARGET = 4, /* Port 4 -> PCI Express0 */ + MAX_MBUS_ARB_TARGETS +}MV_MBUS_ARB_TARGET; + +typedef struct _mvMBusArbCtrl +{ + MV_BOOL starvEn; + MV_BOOL highPrio; + MV_BOOL fixedRoundRobin; + +}MV_MBUS_ARB_CTRL; + +#endif /* #if defined(MV_88F1181) */ + +typedef struct _mvAhbtoMbusDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_AHB_TO_MBUS_DEC_WIN; + +/* mvAhbToMbus.h API list */ + +MV_STATUS mvAhbToMbusInit(MV_VOID); +MV_STATUS mvAhbToMbusWinSet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin); +MV_STATUS mvAhbToMbusWinGet(MV_U32 winNum, MV_AHB_TO_MBUS_DEC_WIN *pAddrDecWin); +MV_STATUS mvAhbToMbusWinEnable(MV_U32 winNum,MV_BOOL enable); +MV_U32 mvAhbToMbusWinRemap(MV_U32 winNum, MV_ADDR_WIN *pAddrDecWin); +MV_U32 mvAhbToMbusWinTargetGet(MV_TARGET target); +MV_U32 mvAhbToMbusWinAvailGet(MV_VOID); +MV_STATUS mvAhbToMbusWinTargetSwap(MV_TARGET target1,MV_TARGET target2); + +#if defined(MV_88F1181) + +MV_STATUS mvMbusArbSet(MV_MBUS_ARB_TARGET *pPizzaArbArray); +MV_STATUS mvMbusArbCtrlSet(MV_MBUS_ARB_CTRL *ctrl); +MV_STATUS mvMbusArbCtrlGet(MV_MBUS_ARB_CTRL *ctrl); + +#endif /* #if defined(MV_88F1181) */ + + +MV_VOID mvAhbToMbusAddDecShow(MV_VOID); + + +#endif /* __INCmvAhbToMbush */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusConfig.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusConfig.h new file mode 100644 index 0000000..e01ee38 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusConfig.h @@ -0,0 +1,74 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbusConfigh +#define __INCmvAhbToMbusConfigh + +#include "mvSysHwConfig.h" +#include "mvAhbToMbusRegs.h" + + + +#endif /* __INCmvAhbToMbusConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusRegs.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusRegs.h new file mode 100644 index 0000000..981986e --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvAhbToMbusRegs.h @@ -0,0 +1,188 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvAhbToMbusRegsh +#define __INCmvAhbToMbusRegsh + +/******************************/ +/* ARM Address Map Registers */ +/******************************/ + +#define MAX_AHB_TO_MBUS_WINS 9 +#define MV_AHB_TO_MBUS_INTREG_WIN 8 + + +#define AHB_TO_MBUS_WIN_CTRL_REG(winNum) (0x20000 + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_BASE_REG(winNum) (0x20004 + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum) (0x20008 + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum) (0x2000C + (winNum)*0x10) +#define AHB_TO_MBUS_WIN_INTEREG_REG 0x20080 + +/* Window Control Register */ +/* AHB_TO_MBUS_WIN_CTRL_REG (ATMWCR)*/ +#define ATMWCR_WIN_ENABLE BIT0 /* Window Enable */ + +#define ATMWCR_WIN_TARGET_OFFS 4 /* The target interface associated + with this window*/ +#define ATMWCR_WIN_TARGET_MASK (0xf << ATMWCR_WIN_TARGET_OFFS) + +#define ATMWCR_WIN_ATTR_OFFS 8 /* The target interface attributes + Associated with this window */ +#define ATMWCR_WIN_ATTR_MASK (0xff << ATMWCR_WIN_ATTR_OFFS) + + +/* +Used with the Base register to set the address window size and location +Must be programed from LSB to MSB as sequence of 1’s followed +by sequence of 0’s. The number of 1’s specifies the size of the window +in 64 KB granularity (e.g. a value of 0x00FF specifies 256 = 16 MB). + +NOTE: A value of 0x0 specifies 64KB size. +*/ +#define ATMWCR_WIN_SIZE_OFFS 16 /* Window Size */ +#define ATMWCR_WIN_SIZE_MASK (0xffff << ATMWCR_WIN_SIZE_OFFS) +#define ATMWCR_WIN_SIZE_ALIGNMENT 0x10000 + +/* Window Base Register */ +/* AHB_TO_MBUS_WIN_BASE_REG (ATMWBR) */ + +/* +Used with the size field to set the address window size and location. +Corresponds to transaction address[31:16] +*/ +#define ATMWBR_BASE_OFFS 16 /* Base Address */ +#define ATMWBR_BASE_MASK (0xffff << ATMWBR_BASE_OFFS) +#define ATMWBR_BASE_ALIGNMENT 0x10000 + +/* Window Remap Low Register */ +/* AHB_TO_MBUS_WIN_REMAP_LOW_REG (ATMWRLR) */ + +/* +Used with the size field to specifies address bits[31:0] to be driven to +the target interface.: +target_addr[31:16] = (addr[31:16] & size[15:0]) | (remap[31:16] & ~size[15:0]) +*/ +#define ATMWRLR_REMAP_LOW_OFFS 16 /* Remap Address */ +#define ATMWRLR_REMAP_LOW_MASK (0xffff << ATMWRLR_REMAP_LOW_OFFS) +#define ATMWRLR_REMAP_LOW_ALIGNMENT 0x10000 + +/* Window Remap High Register */ +/* AHB_TO_MBUS_WIN_REMAP_HIGH_REG (ATMWRHR) */ + +/* +Specifies address bits[63:32] to be driven to the target interface. +target_addr[63:32] = (RemapHigh[31:0] +*/ +#define ATMWRHR_REMAP_HIGH_OFFS 0 /* Remap Address */ +#define ATMWRHR_REMAP_HIGH_MASK (0xffffffff << ATMWRHR_REMAP_HIGH_OFFS) + +#if defined(MV_88F1181) || defined(MV_88F1281) +/*******************************************/ +/* Mbus Arbiter Registers */ +/*******************************************/ + +#define MBUS_ARBITER_CTRL_REG 0x10200 +#define MBUS_ARBITER_LOW_REG 0x10204 +#define MBUS_ARBITER_HIGH_REG 0x10208 + + + +/*******************************************/ +/* Mbus Arbiter Registers */ +/*******************************************/ + +/* MBus Arbiter Control register */ +/* MBUS_ARBITER_CTRL_REG (MACR)*/ + +#define MACR_ARB_REQ_CTRL_EN_OFFS 0 +#define MACR_ARB_REQ_CTRL_EN (1 << MACR_ARB_REQ_CTRL_EN_OFFS) + +#define MACR_ARB_ARM_TOP_OFFS 1 +#define MACR_ARB_ARM_TOP (1 << MACR_ARB_ARM_TOP_OFFS) + +#define MACR_ARB_TARGET_OFFS 3 +#define MACR_ARB_TARGET_MASK BIT3 +#define MACR_ARB_TARGET_FIXED (1 << MACR_ARB_TARGET_OFFS) + + + +/* Mbus Arbiter Low Register */ +/* MBUS_ARBITER_LOW_REG (MRLR) */ + +#define MRLR_LOW_ARB_OFFS(num) (num*4) +#define MRLR_LOW_ARB_MASK(num) (0xf << MRLR_LOW_ARB_OFFS(num)) +#define MRLR_SLICE_NUM 8 + +/* Mbus Arbiter High Register */ +/* MBUS_ARBITER_HIGH_REG (MRHR) */ + +#define MRHR_HIGH_ARB_OFFS(num) ((8-num)*4) +#define MRHR_HIGH_ARB_MASK(num) (0xf << MRHR_HIGH_ARB_OFFS(num)) +#define MRHR_SLICE_NUM 8 + +#endif /* defined(MV_88F1181) || defined(MV_88F1281) */ + +#endif /* __INCmvAhbToMbusRegsh */ + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.c new file mode 100644 index 0000000..92b69e0 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.c @@ -0,0 +1,1040 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +/* includes */ +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/sys/mvCpuIfConfig.h" +#include "cpu/mvCpu.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "mvSysHwConfig.h" + +/*#define MV_DEBUG*/ +/* defines */ + +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + + + +/* locals */ +/* static functions */ +static MV_BOOL cpuTargetWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin); + +MV_TARGET sampleAtResetTargetArray[] = BOOT_TARGETS_NAME_ARRAY; +/******************************************************************************* +* mvCpuIfInit - Initialize Controller CPU interface +* +* DESCRIPTION: +* This function initialize Controller CPU interface: +* 1. Set CPU interface configuration registers. +* 2. Set CPU master Pizza arbiter control according to static +* configuration described in configuration file. +* 3. Opens CPU address decode windows. DRAM windows are assumed to be +* already set (auto detection). +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap) +{ + MV_U32 regVal; + MV_TARGET target; + MV_ADDR_WIN addrWin; + + if (cpuAddrWinMap == NULL) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. cpuAddrWinMap == NULL\n")); + return MV_ERROR; + } + + /* Set ARM Configuration register */ + regVal = MV_REG_READ(CPU_CONFIG_REG); + regVal &= ~CPU_CONFIG_DEFAULT_MASK; + regVal |= CPU_CONFIG_DEFAULT; + MV_REG_WRITE(CPU_CONFIG_REG,regVal); + + +#if defined(MV_CPU_ADDRESS_DECODE_WA) + /* Work around for CPU address decode BUG */ + MV_REG_BIT_RESET(AHB_TO_MBUS_WIN_CTRL_REG(6), ATMWCR_WIN_ENABLE); +#endif + + /* First disable all CPU target windows */ + for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) + { + if ((MV_TARGET_IS_DRAM(target))||(target == INTER_REGS)) + { + continue; + } + +#if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PCI(target)) + { + continue; + } +#endif + +#if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PEX(target)) + { + continue; + } +#endif +#if defined(MV_RUN_FROM_FLASH) + /* Don't disable the boot device. */ + if (target == DEV_BOOCS) + { + continue; + } +#endif /* MV_RUN_FROM_FLASH */ + mvCpuIfTargetWinEnable(MV_CHANGE_BOOT_CS(target),MV_FALSE); + } + +#if defined(MV_RUN_FROM_FLASH) + /* Resize the bootcs windows before other windows, because this */ + /* window is enabled and will cause an overlap if not resized. */ + target = DEV_BOOCS; + + if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); + return MV_ERROR; + } + + addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; + addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; + if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) + { + DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", + cpuAddrWinMap[target].winNum)); + } + +#endif /* MV_RUN_FROM_FLASH */ + + /* Go through all targets in user table until table terminator */ + for (target = 0; cpuAddrWinMap[target].enable != TBL_TERM; target++) + { + +#if defined(MV_RUN_FROM_FLASH) + if (target == DEV_BOOCS) + { + continue; + } +#endif /* MV_RUN_FROM_FLASH */ + + /* if DRAM auto sizing is used do not initialized DRAM target windows, */ + /* assuming this already has been done earlier. */ +#ifdef MV_DRAM_AUTO_SIZE + if (MV_TARGET_IS_DRAM(target)) + { + continue; + } +#endif + +#if defined(MV_MEM_OVER_PCI_WA) || defined(MV_UART_OVER_PCI_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PCI(target)) + { + continue; + } +#endif + +#if defined(MV_MEM_OVER_PEX_WA) || defined(MV_UART_OVER_PEX_WA) + /* If the target PEX or PCI and memory is over PEX or PCI we don't touch this CPU windows */ + if (MV_TARGET_IS_PEX(target)) + { + continue; + } +#endif + /* If the target attribute is the same as the boot device attribute */ + /* then it's stays disable */ + if (MV_TARGET_IS_AS_BOOT(target)) + { + continue; + } + + if((0 == cpuAddrWinMap[target].addrWin.size) || + (DIS == cpuAddrWinMap[target].enable)) + + { + if (MV_OK != mvCpuIfTargetWinEnable(target, MV_FALSE)) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinEnable fail\n")); + return MV_ERROR; + } + + } + else + { + if (MV_OK != mvCpuIfTargetWinSet(target, &cpuAddrWinMap[target])) + { + DB(mvOsPrintf("mvCpuIfInit:ERR. mvCpuIfTargetWinSet fail\n")); + return MV_ERROR; + } + + addrWin.baseLow = cpuAddrWinMap[target].addrWin.baseLow; + addrWin.baseHigh = cpuAddrWinMap[target].addrWin.baseHigh; + if (0xffffffff == mvAhbToMbusWinRemap(cpuAddrWinMap[target].winNum ,&addrWin)) + { + DB(mvOsPrintf("mvCpuIfInit:WARN. mvAhbToMbusWinRemap can't remap winNum=%d\n", + cpuAddrWinMap[target].winNum)); + } + + + } + } + + return MV_OK; + + +} +/******************************************************************************* +* mvCpuIfTargetWinSet - Set CPU-to-peripheral target address window +* +* DESCRIPTION: +* This function sets a peripheral target (e.g. SDRAM bank0, PCI0_MEM0) +* address window, also known as address decode window. +* A new address decode window is set for specified target address window. +* If address decode window parameter structure enables the window, +* the routine will also enable the target window, allowing CPU to access +* the target window. +* +* INPUT: +* target - Peripheral target enumerator. +* pAddrDecWin - CPU target window data structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if CPU target window was set correctly, MV_ERROR in case of +* address window overlapps with other active CPU target window or +* trying to assign 36bit base address while CPU does not support that. +* The function returns MV_NOT_SUPPORTED, if the target is unsupported. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_U32 existingWinNum; + MV_DRAM_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinSet: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* 2) Check if the requested window overlaps with current windows */ + if (MV_TRUE == cpuTargetWinOverlap(target, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvCpuIfTargetWinSet: ERR. Target %d overlap\n", target); + return MV_BAD_PARAM; + } + + if (MV_TARGET_IS_DRAM(target)) + { + /* copy relevant data to MV_DRAM_DEC_WIN structure */ + addrDecWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; + addrDecWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; + addrDecWin.addrWin.size = pAddrDecWin->addrWin.size; + addrDecWin.enable = pAddrDecWin->enable; + + + if (mvDramIfWinSet(target,&addrDecWin) != MV_OK); + { + mvOsPrintf("mvCpuIfTargetWinSet: mvDramIfWinSet Failed\n"); + return MV_ERROR; + } + + } + else + { + /* copy relevant data to MV_AHB_TO_MBUS_DEC_WIN structure */ + decWin.addrWin.baseLow = pAddrDecWin->addrWin.baseLow; + decWin.addrWin.baseHigh = pAddrDecWin->addrWin.baseHigh; + decWin.addrWin.size = pAddrDecWin->addrWin.size; + decWin.enable = pAddrDecWin->enable; + decWin.target = target; + + existingWinNum = mvAhbToMbusWinTargetGet(target); + + /* check if there is already another Window configured + for this target */ + if ((existingWinNum < MAX_AHB_TO_MBUS_WINS )&& + (existingWinNum != pAddrDecWin->winNum)) + { + /* if we want to enable the new winow number + passed by the user , then the old one should + be disabled */ + if (MV_TRUE == pAddrDecWin->enable) + { + /* be sure it is disabled */ + mvAhbToMbusWinEnable(existingWinNum , MV_FALSE); + } + } + + if (mvAhbToMbusWinSet(pAddrDecWin->winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinSet: mvAhbToMbusWinSet Failed\n"); + return MV_ERROR; + } + + } + + return MV_OK; +} + +/******************************************************************************* +* mvCpuIfTargetWinGet - Get CPU-to-peripheral target address window +* +* DESCRIPTION: +* Get the CPU peripheral target address window. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* pAddrDecWin - CPU target window information data structure. +* +* RETURN: +* MV_OK if target exist, MV_ERROR otherwise. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin) +{ + + MV_U32 winNum=0xffffffff; + MV_AHB_TO_MBUS_DEC_WIN decWin; + MV_DRAM_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinGet: target %d is Illigal\n", target); + return MV_ERROR; + } + + if (MV_TARGET_IS_DRAM(target)) + { + if (mvDramIfWinGet(target,&addrDecWin) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: Failed to get window target %d\n", + target); + return MV_ERROR; + } + + /* copy relevant data to MV_CPU_DEC_WIN structure */ + pAddrDecWin->addrWin.baseLow = addrDecWin.addrWin.baseLow; + pAddrDecWin->addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pAddrDecWin->addrWin.size = addrDecWin.addrWin.size; + pAddrDecWin->enable = addrDecWin.enable; + pAddrDecWin->winNum = 0xffffffff; + + } + else + { + /* get the Window number associated with this target */ + + winNum = mvAhbToMbusWinTargetGet(target); + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + return MV_NO_SUCH; + + } + + if (mvAhbToMbusWinGet(winNum , &decWin) != MV_OK) + { + mvOsPrintf("%s: mvAhbToMbusWinGet Failed at winNum = %d\n", + __FUNCTION__, winNum); + return MV_ERROR; + + } + + /* copy relevant data to MV_CPU_DEC_WIN structure */ + pAddrDecWin->addrWin.baseLow = decWin.addrWin.baseLow; + pAddrDecWin->addrWin.baseHigh = decWin.addrWin.baseHigh; + pAddrDecWin->addrWin.size = decWin.addrWin.size; + pAddrDecWin->enable = decWin.enable; + pAddrDecWin->winNum = winNum; + + } + + + + + return MV_OK; +} + + +/******************************************************************************* +* mvCpuIfTargetWinEnable - Enable/disable a CPU address decode window +* +* DESCRIPTION: +* This function enable/disable a CPU address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling CPU accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* target - Peripheral target enumerator. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if protection window number was wrong, or the window +* overlapps other target window. +* +*******************************************************************************/ +MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target,MV_BOOL enable) +{ + MV_U32 winNum, temp; + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinEnable: target %d is Illigal\n", target); + return MV_ERROR; + } + + /* get the window and check if it exist */ + temp = mvCpuIfTargetWinGet(target, &addrDecWin); + if (MV_NO_SUCH == temp) + { + return (enable? MV_ERROR: MV_OK); + } + else if( MV_OK != temp) + { + mvOsPrintf("%s: ERR. Getting target %d failed.\n",__FUNCTION__, target); + return MV_ERROR; + } + + + /* check overlap */ + + if (MV_TRUE == enable) + { + if (MV_TRUE == cpuTargetWinOverlap(target, &addrDecWin.addrWin)) + { + DB(mvOsPrintf("%s: ERR. Target %d overlap\n",__FUNCTION__, target)); + return MV_ERROR; + } + + } + + + if (MV_TARGET_IS_DRAM(target)) + { + if (mvDramIfWinEnable(target , enable) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: mvDramIfWinEnable Failed at \n"); + return MV_ERROR; + + } + + } + else + { + /* get the Window number associated with this target */ + + winNum = mvAhbToMbusWinTargetGet(target); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + return (enable? MV_ERROR: MV_OK); + } + + if (mvAhbToMbusWinEnable(winNum , enable) != MV_OK) + { + mvOsPrintf("mvCpuIfTargetWinGet: Failed to enable window = %d\n", + winNum); + return MV_ERROR; + + } + + } + + return MV_OK; +} + + +/******************************************************************************* +* mvCpuIfTargetWinSizeGet - Get CPU target address window size +* +* DESCRIPTION: +* Get the size of CPU-to-peripheral target window. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit size. Function also returns '0' if window is closed. +* Function returns 0xFFFFFFFF in case of an error. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinSizeGet: target %d is Illigal\n", target); + return 0; + } + + /* Get the winNum window */ + if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinSizeGet:ERR. Getting target %d failed.\n", + target); + return 0; + } + + /* Check if window is enabled */ + if (addrDecWin.enable == MV_TRUE) + { + return (addrDecWin.addrWin.size); + } + else + { + return 0; /* Window disabled. return 0 */ + } +} + +/******************************************************************************* +* mvCpuIfTargetWinBaseLowGet - Get CPU target address window base low +* +* DESCRIPTION: +* CPU-to-peripheral target address window base is constructed of +* two parts: Low and high. +* This function gets the CPU peripheral target low base address. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit low base address. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + /* Get the target window */ + if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet:ERR. Getting target %d failed.\n", + target); + return 0xffffffff; + } + + if (MV_FALSE == addrDecWin.enable) + { + return 0xffffffff; + } + return (addrDecWin.addrWin.baseLow); +} + +/******************************************************************************* +* mvCpuIfTargetWinBaseHighGet - Get CPU target address window base high +* +* DESCRIPTION: +* CPU-to-peripheral target address window base is constructed of +* two parts: Low and high. +* This function gets the CPU peripheral target high base address. +* +* INPUT: +* target - Peripheral target enumerator +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit high base address. +* +*******************************************************************************/ +MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target) +{ + MV_CPU_DEC_WIN addrDecWin; + + target = MV_CHANGE_BOOT_CS(target); + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvCpuIfTargetWinBaseLowGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + /* Get the target window */ + if (MV_OK != mvCpuIfTargetWinGet(target, &addrDecWin)) + { + mvOsPrintf("mvCpuIfTargetWinBaseHighGet:ERR. Getting target %d failed.\n", + target); + return 0xffffffff; + } + + if (MV_FALSE == addrDecWin.enable) + { + return 0; + } + + return (addrDecWin.addrWin.baseHigh); +} + +#if defined(MV_INCLUDE_PEX) +/******************************************************************************* +* mvCpuIfPexRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* pexTarget - Peripheral target enumerator. Must be a PEX target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PEX one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 winNum; + + /* Check parameters */ + + if (mvCtrlPexMaxIfGet() > 1) + { + if ((!MV_TARGET_IS_PEX1(pexTarget))&&(!MV_TARGET_IS_PEX0(pexTarget))) + { + mvOsPrintf("mvCpuIfPexRemap: target %d is Illigal\n",pexTarget); + return 0xffffffff; + } + + } + else + { + if (!MV_TARGET_IS_PEX0(pexTarget)) + { + mvOsPrintf("mvCpuIfPexRemap: target %d is Illigal\n",pexTarget); + return 0xffffffff; + } + + } + + /* get the Window number associated with this target */ + winNum = mvAhbToMbusWinTargetGet(pexTarget); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvCpuIfPexRemap: mvAhbToMbusWinTargetGet Failed\n"); + return 0xffffffff; + + } + + return mvAhbToMbusWinRemap(winNum , pAddrDecWin); +} + +#endif + +#if defined(MV_INCLUDE_PCI) +/******************************************************************************* +* mvCpuIfPciRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* pciTarget - Peripheral target enumerator. Must be a PCI target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPciRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin) +{ + MV_U32 winNum; + + /* Check parameters */ + if (!MV_TARGET_IS_PCI(pciTarget)) + { + mvOsPrintf("mvCpuIfPciRemap: target %d is Illigal\n",pciTarget); + return 0xffffffff; + } + + /* get the Window number associated with this target */ + winNum = mvAhbToMbusWinTargetGet(pciTarget); + + if (winNum >= MAX_AHB_TO_MBUS_WINS) + { + mvOsPrintf("mvCpuIfPciRemap: mvAhbToMbusWinTargetGet Failed\n"); + return 0xffffffff; + + } + + return mvAhbToMbusWinRemap(winNum , pAddrDecWin); +} +#endif /* MV_INCLUDE_PCI */ + + +/******************************************************************************* +* mvCpuIfPciIfRemap - Set CPU remap register for address windows. +* +* DESCRIPTION: +* +* INPUT: +* pciTarget - Peripheral target enumerator. Must be a PCI target. +* pAddrDecWin - CPU target window information data structure. +* Note that caller has to fill in the base field only. The +* size field is ignored. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if target is not a PCI one, MV_OK otherwise. +* +*******************************************************************************/ +MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciIfTarget, MV_ADDR_WIN *pAddrDecWin) +{ +#if defined(MV_INCLUDE_PEX) + if (MV_TARGET_IS_PEX(pciIfTarget)) + { + return mvCpuIfPexRemap(pciIfTarget,pAddrDecWin); + } +#endif +#if defined(MV_INCLUDE_PCI) + + if (MV_TARGET_IS_PCI(pciIfTarget)) + { + return mvCpuIfPciRemap(pciIfTarget,pAddrDecWin); + } +#endif + return 0; +} + + + +/******************************************************************************* +* mvCpuIfTargetOfBaseAddressGet - Get the target according to base address +* +* DESCRIPTION: +* +* INPUT: +* baseAddress - base address to be checked +* +* OUTPUT: +* None. +* +* RETURN: +* the target number that baseAddress belongs to or MAX_TARGETS is not +* found +* +*******************************************************************************/ + +MV_TARGET mvCpuIfTargetOfBaseAddressGet(MV_U32 baseAddress) +{ + MV_CPU_DEC_WIN win; + MV_U32 target; + + for( target = 0; target < MAX_TARGETS; target++ ) + { + if( mvCpuIfTargetWinGet( target, &win ) == MV_OK ) + { + if( win.enable ) + { + if ((baseAddress >= win.addrWin.baseLow) && + (baseAddress < win.addrWin.baseLow + win.addrWin.size)) break; + } + } + else return MAX_TARGETS; + + } + + return target; +} +/******************************************************************************* +* cpuTargetWinOverlap - Detect CPU address decode windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case CPU address decode +* windows overlapps. +* This function detects CPU address decode windows overlapping of a +* specified target. The function does not check the target itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* target - Peripheral target enumerator. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlaps current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL cpuTargetWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 targetNum; + MV_CPU_DEC_WIN addrDecWin; + MV_STATUS status; + + + for(targetNum = 0; targetNum < MAX_TARGETS; targetNum++) + { +#if defined(MV_RUN_FROM_FLASH) + if(MV_TARGET_IS_AS_BOOT(target)) + { + if (MV_CHANGE_BOOT_CS(targetNum) == target) + continue; + } +#endif /* MV_RUN_FROM_FLASH */ + + /* don't check our target or illegal targets */ + if (targetNum == target) + { + continue; + } + + /* Get window parameters */ + status = mvCpuIfTargetWinGet(targetNum, &addrDecWin); + if(MV_NO_SUCH == status) + { + continue; + } + if(MV_OK != status) + { + DB(mvOsPrintf("cpuTargetWinOverlap: ERR. TargetWinGet failed\n")); + return MV_TRUE; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + DB(mvOsPrintf( + "cpuTargetWinOverlap: Required target %d overlap current %d\n", + target, targetNum)); + return MV_TRUE; + } + } + + return MV_FALSE; + +} + +/******************************************************************************* +* mvCpuIfAddDecShow - Print the CPU address decode map. +* +* DESCRIPTION: +* This function print the CPU address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvCpuIfAddDecShow(MV_VOID) +{ + MV_CPU_DEC_WIN win; + MV_U32 target; + mvOsOutput( "\n" ); + mvOsOutput( "CPU Interface\n" ); + mvOsOutput( "-------------\n" ); + + for( target = 0; target < MAX_TARGETS; target++ ) + { + + memset( &win, 0, sizeof(MV_CPU_DEC_WIN) ); + + mvOsOutput( "%s ",mvCtrlTargetNameGet(target)); + mvOsOutput( "...." ); + + if( mvCpuIfTargetWinGet( target, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "base %08x, ", win.addrWin.baseLow ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + + } + else + mvOsOutput( "disable\n" ); + } + else if( mvCpuIfTargetWinGet( target, &win ) == MV_NO_SUCH ) + { + mvOsOutput( "no such\n" ); + } + } +} + +/******************************************************************************* +* mvCpuIfEnablePex - Enable PCI Express. +* +* DESCRIPTION: +* This function Enable PCI Express. +* +* INPUT: +* pexIf - PEX interface number. +* pexType - MV_PEX_ROOT_COMPLEX - root complex device +* MV_PEX_END_POINT - end point device +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +#if defined(MV_INCLUDE_PEX) +MV_VOID mvCpuIfEnablePex(MV_U32 pexIf, MV_PEX_TYPE pexType) +{ + /* Set ARM Control and Status register */ +#if !defined(MV_88F6183) && !defined(MV_88F6183L) && !defined(MV_88F6082) + MV_U32 regVal; + regVal = MV_REG_READ(CPU_CTRL_STAT_REG); + regVal &= ~CPU_CTRL_STAT_DEFAULT_MASK; + regVal |= CPU_CTRL_STAT_DEFAULT; + MV_REG_WRITE(CPU_CTRL_STAT_REG,regVal); +#else + /* Set pex mode incase S@R not exist */ + if( pexType == MV_PEX_END_POINT) + { + MV_REG_BIT_RESET(PEX_CTRL_REG(pexIf),PXCR_DEV_TYPE_CTRL_MASK); + /* Change pex mode in capability reg */ + MV_REG_BIT_RESET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_CAPABILITY_REG), BIT22); + MV_REG_BIT_SET(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_CAPABILITY_REG), BIT20); + + } + else + { + MV_REG_BIT_SET(PEX_CTRL_REG(pexIf),PXCR_DEV_TYPE_CTRL_MASK); + } + + /* CPU config register Pex enable */ + MV_REG_BIT_RESET(CPU_CTRL_STAT_REG,CCSR_PCI_ACCESS_MASK); +#endif +} +#endif diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.h new file mode 100644 index 0000000..839995e --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIf.h @@ -0,0 +1,116 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfh +#define __INCmvCpuIfh + +/* includes */ +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIfRegs.h" +#include "ctrlEnv/sys/mvAhbToMbus.h" +#include "ddr1_2/mvDramIf.h" +#if defined(MV_INCLUDE_PEX) +#include "pci-if/mvPciIf.h" +#endif + +/* defines */ + +/* typedefs */ +/* This structure describes CPU interface address decode window */ +typedef struct _mvCpuIfDecWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_U32 winNum; /* Window Number in the AHB To Mbus bridge */ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_CPU_DEC_WIN; + + + +/* mvCpuIfLib.h API list */ + +/* mvCpuIfLib.h API list */ + +MV_STATUS mvCpuIfInit(MV_CPU_DEC_WIN *cpuAddrWinMap); +MV_STATUS mvCpuIfTargetWinSet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinGet(MV_TARGET target, MV_CPU_DEC_WIN *pAddrDecWin); +MV_STATUS mvCpuIfTargetWinEnable(MV_TARGET target,MV_BOOL enable); +MV_U32 mvCpuIfTargetWinSizeGet(MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseLowGet(MV_TARGET target); +MV_U32 mvCpuIfTargetWinBaseHighGet(MV_TARGET target); +MV_TARGET mvCpuIfTargetOfBaseAddressGet(MV_U32 baseAddress); +#if defined(MV_INCLUDE_PEX) +MV_U32 mvCpuIfPexRemap(MV_TARGET pexTarget, MV_ADDR_WIN *pAddrDecWin); +MV_VOID mvCpuIfEnablePex(MV_U32 pexIf, MV_PEX_TYPE pexType); +#endif +#if defined(MV_INCLUDE_PCI) +MV_U32 mvCpuIfPciRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin); +#endif +MV_U32 mvCpuIfPciIfRemap(MV_TARGET pciTarget, MV_ADDR_WIN *pAddrDecWin); + +MV_VOID mvCpuIfAddDecShow(MV_VOID); + + +#endif /* __INCmvCpuIfh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfConfig.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfConfig.h new file mode 100644 index 0000000..0e44e7d --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfConfig.h @@ -0,0 +1,138 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfconfigh +#define __INCmvCpuIfConfigh + +#include "mvSysHwConfig.h" +#include "mvCpuIfRegs.h" + +#if defined(MV_88F1181) + +/* CPU control register map */ +/* Set bits means value is about to change according to new value */ +#define CPU_CONFIG_DEFAULT_MASK (CCR_VEC_INIT_LOC_MASK | \ + CCR_AHB_ERROR_PROP_MASK) + + +#define CPU_CONFIG_DEFAULT (CCR_VEC_INIT_LOC_FF00 ) + +/* CPU Control and status defaults */ +#define CPU_CTRL_STAT_DEFAULT_MASK (CCSR_PCI_ACCESS_MASK) + + +#define CPU_CTRL_STAT_DEFAULT (CCSR_PCI_ACCESS_ENABLE) + +#else + +/* CPU control register map */ +/* Set bits means value is about to change according to new value */ +#define CPU_CONFIG_DEFAULT_MASK (CCR_VEC_INIT_LOC_MASK | \ + CCR_AHB_ERROR_PROP_MASK) + + +#define CPU_CONFIG_DEFAULT (CCR_VEC_INIT_LOC_FF00 ) + +/* CPU Control and status defaults */ +#define CPU_CTRL_STAT_DEFAULT_MASK (CCSR_PCI_ACCESS_MASK) + + +#define CPU_CTRL_STAT_DEFAULT (CCSR_PCI_ACCESS_ENABLE) + +/* Ratio options for CPU to DDR */ +#define CPU_2_DDR_CLK_1x1 1 +#define CPU_2_DDR_CLK_1x2 2 +#define CPU_2_DDR_CLK_1x3 3 +#define CPU_2_DDR_CLK_1x4 4 +#define CPU_2_DDR_CLK_1x5 5 +#define CPU_2_DDR_CLK_1x6 6 +#define CPU_2_DDR_CLK_1x7 7 + +/* Default values for CPU to Mbus-L DDR Interface Tick Driver and */ +/* CPU to Mbus-L Tick Sample fields in CPU config register */ +#define TICK_DRV_1x2 0 +#define TICK_SMPL_1x2 0 +#define TICK_DRV_1x3 1 +#define TICK_SMPL_1x3 2 +#define TICK_DRV_1x4 2 +#define TICK_SMPL_1x4 2 + +#define CPU_2_MBUSL_DDR_CLK_1x2 \ + ((TICK_DRV_1x2 << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x2 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)) +#define CPU_2_MBUSL_DDR_CLK_1x3 \ + ((TICK_DRV_1x3 << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x3 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)) +#define CPU_2_MBUSL_DDR_CLK_1x4 \ + ((TICK_DRV_1x4 << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) | \ + (TICK_SMPL_1x4 << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS)) + + +#define CPU_FTDLL_IC_CONFIG_DEFAULT 0x1b +#define CPU_FTDLL_DC_CONFIG_DEFAULT 0x2 +#endif /* #if defined(MV_88F1181) */ + + +#endif /* __INCmvCpuIfConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfInit.S b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfInit.S new file mode 100644 index 0000000..3415261 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfInit.S @@ -0,0 +1,191 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#define MV_ASMLANGUAGE +#include "mvOsAsm.h" +#include "mvBoardEnvSpec.h" +#include "mvCtrlEnvSpec.h" +#include "mvCpuIfConfig.h" +#include "pex/mvPexRegs.h" +#include "pci/mvPciRegs.h" +#include "mvCtrlEnvAsm.h" +#include "cpu/mvCpuArm.h" + + +/******************************************************************************* +* mvCpuIfPreInit - Make early initialization of CPU interface. +* +* DESCRIPTION: +* The function will initialize the CPU interface parameters that must +* be initialize before any BUS activity towards the DDR interface, +* which means it must be executed from ROM. Because of that, the function +* is implemented in assembly code. +* The function configure the following CPU config register parameters: +* 1) CPU2MbusLTickDrv +* 2) CPU2MbusLTickSample. +* NOTE: This function must be called AFTER the internal register +* base is modified to INTER_REGS_BASE. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +* r11 holds return function address. +*******************************************************************************/ + .extern _start + .extern _cpuARMDDRCLK + .globl _mvCpuIfPreInit +_mvCpuIfPreInit: + + mov r11, LR /* Save link register */ + + /* This function is for Orion2 B0 and up or TC90 only */ + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r4, r5); + + /* goto calcConfigReg if device is TC90 */ + ldr r5, =MV_1281_DEV_ID + cmp r4, r5 + beq calcConfigReg + + /* goto calcConfigReg if bigger than Orion2 A0*/ + ldr r5, =MV_5281_DEV_ID + cmp r4, r5 + bne done + + /* Return if Orion2 and device revision A0 */ + /* Read device revision */ + MV_CTRL_REV_GET_ASM(r4, r5); + cmp r4, #0 + beq done + +calcConfigReg: +#if defined(MV_RUN_FROM_FLASH) + /* Calc the absolute address of the _cpuARMDDRCLK[] in the boot flash */ + ldr r7, = _cpuARMDDRCLK + ldr r4, =_start + ldr r4, [r4] + sub r7, r7, r4 + ldr r4, = Lrom_start_of_data + ldr r4, [r4] + add r7, r4, r7 + + +#else + ldr r7, = _cpuARMDDRCLK + ldr r4, =_start /* r0 <- current position of code */ + ldr r5, =_TEXT_BASE /* test if we run from flash or RAM */ + cmp r4, r5 /* dont reloc during debug */ + beq dram + + /* Calc the absolute address of the _cpuARMDDRCLK[] in the boot flash */ + sub r7, r7, r4 + add r7, r7, #CFG_MONITOR_BASE +#endif + /* Get the "sample on reset" register */ +dram: MV_REG_READ_ASM (r4, r5, MPP_SAMPLE_AT_RESET) + ldr r5, =MSAR_ARMDDRCLCK_MASK + and r5, r4, r5 + mov r5, r5, LSR #MSAR_ARMDDRCLCK_OFFS + tst r4, #MSAR_ARMDDRCLCK_H_MASK + beq 1f + orr r5, r5, #BIT4 + +1: + ldr r4, =MV_CPU_ARM_CLK_ELM_SIZE + mul r5, r4, r5 + add r7, r7, r5 + add r7, r7, #MV_CPU_ARM_CLK_RATIO_OFF + ldr r5, [r7] + + ldr r4, =CPU_2_MBUSL_DDR_CLK_1x2 + cmp r5, #CPU_2_DDR_CLK_1x2 + beq setConfigReg + + ldr r4, =CPU_2_MBUSL_DDR_CLK_1x3 + cmp r5, #CPU_2_DDR_CLK_1x3 + beq setConfigReg + + ldr r4, =CPU_2_MBUSL_DDR_CLK_1x4 + cmp r5, #CPU_2_DDR_CLK_1x4 + beq setConfigReg + + /* Note; x4 and x5 ratios are not supported */ + ldr r4, =0 + +setConfigReg: + /* Read CPU Config register */ + MV_REG_READ_ASM (r7, r5, CPU_CONFIG_REG) + ldr r5, =~(CCR_CPU_2_MBUSL_TICK_DRV_MASK | CCR_CPU_2_MBUSL_TICK_SMPL_MASK) + and r7, r7, r5 /* Clear register fields */ + orr r7, r7, r4 /* Set the values according to the findings */ + MV_REG_WRITE_ASM (r7, r5, CPU_CONFIG_REG) + +done: + mov PC, r11 /* r11 is saved link register */ diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfRegs.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfRegs.h new file mode 100644 index 0000000..45870f7 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvCpuIfRegs.h @@ -0,0 +1,246 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCmvCpuIfRegsh +#define __INCmvCpuIfRegsh + +/****************************************/ +/* ARM Control and Status Registers Map */ +/****************************************/ + +#define CPU_CONFIG_REG 0x20100 +#define CPU_CTRL_STAT_REG 0x20104 +#define CPU_RSTOUTN_MASK_REG 0x20108 +#define CPU_SYS_SOFT_RST_REG 0x2010C +#define CPU_AHB_MBUS_CAUSE_INT_REG 0x20110 +#define CPU_AHB_MBUS_MASK_INT_REG 0x20114 +#define CPU_FTDLL_CONFIG_REG 0x20120 + + + +/* ARM Configuration register */ +/* CPU_CONFIG_REG (CCR) */ + + +/* Reset vector location */ +#define CCR_VEC_INIT_LOC_OFFS 1 +#define CCR_VEC_INIT_LOC_MASK BIT1 +/* reset at 0x00000000 */ +#define CCR_VEC_INIT_LOC_0000 (0 << CCR_VEC_INIT_LOC_OFFS) +/* reset at 0xFFFF0000 */ +#define CCR_VEC_INIT_LOC_FF00 (1 << CCR_VEC_INIT_LOC_OFFS) + + +#define CCR_AHB_ERROR_PROP_OFFS 2 +#define CCR_AHB_ERROR_PROP_MASK BIT2 +/* Erros are not propogated to AHB */ +#define CCR_AHB_ERROR_PROP_NO_INDICATE (0 << CCR_AHB_ERROR_PROP_OFFS) +/* Erros are propogated to AHB */ +#define CCR_AHB_ERROR_PROP_INDICATE (1 << CCR_AHB_ERROR_PROP_OFFS) + + +#define CCR_ENDIAN_INIT_OFFS 3 +#define CCR_ENDIAN_INIT_MASK BIT3 +#define CCR_ENDIAN_INIT_LITTLE (0 << CCR_ENDIAN_INIT_OFFS) +#define CCR_ENDIAN_INIT_BIG (1 << CCR_ENDIAN_INIT_OFFS) + + +#define CCR_INCR_EN_OFFS 4 +#define CCR_INCR_EN_MASK BIT4 +#define CCR_INCR_EN BIT4 + + +#define CCR_MMU_DISABLED_OFFS 5 +#define CCR_MMU_DISABLED_MASK (1 << CCR_MMU_DISABLED_OFFS) +#define CCR_MMU_ENABLED (0 << CCR_MMU_DISABLED_OFFS) +#define CCR_MMU_DISABLED (1 << CCR_MMU_DISABLED_OFFS) +/* Orion2 B0 and up */ +#define CCR_CPU_2_MBUSL_TICK_DRV_OFFS 8 +#define CCR_CPU_2_MBUSL_TICK_DRV_MASK (0xF << CCR_CPU_2_MBUSL_TICK_DRV_OFFS) +#define CCR_CPU_2_MBUSL_TICK_SMPL_OFFS 12 +#define CCR_CPU_2_MBUSL_TICK_SMPL_MASK (0xF << CCR_CPU_2_MBUSL_TICK_SMPL_OFFS) +#define CCR_ICACH_PREF_BUF_ENABLE BIT16 +#define CCR_DCACH_PREF_BUF_ENABLE BIT17 + + + + + +/* ARM Control and Status register */ +/* CPU_CTRL_STAT_REG (CCSR) */ + + +/* +This is used to block PCI express\PCI from access Socrates/Feroceon GP +while ARM boot is still in progress +*/ + +#define CCSR_PCI_ACCESS_OFFS 0 +#define CCSR_PCI_ACCESS_MASK BIT0 +#define CCSR_PCI_ACCESS_ENABLE (0 << CCSR_PCI_ACCESS_OFFS) +#define CCSR_PCI_ACCESS_DISBALE (1 << CCSR_PCI_ACCESS_OFFS) + +#define CCSR_ARM_RESET BIT1 +#define CCSR_SELF_INT BIT2 +#define CCSR_BIG_ENDIAN BIT3 + + +/* RSTOUTn Mask Register */ +/* CPU_RSTOUTN_MASK_REG (CRMR) */ + +#define CRMR_PEX_RST_OUT_OFFS 0 +#define CRMR_PEX_RST_OUT_MASK BIT0 +#define CRMR_PEX_RST_OUT_ENABLE (1 << CRMR_PEX_RST_OUT_OFFS) +#define CRMR_PEX_RST_OUT_DISABLE (0 << CRMR_PEX_RST_OUT_OFFS) + +#define CRMR_WD_RST_OUT_OFFS 1 +#define CRMR_WD_RST_OUT_MASK BIT1 +#define CRMR_WD_RST_OUT_ENABLE (1 << CRMR_WD_RST_OUT_OFFS) +#define CRMR_WD_RST_OUT_DISBALE (0 << CRMR_WD_RST_OUT_OFFS) + +#define CRMR_SOFT_RST_OUT_OFFS 2 +#define CRMR_SOFT_RST_OUT_MASK BIT2 +#define CRMR_SOFT_RST_OUT_ENABLE (1 << CRMR_SOFT_RST_OUT_OFFS) +#define CRMR_SOFT_RST_OUT_DISBALE (0 << CRMR_SOFT_RST_OUT_OFFS) + +/* System Software Reset Register */ +/* CPU_SYS_SOFT_RST_REG (CSSRR) */ + +#define CSSRR_SYSTEM_SOFT_RST BIT0 + +/* AHB to Mbus Bridge Interrupt Cause Register*/ +/* CPU_AHB_MBUS_CAUSE_INT_REG (CAMCIR) */ + +#define CAMCIR_ARM_SELF_INT BIT0 +#define CAMCIR_ARM_TIMER0_INT_REQ BIT1 +#define CAMCIR_ARM_TIMER1_INT_REQ BIT2 +#define CAMCIR_ARM_WD_TIMER_INT_REQ BIT3 + + +/* AHB to Mbus Bridge Interrupt Mask Register*/ +/* CPU_AHB_MBUS_MASK_INT_REG (CAMMIR) */ + +#define CAMCIR_ARM_SELF_INT_OFFS 0 +#define CAMCIR_ARM_SELF_INT_MASK BIT0 +#define CAMCIR_ARM_SELF_INT_EN (1 << CAMCIR_ARM_SELF_INT_OFFS) +#define CAMCIR_ARM_SELF_INT_DIS (0 << CAMCIR_ARM_SELF_INT_OFFS) + + +#define CAMCIR_ARM_TIMER0_INT_REQ_OFFS 1 +#define CAMCIR_ARM_TIMER0_INT_REQ_MASK BIT1 +#define CAMCIR_ARM_TIMER0_INT_REQ_EN (1 << CAMCIR_ARM_TIMER0_INT_REQ_OFFS) +#define CAMCIR_ARM_TIMER0_INT_REQ_DIS (0 << CAMCIR_ARM_TIMER0_INT_REQ_OFFS) + +#define CAMCIR_ARM_TIMER1_INT_REQ_OFFS 2 +#define CAMCIR_ARM_TIMER1_INT_REQ_MASK BIT2 +#define CAMCIR_ARM_TIMER1_INT_REQ_EN (1 << CAMCIR_ARM_TIMER1_INT_REQ_OFFS) +#define CAMCIR_ARM_TIMER1_INT_REQ_DIS (0 << CAMCIR_ARM_TIMER1_INT_REQ_OFFS) + +#define CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS 3 +#define CAMCIR_ARM_WD_TIMER_INT_REQ_MASK BIT3 +#define CAMCIR_ARM_WD_TIMER_INT_REQ_EN (1 << CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS) +#define CAMCIR_ARM_WD_TIMER_INT_REQ_DIS (0 << CAMCIR_ARM_WD_TIMER_INT_REQ_OFFS) + +/* CPU FTDLL Config register (CFCR) fields */ +#define CFCR_FTDLL_ICACHE_TAG_OFFS 0 +#define CFCR_FTDLL_ICACHE_TAG_MASK (0x7F << CFCR_FTDLL_ICACHE_TAG_OFFS) +#define CFCR_FTDLL_DCACHE_TAG_OFFS 8 +#define CFCR_FTDLL_DCACHE_TAG_MASK (0x7F << CFCR_FTDLL_DCACHE_TAG_OFFS) +#define CFCR_FTDLL_OVERWRITE_ENABLE (1 << 15) +/* For Orion 2 D2 only */ +#define CFCR_MRVL_CPU_ID_OFFS 16 +#define CFCR_MRVL_CPU_ID_MASK (0x1 << CFCR_MRVL_CPU_ID_OFFS) +#define CFCR_ARM_CPU_ID (0x0 << CFCR_MRVL_CPU_ID_OFFS) +#define CFCR_MRVL_CPU_ID (0x1 << CFCR_MRVL_CPU_ID_OFFS) +#define CFCR_VFP_SUB_ARC_NUM_OFFS 7 +#define CFCR_VFP_SUB_ARC_NUM_MASK (0x1 << CFCR_VFP_SUB_ARC_NUM_OFFS) +#define CFCR_VFP_SUB_ARC_NUM_1 (0x0 << CFCR_VFP_SUB_ARC_NUM_OFFS) +#define CFCR_VFP_SUB_ARC_NUM_2 (0x1 << CFCR_VFP_SUB_ARC_NUM_OFFS) + + +/*******************************************/ +/* Main Interrupt Controller Registers Map */ +/*******************************************/ + +#define CPU_MAIN_INT_CAUSE_REG 0x20200 +#define CPU_MAIN_IRQ_MASK_REG 0x20204 +#define CPU_MAIN_FIQ_MASK_REG 0x20208 +#define CPU_ENPOINT_MASK_REG 0x2020C + + + +/*******************************************/ +/* ARM Doorbell Registers Map */ +/*******************************************/ + +#define CPU_HOST_TO_ARM_DRBL_REG 0x20400 +#define CPU_HOST_TO_ARM_MASK_REG 0x20404 +#define CPU_ARM_TO_HOST_DRBL_REG 0x20408 +#define CPU_ARM_TO_HOST_MASK_REG 0x2040C + + + +#endif /* __INCmvCpuIfRegsh */ + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.c new file mode 100644 index 0000000..d79aaaa --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.c @@ -0,0 +1,321 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#include "mvSysAudio.h" + +/******************************************************************************* +* mvAudioWinSet - Set AUDIO target address window +* +* DESCRIPTION: +* This function sets a peripheral target (e.g. SDRAM bank0, PCI_MEM0) +* address window, also known as address decode window. +* After setting this target window, the AUDIO will be able to access the +* target within the address window. +* +* INPUT: +* winNum - AUDIO target address decode window number. +* pAddrDecWin - AUDIO target window data structure. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if address window overlapps with other address decode windows. +* MV_BAD_PARAM if base address is invalid parameter or target is +* unknown. +* +*******************************************************************************/ +MV_STATUS mvAudioWinSet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttribs; + MV_DEC_REGS decRegs; + + /* Parameter checking */ + if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvAudioWinSet:Error setting AUDIO window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = 0; + decRegs.sizeReg = 0; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~MV_AUDIO_WIN_ATTR_MASK; + decRegs.sizeReg |= (targetAttribs.attrib << MV_AUDIO_WIN_ATTR_OFFSET); + + /* set target ID */ + decRegs.sizeReg &= ~MV_AUDIO_WIN_TARGET_MASK; + decRegs.sizeReg |= (targetAttribs.targetId << MV_AUDIO_WIN_TARGET_OFFSET); + + if (pAddrDecWin->enable == MV_TRUE) + { + decRegs.sizeReg |= MV_AUDIO_WIN_ENABLE_MASK; + } + else + { + decRegs.sizeReg &= ~MV_AUDIO_WIN_ENABLE_MASK; + } + + MV_REG_WRITE( MV_AUDIO_WIN_CTRL_REG(winNum), decRegs.sizeReg); + MV_REG_WRITE( MV_AUDIO_WIN_BASE_REG(winNum), decRegs.baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvAudioWinGet - Get AUDIO peripheral target address window. +* +* DESCRIPTION: +* Get AUDIO peripheral target address window. +* +* INPUT: +* winNum - AUDIO target address decode window number. +* +* OUTPUT: +* pAddrDecWin - AUDIO target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvAudioWinGet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s : ERR. Invalid winNum %d\n", + __FUNCTION__, winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ( MV_AUDIO_WIN_BASE_REG(winNum) ); + decRegs.sizeReg = MV_REG_READ( MV_AUDIO_WIN_CTRL_REG(winNum) ); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) ) + { + mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & MV_AUDIO_WIN_ATTR_MASK) >> + MV_AUDIO_WIN_ATTR_OFFSET; + targetAttrib.targetId = (decRegs.sizeReg & MV_AUDIO_WIN_TARGET_MASK) >> + MV_AUDIO_WIN_TARGET_OFFSET; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if(decRegs.sizeReg & MV_AUDIO_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + return MV_OK; +} +/******************************************************************************* +* mvAudioAddrDecShow - Print the AUDIO address decode map. +* +* DESCRIPTION: +* This function print the AUDIO address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvAudioAddrDecShow(MV_VOID) +{ + + MV_AUDIO_DEC_WIN win; + int i; + + + mvOsOutput( "\n" ); + mvOsOutput( "AUDIO:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < MV_AUDIO_MAX_ADDR_DECODE_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_AUDIO_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvAudioWinGet( i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + + +/******************************************************************************* +* mvAudioWinInit - Initialize the integrated AUDIO target address window. +* +* DESCRIPTION: +* Initialize the AUDIO peripheral target address window. +* +* INPUT: +* +* +* OUTPUT: +* +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvAudioInit(MV_VOID) +{ + int winNum; + MV_AUDIO_DEC_WIN audioWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_U32 status; + + mvAudioHalInit(); + + /* Initiate Audio address decode */ + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_AUDIO_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_U32 regVal = MV_REG_READ(MV_AUDIO_WIN_CTRL_REG(winNum)); + regVal &= ~MV_AUDIO_WIN_ENABLE_MASK; + MV_REG_WRITE(MV_AUDIO_WIN_CTRL_REG(winNum), regVal); + } + + for(winNum = 0; winNum < MV_AUDIO_MAX_ADDR_DECODE_WIN; winNum++) + { + + /* We will set the Window to DRAM_CS0 in default */ + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(SDRAM_CS0, + &cpuAddrDecWin); + + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + audioWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + audioWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + audioWin.addrWin.size = cpuAddrDecWin.addrWin.size; + audioWin.enable = MV_TRUE; + audioWin.target = SDRAM_CS0; + + if(MV_OK != mvAudioWinSet(winNum, &audioWin)) + { + return MV_ERROR; + } + } + } + + return MV_OK; +} + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.h new file mode 100644 index 0000000..f59eb9a --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysAudio.h @@ -0,0 +1,123 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVSysAudioH +#define __INCMVSysAudioH + +#include "mvCommon.h" +#include "audio/mvAudio.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/sys/mvCpuIf.h" + +/***********************************/ +/* Audio Address Decoding registers*/ +/***********************************/ + +#define MV_AUDIO_MAX_ADDR_DECODE_WIN 2 +#define MV_AUDIO_RECORD_WIN_NUM 0 +#define MV_AUDIO_PLAYBACK_WIN_NUM 1 + +#define MV_AUDIO_WIN_CTRL_REG(win) (AUDIO_REG_BASE + 0xA04 + ((win)<<3)) +#define MV_AUDIO_WIN_BASE_REG(win) (AUDIO_REG_BASE + 0xA00 + ((win)<<3)) + +#define MV_AUDIO_RECORD_WIN_CTRL_REG MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_RECORD_WIN_NUM) +#define MV_AUDIO_RECORD_WIN_BASE_REG MV_AUDIO_WIN_BASE_REG(MV_AUDIO_RECORD_WIN_NUM) +#define MV_AUDIO_PLAYBACK_WIN_CTRL_REG MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_PLAYBACK_WIN_NUM) +#define MV_AUDIO_PLAYBACK_WIN_BASE_REG MV_AUDIO_WIN_BASE_REG(MV_AUDIO_PLAYBACK_WIN_NUM) + + +/* BITs in Windows 0-3 Control and Base Registers */ +#define MV_AUDIO_WIN_ENABLE_BIT 0 +#define MV_AUDIO_WIN_ENABLE_MASK (1<= 2) +MV_TARGET tdmaAddrDecPrioTable[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif + + TBL_TERM +}; + +/******************************************************************************* +* mvCesaWinGet - Get TDMA target address window. +* +* DESCRIPTION: +* Get TDMA target address window. +* +* INPUT: +* winNum - TDMA target address decode window number. +* +* OUTPUT: +* pDecWin - TDMA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +static MV_STATUS mvCesaWinGet(MV_U32 winNum, MV_DEC_WIN *pDecWin) +{ + MV_DEC_WIN_PARAMS winParam; + MV_U32 sizeReg, baseReg; + + /* Parameter checking */ + if (winNum >= MV_CESA_TDMA_ADDR_DEC_WIN) + { + mvOsPrintf("%s : ERR. Invalid winNum %d\n", + __FUNCTION__, winNum); + return MV_NOT_SUPPORTED; + } + + baseReg = MV_REG_READ( MV_CESA_TDMA_BASE_ADDR_REG(winNum) ); + sizeReg = MV_REG_READ( MV_CESA_TDMA_WIN_CTRL_REG(winNum) ); + + /* Check if window is enabled */ + if(sizeReg & MV_CESA_TDMA_WIN_ENABLE_MASK) + { + pDecWin->enable = MV_TRUE; + + /* Extract window parameters from registers */ + winParam.targetId = (sizeReg & MV_CESA_TDMA_WIN_TARGET_MASK) >> MV_CESA_TDMA_WIN_TARGET_OFFSET; + winParam.attrib = (sizeReg & MV_CESA_TDMA_WIN_ATTR_MASK) >> MV_CESA_TDMA_WIN_ATTR_OFFSET; + winParam.size = (sizeReg & MV_CESA_TDMA_WIN_SIZE_MASK) >> MV_CESA_TDMA_WIN_SIZE_OFFSET; + winParam.baseAddr = (baseReg & MV_CESA_TDMA_WIN_BASE_MASK); + + /* Translate the decode window parameters to address decode struct */ + if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin)) + { + mvOsPrintf("Failed to translate register parameters to CESA address" \ + " decode window structure\n"); + return MV_ERROR; + } + } + else + { + pDecWin->enable = MV_FALSE; + } + return MV_OK; +} + +/******************************************************************************* +* cesaWinOverlapDetect - Detect CESA TDMA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case TDMA address decode +* windows overlapps. +* This function detects TDMA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE - if the given address window overlap current address +* decode map, +* MV_FALSE - otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS cesaWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_CESA_TDMA_ADDR_DEC_WIN) + { + mvOsPrintf("mvCesaTdmaWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == cesaWinOverlapDetect(winNum, &pDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) + { + mvOsPrintf("mvCesaTdmaWinSet: Error setting CESA TDMA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pDecWin->target), + pDecWin->addrWin.baseLow, + pDecWin->addrWin.size); + return MV_ERROR; + } + + if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams)) + { + mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* set Size, Attributes and TargetID */ + sizeReg = (((winParams.targetId << MV_CESA_TDMA_WIN_TARGET_OFFSET) & MV_CESA_TDMA_WIN_TARGET_MASK) | + ((winParams.attrib << MV_CESA_TDMA_WIN_ATTR_OFFSET) & MV_CESA_TDMA_WIN_ATTR_MASK) | + ((winParams.size << MV_CESA_TDMA_WIN_SIZE_OFFSET) & MV_CESA_TDMA_WIN_SIZE_MASK)); + + if (pDecWin->enable == MV_TRUE) + { + sizeReg |= MV_CESA_TDMA_WIN_ENABLE_MASK; + } + else + { + sizeReg &= ~MV_CESA_TDMA_WIN_ENABLE_MASK; + } + + /* Update Base value */ + baseReg = (winParams.baseAddr & MV_CESA_TDMA_WIN_BASE_MASK); + + MV_REG_WRITE( MV_CESA_TDMA_WIN_CTRL_REG(winNum), sizeReg); + MV_REG_WRITE( MV_CESA_TDMA_BASE_ADDR_REG(winNum), baseReg); + + return MV_OK; +} + + +static MV_STATUS mvCesaTdmaAddrDecInit (void) +{ + MV_U32 winNum; + MV_STATUS status; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_DEC_WIN cesaWin; + MV_U32 winPrioIndex = 0; + + /* First disable all address decode windows */ + for(winNum=0; winNum= 2 */ + + + + +MV_STATUS mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle) +{ + MV_U32 cesaCryptEngBase; + MV_CPU_DEC_WIN addrDecWin; + + if(sizeof(MV_CESA_SRAM_MAP) > MV_CESA_SRAM_SIZE) + { + mvOsPrintf("mvCesaInit: Wrong SRAM map - %ld > %d\n", + sizeof(MV_CESA_SRAM_MAP), MV_CESA_SRAM_SIZE); + return MV_FAIL; + } + + if (mvCpuIfTargetWinGet(CRYPT_ENG, &addrDecWin) == MV_OK) + cesaCryptEngBase = addrDecWin.addrWin.baseLow; + else + { + mvOsPrintf("mvCesaInit: ERR. mvCpuIfTargetWinGet failed\n"); + return MV_ERROR; + } + +#if (MV_CESA_VERSION >= 2) + mvCesaTdmaAddrDecInit(); +#endif /* MV_CESA_VERSION >= 2 */ + + return mvCesaHalInit(numOfSession, queueDepth, pSramBase, cesaCryptEngBase, + osHandle); + +} diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysCesa.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysCesa.h new file mode 100644 index 0000000..73bcdc5 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysCesa.h @@ -0,0 +1,100 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __mvSysCesa_h__ +#define __mvSysCesa_h__ + + +#include "mvCommon.h" +#include "cesa/mvCesa.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "ctrlEnv/sys/mvCpuIf.h" + +/***************************** TDMA Registers *************************************/ + +#define MV_CESA_TDMA_ADDR_DEC_WIN 4 + +#define MV_CESA_TDMA_BASE_ADDR_REG(win) (MV_CESA_TDMA_REG_BASE + 0xa00 + (win<<3)) + +#define MV_CESA_TDMA_WIN_CTRL_REG(win) (MV_CESA_TDMA_REG_BASE + 0xa04 + (win<<3)) + +#define MV_CESA_TDMA_WIN_ENABLE_BIT 0 +#define MV_CESA_TDMA_WIN_ENABLE_MASK (1 << MV_CESA_TDMA_WIN_ENABLE_BIT) + +#define MV_CESA_TDMA_WIN_TARGET_OFFSET 4 +#define MV_CESA_TDMA_WIN_TARGET_MASK (0xf << MV_CESA_TDMA_WIN_TARGET_OFFSET) + +#define MV_CESA_TDMA_WIN_ATTR_OFFSET 8 +#define MV_CESA_TDMA_WIN_ATTR_MASK (0xff << MV_CESA_TDMA_WIN_ATTR_OFFSET) + +#define MV_CESA_TDMA_WIN_SIZE_OFFSET 16 +#define MV_CESA_TDMA_WIN_SIZE_MASK (0xFFFF << MV_CESA_TDMA_WIN_SIZE_OFFSET) + +#define MV_CESA_TDMA_WIN_BASE_OFFSET 16 +#define MV_CESA_TDMA_WIN_BASE_MASK (0xFFFF << MV_CESA_TDMA_WIN_BASE_OFFSET) + + +MV_STATUS mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle); + +#endif diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysGbe.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysGbe.c new file mode 100644 index 0000000..b00d221 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysGbe.c @@ -0,0 +1,660 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "ctrlEnv/sys/mvSysGbe.h" + + + +typedef struct _mvEthDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_ETH_DEC_WIN; + +MV_TARGET ethAddrDecPrioTap[] = +{ +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif +#if defined(MV_INCLUDE_PCI) + PCI0_MEM, +#endif +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_DEVICE_CS0) + DEVICE_CS0, +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + DEVICE_CS1, +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + DEVICE_CS2, +#endif +#if defined(MV_INCLUDE_DEVICE_CS3) + DEVICE_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_IO, +#endif +#if defined(MV_INCLUDE_PCI) + PCI0_IO, +#endif + TBL_TERM +}; + +static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin); +static MV_STATUS mvEthWinSet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); +static MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin); + + +/******************************************************************************* +* mvEthWinInit - Initialize ETH address decode windows +* +* DESCRIPTION: +* This function initialize ETH window decode unit. It set the +* default address decode windows of the unit. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR if setting fail. +*******************************************************************************/ +/* Configure EthDrv memory map registes. */ +MV_STATUS mvEthWinInit (int port) +{ + MV_U32 winNum, status, winPrioIndex=0, i, regVal=0; + MV_ETH_DEC_WIN ethWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + static MV_U32 accessProtReg = 0; + +#if (MV_ETH_VERSION <= 1) + static MV_BOOL isFirst = MV_TRUE; + + if(isFirst == MV_FALSE) + { + MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(port), accessProtReg); + return MV_OK; + } + isFirst = MV_FALSE; +#endif /* MV_GIGA_ETH_VERSION */ + + /* Initiate Ethernet address decode */ + + /* First disable all address decode windows */ + for(winNum=0; winNum= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == ethWinOverlapDetect(port, winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvEthWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvEthWinSet: Error setting Ethernet window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + + decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); + decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvEthWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.baseReg &= ~ETH_WIN_ATTR_MASK; + decRegs.baseReg |= targetAttribs.attrib << ETH_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.baseReg &= ~ETH_WIN_TARGET_MASK; + decRegs.baseReg |= targetAttribs.targetId << ETH_WIN_TARGET_OFFS; + + /* for the safe side we disable the window before writing the new + values */ + mvEthWinEnable(port, winNum, MV_FALSE); + MV_REG_WRITE(ETH_WIN_BASE_REG(port, winNum), decRegs.baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(ETH_WIN_SIZE_REG(port, winNum), decRegs.sizeReg); + + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvEthWinEnable(port, winNum, MV_TRUE); + } + + return MV_OK; +} + +/******************************************************************************* +* mvETHWinGet - Get dma peripheral target address window. +* +* DESCRIPTION: +* Get ETH peripheral target address window. +* +* INPUT: +* winNum - ETH to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - ETH target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum)); + decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (decRegs.baseReg & ETH_WIN_ATTR_MASK) >> ETH_WIN_ATTR_OFFS; + targetAttrib.targetId = + (decRegs.baseReg & ETH_WIN_TARGET_MASK) >> ETH_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (~(MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port))) & (1 << winNum) ) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvEthWinEnable - Enable/disable a ETH to target address window +* +* DESCRIPTION: +* This function enable/disable a ETH to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling ETH accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - ETH to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvEthWinEnable(int port, MV_U32 winNum,MV_BOOL enable) +{ + MV_ETH_DEC_WIN addrDecWin; + + /* Parameter checking */ + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthTargetWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvEthWinGet(port, winNum, &addrDecWin)) + { + mvOsPrintf("mvEthTargetWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == ethWinOverlapDetect(port, winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_RESET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); + } + else + { /* Overlap detected */ + mvOsPrintf("mvEthTargetWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { /* Disable address decode target window */ + MV_REG_BIT_SET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum)); + } + return MV_OK; +} + +/******************************************************************************* +* mvEthWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* window number +* +*******************************************************************************/ +MV_U32 mvEthWinTargetGet(int port, MV_TARGET target) +{ + MV_ETH_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + + for (winNum=0; winNum= mvCtrlEthMaxPortGet()) + { + mvOsPrintf("mvEthProtWinSet:ERR. Invalid port number %d\n", portNo); + return MV_ERROR; + } + + if (winNum >= ETH_MAX_DECODE_WIN) + { + mvOsPrintf("mvEthProtWinSet:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) + { + mvOsPrintf("mvEthProtWinSet:ERR. Inv access param %d\n", access); + return MV_ERROR; + } + /* Read current protection register */ + protReg = MV_REG_READ(ETH_ACCESS_PROTECT_REG(portNo)); + + /* Clear protection window field */ + protReg &= ~(ETH_PROT_WIN_MASK(winNum)); + + /* Set new protection field value */ + protReg |= (access << (ETH_PROT_WIN_OFFS(winNum))); + + /* Write protection register back */ + MV_REG_WRITE(ETH_ACCESS_PROTECT_REG(portNo), protReg); + + return MV_OK; +} + +/******************************************************************************* +* ethWinOverlapDetect - Detect ETH address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case ETH address decode +* windows overlapps. +* This function detects ETH address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex; + MV_ETH_DEC_WIN addrDecWin; + + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(ETH_BASE_ADDR_ENABLE_REG(port)); + + for (winNumIndex=0; winNumIndex= IDMA_MAX_ADDR_DEC_WIN) + { + mvOsPrintf("mvDmaWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == dmaWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvDmaWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvDmaWinSet: Error setting IDMA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + + decRegs.baseReg = MV_REG_READ(IDMA_BASE_ADDR_REG(winNum)); + decRegs.sizeReg = MV_REG_READ(IDMA_SIZE_REG(winNum)); + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvDmaWinSet: mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + +#if defined(MV_INCLUDE_CESA) + /* See BTS Nastore #19.*/ + /* To access Tunit SRAM from IDMA use targetId = 0x5 */ + /* To access Tunit SRAM from the CPU use targetId = 0x9 */ + if(pAddrDecWin->target == CRYPT_ENG) + targetAttribs.targetId = 5; +#endif /* defined(MV_INCLUDE_CESA) */ + + /* set attributes */ + decRegs.baseReg &= ~IDMA_WIN_ATTR_MASK; + decRegs.baseReg |= targetAttribs.attrib << IDMA_WIN_ATTR_OFFS; + /* set target ID */ + decRegs.baseReg &= ~IDMA_WIN_TARGET_MASK; + decRegs.baseReg |= targetAttribs.targetId << IDMA_WIN_TARGET_OFFS; + + /* for the safe side we disable the window before writing the new + values */ + mvDmaWinEnable(winNum,MV_FALSE); + + MV_REG_WRITE(IDMA_BASE_ADDR_REG(winNum), decRegs.baseReg); + + /* Write to address decode Size Register */ + MV_REG_WRITE(IDMA_SIZE_REG(winNum), decRegs.sizeReg); + + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvDmaWinEnable(winNum, MV_TRUE); + } + + return MV_OK; +} + +/******************************************************************************* +* mvDmaWinGet - Get dma peripheral target address window. +* +* DESCRIPTION: +* Get IDMA peripheral target address window. +* +* INPUT: +* winNum - IDMA to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - IDMA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvDmaWinGet(MV_U32 winNum, MV_DMA_DEC_WIN *pAddrDecWin) +{ + + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= IDMA_MAX_ADDR_DEC_WIN) + { + mvOsPrintf("mvDmaWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(IDMA_BASE_ADDR_REG(winNum)); + decRegs.sizeReg = MV_REG_READ(IDMA_SIZE_REG(winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvDmaWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (decRegs.baseReg & IDMA_WIN_ATTR_MASK) >> IDMA_WIN_ATTR_OFFS; + targetAttrib.targetId = + (decRegs.baseReg & IDMA_WIN_TARGET_MASK) >> IDMA_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (~(MV_REG_READ(IDMA_BASE_ADDR_ENABLE_REG)) & (IBAER_ENABLE(winNum))) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvDmaWinEnable - Enable/disable a DMA to target address window +* +* DESCRIPTION: +* This function enable/disable a DMA to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling DMA accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - IDMA to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvDmaWinEnable(MV_U32 winNum,MV_BOOL enable) +{ + MV_DMA_DEC_WIN addrDecWin; + + /* Parameter checking */ + if (winNum >= IDMA_MAX_ADDR_DEC_WIN) + { + mvOsPrintf("mvDmaWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvDmaWinGet(winNum, &addrDecWin)) + { + mvOsPrintf("mvDmaWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == dmaWinOverlapDetect(winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_RESET(IDMA_BASE_ADDR_ENABLE_REG, IBAER_ENABLE(winNum)); + } + else + { /* Overlap detected */ + mvOsPrintf("mvDmaWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { /* Disable address decode target window */ + MV_REG_BIT_SET(IDMA_BASE_ADDR_ENABLE_REG, IBAER_ENABLE(winNum)); + } + return MV_OK; +} + +/******************************************************************************* +* mvDmaWinTargetGet - Get Window number associated with target +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* window number +* +*******************************************************************************/ +MV_U32 mvDmaWinTargetGet(MV_TARGET target) +{ + MV_DMA_DEC_WIN decWin; + MV_U32 winNum; + + /* Check parameters */ + if (target >= MAX_TARGETS) + { + mvOsPrintf("mvDmaWinTargetGet: target %d is Illigal\n", target); + return 0xffffffff; + } + for (winNum = 0; winNum < IDMA_MAX_ADDR_DEC_WIN ; winNum++) + { + if (mvDmaWinGet(winNum,&decWin) != MV_OK) + { + mvOsPrintf("mvDmaWinTargetGet: mvDmaWinGet returned error\n"); + return 0xffffffff; + } + if (decWin.enable == MV_TRUE) + { + if (decWin.target == target) + { + return winNum; + } + } + } + return 0xFFFFFFFF; +} + +/******************************************************************************* +* mvDmaProtWinSet - Set access protection of IDMA to target window. +* +* DESCRIPTION: +* Each IDMA channel can be configured with access attributes for each +* of the IDMA to target windows (address decode windows). This +* function sets access attributes to a given window for the given channel. +* +* INPUTS: +* chan - IDMA channel number. See MV_DMA_CHANNEL enumerator. +* winNum - IDMA to target address decode window number. +* access - IDMA access rights. See MV_ACCESS_RIGHTS enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_ERROR in case window number is invalid or access right reserved. +* +*******************************************************************************/ +MV_STATUS mvDmaProtWinSet (MV_U32 chan, MV_U32 winNum, MV_ACCESS_RIGHTS access) +{ + MV_U32 protReg; + + /* Parameter checking */ + if ((chan >= MV_IDMA_MAX_CHAN) || (winNum >= IDMA_MAX_ADDR_DEC_WIN)) + { + mvOsPrintf("mvDmaProtWinSet:ERR. Invalid chan number %d\n", chan); + return MV_ERROR; + } + if((access == ACC_RESERVED) || (access >= MAX_ACC_RIGHTS)) + { + mvOsPrintf("mvDmaProtWinSet:ERR. Inv access param %d\n", access); + return MV_ERROR; + } + /* Read current protection register */ + protReg = MV_REG_READ(IDMA_ACCESS_PROTECT_REG(chan)); + + /* Clear protection window field */ + protReg &= ~(ICAPR_PROT_WIN_MASK(winNum)); + + /* Set new protection field value */ + protReg |= (access << (ICAPR_PROT_WIN_OFFS(winNum))); + + /* Write protection register back */ + MV_REG_WRITE(IDMA_ACCESS_PROTECT_REG(chan), protReg); + + return MV_OK; +} + +/******************************************************************************* +* mvDmaOverrideSet - Set DMA target window override +* +* DESCRIPTION: +* The address override feature enables additional address decoupling. +* For example, it allows the use of the same source and destination +* addresses while the source is targeted to one interface and +* destination to a second interface. +* DMA source/destination/next descriptor addresses can be override per +* address decode windows 1, 2 and 3 only. +* This function set override parameters per DMA channel. It access +* DMA control register low. +* +* INPUT: +* chan - IDMA channel number. See MV_DMA_CHANNEL enumerator. +* winNum - Override window numver. +* Note: 1) Not all windows can override. +* 2) Window '0' means disable override. +* override - Type of override. See MV_DMA_OVERRIDE enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM in case window can not perform override. +* +*******************************************************************************/ +MV_STATUS mvDmaOverrideSet(MV_U32 chan, MV_U32 winNum, MV_DMA_OVERRIDE override) +{ + MV_U32 ctrlLowReg; + + /* Parameter checking */ + if ((chan >= MV_IDMA_MAX_CHAN) || (winNum >= IDMA_MAX_OVERRIDE_WIN)) + { + mvOsPrintf("mvDmaOverrideSet:ERR. Invalid chan num %d\n", chan); + return MV_ERROR; + } + /* Read control register */ + ctrlLowReg = MV_REG_READ(IDMA_CTRL_LOW_REG(chan)); + + switch (override) + { + case (DMA_SRC_ADDR): + ctrlLowReg &= ~ICCLR_OVRRD_SRC_MASK; /* Clear SRC field */ + ctrlLowReg |= ICCLR_OVRRD_SRC_BAR(winNum); /* Set reg field */ + break; + case (DMA_DST_ADDR): + ctrlLowReg &= ~ICCLR_OVRRD_DST_MASK; /* Clear DST field */ + ctrlLowReg |= ICCLR_OVRRD_DST_BAR(winNum); /* Set reg field */ + break; + case (DMA_NEXT_DESC): + ctrlLowReg &= ~ICCLR_OVRRD_NDSC_MASK; /* Clear N_Desc field*/ + ctrlLowReg |= ICCLR_OVRRD_NDSC_BAR(winNum); /* Set reg field */ + break; + default: + { + mvOsPrintf("mvDmaOverrideSet:ERR. Inv override param%d\n",override); + return MV_BAD_PARAM; + } + } + /* Write control word back */ + MV_REG_WRITE(IDMA_CTRL_LOW_REG(chan), ctrlLowReg); + + return MV_OK; +} + +/******************************************************************************* +* mvDmaPciRemap - Set DMA remap register for PCI address windows. +* +* DESCRIPTION: +* The PCI interface supports 64-bit addressing. Four of the eight +* address windows have an upper 32-bit address register. To access the +* PCI bus with 64-bit addressing cycles (DAC cycles), this function +* assigns one (or more) of these four windows to target the PCI bus. +* The address generated on the PCI bus is composed of the window base +* address and the High Remap register. +* +* INPUT: +* winNum - IDMA to target address decode window number. Only 0 - 3. +* addrHigh - upper 32-bit address. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if window number is not between 0 and 3. +* +*******************************************************************************/ +MV_STATUS mvDmaPciRemap(MV_U32 winNum, MV_U32 addrHigh) +{ + /* Parameter checking */ + if (winNum >= IDMA_MAX_OVERRIDE_WIN) + { + mvOsPrintf("mvDmaPciRemap:ERR. Invalid window num %d\n", winNum); + return MV_BAD_PARAM; + } + + MV_REG_WRITE(IDMA_HIGH_ADDR_REMAP_REG(winNum), addrHigh); + + return MV_OK; +} + +/******************************************************************************* +* dmaWinOverlapDetect - Detect DMA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case DMA address decode +* windows overlapps. +* This function detects DMA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS dmaWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex; + MV_DMA_DEC_WIN addrDecWin; + + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(IDMA_BASE_ADDR_ENABLE_REG); + + for (winNumIndex = 0; winNumIndex < IDMA_MAX_ADDR_DEC_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + + /* Do not check disabled windows */ + if (baseAddrEnableReg & (IBAER_ENABLE(winNumIndex))) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvDmaWinGet(winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("dmaWinOverlapDetect: ERR. TargetWinGet failed\n")); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + return MV_FALSE; +} + +/******************************************************************************* +* mvDmaAddrDecShow - Print the DMA address decode map. +* +* DESCRIPTION: +* This function print the DMA address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvDmaAddrDecShow(MV_VOID) +{ + + MV_DMA_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "DMA:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < IDMA_MAX_ADDR_DEC_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_DMA_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvDmaWinGet( i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysIdma.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysIdma.h new file mode 100644 index 0000000..5a2a70c --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysIdma.h @@ -0,0 +1,142 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCmvSysIdmah +#define __INCmvSysIdmah + +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* General IDMA */ +#define IDMA_MAX_ADDR_DEC_WIN 8 /* Maximum address decode windows */ +#define IDMA_MAX_OVERRIDE_WIN 4 /* Maximum address override windows */ + +/* IDMA Address Decoding Base and size Registers */ +#define IDMA_BASE_ADDR_REG(winNum) (0x60a00 + ((winNum) * 8)) +#define IDMA_SIZE_REG(winNum) (0x60a04 + ((winNum) * 8)) + +/* IDMA Address Decoding High Address Remap,. Note that only window 0 - 3 */ +/* has remap capabilities */ +#define IDMA_HIGH_ADDR_REMAP_REG(winNum) (0x60a60 + ((winNum) * 4)) + +/* IDMA Base Addres enable register*/ +#define IDMA_BASE_ADDR_ENABLE_REG 0x60a80 + +/* IDMA Access Protection Registers */ +#define IDMA_ACCESS_PROTECT_REG(chan) (0x60a70 + ((chan) * 4)) + /* IDMA Headers Retarget Registers */ +#define IDMA_HEADERS_RETARGET_CTRL_REG 0x60a84 +#define IDMA_HEADERS_RETARGET_BASE_REG 0x60a88 + + +/* Base Addr reg */ +#define IDMA_WIN_TARGET_OFFS 0 /* The target interface associated with window*/ +#define IDMA_WIN_TARGET_MASK (0xf << IDMA_WIN_TARGET_OFFS) +#define IDMA_WIN_ATTR_OFFS 8 /* The target attributes Associated with window*/ +#define IDMA_WIN_ATTR_MASK (0xff << IDMA_WIN_ATTR_OFFS) + +/* IDMA Base Address Enable Register (IBAER) */ +#define IBAER_ENABLE_OFFS 0 +#define IBAER_ENABLE_MASK (0xFF << IBAER_ENABLE_OFFS) +#define IBAER_ENABLE(winNum) (1 << (winNum)) + +/* IDMA Channel Access Protect Register (ICAPR)*/ +#define ICAPR_PROT_NO_ACCESS NO_ACCESS_ALLOWED +#define ICAPR_PROT_READ_ONLY READ_ONLY +#define ICAPR_PROT_FULL_ACCESS FULL_ACCESS +#define ICAPR_PROT_WIN_OFFS(winNum) (2 * (winNum)) +#define ICAPR_PROT_WIN_MASK(winNum) (0x3 << ICAPR_PROT_WIN_OFFS(winNum)) + +/* This struct describes address decode override types */ +typedef enum _mvDmaOverride +{ + DMA_SRC_ADDR, /* Override source address */ + DMA_DST_ADDR, /* Override destination address */ + DMA_NEXT_DESC /* Override next descriptor address */ +}MV_DMA_OVERRIDE; + + +typedef struct _mvDmaDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_DMA_DEC_WIN; + +MV_STATUS mvDmaInit (MV_VOID); + +MV_STATUS mvDmaWinSet(MV_U32 winNum, MV_DMA_DEC_WIN *pAddrDecWin); +MV_STATUS mvDmaWinGet(MV_U32 winNum, MV_DMA_DEC_WIN *pAddrDecWin); +MV_STATUS mvDmaWinEnable(MV_U32 winNum,MV_BOOL enable); +MV_U32 mvDmaWinTargetGet(MV_TARGET target); + +MV_STATUS mvDmaProtWinSet (MV_U32 chan, MV_U32 winNum, MV_ACCESS_RIGHTS access); +MV_STATUS mvDmaOverrideSet(MV_U32 chan, MV_U32 winNum, MV_DMA_OVERRIDE override); +MV_STATUS mvDmaPciRemap(MV_U32 winNum, MV_U32 addrHigh); + +MV_VOID mvDmaAddrDecShow(MV_VOID); + +#endif /* __INCmvSysIdmaBarh */ + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.c new file mode 100644 index 0000000..e9f97b9 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.c @@ -0,0 +1,1490 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "ctrlEnv/sys/mvSysPci.h" + +/* PCI BARs registers offsets are inconsecutive. This struct describes BAR */ +/* register offsets and its function where its is located. */ +/* Also, PCI address remap registers offsets are inconsecutive. This struct */ +/* describes address remap register offsets */ +typedef struct _pciBarRegInfo +{ + MV_U32 funcNum; + MV_U32 baseLowRegOffs; + MV_U32 baseHighRegOffs; + MV_U32 sizeRegOffs; + MV_U32 remapLowRegOffs; + MV_U32 remapHighRegOffs; +}PCI_BAR_REG_INFO; + +typedef struct _pciBarStatus +{ + MV_PCI_BAR bar; + int enable; +}PCI_BAR_STATUS; + +PCI_BAR_STATUS pciBarStatusMap[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + {CS0_BAR, EN}, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + {CS1_BAR, EN}, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + {CS2_BAR, EN}, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + {CS3_BAR, EN}, +#endif +#if defined(MV_INCLUDE_DEVICE_CS0) + {DEVCS0_BAR, EN}, +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + {DEVCS1_BAR, EN}, +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + {DEVCS2_BAR, EN}, +#endif + {BOOTCS_BAR, EN}, + {MEM_INTER_REGS_BAR, EN}, + {IO_INTER_REGS_BAR, EN}, + {P2P_MEM0, DIS}, + {P2P_IO, DIS}, + {TBL_TERM, TBL_TERM} +}; + +/* PCI BAR table. Note that table entry number must match its target */ +/* enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* target which is represent by DEVICE_CS0 enumerator (4). */ +#if 0 +MV_PCI_BAR_WIN pciBarMap[] = +{ +/* base low base high size enable/disable */ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE }, EN}, + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE }, EN}, + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE }, EN}, + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE }, EN}, + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE }, EN}, + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE }, EN}, + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE }, EN}, + {{BOOTDEV_CS_BASE, 0, BOOTDEV_CS_SIZE }, EN}, + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE }, EN}, + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE }, EN}, + {{ 0xFFFFFFFF , 0, 0xFFFFFFFF }, DIS}, /* Ignore P2P */ + {{ 0xFFFFFFFF , 0, 0xFFFFFFFF }, DIS}, /* Ignore P2P */ + /* Table terminator */ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM} +}; +#endif + +/* Locals */ +static MV_U32 pciBurstBytes2Reg(MV_U32 size); +static MV_U32 pciBurstReg2Bytes(MV_U32 size); + +static MV_STATUS pciWinOverlapDetect(MV_U32 pciIf, MV_PCI_BAR bar, + MV_ADDR_WIN *pAddrWin); + +static MV_STATUS pciBarRegInfoGet(MV_U32 pciIf, MV_PCI_BAR bar, + PCI_BAR_REG_INFO *pBarRegInfo); + +static MV_STATUS pciWinIsValid(MV_U32 baseLow, MV_U32 size); + +/* Forward declarations */ +const MV_8* pciBarNameGet(MV_PCI_BAR bar); + +static MV_TARGET pciBarToTarget(MV_PCI_BAR bar) +{ + switch(bar) + { + #if defined(MV_INCLUDE_SDRAM_CS0) + case CS0_BAR: + return SDRAM_CS0; + #endif + #if defined(MV_INCLUDE_SDRAM_CS1) + case CS1_BAR: + return SDRAM_CS1; + #endif + #if defined(MV_INCLUDE_SDRAM_CS2) + case CS2_BAR: + return SDRAM_CS2; + #endif + #if defined(MV_INCLUDE_SDRAM_CS3) + case CS3_BAR: + return SDRAM_CS3; + #endif + #if defined(MV_INCLUDE_DEVICE_CS0) + case DEVCS0_BAR: + return DEVICE_CS0; + #endif + #if defined(MV_INCLUDE_DEVICE_CS1) + case DEVCS1_BAR: + return DEVICE_CS1; + #endif + #if defined(MV_INCLUDE_DEVICE_CS2) + case DEVCS2_BAR: + return DEVICE_CS2; + #endif + case BOOTCS_BAR: + return DEV_BOOCS; + case MEM_INTER_REGS_BAR: + case IO_INTER_REGS_BAR: + return INTER_REGS; + + default: + mvOsPrintf("pciBarToTarget: ERR. no such target\n"); + } + + return -1; + +} +/******************************************************************************* +* mvPciInit - Initialize PCI interfaces +* +* DESCRIPTION: +* This function initiate the PCI interface: +* 1) Set local bus number. In case of convential PCI it gets the bus +* number using mvPciLocalBusNumGet(). In case of PCI-X this +* information is read only. +* 2) Interface device number. In case of conventional PCI it gets the +* device number using mvPciLocalDevNumGet(). In case of PCI-X this +* information is read only. +* 3) PCI Arbiter if needed. +* 4) Enable Master and Slave on PCI interfaces. +* 5) Open PCI BARs according to default setting. +* Note that PCI bridge (P2P) is NOT initialized. +* 6) Enable CPU to PCI ordering. +* +* INPUT: +* +* pciIf - PCI interface number. +* localBus - Local Bus of the PCI interface to be set +* localDev - Local Dev of the PCI interface to be set +* bFirstCall - Indicates wether this is the first call of this +* function . +* +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM +* +*******************************************************************************/ +MV_STATUS mvPciInit(MV_U32 pciIf, MV_PCI_MOD pciIfmod) +{ + MV_PCI_BAR bar, barix; + MV_PCI_BAR_WIN dramDecWin; + MV_PCI_MODE pciMode; + MV_CPU_DEC_WIN addrDecWin; + MV_PCI_PROT_WIN pciProtWin; + MV_PCI_BAR_WIN pciBarMap[PCI_MAX_BARS]; + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciInit: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + + /* device and bus numbers */ + if (MV_OK != mvPciModeGet(pciIf, &pciMode)) + { + mvOsPrintf("mvPciInit: ERR. mvPciModeGet failed\n"); + return MV_ERROR; + } + + /* First disable all PCI target windows */ + for (bar = 0; bar < PCI_MAX_BARS; bar++) + { + mvPciTargetWinEnable(pciIf, bar, MV_FALSE); + } + + /* WA CQ 4382*/ + MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf) ,BIT15); + + /* Building in run time the pci bar mapping table */ + for (bar = 0; bar < PCI_MAX_BARS; bar++) + { + for(barix = 0 ;barix < PCI_MAX_BARS; barix++) + { + if(pciBarStatusMap[barix].bar == bar) + { + pciBarMap[bar].enable = pciBarStatusMap[barix].enable; + break; + } + } + + if(bar == MEM_INTER_REGS_BAR || bar == IO_INTER_REGS_BAR) + { + pciBarMap[bar].addrWin.baseLow = mvCpuIfTargetWinBaseLowGet(pciBarToTarget(bar)); + pciBarMap[bar].addrWin.baseHigh = mvCpuIfTargetWinBaseHighGet(pciBarToTarget(bar)); + pciBarMap[bar].addrWin.size = mvCpuIfTargetWinSizeGet(pciBarToTarget(bar)); + continue; + } + + if(bar == P2P_MEM0 || bar == P2P_IO) + { + pciBarMap[bar].addrWin.baseLow = 0xFFFFFFFF; + pciBarMap[bar].addrWin.baseHigh = 0; + pciBarMap[bar].addrWin.size = 0xFFFFFFFF; + continue; + } + + if (mvCpuIfTargetWinGet(pciBarToTarget(bar), &addrDecWin) == MV_OK) + { + pciBarMap[bar].addrWin.baseLow = addrDecWin.addrWin.baseLow; + pciBarMap[bar].addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pciBarMap[bar].addrWin.size = addrDecWin.addrWin.size; + if(addrDecWin.enable == MV_FALSE) + { + pciBarMap[bar].enable = DIS; + } + } + else + { + pciBarMap[bar].addrWin.baseLow = 0xFFFFFFFF; + pciBarMap[bar].addrWin.baseHigh = 0; + pciBarMap[bar].addrWin.size = 0xFFFFFFFF; + pciBarMap[bar].enable = DIS; + } + } + + /* finally fill table with TBL_TERM entry */ + bar = PCI_MAX_BARS - 1; + pciBarMap[bar].addrWin.baseLow = TBL_TERM; + pciBarMap[bar].addrWin.baseHigh = TBL_TERM; + pciBarMap[bar].addrWin.size = TBL_TERM; + pciBarMap[bar].enable = TBL_TERM; + + + /* Memory Mapped Internal Registers BAR can not be disabled. */ + /* Relocate its BAR first to avoid colisions with other BARs (e.g DRAM) */ + if (MV_OK != mvPciTargetWinSet(pciIf, MEM_INTER_REGS_BAR, + &pciBarMap[MEM_INTER_REGS_BAR])) + { + mvOsPrintf("mvPciInit: ERR. mvPciTargetWinSet failed\n"); + return MV_ERROR; + } + + /* Now, go through all targets in default table until table terminator */ + for (bar = 0; pciBarMap[bar].enable != TBL_TERM; bar++) + { + /* Skip the P2P BARs. They should be configured seperately */ + if (0xFFFFFFFF == pciBarMap[bar].addrWin.baseLow) + { + continue; + } + + + /* check if the size passed is zero ! */ + if (0 == pciBarMap[bar].addrWin.size) + { + /* disable the bar */ + mvPciTargetWinEnable(pciIf,bar,MV_FALSE); + continue; + } + + /* Get DRAM parameters from CPU interface */ + if (MV_PCI_BAR_IS_DRAM_BAR(bar)) + { + if (MV_OK != mvCpuIfTargetWinGet(MV_PCI_DRAM_BAR_TO_DRAM_TARGET(bar), + &addrDecWin)) + { + mvOsPrintf("mvPciInit:ERR. targetWinGet %d fail\n", bar); + return MV_ERROR; + } + + dramDecWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + dramDecWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + dramDecWin.addrWin.size = addrDecWin.addrWin.size; + dramDecWin.enable = addrDecWin.enable; + + if (MV_OK != mvPciTargetWinSet(pciIf, bar, &dramDecWin)) + { + mvOsPrintf("mvPciInit: ERR. mvPciTargetWinSet %d failed\n",bar); + return MV_ERROR; + } + + continue; + } + + if (MV_OK != mvPciTargetWinSet(pciIf, bar, &pciBarMap[bar])) + { + mvOsPrintf("mvPciInit: ERR. mvPciTargetWinSet %d failed\n", bar); + return MV_ERROR; + } + } + + MV_REG_BIT_SET(PCI_ADDR_DECODE_CONTROL_REG(pciIf), + PADCR_REMAP_REG_WR_DIS); + + + /* configure access control unit 0 to DDR to enhance performance */ + pciProtWin.addrWin.baseLow = 0; + pciProtWin.addrWin.baseHigh = 0; + pciProtWin.addrWin.size = mvDramIfSizeGet(); + pciProtWin.attributes.access = ALLOWED; + pciProtWin.attributes.write = ALLOWED; + pciProtWin.attributes.swapType = MV_BYTE_SWAP; + pciProtWin.attributes.readMaxBurst = 128; + pciProtWin.attributes.readBurst = 256; + pciProtWin.attributes.writeMaxBurst = 128; + pciProtWin.attributes.pciOrder = MV_FALSE; + pciProtWin.enable = MV_TRUE; + if( mvPciProtWinSet(pciIf, 0, &pciProtWin) != MV_OK ) + { + mvOsPrintf("mvPciInit: ERR. mvPciProtWinSet failed\n"); + return MV_ERROR; + } + + mvPciHalInit(pciIf, pciIfmod); + + return MV_OK; +} + + + +/******************************************************************************* +* mvPciTargetWinSet - Set PCI to peripheral target address window BAR +* +* DESCRIPTION: +* This function sets an address window from PCI to a peripheral +* target (e.g. SDRAM bank0, PCI_MEM0), also known as BARs. +* A new PCI BAR window is set for specified target address window. +* If address decode window parameter structure enables the window, +* the routine will also enable the target window, allowing PCI to access +* the target window. +* +* INPUT: +* pciIf - PCI interface number. +* bar - BAR to be accessed by slave. +* pAddrBarWin - PCI target window information data structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if PCI BAR target window was set correctly, MV_BAD_PARAM on bad params +* MV_ERROR otherwise +* (e.g. address window overlapps with other active PCI target window). +* +*******************************************************************************/ +MV_STATUS mvPciTargetWinSet(MV_U32 pciIf, + MV_PCI_BAR bar, + MV_PCI_BAR_WIN *pAddrBarWin) +{ + MV_U32 pciData; + MV_U32 sizeToReg; + MV_U32 size; + MV_U32 baseLow; + MV_U32 baseHigh; + MV_U32 localBus; + MV_U32 localDev; + PCI_BAR_REG_INFO barRegInfo; + + size = pAddrBarWin->addrWin.size; + baseLow = pAddrBarWin->addrWin.baseLow; + baseHigh = pAddrBarWin->addrWin.baseHigh; + + /* Parameter checking */ + if(pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciTargetWinSet: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + + if(bar >= PCI_MAX_BARS ) + { + mvOsPrintf("mvPciTargetWinSet: ERR. Illigal PCI BAR %d\n", bar); + return MV_BAD_PARAM; + } + + + /* if the address windows is disabled , we only disable the appropriare + pci bar and ignore other settings */ + + if (MV_FALSE == pAddrBarWin->enable) + { + MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); + return MV_OK; + } + + if (0 == pAddrBarWin->addrWin.size) + { + mvOsPrintf("mvPciTargetWinSet: ERR. Target %d can't be zero!\n",bar); + return MV_BAD_PARAM; + } + + /* Check if the window complies with PCI spec */ + if (MV_TRUE != pciWinIsValid(baseLow, size)) + { + mvOsPrintf("mvPciTargetWinSet: ERR. Target %d window invalid\n", bar); + return MV_BAD_PARAM; + } + + /* 2) Check if the requested window overlaps with current windows */ + if(MV_TRUE == pciWinOverlapDetect(pciIf, bar, &pAddrBarWin->addrWin)) + { + mvOsPrintf("mvPciTargetWinSet: ERR. Overlap detected for target %d\n", + bar); + return MV_BAD_PARAM; + } + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(size, PBBLR_BASE_ALIGNMET); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvPciTargetWinSet: ERR. Target BAR %d size invalid.\n",bar); + return MV_BAD_PARAM; + } + + localBus = mvPciLocalBusNumGet(pciIf); + localDev = mvPciLocalDevNumGet(pciIf); + + /* Get BAR register information */ + pciBarRegInfoGet(pciIf, bar, &barRegInfo); + + /* Internal register space size have no size register. Do not perform */ + /* size register assigment for this slave target */ + if (0 != barRegInfo.sizeRegOffs) + { + /* Update size register */ + MV_REG_WRITE(barRegInfo.sizeRegOffs, (sizeToReg << BAR_SIZE_OFFS)); + } + + /* Read current address */ + pciData = mvPciConfigRead(pciIf, localBus, localDev, barRegInfo.funcNum, + barRegInfo.baseLowRegOffs); + + /* Clear current address */ + pciData &= ~PBBLR_BASE_MASK; + pciData |= (baseLow & PBBLR_BASE_MASK); + + /* Write new address */ + mvPciConfigWrite(pciIf, localBus, localDev, barRegInfo.funcNum, + barRegInfo.baseLowRegOffs, pciData); + + /* Skip base high settings if the BAR has only base low (32-bit) */ + if (0 != barRegInfo.baseHighRegOffs) + { + mvPciConfigWrite(pciIf, localBus, localDev, barRegInfo.funcNum, + barRegInfo.baseHighRegOffs, baseHigh); + } + + /* Enable/disable the BAR */ + if (MV_TRUE == pAddrBarWin->enable) + { + MV_REG_BIT_RESET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); + } + else + { + MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); + } + + return MV_OK; +} + +/******************************************************************************* +* mvPciTargetWinGet - Get PCI to peripheral target address window +* +* DESCRIPTION: +* Get the PCI to peripheral target address window BAR. +* +* INPUT: +* pciIf - PCI interface number. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* pAddrBarWin - PCI target window information data structure. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciTargetWinGet(MV_U32 pciIf, MV_PCI_BAR bar, + MV_PCI_BAR_WIN *pAddrBarWin) +{ + MV_U32 size; + MV_U32 baseLow; + MV_U32 baseHigh; + MV_U32 localBus; + MV_U32 localDev; + MV_U32 barEnable; + PCI_BAR_REG_INFO barRegInfo; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciTargetWinGet: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + + if (bar >= PCI_MAX_BARS ) + { + mvOsPrintf("mvPciTargetWinGet: ERR. Illigal PCI BAR %d.\n", bar); + return MV_BAD_PARAM; + } + + localBus = mvPciLocalBusNumGet(pciIf); + localDev = mvPciLocalDevNumGet(pciIf); + + /* Get BAR register information */ + pciBarRegInfoGet(pciIf, bar, &barRegInfo); + + /* Reading Base Low bar */ + baseLow = mvPciConfigRead(pciIf, localBus, localDev, barRegInfo.funcNum, + barRegInfo.baseLowRegOffs); + + baseLow &= PBBLR_BASE_MASK; + + /* Skip base high if the BAR has only base low (32-bit) */ + if (0 != barRegInfo.baseHighRegOffs) + { + /* Reading Base High */ + baseHigh = mvPciConfigRead(pciIf, localBus, localDev, barRegInfo.funcNum, + barRegInfo.baseHighRegOffs); + } + else + { + baseHigh = 0; + } + + /* Internal register space size have no size register. Do not perform */ + /* size register assigment for this slave target */ + if (0 != barRegInfo.sizeRegOffs) + { + /* Reading bar size*/ + size = ctrlRegToSize( + (MV_REG_READ(barRegInfo.sizeRegOffs) >> PBSR_SIZE_OFFS), + PBBLR_BASE_ALIGNMET); + } + else + { + size = INTER_REGS_SIZE; + } + + /* Assign value to user struct */ + pAddrBarWin->addrWin.baseLow = baseLow; + pAddrBarWin->addrWin.baseHigh = baseHigh; + pAddrBarWin->addrWin.size = size; + + /* Check if window is enabled */ + barEnable = MV_REG_READ(PCI_BASE_ADDR_ENABLE_REG(pciIf)); + + if (~barEnable & (BARER_ENABLE(bar))) + { + pAddrBarWin->enable = MV_TRUE; + } + else + { + pAddrBarWin->enable = MV_FALSE; + } + + return MV_OK; +} + + +/******************************************************************************* +* mvPciTargetWinEnable - Enable/disable a PCI BAR window +* +* DESCRIPTION: +* This function enable/disable a PCI BAR window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling PCI accesses for that BAR (before enabling the +* window it is tested for overlapping). Otherwise, the window will +* be disabled. +* +* INPUT: +* pciIf - PCI interface number. +* bar - BAR to be accessed by slave. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciTargetWinEnable(MV_U32 pciIf, MV_PCI_BAR bar, MV_BOOL enable) +{ + MV_PCI_BAR_WIN barWin; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciTargetWinEnable: ERR. Invalid PCI interface %d\n", + pciIf); + return MV_BAD_PARAM; + } + + if (bar >= PCI_MAX_BARS ) + { + mvOsPrintf("mvPciTargetWinEnable: ERR. Illigal PCI BAR %d\n", bar); + return MV_BAD_PARAM; + } + + if (MV_TRUE == enable) + { /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvPciTargetWinGet(pciIf, bar, &barWin)) + { + mvOsPrintf("mvPciTargetWinEnable: ERR. targetWinGet fail\n"); + return MV_ERROR; + } + + /* Check for overlapping */ + if (MV_TRUE == pciWinOverlapDetect(pciIf, bar, &barWin.addrWin)) + + { /* Overlap detected */ + mvOsPrintf("mvPciTargetWinEnable: ERR. Overlap detected\n"); + return MV_ERROR; + } + else + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_RESET(PCI_BASE_ADDR_ENABLE_REG(pciIf),BARER_ENABLE(bar)); + } + } + else + { + /* Disable address decode target window */ + MV_REG_BIT_SET(PCI_BASE_ADDR_ENABLE_REG(pciIf), BARER_ENABLE(bar)); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvPciProtWinSet - Set PCI protection access window +* +* DESCRIPTION: +* This function sets a specified address window with access protection +* attributes. If protection structure enables the window the routine will +* also enable the protection window. +* +* INPUT: +* pciIf - PCI interface number. +* winNum - Protecion window number. +* pProtWin - Protection window structure. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciProtWinSet(MV_U32 pciIf, + MV_U32 winNum, + MV_PCI_PROT_WIN *pProtWin) +{ + MV_U32 protBaseLow; + MV_U32 protBaseHigh; + MV_U32 protSize; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciProtWinSet: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + if (winNum >= PCI_MAX_PROT_WIN) + { + mvOsPrintf("mvPciProtWinSet: ERR. Invalid window num %d\n", winNum); + return MV_BAD_PARAM; + } + + /* Check if the window complies with PCI spec */ + if (MV_TRUE != pciWinIsValid(pProtWin->addrWin.baseLow, + pProtWin->addrWin.size)) + { + mvOsPrintf("mvPciProtWinSet: ERR. Win base 0x%x unaligned to size 0x%x\n", + pProtWin->addrWin.baseLow, pProtWin->addrWin.size); + + return MV_BAD_PARAM; + } + + if (pProtWin->attributes.swapType >= SWAP_TYPE_MAX) + { + mvOsPrintf("mvPciProtWinSet: ERR. Swap parameter invalid %d\n", + pProtWin->attributes.swapType); + return MV_BAD_PARAM; + + } + + /* 1) Calculate protection window base low register value */ + protBaseLow = pProtWin->addrWin.baseLow; + + /* Setting the appropriate bits according to the passed values */ + if (MV_TRUE == pProtWin->enable) + { + protBaseLow |= PACBLR_EN; + } + else + { + protBaseLow &= ~PACBLR_EN; + } + + + /* Access protect */ + if (ALLOWED == pProtWin->attributes.access) + { + protBaseLow &= ~PACBLR_ACCPROT; + } + else + { + protBaseLow |= PACBLR_ACCPROT; + } + + /* Write Protect */ + if (ALLOWED == pProtWin->attributes.write) + { + protBaseLow &= ~PACBLR_WRPROT; + } + else + { + protBaseLow |= PACBLR_WRPROT; + } + + /* PCI slave Data Swap Control */ + protBaseLow |= (pProtWin->attributes.swapType << PACBLR_PCISWAP_OFFS); + + + /* Read Max Burst */ + if (( pciBurstBytes2Reg(pProtWin->attributes.readMaxBurst) << PACBLR_RDMBURST_OFFS) > PACBLR_RDMBURST_128BYTE) + { + mvOsPrintf("mvPciProtWinSet: ERR illigal read max burst\n"); + return MV_ERROR; + } + protBaseLow |= (pciBurstBytes2Reg(pProtWin->attributes.readMaxBurst) << PACBLR_RDMBURST_OFFS); + + + /* Typical PCI read transaction Size. Only valid for PCI conventional */ + if ((pciBurstBytes2Reg(pProtWin->attributes.readBurst) << PACBLR_RDSIZE_OFFS) > PACBLR_RDSIZE_256BYTE ) + { + mvOsPrintf("mvPciProtWinSet: ERR. illigal read size\n"); + return MV_ERROR; + } + protBaseLow |= (pciBurstBytes2Reg(pProtWin->attributes.readBurst) << PACBLR_RDSIZE_OFFS); + + + /* 2) Calculate protection window base high register value */ + protBaseHigh = pProtWin->addrWin.baseHigh; + + /* 3) Calculate protection window size register value */ + protSize = ctrlSizeToReg(pProtWin->addrWin.size, PACSR_SIZE_ALIGNMENT) << PACSR_SIZE_OFFS; + + + /* Write Max Burst */ + if ((pciBurstBytes2Reg(pProtWin->attributes.writeMaxBurst) << PACSR_WRMBURST_OFFS) > PACSR_WRMBURST_128BYTE ) + { + mvOsPrintf("mvPciProtWinSet: ERR illigal write max burst\n"); + return MV_ERROR; + } + protSize |= (pciBurstBytes2Reg(pProtWin->attributes.writeMaxBurst) << PACSR_WRMBURST_OFFS); + + /* Pci Order */ + if (MV_TRUE == pProtWin->attributes.pciOrder) + { + protSize |= PACSR_PCI_ORDERING; + } + else + { + protSize &= ~PACSR_PCI_ORDERING; + } + + /* Writing protection window walues into registers */ + MV_REG_WRITE(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum), protBaseLow); + MV_REG_WRITE(PCI_ACCESS_CTRL_BASEH_REG(pciIf,winNum), protBaseHigh); + MV_REG_WRITE(PCI_ACCESS_CTRL_SIZE_REG(pciIf,winNum), protSize); + + return MV_OK; +} +/******************************************************************************* +* mvPciProtWinGet - Get PCI protection access window +* +* DESCRIPTION: +* This function gets a specified address window and access protection +* attributes for a specific protection window . +* +* INPUT: +* pciIf - PCI interface number. +* winNum - Protecion window number. +* pProtWin - pointer to a Protection window structure. +* +* OUTPUT: +* pProtWin - Protection window structure. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciProtWinGet(MV_U32 pciIf, + MV_U32 winNum, + MV_PCI_PROT_WIN *pProtWin) +{ + MV_U32 protBaseLow; + MV_U32 protBaseHigh; + MV_U32 protSize; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciProtWinGet: ERR. Invalid PCI interface %d\n", pciIf); + return MV_BAD_PARAM; + } + if (winNum >= PCI_MAX_PROT_WIN) + { + mvOsPrintf("mvPciProtWinGet: ERR. Invalid window num %d\n", winNum); + return MV_BAD_PARAM; + } + + /* Writing protection window walues into registers */ + protBaseLow = MV_REG_READ(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum)); + protBaseHigh = MV_REG_READ(PCI_ACCESS_CTRL_BASEH_REG(pciIf,winNum)); + protSize = MV_REG_READ(PCI_ACCESS_CTRL_SIZE_REG(pciIf,winNum)); + + + /* 1) Get Protection Windows base low */ + pProtWin->addrWin.baseLow = protBaseLow & PACBLR_BASE_L_MASK; + + /* Get the appropriate protection attributes according to register bits*/ + + /* Is Windows enabled ? */ + if (protBaseLow & PACBLR_EN) + { + pProtWin->enable = MV_TRUE; + } + else + { + pProtWin->enable = MV_FALSE; + } + + + /* What is access protect ? */ + if (protBaseLow & PACBLR_ACCPROT) + { + pProtWin->attributes.access = FORBIDDEN; + } + else + { + pProtWin->attributes.access = ALLOWED; + } + + /* Is write protect ? */ + if (protBaseLow & PACBLR_WRPROT) + { + pProtWin->attributes.write = FORBIDDEN; + } + else + { + pProtWin->attributes.write = ALLOWED; + } + + + /* PCI slave Data Swap Control */ + pProtWin->attributes.swapType = (protBaseLow & PACBLR_PCISWAP_MASK) >> PACBLR_PCISWAP_OFFS; + + + /* Read Max Burst */ + pProtWin->attributes.readMaxBurst = pciBurstReg2Bytes((protBaseLow & PACBLR_RDMBURST_MASK) >> PACBLR_RDMBURST_OFFS); + + /* Typical PCI read transaction Size. */ + pProtWin->attributes.readBurst = pciBurstReg2Bytes((protBaseLow & PACBLR_RDSIZE_MASK) >> PACBLR_RDSIZE_OFFS); + + + /* window base high register value */ + pProtWin->addrWin.baseHigh = protBaseHigh; + + /*Calculate protection window size register value */ + pProtWin->addrWin.size = ctrlRegToSize(((protSize & PACSR_SIZE_MASK) >> PACSR_SIZE_OFFS),PACSR_SIZE_ALIGNMENT); + + + /* Write Max Burst */ + pProtWin->attributes.writeMaxBurst = pciBurstReg2Bytes((protSize & PACSR_WRMBURST_MASK) >> PACSR_WRMBURST_OFFS); + + /* Pci Order */ + if (protSize & PACSR_PCI_ORDERING) + { + pProtWin->attributes.pciOrder = MV_TRUE; + } + else + { + pProtWin->attributes.pciOrder = MV_FALSE; + } + + + return MV_OK; +} + + +/******************************************************************************* +* mvPciProtWinEnable - Enable/disable a PCI protection access window +* +* DESCRIPTION: +* This function enable/disable a PCI protection access window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* protection window, otherwise, the protection window will be disabled. +* +* INPUT: +* pciIf - PCI interface number. +* winNum - Protecion window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciProtWinEnable(MV_U32 pciIf, MV_U32 winNum, MV_BOOL enable) +{ + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciProtWinEnable: ERR. Invalid PCI interface %d\n", + pciIf); + return MV_BAD_PARAM; + } + + if (winNum >= PCI_MAX_PROT_WIN) + { + mvOsPrintf("mvPciProtWinEnable: ERR. Invalid window num %d\n", winNum); + return MV_BAD_PARAM; + } + + if (MV_TRUE == enable) + { + MV_REG_BIT_SET(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum), PACBLR_EN); + } + else + { + MV_REG_BIT_RESET(PCI_ACCESS_CTRL_BASEL_REG(pciIf,winNum), PACBLR_EN); + } + + return MV_OK; +} + + +/******************************************************************************* +* mvPciTargetRemap - Set PCI to target address window remap. +* +* DESCRIPTION: +* The PCI interface supports remap of the BAR original address window. +* For each BAR it is possible to define a remap address. For example +* an address 0x12345678 that hits BAR 0x10 (SDRAM CS[0]) will be modified +* according to remap register but will also be targeted to the +* SDRAM CS[0]. +* +* INPUT: +* pciIf - PCI interface number. +* bar - Peripheral target enumerator accessed by slave. +* pAddrWin - Address window to be checked. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPciTargetRemap(MV_U32 pciIf, + MV_PCI_BAR bar, + MV_ADDR_WIN *pAddrWin) +{ + PCI_BAR_REG_INFO barRegInfo; + + /* Parameter checking */ + if (pciIf >= mvCtrlPciMaxIfGet()) + { + mvOsPrintf("mvPciTargetRemap: ERR. Invalid PCI interface num %d\n", + pciIf); + return MV_BAD_PARAM; + } + + if (MV_IS_NOT_ALIGN(pAddrWin->baseLow, PBARR_REMAP_ALIGNMENT)) + { + mvOsPrintf("mvPciTargetRemap: Error remapping PCI interface %d bar %s."\ + "\nAddress 0x%08x is unaligned to size 0x%x.\n", + pciIf, + pciBarNameGet(bar), + pAddrWin->baseLow, + pAddrWin->size); + return MV_ERROR; + } + + pciBarRegInfoGet(pciIf, bar, &barRegInfo); + + /* Set remap low register value */ + MV_REG_WRITE(barRegInfo.remapLowRegOffs, pAddrWin->baseLow); + + /* Skip base high settings if the BAR has only base low (32-bit) */ + if (0 != barRegInfo.remapHighRegOffs) + { + MV_REG_WRITE(barRegInfo.remapHighRegOffs, pAddrWin->baseHigh); + } + + return MV_OK; +} + +/******************************************************************************* +* pciWinOverlapDetect - Detect address windows overlapping +* +* DESCRIPTION: +* This function detects address window overlapping of a given address +* window in PCI BARs. +* +* INPUT: +* pAddrWin - Address window to be checked. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pciWinOverlapDetect(MV_U32 pciIf, + MV_PCI_BAR bar, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 barEnableReg; + MV_U32 targetBar; + MV_PCI_BAR_WIN barAddrWin; + + /* Read base address enable register. Do not check disabled windows */ + barEnableReg = MV_REG_READ(PCI_BASE_ADDR_ENABLE_REG(pciIf)); + + for(targetBar = 0; targetBar < PCI_MAX_BARS; targetBar++) + { + /* don't check our target or illegal targets */ + if (targetBar == bar) + { + continue; + } + + /* Do not check disabled windows */ + if (barEnableReg & (BARER_ENABLE(targetBar))) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvPciTargetWinGet(pciIf, targetBar, &barAddrWin)) + { + mvOsPrintf("pciWinOverlapDetect: ERR. TargetWinGet failed\n"); + return MV_ERROR; + } + + /* skip overlapp detect between MEM_INTER_REGS_BAR and IO_INTER_REGS_BAR*/ + if (((bar == MEM_INTER_REGS_BAR)&&(targetBar == IO_INTER_REGS_BAR)) || + ((bar == IO_INTER_REGS_BAR)&&(targetBar == MEM_INTER_REGS_BAR))) + { + return MV_FALSE; + } + else if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &barAddrWin.addrWin)) + { + mvOsPrintf("pciWinOverlapDetect: BAR %d overlap current %d\n", + bar, targetBar); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* cpuWinIsValid - Check if the given address window is valid +* +* DESCRIPTION: +* PCI spec restrict BAR base to be aligned to BAR size. +* This function checks if the given address window is valid. +* +* INPUT: +* baseLow - 32bit low base address. +* size - Window size. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the address window is valid, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_STATUS pciWinIsValid(MV_U32 baseLow, MV_U32 size) +{ + + /* PCI spec restrict BAR base to be aligned to BAR size */ + if(MV_IS_NOT_ALIGN(baseLow, size)) + { + return MV_ERROR; + } + else + { + return MV_TRUE; + } +} + +/******************************************************************************* +* pciBarRegInfoGet - Get BAR register information +* +* DESCRIPTION: +* PCI BARs registers offsets are inconsecutive. +* This function gets a PCI BAR register information like register offsets +* and function location of the BAR. +* +* INPUT: +* pciIf - PCI interface number. +* bar - The PCI BAR in question. +* +* OUTPUT: +* pBarRegInfo - BAR register info struct. +* +* RETURN: +* MV_BAD_PARAM when bad parameters ,MV_ERROR on error ,othewise MV_OK +* +*******************************************************************************/ +static MV_STATUS pciBarRegInfoGet(MV_U32 pciIf, + MV_PCI_BAR bar, + PCI_BAR_REG_INFO *pBarRegInfo) +{ + switch (bar) + { + /* Function 0 Bars */ + #if defined(MV_INCLUDE_SDRAM_CS0) + case CS0_BAR: /* SDRAM chip select 0 bar*/ + pBarRegInfo->funcNum = 0; + pBarRegInfo->baseLowRegOffs = PCI_SCS0_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_SCS0_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_CS0_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_CS0_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + #endif + #if defined(MV_INCLUDE_SDRAM_CS1) + case CS1_BAR: /* SDRAM chip select 1 bar*/ + pBarRegInfo->funcNum = 0; + pBarRegInfo->baseLowRegOffs = PCI_SCS1_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_SCS1_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_CS1_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_CS1_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + #endif + case MEM_INTER_REGS_BAR: /* Memory Mapped Internal bar */ + pBarRegInfo->funcNum = 0; + pBarRegInfo->baseLowRegOffs = PCI_INTER_REG_MEM_MAPPED_BASE_ADDR_L; + pBarRegInfo->baseHighRegOffs = PCI_INTER_REG_MEM_MAPPED_BASE_ADDR_H; + pBarRegInfo->sizeRegOffs = 0; + pBarRegInfo->remapLowRegOffs = 0; + pBarRegInfo->remapHighRegOffs = 0; + break; + + /* Function 1 Bars */ + #if defined(MV_INCLUDE_SDRAM_CS2) + case CS2_BAR: /* SDRAM chip select 2 bar*/ + pBarRegInfo->funcNum = 1; + pBarRegInfo->baseLowRegOffs = PCI_SCS2_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_SCS2_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_CS2_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_CS2_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + #endif + #if defined(MV_INCLUDE_SDRAM_CS3) + case CS3_BAR: /* SDRAM chip select 3 bar*/ + pBarRegInfo->funcNum = 1; + pBarRegInfo->baseLowRegOffs = PCI_SCS3_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_SCS3_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_CS3_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_CS3_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + #endif + #if defined(MV_INCLUDE_DEVICE_CS0) + /* Function 2 Bars */ + case DEVCS0_BAR: /* Device chip select 0 bar*/ + pBarRegInfo->funcNum = 2; + pBarRegInfo->baseLowRegOffs = PCI_DEVCS0_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_DEVCS0_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_DEVCS0_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_DEVCS0_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + #endif + #if defined(MV_INCLUDE_DEVICE_CS1) + case DEVCS1_BAR: /* Device chip select 0 bar*/ + pBarRegInfo->funcNum = 2; + pBarRegInfo->baseLowRegOffs = PCI_DEVCS1_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_DEVCS1_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_DEVCS1_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_DEVCS1_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + #endif + #if defined(MV_INCLUDE_DEVICE_CS2) + case DEVCS2_BAR: /* Device chip select 0 bar*/ + pBarRegInfo->funcNum = 2; + pBarRegInfo->baseLowRegOffs = PCI_DEVCS2_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_DEVCS2_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_DEVCS2_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_DEVCS2_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + #endif + case BOOTCS_BAR: /* Boot device chip select bar*/ + pBarRegInfo->funcNum = 3; + pBarRegInfo->baseLowRegOffs = PCI_BOOTCS_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_BOOTCS_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_BOOTCS_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_BOOTCS_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + + /* Function 4 Bars */ + case P2P_MEM0: /* P2P memory 0 */ + pBarRegInfo->funcNum = 4; + pBarRegInfo->baseLowRegOffs = PCI_P2P_MEM0_BASE_ADDR_LOW; + pBarRegInfo->baseHighRegOffs = PCI_P2P_MEM0_BASE_ADDR_HIGH; + pBarRegInfo->sizeRegOffs = PCI_P2P_MEM0_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_P2P_MEM0_ADDR_REMAP_LOW_REG(pciIf); + pBarRegInfo->remapHighRegOffs = PCI_P2P_MEM0_ADDR_REMAP_HIGH_REG(pciIf); + break; + case P2P_IO: /* P2P IO */ + pBarRegInfo->funcNum = 4; + pBarRegInfo->baseLowRegOffs = PCI_P2P_IO_BASE_ADDR; + pBarRegInfo->baseHighRegOffs = 0; + pBarRegInfo->sizeRegOffs = PCI_P2P_IO_BAR_SIZE_REG(pciIf); + pBarRegInfo->remapLowRegOffs = PCI_P2P_IO_ADDR_REMAP_REG(pciIf); + pBarRegInfo->remapHighRegOffs = 0; + break; + case IO_INTER_REGS_BAR: /* IO Mapped Internal bar */ + pBarRegInfo->funcNum = 4; + pBarRegInfo->baseLowRegOffs = PCI_INTER_REGS_IO_MAPPED_BASE_ADDR; + pBarRegInfo->baseHighRegOffs = 0; + pBarRegInfo->sizeRegOffs = 0; + pBarRegInfo->remapLowRegOffs = 0; + pBarRegInfo->remapHighRegOffs = 0; + break; + + + default: + mvOsPrintf("mvPciTargetWinGet: ERR.non existing target\n"); + return MV_ERROR; + + } + + return MV_OK; +} + +/******************************************************************************* +* pciBarNameGet - Get the string name of PCI BAR. +* +* DESCRIPTION: +* This function get the string name of PCI BAR. +* +* INPUT: +* bar - PCI bar number. +* +* OUTPUT: +* None. +* +* RETURN: +* pointer to the string name of PCI BAR. +* +*******************************************************************************/ +const MV_8* pciBarNameGet( MV_PCI_BAR bar ) +{ + switch( bar ) + { + #if defined(MV_INCLUDE_SDRAM_CS0) + case CS0_BAR: + return "CS0_BAR.............."; + #endif + #if defined(MV_INCLUDE_SDRAM_CS1) + case CS1_BAR: + return "CS1_BAR.............."; + #endif + #if defined(MV_INCLUDE_SDRAM_CS2) + case CS2_BAR: + return "CS2_BAR.............."; + #endif + #if defined(MV_INCLUDE_SDRAM_CS3) + case CS3_BAR: + return "CS3_BAR.............."; + #endif + #if defined(MV_INCLUDE_DEVICE_CS0) + case DEVCS0_BAR: + return "DEVCS0_BAR..........."; + #endif + #if defined(MV_INCLUDE_DEVICE_CS1) + case DEVCS1_BAR: + return "DEVCS1_BAR..........."; + #endif + #if defined(MV_INCLUDE_DEVICE_CS2) + case DEVCS2_BAR: + return "DEVCS2_BAR..........."; + #endif + case BOOTCS_BAR: + return "BOOTCS_BAR..........."; + case MEM_INTER_REGS_BAR: + return "MEM_INTER_REGS_BAR..."; + case IO_INTER_REGS_BAR: + return "IO_INTER_REGS_BAR...."; + case P2P_MEM0: + return "P2P_MEM0............."; + case P2P_IO: + return "P2P_IO..............."; + default: + return "target unknown"; + } +} + +/******************************************************************************* +* mvPciAddrDecShow - Print the PCI address decode map (BARs). +* +* DESCRIPTION: +* This function print the PCI address decode map (BARs). +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvPciAddrDecShow(MV_VOID) +{ + MV_PCI_BAR_WIN win; + MV_PCI_BAR bar; + MV_U32 pciIf; + + for( pciIf = 0; pciIf < mvCtrlPciMaxIfGet(); pciIf++ ) + { + if (MV_FALSE == mvCtrlPwrClckGet(PCI_UNIT_ID, pciIf)) continue; + mvOsOutput( "\n" ); + mvOsOutput( "PCI%d:\n", pciIf ); + mvOsOutput( "-----\n" ); + + for( bar = 0; bar < PCI_MAX_BARS; bar++ ) + { + memset( &win, 0, sizeof(MV_PCI_BAR_WIN) ); + + mvOsOutput( "%s ", pciBarNameGet(bar) ); + + if( mvPciTargetWinGet( pciIf, bar, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "base %08x, ", win.addrWin.baseLow ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } + } +} + +/* convert burst bytes to register value*/ +static MV_U32 pciBurstBytes2Reg(MV_U32 size) +{ + MV_U32 ret; + switch(size) + { + case 32: ret = 0; break; + case 64: ret = 1; break; + case 128: ret = 2; break; + case 256: ret = 3; break; + default: ret = 0xF; /* error */ + } + return ret; +} + +/* convert register value to burst bytes*/ +static MV_U32 pciBurstReg2Bytes(MV_U32 size) +{ + MV_U32 ret; + switch(size) + { + case 0: ret = 32; break; + case 1: ret = 64; break; + case 2: ret = 128; break; + case 3: ret = 256; break; + default: ret = 0x0; /* error */ + } + return ret; +} + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.h new file mode 100644 index 0000000..de1f526 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPci.h @@ -0,0 +1,277 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef __INCSysPCIH +#define __INCSysPCIH + +#include "ctrlEnv/sys/mvCpuIf.h" +#include "pci/mvPci.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define PCI_MAX_PROT_WIN 6 + +/* 4KB granularity */ +#define MINIMUM_WINDOW_SIZE 0x1000 +#define MINIMUM_BAR_SIZE 0x1000 +#define MINIMUM_BAR_SIZE_MASK 0xFFFFF000 +#define BAR_SIZE_OFFS 12 +#define BAR_SIZE_MASK (0xFFFFF << BAR_SIZE_OFFS) + +#define PCI_IO_WIN_NUM 1 /* Number of PCI_IO windows */ +#define PCI_MEM_WIN_NUM 4 /* Number of PCI_MEM windows */ + +#ifndef MV_ASMLANGUAGE +#include "ctrlEnv/mvCtrlEnvLib.h" +typedef enum _mvPCIBars +{ + PCI_BAR_TBL_TERM = -1, /* none valid bar, used as bars list terminator */ +#if defined(MV_INCLUDE_SDRAM_CS0) + CS0_BAR, /* SDRAM chip select 0 bar*/ +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + CS1_BAR, /* SDRAM chip select 1 bar*/ +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + CS2_BAR, /* SDRAM chip select 2 bar*/ +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + CS3_BAR, /* SDRAM chip select 3 bar*/ +#endif +#if defined(MV_INCLUDE_DEVICE_CS0) + DEVCS0_BAR, /* Device chip select 0 bar*/ +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + DEVCS1_BAR, /* Device chip select 1 bar*/ +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + DEVCS2_BAR, /* Device chip select 2 bar*/ +#endif + BOOTCS_BAR, /* Boot device chip select bar*/ + MEM_INTER_REGS_BAR, /* Memory Mapped Internal bar */ + IO_INTER_REGS_BAR, /* IO Mapped Internal bar */ + P2P_MEM0, /* P2P memory 0 */ + P2P_IO, /* P2P IO */ + PCI_MAX_BARS + +}MV_PCI_BAR; +#endif /* MV_ASMLANGUAGE */ + +#if defined(MV_INCLUDE_SDRAM_CS3) +#define MV_PCI_BAR_IS_DRAM_BAR(bar) \ + ((bar >= CS0_BAR) && (bar <= CS3_BAR)) +#elif defined(MV_INCLUDE_SDRAM_CS2) +#define MV_PCI_BAR_IS_DRAM_BAR(bar) \ + ((bar >= CS0_BAR) && (bar <= CS2_BAR)) +#elif defined(MV_INCLUDE_SDRAM_CS1) +#define MV_PCI_BAR_IS_DRAM_BAR(bar) \ + ((bar >= CS0_BAR) && (bar <= CS1_BAR)) +#elif defined(MV_INCLUDE_SDRAM_CS0) +#define MV_PCI_BAR_IS_DRAM_BAR(bar) \ + ((bar == CS0_BAR)) +#endif + + +/****************************************/ +/* PCI Slave Address Decoding registers */ +/****************************************/ +#define PCI_CS0_BAR_SIZE_REG(pciIf) (0x30c08 + ((pciIf) * 0x80)) +#define PCI_CS1_BAR_SIZE_REG(pciIf) (0x30d08 + ((pciIf) * 0x80)) +#define PCI_CS2_BAR_SIZE_REG(pciIf) (0x30c0c + ((pciIf) * 0x80)) +#define PCI_CS3_BAR_SIZE_REG(pciIf) (0x30d0c + ((pciIf) * 0x80)) +#define PCI_DEVCS0_BAR_SIZE_REG(pciIf) (0x30c10 + ((pciIf) * 0x80)) +#define PCI_DEVCS1_BAR_SIZE_REG(pciIf) (0x30d10 + ((pciIf) * 0x80)) +#define PCI_DEVCS2_BAR_SIZE_REG(pciIf) (0x30d18 + ((pciIf) * 0x80)) +#define PCI_BOOTCS_BAR_SIZE_REG(pciIf) (0x30d14 + ((pciIf) * 0x80)) +#define PCI_P2P_MEM0_BAR_SIZE_REG(pciIf) (0x30d1c + ((pciIf) * 0x80)) +#define PCI_P2P_IO_BAR_SIZE_REG(pciIf) (0x30d24 + ((pciIf) * 0x80)) +#define PCI_EXPAN_ROM_BAR_SIZE_REG(pciIf) (0x30d2c + ((pciIf) * 0x80)) +#define PCI_BASE_ADDR_ENABLE_REG(pciIf) (0x30c3c + ((pciIf) * 0x80)) +#define PCI_CS0_ADDR_REMAP_REG(pciIf) (0x30c48 + ((pciIf) * 0x80)) +#define PCI_CS1_ADDR_REMAP_REG(pciIf) (0x30d48 + ((pciIf) * 0x80)) +#define PCI_CS2_ADDR_REMAP_REG(pciIf) (0x30c4c + ((pciIf) * 0x80)) +#define PCI_CS3_ADDR_REMAP_REG(pciIf) (0x30d4c + ((pciIf) * 0x80)) +#define PCI_DEVCS0_ADDR_REMAP_REG(pciIf) (0x30c50 + ((pciIf) * 0x80)) +#define PCI_DEVCS1_ADDR_REMAP_REG(pciIf) (0x30d50 + ((pciIf) * 0x80)) +#define PCI_DEVCS2_ADDR_REMAP_REG(pciIf) (0x30d58 + ((pciIf) * 0x80)) +#define PCI_BOOTCS_ADDR_REMAP_REG(pciIf) (0x30d54 + ((pciIf) * 0x80)) +#define PCI_P2P_MEM0_ADDR_REMAP_LOW_REG(pciIf) (0x30d5c + ((pciIf) * 0x80)) +#define PCI_P2P_MEM0_ADDR_REMAP_HIGH_REG(pciIf) (0x30d60 + ((pciIf) * 0x80)) +#define PCI_P2P_IO_ADDR_REMAP_REG(pciIf) (0x30d6c + ((pciIf) * 0x80)) +#define PCI_EXPAN_ROM_ADDR_REMAP_REG(pciIf) (0x30f38 + ((pciIf) * 0x80)) +#define PCI_DRAM_BAR_BANK_SELECT_REG(pciIf) (0x30c1c + ((pciIf) * 0x80)) +#define PCI_ADDR_DECODE_CONTROL_REG(pciIf) (0x30d3c + ((pciIf) * 0x80)) + +/* PCI Bars Size Registers (PBSR) */ +#define PBSR_SIZE_OFFS 12 +#define PBSR_SIZE_MASK (0xfffff << PBSR_SIZE_OFFS) + +/* Base Address Registers Enable Register (BARER) */ +#define BARER_ENABLE(target) (1 << (target)) + +/* PCI Base Address Remap Registers (PBARR) */ +#define PBARR_REMAP_OFFS 12 +#define PBARR_REMAP_MASK (0xfffff << PBARR_REMAP_OFFS) +#define PBARR_REMAP_ALIGNMENT (1 << PBARR_REMAP_OFFS) + +/* PCI DRAM Bar Bank Select Register (PDBBSR) */ +#define PDBBSR_DRAM_BANK_OFFS(bank) ((bank) * 2) +#define PDBBSR_DRAM_BANK_MASK(bank) (0x3 << PDBBSR_DRAM_BANK_OFFS(bank)) + +/* PCI Address Decode Control Register (PADCR)*/ +#define PADCR_REMAP_REG_WR_DIS BIT0 +#define PADCR_MSG_REG_ACC BIT3 + +#define PADCR_VPD_HIGH_ADDR_OFFS 8 /* Bits [31:15] of the VPD address */ +#define PADCR_VPD_HIGH_ADDR_MASK (0x1ffff << PADCR_VPD_HIGH_ADDR_OFFS) + +/* PCI Headers Retarget Control Register (PHRCR) */ +#define PHRCR_ENABLE BIT0 +#define PHRCR_BUFF_SIZE_OFFS 1 +#define PHRCR_BUFF_SIZE_MASK (0x7 << PHRCR_BUFF_SIZE_OFFS) +#define PHRCR_BUFF_SIZE_258BYTE (0x0 << PHRCR_BUFF_SIZE_OFFS) +#define PHRCR_BUFF_SIZE_512BYTE (0x1 << PHRCR_BUFF_SIZE_OFFS) +#define PHRCR_BUFF_SIZE_1KB (0x2 << PHRCR_BUFF_SIZE_OFFS) +#define PHRCR_BUFF_SIZE_2KB (0x3 << PHRCR_BUFF_SIZE_OFFS) +#define PHRCR_BUFF_SIZE_4KB (0x4 << PHRCR_BUFF_SIZE_OFFS) +#define PHRCR_BUFF_SIZE_8KB (0x5 << PHRCR_BUFF_SIZE_OFFS) +#define PHRCR_MASK1_OFFS 16 +#define PHRCR_MASK1_MASK (0xffff << PHRCR_MASK1_OFFS) + +/* PCI Headers Retarget Base Register (PHRBR) */ +#define PHRBR_BASE_OFFS 16 +#define PHRBR_BASE_MASK (0xffff << PHRBR_BASE_OFFS) + +/* PCI Headers Retarget Base High Register (PHRBHR) */ +#define PHRBHR_BASE_OFFS 0 +#define PHRBHR_BASE_MASK (0xffffffff << PHRBHR_BASE_OFFS) + +/* This structure describes a PCI BAR. It is also refered as PCI target */ +/* window to keep consistency with other address decode units in the system */ +typedef struct _mvPciBarWin +{ + MV_ADDR_WIN addrWin; /* Address window */ + MV_BOOL enable; /* BAR enable/disable */ +}MV_PCI_BAR_WIN; + +/* This structure describes PCI region attributes */ +typedef struct _mvPciRegionAttr +{ + MV_PROT_RIGHT access; /* Access protection */ + MV_PROT_RIGHT write; /* Write protection */ + MV_SWAP_TYPE swapType; /* Data swap mode for that region */ + MV_U32 readMaxBurst; /* Read max burst */ + MV_U32 readBurst; /* Read burst. Conventional PCI only */ + MV_U32 writeMaxBurst; /* Write max burst */ + MV_BOOL pciOrder; /* Hardware support for PCI ordering */ +}MV_PCI_REGION_ATTR; + +/* The PCI slave interface supports configurable access control. */ +/* It is possible to define up to six address ranges to different */ +/* configurations. This structure describes the PCI access region */ +typedef struct _mvPciProtWin +{ + MV_ADDR_WIN addrWin; /* An address window */ + MV_PCI_REGION_ATTR attributes; /* Window attributes */ + MV_BOOL enable; /* Window enabled/disabled */ +}MV_PCI_PROT_WIN; + +/* Global Functions prototypes */ + +/* mvPciInit - Initialize PCI interfaces*/ +MV_STATUS mvPciInit(MV_U32 pciIf, MV_PCI_MOD pciIfmod); + +/* mvPciTargetWinSet - Set PCI to peripheral target address window BAR*/ +MV_STATUS mvPciTargetWinSet(MV_U32 pciIf, MV_PCI_BAR slaveTarget, + MV_PCI_BAR_WIN *pAddrBarWin); + +/* mvPciTargetWinGet - Get PCI to peripheral target address window*/ +MV_STATUS mvPciTargetWinGet(MV_U32 pciIf, MV_PCI_BAR slaveTarget, + MV_PCI_BAR_WIN *pAddrBarWin); + +/* mvPciTargetWinEnable - Enable/disable a PCI BAR window*/ +MV_STATUS mvPciTargetWinEnable(MV_U32 pciIf,MV_PCI_BAR slaveTarget, + MV_BOOL enable); + +/* mvPciProtWinSet - Set PCI protection access window*/ +MV_STATUS mvPciProtWinSet(MV_U32 pciIf, MV_U32 winNum, + MV_PCI_PROT_WIN *pProtWin); + +/* mvPciProtWinGet - Get PCI protection access window*/ +MV_STATUS mvPciProtWinGet(MV_U32 pciIf, + MV_U32 winNum, + MV_PCI_PROT_WIN *pProtWin); + +/* mvPciProtWinEnable - Get PCI protection access window*/ +MV_STATUS mvPciProtWinEnable(MV_U32 pciIf, MV_U32 winNum, MV_BOOL enable); + +/* mvPciTargetRemap - Set PCI to target address window remap.*/ +MV_STATUS mvPciTargetRemap(MV_U32 pciIf, MV_PCI_BAR slaveTarget, + MV_ADDR_WIN *pAddrWin); + +/* mvPciAddrDecShow - Display address decode windows attributes */ +MV_VOID mvPciAddrDecShow(MV_VOID); + +#endif diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.c new file mode 100644 index 0000000..fd5a9e0 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.c @@ -0,0 +1,1696 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "ctrlEnv/sys/mvSysPex.h" + +/* this structure describes the mapping between a Pex Window and a CPU target*/ +typedef struct _pexWinToTarget +{ + MV_TARGET target; + MV_BOOL enable; + +}PEX_WIN_TO_TARGET; + +/* this array is a priority array that define How Pex windows should be +configured , We have only 6 Pex Windows that can be configured , but we +have maximum of 9 CPU target windows ! the following array is a priority +array where the lowest index has the highest priotiy and the highest +index has the lowest priority of being cnfigured */ + +MV_U32 pexDevBarPrioTable[] = +{ +#if defined(MV_INCLUDE_DEVICE_CS0) + DEVICE_CS0, +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + DEVICE_CS1, +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + DEVICE_CS2, +#endif +#if defined(MV_INCLUDE_DEVICE_CS3) + DEVICE_CS3, +#endif +/* +#if defined(MV_INCLUDE_DEVICE_CS4) + DEVICE_CS4, +#endif +*/ + TBL_TERM +}; + + +/* PEX Wins registers offsets are inconsecutive. This struct describes WIN */ +/* register offsets and its function where its is located. */ +/* Also, PEX address remap registers offsets are inconsecutive. This struct */ +/* describes address remap register offsets */ +typedef struct _pexWinRegInfo +{ + MV_U32 baseLowRegOffs; + MV_U32 baseHighRegOffs; + MV_U32 sizeRegOffs; + MV_U32 remapLowRegOffs; + MV_U32 remapHighRegOffs; + +}PEX_WIN_REG_INFO; + +static MV_STATUS pexWinOverlapDetect(MV_U32 pexIf, MV_U32 winNum, + MV_ADDR_WIN *pAddrWin); +static MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, MV_U32 winNum, + PEX_WIN_REG_INFO *pWinRegInfo); +const MV_8* pexBarNameGet( MV_U32 bar ); + +static MV_STATUS pexBarIsValid(MV_U32 baseLow, MV_U32 size); + +static MV_BOOL pexIsWinWithinBar(MV_U32 pexIf,MV_ADDR_WIN *pAddrWin); +static MV_BOOL pexBarOverlapDetect(MV_U32 pexIf,MV_U32 barNum, + MV_ADDR_WIN *pAddrWin); + +/******************************************************************************* +* mvPexInit - Initialize PEX interfaces +* +* DESCRIPTION: +* +* This function is responsible of intialization of the Pex Interface , It +* configure the Pex Bars and Windows in the following manner: +* +* Assumptions : +* Bar0 is always internal registers bar +* Bar1 is always the DRAM bar +* Bar2 is always the Device bar +* +* 1) Sets the Internal registers bar base by obtaining the base from +* the CPU Interface +* 2) Sets the DRAM bar base and size by getting the base and size from +* the CPU Interface when the size is the sum of all enabled DRAM +* chip selects and the base is the base of CS0 . +* 3) Sets the Device bar base and size by getting these values from the +* CPU Interface when the base is the base of the lowest base of the +* Device chip selects, and the +* +* +* INPUT: +* +* pexIf - PEX interface number. +* +* +* OUTPUT: +* None. +* +* RETURN: +* MV_OK if function success otherwise MV_ERROR or MV_BAD_PARAM +* +*******************************************************************************/ +MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType) +{ + MV_U32 bar; + MV_U32 winNum; + MV_PEX_BAR pexBar; + MV_PEX_DEC_WIN pexWin; + MV_CPU_DEC_WIN addrDecWin; + MV_TARGET target; + MV_U32 pexCurrWin=0; + MV_U32 status; + /* default and exapntion rom + are always configured */ + +#ifndef MV_DISABLE_PEX_DEVICE_BAR + MV_U32 winIndex; + MV_U32 maxBase=0, sizeOfMaxBase=0; + MV_U32 pexStartWindow; +#endif + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexInit: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + /* Enabled CPU access to PCI-Express */ + mvCpuIfEnablePex(pexIf, pexType); + + /* Start with bars */ + /* First disable all PEX bars*/ + for (bar = 0; bar < PEX_MAX_BARS; bar++) + { + if (PEX_INTER_REGS_BAR != bar) + { + if (MV_OK != mvPexBarEnable(pexIf, bar, MV_FALSE)) + { + mvOsPrintf("mvPexInit:mvPexBarEnable bar =%d failed \n",bar); + return MV_ERROR; + } + + } + + } + + /* and disable all PEX target windows */ + for (winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_FALSE)) + { + mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", + winNum); + return MV_ERROR; + + } + } + + /* Now, go through all bars*/ + + + +/******************************************************************************/ +/* Internal registers bar */ +/******************************************************************************/ + bar = PEX_INTER_REGS_BAR; + + /* we only open the bar , no need to open windows for this bar */ + + /* first get the CS attribute from the CPU Interface */ + if (MV_OK !=mvCpuIfTargetWinGet(INTER_REGS,&addrDecWin)) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",INTER_REGS); + return MV_ERROR; + } + + pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexBar.addrWin.size = addrDecWin.addrWin.size; + pexBar.enable = MV_TRUE; + + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + +/******************************************************************************/ +/* DRAM bar */ +/******************************************************************************/ + + bar = PEX_DRAM_BAR; + + pexBar.addrWin.size = 0; + + for (target = SDRAM_CS0;target < MV_DRAM_MAX_CS; target++ ) + { + + status = mvCpuIfTargetWinGet(target,&addrDecWin); + + if((MV_NO_SUCH == status)&&(target != SDRAM_CS0)) + { + continue; + } + + /* first get attributes from CPU If */ + if (MV_OK != status) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target); + return MV_ERROR; + } + if (addrDecWin.enable == MV_TRUE) + { + /* the base is the base of DRAM CS0 always */ + if (SDRAM_CS0 == target ) + { + pexBar.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + + } + + /* increment the bar size to be the sum of the size of all + DRAM chips selecs */ + pexBar.addrWin.size += addrDecWin.addrWin.size; + + /* set a Pex window for this target ! + DRAM CS always will have a Pex Window , and is not a + part of the priority table */ + pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexWin.addrWin.size = addrDecWin.addrWin.size; + + /* we disable the windows at first because we are not + sure that it is witihin bar boundries */ + pexWin.enable =MV_FALSE; + pexWin.target = target; + pexWin.targetBar = bar; + + if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++,&pexWin)) + { + mvOsPrintf("mvPexInit: ERR. mvPexTargetWinSet failed\n"); + return MV_ERROR; + } + } + } + + /* check if the size of the bar is illeggal */ + if (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT)) + { + /* try to get a good size */ + pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, + PXBCR_BAR_SIZE_ALIGNMENT); + } + + /* check if the size and base are valid */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,bar,&pexBar.addrWin)) + { + mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n",bar); + mvOsPrintf("it will be disabled\n"); + mvOsPrintf("please check Pex and CPU windows configuration\n"); + } + else + { + pexBar.enable = MV_TRUE; + + /* configure the bar */ + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + + /* after the bar was configured then we enable the Pex windows*/ + for (winNum = 0;winNum < pexCurrWin ;winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) + { + mvOsPrintf("mvPexInit: Can't enable window =%d\n",winNum); + return MV_ERROR; + } + + } + } + +/******************************************************************************/ +/* DEVICE bar */ +/******************************************************************************/ + +/* Open the Device BAR for non linux only */ +#ifndef MV_DISABLE_PEX_DEVICE_BAR + + /* then device bar*/ + bar = PEX_DEVICE_BAR; + + /* save the starting window */ + pexStartWindow = pexCurrWin; + pexBar.addrWin.size = 0; + pexBar.addrWin.baseLow = 0xffffffff; + pexBar.addrWin.baseHigh = 0; + maxBase = 0; + + for (target = DEV_TO_TARGET(START_DEV_CS);target < DEV_TO_TARGET(MV_DEV_MAX_CS); target++ ) + { + status = mvCpuIfTargetWinGet(target,&addrDecWin); + + if (MV_NO_SUCH == status) + { + continue; + } + + if (MV_OK != status) + { + mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target); + return MV_ERROR; + } + + if (addrDecWin.enable == MV_TRUE) + { + /* get the minimum base */ + if (addrDecWin.addrWin.baseLow < pexBar.addrWin.baseLow) + { + pexBar.addrWin.baseLow = addrDecWin.addrWin.baseLow; + } + + /* get the maximum base */ + if (addrDecWin.addrWin.baseLow > maxBase) + { + maxBase = addrDecWin.addrWin.baseLow; + sizeOfMaxBase = addrDecWin.addrWin.size; + } + + /* search in the priority table for this target */ + for (winIndex = 0; pexDevBarPrioTable[winIndex] != TBL_TERM; + winIndex++) + { + if (pexDevBarPrioTable[winIndex] != target) + { + continue; + } + else if (pexDevBarPrioTable[winIndex] == target) + { + /*found it */ + + /* if the index of this target in the prio table is valid + then we set the Pex window for this target, a valid index is + an index that is lower than the number of the windows that + was not configured yet */ + + /* we subtract 2 always because the default and expantion + rom windows are always configured */ + if ( pexCurrWin < PEX_MAX_TARGET_WIN - 2) + { + /* set a Pex window for this target ! */ + pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh; + pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow; + pexWin.addrWin.size = addrDecWin.addrWin.size; + + /* we disable the windows at first because we are not + sure that it is witihin bar boundries */ + pexWin.enable = MV_FALSE; + pexWin.target = target; + pexWin.targetBar = bar; + + if (MV_OK != mvPexTargetWinSet(pexIf,pexCurrWin++, + &pexWin)) + { + mvOsPrintf("mvPexInit: ERR. Window Set failed\n"); + return MV_ERROR; + } + } + } + } + } + } + + pexBar.addrWin.size = maxBase - pexBar.addrWin.baseLow + sizeOfMaxBase; + pexBar.enable = MV_TRUE; + + /* check if the size of the bar is illegal */ + if (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT)) + { + /* try to get a good size */ + pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size, + PXBCR_BAR_SIZE_ALIGNMENT); + } + + /* check if the size and base are valid */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,bar,&pexBar.addrWin)) + { + mvOsPrintf("mvPexInit:Warning :Bar %d size is illigal\n",bar); + mvOsPrintf("it will be disabled\n"); + mvOsPrintf("please check Pex and CPU windows configuration\n"); + } + else + { + if (MV_OK != mvPexBarSet(pexIf, bar, &pexBar)) + { + mvOsPrintf("mvPexInit: ERR. mvPexBarSet %d failed\n", bar); + return MV_ERROR; + } + + /* now enable the windows */ + for (winNum = pexStartWindow; winNum < pexCurrWin ; winNum++) + { + if (MV_OK != mvPexTargetWinEnable(pexIf, winNum, MV_TRUE)) + { + mvOsPrintf("mvPexInit:mvPexTargetWinEnable winNum =%d failed \n", + winNum); + return MV_ERROR; + } + } + } + +#endif + + return mvPexHalInit(pexIf, pexType); + +} + +/******************************************************************************* +* mvPexTargetWinSet - Set PEX to peripheral target address window BAR +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_OK if PEX BAR target window was set correctly, +* MV_BAD_PARAM on bad params +* MV_ERROR otherwise +* (e.g. address window overlapps with other active PEX target window). +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin) +{ + + MV_DEC_REGS decRegs; + PEX_WIN_REG_INFO winRegInfo; + MV_TARGET_ATTRIB targetAttribs; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf,winNum,&winRegInfo); + + + if (MV_TRUE == pAddrDecWin->enable) + { + + /* 2) Check if the requested window overlaps with current windows */ + if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvPexTargetWinSet: ERR. Target %d overlap\n", winNum); + return MV_BAD_PARAM; + } + + /* 2) Check if the requested window overlaps with current windows */ + if (MV_FALSE == pexIsWinWithinBar(pexIf,&pAddrDecWin->addrWin)) + { + mvOsPrintf("mvPexTargetWinSet: Win %d should be in bar boundries\n", + winNum); + return MV_BAD_PARAM; + } + + } + + + + /* read base register*/ + + if (winRegInfo.baseLowRegOffs) + { + decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs); + } + else + { + decRegs.baseReg = 0; + } + + if (winRegInfo.sizeRegOffs) + { + decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs); + } + else + { + decRegs.sizeReg =0; + } + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvPexTargetWinSet:mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + /* enable\Disable */ + if (MV_TRUE == pAddrDecWin->enable) + { + decRegs.sizeReg |= PXWCR_WIN_EN; + } + else + { + decRegs.sizeReg &= ~PXWCR_WIN_EN; + } + + + /* clear bit location */ + decRegs.sizeReg &= ~PXWCR_WIN_BAR_MAP_MASK; + + /* set bar Mapping */ + if (pAddrDecWin->targetBar == 1) + { + decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR1; + } + else if (pAddrDecWin->targetBar == 2) + { + decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR2; + } + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~PXWCR_ATTRIB_MASK; + decRegs.sizeReg |= targetAttribs.attrib << PXWCR_ATTRIB_OFFS; + /* set target ID */ + decRegs.sizeReg &= ~PXWCR_TARGET_MASK; + decRegs.sizeReg |= targetAttribs.targetId << PXWCR_TARGET_OFFS; + + + /* 3) Write to address decode Base Address Register */ + + if (winRegInfo.baseLowRegOffs) + { + MV_REG_WRITE(winRegInfo.baseLowRegOffs, decRegs.baseReg); + } + + /* write size reg */ + if (winRegInfo.sizeRegOffs) + { + if ((MV_PEX_WIN_DEFAULT == winNum)|| + (MV_PEX_WIN_EXP_ROM == winNum)) + { + /* clear size because there is no size field*/ + decRegs.sizeReg &= ~PXWCR_SIZE_MASK; + + /* clear enable because there is no enable field*/ + decRegs.sizeReg &= ~PXWCR_WIN_EN; + + } + + MV_REG_WRITE(winRegInfo.sizeRegOffs, decRegs.sizeReg); + } + + + return MV_OK; + +} + +/******************************************************************************* +* mvPexTargetWinGet - Get PEX to peripheral target address window +* +* DESCRIPTION: +* Get the PEX to peripheral target address window BAR. +* +* INPUT: +* pexIf - PEX interface number. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* pAddrBarWin - PEX target window information data structure. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin) +{ + MV_TARGET_ATTRIB targetAttrib; + MV_DEC_REGS decRegs; + + PEX_WIN_REG_INFO winRegInfo; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf,winNum,&winRegInfo); + + /* read base register*/ + if (winRegInfo.baseLowRegOffs) + { + decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs); + } + else + { + decRegs.baseReg = 0; + } + + /* read size reg */ + if (winRegInfo.sizeRegOffs) + { + decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs); + } + else + { + decRegs.sizeReg =0; + } + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvPexTargetWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + + } + + if (decRegs.sizeReg & PXWCR_WIN_EN) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + + } + + + #if 0 + if (-1 == pAddrDecWin->addrWin.size) + { + return MV_ERROR; + } + #endif + + + /* get target bar */ + if ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) == PXWCR_WIN_BAR_MAP_BAR1 ) + { + pAddrDecWin->targetBar = 1; + } + else if ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) == + PXWCR_WIN_BAR_MAP_BAR2 ) + { + pAddrDecWin->targetBar = 2; + } + + /* attrib and targetId */ + pAddrDecWin->attrib = (decRegs.sizeReg & PXWCR_ATTRIB_MASK) >> + PXWCR_ATTRIB_OFFS; + pAddrDecWin->targetId = (decRegs.sizeReg & PXWCR_TARGET_MASK) >> + PXWCR_TARGET_OFFS; + + targetAttrib.attrib = pAddrDecWin->attrib; + targetAttrib.targetId = pAddrDecWin->targetId; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + return MV_OK; + +} + + +/******************************************************************************* +* mvPexTargetWinEnable - Enable/disable a PEX BAR window +* +* DESCRIPTION: +* This function enable/disable a PEX BAR window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling PEX accesses for that BAR (before enabling the +* window it is tested for overlapping). Otherwise, the window will +* be disabled. +* +* INPUT: +* pexIf - PEX interface number. +* bar - BAR to be accessed by slave. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf,MV_U32 winNum, MV_BOOL enable) +{ + PEX_WIN_REG_INFO winRegInfo; + MV_PEX_DEC_WIN addrDecWin; + + /* Parameter checking */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinEnable: ERR. Invalid PEX If %d\n", pexIf); + return MV_BAD_PARAM; + } + + if (winNum >= PEX_MAX_TARGET_WIN) + { + mvOsPrintf("mvPexTargetWinEnable ERR. Invalid PEX winNum %d\n", winNum); + return MV_BAD_PARAM; + + } + + + /* get the pex Window registers offsets */ + pexWinRegInfoGet(pexIf,winNum,&winRegInfo); + + + /* if the address windows is disabled , we only disable the appropriare + pex window and ignore other settings */ + + if (MV_FALSE == enable) + { + + /* this is not relevant to default and expantion rom + windows */ + if (winRegInfo.sizeRegOffs) + { + if ((MV_PEX_WIN_DEFAULT != winNum)&& + (MV_PEX_WIN_EXP_ROM != winNum)) + { + MV_REG_BIT_RESET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN); + } + } + + } + else + { + if (MV_OK != mvPexTargetWinGet(pexIf,winNum, &addrDecWin)) + { + mvOsPrintf("mvPexTargetWinEnable: mvPexTargetWinGet Failed\n"); + return MV_ERROR; + } + + /* Check if the requested window overlaps with current windows */ + if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &addrDecWin.addrWin)) + { + mvOsPrintf("mvPexTargetWinEnable: ERR. Target %d overlap\n", winNum); + return MV_BAD_PARAM; + } + + if (MV_FALSE == pexIsWinWithinBar(pexIf,&addrDecWin.addrWin)) + { + mvOsPrintf("mvPexTargetWinEnable: Win %d should be in bar boundries\n", + winNum); + return MV_BAD_PARAM; + } + + + /* this is not relevant to default and expantion rom + windows */ + if (winRegInfo.sizeRegOffs) + { + if ((MV_PEX_WIN_DEFAULT != winNum)&& + (MV_PEX_WIN_EXP_ROM != winNum)) + { + MV_REG_BIT_SET(winRegInfo.sizeRegOffs, PXWCR_WIN_EN); + } + } + + + } + + return MV_OK; + +} + + + +/******************************************************************************* +* mvPexTargetWinRemap - Set PEX to target address window remap. +* +* DESCRIPTION: +* The PEX interface supports remap of the BAR original address window. +* For each BAR it is possible to define a remap address. For example +* an address 0x12345678 that hits BAR 0x10 (SDRAM CS[0]) will be modified +* according to remap register but will also be targeted to the +* SDRAM CS[0]. +* +* INPUT: +* pexIf - PEX interface number. +* bar - Peripheral target enumerator accessed by slave. +* pAddrWin - Address window to be checked. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_REMAP_WIN *pAddrWin) +{ + + PEX_WIN_REG_INFO winRegInfo; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", + pexIf); + return MV_BAD_PARAM; + } + if (MV_PEX_WIN_DEFAULT == winNum) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", + winNum); + return MV_BAD_PARAM; + + } + + if (MV_IS_NOT_ALIGN(pAddrWin->addrWin.baseLow, PXWRR_REMAP_ALIGNMENT)) + { + mvOsPrintf("mvPexTargetWinRemap: Error remap PEX interface %d win %d."\ + "\nAddress 0x%08x is unaligned to size 0x%x.\n", + pexIf, + winNum, + pAddrWin->addrWin.baseLow, + pAddrWin->addrWin.size); + + return MV_ERROR; + } + + pexWinRegInfoGet(pexIf, winNum, &winRegInfo); + + /* Set remap low register value */ + MV_REG_WRITE(winRegInfo.remapLowRegOffs, pAddrWin->addrWin.baseLow); + + /* Skip base high settings if the BAR has only base low (32-bit) */ + if (0 != winRegInfo.remapHighRegOffs) + { + MV_REG_WRITE(winRegInfo.remapHighRegOffs, pAddrWin->addrWin.baseHigh); + } + + + if (pAddrWin->enable == MV_TRUE) + { + MV_REG_BIT_SET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + else + { + MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + + return MV_OK; +} + +/******************************************************************************* +* mvPexTargetWinRemapEnable - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ + +MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, + MV_BOOL enable) +{ + PEX_WIN_REG_INFO winRegInfo; + + /* Parameter checking */ + if (pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n", + pexIf); + return MV_BAD_PARAM; + } + if (MV_PEX_WIN_DEFAULT == winNum) + { + mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX win num %d\n", + winNum); + return MV_BAD_PARAM; + + } + + + pexWinRegInfoGet(pexIf, winNum, &winRegInfo); + + if (enable == MV_TRUE) + { + MV_REG_BIT_SET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + else + { + MV_REG_BIT_RESET(winRegInfo.remapLowRegOffs,PXWRR_REMAP_EN); + } + + return MV_OK; + +} + +/******************************************************************************* +* mvPexBarSet - Set PEX bar address and size +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvPexBarSet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin) +{ + MV_U32 regBaseLow; + MV_U32 regSize,sizeToReg; + + + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarSet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarSet: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + + if (pAddrWin->addrWin.size == 0) + { + mvOsPrintf("mvPexBarSet: Size zero is Illigal\n" ); + return MV_BAD_PARAM; + } + + + /* Check if the window complies with PEX spec */ + if (MV_TRUE != pexBarIsValid(pAddrWin->addrWin.baseLow, + pAddrWin->addrWin.size)) + { + mvOsPrintf("mvPexBarSet: ERR. Target %d window invalid\n", barNum); + return MV_BAD_PARAM; + } + + /* 2) Check if the requested bar overlaps with current bars */ + if (MV_TRUE == pexBarOverlapDetect(pexIf,barNum, &pAddrWin->addrWin)) + { + mvOsPrintf("mvPexBarSet: ERR. Target %d overlap\n", barNum); + return MV_BAD_PARAM; + } + + /* Get size register value according to window size */ + sizeToReg = ctrlSizeToReg(pAddrWin->addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT); + + /* Read bar size */ + if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ + { + regSize = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); + + /* Size parameter validity check. */ + if (-1 == sizeToReg) + { + mvOsPrintf("mvPexBarSet: ERR. Target BAR %d size invalid.\n",barNum); + return MV_BAD_PARAM; + } + + regSize &= ~PXBCR_BAR_SIZE_MASK; + regSize |= (sizeToReg << PXBCR_BAR_SIZE_OFFS) ; + + MV_REG_WRITE(PEX_BAR_CTRL_REG(pexIf,barNum),regSize); + + } + + /* set size */ + + + + /* Read base address low */ + regBaseLow = MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf, + PEX_MV_BAR_BASE(barNum))); + + /* clear current base */ + if (PEX_INTER_REGS_BAR == barNum) + { + regBaseLow &= ~PXBIR_BASE_MASK; + regBaseLow |= (pAddrWin->addrWin.baseLow & PXBIR_BASE_MASK); + } + else + { + regBaseLow &= ~PXBR_BASE_MASK; + regBaseLow |= (pAddrWin->addrWin.baseLow & PXBR_BASE_MASK); + } + + /* if we had a previous value that contain the bar type (MeM\IO), we want to + restore it */ + regBaseLow |= PEX_BAR_DEFAULT_ATTRIB; + + + + /* write base low */ + MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum)), + regBaseLow); + + if (pAddrWin->addrWin.baseHigh != 0) + { + /* Read base address high */ + MV_REG_WRITE(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum)), + pAddrWin->addrWin.baseHigh); + + } + + /* lastly enable the Bar */ + if (pAddrWin->enable == MV_TRUE) + { + if (PEX_INTER_REGS_BAR != barNum) /* internal registers + are enabled always */ + { + MV_REG_BIT_SET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + } + } + else if (MV_FALSE == pAddrWin->enable) + { + if (PEX_INTER_REGS_BAR != barNum) /* internal registers + are enabled always */ + { + MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + } + + } + + + + return MV_OK; +} + + +/******************************************************************************* +* mvPexBarGet - Get PEX bar address and size +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ + +MV_STATUS mvPexBarGet(MV_U32 pexIf, + MV_U32 barNum, + MV_PEX_BAR *pAddrWin) +{ + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarGet: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarGet: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + /* read base low */ + pAddrWin->addrWin.baseLow = + MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE(barNum))); + + + if (PEX_INTER_REGS_BAR == barNum) + { + pAddrWin->addrWin.baseLow &= PXBIR_BASE_MASK; + } + else + { + pAddrWin->addrWin.baseLow &= PXBR_BASE_MASK; + } + + + /* read base high */ + pAddrWin->addrWin.baseHigh = + MV_REG_READ(PEX_CFG_DIRECT_ACCESS(pexIf,PEX_MV_BAR_BASE_HIGH(barNum))); + + + /* Read bar size */ + if (PEX_INTER_REGS_BAR != barNum) /* internal registers have no size */ + { + pAddrWin->addrWin.size = MV_REG_READ(PEX_BAR_CTRL_REG(pexIf,barNum)); + + /* check if enable or not */ + if (pAddrWin->addrWin.size & PXBCR_BAR_EN) + { + pAddrWin->enable = MV_TRUE; + } + else + { + pAddrWin->enable = MV_FALSE; + } + + /* now get the size */ + pAddrWin->addrWin.size &= PXBCR_BAR_SIZE_MASK; + pAddrWin->addrWin.size >>= PXBCR_BAR_SIZE_OFFS; + + pAddrWin->addrWin.size = ctrlRegToSize(pAddrWin->addrWin.size, + PXBCR_BAR_SIZE_ALIGNMENT); + + } + else /* PEX_INTER_REGS_BAR */ + { + pAddrWin->addrWin.size = INTER_REGS_SIZE; + pAddrWin->enable = MV_TRUE; + } + + + return MV_OK; +} + +/******************************************************************************* +* mvPexBarEnable - +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ + + +MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable) +{ + + MV_PEX_BAR pexBar; + + /* check parameters */ + if(pexIf >= mvCtrlPexMaxIfGet()) + { + mvOsPrintf("mvPexBarEnable: ERR. Invalid PEX interface %d\n", pexIf); + return MV_BAD_PARAM; + } + + + if(barNum >= PEX_MAX_BARS) + { + mvOsPrintf("mvPexBarEnable: ERR. Invalid bar number %d\n", barNum); + return MV_BAD_PARAM; + } + + if (PEX_INTER_REGS_BAR == barNum) + { + if (MV_TRUE == enable) + { + return MV_OK; + } + else + { + return MV_ERROR; + } + } + + + if (MV_FALSE == enable) + { + /* disable bar and quit */ + MV_REG_BIT_RESET(PEX_BAR_CTRL_REG(pexIf,barNum),PXBCR_BAR_EN); + return MV_OK; + } + + /* else */ + + if (mvPexBarGet(pexIf,barNum,&pexBar) != MV_OK) + { + mvOsPrintf("mvPexBarEnable: mvPexBarGet Failed\n"); + return MV_ERROR; + + } + + if (MV_TRUE == pexBar.enable) + { + /* it is already enabled !!! */ + return MV_OK; + } + + /* else enable the bar*/ + + pexBar.enable = MV_TRUE; + + if (mvPexBarSet(pexIf,barNum,&pexBar) != MV_OK) + { + mvOsPrintf("mvPexBarEnable: mvPexBarSet Failed\n"); + return MV_ERROR; + + } + + return MV_OK; +} + + +/******************************************************************************* +* pexWinOverlapDetect - Detect address windows overlapping +* +* DESCRIPTION: +* This function detects address window overlapping of a given address +* window in PEX BARs. +* +* INPUT: +* pAddrWin - Address window to be checked. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexWinOverlapDetect(MV_U32 pexIf, + MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 win; + MV_PEX_DEC_WIN addrDecWin; + + + for(win = 0; win < PEX_MAX_TARGET_WIN -2 ; win++) + { + /* don't check our target or illegal targets */ + if (winNum == win) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvPexTargetWinGet(pexIf, win, &addrDecWin)) + { + mvOsPrintf("pexWinOverlapDetect: ERR. TargetWinGet failed win=%x\n", + win); + return MV_ERROR; + } + + /* Do not check disabled windows */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin)) + { + mvOsPrintf("pexWinOverlapDetect: winNum %d overlap current %d\n", + winNum, win); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* pexIsWinWithinBar - Detect if address is within PEX bar boundries +* +* DESCRIPTION: +* +* INPUT: +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexIsWinWithinBar(MV_U32 pexIf, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 bar; + MV_PEX_BAR addrDecWin; + + for(bar = 0; bar < PEX_MAX_BARS; bar++) + { + + /* Get window parameters */ + if (MV_OK != mvPexBarGet(pexIf, bar, &addrDecWin)) + { + mvOsPrintf("pexIsWinWithinBar: ERR. mvPexBarGet failed\n"); + return MV_ERROR; + } + + /* Do not check disabled bars */ + if (MV_FALSE == addrDecWin.enable) + { + continue; + } + + + if(MV_TRUE == ctrlWinWithinWinTest(pAddrWin, &addrDecWin.addrWin)) + { + return MV_TRUE; + } + } + + return MV_FALSE; + +} + +/******************************************************************************* +* pexBarOverlapDetect - Detect address windows overlapping +* +* DESCRIPTION: +* This function detects address window overlapping of a given address +* window in PEX BARs. +* +* INPUT: +* pAddrWin - Address window to be checked. +* bar - BAR to be accessed by slave. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_BOOL pexBarOverlapDetect(MV_U32 pexIf, + MV_U32 barNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 bar; + MV_PEX_BAR barDecWin; + + + for(bar = 0; bar < PEX_MAX_BARS; bar++) + { + /* don't check our target or illegal targets */ + if (barNum == bar) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvPexBarGet(pexIf, bar, &barDecWin)) + { + mvOsPrintf("pexBarOverlapDetect: ERR. TargetWinGet failed\n"); + return MV_ERROR; + } + + /* don'nt check disabled bars */ + if (barDecWin.enable == MV_FALSE) + { + continue; + } + + + if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &barDecWin.addrWin)) + { + mvOsPrintf("pexBarOverlapDetect: winNum %d overlap current %d\n", + barNum, bar); + return MV_TRUE; + } + } + + return MV_FALSE; +} + +/******************************************************************************* +* pexBarIsValid - Check if the given address window is valid +* +* DESCRIPTION: +* PEX spec restrict BAR base to be aligned to BAR size. +* This function checks if the given address window is valid. +* +* INPUT: +* baseLow - 32bit low base address. +* size - Window size. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the address window is valid, MV_FALSE otherwise. +* +*******************************************************************************/ +static MV_STATUS pexBarIsValid(MV_U32 baseLow, MV_U32 size) +{ + + /* PCI spec restrict BAR base to be aligned to BAR size */ + if(MV_IS_NOT_ALIGN(baseLow, size)) + { + return MV_ERROR; + } + else + { + return MV_TRUE; + } + + return MV_TRUE; +} + +/******************************************************************************* +* pexBarRegInfoGet - Get BAR register information +* +* DESCRIPTION: +* PEX BARs registers offsets are inconsecutive. +* This function gets a PEX BAR register information like register offsets +* and function location of the BAR. +* +* INPUT: +* pexIf - PEX interface number. +* bar - The PEX BAR in question. +* +* OUTPUT: +* pBarRegInfo - BAR register info struct. +* +* RETURN: +* MV_BAD_PARAM when bad parameters ,MV_ERROR on error ,othewise MV_OK +* +*******************************************************************************/ +static MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, + MV_U32 winNum, + PEX_WIN_REG_INFO *pWinRegInfo) +{ + + if ((winNum >= 0)&&(winNum <=3)) + { + pWinRegInfo->baseLowRegOffs = PEX_WIN0_3_BASE_REG(pexIf,winNum); + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN0_3_CTRL_REG(pexIf,winNum); + pWinRegInfo->remapLowRegOffs = PEX_WIN0_3_REMAP_REG(pexIf,winNum); + pWinRegInfo->remapHighRegOffs = 0; + } + else if ((winNum >= 4)&&(winNum <=5)) + { + pWinRegInfo->baseLowRegOffs = PEX_WIN4_5_BASE_REG(pexIf,winNum); + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN4_5_CTRL_REG(pexIf,winNum); + pWinRegInfo->remapLowRegOffs = PEX_WIN4_5_REMAP_REG(pexIf,winNum); + pWinRegInfo->remapHighRegOffs = PEX_WIN4_5_REMAP_HIGH_REG(pexIf,winNum); + + } + else if (MV_PEX_WIN_DEFAULT == winNum) + { + pWinRegInfo->baseLowRegOffs = 0; + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN_DEFAULT_CTRL_REG(pexIf); + pWinRegInfo->remapLowRegOffs = 0; + pWinRegInfo->remapHighRegOffs = 0; + } + else if (MV_PEX_WIN_EXP_ROM == winNum) + { + pWinRegInfo->baseLowRegOffs = 0; + pWinRegInfo->baseHighRegOffs = 0; + pWinRegInfo->sizeRegOffs = PEX_WIN_EXP_ROM_CTRL_REG(pexIf); + pWinRegInfo->remapLowRegOffs = PEX_WIN_EXP_ROM_REMAP_REG(pexIf); + pWinRegInfo->remapHighRegOffs = 0; + + } + + return MV_OK; +} + +/******************************************************************************* +* pexBarNameGet - Get the string name of PEX BAR. +* +* DESCRIPTION: +* This function get the string name of PEX BAR. +* +* INPUT: +* bar - PEX bar number. +* +* OUTPUT: +* None. +* +* RETURN: +* pointer to the string name of PEX BAR. +* +*******************************************************************************/ +const MV_8* pexBarNameGet( MV_U32 bar ) +{ + switch( bar ) + { + case PEX_INTER_REGS_BAR: + return "Internal Regs Bar0...."; + case PEX_DRAM_BAR: + return "DRAM Bar1............."; + case PEX_DEVICE_BAR: + return "Devices Bar2.........."; + default: + return "Bar unknown"; + } +} +/******************************************************************************* +* mvPexAddrDecShow - Print the PEX address decode map (BARs and windows). +* +* DESCRIPTION: +* This function print the PEX address decode map (BARs and windows). +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvPexAddrDecShow(MV_VOID) +{ + MV_PEX_BAR pexBar; + MV_PEX_DEC_WIN win; + MV_U32 pexIf; + MV_U32 bar,winNum; + + for( pexIf = MV_PEX_START_IF; pexIf < mvCtrlPexMaxIfGet(); pexIf++ ) + { + if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf)) continue; + mvOsOutput( "\n" ); + mvOsOutput( "PEX%d:\n", pexIf ); + mvOsOutput( "-----\n" ); + + mvOsOutput( "\nPex Bars \n\n"); + + for( bar = 0; bar < PEX_MAX_BARS; bar++ ) + { + memset( &pexBar, 0, sizeof(MV_PEX_BAR) ); + + mvOsOutput( "%s ", pexBarNameGet(bar) ); + + if( mvPexBarGet( pexIf, bar, &pexBar ) == MV_OK ) + { + if( pexBar.enable ) + { + mvOsOutput( "base %08x, ", pexBar.addrWin.baseLow ); + mvSizePrint( pexBar.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } + mvOsOutput( "\nPex Decode Windows\n\n"); + + for( winNum = 0; winNum < PEX_MAX_TARGET_WIN - 2; winNum++) + { + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "win%d - ", winNum ); + + if ( mvPexTargetWinGet(pexIf,winNum,&win) == MV_OK) + { + if (win.enable) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + + + } + } + + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "default win - " ); + + if ( mvPexTargetWinGet(pexIf, MV_PEX_WIN_DEFAULT, &win) == MV_OK) + { + mvOsOutput( "%s ", + mvCtrlTargetNameGet(win.target) ); + mvOsOutput( "\n" ); + } + memset( &win, 0,sizeof(MV_PEX_DEC_WIN) ); + + mvOsOutput( "Expansion ROM - " ); + + if ( mvPexTargetWinGet(pexIf, MV_PEX_WIN_EXP_ROM, &win) == MV_OK) + { + mvOsOutput( "%s ", + mvCtrlTargetNameGet(win.target) ); + mvOsOutput( "\n" ); + } + + } +} + + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.h new file mode 100644 index 0000000..3505613 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysPex.h @@ -0,0 +1,348 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCSysPEXH +#define __INCSysPEXH + +#include "mvCommon.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +/* 4KB granularity */ +#define MINIMUM_WINDOW_SIZE 0x1000 +#define MINIMUM_BAR_SIZE 0x1000 +#define MINIMUM_BAR_SIZE_MASK 0xFFFFF000 +#define BAR_SIZE_OFFS 12 +#define BAR_SIZE_MASK (0xFFFFF << BAR_SIZE_OFFS) + + + +#define MV_PEX_WIN_DEFAULT 6 +#define MV_PEX_WIN_EXP_ROM 7 +#define PEX_MAX_TARGET_WIN 8 + + +#define PEX_MAX_BARS 3 +#define PEX_INTER_REGS_BAR 0 +#define PEX_DRAM_BAR 1 +#define PEX_DEVICE_BAR 2 + +/*************************************/ +/* PCI Express BAR Control Registers */ +/*************************************/ +#define PEX_BAR_CTRL_REG(pexIf,bar) (0x41804 + (bar-1)*4- (pexIf)*0x10000) +#define PEX_EXP_ROM_BAR_CTRL_REG(pexIf) (0x4180C - (pexIf)*0x10000) + + +/* PCI Express BAR Control Register */ +/* PEX_BAR_CTRL_REG (PXBCR) */ + +#define PXBCR_BAR_EN BIT0 +#define PXBCR_BAR_SIZE_OFFS 16 +#define PXBCR_BAR_SIZE_MASK (0xffff << PXBCR_BAR_SIZE_OFFS) +#define PXBCR_BAR_SIZE_ALIGNMENT 0x10000 + + + +/* PCI Express Expansion ROM BAR Control Register */ +/* PEX_EXP_ROM_BAR_CTRL_REG (PXERBCR) */ + +#define PXERBCR_EXPROM_EN BIT0 +#define PXERBCR_EXPROMSZ_OFFS 19 +#define PXERBCR_EXPROMSZ_MASK (0xf << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_512KB (0x0 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_1024KB (0x1 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_2048KB (0x3 << PXERBCR_EXPROMSZ_OFFS) +#define PXERBCR_EXPROMSZ_4096KB (0x7 << PXERBCR_EXPROMSZ_OFFS) + +/************************************************/ +/* PCI Express Address Window Control Registers */ +/************************************************/ +#define PEX_WIN0_3_CTRL_REG(pexIf,winNum) \ + (0x41820 + (winNum) * 0x10 - (pexIf) * 0x10000) +#define PEX_WIN0_3_BASE_REG(pexIf,winNum) \ + (0x41824 + (winNum) * 0x10 - (pexIf) * 0x10000) +#define PEX_WIN0_3_REMAP_REG(pexIf,winNum) \ + (0x4182C + (winNum) * 0x10 - (pexIf) * 0x10000) +#define PEX_WIN4_5_CTRL_REG(pexIf,winNum) \ + (0x41860 + (winNum - 4) * 0x20 - (pexIf) * 0x10000) +#define PEX_WIN4_5_BASE_REG(pexIf,winNum) \ + (0x41864 + (winNum - 4) * 0x20 - (pexIf) * 0x10000) +#define PEX_WIN4_5_REMAP_REG(pexIf,winNum) \ + (0x4186C + (winNum - 4) * 0x20 - (pexIf) * 0x10000) +#define PEX_WIN4_5_REMAP_HIGH_REG(pexIf,winNum) \ + (0x41870 + (winNum - 4) * 0x20 - (pexIf) * 0x10000) + +#define PEX_WIN_DEFAULT_CTRL_REG(pexIf) (0x418B0 - (pexIf) * 0x10000) +#define PEX_WIN_EXP_ROM_CTRL_REG(pexIf) (0x418C0 - (pexIf) * 0x10000) +#define PEX_WIN_EXP_ROM_REMAP_REG(pexIf) (0x418C4 - (pexIf) * 0x10000) + +/* PCI Express Window Control Register */ +/* PEX_WIN_CTRL_REG (PXWCR) */ + +#define PXWCR_WIN_EN BIT0 /* Window Enable.*/ + +#define PXWCR_WIN_BAR_MAP_OFFS 1 /* Mapping to BAR.*/ +#define PXWCR_WIN_BAR_MAP_MASK BIT1 +#define PXWCR_WIN_BAR_MAP_BAR1 (0 << PXWCR_WIN_BAR_MAP_OFFS) +#define PXWCR_WIN_BAR_MAP_BAR2 (1 << PXWCR_WIN_BAR_MAP_OFFS) + +#define PXWCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWCR_TARGET_MASK (0xf << PXWCR_TARGET_OFFS) + +#define PXWCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWCR_ATTRIB_MASK (0xff << PXWCR_ATTRIB_OFFS) + +#define PXWCR_SIZE_OFFS 16 /* size */ +#define PXWCR_SIZE_MASK (0xffff << PXWCR_SIZE_OFFS) +#define PXWCR_SIZE_ALIGNMENT 0x10000 + +/* PCI Express Window Base Register */ +/* PEX_WIN_BASE_REG (PXWBR)*/ + +#define PXWBR_BASE_OFFS 16 /* address[31:16] */ +#define PXWBR_BASE_MASK (0xffff << PXWBR_BASE_OFFS) +#define PXWBR_BASE_ALIGNMENT 0x10000 + +/* PCI Express Window Remap Register */ +/* PEX_WIN_REMAP_REG (PXWRR)*/ + +#define PXWRR_REMAP_EN BIT0 +#define PXWRR_REMAP_OFFS 16 +#define PXWRR_REMAP_MASK (0xffff << PXWRR_REMAP_OFFS) +#define PXWRR_REMAP_ALIGNMENT 0x10000 + +/* PCI Express Window Remap (High) Register */ +/* PEX_WIN_REMAP_HIGH_REG (PXWRHR)*/ + +#define PXWRHR_REMAP_HIGH_OFFS 0 +#define PXWRHR_REMAP_HIGH_MASK (0xffffffff << PXWRHR_REMAP_HIGH_OFFS) + +/* PCI Express Default Window Control Register */ +/* PEX_WIN_DEFAULT_CTRL_REG (PXWDCR) */ + +#define PXWDCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWDCR_TARGET_MASK (0xf << PXWDCR_TARGET_OFFS) +#define PXWDCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWDCR_ATTRIB_MASK (0xff << PXWDCR_ATTRIB_OFFS) + +/* PCI Express Expansion ROM Window Control Register */ +/* PEX_WIN_EXP_ROM_CTRL_REG (PXWERCR)*/ + +#define PXWERCR_TARGET_OFFS 4 /*Unit ID */ +#define PXWERCR_TARGET_MASK (0xf << PXWERCR_TARGET_OFFS) +#define PXWERCR_ATTRIB_OFFS 8 /* target attributes */ +#define PXWERCR_ATTRIB_MASK (0xff << PXWERCR_ATTRIB_OFFS) + +/* PCI Express Expansion ROM Window Remap Register */ +/* PEX_WIN_EXP_ROM_REMAP_REG (PXWERRR)*/ + +#define PXWERRR_REMAP_EN BIT0 +#define PXWERRR_REMAP_OFFS 16 +#define PXWERRR_REMAP_MASK (0xffff << PXWERRR_REMAP_OFFS) +#define PXWERRR_REMAP_ALIGNMENT 0x10000 + + + +/*PEX_MEMORY_BAR_BASE_ADDR(barNum) (PXMBBA)*/ +/* PCI Express BAR0 Internal Register*/ +/*PEX BAR0_INTER_REG (PXBIR)*/ + +#define PXBIR_IOSPACE BIT0 /* Memory Space Indicator */ + +#define PXBIR_TYPE_OFFS 1 /* BAR Type/Init Val. */ +#define PXBIR_TYPE_MASK (0x3 << PXBIR_TYPE_OFFS) +#define PXBIR_TYPE_32BIT_ADDR (0x0 << PXBIR_TYPE_OFFS) +#define PXBIR_TYPE_64BIT_ADDR (0x2 << PXBIR_TYPE_OFFS) + +#define PXBIR_PREFETCH_EN BIT3 /* Prefetch Enable */ + +#define PXBIR_BASE_OFFS 20 /* Base address. Address bits [31:20] */ +#define PXBIR_BASE_MASK (0xfff << PXBIR_BASE_OFFS) +#define PXBIR_BASE_ALIGNMET (1 << PXBIR_BASE_OFFS) + + +/* PCI Express BAR0 Internal (High) Register*/ +/*PEX BAR0_INTER_REG_HIGH (PXBIRH)*/ + +#define PXBIRH_BASE_OFFS 0 /* Base address. Bits [63:32] */ +#define PXBIRH_BASE_MASK (0xffffffff << PBBHR_BASE_OFFS) + + +#define PEX_BAR_DEFAULT_ATTRIB 0xc /* Memory - Prefetch - 64 bit address */ +#define PEX_BAR0_DEFAULT_ATTRIB PEX_BAR_DEFAULT_ATTRIB +#define PEX_BAR1_DEFAULT_ATTRIB PEX_BAR_DEFAULT_ATTRIB +#define PEX_BAR2_DEFAULT_ATTRIB PEX_BAR_DEFAULT_ATTRIB + + +/* PCI Express BAR1 Register */ +/* PCI Express BAR2 Register*/ +/*PEX BAR1_REG (PXBR)*/ +/*PEX BAR2_REG (PXBR)*/ + +#define PXBR_IOSPACE BIT0 /* Memory Space Indicator */ + +#define PXBR_TYPE_OFFS 1 /* BAR Type/Init Val. */ +#define PXBR_TYPE_MASK (0x3 << PXBR_TYPE_OFFS) +#define PXBR_TYPE_32BIT_ADDR (0x0 << PXBR_TYPE_OFFS) +#define PXBR_TYPE_64BIT_ADDR (0x2 << PXBR_TYPE_OFFS) + +#define PXBR_PREFETCH_EN BIT3 /* Prefetch Enable */ + +#define PXBR_BASE_OFFS 16 /* Base address. Address bits [31:16] */ +#define PXBR_BASE_MASK (0xffff << PXBR_BASE_OFFS) +#define PXBR_BASE_ALIGNMET (1 << PXBR_BASE_OFFS) + + +/* PCI Express BAR1 (High) Register*/ +/* PCI Express BAR2 (High) Register*/ +/*PEX BAR1_REG_HIGH (PXBRH)*/ +/*PEX BAR2_REG_HIGH (PXBRH)*/ + +#define PXBRH_BASE_OFFS 0 /* Base address. Address bits [63:32] */ +#define PXBRH_BASE_MASK (0xffffffff << PXBRH_BASE_OFFS) + +/* PCI Express Expansion ROM BAR Register*/ +/*PEX_EXPANSION_ROM_BASE_ADDR_REG (PXERBAR)*/ + +#define PXERBAR_EXPROMEN BIT0 /* Expansion ROM Enable */ + +#define PXERBAR_BASE_512K_OFFS 19 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_512K_MASK (0x1fff << PXERBAR_BASE_512K_OFFS) + +#define PXERBAR_BASE_1MB_OFFS 20 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_1MB_MASK (0xfff << PXERBAR_BASE_1MB_OFFS) + +#define PXERBAR_BASE_2MB_OFFS 21 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_2MB_MASK (0x7ff << PXERBAR_BASE_2MB_OFFS) + +#define PXERBAR_BASE_4MB_OFFS 22 /* Expansion ROM Base Address */ +#define PXERBAR_BASE_4MB_MASK (0x3ff << PXERBAR_BASE_4MB_OFFS) + +/* PEX Bar attributes */ +typedef struct _mvPexBar +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_PEX_BAR; + +/* PEX Remap Window attributes */ +typedef struct _mvPexRemapWin +{ + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_PEX_REMAP_WIN; + +/* PEX Remap Window attributes */ +typedef struct _mvPexDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_U32 targetBar; + MV_U8 attrib; /* chip select attributes */ + MV_TARGET_ID targetId; /* Target Id of this MV_TARGET */ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_PEX_DEC_WIN; + +/* Global Functions prototypes */ +/* mvPexHalInit - Initialize PEX interfaces*/ +MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType); + + +/* mvPexTargetWinSet - Set PEX to peripheral target address window BAR*/ +MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin); + +/* mvPexTargetWinGet - Get PEX to peripheral target address window*/ +MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_DEC_WIN *pAddrDecWin); + +/* mvPexTargetWinEnable - Enable/disable a PEX BAR window*/ +MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf,MV_U32 winNum, MV_BOOL enable); + +/* mvPexTargetWinRemap - Set PEX to target address window remap.*/ +MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum, + MV_PEX_REMAP_WIN *pAddrWin); + +/* mvPexTargetWinRemapEnable -enable\disable a PEX Window remap.*/ +MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum, + MV_BOOL enable); + +/* mvPexBarSet - Set PEX bar address and size */ +MV_STATUS mvPexBarSet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *addrWin); + +/* mvPexBarGet - Get PEX bar address and size */ +MV_STATUS mvPexBarGet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *addrWin); + +/* mvPexBarEnable - enable\disable a PEX bar*/ +MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable); + +/* mvPexAddrDecShow - Display address decode windows attributes */ +MV_VOID mvPexAddrDecShow(MV_VOID); + +#endif diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.c b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.c new file mode 100644 index 0000000..082cb4b --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.c @@ -0,0 +1,427 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#include "mvTypes.h" +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "cpu/mvCpu.h" +#include "ctrlEnv/sys/mvCpuIf.h" +#include "sata/CoreDriver/mvRegs.h" +#include "ctrlEnv/sys/mvSysSata.h" + +MV_TARGET sataAddrDecPrioTab[] = +{ +#if defined(MV_INCLUDE_SDRAM_CS0) + SDRAM_CS0, +#endif +#if defined(MV_INCLUDE_SDRAM_CS1) + SDRAM_CS1, +#endif +#if defined(MV_INCLUDE_SDRAM_CS2) + SDRAM_CS2, +#endif +#if defined(MV_INCLUDE_SDRAM_CS3) + SDRAM_CS3, +#endif +#if defined(MV_INCLUDE_PEX) + PEX0_MEM, +#endif +#if defined(MV_INCLUDE_PCI) + PCI0_MEM, +#endif + TBL_TERM +}; + + +/******************************************************************************* +* sataWinOverlapDetect - Detect SATA address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviur is expected in case SATA address decode +* windows overlapps. +* This function detects SATA address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS sataWinOverlapDetect(int dev, MV_U32 winNum, + MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_SATA_DEC_WIN addrDecWin; + + for(winNumIndex=0; winNumIndex= MV_SATA_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == sataWinOverlapDetect(dev, winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvSataWinSet:Error setting SATA window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = 0; + decRegs.sizeReg = 0; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* set attributes */ + decRegs.sizeReg &= ~MV_SATA_WIN_ATTR_MASK; + decRegs.sizeReg |= (targetAttribs.attrib << MV_SATA_WIN_ATTR_OFFSET); + + /* set target ID */ + decRegs.sizeReg &= ~MV_SATA_WIN_TARGET_MASK; + decRegs.sizeReg |= (targetAttribs.targetId << MV_SATA_WIN_TARGET_OFFSET); + + if (pAddrDecWin->enable == MV_TRUE) + { + decRegs.sizeReg |= MV_SATA_WIN_ENABLE_MASK; + } + else + { + decRegs.sizeReg &= ~MV_SATA_WIN_ENABLE_MASK; + } + + MV_REG_WRITE( MV_SATA_WIN_CTRL_REG(dev, winNum), decRegs.sizeReg); + MV_REG_WRITE( MV_SATA_WIN_BASE_REG(dev, winNum), decRegs.baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvSataWinGet - Get SATA peripheral target address window. +* +* DESCRIPTION: +* Get SATA peripheral target address window. +* +* INPUT: +* winNum - SATA target address decode window number. +* +* OUTPUT: +* pAddrDecWin - SATA target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSataWinGet(int dev, MV_U32 winNum, MV_SATA_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= MV_SATA_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", + __FUNCTION__, dev, winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ( MV_SATA_WIN_BASE_REG(dev, winNum) ); + decRegs.sizeReg = MV_REG_READ( MV_SATA_WIN_CTRL_REG(dev, winNum) ); + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) ) + { + mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = (decRegs.sizeReg & MV_SATA_WIN_ATTR_MASK) >> + MV_SATA_WIN_ATTR_OFFSET; + targetAttrib.targetId = (decRegs.sizeReg & MV_SATA_WIN_TARGET_MASK) >> + MV_SATA_WIN_TARGET_OFFSET; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if(decRegs.sizeReg & MV_SATA_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + return MV_OK; +} +/******************************************************************************* +* mvSataAddrDecShow - Print the SATA address decode map. +* +* DESCRIPTION: +* This function print the SATA address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvSataAddrDecShow(MV_VOID) +{ + + MV_SATA_DEC_WIN win; + int i; + + if (MV_FALSE == mvCtrlPwrClckGet(SATA_UNIT_ID, 0)) return; + + mvOsOutput( "\n" ); + mvOsOutput( "SATA:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < MV_SATA_MAX_ADDR_DECODE_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_SATA_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvSataWinGet(0, i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + mvOsOutput( "...." ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + + +/******************************************************************************* +* mvSataWinInit - Initialize the integrated SATA target address window. +* +* DESCRIPTION: +* Initialize the SATA peripheral target address window. +* +* INPUT: +* +* +* OUTPUT: +* +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvSataWinInit(MV_VOID) +{ + int winNum; + MV_SATA_DEC_WIN sataWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + MV_U32 status, winPrioIndex = 0; + + /* Initiate Sata address decode */ + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_SATA_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_U32 regVal = MV_REG_READ(MV_SATA_WIN_CTRL_REG(0, winNum)); + regVal &= ~MV_SATA_WIN_ENABLE_MASK; + MV_REG_WRITE(MV_SATA_WIN_CTRL_REG(0, winNum), regVal); + } + + winNum = 0; + while( (sataAddrDecPrioTab[winPrioIndex] != TBL_TERM) && + (winNum < MV_SATA_MAX_ADDR_DECODE_WIN) ) + { + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(sataAddrDecPrioTab[winPrioIndex], + &cpuAddrDecWin); + + if(MV_NO_SUCH == status) + { + winPrioIndex++; + continue; + } + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + sataWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + sataWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + sataWin.addrWin.size = cpuAddrDecWin.addrWin.size; + sataWin.enable = MV_TRUE; + sataWin.target = sataAddrDecPrioTab[winPrioIndex]; + + if(MV_OK != mvSataWinSet(0/*dev*/, winNum, &sataWin)) + { + return MV_ERROR; + } + winNum++; + } + winPrioIndex++; + } + return MV_OK; +} + + + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.h new file mode 100644 index 0000000..325fb8d --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysSata.h @@ -0,0 +1,128 @@ + +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef __INCMVSysSataAddrDech +#define __INCMVSysSataAddrDech + +#include "mvCommon.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/sys/mvCpuIf.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _mvSataDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +} MV_SATA_DEC_WIN; + + +#define MV_SATA_MAX_ADDR_DECODE_WIN 4 + +#define MV_SATA_WIN_CTRL_REG(dev, win) (SATA_REG_BASE + 0x30 + ((win)<<4)) +#define MV_SATA_WIN_BASE_REG(dev, win) (SATA_REG_BASE + 0x34 + ((win)<<4)) + +/* BITs in Bridge Interrupt Cause and Mask registers */ +#define MV_SATA_ADDR_DECODE_ERROR_BIT 0 +#define MV_SATA_ADDR_DECODE_ERROR_MASK (1<= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinSet: ERR. Invalid win num %d\n",winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == tdmWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) + { + mvOsPrintf("mvTdmWinSet: ERR. Window %d overlap\n", winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) + { + mvOsPrintf("mvTdmWinSet: Error setting TDM window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pAddrDecWin->target), + pAddrDecWin->addrWin.baseLow, + pAddrDecWin->addrWin.size); + return MV_ERROR; + } + + decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum)); + decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS; + + if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs)) + { + mvOsPrintf("mvTdmWinSet: mvCtrlAddrDecToReg Failed\n"); + return MV_ERROR; + } + + mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs); + + /* for the safe side we disable the window before writing the new + values */ + mvTdmWinEnable(winNum, MV_FALSE); + + ctrlReg |= (targetAttribs.attrib << TDM_WIN_ATTRIB_OFFS); + ctrlReg |= (targetAttribs.targetId << TDM_WIN_TARGET_OFFS); + ctrlReg |= (decRegs.sizeReg << TDM_WIN_SIZE_OFFS); + + /* Write to address base and control registers */ + MV_REG_WRITE(TDM_WIN_BASE_REG(winNum), decRegs.baseReg); + MV_REG_WRITE(TDM_WIN_CTRL_REG(winNum), ctrlReg); + /* Enable address decode target window */ + if (pAddrDecWin->enable == MV_TRUE) + { + mvTdmWinEnable(winNum, MV_TRUE); + } + return MV_OK; +} + +/******************************************************************************* +* mvTdmWinGet - Get peripheral target address window. +* +* DESCRIPTION: +* Get TDM peripheral target address window. +* +* INPUT: +* winNum - TDM to target address decode window number. +* +* OUTPUT: +* pAddrDecWin - TDM target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ + +MV_STATUS mvTdmWinGet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin) +{ + + MV_DEC_REGS decRegs; + MV_TARGET_ATTRIB targetAttrib; + + /* Parameter checking */ + if (winNum >= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinGet: ERR. Invalid winNum %d\n", winNum); + return MV_NOT_SUPPORTED; + } + + decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum)); + decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >> TDM_WIN_SIZE_OFFS; + + if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin))) + { + mvOsPrintf("mvTdmWinGet: mvCtrlRegToAddrDec Failed \n"); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ATTRIB_MASK) >> TDM_WIN_ATTRIB_OFFS; + targetAttrib.targetId = + (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_TARGET_MASK) >> TDM_WIN_TARGET_OFFS; + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + /* Check if window is enabled */ + if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK) + { + pAddrDecWin->enable = MV_TRUE; + } + else + { + pAddrDecWin->enable = MV_FALSE; + } + + return MV_OK; +} + +/******************************************************************************* +* mvTdmWinEnable - Enable/disable a TDM to target address window +* +* DESCRIPTION: +* This function enable/disable a TDM to target address window. +* According to parameter 'enable' the routine will enable the +* window, thus enabling TDM accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - TDM to target address decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* N/A +* +* RETURN: +* MV_ERROR if decode window number was wrong or enabled window overlapps. +* +*******************************************************************************/ +MV_STATUS mvTdmWinEnable(int winNum, MV_BOOL enable) +{ + MV_TDM_DEC_WIN addrDecWin; + + if (MV_TRUE == enable) + { + if (winNum >= TDM_MBUS_MAX_WIN) + { + mvOsPrintf("mvTdmWinEnable:ERR. Invalid winNum%d\n",winNum); + return MV_ERROR; + } + + /* First check for overlap with other enabled windows */ + /* Get current window */ + if (MV_OK != mvTdmWinGet(winNum, &addrDecWin)) + { + mvOsPrintf("mvTdmWinEnable:ERR. targetWinGet fail\n"); + return MV_ERROR; + } + /* Check for overlapping */ + if (MV_FALSE == tdmWinOverlapDetect(winNum, &(addrDecWin.addrWin))) + { + /* No Overlap. Enable address decode target window */ + MV_REG_BIT_SET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK); + } + else + { /* Overlap detected */ + mvOsPrintf("mvTdmWinEnable:ERR. Overlap detected\n"); + return MV_ERROR; + } + } + else + { + MV_REG_BIT_RESET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK); + } + return MV_OK; +} + + +/******************************************************************************* +* tdmWinOverlapDetect - Detect TDM address windows overlapping +* +* DESCRIPTION: +* An unpredicted behaviour is expected in case TDM address decode +* windows overlapps. +* This function detects TDM address decode windows overlapping of a +* specified window. The function does not check the window itself for +* overlapping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS tdmWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 winNumIndex; + MV_TDM_DEC_WIN addrDecWin; + + for (winNumIndex = 0; winNumIndex < TDM_MBUS_MAX_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + /* Do not check disabled windows */ + if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK) + { + /* Get window parameters */ + if (MV_OK != mvTdmWinGet(winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("dmaWinOverlapDetect: ERR. TargetWinGet failed\n")); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + } + return MV_FALSE; +} + +/******************************************************************************* +* mvTdmAddrDecShow - Print the TDM address decode map. +* +* DESCRIPTION: +* This function print the TDM address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvTdmAddrDecShow(MV_VOID) +{ + MV_TDM_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "TDM:\n" ); + mvOsOutput( "----\n" ); + + for( i = 0; i < TDM_MBUS_MAX_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_TDM_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if (mvTdmWinGet(i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %08x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow); + mvOsOutput( "...." ); + mvSizePrint( win.addrWin.size ); + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysTdm.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysTdm.h new file mode 100644 index 0000000..596c6c3 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysTdm.h @@ -0,0 +1,92 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvSysTdmh +#define __INCmvSysTdmh + +#include "ctrlEnv/sys/mvCpuIf.h" +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define TDM_MBUS_MAX_WIN 4 +#define TDM_WIN_CTRL_REG(win) ((TDM_REG_BASE +0x4030) + (win<<4)) +#define TDM_WIN_BASE_REG(win) ((TDM_REG_BASE +0x4034) + (win<<4)) + +/* TDM_WIN_CTRL_REG bits */ +#define TDM_WIN_ENABLE_OFFS 0 +#define TDM_WIN_ENABLE_MASK (1<= MV_USB_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum); + return MV_BAD_PARAM; + } + + /* Check if the requested window overlapps with current windows */ + if (MV_TRUE == usbWinOverlapDetect(dev, winNum, &pDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, winNum); + return MV_ERROR; + } + + /* check if address is aligned to the size */ + if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size)) + { + mvOsPrintf("mvUsbWinSet:Error setting USB window %d to "\ + "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n", + winNum, + mvCtrlTargetNameGet(pDecWin->target), + pDecWin->addrWin.baseLow, + pDecWin->addrWin.size); + return MV_ERROR; + } + + if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams)) + { + mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* set Size, Attributes and TargetID */ + sizeReg = (((winParams.targetId << MV_USB_WIN_TARGET_OFFSET) & MV_USB_WIN_TARGET_MASK) | + ((winParams.attrib << MV_USB_WIN_ATTR_OFFSET) & MV_USB_WIN_ATTR_MASK) | + ((winParams.size << MV_USB_WIN_SIZE_OFFSET) & MV_USB_WIN_SIZE_MASK)); + +#if defined(MV645xx) || defined(MV646xx) + /* If window is DRAM with HW cache coherency, make sure bit2 is set */ + sizeReg &= ~MV_USB_WIN_BURST_WR_LIMIT_MASK; + + if((MV_TARGET_IS_DRAM(pDecWin->target)) && + (pDecWin->addrWinAttr.cachePolicy != NO_COHERENCY)) + { + sizeReg |= MV_USB_WIN_BURST_WR_32BIT_LIMIT; + } + else + { + sizeReg |= MV_USB_WIN_BURST_WR_NO_LIMIT; + } +#endif /* MV645xx || MV646xx */ + + if (pDecWin->enable == MV_TRUE) + { + sizeReg |= MV_USB_WIN_ENABLE_MASK; + } + else + { + sizeReg &= ~MV_USB_WIN_ENABLE_MASK; + } + + /* Update Base value */ + baseReg = (winParams.baseAddr & MV_USB_WIN_BASE_MASK); + + MV_REG_WRITE( MV_USB_WIN_CTRL_REG(dev, winNum), sizeReg); + MV_REG_WRITE( MV_USB_WIN_BASE_REG(dev, winNum), baseReg); + + return MV_OK; +} + +/******************************************************************************* +* mvUsbWinGet - Get USB peripheral target address window. +* +* DESCRIPTION: +* Get USB peripheral target address window. +* +* INPUT: +* winNum - USB target address decode window number. +* +* OUTPUT: +* pDecWin - USB target window data structure. +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvUsbWinGet(int dev, MV_U32 winNum, MV_DEC_WIN *pDecWin) +{ + MV_DEC_WIN_PARAMS winParam; + MV_U32 sizeReg, baseReg; + + /* Parameter checking */ + if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN) + { + mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n", + __FUNCTION__, dev, winNum); + return MV_NOT_SUPPORTED; + } + + baseReg = MV_REG_READ( MV_USB_WIN_BASE_REG(dev, winNum) ); + sizeReg = MV_REG_READ( MV_USB_WIN_CTRL_REG(dev, winNum) ); + + /* Check if window is enabled */ + if(sizeReg & MV_USB_WIN_ENABLE_MASK) + { + pDecWin->enable = MV_TRUE; + + /* Extract window parameters from registers */ + winParam.targetId = (sizeReg & MV_USB_WIN_TARGET_MASK) >> MV_USB_WIN_TARGET_OFFSET; + winParam.attrib = (sizeReg & MV_USB_WIN_ATTR_MASK) >> MV_USB_WIN_ATTR_OFFSET; + winParam.size = (sizeReg & MV_USB_WIN_SIZE_MASK) >> MV_USB_WIN_SIZE_OFFSET; + winParam.baseAddr = (baseReg & MV_USB_WIN_BASE_MASK); + + /* Translate the decode window parameters to address decode struct */ + if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin)) + { + mvOsPrintf("Failed to translate register parameters to USB address" \ + " decode window structure\n"); + return MV_ERROR; + } + } + else + { + pDecWin->enable = MV_FALSE; + } + return MV_OK; +} + +/******************************************************************************* +* mvUsbWinInit - +* +* INPUT: +* +* OUTPUT: +* +* RETURN: +* MV_ERROR if register parameters are invalid. +* +*******************************************************************************/ +MV_STATUS mvUsbWinInit(int dev) +{ + MV_STATUS status; + MV_DEC_WIN usbWin; + MV_CPU_DEC_WIN cpuAddrDecWin; + int winNum; + MV_U32 winPrioIndex = 0; + + /* First disable all address decode windows */ + for(winNum = 0; winNum < MV_USB_MAX_ADDR_DECODE_WIN; winNum++) + { + MV_REG_BIT_RESET(MV_USB_WIN_CTRL_REG(dev, winNum), MV_USB_WIN_ENABLE_MASK); + } + + /* Go through all windows in user table until table terminator */ + winNum = 0; + while( (usbAddrDecPrioTab[winPrioIndex] != TBL_TERM) && + (winNum < MV_USB_MAX_ADDR_DECODE_WIN) ) + { + /* first get attributes from CPU If */ + status = mvCpuIfTargetWinGet(usbAddrDecPrioTab[winPrioIndex], + &cpuAddrDecWin); + + if(MV_NO_SUCH == status) + { + winPrioIndex++; + continue; + } + if (MV_OK != status) + { + mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); + return MV_ERROR; + } + + if (cpuAddrDecWin.enable == MV_TRUE) + { + usbWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh; + usbWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow; + usbWin.addrWin.size = cpuAddrDecWin.addrWin.size; + usbWin.enable = MV_TRUE; + usbWin.target = usbAddrDecPrioTab[winPrioIndex]; + +#if defined(MV645xx) || defined(MV646xx) + /* Get the default attributes for that target window */ + mvCtrlDefAttribGet(usbWin.target, &usbWin.addrWinAttr); +#endif /* MV645xx || MV646xx */ + + if(MV_OK != mvUsbWinSet(dev, winNum, &usbWin)) + { + return MV_ERROR; + } + winNum++; + } + winPrioIndex++; + } + return MV_OK; +} + +/******************************************************************************* +* mvUsbAddrDecShow - Print the USB address decode map. +* +* DESCRIPTION: +* This function print the USB address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvUsbAddrDecShow(MV_VOID) +{ + MV_DEC_WIN addrDecWin; + int i, winNum; + + mvOsOutput( "\n" ); + mvOsOutput( "USB:\n" ); + mvOsOutput( "----\n" ); + + for(i=0; i= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + if (pAddrDecWin == NULL) + { + DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + /* Check if the requested window overlaps with current windows */ + if (MV_TRUE == xorWinOverlapDetect(unit, winNum, &pAddrDecWin->addrWin)) + { + DB(mvOsPrintf("%s: ERR. Window %d overlap\n",__FUNCTION__,winNum)); + return MV_ERROR; + } + + xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum)); + xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum)); + + /* Get Base Address and size registers values */ + if(MV_OK != mvCtrlAddrDecToReg(&pAddrDecWin->addrWin, &xorDecRegs)) + { + DB(mvOsPrintf("%s: ERR. Invalid addr dec window\n",__FUNCTION__)); + return MV_BAD_PARAM; + } + + + mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs); + + /* set attributes */ + xorDecRegs.baseReg &= ~XEBARX_ATTR_MASK; + xorDecRegs.baseReg |= targetAttribs.attrib << XEBARX_ATTR_OFFS; + /* set target ID */ + xorDecRegs.baseReg &= ~XEBARX_TARGET_MASK; + xorDecRegs.baseReg |= targetAttribs.targetId << XEBARX_TARGET_OFFS; + + + /* Write to address decode Base Address Register */ + MV_REG_WRITE(XOR_BASE_ADDR_REG(unit,winNum), xorDecRegs.baseReg); + + /* Write to Size Register */ + MV_REG_WRITE(XOR_SIZE_MASK_REG(unit,winNum), xorDecRegs.sizeReg); + + for (chan = 0; chan < MV_XOR_MAX_CHAN; chan++) + { + if (pAddrDecWin->enable) + { + MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + else + { + MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + } + return MV_OK; +} + +/******************************************************************************* +* mvXorTargetWinGet - Get xor peripheral target address window. +* +* DESCRIPTION: +* Get xor peripheral target address window. +* +* INPUT: +* winNum - One of the possible XOR memory decode windows. +* +* OUTPUT: +* base - Window base address. +* size - Window size. +* enable - window enable/disable. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorTargetWinGet(MV_U32 unit,MV_U32 winNum, MV_XOR_DEC_WIN *pAddrDecWin) +{ + MV_DEC_REGS xorDecRegs; + MV_TARGET_ATTRIB targetAttrib; + MV_U32 chan=0,chanWinEn; + + /* Parameter checking */ + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__ , winNum)); + return MV_ERROR; + } + + if (NULL == pAddrDecWin) + { + DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + + chanWinEn = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,0)) & XEXWCR_WIN_EN_MASK(winNum); + + for (chan = 0; chan < MV_XOR_MAX_CHAN_PER_UNIT; chan++) + { + /* Check if enable bit is equal for all channels */ + if ((MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)) & + XEXWCR_WIN_EN_MASK(winNum)) != chanWinEn) + { + mvOsPrintf("%s: ERR. Window enable field must be equal in " + "all channels\n",__FUNCTION__); + return MV_ERROR; + } + } + + + + xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum)); + xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum)); + + if (MV_OK != mvCtrlRegToAddrDec(&xorDecRegs, &pAddrDecWin->addrWin)) + { + mvOsPrintf("%s: ERR. mvCtrlRegToAddrDec failed\n", __FUNCTION__); + return MV_ERROR; + } + + /* attrib and targetId */ + targetAttrib.attrib = + (xorDecRegs.baseReg & XEBARX_ATTR_MASK) >> XEBARX_ATTR_OFFS; + targetAttrib.targetId = + (xorDecRegs.baseReg & XEBARX_TARGET_MASK) >> XEBARX_TARGET_OFFS; + + + pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib); + + if(chanWinEn) + { + pAddrDecWin->enable = MV_TRUE; + } + else pAddrDecWin->enable = MV_FALSE; + + return MV_OK; +} + +/******************************************************************************* +* mvXorTargetWinEnable - Enable/disable a Xor address decode window +* +* DESCRIPTION: +* This function enable/disable a XOR address decode window. +* if parameter 'enable' == MV_TRUE the routine will enable the +* window, thus enabling XOR accesses (before enabling the window it is +* tested for overlapping). Otherwise, the window will be disabled. +* +* INPUT: +* winNum - Decode window number. +* enable - Enable/disable parameter. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorTargetWinEnable(MV_U32 unit,MV_U32 winNum, MV_BOOL enable) +{ + MV_XOR_DEC_WIN addrDecWin; + MV_U32 chan; + + /* Parameter checking */ + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid winNum%d\n", __FUNCTION__, winNum)); + return MV_ERROR; + } + + if (enable == MV_TRUE) + { + /* Get current window */ + if (MV_OK != mvXorTargetWinGet(unit,winNum, &addrDecWin)) + { + DB(mvOsPrintf("%s: ERR. targetWinGet fail\n", __FUNCTION__)); + return MV_ERROR; + } + + /* Check for overlapping */ + if (MV_TRUE == xorWinOverlapDetect(unit,winNum, &(addrDecWin.addrWin))) + { + /* Overlap detected */ + DB(mvOsPrintf("%s: ERR. Overlap detected\n", __FUNCTION__)); + return MV_ERROR; + } + + /* No Overlap. Enable address decode target window */ + for (chan = 0; chan < MV_XOR_MAX_CHAN; chan++) + { + MV_REG_BIT_SET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + + } + else + { + /* Disable address decode target window */ + + for (chan = 0; chan < MV_XOR_MAX_CHAN; chan++) + { + MV_REG_BIT_RESET(XOR_WINDOW_CTRL_REG(unit,chan), + XEXWCR_WIN_EN_MASK(winNum)); + } + + } + + return MV_OK; +} + +/******************************************************************************* +* mvXorSetProtWinSet - Configure access attributes of a XOR engine +* to one of the XOR memory windows. +* +* DESCRIPTION: +* Each engine can be configured with access attributes for each of the +* memory spaces. This function sets access attributes +* to a given window for the given engine +* +* INPUTS: +* chan - One of the possible engines. +* winNum - One of the possible XOR memory spaces. +* access - Protection access rights. +* write - Write rights. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorProtWinSet (MV_U32 unit,MV_U32 chan, MV_U32 winNum, MV_BOOL access, + MV_BOOL write) +{ + MV_U32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) + { + DB(mvOsPrintf("%s: ERR. Invalid chan num %d\n", __FUNCTION__ , chan)); + return MV_BAD_PARAM; + } + if (winNum >= XOR_MAX_ADDR_DEC_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + + temp = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)) & + (~XEXWCR_WIN_ACC_MASK(winNum)); + + /* if access is disable */ + if (!access) + { + /* disable access */ + temp |= XEXWCR_WIN_ACC_NO_ACC(winNum); + } + /* if access is enable */ + else + { + /* if write is enable */ + if (write) + { + /* enable write */ + temp |= XEXWCR_WIN_ACC_RW(winNum); + } + /* if write is disable */ + else + { + /* disable write */ + temp |= XEXWCR_WIN_ACC_RO(winNum); + } + } + MV_REG_WRITE(XOR_WINDOW_CTRL_REG(unit,chan),temp); + return MV_OK; +} + +/******************************************************************************* +* mvXorPciRemap - Set XOR remap register for PCI address windows. +* +* DESCRIPTION: +* only Windows 0-3 can be remapped. +* +* INPUT: +* winNum - window number +* pAddrDecWin - pointer to address space window structure +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +MV_STATUS mvXorPciRemap(MV_U32 unit,MV_U32 winNum, MV_U32 addrHigh) +{ + /* Parameter checking */ + if (winNum >= XOR_MAX_REMAP_WIN) + { + DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, winNum)); + return MV_BAD_PARAM; + } + + MV_REG_WRITE(XOR_HIGH_ADDR_REMAP_REG(unit,winNum), addrHigh); + + return MV_OK; +} + +/******************************************************************************* +* xorWinOverlapDetect - Detect XOR address windows overlaping +* +* DESCRIPTION: +* An unpredicted behaviour is expected in case XOR address decode +* windows overlaps. +* This function detects XOR address decode windows overlaping of a +* specified window. The function does not check the window itself for +* overlaping. The function also skipps disabled address decode windows. +* +* INPUT: +* winNum - address decode window number. +* pAddrDecWin - An address decode window struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_TRUE if the given address window overlap current address +* decode map, MV_FALSE otherwise, MV_ERROR if reading invalid data +* from registers. +* +*******************************************************************************/ +static MV_STATUS xorWinOverlapDetect(MV_U32 unit,MV_U32 winNum, MV_ADDR_WIN *pAddrWin) +{ + MV_U32 baseAddrEnableReg; + MV_U32 winNumIndex,chan; + MV_XOR_DEC_WIN addrDecWin; + + if (pAddrWin == NULL) + { + DB(mvOsPrintf("%s: ERR. pAddrWin is NULL pointer\n", __FUNCTION__ )); + return MV_BAD_PTR; + } + + for (chan = 0; chan < MV_XOR_MAX_CHAN; chan++) + { + /* Read base address enable register. Do not check disabled windows */ + baseAddrEnableReg = MV_REG_READ(XOR_WINDOW_CTRL_REG(unit,chan)); + + for (winNumIndex = 0; winNumIndex < XOR_MAX_ADDR_DEC_WIN; winNumIndex++) + { + /* Do not check window itself */ + if (winNumIndex == winNum) + { + continue; + } + + /* Do not check disabled windows */ + if ((baseAddrEnableReg & XEXWCR_WIN_EN_MASK(winNumIndex)) == 0) + { + continue; + } + + /* Get window parameters */ + if (MV_OK != mvXorTargetWinGet(unit,winNumIndex, &addrDecWin)) + { + DB(mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__ )); + return MV_ERROR; + } + + if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin))) + { + return MV_TRUE; + } + } + } + + return MV_FALSE; +} + +static MV_VOID mvXorAddrDecShowUnit(MV_U32 unit) +{ + MV_XOR_DEC_WIN win; + int i; + + mvOsOutput( "\n" ); + mvOsOutput( "XOR %d:\n", unit ); + mvOsOutput( "----\n" ); + + for( i = 0; i < XOR_MAX_ADDR_DEC_WIN; i++ ) + { + memset( &win, 0, sizeof(MV_XOR_DEC_WIN) ); + + mvOsOutput( "win%d - ", i ); + + if( mvXorTargetWinGet(unit, i, &win ) == MV_OK ) + { + if( win.enable ) + { + mvOsOutput( "%s base %x, ", + mvCtrlTargetNameGet(win.target), win.addrWin.baseLow ); + + mvSizePrint( win.addrWin.size ); + + mvOsOutput( "\n" ); + } + else + mvOsOutput( "disable\n" ); + } + } +} + +/******************************************************************************* +* mvXorAddrDecShow - Print the XOR address decode map. +* +* DESCRIPTION: +* This function print the XOR address decode map. +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvXorAddrDecShow(MV_VOID) +{ + int i; + + for( i = 0; i < MV_XOR_MAX_UNIT; i++ ) + mvXorAddrDecShowUnit(i); + +} diff --git a/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysXor.h b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysXor.h new file mode 100644 index 0000000..4d46708 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/ctrlEnv/sys/mvSysXor.h @@ -0,0 +1,141 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCMVSysXorh +#define __INCMVSysXorh + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ctrlEnv/sys/mvCpuIf.h" + +#include "ctrlEnv/mvCtrlEnvLib.h" +#include "ctrlEnv/mvCtrlEnvAddrDec.h" + +#define XOR_MAX_ADDR_DEC_WIN 8 /* Maximum address decode windows */ +#define XOR_MAX_REMAP_WIN 4 /* Maximum address arbiter windows */ + +/* XOR Engine Address Decoding Register Map */ +#define XOR_WINDOW_CTRL_REG(unit,chan) (XOR_UNIT_BASE(unit)+(0x240 + ((chan) * 4))) +#define XOR_BASE_ADDR_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x250 + ((winNum) * 4))) +#define XOR_SIZE_MASK_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x270 + ((winNum) * 4))) +#define XOR_HIGH_ADDR_REMAP_REG(unit,winNum) (XOR_UNIT_BASE(unit)+(0x290 + ((winNum) * 4))) + +/* XOR Engine [0..1] Window Control Registers (XExWCR) */ +#define XEXWCR_WIN_EN_OFFS(winNum) (winNum) +#define XEXWCR_WIN_EN_MASK(winNum) (1 << (XEXWCR_WIN_EN_OFFS(winNum))) +#define XEXWCR_WIN_EN_ENABLE(winNum) (1 << (XEXWCR_WIN_EN_OFFS(winNum))) +#define XEXWCR_WIN_EN_DISABLE(winNum) (0 << (XEXWCR_WIN_EN_OFFS(winNum))) + +#define XEXWCR_WIN_ACC_OFFS(winNum) ((2 * winNum) + 16) +#define XEXWCR_WIN_ACC_MASK(winNum) (3 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_NO_ACC(winNum) (0 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_RO(winNum) (1 << (XEXWCR_WIN_ACC_OFFS(winNum))) +#define XEXWCR_WIN_ACC_RW(winNum) (3 << (XEXWCR_WIN_ACC_OFFS(winNum))) + +/* XOR Engine Base Address Registers (XEBARx) */ +#define XEBARX_TARGET_OFFS (0) +#define XEBARX_TARGET_MASK (0xF << XEBARX_TARGET_OFFS) +#define XEBARX_ATTR_OFFS (8) +#define XEBARX_ATTR_MASK (0xFF << XEBARX_ATTR_OFFS) +#define XEBARX_BASE_OFFS (16) +#define XEBARX_BASE_MASK (0xFFFF << XEBARX_BASE_OFFS) + +/* XOR Engine Size Mask Registers (XESMRx) */ +#define XESMRX_SIZE_MASK_OFFS (16) +#define XESMRX_SIZE_MASK_MASK (0xFFFF << XESMRX_SIZE_MASK_OFFS) + +/* XOR Engine High Address Remap Register (XEHARRx1) */ +#define XEHARRX_REMAP_OFFS (0) +#define XEHARRX_REMAP_MASK (0xFFFFFFFF << XEHARRX_REMAP_OFFS) + +typedef struct _mvXorDecWin +{ + MV_TARGET target; + MV_ADDR_WIN addrWin; /* An address window*/ + MV_BOOL enable; /* Address decode window is enabled/disabled */ + +}MV_XOR_DEC_WIN; + +MV_STATUS mvXorInit (MV_VOID); +MV_STATUS mvXorTargetWinSet(MV_U32 unit, MV_U32 winNum, + MV_XOR_DEC_WIN *pAddrDecWin); +MV_STATUS mvXorTargetWinGet(MV_U32 unit, MV_U32 winNum, + MV_XOR_DEC_WIN *pAddrDecWin); +MV_STATUS mvXorTargetWinEnable(MV_U32 unit, + MV_U32 winNum, MV_BOOL enable); +MV_STATUS mvXorProtWinSet (MV_U32 unit,MV_U32 chan, MV_U32 winNum, MV_BOOL access, + MV_BOOL write); +MV_STATUS mvXorPciRemap(MV_U32 unit, MV_U32 winNum, MV_U32 addrHigh); + +MV_VOID mvXorAddrDecShow(MV_VOID); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/mv_feroceon/mv_orion/orion_family/device/mvDevice.c b/board/mv_feroceon/mv_orion/orion_family/device/mvDevice.c new file mode 100644 index 0000000..8078352 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/device/mvDevice.c @@ -0,0 +1,318 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "mvDevice.h" + +/* defines */ +#ifdef MV_DEBUG + #define DB(x) x +#else + #define DB(x) +#endif + + + +/******************************************************************************* +* mvDevPramSet - Set device interface bank parameters +* +* DESCRIPTION: +* This function sets a device bank parameters to a given device. +* +* INPUT: +* device - Device number. See MV_DEVICE enumerator. +* *pDevParams - Device bank parameter struct. +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvDevIfPramSet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams) +{ + MV_U32 devParam; + + /* check parameters */ + if (device >= MV_DEV_MAX_CS) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device)); + return MV_BAD_PARAM; + + } + if (pDevParams->turnOff > MAX_DBP_TURNOFF) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. turnOff parameter out of range\n")); + return MV_ERROR; + } + if (pDevParams->acc2First > MAX_DBP_ACC2FIRST) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. acc2First out of range\n")); + return MV_ERROR; + } + if (pDevParams->acc2Next > MAX_DBP_ACC2NEXT) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. acc2Next out of range\n")); + return MV_ERROR; + } + if (pDevParams->ale2Wr > MAX_DBP_ALE2WR) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. ale2Wr parameter out of range\n")); + return MV_ERROR; + } + if (pDevParams->wrLow > MAX_DBP_WRLOW) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. wrLow parameter out of range\n")); + return MV_ERROR; + } + if (pDevParams->wrHigh > MAX_DBP_WRHIGH) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. wrHigh parameter out of range\n")); + return MV_ERROR; + } + if ((pDevParams->badrSkew << DBP_BADRSKEW_OFFS) > DBP_BADRSKEW_2CYCLE ) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. badrSkew parameter out of range\n")); + return MV_ERROR; + } + if ((pDevParams->deviceWidth != 8 )&& + (pDevParams->deviceWidth != 16 )&& + (pDevParams->deviceWidth != 32 )) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. deviceWidth out of range\n")); + return MV_ERROR; + } + + + devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device)); + + + /* setting values */ + devParam |= (pDevParams->turnOff << DBP_TURNOFF_OFFS); + devParam |= (pDevParams->acc2First << DBP_ACC2FIRST_OFFS); + devParam |= (pDevParams->acc2Next << DBP_ACC2NEXT_OFFS); + devParam |= (pDevParams->ale2Wr << DBP_ALE2WR_OFFS); + devParam |= (pDevParams->wrLow << DBP_WRLOW_OFFS); + devParam |= (pDevParams->wrHigh << DBP_WRHIGH_OFFS); + devParam |= (pDevParams->badrSkew << DBP_BADRSKEW_OFFS); + + + switch (pDevParams->deviceWidth) + { + case 8: + devParam |= DBP_DEVWIDTH_8BIT; + break; + case 16: + devParam |= DBP_DEVWIDTH_16BIT; + break; + case 32: + devParam |= DBP_DEVWIDTH_32BIT; + break; + default: + DB(mvOsPrintf("mvDevIfPramSet: ERR. deviceWidth invalid\n")); + return MV_ERROR; + break; + } + + MV_REG_WRITE(DEV_BANK_PARAM_REG(device),devParam); + + return MV_OK; +} + +/******************************************************************************* +* mvDevPramget - Get device interface bank parameters +* +* DESCRIPTION: +* This function retrieves a device bank parameter settings. +* +* INPUT: +* device - Device number. See MV_DEVICE enumerator. +* +* OUTPUT: +* *pDevParams - Device bank parameter struct. +* +* RETURN: +* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK +* +*******************************************************************************/ +MV_STATUS mvDevPramGet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams) +{ + MV_U32 devParam; + + /* check parameters */ + if (device >= MV_DEV_MAX_CS) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device)); + return MV_BAD_PARAM; + + } + + devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device)); + + pDevParams->turnOff = (devParam & DBP_TURNOFF_MASK) >> DBP_TURNOFF_OFFS; + pDevParams->acc2First = (devParam & DBP_ACC2FIRST_MASK)>>DBP_ACC2FIRST_OFFS; + pDevParams->acc2Next = (devParam & DBP_ACC2NEXT_MASK) >> DBP_ACC2NEXT_OFFS; + pDevParams->ale2Wr = (devParam & DBP_ALE2WR_MASK) >> DBP_ALE2WR_OFFS; + pDevParams->wrLow = (devParam & DBP_WRLOW_MASK) >> DBP_WRLOW_OFFS; + pDevParams->wrHigh = (devParam & DBP_WRHIGH_MASK) >> DBP_WRHIGH_OFFS; + pDevParams->badrSkew = (devParam & DBP_BADRSKEW_MASK) >> DBP_BADRSKEW_OFFS; + + + + switch (devParam & DBP_DEVWIDTH_MASK) + { + case DBP_DEVWIDTH_8BIT: + pDevParams->deviceWidth=8; + break; + case DBP_DEVWIDTH_16BIT: + pDevParams->deviceWidth=16; + break; + case DBP_DEVWIDTH_32BIT: + pDevParams->deviceWidth=32; + break; + default: + DB(mvOsPrintf("mvDevIfPramSet: ERR. invalid deviceWidth\n")); + return MV_ERROR; + break; + } + + + return MV_OK; +} + +/******************************************************************************* +* mvDevWidthGet - Get device width parameter +* +* DESCRIPTION: +* This function gets width parameter of a given device. +* +* INPUT: +* device - Device number. See MV_DEVICE enumerator. +* +* OUTPUT: +* None. +* +* RETURN: +* Device width in bytes. +* +*******************************************************************************/ +MV_U32 mvDevWidthGet(MV_DEVICE device) +{ + + MV_U32 devParam; + + /* check parameters */ + if (device >= MV_DEV_MAX_CS) + { + DB(mvOsPrintf("mvDevIfPramSet: ERR. Invalid Device num %d\n", device)); + return MV_BAD_PARAM; + + } + + devParam = MV_REG_READ(DEV_BANK_PARAM_REG(device)); + + devParam = (devParam & DBP_DEVWIDTH_MASK) >> DBP_DEVWIDTH_OFFS; + + return (MV_U32)(0x8 << devParam); + +} + +/******************************************************************************* +* mvDevNandSet - Set NAND chip-select and care mode +* +* DESCRIPTION: +* This function set the NAND flash controller registers with NAND +* device chip-select. +* +* INPUT: +* devNum - Device number. See MV_DEVICE enumerator. +* careMode - NAND device care mode (0 = Don't care, '1' = care). +* +* OUTPUT: +* None. +* +* RETURN: +* None. +* +*******************************************************************************/ +MV_VOID mvDevNandSet(MV_DEVICE devNum, MV_BOOL careMode) +{ + MV_U32 nfCtrlReg; /* NAND Flash Control Register */ + + /* Set chip select */ + nfCtrlReg = MV_REG_READ(DEV_NAND_CTRL_REG); + + nfCtrlReg |= (DINFCR_NF_CS_MASK(devNum)); + + if (careMode) + nfCtrlReg |= (DINFCR_NF_ACT_CE_MASK(devNum)); + else + nfCtrlReg &= ~(DINFCR_NF_ACT_CE_MASK(devNum)); + + + MV_REG_WRITE(DEV_NAND_CTRL_REG, nfCtrlReg); + +} + + diff --git a/board/mv_feroceon/mv_orion/orion_family/device/mvDevice.h b/board/mv_feroceon/mv_orion/orion_family/device/mvDevice.h new file mode 100644 index 0000000..bcc868f --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/device/mvDevice.h @@ -0,0 +1,101 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDeviceH +#define __INCmvDeviceH + +#include "mvCommon.h" +#include "mvOs.h" +#include "ctrlEnv/mvCtrlEnvSpec.h" +#include "device/mvDeviceRegs.h" + +/* This structure describes device interface parameters to be assigned to */ +/* device bank parameter */ +typedef struct _mvDeviceParam +{ /* boundary values */ + MV_U32 turnOff; /* 0x0 - 0xf */ + MV_U32 acc2First; /* 0x0 - 0x1f */ + MV_U32 acc2Next; /* 0x0 - 0x1f */ + MV_U32 ale2Wr; /* 0x0 - 0xf */ + MV_U32 wrLow; /* 0x0 - 0xf */ + MV_U32 wrHigh; /* 0x0 - 0xf */ + MV_U32 badrSkew; /* 0x0 - 0x2 */ + MV_U32 deviceWidth; /* in Bytes */ +} MV_DEVICE_PARAM; + + +/* mvDevPramSet - Set device interface bank parameters */ +MV_STATUS mvDevIfPramSet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams); + +/* mvDevPramget - Get device interface bank parameters */ +MV_STATUS mvDevPramGet(MV_DEVICE device, MV_DEVICE_PARAM *pDevParams); + +/* mvDevWidthGet - Get device width parameter*/ +MV_U32 mvDevWidthGet(MV_DEVICE device); + +/* mvDevNandDevCsSet - Set the NAND flash controller registers with */ +/* NAND device chip-select and care mode */ +MV_VOID mvDevNandSet(MV_DEVICE devNum, MV_BOOL careMode); + +#endif /* #ifndef __INCmvDeviceH */ diff --git a/board/mv_feroceon/mv_orion/orion_family/device/mvDeviceRegs.h b/board/mv_feroceon/mv_orion/orion_family/device/mvDeviceRegs.h new file mode 100644 index 0000000..b368028 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_family/device/mvDeviceRegs.h @@ -0,0 +1,223 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvDeviceRegsH +#define __INCmvDeviceRegsH + +#ifndef MV_ASMLANGUAGE +#include "ctrlEnv/mvCtrlEnvLib.h" +/* This enumerator describes the Marvell controller possible devices that */ +/* can be connected to its device interface. */ +typedef enum _mvDevice +{ +#if defined(MV_INCLUDE_DEVICE_CS0) + DEV_CS0 = 0, /* Device connected to dev CS[0] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS1) + DEV_CS1 = 1, /* Device connected to dev CS[1] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS2) + DEV_CS2 = 2, /* Device connected to dev CS[2] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS3) + DEV_CS3 = 3, /* Device connected to dev CS[2] */ +#endif +#if defined(MV_INCLUDE_DEVICE_CS4) + DEV_CS4 = 4, /* Device connected to BOOT dev */ +#endif + MV_DEV_MAX_CS = MV_DEVICE_MAX_CS +}MV_DEVICE; + + +#endif /* MV_ASMLANGUAGE */ + + +/* registers offsets */ + +#if defined(MV_88F5182) || defined(MV_88W8660) || defined(MV_88F5082) +#define DEV_NAND_CTRL_REG 0x104E8 +#define DEV_RGMII_AC_TIMING_REG 0x104F0 +#else +#define DEV_NAND_CTRL_REG 0x10470 +#define DEV_RGMII_AC_TIMING_REG 0x104E8 +#endif + + +#define DEV_INTERF_CTRL_REG 0x104C0 +#define DEV_INTERF_XBAR_TIMEOUT_REG 0x104C4 + +#define DEV_INTR_CAUSE_REG 0x104D0 +#define DEV_INTR_MASK_REG 0x104D4 + + +/* Device Bank Parameters register fields (DBP_REG)*/ +/* Boot Device Bank Parameters (DBP) register fields (DEV_BOOT_BANK_PARAM_REG)*/ + +#define DBP_TURNOFF_OFFS 0 +#define DBP_TURNOFF_MASK (0x7 << DBP_TURNOFF_OFFS) +#define MAX_DBP_TURNOFF 0x7 + +#define DBP_ACC2FIRST_OFFS 3 +#define DBP_ACC2FIRST_MASK (0xf << DBP_ACC2FIRST_OFFS) +#define MAX_DBP_ACC2FIRST 0xf + +#define DBP_ACC2NEXT_OFFS 7 +#define DBP_ACC2NEXT_MASK (0xf << DBP_ACC2NEXT_OFFS) +#define MAX_DBP_ACC2NEXT 0xf + + +#define DBP_ALE2WR_OFFS 11 +#define DBP_ALE2WR_MASK (0x7 << DBP_ALE2WR_OFFS) +#define MAX_DBP_ALE2WR 0x7 + + +#define DBP_WRLOW_OFFS 14 +#define DBP_WRLOW_MASK (0x7 << DBP_WRLOW_OFFS) +#define MAX_DBP_WRLOW 0x7 + + +#define DBP_WRHIGH_OFFS 17 +#define DBP_WRHIGH_MASK (0x7 << DBP_WRHIGH_OFFS) +#define MAX_DBP_WRHIGH 0x7 + + +#define DBP_DEVWIDTH_OFFS 20 /* Device Width */ +#define DBP_DEVWIDTH_MASK (0x3 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_8BIT (0x0 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_16BIT (0x1 << DBP_DEVWIDTH_OFFS) +#define DBP_DEVWIDTH_32BIT (0x2 << DBP_DEVWIDTH_OFFS) + + +#define DBP_TURNOFFEXT BIT22 /* TurnOff Extension */ +#define DBP_ACC2FIRSTEXT BIT23 /* Acc2First Extension */ +#define DBP_ACC2NEXTEXT BIT24 /* Acc2Next Extension */ +#define DBP_ALE2WREXT BIT25 /* ALE2Wr Extension */ +#define DBP_WRLOWEXT BIT26 /* WrLow Extension */ +#define DBP_WRHIGHEXT BIT27 /* WrHigh Extension */ + +#define DBP_BADRSKEW_OFFS 28 +#define DBP_BADRSKEW_MASK (0x3 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_NOGAP (0x0 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_1CYCLE (0x1 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_2CYCLE (0x2 << DBP_BADRSKEW_OFFS) + +#define DBP_BADRSKEW_OFFS 28 +#define DBP_BADRSKEW_MASK (0x3 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_NOGAP (0x0 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_1CYCLE (0x1 << DBP_BADRSKEW_OFFS) +#define DBP_BADRSKEW_2CYCLE (0x2 << DBP_BADRSKEW_OFFS) + +#define DBP_RESRV_OFFS 30 +#define DBP_RESRV_MASK (0x3 << DBP_RESRV_OFFS) +#define DBP_RESRV_VAL (0x2 << DBP_RESRV_OFFS) + + + +/* Device Interface Control register fields (DIC) (DIC_REG)*/ + +#define DIC_TIMEOUT_OFFS 0 /* Timeout Timer Preset Value. */ +#define DIC_TIMEOUT_MASK (0xffff << DIC_TIMEOUT_OFFS) +#define MAX_DIC_TIMEOUT 0xffff + +#define DIC_RDTRIG BIT16 /* Read Trigger Control */ +#define DIC_RES18 BIT18 /* must be 1 */ +#define DIC_PERRPROP BIT19 /* Parity error propagation enable */ +#define DIC_PARSEL BIT20 /* Even or Odd parity select */ +#define DIC_FORCEPAREN BIT21 /* Force Parity Enable */ + +#define DIC_RDDPPAR_OFFS 22 /* Read data path parity select */ +#define DIC_RDDPPAR_MASK (1 << DIC_RDDPPAR_OFFS) +#define DIC_RDDPPAR_EVEN (0 << DIC_RDDPPAR_OFFS) +#define DIC_RDDPPAR_ODD (1 << DIC_RDDPPAR_OFFS) + +#define DIC_WRDPPAR_OFFS 23 /* Write data path parity select*/ +#define DIC_WRDPPAR_MASK (1 << DIC_WRDPPAR_OFFS) +#define DIC_WRDPPAR_EVEN (0 << DIC_WRDPPAR_OFFS) +#define DIC_WRDPPAR_ODD (1 << DIC_WRDPPAR_OFFS) + +#define DIC_FORCEPAR_OFFS 24 +#define DIC_FORCEPAR_MASK (0xf << DIC_FORCEPAR_OFFS) +#define MAX_DIC_FORCEPAR 0xf + +#define DIC_RES30_OFFS 30 /* must be 0 */ +#define DIC_RES30_MASK (0x3 << DIC_RES30_OFFS + +/* Device Interface Crossbar Control Low (DICCL) register (DIC_L_XBAR_REG) */ +/* Device Interface Crossbar Control High (DICCH) register (DIC_H_XBAR_REG) */ + +#define DICCL_OFFS(num) (4*num) +#define DICCL_MASK(num) (0xf << DICCL_OFFS(num)) + +#define DICCH_OFFS(num) (4*(num-8)) +#define DICCH__MASK(num) (0xf << DICCH_OFFS(num)) + +#define DICC_CPU 0x2 +#define DICC_PCI0 0x3 +#define DICC_PCI1 0x4 +#define DICC_MPSC 0x5 +#define DICC_IDMA 0x6 +#define DICC_GETH 0x7 + + +#endif /* #ifndef __INCmvDeviceRegsH */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F1281SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F1281SysHwConfig.h new file mode 100644 index 0000000..20927a4 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F1281SysHwConfig.h @@ -0,0 +1,182 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F1281SysHwConfigh +#define __INCmv88F1281SysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ +#define MV_INCLUDE_PEX +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_UART +#define MV_INCLUDE_NAND + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA driver*/ +#define MV_INC_BOARD_PCI_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 1 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* Bridge exist on pciIf1*/ + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ + +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + + + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + + + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + + +#define PEX1_MEM_BASE 0x98000000 +#define PEX1_MEM_SIZE _128M + +#define PEX1_IO_BASE 0xf0100000 +#define PEX1_IO_SIZE _1M + + +/* Device: CS0 - Flash, CS1 - Boot Flash */ +#define DEVICE_CS0_BASE 0xf8000000 +#define DEVICE_CS0_SIZE _16M + +#define DEVICE_CS1_BASE BOOTDEV_CS_BASE +#define DEVICE_CS1_SIZE BOOTDEV_CS_SIZE + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PEX1_MEM_BASE +#define PCI_IF1_MEM0_SIZE PEX1_MEM_SIZE +#define PCI_IF1_IO_BASE PEX1_IO_BASE +#define PCI_IF1_IO_SIZE PEX1_IO_SIZE + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{PEX1_MEM_BASE , 0, PEX1_MEM_SIZE } ,0x1 ,EN}, \ + {{PEX1_IO_BASE , 0, PEX1_IO_SIZE } ,0x3 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x7 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x4 ,EN}, \ + /* Table terminator */\ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +}; + +#endif /* __INCmv88F1281SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F1X81SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F1X81SysHwConfig.h new file mode 100644 index 0000000..44102cf --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F1X81SysHwConfig.h @@ -0,0 +1,162 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F1X81SysHwConfigh +#define __INCmv88F1X81SysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ +#define MV_INCLUDE_PEX +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_UART + + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA driver*/ +#define MV_INC_BOARD_PCI_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 1 /* Bridge exist on pciIf1*/ + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ + +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + + + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + + + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + + +#define PEX1_MEM_BASE 0x98000000 +#define PEX1_MEM_SIZE _128M + +#define PEX1_IO_BASE 0xf0100000 +#define PEX1_IO_SIZE _1M + + + + +#define FLASH_CS_BASE 0xf8000000 +#define FLASH_CS_SIZE _16M + + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PEX1_MEM_BASE +#define PCI_IF1_MEM0_SIZE PEX1_MEM_SIZE +#define PCI_IF1_IO_BASE PEX1_IO_BASE +#define PCI_IF1_IO_SIZE PEX1_IO_SIZE + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + + + +#endif /* __INCmv88F1X81SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F5082SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F5082SysHwConfig.h new file mode 100644 index 0000000..d55305f --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F5082SysHwConfig.h @@ -0,0 +1,258 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F5082SysHwConfigh +#define __INCmv88F5082SysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PEX +#define MV_INCLUDE_IDMA +#define MV_INCLUDE_CESA +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_INTEG_SATA +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART + + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA */ +#define MV_INC_BOARD_PEX_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + +/* RD Boards specific */ +#if defined(RD_88F5082) || defined (RD_88F5082_3) + +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#undef MV_INCLUDE_IDMA + +#endif + + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + +/* Device: CS0 - SRAM, CS1 - RTC, CS2 - UART, CS3 - large flash */ +#define DEVICE_CS0_BASE 0xfa000000 +#define DEVICE_CS0_SIZE _2M + +#define DEVICE_CS1_BASE 0xf8000000 +#define DEVICE_CS1_SIZE _32M + +#define DEVICE_CS2_BASE 0xfa800000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE BOOTDEV_CS_BASE +#define DEVICE_CS3_SIZE BOOTDEV_CS_SIZE + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define CRYPT_ENG_BASE 0xFB000000 +#define CRYPT_ENG_SIZE _64K + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#undef PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x5 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x6 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x7 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x4 ,EN}, \ + {{CRYPT_ENG_BASE, 0, CRYPT_ENG_SIZE} ,0x7 ,DIS}, \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +} + +#endif /* __INCmv88F5082SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F5180NSysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F5180NSysHwConfig.h new file mode 100644 index 0000000..ea767a7 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F5180NSysHwConfig.h @@ -0,0 +1,221 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F5X81SysHwConfigh +#define __INCmv88F5X81SysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ +#define MV_INCLUDE_PCI +#define MV_INCLUDE_IDMA +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA */ +#define MV_INC_BOARD_PCI_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + + +/* PCI0: IO and memory space */ +#define PCI0_MEM_BASE 0x98000000 +#define PCI0_MEM_SIZE _128M + +#define PCI0_IO_BASE 0xf0100000 +#define PCI0_IO_SIZE _1M + + +/* Device: CS0 - SRAM, CS1 - RTC, CS2 - UART, CS3 - large flash */ +#define DEVICE_CS0_BASE 0xfa000000 +#define DEVICE_CS0_SIZE _2M + +#define DEVICE_CS1_BASE 0xf8000000 +#define DEVICE_CS1_SIZE _32M + +#define DEVICE_CS2_BASE 0xfa800000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE BOOTDEV_CS_BASE +#define DEVICE_CS3_SIZE BOOTDEV_CS_SIZE + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PCI0_MEM_BASE , 0, PCI0_MEM_SIZE } ,0x1 ,EN}, \ + {{PCI0_IO_BASE , 0, PCI0_IO_SIZE } ,0x3 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x5 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x6 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x7 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x4 ,EN}, \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +} + +#endif /* __INCmv88F5X81SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F5181LSysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F5181LSysHwConfig.h new file mode 100644 index 0000000..78d7b91 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F5181LSysHwConfig.h @@ -0,0 +1,272 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F5181LSysHwConfigh +#define __INCmv88F5181LSysHwConfigh + + +/****************************************/ +/* Soc supported Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PCI +#define MV_INCLUDE_PEX +#define MV_INCLUDE_IDMA +#define MV_INCLUDE_CESA +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_USB +#define MV_INCLUDE_TDM +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board Telephony SLIC */ +#define MV_INC_BOARD_SLIC +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA */ +#define MV_INC_BOARD_PCI_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + + +#if defined(RD_88F5181L_GE) || defined (RD_88F5181L_FE) || defined (RD_88F5181L_FXO_GE) + +/* On-Board Marvell Switch */ +#define MV_INC_BOARD_QD_SWITCH +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#endif + + + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + + +/* PCI0: IO and memory space */ +#define PCI0_MEM_BASE 0x98000000 +#define PCI0_MEM_SIZE _128M + +#define PCI0_IO_BASE 0xf0100000 +#define PCI0_IO_SIZE _1M + + +/* Device: CS0 - SRAM, CS1 - RTC, CS2 - UART, CS3 - large flash */ +#define DEVICE_CS0_BASE 0xfa000000 +#define DEVICE_CS0_SIZE _2M + +#define DEVICE_CS1_BASE 0xf8000000 +#define DEVICE_CS1_SIZE _32M + +#define DEVICE_CS2_BASE 0xfa800000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE BOOTDEV_CS_BASE +#define DEVICE_CS3_SIZE BOOTDEV_CS_SIZE + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + +#define CRYPT_ENG_BASE 0xFB000000 +#define CRYPT_ENG_SIZE _64K + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{PCI0_MEM_BASE , 0, PCI0_MEM_SIZE } ,0x1 ,EN}, \ + {{PCI0_IO_BASE , 0, PCI0_IO_SIZE } ,0x3 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x5 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x6 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x7 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x4 ,EN}, \ + {{CRYPT_ENG_BASE, 0, CRYPT_ENG_SIZE} ,0x7 ,DIS}, \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +} + +#endif /* __INCmv88F5181LSysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F5182SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F5182SysHwConfig.h new file mode 100644 index 0000000..4740055 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F5182SysHwConfig.h @@ -0,0 +1,284 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F5182SysHwConfigh +#define __INCmv88F5182SysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PCI +#define MV_INCLUDE_PEX +#define MV_INCLUDE_IDMA +#define MV_INCLUDE_CESA +#define MV_INCLUDE_XOR +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_INTEG_SATA +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART + + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA */ +#define MV_INC_BOARD_PCI_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + +/* RD Boards specific */ +#if defined(RD_88F5182) + +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#undef MV_INCLUDE_IDMA + +#endif + +#if defined (RD_88F5182_3) + +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#undef MV_INCLUDE_MONT_EXT +#undef MV_INCLUDE_IDMA +#undef MV_INCLUDE_CESA +#undef MV_INCLUDE_XOR +#endif + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + +/* PCI0: IO and memory space */ +#define PCI0_MEM_BASE 0x98000000 +#define PCI0_MEM_SIZE _128M + +#define PCI0_IO_BASE 0xf0100000 +#define PCI0_IO_SIZE _1M + +/* Device: CS0 - 7seg, CS1 - large flash, CS2 - NAND, CS3 - NA */ +#define DEVICE_CS0_BASE 0xfa000000 +#define DEVICE_CS0_SIZE _2M + +#define DEVICE_CS1_BASE 0xf8000000 +#define DEVICE_CS1_SIZE _32M + +#define DEVICE_CS2_BASE 0xfa800000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE BOOTDEV_CS_BASE +#define DEVICE_CS3_SIZE BOOTDEV_CS_SIZE + +#ifdef MV_NAND_BOOT +#define CFG_NAND_BASE BOOTDEV_CS_BASE +#else +#define CFG_NAND_BASE DEVICE_CS2_BASE +#endif + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define CRYPT_ENG_BASE 0xFB000000 +#define CRYPT_ENG_SIZE _64K + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{PCI0_MEM_BASE , 0, PCI0_MEM_SIZE } ,0x1 ,EN}, \ + {{PCI0_IO_BASE , 0, PCI0_IO_SIZE } ,0x3 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x5 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x6 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x7 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x4 ,EN}, \ + {{CRYPT_ENG_BASE, 0, CRYPT_ENG_SIZE} ,0x7 ,DIS}, \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +} + +#endif /* __INCmv88F5182SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F5X81SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F5X81SysHwConfig.h new file mode 100644 index 0000000..0d68301 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F5X81SysHwConfig.h @@ -0,0 +1,330 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F5X81SysHwConfigh +#define __INCmv88F5X81SysHwConfigh + + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ +#define MV_INCLUDE_PCI +#define MV_INCLUDE_PEX +#define MV_INCLUDE_IDMA +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA */ +#define MV_INC_BOARD_PCI_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + +/* RD Boards specific */ +#if defined(MV_POS_NAS) + +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM + +#endif + +#if defined(RD_88F5181_GTWGE) || defined (RD_88F5181_GTWFE) +/* On-Board Marvell Switch */ +#define MV_INC_BOARD_QD_SWITCH + +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM + +#endif + + +#if defined(DB_VOIP) +/* On-Board Telephony SLIC */ +#define MV_INC_BOARD_SLIC +/* On-Board TDM FPGA */ +#define MV_INC_BOARD_TDM_FPGA +/* On-Board Marvell Switch */ +#define MV_INC_BOARD_QD_SWITCH + +#undef MV_INC_BOARD_NAND_FLASH +#endif + +#if defined(DB_MNG) +#undef MV_INC_BOARD_DDIM +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INCLUDE_USB +#endif + +#if defined(DB_PRPMC) || defined (DB_PEX_PCI) + +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INCLUDE_USB +#undef MV_INC_BOARD_DDIM +#if defined(DB_PEX_PCI) + #undef PCI1_IF_MODE + #define PCI1_IF_MODE PCI_IF_MODE_DEVICE +#endif + +#endif /* defined(DB_PRPMC) || defined (DB_PEX_PCI) */ + + +#if defined(MV_POS_NAS) +#undef MV_INCLUDE_MONT_FFS +#endif + +#if defined(DB_FPGA) +#undef MV_INCLUDE_PEX +#undef MV_INCLUDE_IDMA +#undef MV_INCLUDE_GIG_ETH +#undef MV_INCLUDE_USB +#undef MV_INCLUDE_TWSI +#undef MV_INCLUDE_NAND +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#undef MV_MEM_OVER_PCI_WA +#undef MV_MEM_OVER_PEX_WA +#define MV_UART_OVER_PCI_WA +#endif + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +#define SDRAM_CS2_BASE 0x20000000 +#define SDRAM_CS2_SIZE _256M + +#define SDRAM_CS3_BASE 0x30000000 +#define SDRAM_CS3_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + + +/* PCI0: IO and memory space */ +#define PCI0_MEM_BASE 0x98000000 +#define PCI0_MEM_SIZE _128M + +#define PCI0_IO_BASE 0xf0100000 +#define PCI0_IO_SIZE _1M + +#if defined(DB_FPGA) +#define DEVICE_CS0_BASE 0xf8000000 +#define DEVICE_CS0_SIZE _32M + +#define DEVICE_CS1_BASE 0xfa000000 +#define DEVICE_CS1_SIZE _2M +#else +#define DEVICE_CS0_BASE 0xfa000000 +#define DEVICE_CS0_SIZE _2M + +#define DEVICE_CS1_BASE 0xf8000000 +#define DEVICE_CS1_SIZE _32M +#endif + +#define DEVICE_CS2_BASE 0xfa800000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE BOOTDEV_CS_BASE +#define DEVICE_CS3_SIZE BOOTDEV_CS_SIZE + +#ifdef MV_NAND_BOOT +#define CFG_NAND_BASE BOOTDEV_CS_BASE +#else +#define CFG_NAND_BASE DEVICE_CS2_BASE +#endif +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + + +/* Board clock detection */ +#undef MV_TCLK_CALC +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS2_BASE , 0, SDRAM_CS2_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS3_BASE , 0, SDRAM_CS3_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{PCI0_MEM_BASE , 0, PCI0_MEM_SIZE } ,0x1 ,EN}, \ + {{PCI0_IO_BASE , 0, PCI0_IO_SIZE } ,0x3 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x5 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x6 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x7 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x4 ,EN}, \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +} + +#endif /* __INCmv88F5X81SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F6082SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F6082SysHwConfig.h new file mode 100644 index 0000000..63a57b2 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F6082SysHwConfig.h @@ -0,0 +1,291 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F6082SysHwConfigh +#define __INCmv88F6082SysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PEX +#define MV_INCLUDE_CESA +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_INTEG_SATA +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART +#define MV_INCLUDE_SPI +#define MV_INCLUDE_INTEG_MFLASH +/*#define MV_INCLUDE_INTEG_MFLASH_SPI*/ + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board SPI Flash support */ +#define MV_INC_BOARD_SPI_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + +#if defined(MV_INCLUDE_INTEG_MFLASH_SPI) && defined (MV_INC_BOARD_SPI_FLASH) +#error "Cannot Use MFlash in SPI mode while configuring and external SPI flash" +#endif + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +/* Tailgate WA for Nanya memory */ +/* #define MV_MEM_OVER_PCI_WA */ + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + +/*********************************************/ +/* DB boards specifics */ +/*********************************************/ + +#if defined(DB_88F6082BP) || defined(DB_88F6082LBP) + +#undef MV_INC_BOARD_DDIM + +#endif + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + +#if defined(RD_88F6082NAS) +#undef MV_INC_BOARD_DDIM +#undef MV_INCLUDE_IDMA +#undef MV_INCLUDE_PCI +#undef MV_INC_BOARD_SPI_FLASH +#endif + +#if defined (RD_88F6082GE_SATA) || defined (RD_88F6082SA) || defined (RD_88F6082DAS_PLUS) \ + || defined (RD_88F6082MICRO_DAS_NAS) +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#undef MV_INCLUDE_IDMA +#undef MV_INCLUDE_PCI +#endif + +#if defined (RD_88F6082MICRO_DAS_NAS) +#define MV_INC_DRAM_MFG_TEST +#endif + +#if defined (RD_88F6082_DX243) +#undef MV_INC_BOARD_DDIM +#undef MV_INCLUDE_IDMA +#undef MV_INCLUDE_PCI +#define MV_INCLUDE_PEX +#undef MV_INCLUDE_CESA +#undef MV_INCLUDE_INTEG_SATA +#undef MV_INCLUDE_USB +#undef MV_INC_BOARD_NAND_FLASH +#endif + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + +/* Device: CS0 - NAND, CS1 - MFlash, CS2 - SPI, CS3 - Boot ROM, CS4 - Boot device */ +#define DEVICE_CS0_BASE 0xf8000000 +#define DEVICE_CS0_SIZE _1M + +#define DEVICE_MFLASH_BASE 0xf8100000 +#define DEVICE_CS1_BASE DEVICE_MFLASH_BASE +#define DEVICE_CS1_SIZE _1M + +#define DEVICE_CS2_BASE 0xf9000000 +#define DEVICE_CS2_SIZE _16M + +#define DEVICE_CS3_BASE 0xfa000000 +#define DEVICE_CS3_SIZE _1M + +#define DEVICE_CS4_BASE BOOTDEV_CS_BASE +#define DEVICE_CS4_SIZE BOOTDEV_CS_SIZE + +#define CFG_NAND_BASE DEVICE_CS0_BASE + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define CRYPT_ENG_BASE 0xFB000000 +#define CRYPT_ENG_SIZE _64K + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x1 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x3 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x5 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x6 ,EN}, \ + {{DEVICE_CS4_BASE, 0, DEVICE_CS4_SIZE},0x4 ,EN}, \ + {{CRYPT_ENG_BASE, 0, CRYPT_ENG_SIZE} ,0x7 ,EN}, \ + /* Table terminator */\ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +}; + +#endif /* __INCmv88F6082SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F6183LSysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F6183LSysHwConfig.h new file mode 100644 index 0000000..1a8afd0 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F6183LSysHwConfig.h @@ -0,0 +1,202 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F6183LSysHwConfigh +#define __INCmv88F6183LSysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PEX +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART +#define MV_INCLUDE_SPI + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board SPI Flash support */ +#define MV_INC_BOARD_SPI_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +/* Tailgate WA for Nanya memory */ +/* #define MV_MEM_OVER_PCI_WA */ + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#endif + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + +/* Device: CS0 - NAND, CS1 - SPI, CS2 - SPI, CS3 - Boot ROM, CS4 - Boot device */ + + +#define DEVICE_CS0_BASE 0xf8800000 +#define DEVICE_CS0_SIZE _8M + +#define DEVICE_SPI_BASE 0xf8000000 +#define DEVICE_CS1_BASE DEVICE_SPI_BASE +#define DEVICE_CS1_SIZE _8M + +#define DEVICE_CS4_BASE BOOTDEV_CS_BASE +#define DEVICE_CS4_SIZE BOOTDEV_CS_SIZE + +#ifdef MV_NAND_BOOT +#define CFG_NAND_BASE BOOTDEV_CS_BASE +#else +#define CFG_NAND_BASE DEVICE_CS2_BASE +#endif + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x1 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x3 ,EN}, \ + {{DEVICE_CS4_BASE, 0, DEVICE_CS4_SIZE},0x4 ,EN}, \ + /* Table terminator */\ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +}; + +#endif /* __INCmv88F6183LSysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88F6183SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88F6183SysHwConfig.h new file mode 100644 index 0000000..3878a70 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88F6183SysHwConfig.h @@ -0,0 +1,254 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F6183SysHwConfigh +#define __INCmv88F6183SysHwConfigh + +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PEX +#define MV_INCLUDE_CESA +#define MV_INCLUDE_GIG_ETH +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART +#define MV_INCLUDE_SPI + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board SPI Flash support */ +#define MV_INC_BOARD_SPI_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +/* Tailgate WA for Nanya memory */ +/* #define MV_MEM_OVER_PCI_WA */ + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + +#if defined(RD_88F6183AP) +#define MV_INC_BOARD_QD_SWITCH +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#endif + +#if defined(RD_88F6183GP) +#undef MV_INC_BOARD_DDIM +#undef MV_INC_BOARD_SPI_FLASH +#endif + + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + +/* Device: CS0 - NAND, CS1 - SPI, CS2 - SPI, CS3 - Boot ROM, CS4 - Boot device */ + + +#define DEVICE_CS0_BASE 0xf8800000 +#define DEVICE_CS0_SIZE _8M + +#define DEVICE_SPI_BASE 0xf8000000 +#define DEVICE_CS1_BASE DEVICE_SPI_BASE +#define DEVICE_CS1_SIZE _8M + +#define DEVICE_CS4_BASE BOOTDEV_CS_BASE +#define DEVICE_CS4_SIZE BOOTDEV_CS_SIZE + +#ifdef MV_NAND_BOOT +#define CFG_NAND_BASE BOOTDEV_CS_BASE +#else +#define CFG_NAND_BASE DEVICE_CS2_BASE +#endif + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#define CRYPT_ENG_BASE 0xFB000000 +#define CRYPT_ENG_SIZE _64K + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x1 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x3 ,EN}, \ + {{DEVICE_CS4_BASE, 0, DEVICE_CS4_SIZE},0x4 ,EN}, \ + {{CRYPT_ENG_BASE, 0, CRYPT_ENG_SIZE} ,0x7 ,EN}, \ + /* Table terminator */\ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +}; + +#endif /* __INCmv88F6183SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mv88w8660SysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mv88w8660SysHwConfig.h new file mode 100644 index 0000000..9f39aea --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mv88w8660SysHwConfig.h @@ -0,0 +1,254 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmv88F5X81SysHwConfigh +#define __INCmv88F5X81SysHwConfigh +/****************************************/ +/* Soc supporetd Units definitions */ +/****************************************/ + +#define MV_INCLUDE_PCI +#define MV_INCLUDE_PEX +#define MV_INCLUDE_IDMA +#define MV_INCLUDE_UNM_ETH +#define MV_INCLUDE_USB +#define MV_INCLUDE_TWSI +#define MV_INCLUDE_NAND +#define MV_INCLUDE_UART + +/*********************************************/ +/* Board Specific defines : On-Board devices */ +/*********************************************/ + +/* DRAM ddim detection support */ +#define MV_INC_BOARD_DDIM +/* On-Board NOR Flash support */ +#define MV_INC_BOARD_NOR_FLASH +/* On-Board NAND Flash support */ +#define MV_INC_BOARD_NAND_FLASH +/* On-Board RTC */ +#define MV_INC_BOARD_RTC +/* On-Board PCI\PEX SATA */ +#define MV_INC_BOARD_PCI_SATA + +/* PEX-PCI\PCI-PCI Bridge*/ +#define PCI0_IF_PTP 0 /* no Bridge on pciIf0*/ +#define PCI1_IF_PTP 0 /* no Bridge on pciIf1*/ + +/*********************************************/ +/* U-Boot Specific */ +/*********************************************/ +#define MV_INCLUDE_MONT_EXT + +#if defined(MV_INCLUDE_MONT_EXT) +#define MV_INCLUDE_MONT_MMU +#define MV_INCLUDE_MONT_MPU +#if defined(MV_INC_BOARD_NOR_FLASH) +#define MV_INCLUDE_MONT_FFS +#endif +#define MV_INCLUDE_MONT_LOAD_NET +#endif + + +/*********************************************/ +/* RD boards specifics */ +/*********************************************/ + +#if defined(RD_88W8660) +#define MV_INC_BOARD_QD_SWITCH +#undef MV_INC_BOARD_NAND_FLASH +#undef MV_INC_BOARD_DDIM +#endif + + +#if defined(RD_88W8660_AP82S) +#define MV_INC_BOARD_QD_SWITCH +#undef MV_INC_BOARD_DDIM +#endif + +/* + * System memory mapping + */ + +/* SDRAM: actual mapping is auto detected */ +#define SDRAM_CS0_BASE 0x00000000 +#define SDRAM_CS0_SIZE _256M + +#define SDRAM_CS1_BASE 0x10000000 +#define SDRAM_CS1_SIZE _256M + +/* PEX */ +#define PEX0_MEM_BASE 0x90000000 +#define PEX0_MEM_SIZE _128M + +#define PEX0_IO_BASE 0xf0000000 +#define PEX0_IO_SIZE _1M + +/* PEX Work arround */ +/* the target we will use for the workarround */ +#define PEX_CONFIG_RW_WA_TARGET PEX0_MEM +/*a flag that indicates if we are going to use the +size and base of the target we using for the workarround +window */ +#define PEX_CONFIG_RW_WA_USE_ORIGINAL_WIN_VALUES 1 +/* if the above flag is 0 then the following values +will be used for the workarround window base and size, +otherwise the following defines will be ignored */ +#define PEX_CONFIG_RW_WA_BASE 0x50000000 +#define PEX_CONFIG_RW_WA_SIZE _16M + + +/* PCI0: IO and memory space */ +#define PCI0_MEM_BASE 0x98000000 +#define PCI0_MEM_SIZE _128M + +#define PCI0_IO_BASE 0xf0100000 +#define PCI0_IO_SIZE _1M + + +/* Device: CS0 - SRAM, CS1 - RTC, CS2 - UART, CS3 - large flash */ +#define DEVICE_CS0_BASE 0xfa000000 +#define DEVICE_CS0_SIZE _2M + +#define DEVICE_CS1_BASE 0xf8000000 +#define DEVICE_CS1_SIZE _32M + +#define DEVICE_CS2_BASE 0xfa800000 +#define DEVICE_CS2_SIZE _1M + +#define DEVICE_CS3_BASE BOOTDEV_CS_BASE +#define DEVICE_CS3_SIZE BOOTDEV_CS_SIZE + +/* Internal registers: size is defined in Controllerenvironment */ +#define INTER_REGS_BASE 0xF1000000 + + +#if defined (MV_INCLUDE_PCI) && defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#define PCI_IF1_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF1_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF1_IO_BASE PCI0_IO_BASE +#define PCI_IF1_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PCI) + +#define PCI_IF0_MEM0_BASE PCI0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PCI0_MEM_SIZE +#define PCI_IF0_IO_BASE PCI0_IO_BASE +#define PCI_IF0_IO_SIZE PCI0_IO_SIZE + +#elif defined (MV_INCLUDE_PEX) + +#define PCI_IF0_MEM0_BASE PEX0_MEM_BASE +#define PCI_IF0_MEM0_SIZE PEX0_MEM_SIZE +#define PCI_IF0_IO_BASE PEX0_IO_BASE +#define PCI_IF0_IO_SIZE PEX0_IO_SIZE + +#endif + + +/* DRAM detection stuff */ +#define MV_DRAM_AUTO_SIZE + +#define PCI_ARBITER_CTRL /* Use/unuse the Marvell integrated PCI arbiter */ +#undef PCI_ARBITER_BOARD /* Use/unuse the PCI arbiter on board */ + +/* Check macro validity */ +#if defined(PCI_ARBITER_CTRL) && defined (PCI_ARBITER_BOARD) + #error "Please select either integrated PCI arbiter or board arbiter" +#endif + + +/* Board clock detection */ +#define TCLK_AUTO_DETECT /* Use Tclk auto detection */ +#define SYSCLK_AUTO_DETECT /* Use SysClk auto detection */ +#define PCLCK_AUTO_DETECT /* Use PClk auto detection */ + + +/************* Ethernet driver configuration ********************/ + +/*#define ETH_JUMBO_SUPPORT*/ +/* HW cache coherency configuration */ +#define DMA_RAM_COHER NO_COHERENCY +#define ETHER_DRAM_COHER MV_UNCACHED +#define INTEG_SRAM_COHER MV_UNCACHED /* Where integrated SRAM available */ + +#define ETH_DESCR_IN_SDRAM +#undef ETH_DESCR_IN_SRAM + +#if (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WB" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_HW_WT" +#elif (ETHER_DRAM_COHER == MV_CACHE_COHER_SW) +# define ETH_SDRAM_CONFIG_STR "MV_CACHE_COHER_SW" +#elif (ETHER_DRAM_COHER == MV_UNCACHED) +# define ETH_SDRAM_CONFIG_STR "MV_UNCACHED" +#else +# error "Unexpected ETHER_DRAM_COHER value" + +#endif /* ETHER_DRAM_COHER */ + + +/*********** Idma default configuration ***********/ +#define UBOOT_CNTRL_DMA_DV (ICCLR_DST_BURST_LIM_8BYTE | \ + ICCLR_SRC_INC | \ + ICCLR_DST_INC | \ + ICCLR_SRC_BURST_LIM_8BYTE | \ + ICCLR_NON_CHAIN_MODE | \ + ICCLR_BLOCK_MODE ) + + +/* CPU address decode table. Note that table entry number must match its */ +/* winNum enumerator. For example, table entry '4' must describe Deivce CS0 */ +/* winNum which is represent by DEVICE_CS0 enumerator (4). */ +#define MV_CPU_IF_ADDR_WIN_MAP_TBL { \ +/* base low base high size WinNum enable */ \ + {{SDRAM_CS0_BASE , 0, SDRAM_CS0_SIZE} ,0xFFFFFFFF,DIS}, \ + {{SDRAM_CS1_BASE , 0, SDRAM_CS1_SIZE} ,0xFFFFFFFF,DIS}, \ + {{PEX0_MEM_BASE , 0, PEX0_MEM_SIZE } ,0x0 ,EN}, \ + {{PEX0_IO_BASE , 0, PEX0_IO_SIZE } ,0x2 ,EN}, \ + {{PCI0_MEM_BASE , 0, PCI0_MEM_SIZE } ,0x1 ,EN}, \ + {{PCI0_IO_BASE , 0, PCI0_IO_SIZE } ,0x3 ,EN}, \ + {{INTER_REGS_BASE, 0, INTER_REGS_SIZE},0x8 ,EN}, \ + {{DEVICE_CS0_BASE, 0, DEVICE_CS0_SIZE},0x5 ,EN}, \ + {{DEVICE_CS1_BASE, 0, DEVICE_CS1_SIZE},0x6 ,EN}, \ + {{DEVICE_CS2_BASE, 0, DEVICE_CS2_SIZE},0x7 ,EN}, \ + {{DEVICE_CS3_BASE, 0, DEVICE_CS3_SIZE},0x4 ,EN}, \ + /* Table terminator */ \ + {{TBL_TERM, TBL_TERM, TBL_TERM}, TBL_TERM,TBL_TERM} \ +} + +#endif /* __INCmv88F5X81SysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/orion_sys/mvSysHwConfig.h b/board/mv_feroceon/mv_orion/orion_sys/mvSysHwConfig.h new file mode 100644 index 0000000..c2dfe84 --- /dev/null +++ b/board/mv_feroceon/mv_orion/orion_sys/mvSysHwConfig.h @@ -0,0 +1,190 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvSysHwCfg.h - Marvell system HW configuration file +* +* DESCRIPTION: +* None. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +#ifndef __INCmvSysHwConfigh +#define __INCmvSysHwConfigh + + +#define MV_CACHEABLE(address) ((address) | 0x80000000) + +/* includes */ +#define _1K 0x00000400 +#define _4K 0x00001000 +#define _8K 0x00002000 +#define _16K 0x00004000 +#define _32K 0x00008000 +#define _64K 0x00010000 +#define _128K 0x00020000 +#define _256K 0x00040000 +#define _512K 0x00080000 + +#define _1M 0x00100000 +#define _2M 0x00200000 +#define _4M 0x00400000 +#define _8M 0x00800000 +#define _16M 0x01000000 +#define _32M 0x02000000 +#define _64M 0x04000000 +#define _128M 0x08000000 +#define _256M 0x10000000 +#define _512M 0x20000000 + +#define _1G 0x40000000 +#define _2G 0x80000000 + +#if defined(DB_CUSTOMER) +#include "mvCustomerSysHwConfig.h" +#elif defined(MV_88F1181) +#include "mv88F1X81SysHwConfig.h" +#elif defined(MV_88F1281) +#include "mv88F1281SysHwConfig.h" +#elif defined(MV_88F5182) +#include "mv88F5182SysHwConfig.h" +#elif defined(MV_88F5082) +#include "mv88F5082SysHwConfig.h" +#elif defined(MV_88F5181L) +#include "mv88F5181LSysHwConfig.h" +#elif defined(MV_88W8660) +#include "mv88w8660SysHwConfig.h" +#elif defined(MV_88F5181) +#include "mv88F5X81SysHwConfig.h" +#elif defined(MV_88F5180N) +#include "mv88F5180NSysHwConfig.h" +#elif defined(MV_88F6082) +#include "mv88F6082SysHwConfig.h" +#elif defined(MV_88F6183) +#include "mv88F6183SysHwConfig.h" +#elif defined(MV_88F6183L) +#include "mv88F6183LSysHwConfig.h" +#endif + +#if defined(MV_BOOTSIZE_256K) + +#define BOOTDEV_CS_SIZE _256K + +#elif defined(MV_BOOTSIZE_512K) + +#define BOOTDEV_CS_SIZE _512K + +#elif defined(MV_BOOTSIZE_4M) + +#define BOOTDEV_CS_SIZE _4M + +#elif defined(MV_BOOTSIZE_8M) + +#define BOOTDEV_CS_SIZE _8M + +#elif defined(MV_BOOTSIZE_16M) + +#define BOOTDEV_CS_SIZE _16M + +#elif defined(MV_BOOTSIZE_32M) + +#define BOOTDEV_CS_SIZE _32M + +#elif defined(MV_BOOTSIZE_64M) + +#define BOOTDEV_CS_SIZE _64M + +#elif defined(MV_NAND_BOOT) + +#define BOOTDEV_CS_SIZE _512K + +#else + +#define Error MV_BOOTSIZE undefined + +#endif + +#define BOOTDEV_CS_BASE ((0xFFFFFFFF - BOOTDEV_CS_SIZE) + 1) + +/* We use the following registers to store DRAM interface pre configuration */ +/* auto-detection results */ +/* IMPORTANT: We are using mask register for that purpose. Before writing */ +/* to units mask register, make sure main maks register is set to disable */ +/* all interrupts. */ +#define DRAM_BUF_REG0 0x1011c /* sdram bank 0 size */ +#define DRAM_BUF_REG1 0x20318 /* sdram config */ +#define DRAM_BUF_REG2 0x20114 /* sdram mode */ +#define DRAM_BUF_REG3 0x20320 /* dunit control low */ +#define DRAM_BUF_REG4 0x20404 /* sdram address control */ +#define DRAM_BUF_REG5 0x2040c /* sdram timing control low */ + +#if defined(MV_INCLUDE_PEX) +#define DRAM_BUF_REG6 0x40108 /* sdram timing control high */ +#define DRAM_BUF_REG7 0x40114 /* sdram ODT control low */ +#define DRAM_BUF_REG8 0x41910 /* sdram ODT control high */ +#define DRAM_BUF_REG9 0x41a08 /* sdram Dunit ODT control */ +#define DRAM_BUF_REG10 0x41a30 /* sdram Extended Mode */ +#elif defined(MV_INCLUDE_IDMA) +#define DRAM_BUF_REG6 0x60810 /* sdram timing control high */ +#define DRAM_BUF_REG7 0x60814 /* sdram ODT control low */ +#define DRAM_BUF_REG8 0x60818 /* sdram ODT control high */ +#define DRAM_BUF_REG9 0x6081c /* sdram Dunit ODT control */ +#define DRAM_BUF_REG10 0x60820 /* sdram Extended Mode */ +#elif defined(DB_FPGA) +#define DRAM_BUF_REG6 0x10108 /* sdram timing control high */ +#define DRAM_BUF_REG7 0x10118 /* sdram ODT control low */ +#define DRAM_BUF_REG8 0x10118 /* sdram ODT control high */ +#define DRAM_BUF_REG9 0x10118 /* sdram Dunit ODT control */ +#define DRAM_BUF_REG10 0x1010c /* sdram Extended Mode */ +#endif + +/* Following the pre-configuration registers default values restored after */ +/* auto-detection is done */ +#define DRAM_BUF_REG0_DV 0 /* GPIO Interrupt Level Mask Reg */ +#define DRAM_BUF_REG1_DV 0 /* ARM Timer 1 reload register */ +#define DRAM_BUF_REG2_DV 0 /* AHB to MBUS Bridge int Mask Reg */ +#define DRAM_BUF_REG3_DV 0 /* ARM Watchdog Timer Register */ +#define DRAM_BUF_REG4_DV 0 /* Host to ARM Doorbel Mask Register */ +#define DRAM_BUF_REG5_DV 0 /* ARM To Host Doorbel Mask Register */ +#define DRAM_BUF_REG6_DV 0 /* PCI Exp Uncorrectable Err Mask Reg */ +#define DRAM_BUF_REG7_DV 0 /* PCI Exp Correctable Err Mask Reg */ +#define DRAM_BUF_REG8_DV 0 /* PCI Express interrupt Mask Reg */ +#define DRAM_BUF_REG9_DV 0 /* PCI Express Spare Register */ +#if defined(DB_FPGA) +#define DRAM_BUF_REG10_DV 0x0 +#else +#define DRAM_BUF_REG10_DV 0x012C0004 /* PCI Exp Acknowledge Timers (x4) Reg*/ +#endif + + +#define MV_ETH_TX_Q_NUM 1 +#define MV_ETH_RX_Q_NUM 1 +#define ETH_NUM_OF_RX_DESCR 64 +#define ETH_NUM_OF_TX_DESCR ETH_NUM_OF_RX_DESCR*2 + +/* port's default queueus */ +#define ETH_DEF_TXQ 0 +#define ETH_DEF_RXQ 0 + +#define MV_DISABLE_PEX_DEVICE_BAR + +#endif /* __INCmvSysHwConfigh */ diff --git a/board/mv_feroceon/mv_orion/platform.S b/board/mv_feroceon/mv_orion/platform.S new file mode 100644 index 0000000..a7ebdcc --- /dev/null +++ b/board/mv_feroceon/mv_orion/platform.S @@ -0,0 +1,1682 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#define MV_ASMLANGUAGE +#include "mvOsAsm.h" +#include +#include +#include "mvBoardEnvSpec.h" +#include "mvCtrlEnvSpec.h" +#include "mvCpuIfConfig.h" +#include "pex/mvPexRegs.h" +#include "ddr1_2/mvDramIfRegs.h" +#include "pci/mvPciRegs.h" +#include "mvCtrlEnvAsm.h" +#if defined(MV_INC_BOARD_SPI_FLASH) +#include "spi/mvSpiSpec.h" +#endif + + +#define MAGIC_BYTE0 ((MV_BOARD_I2C_MAGIC >> 24 )& 0xff) +#define MAGIC_BYTE1 ((MV_BOARD_I2C_MAGIC >> 16 )& 0xff) +#define MAGIC_BYTE2 ((MV_BOARD_I2C_MAGIC >> 8)& 0xff) +#define MAGIC_BYTE3 ((MV_BOARD_I2C_MAGIC >> 0)& 0xff) + + +/* + get_board_id - get board id from twsi eeprom + input : r5 - board id data start offset in the eeprom + +*/ +.globl lowlevel_init + +/************************************************/ +/* lowlevel_init * +/************************************************/ + +lowlevel_init: + + /* if we are DDRI board then we + should open the CS2 for only 1 MB + to turn the 7segement and not to overlap with the + internal registers and we will do it always + */ +#if !defined(MV_88F6183) && !defined(MV_88F6183L) +#if defined(MV_88F6082) + ldr r4, =0x000f1d11 +#else + ldr r4, =0x000f1b11 +#endif + + MV_DV_REG_WRITE_ASM(r4, r1, 0x20060) +#endif + + /* change reg base to 0xf1000000 */ + ldr r4, =CFG_MV_REGS + MV_DV_REG_WRITE_ASM(r4, r1, 0x20080) + +#ifndef DB_FPGA + /* Clear device ID in PCI in MV_88F5082 */ + /* Read device ID */ + MV_CTRL_MODEL_GET_ASM(r4, r1); + ldr r1, =MV_5082_DEV_ID + cmp r4, r1 + bne next + + /* Read bus number */ + MV_REG_READ_ASM(r1, r4, PCI_P2P_CONFIG_REG(0)); + mov r4, r1; + and r1, r1, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + and r4, r4, #PPCR_DEV_NUM_MASK; + orr r1, r4, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); + /* Set PCI config enable BIT31 */ + orr r1, r1, #PCAR_CONFIG_EN; + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r1, r4, PCI_CONFIG_ADDR_REG(0)); + /* Set PCI configuration data to 0xffffffff */ + ldr r1, =0xffffffff + MV_REG_WRITE_ASM(r1, r4, PCI_CONFIG_DATA_REG(0)); + +#endif /* DB_FPGA */ + /* save Link Registers */ +next: mov r2, lr + +#ifndef DB_FPGA + bl _i2cInit + + /* Initialize BUS-L to DDR configuration parameters */ + /* Must be done prior to DDR operation */ + bl _mvCpuIfPreInit +#endif /* DB_FPGA */ + + +#if !defined(MV_INC_BOARD_DDIM) + + + +#if defined(DB_CUSTOMER) + /* Insert here customer boards specific */ + /* init MPP */ + ldr r6, =RD_88F5181L_CUS1_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F5181L_CUS1_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_88F5181L_CUS1_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =RD_88F5181L_CUS1_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =RD_88F5181L_CUS1_GPP_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + ldr r6, =RD_88F5181L_CUS1_GPP_VAL + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F6183GP) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, 0x1480) + +#if defined(MV_INCLUDE_PCI) + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) +#endif + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F6183AP) +#if defined(MV_INC_BOARD_SPI_FLASH) + /* configure the Prescale of SPI clk Tclk = 166MHz */ + MV_REG_READ_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) + and r6, r6, #~MV_SPI_CLK_PRESCALE_MASK + orr r6, r6, #0x14 + MV_REG_WRITE_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) +#endif + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, 0x1480) + +#if defined(MV_INCLUDE_PCI) + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) +#endif + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5082) + /* Set SATA LED to blink */ + ldr r6, =0x1 + MV_REG_WRITE_ASM (r6, r1, 0x8002C) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + +#if defined(MV_INCLUDE_PCI) + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) +#endif + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5082_3) + /* Set SATA LED to blink */ + ldr r6, =0x1 + MV_REG_WRITE_ASM (r6, r1, 0x8002C) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5182) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + +#if defined(MV_INCLUDE_PCI) + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) +#endif + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5182_3) + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88W8660) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88W8660_AP82S) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5181L_FE) + + /* init MPP */ + ldr r6, =RD_88F5181L_VOIP_FE_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F5181L_VOIP_FE_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_88F5181L_VOIP_FE_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =RD_88F5181L_VOIP_FE_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =RD_88F5181L_VOIP_FE_GPP_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 -turn off leds0 0,15 wireless indication-*/ + ldr r6, =RD_88F5181L_VOIP_FE_GPP_IO + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5181L_GE) + + /* init MPP */ + ldr r6, =RD_88F5181L_VOIP_GE_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F5181L_VOIP_GE_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_88F5181L_VOIP_GE_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =RD_88F5181L_VOIP_GE_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0xFFFF0330 + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 -turn off leds 10 wireless indication-*/ + ldr r6, =0xC + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5181_GTWFE) + + /* init MPP */ + ldr r6, =RD_88F5181_GTW_FE_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F5181_GTW_FE_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_88F5181_GTW_FE_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =RD_88F5181_GTW_FE_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0xFFFF0330 + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 -turn off leds 10 wireless indication-*/ + ldr r6, =0xC + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5181_GTWGE) + + /* init MPP */ + ldr r6, =RD_88F5181_GTW_GE_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F5181_GTW_GE_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_88F5181_GTW_GE_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =RD_88F5181_GTW_GE_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0xFFFF0330 + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 -turn off leds 10 wireless indication-*/ + ldr r6, =0xC + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F5181L_FXO_GE) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(MV_POS_NAS) + + /* init MPP */ + ldr r6, =RD_88F5181_POS_NAS_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F5181_POS_NAS_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_88F5181_POS_NAS_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =RD_88F5181_POS_NAS_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0x00000BDF + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 */ + ldr r6, =0x0000e000 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(MV_VOIP) + + /* init MPP */ + ldr r6, =RD_88F5181_VOIP_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F5181_VOIP_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =RD_88F5181_VOIP_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =RD_88F5181_VOIP_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0x000005F5 + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 */ + ldr r6, =0x0000D000 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + bl _mvDramIfStaticInit + + b done + +#elif defined(DB_PRPMC) + + /* init MPP */ + ldr r6, =DB_88F5181_DDR1_PRPMC_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5181_DDR1_PRPMC_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5181_DDR1_PRPMC_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5181_DDR1_PRPMC_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0xFFFF8FFC + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 */ + ldr r6, =0x00006000 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + bl _mvDramIfStaticInit + + b done + +#elif defined(DB_MNG) + + /* init MPP */ + ldr r6, =DB_88F5181_DDR1_MNG_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5181_DDR1_MNG_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5181_DDR1_MNG_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5181_DDR1_MNG_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =DB_88F5181_DDR1_MNG_GPP_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 */ + ldr r6, =0x00006000 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Init PCI arbiter according to Monarch bit 4 in I2c register 0x27 */ + /* If this bit is set disable internal arbiter. */ + mov r4, #0x27 + mov r7, #1 + + bl _i2cRead /* result in r7 */ + + tst r7, #0x10 + + bne no_pci_arbiter + + /* Activate PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + +no_pci_arbiter: + bl _mvDramIfStaticInit + + b done + +#elif defined(DB_FPGA) + +#if defined(MV_MEM_OVER_PCI_WA) + /* Disable PCI ARBITER */ + ldr r6, =0x00000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + MV_REG_READ_ASM (r6, r1, 0x30c00) + orr r6, r6, #0x20000000 + bic r6, r6, #0x10 + MV_REG_WRITE_ASM (r6, r1, 0x30c00) + + /* Set config bus to 1 and device to 0 */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + mov r1, r6; + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + and r1, r1, #PPCR_DEV_NUM_MASK; + orr r6, r1, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */ + /* Set PCI config enable BIT31 and config reg 64 */ + orr r6, r6, #PCAR_CONFIG_EN; + orr r6, r6, #0x64; + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + MV_REG_READ_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + /* Write the Data to the PCI Data register */ + ldr r1, =0xffff + bic r7, r7, r1 + orr r7, r7, #0x100 + MV_REG_WRITE_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + + /* Set config PCI ME/IOE/MEME */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + mov r1, r6; + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + and r1, r1, #PPCR_DEV_NUM_MASK; + orr r6, r1, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */ + /* Set PCI config enable BIT31 and config reg 4 */ + orr r6, r6, #(PCAR_CONFIG_EN | 0x4); + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + MV_REG_READ_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + /* Write the Data to the PCI Data register */ + orr r7, r7, #0x7 + MV_REG_WRITE_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + + MV_REG_READ_ASM (r6, r1, 0x20104) + and r6, r6, #~0x1; + MV_REG_WRITE_ASM (r6, r1, 0x20104) + + /* Read PCI agent device ID */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + ldr r1, =(0x8 << PCAR_DEVICE_NUM_OFFS); + orr r6, r6, r1 + /* Set PCI config enable BIT31 */ + orr r6, r6, #PCAR_CONFIG_EN; + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + +wait_for_pci: + /* Read the Data returned in the PCI Data register */ + MV_REG_READ_ASM(r6, r1, PCI_CONFIG_DATA_REG(0)); + mov r6, r6, LSR #PDVIR_DEV_ID_OFFS /* toReg = toReg >> 16 */ + + /* if Orion NAS default board is DB, rd must have special compilation flag */ + ldr r1, =MV_5181_DEV_ID + cmp r1, r6 + beq dram_config + ldr r1, =0x6450 + cmp r1, r6 + beq dram_config + b wait_for_pci + +dram_config: + /* Set PCI agent ME/IOE/MEME */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + ldr r1, =(0x8 << PCAR_DEVICE_NUM_OFFS); + orr r6, r6, r1 + /* Set PCI config enable BIT31 */ + orr r6, r6, #(PCAR_CONFIG_EN | 0x4); + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + MV_REG_READ_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + /* Write the Data to the PCI Data register */ + orr r7, r7, #0x7 + MV_REG_WRITE_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + + ldr r6, =0x0 + /* Set PCI window base address to address 0 */ + MV_REG_WRITE_ASM (r6, r1, 0x20014) + /* Set remap to 128MB */ + ldr r6, =BIT27 + MV_REG_WRITE_ASM (r6, r1, 0x20018) + + /* Set PCI window size 128MB */ + MV_REG_READ_ASM (r6, r1, 0x20010) + ldr r1, =0xffff + and r6, r6, r1 + ldr r1, =0x7ff + orr r6, r1, LSL #16 + MV_REG_WRITE_ASM (r6, r1, 0x20010) + + /* Set PCI I/O window base address to address f2000000 */ + ldr r6, =0xf5131 + MV_REG_WRITE_ASM (r6, r1, 0x20030) + /* Set base to 0xf2000000 */ + ldr r6, =0xf2000000 + MV_REG_WRITE_ASM (r6, r1, 0x20034) + /* Set remap to 0xf1000000 */ + ldr r6, =0xf1000000 + MV_REG_WRITE_ASM (r6, r1, 0x20038) + +#else + + /* Disable PCI ARBITER */ + ldr r6, =0x00000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + MV_REG_READ_ASM (r6, r1, 0x30c00) + orr r6, r6, #0x20000000 + bic r6, r6, #0x10 + MV_REG_WRITE_ASM (r6, r1, 0x30c00) + + /* Enable access to internal registers in PCI IO tran' */ + MV_REG_READ_ASM (r6, r1, 0x30c3c) + bic r6, r6, #0x400 + MV_REG_WRITE_ASM (r6, r1, 0x30c3c) + + + /* Set config bus to 1 and device to 0 */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + mov r1, r6; + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + and r1, r1, #PPCR_DEV_NUM_MASK; + orr r6, r1, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */ + /* Set PCI config enable BIT31 and config reg 64 */ + orr r6, r6, #PCAR_CONFIG_EN; + orr r6, r6, #0x64; + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + MV_REG_READ_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + /* Write the Data to the PCI Data register */ + ldr r1, =0xffff + bic r7, r7, r1 + orr r7, r7, #0x100 + MV_REG_WRITE_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + + /* Set config PCI ME/IOE/MEME */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + mov r1, r6; + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + and r1, r1, #PPCR_DEV_NUM_MASK; + orr r6, r1, LSR #(PPCR_DEV_NUM_OFFS - PCAR_DEVICE_NUM_OFFS); /* toReg = toReg | (tmpReg >> 13) */ + /* Set PCI config enable BIT31 and config reg 4 */ + orr r6, r6, #(PCAR_CONFIG_EN | 0x4); + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + MV_REG_READ_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + /* Write the Data to the PCI Data register */ + orr r7, r7, #0x7 + MV_REG_WRITE_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + + MV_REG_READ_ASM (r6, r1, 0x20104) + and r6, r6, #~0x1; + MV_REG_WRITE_ASM (r6, r1, 0x20104) + + /* Read PCI agent device ID */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + ldr r1, =(0x8 << PCAR_DEVICE_NUM_OFFS); + orr r6, r6, r1 + /* Set PCI config enable BIT31 */ + orr r6, r6, #PCAR_CONFIG_EN; + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + +wait_for_pci: + /* Read the Data returned in the PCI Data register */ + MV_REG_READ_ASM(r6, r1, PCI_CONFIG_DATA_REG(0)); + mov r6, r6, LSR #PDVIR_DEV_ID_OFFS /* toReg = toReg >> 16 */ + + ldr r1, =0x6450 + cmp r1, r6 + beq con_config + b wait_for_pci + +con_config: + /* Set PCI agent ME/IOE/MEME */ + MV_REG_READ_ASM(r6, r1, PCI_P2P_CONFIG_REG(0)); + and r6, r6, #PPCR_BUS_NUM_MASK; + /* Read dev number */ + ldr r1, =(0x8 << PCAR_DEVICE_NUM_OFFS); + orr r6, r6, r1 + /* Set PCI config enable BIT31 */ + orr r6, r6, #(PCAR_CONFIG_EN | 0x4); + /* Write the address to the PCI configuration address register */ + MV_REG_WRITE_ASM(r6, r1, PCI_CONFIG_ADDR_REG(0)); + MV_REG_READ_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + /* Write the Data to the PCI Data register */ + orr r7, r7, #0x7 + MV_REG_WRITE_ASM(r7, r1, PCI_CONFIG_DATA_REG(0)); + + /* Set PCI I/O window base address to address f2000000 */ + ldr r6, =0xf5131 + MV_REG_WRITE_ASM (r6, r1, 0x20030) + /* Set base to 0xf2000000 */ + ldr r6, =0xf2000000 + MV_REG_WRITE_ASM (r6, r1, 0x20034) + /* Set remap to 0xf1000000 */ + ldr r6, =0xf1000000 + MV_REG_WRITE_ASM (r6, r1, 0x20038) + + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + bl _mvDramIfStaticInit +#endif + b done +#elif defined(DB_PEX_PCI) + /* init MPP */ + ldr r6, =DB_88F5181_DDR1_PEXPCI_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5181_DDR1_PEXPCI_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5181_DDR1_PEXPCI_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5181_DDR1_PEXPCI_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0xFFFF0FFF + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 */ + ldr r6, =0x00001000 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + bl _mvDramIfStaticInit + + b done + +#elif defined(RD_88F6082NAS) + /* Set SATA LED to blink and do not invert indication */ + ldr r6, =0x9 + MV_REG_WRITE_ASM (r6, r1, 0x6002C) + + /* init MPP */ + ldr r6, =RD_88F6082_NAS_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F6082_NAS_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + + /* init GPP , disable HDD power */ + MV_REG_READ_ASM (r6, r1, 0x10100) + bic r6, r6, #(1 << 11) + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /* init GPP , Out enable */ + ldr r6, =RD_88F6082_NAS_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + b done + +#elif defined(RD_88F6082DAS_PLUS) + /* Set SATA LED to blink */ + ldr r6, =0x1 + MV_REG_WRITE_ASM (r6, r1, 0x6002C) + + /* init MPP */ + ldr r6, =RD_88F6082_DAS_P_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F6082_DAS_P_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + + /* init GPP , disable HDD power */ + MV_REG_READ_ASM (r6, r1, 0x10100) + bic r6, r6, #(1 << 2) + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /* init GPP , Out enable */ + ldr r6, =RD_88F6082_DAS_P_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + b done + +#elif defined(RD_88F6082MICRO_DAS_NAS) + + /* Invert SATA indecation polarety and set LED to blink */ + ldr r6, =0x9 + MV_REG_WRITE_ASM (r6, r1, 0x6002C) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /*DDR SDRAM set pad drive */ + MV_REG_READ_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + orr r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + orr r6, r6, #0x3000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + bic r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + MV_REG_READ_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + orr r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + orr r6, r6, #0x3000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + bic r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + +#ifdef MV_INC_DRAM_MFG_TEST + /* DDR MFG test */ + bl _mvDramMfgTest +#endif + + b done + +#elif defined(RD_88F6082GE_SATA) + /* Set SATA LED to blink */ + ldr r6, =0x1 + MV_REG_WRITE_ASM (r6, r1, 0x6002C) + + /* init MPP */ + ldr r6, =RD_88F6082_GE_SATA_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =RD_88F6082_GE_SATA_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + + /* init GPP , disable HDD power */ + MV_REG_READ_ASM (r6, r1, 0x10100) + and r6, r6, #(1 << 10) + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /* init GPP , Out enable */ + ldr r6, =RD_88F6082_GE_SATA_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + b done + +#elif defined(DB_88F6082BP) + /* Set SATA LED to blink */ + ldr r6, =0x1 + MV_REG_WRITE_ASM (r6, r1, 0x6002C) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /*DDR SDRAM set pad drive */ + MV_REG_READ_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + orr r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + orr r6, r6, #0x3000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + bic r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_ADDR_CTRL_PADS_CAL_REG) + MV_REG_READ_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + orr r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + orr r6, r6, #0x3000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + bic r6, r6, #0x80000000 + MV_REG_WRITE_ASM (r6, r1, SDRAM_DATA_PADS_CAL_REG) + + b done + +#elif defined(DB_88F6082LBP) + /* Set SATA LED to blink */ + ldr r6, =0x1 + MV_REG_WRITE_ASM (r6, r1, 0x6002C) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + b done + +#elif defined(RD_88F6082_DX243) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + b done + +#endif + +#else /* #if !defined(MV_INC_BOARD_DDIM) */ + +/* First jump to the new board release without the board ID on the TWSI */ +#if defined(MV_88F5082) + b db_88f5082_ddr2 +#elif defined(MV_88F1281) + b db_88f1281_ddr2 +#elif defined(MV_88F5182) + b db_88f5182_ddr2 +#elif defined(DB_88F5181) + b db_88f5x81_ddrx +#elif defined(RD_DB_88F5181L) + b db_88f5181L_ddr2 +#elif defined(MV_88W8660) + b db_88w8660_ddr2 +#elif defined(MV_88F5180N) + b db_88f5180n_ddrx +#elif defined(MV_88F6082) + b db_88f6082_sa +#elif defined(MV_88F6183) ||defined(MV_88F6183L) + b db_88f6183_bp +#else + cmp r7, #DB_88F5181_5281_DDR1 + beq db_88f5181_5281_ddr1 + cmp r7, #DB_88F5181_5281_DDR2 + beq db_88f5181_5281_ddr2 +#endif + + +#if defined(MV_88F5082) + +db_88f5082_ddr2: + /* Set SATA LED to blink */ + ldr r6, =0x1 + MV_REG_WRITE_ASM (r6, r1, 0x8002C) + + /* init MPP */ + ldr r6, =DB_88F5082_DDR2_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5082_DDR2_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5082_DDR2_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + + /* turn 7segment to val 1 - Set DevCS0- window 6 is the default*/ + ldr r6, =0x8FCFFFFF + MV_REG_WRITE_ASM (r6, r1, 0x1045C) + ldr r6, =0x000F1E11 + MV_REG_WRITE_ASM (r6, r1, 0x20050) + ldr r6, =0xE0000000 + MV_REG_WRITE_ASM (r6, r1, 0x20054) + + + ldr r6, =0xE0000010 /* DevCS0 Default base address +0x10 */ + ldr r6, [r6] + + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + /* Set dram width to 16bit */ + MV_REG_READ_ASM (r6, r1, 0x1400) + bic r6, r6, #0xc000 + orr r6, r6, #0x4000 + MV_REG_WRITE_ASM (r6, r1, 0x1400) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + ldr r6, =0xE0000020 /* DevCS0 Default base address +0x20 */ + ldr r6, [r6] + + b done + + +#elif defined(MV_88F5182) + +db_88f5182_ddr2: + + /* init MPP */ + ldr r6, =DB_88F5182_DDR2_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5182_DDR2_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5182_DDR2_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + + /* turn 7segment to val 1 - Set DevCS0- window 6 is the default*/ + ldr r6, =0x8FCFFFFF + MV_REG_WRITE_ASM (r6, r1, 0x1045C) + ldr r6, =0x000F1E11 + MV_REG_WRITE_ASM (r6, r1, 0x20050) + ldr r6, =0xE0000000 + MV_REG_WRITE_ASM (r6, r1, 0x20054) + + + ldr r6, =0xE0000010 /* DevCS0 Default base address +0x10 */ + ldr r6, [r6] + + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + /* Set dram width to 16bit */ + MV_REG_READ_ASM (r6, r1, 0x1400) + bic r6, r6, #0xc000 + orr r6, r6, #0x4000 + MV_REG_WRITE_ASM (r6, r1, 0x1400) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + ldr r6, =0xE0000020 /* DevCS0 Default base address +0x20 */ + ldr r6, [r6] + + b done + +#elif defined(MV_88F1281) + +db_88f1281_ddr2: + + /* init MPP */ + ldr r6, =DB_88F1281_DDR2_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F1281_DDR2_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + /* init GPP , Out enable */ + ldr r6, =DB_88F1281_DDR2_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 */ + ldr r6, =0x4 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + b done + +#elif defined(RD_DB_88F5181L) + +db_88f5181L_ddr2: + + /* init MPP */ + ldr r6, =DB_88F5181L_DDR2_2XTDM_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5181L_DDR2_2XTDM_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5181L_DDR2_2XTDM_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5181L_DDR2_2XTDM_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* turn 7segment to val 1 - Set DevCS0- window 6 is the default*/ + ldr r6, =0x8FCFFFFF + MV_REG_WRITE_ASM (r6, r1, 0x1045C) + ldr r6, =0x000F1E11 + MV_REG_WRITE_ASM (r6, r1, 0x20050) + ldr r6, =0xE0000000 + MV_REG_WRITE_ASM (r6, r1, 0x20054) + + + ldr r6, =0xE0000010 /* DevCS0 Default base address +0x10 */ + ldr r6, [r6] + + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + ldr r6, =0xE0000020 /* DevCS0 Default base address +0x20 */ + ldr r6, [r6] + + b done + + +#elif defined(MV_88F6183) || defined(MV_88F6183L) +db_88f6183_bp: + +#if defined(MV_INC_BOARD_SPI_FLASH) + /* configure the Prescale of SPI clk Tclk = 166MHz */ + MV_REG_READ_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) + and r6, r6, #~MV_SPI_CLK_PRESCALE_MASK + orr r6, r6, #0x14 + MV_REG_WRITE_ASM (r6, r1, MV_SPI_IF_CONFIG_REG) +#endif + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, 0x1480) + +1: MV_REG_READ_ASM (r6, r1, 0x1480) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + b done + +#elif defined(MV_88W8660) + +db_88w8660_ddr2: + /* init MPP */ + ldr r6, =DB_88W8660_DDR2_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88W8660_DDR2_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + + /* turn 7segment to val 1 - Set DevCS0- window 6 is the default*/ + ldr r6, =0x8FCFFFFF + MV_REG_WRITE_ASM (r6, r1, 0x1045C) + ldr r6, =0x000F1E11 + MV_REG_WRITE_ASM (r6, r1, 0x20050) + ldr r6, =0xE0000000 + MV_REG_WRITE_ASM (r6, r1, 0x20054) + + + ldr r6, =0xE0000010 /* DevCS0 Default base address +0x10 */ + ldr r6, [r6] + + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + ldr r6, =0xE0000020 /* DevCS0 Default base address +0x20 */ + ldr r6, [r6] + + b done + +#elif defined(MV_88F5180N) +db_88f5180n_ddrx: + + /* init MPP */ + ldr r6, =DB_88F5180N_DDRX_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5180N_DDRX_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5180N_DDRX_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5180N_DDRX_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* turn 7segment to val 1 - Set DevCS0- window 6 is the default*/ + ldr r6, =0x8FCFFFFF + MV_REG_WRITE_ASM (r6, r1, 0x1045C) + ldr r6, =0x000F1E11 + MV_REG_WRITE_ASM (r6, r1, 0x20050) + ldr r6, =0xE0000000 + MV_REG_WRITE_ASM (r6, r1, 0x20054) + + + ldr r6, =0xE0000010 /* DevCS0 Default base address +0x10 */ + ldr r6, [r6] + + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + ldr r6, =0xE0000020 /* DevCS0 Default base address +0x20 */ + ldr r6, [r6] + + b done + +#elif defined(MV_88F6082) +db_88f6082_sa: + /* init MPP */ + ldr r6, =DB_88F6082_SA_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F6082_SA_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + + /* init GPP , Out enable */ + ldr r6, =DB_88F6082_SA_OE + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + ldr r6, =0xE0000020 /* DevCS0 Default base address +0x20 */ + ldr r6, [r6] + + b done +#else + +db_88f5181_5281_ddr1: /*old board*/ + + /* init MPP */ + ldr r6, =DB_88F5181_5281_DDR1_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5181_5281_DDR1_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5181_5281_DDR1_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5181_5281_DDR1_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + + /* turn 7segment to val 1 - Set DevCS2- window 6 is the default*/ + ldr r6, =0x8FCFFFFF + MV_REG_WRITE_ASM (r6, r1, 0x10464) + ldr r6, =0x000F1B11 + MV_REG_WRITE_ASM (r6, r1, 0x20060) + ldr r6, =0xF0000000 + MV_REG_WRITE_ASM (r6, r1, 0x20064) + + + ldr r6, =0xF0000010 /* DevCS2 Default base address +0x10 */ + ldr r6, [r6] + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + #if 0 + ldr r6, =0xF0000020 /* DevCS2 Default base address +0x20 */ + ldr r6, [r6] + #endif + + b done + +db_88f5181_5281_ddr2: /*old board*/ + + /* init MPP */ + ldr r6, =DB_88F5181_5281_DDR2_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5181_5281_DDR2_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5181_5281_DDR2_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5181_5281_DDR2_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* init GPP , Out enable */ + ldr r6, =0xFFFF3F3F + MV_REG_WRITE_ASM (r6, r1, 0x10104) + + /* turn Led to 1 */ + ldr r6, =0x00004000 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + /* turn Led to 2 */ + ldr r6, =0x00008000 + MV_REG_WRITE_ASM (r6, r1, 0x10100) + + b done + +db_88f5x81_ddrx: + + /* init MPP */ + ldr r6, =DB_88F5X81_DDRX_MPP0_7 + MV_REG_WRITE_ASM (r6, r1, 0x10000) + ldr r6, =DB_88F5X81_DDRX_MPP8_15 + MV_REG_WRITE_ASM (r6, r1, 0x10004) + ldr r6, =DB_88F5X81_DDRX_MPP16_23 + MV_REG_WRITE_ASM (r6, r1, 0x10050) + ldr r6, =DB_88F5X81_DDRX_MPP_DEV + MV_REG_WRITE_ASM (r6, r1, 0x10008) + + /* turn 7segment to val 1 - Set DevCS0- window 6 is the default*/ + ldr r6, =0x8FCFFFFF + MV_REG_WRITE_ASM (r6, r1, 0x1045C) + ldr r6, =0x000F1E11 + MV_REG_WRITE_ASM (r6, r1, 0x20050) + ldr r6, =0xE0000000 + MV_REG_WRITE_ASM (r6, r1, 0x20054) + + ldr r6, =0xE0000010 /* DevCS0 Default base address +0x10 */ + ldr r6, [r6] + + /* PCI ARBITER */ + ldr r6, =0x80000030 + MV_REG_WRITE_ASM (r6, r1, 0x31d00) + + /*DDR SDRAM Initialization Control */ + ldr r6, =0x00000001 + MV_REG_WRITE_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) +1: MV_REG_READ_ASM (r6, r1, DDR_SDRAM_INIT_CTRL_REG) + cmp r6, #0 + bne 1b + + /* Load r3 with the size to open SDRAM bank 0 */ + mov r3, #0x04000000 /* Open DRAM bank 0 to 64MB */ + + /* Call DRAM basic initialization to allow C runtime stack */ + bl _mvDramIfBasicInit + + ldr r6, =0xE0000020 /* DevCS0 Default base address +0x20 */ + ldr r6, [r6] + + b done +#endif + + +#endif /*#if !defined(MV_INC_BOARD_DDIM)*/ +done: + mov lr, r2 + + + /* All done by Integrator's boot monitor! */ + mov pc, lr + + + .globl _mvDramMfgTest + +_mvDramMfgTest: + + mov r11, lr /* Save link register */ + + ldr r3,=0x55555555 + ldr r7,=0x0 + ldr r8,=0x0 + +mem_test: + /* memory test for the U-Boot space */ + + ldr r4,= 0 + ldr r5,= 0x400000 + +fill_mem: + str r3, [r4] + add r4, r4, #4 + cmp r4, r5 + bne fill_mem + + ldr r4,= 0 + +check_mem: + ldr r6, [r4] + cmp r6, r3 + bne fail_mem + add r4, r4, #4 + cmp r4, r5 + bne check_mem + + cmp r8, #0x0 + bne next_test + ldr r3,=0xAAAAAAAA + add r8, r8, #1 + b mem_test + +next_test: + /* Undo walking 1 or 0 */ + b pass_mem + cmp r8, #0x1 + bne next_test1 + /* walking 1 */ + mov r3, r8, LSL r7 + add r7, r7, #1 + cmp r7, #0x32 + bne mem_test + + add r8, r8, #1 + eor r7, r7, r7 + ldr r3,=0x7FFFFFFF + +next_test1: + cmp r8, #0x2 + bne pass_mem + /* walking 0 */ + mov r3, r3, ROR r7 + add r7, r7, #1 + cmp r7, #0x32 + bne mem_test + +pass_mem: + mov lr, r11 + mov pc, lr + +fail_mem: + /* Error Message */ + bl _mvDramMfgFailMes +fail_mem1: + b fail_mem1 + + .globl _mvDramMfgFailMes + +_mvDramMfgFailMes: + + mov r11, lr /* Save link register */ + + ldr r2, =(INTER_REGS_BASE + 0x12000); + + mov r1, #10 + strb r1, [r2] + mov r1, #13 + strb r1, [r2] + mov r1, #'M' + strb r1, [r2] + mov r1, #'F' + strb r1, [r2] + mov r1, #'G' + strb r1, [r2] + mov r1, #' ' + strb r1, [r2] + mov r1, #'D' + strb r1, [r2] + mov r1, #'R' + strb r1, [r2] + mov r1, #'A' + strb r1, [r2] + mov r1, #'M' + strb r1, [r2] + mov r1, #' ' + strb r1, [r2] + mov r1, #'F' + strb r1, [r2] + mov r1, #'A' + strb r1, [r2] + mov r1, #'I' + strb r1, [r2] + mov r1, #'L' + strb r1, [r2] + mov r1, #'!' + strb r1, [r2] + mov lr, r11 + mov pc, lr + diff --git a/board/mv_feroceon/uboot_oss/mvOs.c b/board/mv_feroceon/uboot_oss/mvOs.c new file mode 100644 index 0000000..77f15e1 --- /dev/null +++ b/board/mv_feroceon/uboot_oss/mvOs.c @@ -0,0 +1,248 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +*******************************************************************************/ +/******************************************************************************* +* mvOsCpuArchLib.c - Marvell CPU architecture library +* +* DESCRIPTION: +* This library introduce Marvell API for OS dependent CPU architecture +* APIs. This library introduce single CPU architecture services APKI +* cross OS. +* +* DEPENDENCIES: +* None. +* +*******************************************************************************/ + +/* includes */ +#include +#include "mvOs.h" + +static MV_U32 read_p15_c0 (void); + +/* defines */ +#define ARM_ID_REVISION_OFFS 0 +#define ARM_ID_REVISION_MASK (0xf << ARM_ID_REVISION_OFFS) + +#define ARM_ID_PART_NUM_OFFS 4 +#define ARM_ID_PART_NUM_MASK (0xfff << ARM_ID_PART_NUM_OFFS) + +#define ARM_ID_ARCH_OFFS 16 +#define ARM_ID_ARCH_MASK (0xf << ARM_ID_ARCH_OFFS) + +#define ARM_ID_VAR_OFFS 20 +#define ARM_ID_VAR_MASK (0xf << ARM_ID_VAR_OFFS) + +#define ARM_ID_ASCII_OFFS 24 +#define ARM_ID_ASCII_MASK (0xff << ARM_ID_ASCII_OFFS) + + +/******************************************************************************* +* mvOsCpuVerGet() - +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit CPU Revision +* +*******************************************************************************/ +MV_U32 mvOsCpuRevGet( MV_VOID ) +{ + return ((read_p15_c0() & ARM_ID_REVISION_MASK ) >> ARM_ID_REVISION_OFFS); +} +/******************************************************************************* +* mvOsCpuPartGet() - +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit CPU Part number +* +*******************************************************************************/ +MV_U32 mvOsCpuPartGet( MV_VOID ) +{ + return ((read_p15_c0() & ARM_ID_PART_NUM_MASK ) >> ARM_ID_PART_NUM_OFFS); +} +/******************************************************************************* +* mvOsCpuArchGet() - +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit CPU Architicture number +* +*******************************************************************************/ +MV_U32 mvOsCpuArchGet( MV_VOID ) +{ + return ((read_p15_c0() & ARM_ID_ARCH_MASK ) >> ARM_ID_ARCH_OFFS); +} +/******************************************************************************* +* mvOsCpuVarGet() - +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit CPU Variant number +* +*******************************************************************************/ +MV_U32 mvOsCpuVarGet( MV_VOID ) +{ + return ((read_p15_c0() & ARM_ID_VAR_MASK ) >> ARM_ID_VAR_OFFS); +} +/******************************************************************************* +* mvOsCpuAsciiGet() - +* +* DESCRIPTION: +* +* INPUT: +* None. +* +* OUTPUT: +* None. +* +* RETURN: +* 32bit CPU Variant number +* +*******************************************************************************/ +MV_U32 mvOsCpuAsciiGet( MV_VOID ) +{ + return ((read_p15_c0() & ARM_ID_ASCII_MASK ) >> ARM_ID_ASCII_OFFS); +} + + + +/* +static unsigned long read_p15_c0 (void) +*/ +/* read co-processor 15, register #0 (ID register) */ +static MV_U32 read_p15_c0 (void) +{ + MV_U32 value; + + __asm__ __volatile__( + "mrc p15, 0, %0, c0, c0, 0 @ read control reg\n" + : "=r" (value) + : + : "memory"); + + return value; +} + + +MV_U32 mvOsIoVirtToPhy( void* pDev, void* pVirtAddr ) +{ + return (MV_U32)pVirtAddr; +} + +void* mvOsIoUncachedMalloc( void* osHandle, MV_U32 size, MV_ULONG* pPhyAddr, MV_U32* memHandle) +{ + *pPhyAddr = (MV_ULONG)malloc(size); + return (void *)(*pPhyAddr); +} + +void mvOsIoUncachedFree( void* osHandle, MV_U32 size, MV_ULONG phyAddr, void* pVirtAddr, MV_U32 memHandle) +{ + free(pVirtAddr); +} + +void* mvOsIoCachedMalloc( void* osHandle, MV_U32 size, MV_ULONG* pPhyAddr, MV_U32* memHandle) +{ + *pPhyAddr = (MV_ULONG)malloc(size); + return (void *)(*pPhyAddr); +} + +void mvOsIoCachedFree( void* osHandle, MV_U32 size, MV_ULONG phyAddr, void* pVirtAddr, MV_U32 memHandle) +{ + free(pVirtAddr); +} + +MV_U32 mvOsCacheFlush( void* osHandle, void* p, int size ) +{ + return (MV_U32)p;/* ronen - need to be filled */ +} + +MV_U32 mvOsCacheInvalidate( void* osHandle, void* p, int size ) +{ + return (MV_U32)p;/* ronen - need to be filled */ +} + +int mvOsRand(void) +{ + return 0; +} + +int mvOsStrCmp(const char *str1,const char *str2) +{ + + do + { + if ((*str1++) != (*str2++)) return 1; /* not equal */ + + } + while ((*str1 != '\0') && (*str2 != '\0')); + + if (*str1 != *str2) return 1; /* not equal */ + + /* equal */ + return 0; + +} + +#if defined(REG_DEBUG) +extern int reg_arry[REG_ARRAY_SIZE][2]; +extern int reg_arry_index; +void reglog(unsigned int offset, unsigned int data) +{ + reg_arry[reg_arry_index%REG_ARRAY_SIZE][0] = (offset); + reg_arry[reg_arry_index%REG_ARRAY_SIZE][1] = (data); + reg_arry_index++; +} +#endif diff --git a/board/mv_feroceon/uboot_oss/mvOs.h b/board/mv_feroceon/uboot_oss/mvOs.h new file mode 100644 index 0000000..2343f2c --- /dev/null +++ b/board/mv_feroceon/uboot_oss/mvOs.h @@ -0,0 +1,362 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + + +#ifndef MV_OS_H +#define MV_OS_H + +/*************/ +/* Includes */ +/*************/ + +#include "mvTypes.h" +#include "mvCommon.h" +#include +#include +#include "mvSysHwConfig.h" +#include "mvCtrlEnvSpec.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +/*************/ +/* Constants */ +/*************/ + +#define MV_OS_WAIT_FOREVER 0 + +/*************/ +/* Datatypes */ +/*************/ + +#define CPU_PHY_MEM(x) (MV_U32)x +#define CPU_MEMIO_CACHED_ADDR(x) (void*)x +#define CPU_MEMIO_UNCACHED_ADDR(x) (void*)x + + +/* CPU architecture dependent 32, 16, 8 bit read/write IO addresses */ +#define MV_MEMIO32_WRITE(addr, data) \ + ((*((volatile unsigned int*)(addr))) = ((unsigned int)(data))) + +#define MV_MEMIO32_READ(addr) \ + ((*((volatile unsigned int*)(addr)))) + +#define MV_MEMIO16_WRITE(addr, data) \ + ((*((volatile unsigned short*)(addr))) = ((unsigned short)(data))) + +#define MV_MEMIO16_READ(addr) \ + ((*((volatile unsigned short*)(addr)))) + +#define MV_MEMIO8_WRITE(addr, data) \ + ((*((volatile unsigned char*)(addr))) = ((unsigned char)(data))) + +#define MV_MEMIO8_READ(addr) \ + ((*((volatile unsigned char*)(addr)))) + + +/* No Fast Swap implementation (in assembler) for ARM */ +#define MV_32BIT_LE_FAST(val) MV_32BIT_LE(val) +#define MV_16BIT_LE_FAST(val) MV_16BIT_LE(val) +#define MV_32BIT_BE_FAST(val) MV_32BIT_BE(val) +#define MV_16BIT_BE_FAST(val) MV_16BIT_BE(val) + +/* 32 and 16 bit read/write in big/little endian mode */ + +/* 16bit write in little endian mode */ +#define MV_MEMIO_LE16_WRITE(addr, data) \ + MV_MEMIO16_WRITE(addr, MV_16BIT_LE_FAST(data)) + +/* 16bit read in little endian mode */ +static __inline MV_U16 MV_MEMIO_LE16_READ(MV_U32 addr) +{ + MV_U16 data; + + data= (MV_U16)MV_MEMIO16_READ(addr); + + return (MV_U16)MV_16BIT_LE_FAST(data); +} + +/* 32bit write in little endian mode */ +#define MV_MEMIO_LE32_WRITE(addr, data) \ + MV_MEMIO32_WRITE(addr, MV_32BIT_LE_FAST(data)) + +/* 32bit read in little endian mode */ +static __inline MV_U32 MV_MEMIO_LE32_READ(MV_U32 addr) +{ + MV_U32 data; + + data= (MV_U32)MV_MEMIO32_READ(addr); + + return (MV_U32)MV_32BIT_LE_FAST(data); +} + +/****************************************************************************** +* This debug function enable the write of each register that u-boot access to +* to an array in the DRAM, the function record only MV_REG_WRITE access. +* The function could not be operate when booting from flash. +* In order to print the array we use the printreg command. +******************************************************************************/ +#if defined(REG_DEBUG) +#define REG_ARRAY_SIZE 4096 +extern int reg_arry[REG_ARRAY_SIZE][2]; +extern int reg_arry_index; + +void reglog(unsigned int offset, unsigned int data); +#endif + +/* Marvell controller register read/write macros */ +#define MV_REG_VALUE(offset) \ + (MV_MEMIO32_READ((INTER_REGS_BASE | (offset)))) + +#define MV_REG_READ(offset) \ + (MV_MEMIO_LE32_READ(INTER_REGS_BASE | (offset))) + +#if defined(REG_DEBUG) +#define MV_REG_WRITE(offset, val) \ + MV_MEMIO_LE32_WRITE((INTER_REGS_BASE | (offset)), (val)); \ + reglog((INTER_REGS_BASE | (offset)), (val)); +#else +#define MV_REG_WRITE(offset, val) \ + MV_MEMIO_LE32_WRITE((INTER_REGS_BASE | (offset)), (val)); +#endif + +#if defined(REG_DEBUG) +#define MV_REG_WORD_WRITE(offset, val) \ + MV_MEMIO_LE16_WRITE((INTER_REGS_BASE | (offset)), (val)); \ + reglog((INTER_REGS_BASE | (offset)), (val)); +#else +#define MV_REG_WORD_WRITE(offset, val) \ + MV_MEMIO_LE16_WRITE((INTER_REGS_BASE | (offset)), (val)) +#endif + +#define MV_REG_WORD_READ(offset) \ + (MV_MEMIO16_READ((INTER_REGS_BASE | (offset)))) + +#define MV_REG_BYTE_READ(offset) \ + (MV_MEMIO8_READ((INTER_REGS_BASE | (offset)))) + +#if defined(REG_DEBUG) +#define MV_REG_BYTE_WRITE(offset, val) \ + MV_MEMIO8_WRITE((INTER_REGS_BASE | (offset)), (val)); \ + reglog((INTER_REGS_BASE | (offset)), (val)); +#else +#define MV_REG_BYTE_WRITE(offset, val) \ + MV_MEMIO8_WRITE((INTER_REGS_BASE | (offset)), (val)) +#endif + +#if defined(REG_DEBUG) +#define MV_REG_BIT_SET(offset, bitMask) \ + (MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \ + (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) | \ + MV_32BIT_LE_FAST(bitMask)))); \ + reglog((INTER_REGS_BASE | (offset)), (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)))); +#else +#define MV_REG_BIT_SET(offset, bitMask) \ + (MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \ + (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) | \ + MV_32BIT_LE_FAST(bitMask)))) +#endif + +#if defined(REG_DEBUG) +#define MV_REG_BIT_RESET(offset,bitMask) \ + (MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \ + (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) & \ + MV_32BIT_LE_FAST(~bitMask)))); \ + reglog((INTER_REGS_BASE | (offset)), (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)))); +#else +#define MV_REG_BIT_RESET(offset,bitMask) \ + (MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \ + (MV_MEMIO32_READ(INTER_REGS_BASE | (offset)) & \ + MV_32BIT_LE_FAST(~bitMask)))) +#endif + + +/* Flash APIs */ +#define MV_FL_8_READ MV_MEMIO8_READ +#define MV_FL_16_READ MV_MEMIO_LE16_READ +#define MV_FL_32_READ MV_MEMIO_LE32_READ +#define MV_FL_8_DATA_READ MV_MEMIO8_READ +#define MV_FL_16_DATA_READ MV_MEMIO16_READ +#define MV_FL_32_DATA_READ MV_MEMIO32_READ +#define MV_FL_8_WRITE MV_MEMIO8_WRITE +#define MV_FL_16_WRITE MV_MEMIO_LE16_WRITE +#define MV_FL_32_WRITE MV_MEMIO_LE32_WRITE +#define MV_FL_8_DATA_WRITE MV_MEMIO8_WRITE +#define MV_FL_16_DATA_WRITE MV_MEMIO16_WRITE +#define MV_FL_32_DATA_WRITE MV_MEMIO32_WRITE + + +/* CPU cache information */ +#define CPU_I_CACHE_LINE_SIZE 32 /* 2do: replace 32 with linux core macro */ +#define CPU_D_CACHE_LINE_SIZE 32 /* 2do: replace 32 with linux core macro */ + + +/* Data cache flush one line */ +#define mvOsCacheLineFlushInv(handle, addr) +#define mvOsCacheLineInv(handle, addr) +/* Flush CPU pipe */ +#define CPU_PIPE_FLUSH + +#define INLINE inline +#define mvOsSPrintf sprintf + +/* In order to minimize image size printf, is defined as NULL */ + +#ifdef MV_RT_DEBUG +# define mvOsPrintf printf +#else +# define mvOsPrintf(fmt,args...) +#endif /* MV_RT_DEBUG */ + +#define mvOsOutput printf +#define mvOsMalloc malloc +#define mvOsFree free +#define mvOsMemcpy memcpy +#define mvOsDelay(ms) udelay(ms*1000) +#define mvOsSleep(us) mvOsDelay(us) +#define mvOsTaskLock() +#define mvOsTaskUnlock() +#define mvOsIntLock() 0 +#define mvOsIntUnlock(key) +#define mvOsUDelay(x) udelay(x) + +#define strtol simple_strtoul + +#define mvOsDivide(num, div) \ +({ \ + int i=0, rem=(num); \ + \ + while(rem >= (div)) \ + { \ + rem -= (div); \ + i++; \ + } \ + (i); \ +}) + +#define mvOsReminder(num, div) \ +({ \ + int rem = (num); \ + \ + while(rem >= (div)) \ + rem -= (div); \ + (rem); \ +}) + +#if defined(MV_BRIDGE_SYNC_REORDER) +extern MV_U32 *mvUncachedParam; + +static INLINE void mvOsBridgeReorderWA(void) +{ + /* sync write reordering in the bridge */ + volatile MV_U32 val = 0; + + val = mvUncachedParam[0]; +} +#endif + +static INLINE void mvOsBCopy(MV_U8* srcAddr, MV_U8* dstAddr, int byteCount) + +{ + + while(byteCount != 0) + + { + + *dstAddr = *srcAddr; + + dstAddr++; + + srcAddr++; + + byteCount--; + + } + +} + +/* ARM architecture APIs */ +MV_U32 mvOsCpuRevGet (MV_VOID); +MV_U32 mvOsCpuPartGet (MV_VOID); +MV_U32 mvOsCpuArchGet (MV_VOID); +MV_U32 mvOsCpuVarGet (MV_VOID); +MV_U32 mvOsCpuAsciiGet (MV_VOID); +MV_U32 mvOsIoVirtToPhy( void* osHandle, void* pVirtAddr ); +void* mvOsIoUncachedMalloc( void* osHandle, MV_U32 size, MV_ULONG* pPhyAddr, MV_U32* memHandle); +void mvOsIoUncachedFree( void* osHandle, MV_U32 size, MV_ULONG phyAddr, void* pVirtAddr, MV_U32 memHandle); +void* mvOsIoCachedMalloc( void* osHandle, MV_U32 size, MV_ULONG* pPhyAddr, MV_U32* memHandle); +void mvOsIoCachedFree( void* osHandle, MV_U32 size, MV_ULONG phyAddr, void* pVirtAddr, MV_U32 memHandle); +MV_U32 mvOsCacheFlush( void* osHandle, void* p, int size ); +MV_U32 mvOsCacheInvalidate( void* osHandle, void* p, int size ); +int mvOsRand(void); +int mvOsStrCmp(const char *str1,const char *str2); + +#ifdef __cplusplus +} +#endif + +#endif /* MV_OS_H */ diff --git a/board/mv_feroceon/uboot_oss/mvOsAsm.h b/board/mv_feroceon/uboot_oss/mvOsAsm.h new file mode 100644 index 0000000..ca33ee2 --- /dev/null +++ b/board/mv_feroceon/uboot_oss/mvOsAsm.h @@ -0,0 +1,134 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __INCmvOsAsmh +#define __INCmvOsAsmh + + +#include "mvCommon.h" + +#if defined(MV_MIPS) + #define CPU_FAMILY MIPS + #include "asm.h" + +#elif defined (MV_PPC) + #define CPU_FAMILY PPC + #include + #include <74xx_7xx.h> + #include + #include + #include + #include + +#elif defined (MV_ARM) + #define CPU_FAMILY ARM + #include + +/* BE/ LE swap for Asm */ +#if defined(MV_CPU_LE) + +#define htoll(x) x +#define HTOLL(sr,tr) + +#elif defined(MV_CPU_BE) + +#define htoll(x) ((((x) & 0x00ff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) >> 8) & 0xff00) | \ + (((x) >> 24) & 0x00ff)) + + +#define HTOLL(sr,temp) /*sr = A ,B ,C ,D */\ + eor temp, sr, sr, ROR #16 ; /*temp = A^C,B^D,C^A,D^B */\ + bic temp, temp, #0xFF0000 ; /*temp = A^C,0 ,C^A,D^B */\ + mov sr, sr, ROR #8 ; /*sr = D ,A ,B ,C */\ + eor sr, sr, temp, LSR #8 /*sr = D ,C ,B ,A */ + +#endif + +#define MV_REG_READ_ASM(toReg, tmpReg, regOffs) \ + ldr tmpReg, =(INTER_REGS_BASE + regOffs) ; \ + ldr toReg, [tmpReg] ; \ + HTOLL(toReg,tmpReg) + +#define MV_REG_WRITE_ASM(fromReg, tmpReg, regOffs) \ + HTOLL(fromReg,tmpReg) ; \ + ldr tmpReg, =(INTER_REGS_BASE + regOffs) ; \ + str fromReg, [tmpReg] + +#define MV_DV_REG_READ_ASM(toReg, tmpReg, regOffs) \ + ldr tmpReg, =(CFG_DFL_MV_REGS + regOffs) ; \ + ldr toReg, [tmpReg] ; \ + HTOLL(toReg,tmpReg) + +#define MV_DV_REG_WRITE_ASM(fromReg, tmpReg, regOffs) \ + HTOLL(fromReg,tmpReg) ; \ + ldr tmpReg, =(CFG_DFL_MV_REGS + regOffs) ; \ + str fromReg, [tmpReg] + +#else + #error "CPU type not selected" +#endif + +#endif /* __INCmvOsAsmh */ diff --git a/board/mv_feroceon/uboot_oss/mvOsSata.c b/board/mv_feroceon/uboot_oss/mvOsSata.c new file mode 100644 index 0000000..cc457a4 --- /dev/null +++ b/board/mv_feroceon/uboot_oss/mvOsSata.c @@ -0,0 +1,31 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include "mvOsSata.h" + +MV_U16 mvSwapShort(MV_U16 data) +{ + return MV_CPU_TO_LE16(data); +} +MV_U32 mvSwapWord(MV_U32 data) +{ + return MV_CPU_TO_LE32(data); +} + diff --git a/board/mv_feroceon/uboot_oss/mvOsSata.h b/board/mv_feroceon/uboot_oss/mvOsSata.h new file mode 100644 index 0000000..df89717 --- /dev/null +++ b/board/mv_feroceon/uboot_oss/mvOsSata.h @@ -0,0 +1,194 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ +/******************************************************************************* +* mvOsBios.h - O.S. interface header file for BIOS IAL +* +* DESCRIPTION: +* This header file contains OS dependent definition for BIOS +* +* DEPENDENCIES: +* +* FILE REVISION NUMBER: +* $Revision: 1.1.1.1 $ +*******************************************************************************/ + +#ifndef __INCmvOsSUBooth +#define __INCmvOsSUBooth + +#include "mvTypes.h" +#include "mvOs.h" + +/* Definitions */ +#if defined (LOG_DEBUG) || defined (LOG_ERROR) + #define PRNTHEXTSINGLE + #define DEBUG_IAL + #define DEBUG_IAL_SERIAL +#endif + +#if defined(REG_DEBUG) +extern int reg_arry[REG_ARRAY_SIZE][2]; +extern int reg_arry_index; +#endif + +/* + * Override CORE Driver SW queue size to 1. The CORE Driver SW queue is not + * used for issuing UDMA commands; so minimizing this to 1 makes it possible + * to minimize footprint of BIOS Extension driver when statically allocating + * the channel's data structures. + */ +#define MV_SATA_OVERRIDE_SW_QUEUE_SIZE +#define MV_SATA_REQUESTED_SW_QUEUE_SIZE 1 + + +#define MV_REGS_ACCESSED_BY_IO_BAR +/* System dependent macro for flushing CPU write cache */ +#define MV_CPU_WRITE_BUFFER_FLUSH() + +/* System dependent register read / write in byte/word/dword variants */ +unsigned long readRegister (unsigned long base, unsigned long offset); +void writeRegister (unsigned long base, unsigned long offset, unsigned long value); +/*void pioWrite16bit (unsigned short offset, unsigned short data); +unsigned short pioRead16bit (unsigned short offset);*/ +void waitForKeystroke (void); +unsigned short readSegmentOffset16bit (unsigned short segment_, unsigned short offset_); +unsigned char readSegmentOffset8bit (unsigned short segment_, unsigned short offset_); +void writeSegmentOffset16bit (unsigned short segment_, unsigned short offset_, unsigned short value_); +void writeSegmentOffset8bit (unsigned short segment_, unsigned short offset_, unsigned char value_); +void memcpySegmentOffset32bitForward (unsigned short segment_, + unsigned short destinationOffset_, + unsigned short sourceOffset_, + unsigned short byteCount_); + + +MV_U16 mvSwapShort(MV_U16 data); +MV_U32 mvSwapWord(MV_U32 data); + +#ifdef PRNTHEXTSINGLE +void printHexSingle(char *fmt, unsigned short value_); +#else + #define printHexSingle(x,y) +#endif + +/* System dependent little endian from / to CPU conversions */ +#if (_BYTE_ORDER == _BIG_ENDIAN) +# define MV_CPU_TO_LE16(x) MV_16BIT_LE(x) +# define MV_CPU_TO_LE32(x) MV_32BIT_LE(x) + +# define MV_LE16_TO_CPU(x) MV_16BIT_LE(x) +# define MV_LE32_TO_CPU(x) MV_32BIT_LE(x) +#else +# define MV_CPU_TO_LE16(x) (x) +# define MV_CPU_TO_LE32(x) (x) + +# define MV_LE16_TO_CPU(x) (x) +# define MV_LE32_TO_CPU(x) (x) +#endif + + +/* System dependent register read / write in byte/word/dword variants */ +/* Write 32/16/8 bit NonCacheable */ +#if defined(REG_DEBUG) +#define MV_WRITE_CHAR(address, data) \ + ((*((volatile unsigned char *)(address)))= \ + ((unsigned char)(data))); \ + reglog((address), (data)); +#else +#define MV_WRITE_CHAR(address, data) \ + ((*((volatile unsigned char *)(address)))= \ + ((unsigned char)(data))) +#endif + +#if defined(REG_DEBUG) +#define MV_WRITE_SHORT(address, data) \ + ((*((volatile unsigned short *)(address))) = \ + ((unsigned short)(data))); \ + reglog((address), (data)); +#else +#define MV_WRITE_SHORT(address, data) \ + ((*((volatile unsigned short *)(address))) = \ + ((unsigned short)(data))) +#endif + +#if defined(REG_DEBUG) +#define MV_WRITE_WORD(address, data) \ + ((*((volatile unsigned int *)(address))) = \ + ((unsigned int)(data))); \ + reglog((address), (data)); +#else +#define MV_WRITE_WORD(address, data) \ + ((*((volatile unsigned int *)(address))) = \ + ((unsigned int)(data))) +#endif + +/* Read 32/16/8 bit NonCacheable - returns data direct. */ + +#define MV_READCHAR(address) \ + ((*((volatile unsigned char *)(address)))) + +#define MV_READSHORT(address) \ + ((*((volatile unsigned short *)(address)))) + +#define MV_READWORD(address) \ + ((*((volatile unsigned int *)(address)))) + +#define MV_REG_WRITE_BYTE(base, offset, val) MV_WRITE_CHAR(base + offset, val) +#define MV_REG_WRITE_WORD(base, offset, val) MV_WRITE_SHORT(base + offset, MV_CPU_TO_LE16(val)) +#define MV_REG_WRITE_DWORD(base, offset, val) MV_WRITE_WORD(base + offset, MV_CPU_TO_LE32(val)) +#define MV_REG_READ_BYTE(base, offset) MV_READCHAR(base + offset) +#define MV_REG_READ_WORD(base, offset) mvSwapShort(MV_READSHORT(base + offset)) +#define MV_REG_READ_DWORD(base, offset) mvSwapWord(MV_READWORD(base + offset)) + + +/* System dependant typedefs */ +typedef void *MV_VOID_PTR; +typedef unsigned long *MV_U32_PTR; +typedef unsigned short *MV_U16_PTR; +typedef unsigned char *MV_U8_PTR; +typedef char *MV_CHAR_PTR; +typedef unsigned long MV_BUS_ADDR_T; +typedef unsigned long MV_CPU_FLAGS; + +/* Structures */ +/* System dependent structure */ +typedef struct mvOsSemaphore +{ + unsigned long lock; + unsigned long flags; +} MV_OS_SEMAPHORE; + +/* Typedefs */ +typedef enum mvBoolean +{ + MV_SFALSE, MV_STRUE +} MV_BOOLEAN; + + +/* Functions (User implemented)*/ +#include "sata/CoreDriver/mvLog.h" + +/* Semaphore init, take and release */ +#define mvOsSemInit(x) MV_TRUE +#define mvOsSemTake(x) +#define mvOsSemRelease(x) + +/* Delay function in micro seconds resolution */ +#define mvMicroSecondsDelay(dummy, time) udelay(time) + +#endif /* __INCmvOsSUBooth */ diff --git a/board/ns9750dev/led.c b/board/ns9750dev/led.c index b85c869..98bb3ed 100644 --- a/board/ns9750dev/led.c +++ b/board/ns9750dev/led.c @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: led.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * $Id: led.c,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * @Author: Markus Pietrek * @Descr: Defines helper functions for toggeling LEDs * @Usage: diff --git a/board/xilinx/common/xdma_channel_sg.c b/board/xilinx/common/xdma_channel_sg.c index a8e9462..9aa30c4 100644 --- a/board/xilinx/common/xdma_channel_sg.c +++ b/board/xilinx/common/xdma_channel_sg.c @@ -1,4 +1,4 @@ -/* $Id: xdma_channel_sg.c,v 1.6 2003/02/03 19:50:33 moleres Exp $ */ +/* $Id: xdma_channel_sg.c,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ /****************************************************************************** * * Author: Xilinx, Inc. diff --git a/board/xilinx/common/xipif_v1_23_b.c b/board/xilinx/common/xipif_v1_23_b.c index c7311ab..5c46a3b 100644 --- a/board/xilinx/common/xipif_v1_23_b.c +++ b/board/xilinx/common/xipif_v1_23_b.c @@ -1,4 +1,4 @@ -/* $Id: xipif_v1_23_b.c,v 1.1 2002/03/18 23:24:52 linnj Exp $ */ +/* $Id: xipif_v1_23_b.c,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ /****************************************************************************** * * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" diff --git a/board/xilinx/common/xipif_v1_23_b.h b/board/xilinx/common/xipif_v1_23_b.h index 3ce1fff..7003196 100644 --- a/board/xilinx/common/xipif_v1_23_b.h +++ b/board/xilinx/common/xipif_v1_23_b.h @@ -1,4 +1,4 @@ -/* $Id: xipif_v1_23_b.h,v 1.1 2002/03/18 23:24:52 linnj Exp $ */ +/* $Id: xipif_v1_23_b.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ /****************************************************************************** * * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" diff --git a/board/xilinx/xilinx_iic/xiic_l.c b/board/xilinx/xilinx_iic/xiic_l.c index 6b78163..4f394bb 100644 --- a/board/xilinx/xilinx_iic/xiic_l.c +++ b/board/xilinx/xilinx_iic/xiic_l.c @@ -1,4 +1,4 @@ -/* $Id: xiic_l.c,v 1.2 2002/12/05 19:32:40 meinelte Exp $ */ +/* $Id: xiic_l.c,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ /****************************************************************************** * * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" diff --git a/board/xilinx/xilinx_iic/xiic_l.h b/board/xilinx/xilinx_iic/xiic_l.h index a2c4c49..1357f52 100644 --- a/board/xilinx/xilinx_iic/xiic_l.h +++ b/board/xilinx/xilinx_iic/xiic_l.h @@ -1,4 +1,4 @@ -/* $Id: xiic_l.h,v 1.2 2002/12/05 19:32:40 meinelte Exp $ */ +/* $Id: xiic_l.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ /***************************************************************************** * * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" diff --git a/common/Makefile b/common/Makefile index 7dbf84a..a656356 100644 --- a/common/Makefile +++ b/common/Makefile @@ -51,7 +51,8 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o \ memsize.o miiphybb.o miiphyutil.o \ s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \ usb.o usb_kbd.o usb_storage.o \ - virtex2.o xilinx.o + virtex2.o xilinx.o \ + qnap_rcvr.o OBJS = $(AOBJS) $(COBJS) diff --git a/common/bedbug.c b/common/bedbug.c index 6966de7..1bf69ad 100644 --- a/common/bedbug.c +++ b/common/bedbug.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: bedbug.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ */ #include diff --git a/common/cmd_ace.c b/common/cmd_ace.c index b6d6105..f1f2ca7 100644 --- a/common/cmd_ace.c +++ b/common/cmd_ace.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id:$" +#ident "$Id: cmd_ace.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $" /* * The Xilinx SystemACE chip support is activated by defining diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 8599a49..5d8a0eb 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -839,6 +839,16 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, } #endif /* CONFIG_PPC */ +#ifdef CONFIG_MARVELL +char extraBootArgs[200]; + +/* NetBSD Stage-2 Loader Parameters: +* r6: boot args string +*/ +#define DECLARE_NETBSD_CMDLINE +register volatile char *cmdline asm ("r6"); +#endif + static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], @@ -847,14 +857,19 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, int verify) { DECLARE_GLOBAL_DATA_PTR; +#ifdef CONFIG_MARVELL + DECLARE_NETBSD_CMDLINE; +#else + char *cmdline; +#endif + bd_t *bd = gd->bd; + image_header_t *hdr = &header; void (*loader)(bd_t *, image_header_t *, char *, char *); image_header_t *img_addr; char *consdev; - char *cmdline; - /* * Booting a (NetBSD) kernel image @@ -887,9 +902,27 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, if (argc > 2) { ulong len; int i; +#ifdef CONFIG_MARVELL + unsigned int mvBoardIdGet(void); + char buf[30]; + sprintf(extraBootArgs ,"boardId=%x",mvBoardIdGet()); + + for (i = 0; i < 4; i++) + { + sprintf(buf ," dram%d_start=%x",i, bd->bi_dram[i].start); + strcat(extraBootArgs, buf); + sprintf(buf ," dram%d_size=%x",i, bd->bi_dram[i].size); + strcat(extraBootArgs, buf); + } + +#endif for (i=2, len=0 ; i 2) cmdline[len++] = ' '; + strcpy (&cmdline[len], extraBootArgs); + len += strlen (extraBootArgs); +#endif + + } else if ((cmdline = getenv("bootargs")) == NULL) { cmdline = ""; } - loader = (void (*)(bd_t *, image_header_t *, char *, char *)) hdr->ih_ep; + loader = (void (*)(bd_t *, image_header_t *, char *, char *))ntohl(hdr->ih_ep); printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", (ulong)loader); diff --git a/common/cmd_doc.c b/common/cmd_doc.c index 5e9bea3..05f1f1a 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -3,7 +3,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2000.c,v 1.46 2001/10/02 15:05:13 dwmw2 Exp $ + * $Id: cmd_doc.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ */ #include diff --git a/common/cmd_eeprom.c b/common/cmd_eeprom.c index d15a412..55e5c71 100644 --- a/common/cmd_eeprom.c +++ b/common/cmd_eeprom.c @@ -395,7 +395,11 @@ eeprom_probe (unsigned dev_addr, unsigned offset) chip |= dev_addr; /* insert device address */ +#if defined(CONFIG_MARVELL) + return (i2c_probe (1, chip)); +#else return (i2c_probe (chip)); +#endif } #endif diff --git a/common/cmd_elf.c b/common/cmd_elf.c index eccf2e9..d645bbf 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -139,7 +139,11 @@ int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) */ if ((tmp = getenv ("bootaddr")) == NULL) + #ifdef __ARM__ + bootaddr = 0x700; + #else bootaddr = 0x4200; + #endif else bootaddr = simple_strtoul (tmp, NULL, 16); diff --git a/common/cmd_ext2.c b/common/cmd_ext2.c index 5db42f2..ccac058 100644 --- a/common/cmd_ext2.c +++ b/common/cmd_ext2.c @@ -264,6 +264,7 @@ int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ext2fs_close(); return(1); } + if ((count < filelen) && (count != 0)) { filelen = count; } diff --git a/common/cmd_flash.c b/common/cmd_flash.c index 0aa4783..f6e3dd0 100644 --- a/common/cmd_flash.c +++ b/common/cmd_flash.c @@ -45,6 +45,10 @@ int find_dev_and_part(const char *id, struct mtd_device **dev, extern flash_info_t flash_info[]; /* info for FLASH chips */ +#if defined (CONFIG_MARVELL) +extern int mv_flash_real_protect_bank(flash_info_t *info, int prot); +#endif + /* * The user interface starts numbering for Flash banks with 1 * for historical reasons. @@ -586,6 +590,7 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) puts ("missing or unknown FLASH type\n"); return 1; } + for (i=0; isector_count; ++i) { #if defined(CFG_FLASH_PROTECTION) if (flash_real_protect(info, i, p)) @@ -594,7 +599,8 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #else info->protect[i] = p; #endif /* CFG_FLASH_PROTECTION */ - } + } + #if defined(CFG_FLASH_PROTECTION) if (!rcode) puts (" done\n"); diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index c543bb5..63dd4da 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -536,10 +536,17 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]) int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { int j; +#if defined(CONFIG_MARVELL) + int i = 0; +#endif #if defined(CFG_I2C_NOPROBES) int k, skip; #endif +#if defined(CONFIG_MARVELL) && defined(MV78XX0) + for(i = 0; i < 2; i++) { + printf ("\nValid chip channel %d\n",i); +#endif puts ("Valid chip addresses:"); for(j = 0; j < 128; j++) { #if defined(CFG_I2C_NOPROBES) @@ -553,10 +560,17 @@ int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (skip) continue; #endif +#if defined(CONFIG_MARVELL) + if(i2c_probe(i,j) == 0) { +#else if(i2c_probe(j) == 0) { +#endif printf(" %02X", j); } } +#if defined(CONFIG_MARVELL) && defined(MV78XX0) + } +#endif putc ('\n'); #if defined(CFG_I2C_NOPROBES) diff --git a/common/cmd_ide.c b/common/cmd_ide.c index b67d35a..e340d34 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -31,6 +31,8 @@ #include #include #include +#ifndef CONFIG_MARVELL /* Marvell has a board specific IDE support */ + #if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA) # include #endif @@ -2066,3 +2068,5 @@ U_BOOT_CMD( ); #endif /* CONFIG_COMMANDS & CFG_CMD_IDE */ + +#endif diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 34920b1..77c102e 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -15,7 +15,7 @@ * Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4 * kernel tree. * - * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $ + * $Id: cmd_jffs2.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * Copyright 2002 SYSGO Real-Time Solutions GmbH * * See file CREDITS for list of people who contributed to this @@ -91,7 +91,6 @@ #include #include #include -#include #include #include @@ -99,11 +98,19 @@ #include +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#ifdef CFG_NAND_LEGACY +#include +#else /* !CFG_NAND_LEGACY */ +#include +#include +#endif /* !CFG_NAND_LEGACY */ +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ /* enable/disable debugging messages */ -#define DEBUG -#undef DEBUG +#define DEBUG_JFFS +#undef DEBUG_JFFS -#ifdef DEBUG +#ifdef DEBUG_JFFS # define DEBUGF(fmt, args...) printf(fmt ,##args) #else # define DEBUGF(fmt, args...) @@ -123,7 +130,7 @@ /* this flag needs to be set in part_info struct mask_flags * field for read-only partitions */ -#define MTD_WRITEABLE 1 +#define MTD_WRITEABLE_CMD 1 #ifdef CONFIG_JFFS2_CMDLINE /* default values for mtdids and mtdparts variables */ @@ -365,10 +372,9 @@ static int part_validate_nand(struct mtdids *id, struct part_info *part) { #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) /* info for NAND chips */ - extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; - struct nand_chip *nand; + nand_info_t *nand; - nand = &nand_dev_desc[id->num]; + nand = &nand_info[id->num]; if ((unsigned long)(part->offset) % nand->erasesize) { printf("%s%d: partition (%s) start offset alignment incorrect\n", @@ -464,7 +470,9 @@ static int part_del(struct mtd_device *dev, struct part_info *part) } } +#ifdef CFG_NAND_LEGACY jffs2_free_cache(part); +#endif list_del(&part->link); free(part); dev->num_parts--; @@ -491,7 +499,9 @@ static void part_delall(struct list_head *head) list_for_each_safe(entry, n, head) { part_tmp = list_entry(entry, struct part_info, link); +#ifdef CFG_NAND_LEGACY jffs2_free_cache(part_tmp); +#endif list_del(entry); free(part_tmp); } @@ -646,7 +656,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i /* test for options */ mask_flags = 0; if (strncmp(p, "ro", 2) == 0) { - mask_flags |= MTD_WRITEABLE; + mask_flags |= MTD_WRITEABLE_CMD; p += 2; } @@ -713,6 +723,7 @@ static int device_validate(u8 type, u8 num, u32 *size) if (num < CFG_MAX_FLASH_BANKS) { extern flash_info_t flash_info[]; *size = flash_info[num].size; + return 0; } @@ -724,8 +735,12 @@ static int device_validate(u8 type, u8 num, u32 *size) } else if (type == MTD_DEV_TYPE_NAND) { #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) if (num < CFG_MAX_NAND_DEVICE) { +#ifndef CFG_NAND_LEGACY + *size = nand_info[num].size; +#else extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; *size = nand_dev_desc[num].totlen; +#endif return 0; } @@ -1169,7 +1184,7 @@ static int generate_mtdparts(char *buf, u32 buflen) } /* ro mask flag */ - if (part->mask_flags && MTD_WRITEABLE) { + if (part->mask_flags && MTD_WRITEABLE_CMD) { len = 2; if (len > maxlen) goto cleanup; @@ -1253,7 +1268,7 @@ static void list_partitions(void) part_num = 0; list_for_each(pentry, &dev->parts) { part = list_entry(pentry, struct part_info, link); - printf(" %d: %-22s\t0x%08x\t0x%08x\t%d\n", + printf("%2d: %-20s0x%08x\t0x%08x\t%d\n", part_num, part->name, part->size, part->offset, part->mask_flags); @@ -1285,7 +1300,7 @@ static void list_partitions(void) * Given partition identifier in form of , find * corresponding device and verify partition number. * - * @param id string describing device and partition + * @param id string describing device and partition or partition name * @param dev pointer to the requested device (output) * @param part_num verified partition number (output) * @param part pointer to requested partition (output) @@ -1294,11 +1309,23 @@ static void list_partitions(void) int find_dev_and_part(const char *id, struct mtd_device **dev, u8 *part_num, struct part_info **part) { + struct list_head *dentry, *pentry; u8 type, dnum, pnum; const char *p; DEBUGF("--- find_dev_and_part ---\nid = %s\n", id); + list_for_each(dentry, &devices) { + *part_num = 0; + *dev = list_entry(dentry, struct mtd_device, link); + list_for_each(pentry, &(*dev)->parts) { + *part = list_entry(pentry, struct part_info, link); + if (strcmp((*part)->name, id) == 0) + return 0; + (*part_num)++; + } + } + p = id; *dev = NULL; *part = NULL; diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 0f4f9b7..627805e 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -28,6 +28,7 @@ */ #include +#include #include #if (CONFIG_COMMANDS & CFG_CMD_MMC) #include @@ -429,8 +430,26 @@ int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int rc; puts ("Copy to Flash... "); +#if defined(CONFIG_MARVELL) + /* If source addr is flash copy data to memory first */ + if (addr2info(addr) != NULL) + { char* tmp_buff; + int i; + if (NULL == (tmp_buff = malloc(count*size))) + { + puts (" Copy fail, NULL pointer buffer\n"); + return (1); + } + for( i = 0 ; i < (count*size); i++) + *(tmp_buff + i) = *((char *)addr + i); + + rc = flash_write (tmp_buff, dest, count*size); + free(tmp_buff); + } + else +#endif /* defined(CONFIG_MARVELL) */ + rc = flash_write ((char *)addr, dest, count*size); - rc = flash_write ((char *)addr, dest, count*size); if (rc != 0) { flash_perror (rc); return (1); diff --git a/common/cmd_nand.c b/common/cmd_nand.c index b0c01d1..833e0dc 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -9,6 +9,612 @@ */ #include + + +#ifndef CFG_NAND_LEGACY +/* + * + * New NAND support + * + */ +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include +#include +#include +#include + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include +# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) +#else +# define SHOW_BOOT_PROGRESS(arg) +#endif + +#include +#include + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + +/* parition handling routines */ +int mtdparts_init(void); +int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num); +int find_dev_and_part(const char *id, struct mtd_device **dev, + u8 *part_num, struct part_info **part); +#endif + +extern nand_info_t nand_info[]; /* info for NAND chips */ + +static int nand_dump_oob(nand_info_t *nand, ulong off) +{ + return 0; +} + +static int nand_dump(nand_info_t *nand, ulong off) +{ + int i; + u_char *buf, *p; + + buf = malloc(nand->oobblock + nand->oobsize); + if (!buf) { + puts("No memory for page buffer\n"); + return 1; + } + off &= ~(nand->oobblock - 1); + i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize); + if (i < 0) { + printf("Error (%d) reading page %08x\n", i, off); + free(buf); + return 1; + } + printf("Page %08x dump:\n", off); + i = nand->oobblock >> 4; p = buf; + while (i--) { + printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + p += 16; + } + puts("OOB:\n"); + i = nand->oobsize >> 3; + while (i--) { + printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + p += 8; + } + free(buf); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static inline int str2long(char *p, ulong *num) +{ + char *endptr; + + *num = simple_strtoul(p, &endptr, 16); + return (*p != '\0' && *endptr == '\0') ? 1 : 0; +} + +static int +arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, ulong *size) +{ + int idx = nand_curr_device; +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + struct mtd_device *dev; + struct part_info *part; + u8 pnum; + + if (argc >= 1 && !(str2long(argv[0], off))) { + if ((mtdparts_init() == 0) && + (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) { + if (dev->id->type != MTD_DEV_TYPE_NAND) { + puts("not a NAND device\n"); + return -1; + } + *off = part->offset; + if (argc >= 2) { + if (!(str2long(argv[1], size))) { + printf("'%s' is not a number\n", argv[1]); + return -1; + } + if (*size > part->size) + *size = part->size; + } else { + *size = part->size; + } + idx = dev->id->num; + *nand = nand_info[idx]; + goto out; + } + } +#endif + + if (argc >= 1) { + if (!(str2long(argv[0], off))) { + printf("'%s' is not a number\n", argv[0]); + return -1; + } + } else { + *off = 0; + } + + if (argc >= 2) { + if (!(str2long(argv[1], size))) { + printf("'%s' is not a number\n", argv[1]); + return -1; + } + } else { + *size = nand->size - *off; + } + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) +out: +#endif + printf("device %d ", idx); + if (*size == nand->size) + puts("whole chip\n"); + else + printf("offset 0x%x, size 0x%x\n", *off, *size); + return 0; +} + +int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + int i, dev, ret; + ulong addr, off, size; + char *cmd, *s; + nand_info_t *nand; + int quiet = 0; + const char *quiet_str = getenv("quiet"); + + /* at least two arguments please */ + if (argc < 2) + goto usage; + + if (quiet_str) + quiet = simple_strtoul(quiet_str, NULL, 0) != 0; + + cmd = argv[1]; + + if (strcmp(cmd, "info") == 0) { + + putc('\n'); + for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { + if (nand_info[i].name) + printf("Device %d: %s, sector size %lu KB\n", + i, nand_info[i].name, + nand_info[i].erasesize >> 10); + } + return 0; + } + + if (strcmp(cmd, "device") == 0) { + + if (argc < 3) { + if ((nand_curr_device < 0) || + (nand_curr_device >= CFG_MAX_NAND_DEVICE)) + puts("\nno devices available\n"); + else + printf("\nDevice %d: %s\n", nand_curr_device, + nand_info[nand_curr_device].name); + return 0; + } + dev = (int)simple_strtoul(argv[2], NULL, 10); + if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) { + puts("No such device\n"); + return 1; + } + printf("Device %d: %s", dev, nand_info[dev].name); + puts("... is now current device\n"); + nand_curr_device = dev; + +#ifdef CFG_NAND_SELECT_DEVICE + /* + * Select the chip in the board/cpu specific driver + */ + board_nand_select_device(nand_info[dev].priv, dev); +#endif + + return 0; + } + + if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 && + strncmp(cmd, "dump", 4) != 0 && + strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && + strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && + strcmp(cmd, "biterr") != 0 && + strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) + goto usage; + + /* the following commands operate on the current device */ + if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE || + !nand_info[nand_curr_device].name) { + puts("\nno devices available\n"); + return 1; + } + nand = &nand_info[nand_curr_device]; + + if (strcmp(cmd, "bad") == 0) { + printf("\nDevice %d bad blocks:\n", nand_curr_device); + for (off = 0; off < nand->size; off += nand->erasesize) + if (nand_block_isbad(nand, off)) + printf(" %08x\n", off); + return 0; + } + + /* + * Syntax is: + * 0 1 2 3 4 + * nand erase [clean] [off size] + */ + if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) { + nand_erase_options_t opts; + /* "clean" at index 2 means request to write cleanmarker */ + int clean = argc > 2 && !strcmp("clean", argv[2]); + int o = clean ? 3 : 2; + int scrub = !strcmp(cmd, "scrub"); + + printf("\nNAND %s: ", scrub ? "scrub" : "erase"); + /* skip first two or three arguments, look for offset and size */ + if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0) + return 1; + + memset(&opts, 0, sizeof(opts)); + opts.offset = off; + opts.length = size; + opts.jffs2 = clean; + opts.quiet = quiet; + + if (scrub) { + puts("Warning: " + "scrub option will erase all factory set " + "bad blocks!\n" + " " + "There is no reliable way to recover them.\n" + " " + "Use this command only for testing purposes " + "if you\n" + " " + "are sure of what you are doing!\n" + "\nReally scrub this NAND flash? \n"); + + if (getc() == 'y' && getc() == '\r') { + opts.scrub = 1; + } else { + puts("scrub aborted\n"); + return -1; + } + } + ret = nand_erase_opts(nand, &opts); + printf("%s\n", ret ? "ERROR" : "OK"); + + return ret == 0 ? 0 : 1; + } + + if (strncmp(cmd, "dump", 4) == 0) { + if (argc < 3) + goto usage; + + s = strchr(cmd, '.'); + off = (int)simple_strtoul(argv[2], NULL, 16); + + if (s != NULL && strcmp(s, ".oob") == 0) + ret = nand_dump_oob(nand, off); + else + ret = nand_dump(nand, off); + + return ret == 0 ? 1 : 0; + + } + + /* read write */ + if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { + int read; + + if (argc < 4) + goto usage; + + addr = (ulong)simple_strtoul(argv[2], NULL, 16); + + read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ + printf("\nNAND %s: ", read ? "read" : "write"); + if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) + return 1; + + s = strchr(cmd, '.'); + if (s != NULL && + (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) { + if (read) { + /* read */ + nand_read_options_t opts; + memset(&opts, 0, sizeof(opts)); + opts.buffer = (u_char*) addr; + opts.length = size; + opts.offset = off; + opts.quiet = quiet; + ret = nand_read_opts(nand, &opts); + } else { + /* write */ + nand_write_options_t opts; + memset(&opts, 0, sizeof(opts)); + opts.buffer = (u_char*) addr; + opts.length = size; + opts.offset = off; + /* opts.forcejffs2 = 1; */ + opts.pad = 1; + opts.blockalign = 1; + opts.quiet = quiet; + ret = nand_write_opts(nand, &opts); + } + } else { + if (read) + ret = nand_read(nand, off, &size, (u_char *)addr); + else + ret = nand_write(nand, off, &size, (u_char *)addr); + } + + printf(" %d bytes %s: %s\n", size, + read ? "read" : "written", ret ? "ERROR" : "OK"); + + return ret == 0 ? 0 : 1; + } + + if (strcmp(cmd, "markbad") == 0) { + addr = (ulong)simple_strtoul(argv[2], NULL, 16); + + int ret = nand->block_markbad(nand, addr); + if (ret == 0) { + printf("block 0x%08lx successfully marked as bad\n", + (ulong) addr); + return 0; + } else { + printf("block 0x%08lx NOT marked as bad! ERROR %d\n", + (ulong) addr, ret); + } + return 1; + } + if (strcmp(cmd, "biterr") == 0) { + /* todo */ + return 1; + } + + if (strcmp(cmd, "lock") == 0) { + int tight = 0; + int status = 0; + if (argc == 3) { + if (!strcmp("tight", argv[2])) + tight = 1; + if (!strcmp("status", argv[2])) + status = 1; + } + + if (status) { + ulong block_start = 0; + ulong off; + int last_status = -1; + + struct nand_chip *nand_chip = nand->priv; + /* check the WP bit */ + nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1); + printf("device is %swrite protected\n", + (nand_chip->read_byte(nand) & 0x80 ? + "NOT " : "" ) ); + + for (off = 0; off < nand->size; off += nand->oobblock) { + int s = nand_get_lock_status(nand, off); + + /* print message only if status has changed + * or at end of chip + */ + if (off == nand->size - nand->oobblock + || (s != last_status && off != 0)) { + + printf("%08x - %08x: %8d pages %s%s%s\n", + block_start, + off-1, + (off-block_start)/nand->oobblock, + ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), + ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), + ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); + } + + last_status = s; + } + } else { + if (!nand_lock(nand, tight)) { + puts("NAND flash successfully locked\n"); + } else { + puts("Error locking NAND flash\n"); + return 1; + } + } + return 0; + } + + if (strcmp(cmd, "unlock") == 0) { + if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0) + return 1; + + if (!nand_unlock(nand, off, size)) { + puts("NAND flash successfully unlocked\n"); + } else { + puts("Error unlocking NAND flash, " + "write and erase will probably fail\n"); + return 1; + } + return 0; + } + +usage: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD(nand, 5, 1, do_nand, + "nand - NAND sub-system\n", + "info - show available NAND devices\n" + "nand device [dev] - show or set current device\n" + "nand read[.jffs2/.e] - addr off|partition size (Using the .e option skips bad blocks)\n" + "nand write[.jffs2/.e] - addr off|partiton size (Using the .e option skips bad blocks)\n" + " at offset `off' to/from memory address `addr'\n" + "nand erase [clean] [off size] - erase `size' bytes from\n" + " offset `off' (entire device if not specified)\n" + "nand bad - show bad blocks\n" + "nand dump[.oob] off - dump page\n" + "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n" + "nand markbad off - mark bad block at offset (UNSAFE)\n" + "nand biterr off - make a bit error at offset (UNSAFE)\n" + "nand lock [tight] [status] - bring nand to lock state or display locked pages\n" + "nand unlock [offset] [size] - unlock section\n"); + +static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, + ulong offset, ulong addr, char *cmd) +{ + int r; + char *ep; + ulong cnt; + image_header_t *hdr; + + printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset); + + cnt = nand->oobblock; + r = nand_read(nand, offset, &cnt, (u_char *) addr); + if (r) { + puts("** Read error\n"); + SHOW_BOOT_PROGRESS(-1); + return 1; + } + + hdr = (image_header_t *) addr; + + if (ntohl(hdr->ih_magic) != IH_MAGIC) { + printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); + SHOW_BOOT_PROGRESS(-1); + return 1; + } + + print_image_hdr(hdr); + + cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t)); + + r = nand_read(nand, offset, &cnt, (u_char *) addr); + if (r) { + puts("** Read error\n"); + SHOW_BOOT_PROGRESS(-1); + return 1; + } + + /* Loading ok, update default load address */ + + load_addr = addr; + + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) { + char *local_args[2]; + extern int do_bootm(cmd_tbl_t *, int, int, char *[]); + + local_args[0] = cmd; + local_args[1] = NULL; + + printf("Automatic boot of image at addr 0x%08lx ...\n", addr); + + do_bootm(cmdtp, 0, 1, local_args); + return 1; + } + return 0; +} + +int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + char *boot_device = NULL; + int idx; + ulong addr, offset = 0; +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) + struct mtd_device *dev; + struct part_info *part; + u8 pnum; + + if (argc >= 2) { + char *p = (argc == 2) ? argv[1] : argv[2]; + if (!(str2long(p, &addr)) && (mtdparts_init() == 0) && + (find_dev_and_part(p, &dev, &pnum, &part) == 0)) { + if (dev->id->type != MTD_DEV_TYPE_NAND) { + puts("Not a NAND device\n"); + return 1; + } + if (argc > 3) + goto usage; + if (argc == 3) + addr = simple_strtoul(argv[2], NULL, 16); + else + addr = CFG_LOAD_ADDR; + return nand_load_image(cmdtp, &nand_info[dev->id->num], + part->offset, addr, argv[0]); + } + } +#endif + + switch (argc) { + case 1: + addr = CFG_LOAD_ADDR; + boot_device = getenv("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv("bootdevice"); + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + break; + case 4: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + offset = simple_strtoul(argv[3], NULL, 16); + break; + default: +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE) +usage: +#endif + printf("Usage:\n%s\n", cmdtp->usage); + SHOW_BOOT_PROGRESS(-1); + return 1; + } + + if (!boot_device) { + puts("\n** No boot device **\n"); + SHOW_BOOT_PROGRESS(-1); + return 1; + } + + idx = simple_strtoul(boot_device, NULL, 16); + + if (idx < 0 || idx >= CFG_MAX_NAND_DEVICE || !nand_info[idx].name) { + printf("\n** Device %d not available\n", idx); + SHOW_BOOT_PROGRESS(-1); + return 1; + } + + return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]); +} + +U_BOOT_CMD(nboot, 4, 1, do_nandboot, + "nboot - boot from NAND device\n", + "[partition] | [[[loadAddr] dev] offset]\n"); + +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ + +#else /* CFG_NAND_LEGACY */ +/* + * + * Legacy NAND support - to be phased out + * + */ #include #include #include @@ -22,10 +628,11 @@ #endif #if (CONFIG_COMMANDS & CFG_CMD_NAND) - -#include +#include +#if 0 #include #include +#endif #ifdef CONFIG_OMAP1510 void archflashwp(void *archdata, int wp); @@ -33,15 +640,6 @@ void archflashwp(void *archdata, int wp); #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) -/* - * Definition of the out of band configuration structure - */ -struct nand_oob_config { - int ecc_pos[6]; /* position of ECC bytes inside oob */ - int badblock_pos; /* position of bad block flag inside oob -1 = inactive */ - int eccvalid_pos; /* position of ECC valid flag inside oob -1 = inactive */ -} oob_config = { {0}, 0, 0}; - #undef NAND_DEBUG #undef PSYCHO_DEBUG @@ -63,218 +661,210 @@ struct nand_oob_config { #define CONFIG_MTD_NAND_ECC /* enable ECC */ #define CONFIG_MTD_NAND_ECC_JFFS2 -/* bits for nand_rw() `cmd'; or together as needed */ +/* bits for nand_legacy_rw() `cmd'; or together as needed */ #define NANDRW_READ 0x01 #define NANDRW_WRITE 0x00 #define NANDRW_JFFS2 0x02 #define NANDRW_JFFS2_SKIP 0x04 /* - * Function Prototypes + * Imports from nand_legacy.c */ -static void nand_print(struct nand_chip *nand); -int nand_rw (struct nand_chip* nand, int cmd, - size_t start, size_t len, - size_t * retlen, u_char * buf); -int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean); -static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len, - size_t * retlen, u_char *buf, u_char *ecc_code); -static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len, - size_t * retlen, const u_char * buf, u_char * ecc_code); -static void nand_print_bad(struct nand_chip *nand); -static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len, - size_t * retlen, u_char * buf); -static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, - size_t * retlen, const u_char * buf); -static int NanD_WaitReady(struct nand_chip *nand, int ale_wait); -#ifdef CONFIG_MTD_NAND_ECC -static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); -static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); -#endif +extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; +extern int curr_device; +extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, + size_t len, int clean); +extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start, + size_t len, size_t *retlen, u_char *buf); +extern void nand_print(struct nand_chip *nand); +extern void nand_print_bad(struct nand_chip *nand); +extern int nand_read_oob(struct nand_chip *nand, size_t ofs, + size_t len, size_t *retlen, u_char *buf); +extern int nand_write_oob(struct nand_chip *nand, size_t ofs, + size_t len, size_t *retlen, const u_char *buf); -struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}}; -/* Current NAND Device */ -static int curr_device = -1; - -/* ------------------------------------------------------------------------- */ - -int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - int rcode = 0; + int rcode = 0; - switch (argc) { - case 0: - case 1: - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - case 2: - if (strcmp(argv[1],"info") == 0) { - int i; + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 2: + if (strcmp (argv[1], "info") == 0) { + int i; - putc ('\n'); + putc ('\n'); - for (i=0; i= CFG_MAX_NAND_DEVICE)) { - puts ("\nno devices available\n"); - return 1; - } - printf ("\nDevice %d: ", curr_device); - nand_print(&nand_dev_desc[curr_device]); - return 0; - - } else if (strcmp(argv[1],"bad") == 0) { - if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) { - puts ("\nno devices available\n"); - return 1; - } - printf ("\nDevice %d bad blocks:\n", curr_device); - nand_print_bad(&nand_dev_desc[curr_device]); - return 0; - - } - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - case 3: - if (strcmp(argv[1],"device") == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - - printf ("\nDevice %d: ", dev); - if (dev >= CFG_MAX_NAND_DEVICE) { - puts ("unknown device\n"); - return 1; - } - nand_print(&nand_dev_desc[dev]); - /*nand_print (dev);*/ - - if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) { - return 1; - } - - curr_device = dev; - - puts ("... is now current device\n"); - - return 0; - } - else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) { - struct nand_chip* nand = &nand_dev_desc[curr_device]; - ulong off = 0; - ulong size = nand->totlen; - int ret; - - printf ("\nNAND erase: device %d offset %ld, size %ld ... ", - curr_device, off, size); - - ret = nand_erase (nand, off, size, 1); - - printf("%s\n", ret ? "ERROR" : "OK"); - - return ret; - } - - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - default: - /* at least 4 args */ - - if (strncmp(argv[1], "read", 4) == 0 || - strncmp(argv[1], "write", 5) == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong off = simple_strtoul(argv[3], NULL, 16); - ulong size = simple_strtoul(argv[4], NULL, 16); - int cmd = (strncmp(argv[1], "read", 4) == 0) ? - NANDRW_READ : NANDRW_WRITE; - int ret, total; - char* cmdtail = strchr(argv[1], '.'); - - if (cmdtail && !strncmp(cmdtail, ".oob", 2)) { - /* read out-of-band data */ - if (cmd & NANDRW_READ) { - ret = nand_read_oob(nand_dev_desc + curr_device, - off, size, (size_t *)&total, - (u_char*)addr); + for (i = 0; i < CFG_MAX_NAND_DEVICE; ++i) { + if (nand_dev_desc[i].ChipID == + NAND_ChipID_UNKNOWN) + continue; /* list only known devices */ + printf ("Device %d: ", i); + nand_print (&nand_dev_desc[i]); } - else { - ret = nand_write_oob(nand_dev_desc + curr_device, - off, size, (size_t *)&total, - (u_char*)addr); + return 0; + + } else if (strcmp (argv[1], "device") == 0) { + if ((curr_device < 0) + || (curr_device >= CFG_MAX_NAND_DEVICE)) { + puts ("\nno devices available\n"); + return 1; } + printf ("\nDevice %d: ", curr_device); + nand_print (&nand_dev_desc[curr_device]); + return 0; + + } else if (strcmp (argv[1], "bad") == 0) { + if ((curr_device < 0) + || (curr_device >= CFG_MAX_NAND_DEVICE)) { + puts ("\nno devices available\n"); + return 1; + } + printf ("\nDevice %d bad blocks:\n", curr_device); + nand_print_bad (&nand_dev_desc[curr_device]); + return 0; + + } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 3: + if (strcmp (argv[1], "device") == 0) { + int dev = (int) simple_strtoul (argv[2], NULL, 10); + + printf ("\nDevice %d: ", dev); + if (dev >= CFG_MAX_NAND_DEVICE) { + puts ("unknown device\n"); + return 1; + } + nand_print (&nand_dev_desc[dev]); + /*nand_print (dev); */ + + if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) { + return 1; + } + + curr_device = dev; + + puts ("... is now current device\n"); + + return 0; + } else if (strcmp (argv[1], "erase") == 0 + && strcmp (argv[2], "clean") == 0) { + struct nand_chip *nand = &nand_dev_desc[curr_device]; + ulong off = 0; + ulong size = nand->totlen; + int ret; + + printf ("\nNAND erase: device %d offset %ld, size %ld ... ", curr_device, off, size); + + ret = nand_legacy_erase (nand, off, size, 1); + + printf ("%s\n", ret ? "ERROR" : "OK"); + return ret; } - else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2)) - cmd |= NANDRW_JFFS2; /* skip bad blocks */ - else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) { - cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ - if (cmd & NANDRW_READ) - cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ - } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + default: + /* at least 4 args */ + + if (strncmp (argv[1], "read", 4) == 0 || + strncmp (argv[1], "write", 5) == 0) { + ulong addr = simple_strtoul (argv[2], NULL, 16); + ulong off = simple_strtoul (argv[3], NULL, 16); + ulong size = simple_strtoul (argv[4], NULL, 16); + int cmd = (strncmp (argv[1], "read", 4) == 0) ? + NANDRW_READ : NANDRW_WRITE; + int ret, total; + char *cmdtail = strchr (argv[1], '.'); + + if (cmdtail && !strncmp (cmdtail, ".oob", 2)) { + /* read out-of-band data */ + if (cmd & NANDRW_READ) { + ret = nand_read_oob (nand_dev_desc + curr_device, + off, size, (size_t *) & total, + (u_char *) addr); + } else { + ret = nand_write_oob (nand_dev_desc + curr_device, + off, size, (size_t *) & total, + (u_char *) addr); + } + return ret; + } else if (cmdtail && !strncmp (cmdtail, ".jffs2", 2)) + cmd |= NANDRW_JFFS2; /* skip bad blocks */ + else if (cmdtail && !strncmp (cmdtail, ".jffs2s", 2)) { + cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ + if (cmd & NANDRW_READ) + cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ + } #ifdef SXNI855T - /* need ".e" same as ".j" for compatibility with older units */ - else if (cmdtail && !strcmp(cmdtail, ".e")) - cmd |= NANDRW_JFFS2; /* skip bad blocks */ + /* need ".e" same as ".j" for compatibility with older units */ + else if (cmdtail && !strcmp (cmdtail, ".e")) + cmd |= NANDRW_JFFS2; /* skip bad blocks */ #endif #ifdef CFG_NAND_SKIP_BAD_DOT_I - /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */ - /* ".i" for image -> read skips bad block (no 0xff) */ - else if (cmdtail && !strcmp(cmdtail, ".i")) { - cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ - if (cmd & NANDRW_READ) - cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ - } + /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */ + /* ".i" for image -> read skips bad block (no 0xff) */ + else if (cmdtail && !strcmp (cmdtail, ".i")) { + cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */ + if (cmd & NANDRW_READ) + cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */ + } #endif /* CFG_NAND_SKIP_BAD_DOT_I */ - else if (cmdtail) { + else if (cmdtail) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + printf ("\nNAND %s: device %d offset %ld, size %ld ...\n", + (cmd & NANDRW_READ) ? "read" : "write", + curr_device, off, size); + + ret = nand_legacy_rw (nand_dev_desc + curr_device, + cmd, off, size, + (size_t *) & total, + (u_char *) addr); + + printf (" %d bytes %s: %s\n", total, + (cmd & NANDRW_READ) ? "read" : "written", + ret ? "ERROR" : "OK"); + + return ret; + } else if (strcmp (argv[1], "erase") == 0 && + (argc == 4 || strcmp ("clean", argv[2]) == 0)) { + int clean = argc == 5; + ulong off = + simple_strtoul (argv[2 + clean], NULL, 16); + ulong size = + simple_strtoul (argv[3 + clean], NULL, 16); + int ret; + + printf ("\nNAND erase: device %d offset %ld, size %ld ...\n", + curr_device, off, size); + + ret = nand_legacy_erase (nand_dev_desc + curr_device, + off, size, clean); + + printf ("%s\n", ret ? "ERROR" : "OK"); + + return ret; + } else { printf ("Usage:\n%s\n", cmdtp->usage); - return 1; + rcode = 1; } - printf ("\nNAND %s: device %d offset %ld, size %ld ... ", - (cmd & NANDRW_READ) ? "read" : "write", - curr_device, off, size); - - ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size, - (size_t *)&total, (u_char*)addr); - - printf (" %d bytes %s: %s\n", total, - (cmd & NANDRW_READ) ? "read" : "written", - ret ? "ERROR" : "OK"); - - return ret; - } else if (strcmp(argv[1],"erase") == 0 && - (argc == 4 || strcmp("clean", argv[2]) == 0)) { - int clean = argc == 5; - ulong off = simple_strtoul(argv[2 + clean], NULL, 16); - ulong size = simple_strtoul(argv[3 + clean], NULL, 16); - int ret; - - printf ("\nNAND erase: device %d offset %ld, size %ld ... ", - curr_device, off, size); - - ret = nand_erase (nand_dev_desc + curr_device, off, size, clean); - - printf("%s\n", ret ? "ERROR" : "OK"); - - return ret; - } else { - printf ("Usage:\n%s\n", cmdtp->usage); - rcode = 1; + return rcode; } - - return rcode; - } } U_BOOT_CMD( nand, 5, 1, do_nand, - "nand - NAND sub-system\n", + "nand - legacy NAND sub-system\n", "info - show available NAND devices\n" "nand device [dev] - show or set current device\n" "nand read[.jffs2[s]] addr off size\n" @@ -340,8 +930,8 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR, offset); - if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset, - SECTORSIZE, NULL, (u_char *)addr)) { + if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset, + SECTORSIZE, NULL, (u_char *)addr)) { printf ("** Read error on %d\n", dev); SHOW_BOOT_PROGRESS (-1); return 1; @@ -356,13 +946,14 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); cnt -= SECTORSIZE; } else { - printf ("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); + printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic)); SHOW_BOOT_PROGRESS (-1); return 1; } - if (nand_rw (nand_dev_desc + dev, NANDRW_READ, offset + SECTORSIZE, cnt, - NULL, (u_char *)(addr+SECTORSIZE))) { + if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, + offset + SECTORSIZE, cnt, NULL, + (u_char *)(addr+SECTORSIZE))) { printf ("** Read error on %d\n", dev); SHOW_BOOT_PROGRESS (-1); return 1; @@ -394,1505 +985,6 @@ U_BOOT_CMD( "loadAddr dev\n" ); -/* returns 0 if block containing pos is OK: - * valid erase block and - * not marked bad, or no bad mark position is specified - * returns 1 if marked bad or otherwise invalid - */ -int check_block (struct nand_chip *nand, unsigned long pos) -{ - size_t retlen; - uint8_t oob_data; - uint16_t oob_data16[6]; - int page0 = pos & (-nand->erasesize); - int page1 = page0 + nand->oobblock; - int badpos = oob_config.badblock_pos; - - if (pos >= nand->totlen) - return 1; - - if (badpos < 0) - return 0; /* no way to check, assume OK */ - - if (nand->bus16) { - if (nand_read_oob(nand, (page0 + 0), 12, &retlen, (uint8_t *)oob_data16) - || (oob_data16[2] & 0xff00) != 0xff00) - return 1; - if (nand_read_oob(nand, (page1 + 0), 12, &retlen, (uint8_t *)oob_data16) - || (oob_data16[2] & 0xff00) != 0xff00) - return 1; - } else { - /* Note - bad block marker can be on first or second page */ - if (nand_read_oob(nand, page0 + badpos, 1, &retlen, (unsigned char *)&oob_data) - || oob_data != 0xff - || nand_read_oob (nand, page1 + badpos, 1, &retlen, (unsigned char *)&oob_data) - || oob_data != 0xff) - return 1; - } - - return 0; -} - -/* print bad blocks in NAND flash */ -static void nand_print_bad(struct nand_chip* nand) -{ - unsigned long pos; - - for (pos = 0; pos < nand->totlen; pos += nand->erasesize) { - if (check_block(nand, pos)) - printf(" 0x%8.8lx\n", pos); - } - puts("\n"); -} - -/* cmd: 0: NANDRW_WRITE write, fail on bad block - * 1: NANDRW_READ read, fail on bad block - * 2: NANDRW_WRITE | NANDRW_JFFS2 write, skip bad blocks - * 3: NANDRW_READ | NANDRW_JFFS2 read, data all 0xff for bad blocks - * 7: NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP read, skip bad blocks - */ -int nand_rw (struct nand_chip* nand, int cmd, - size_t start, size_t len, - size_t * retlen, u_char * buf) -{ - int ret = 0, n, total = 0; - char eccbuf[6]; - /* eblk (once set) is the start of the erase block containing the - * data being processed. - */ - unsigned long eblk = ~0; /* force mismatch on first pass */ - unsigned long erasesize = nand->erasesize; - - while (len) { - if ((start & (-erasesize)) != eblk) { - /* have crossed into new erase block, deal with - * it if it is sure marked bad. - */ - eblk = start & (-erasesize); /* start of block */ - if (check_block(nand, eblk)) { - if (cmd == (NANDRW_READ | NANDRW_JFFS2)) { - while (len > 0 && - start - eblk < erasesize) { - *(buf++) = 0xff; - ++start; - ++total; - --len; - } - continue; - } else if (cmd == (NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP)) { - start += erasesize; - continue; - } else if (cmd == (NANDRW_WRITE | NANDRW_JFFS2)) { - /* skip bad block */ - start += erasesize; - continue; - } else { - ret = 1; - break; - } - } - } - /* The ECC will not be calculated correctly if - less than 512 is written or read */ - /* Is request at least 512 bytes AND it starts on a proper boundry */ - if((start != ROUND_DOWN(start, 0x200)) || (len < 0x200)) - printf("Warning block writes should be at least 512 bytes and start on a 512 byte boundry\n"); - - if (cmd & NANDRW_READ) { - ret = nand_read_ecc(nand, start, - min(len, eblk + erasesize - start), - (size_t *)&n, (u_char*)buf, (u_char *)eccbuf); - } else { - ret = nand_write_ecc(nand, start, - min(len, eblk + erasesize - start), - (size_t *)&n, (u_char*)buf, (u_char *)eccbuf); - } - - if (ret) - break; - - start += n; - buf += n; - total += n; - len -= n; - } - if (retlen) - *retlen = total; - - return ret; -} - -static void nand_print(struct nand_chip *nand) -{ - if (nand->numchips > 1) { - printf("%s at 0x%lx,\n" - "\t %d chips %s, size %d MB, \n" - "\t total size %ld MB, sector size %ld kB\n", - nand->name, nand->IO_ADDR, nand->numchips, - nand->chips_name, 1 << (nand->chipshift - 20), - nand->totlen >> 20, nand->erasesize >> 10); - } - else { - printf("%s at 0x%lx (", nand->chips_name, nand->IO_ADDR); - print_size(nand->totlen, ", "); - print_size(nand->erasesize, " sector)\n"); - } -} - -/* ------------------------------------------------------------------------- */ - -static int NanD_WaitReady(struct nand_chip *nand, int ale_wait) -{ - /* This is inline, to optimise the common case, where it's ready instantly */ - int ret = 0; - -#ifdef NAND_NO_RB /* in config file, shorter delays currently wrap accesses */ - if(ale_wait) - NAND_WAIT_READY(nand); /* do the worst case 25us wait */ - else - udelay(10); -#else /* has functional r/b signal */ - NAND_WAIT_READY(nand); -#endif - return ret; -} - -/* NanD_Command: Send a flash command to the flash chip */ - -static inline int NanD_Command(struct nand_chip *nand, unsigned char command) -{ - unsigned long nandptr = nand->IO_ADDR; - - /* Assert the CLE (Command Latch Enable) line to the flash chip */ - NAND_CTL_SETCLE(nandptr); - - /* Send the command */ - WRITE_NAND_COMMAND(command, nandptr); - - /* Lower the CLE line */ - NAND_CTL_CLRCLE(nandptr); - -#ifdef NAND_NO_RB - if(command == NAND_CMD_RESET){ - u_char ret_val; - NanD_Command(nand, NAND_CMD_STATUS); - do { - ret_val = READ_NAND(nandptr);/* wait till ready */ - } while((ret_val & 0x40) != 0x40); - } -#endif - return NanD_WaitReady(nand, 0); -} - -/* NanD_Address: Set the current address for the flash chip */ - -static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs) -{ - unsigned long nandptr; - int i; - - nandptr = nand->IO_ADDR; - - /* Assert the ALE (Address Latch Enable) line to the flash chip */ - NAND_CTL_SETALE(nandptr); - - /* Send the address */ - /* Devices with 256-byte page are addressed as: - * Column (bits 0-7), Page (bits 8-15, 16-23, 24-31) - * there is no device on the market with page256 - * and more than 24 bits. - * Devices with 512-byte page are addressed as: - * Column (bits 0-7), Page (bits 9-16, 17-24, 25-31) - * 25-31 is sent only if the chip support it. - * bit 8 changes the read command to be sent - * (NAND_CMD_READ0 or NAND_CMD_READ1). - */ - - if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) - WRITE_NAND_ADDRESS(ofs, nandptr); - - ofs = ofs >> nand->page_shift; - - if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) { - for (i = 0; i < nand->pageadrlen; i++, ofs = ofs >> 8) { - WRITE_NAND_ADDRESS(ofs, nandptr); - } - } - - /* Lower the ALE line */ - NAND_CTL_CLRALE(nandptr); - - /* Wait for the chip to respond */ - return NanD_WaitReady(nand, 1); -} - -/* NanD_SelectChip: Select a given flash chip within the current floor */ - -static inline int NanD_SelectChip(struct nand_chip *nand, int chip) -{ - /* Wait for it to be ready */ - return NanD_WaitReady(nand, 0); -} - -/* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */ - -static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip) -{ - int mfr, id, i; - - NAND_ENABLE_CE(nand); /* set pin low */ - /* Reset the chip */ - if (NanD_Command(nand, NAND_CMD_RESET)) { -#ifdef NAND_DEBUG - printf("NanD_Command (reset) for %d,%d returned true\n", - floor, chip); -#endif - NAND_DISABLE_CE(nand); /* set pin high */ - return 0; - } - - /* Read the NAND chip ID: 1. Send ReadID command */ - if (NanD_Command(nand, NAND_CMD_READID)) { -#ifdef NAND_DEBUG - printf("NanD_Command (ReadID) for %d,%d returned true\n", - floor, chip); -#endif - NAND_DISABLE_CE(nand); /* set pin high */ - return 0; - } - - /* Read the NAND chip ID: 2. Send address byte zero */ - NanD_Address(nand, ADDR_COLUMN, 0); - - /* Read the manufacturer and device id codes from the device */ - - mfr = READ_NAND(nand->IO_ADDR); - - id = READ_NAND(nand->IO_ADDR); - - NAND_DISABLE_CE(nand); /* set pin high */ - -#ifdef NAND_DEBUG - printf("NanD_Command (ReadID) got %x %x\n", mfr, id); -#endif - if (mfr == 0xff || mfr == 0) { - /* No response - return failure */ - return 0; - } - - /* Check it's the same as the first chip we identified. - * M-Systems say that any given nand_chip device should only - * contain _one_ type of flash part, although that's not a - * hardware restriction. */ - if (nand->mfr) { - if (nand->mfr == mfr && nand->id == id) { - return 1; /* This is another the same the first */ - } else { - printf("Flash chip at floor %d, chip %d is different:\n", - floor, chip); - } - } - - /* Print and store the manufacturer and ID codes. */ - for (i = 0; nand_flash_ids[i].name != NULL; i++) { - if (mfr == nand_flash_ids[i].manufacture_id && - id == nand_flash_ids[i].model_id) { -#ifdef NAND_DEBUG - printf("Flash chip found:\n\t Manufacturer ID: 0x%2.2X, " - "Chip ID: 0x%2.2X (%s)\n", mfr, id, - nand_flash_ids[i].name); -#endif - if (!nand->mfr) { - nand->mfr = mfr; - nand->id = id; - nand->chipshift = - nand_flash_ids[i].chipshift; - nand->page256 = nand_flash_ids[i].page256; - nand->eccsize = 256; - if (nand->page256) { - nand->oobblock = 256; - nand->oobsize = 8; - nand->page_shift = 8; - } else { - nand->oobblock = 512; - nand->oobsize = 16; - nand->page_shift = 9; - } - nand->pageadrlen = nand_flash_ids[i].pageadrlen; - nand->erasesize = nand_flash_ids[i].erasesize; - nand->chips_name = nand_flash_ids[i].name; - nand->bus16 = nand_flash_ids[i].bus16; - return 1; - } - return 0; - } - } - - -#ifdef NAND_DEBUG - /* We haven't fully identified the chip. Print as much as we know. */ - printf("Unknown flash chip found: %2.2X %2.2X\n", - id, mfr); -#endif - - return 0; -} - -/* NanD_ScanChips: Find all NAND chips present in a nand_chip, and identify them */ - -static void NanD_ScanChips(struct nand_chip *nand) -{ - int floor, chip; - int numchips[NAND_MAX_FLOORS]; - int maxchips = NAND_MAX_CHIPS; - int ret = 1; - - nand->numchips = 0; - nand->mfr = 0; - nand->id = 0; - - - /* For each floor, find the number of valid chips it contains */ - for (floor = 0; floor < NAND_MAX_FLOORS; floor++) { - ret = 1; - numchips[floor] = 0; - for (chip = 0; chip < maxchips && ret != 0; chip++) { - - ret = NanD_IdentChip(nand, floor, chip); - if (ret) { - numchips[floor]++; - nand->numchips++; - } - } - } - - /* If there are none at all that we recognise, bail */ - if (!nand->numchips) { -#ifdef NAND_DEBUG - puts ("No NAND flash chips recognised.\n"); -#endif - return; - } - - /* Allocate an array to hold the information for each chip */ - nand->chips = malloc(sizeof(struct Nand) * nand->numchips); - if (!nand->chips) { - puts ("No memory for allocating chip info structures\n"); - return; - } - - ret = 0; - - /* Fill out the chip array with {floor, chipno} for each - * detected chip in the device. */ - for (floor = 0; floor < NAND_MAX_FLOORS; floor++) { - for (chip = 0; chip < numchips[floor]; chip++) { - nand->chips[ret].floor = floor; - nand->chips[ret].chip = chip; - nand->chips[ret].curadr = 0; - nand->chips[ret].curmode = 0x50; - ret++; - } - } - - /* Calculate and print the total size of the device */ - nand->totlen = nand->numchips * (1 << nand->chipshift); - -#ifdef NAND_DEBUG - printf("%d flash chips found. Total nand_chip size: %ld MB\n", - nand->numchips, nand->totlen >> 20); -#endif -} - -/* we need to be fast here, 1 us per read translates to 1 second per meg */ -static void NanD_ReadBuf (struct nand_chip *nand, u_char * data_buf, int cntr) -{ - unsigned long nandptr = nand->IO_ADDR; - - NanD_Command (nand, NAND_CMD_READ0); - - if (nand->bus16) { - u16 val; - - while (cntr >= 16) { - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - cntr -= 16; - } - - while (cntr > 0) { - val = READ_NAND (nandptr); - *data_buf++ = val & 0xff; - *data_buf++ = val >> 8; - cntr -= 2; - } - } else { - while (cntr >= 16) { - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - *data_buf++ = READ_NAND (nandptr); - cntr -= 16; - } - - while (cntr > 0) { - *data_buf++ = READ_NAND (nandptr); - cntr--; - } - } -} - -/* - * NAND read with ECC - */ -static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len, - size_t * retlen, u_char *buf, u_char *ecc_code) -{ - int col, page; - int ecc_status = 0; -#ifdef CONFIG_MTD_NAND_ECC - int j; - int ecc_failed = 0; - u_char *data_poi; - u_char ecc_calc[6]; -#endif - - /* Do not allow reads past end of device */ - if ((start + len) > nand->totlen) { - printf ("%s: Attempt read beyond end of device %x %x %x\n", - __FUNCTION__, (uint) start, (uint) len, (uint) nand->totlen); - *retlen = 0; - return -1; - } - - /* First we calculate the starting page */ - /*page = shr(start, nand->page_shift);*/ - page = start >> nand->page_shift; - - /* Get raw starting column */ - col = start & (nand->oobblock - 1); - - /* Initialize return value */ - *retlen = 0; - - /* Select the NAND device */ - NAND_ENABLE_CE(nand); /* set pin low */ - - /* Loop until all data read */ - while (*retlen < len) { - -#ifdef CONFIG_MTD_NAND_ECC - /* Do we have this page in cache ? */ - if (nand->cache_page == page) - goto readdata; - /* Send the read command */ - NanD_Command(nand, NAND_CMD_READ0); - if (nand->bus16) { - NanD_Address(nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + (col >> 1)); - } else { - NanD_Address(nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + col); - } - - /* Read in a page + oob data */ - NanD_ReadBuf(nand, nand->data_buf, nand->oobblock + nand->oobsize); - - /* copy data into cache, for read out of cache and if ecc fails */ - if (nand->data_cache) { - memcpy (nand->data_cache, nand->data_buf, - nand->oobblock + nand->oobsize); - } - - /* Pick the ECC bytes out of the oob data */ - for (j = 0; j < 6; j++) { - ecc_code[j] = nand->data_buf[(nand->oobblock + oob_config.ecc_pos[j])]; - } - - /* Calculate the ECC and verify it */ - /* If block was not written with ECC, skip ECC */ - if (oob_config.eccvalid_pos != -1 && - (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0x0f) != 0x0f) { - - nand_calculate_ecc (&nand->data_buf[0], &ecc_calc[0]); - switch (nand_correct_data (&nand->data_buf[0], &ecc_code[0], &ecc_calc[0])) { - case -1: - printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page); - ecc_failed++; - break; - case 1: - case 2: /* transfer ECC corrected data to cache */ - if (nand->data_cache) - memcpy (nand->data_cache, nand->data_buf, 256); - break; - } - } - - if (oob_config.eccvalid_pos != -1 && - nand->oobblock == 512 && (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0xf0) != 0xf0) { - - nand_calculate_ecc (&nand->data_buf[256], &ecc_calc[3]); - switch (nand_correct_data (&nand->data_buf[256], &ecc_code[3], &ecc_calc[3])) { - case -1: - printf ("%s: Failed ECC read, page 0x%08x\n", __FUNCTION__, page); - ecc_failed++; - break; - case 1: - case 2: /* transfer ECC corrected data to cache */ - if (nand->data_cache) - memcpy (&nand->data_cache[256], &nand->data_buf[256], 256); - break; - } - } -readdata: - /* Read the data from ECC data buffer into return buffer */ - data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf; - data_poi += col; - if ((*retlen + (nand->oobblock - col)) >= len) { - memcpy (buf + *retlen, data_poi, len - *retlen); - *retlen = len; - } else { - memcpy (buf + *retlen, data_poi, nand->oobblock - col); - *retlen += nand->oobblock - col; - } - /* Set cache page address, invalidate, if ecc_failed */ - nand->cache_page = (nand->data_cache && !ecc_failed) ? page : -1; - - ecc_status += ecc_failed; - ecc_failed = 0; - -#else - /* Send the read command */ - NanD_Command(nand, NAND_CMD_READ0); - if (nand->bus16) { - NanD_Address(nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + (col >> 1)); - } else { - NanD_Address(nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + col); - } - - /* Read the data directly into the return buffer */ - if ((*retlen + (nand->oobblock - col)) >= len) { - NanD_ReadBuf(nand, buf + *retlen, len - *retlen); - *retlen = len; - /* We're done */ - continue; - } else { - NanD_ReadBuf(nand, buf + *retlen, nand->oobblock - col); - *retlen += nand->oobblock - col; - } -#endif - /* For subsequent reads align to page boundary. */ - col = 0; - /* Increment page address */ - page++; - } - - /* De-select the NAND device */ - NAND_DISABLE_CE(nand); /* set pin high */ - - /* - * Return success, if no ECC failures, else -EIO - * fs driver will take care of that, because - * retlen == desired len and result == -EIO - */ - return ecc_status ? -1 : 0; -} - -/* - * Nand_page_program function is used for write and writev ! - */ -static int nand_write_page (struct nand_chip *nand, - int page, int col, int last, u_char * ecc_code) -{ - - int i; - unsigned long nandptr = nand->IO_ADDR; - -#ifdef CONFIG_MTD_NAND_ECC -#ifdef CONFIG_MTD_NAND_VERIFY_WRITE - int ecc_bytes = (nand->oobblock == 512) ? 6 : 3; -#endif -#endif - /* pad oob area */ - for (i = nand->oobblock; i < nand->oobblock + nand->oobsize; i++) - nand->data_buf[i] = 0xff; - -#ifdef CONFIG_MTD_NAND_ECC - /* Zero out the ECC array */ - for (i = 0; i < 6; i++) - ecc_code[i] = 0x00; - - /* Read back previous written data, if col > 0 */ - if (col) { - NanD_Command (nand, NAND_CMD_READ0); - if (nand->bus16) { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + (col >> 1)); - } else { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + col); - } - - if (nand->bus16) { - u16 val; - - for (i = 0; i < col; i += 2) { - val = READ_NAND (nandptr); - nand->data_buf[i] = val & 0xff; - nand->data_buf[i + 1] = val >> 8; - } - } else { - for (i = 0; i < col; i++) - nand->data_buf[i] = READ_NAND (nandptr); - } - } - - /* Calculate and write the ECC if we have enough data */ - if ((col < nand->eccsize) && (last >= nand->eccsize)) { - nand_calculate_ecc (&nand->data_buf[0], &(ecc_code[0])); - for (i = 0; i < 3; i++) { - nand->data_buf[(nand->oobblock + - oob_config.ecc_pos[i])] = ecc_code[i]; - } - if (oob_config.eccvalid_pos != -1) { - nand->data_buf[nand->oobblock + - oob_config.eccvalid_pos] = 0xf0; - } - } - - /* Calculate and write the second ECC if we have enough data */ - if ((nand->oobblock == 512) && (last == nand->oobblock)) { - nand_calculate_ecc (&nand->data_buf[256], &(ecc_code[3])); - for (i = 3; i < 6; i++) { - nand->data_buf[(nand->oobblock + - oob_config.ecc_pos[i])] = ecc_code[i]; - } - if (oob_config.eccvalid_pos != -1) { - nand->data_buf[nand->oobblock + - oob_config.eccvalid_pos] &= 0x0f; - } - } -#endif - /* Prepad for partial page programming !!! */ - for (i = 0; i < col; i++) - nand->data_buf[i] = 0xff; - - /* Postpad for partial page programming !!! oob is already padded */ - for (i = last; i < nand->oobblock; i++) - nand->data_buf[i] = 0xff; - - /* Send command to begin auto page programming */ - NanD_Command (nand, NAND_CMD_READ0); - NanD_Command (nand, NAND_CMD_SEQIN); - if (nand->bus16) { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + (col >> 1)); - } else { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + col); - } - - /* Write out complete page of data */ - if (nand->bus16) { - for (i = 0; i < (nand->oobblock + nand->oobsize); i += 2) { - WRITE_NAND (nand->data_buf[i] + - (nand->data_buf[i + 1] << 8), - nand->IO_ADDR); - } - } else { - for (i = 0; i < (nand->oobblock + nand->oobsize); i++) - WRITE_NAND (nand->data_buf[i], nand->IO_ADDR); - } - - /* Send command to actually program the data */ - NanD_Command (nand, NAND_CMD_PAGEPROG); - NanD_Command (nand, NAND_CMD_STATUS); -#ifdef NAND_NO_RB - { - u_char ret_val; - - do { - ret_val = READ_NAND (nandptr); /* wait till ready */ - } while ((ret_val & 0x40) != 0x40); - } -#endif - /* See if device thinks it succeeded */ - if (READ_NAND (nand->IO_ADDR) & 0x01) { - printf ("%s: Failed write, page 0x%08x, ", __FUNCTION__, - page); - return -1; - } -#ifdef CONFIG_MTD_NAND_VERIFY_WRITE - /* - * The NAND device assumes that it is always writing to - * a cleanly erased page. Hence, it performs its internal - * write verification only on bits that transitioned from - * 1 to 0. The device does NOT verify the whole page on a - * byte by byte basis. It is possible that the page was - * not completely erased or the page is becoming unusable - * due to wear. The read with ECC would catch the error - * later when the ECC page check fails, but we would rather - * catch it early in the page write stage. Better to write - * no data than invalid data. - */ - - /* Send command to read back the page */ - if (col < nand->eccsize) - NanD_Command (nand, NAND_CMD_READ0); - else - NanD_Command (nand, NAND_CMD_READ1); - if (nand->bus16) { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + (col >> 1)); - } else { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + col); - } - - /* Loop through and verify the data */ - if (nand->bus16) { - for (i = col; i < last; i = +2) { - if ((nand->data_buf[i] + - (nand->data_buf[i + 1] << 8)) != READ_NAND (nand->IO_ADDR)) { - printf ("%s: Failed write verify, page 0x%08x ", - __FUNCTION__, page); - return -1; - } - } - } else { - for (i = col; i < last; i++) { - if (nand->data_buf[i] != READ_NAND (nand->IO_ADDR)) { - printf ("%s: Failed write verify, page 0x%08x ", - __FUNCTION__, page); - return -1; - } - } - } - -#ifdef CONFIG_MTD_NAND_ECC - /* - * We also want to check that the ECC bytes wrote - * correctly for the same reasons stated above. - */ - NanD_Command (nand, NAND_CMD_READOOB); - if (nand->bus16) { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + (col >> 1)); - } else { - NanD_Address (nand, ADDR_COLUMN_PAGE, - (page << nand->page_shift) + col); - } - if (nand->bus16) { - for (i = 0; i < nand->oobsize; i += 2) { - u16 val; - - val = READ_NAND (nand->IO_ADDR); - nand->data_buf[i] = val & 0xff; - nand->data_buf[i + 1] = val >> 8; - } - } else { - for (i = 0; i < nand->oobsize; i++) { - nand->data_buf[i] = READ_NAND (nand->IO_ADDR); - } - } - for (i = 0; i < ecc_bytes; i++) { - if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) { - printf ("%s: Failed ECC write " - "verify, page 0x%08x, " - "%6i bytes were succesful\n", - __FUNCTION__, page, i); - return -1; - } - } -#endif /* CONFIG_MTD_NAND_ECC */ -#endif /* CONFIG_MTD_NAND_VERIFY_WRITE */ - return 0; -} - -static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len, - size_t * retlen, const u_char * buf, u_char * ecc_code) -{ - int i, page, col, cnt, ret = 0; - - /* Do not allow write past end of device */ - if ((to + len) > nand->totlen) { - printf ("%s: Attempt to write past end of page\n", __FUNCTION__); - return -1; - } - - /* Shift to get page */ - page = ((int) to) >> nand->page_shift; - - /* Get the starting column */ - col = to & (nand->oobblock - 1); - - /* Initialize return length value */ - *retlen = 0; - - /* Select the NAND device */ -#ifdef CONFIG_OMAP1510 - archflashwp(0,0); -#endif -#ifdef CFG_NAND_WP - NAND_WP_OFF(); -#endif - - NAND_ENABLE_CE(nand); /* set pin low */ - - /* Check the WP bit */ - NanD_Command(nand, NAND_CMD_STATUS); - if (!(READ_NAND(nand->IO_ADDR) & 0x80)) { - printf ("%s: Device is write protected!!!\n", __FUNCTION__); - ret = -1; - goto out; - } - - /* Loop until all data is written */ - while (*retlen < len) { - /* Invalidate cache, if we write to this page */ - if (nand->cache_page == page) - nand->cache_page = -1; - - /* Write data into buffer */ - if ((col + len) >= nand->oobblock) { - for (i = col, cnt = 0; i < nand->oobblock; i++, cnt++) { - nand->data_buf[i] = buf[(*retlen + cnt)]; - } - } else { - for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++) { - nand->data_buf[i] = buf[(*retlen + cnt)]; - } - } - /* We use the same function for write and writev !) */ - ret = nand_write_page (nand, page, col, i, ecc_code); - if (ret) - goto out; - - /* Next data start at page boundary */ - col = 0; - - /* Update written bytes count */ - *retlen += cnt; - - /* Increment page address */ - page++; - } - - /* Return happy */ - *retlen = len; - -out: - /* De-select the NAND device */ - NAND_DISABLE_CE(nand); /* set pin high */ -#ifdef CONFIG_OMAP1510 - archflashwp(0,1); -#endif -#ifdef CFG_NAND_WP - NAND_WP_ON(); -#endif - - return ret; -} - -/* read from the 16 bytes of oob data that correspond to a 512 byte - * page or 2 256-byte pages. - */ -static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len, - size_t * retlen, u_char * buf) -{ - int len256 = 0; - struct Nand *mychip; - int ret = 0; - - mychip = &nand->chips[ofs >> nand->chipshift]; - - /* update address for 2M x 8bit devices. OOB starts on the second */ - /* page to maintain compatibility with nand_read_ecc. */ - if (nand->page256) { - if (!(ofs & 0x8)) - ofs += 0x100; - else - ofs -= 0x8; - } - - NAND_ENABLE_CE(nand); /* set pin low */ - NanD_Command(nand, NAND_CMD_READOOB); - if (nand->bus16) { - NanD_Address(nand, ADDR_COLUMN_PAGE, - ((ofs >> nand->page_shift) << nand->page_shift) + - ((ofs & (nand->oobblock - 1)) >> 1)); - } else { - NanD_Address(nand, ADDR_COLUMN_PAGE, ofs); - } - - /* treat crossing 8-byte OOB data for 2M x 8bit devices */ - /* Note: datasheet says it should automaticaly wrap to the */ - /* next OOB block, but it didn't work here. mf. */ - if (nand->page256 && ofs + len > (ofs | 0x7) + 1) { - len256 = (ofs | 0x7) + 1 - ofs; - NanD_ReadBuf(nand, buf, len256); - - NanD_Command(nand, NAND_CMD_READOOB); - NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff)); - } - - NanD_ReadBuf(nand, &buf[len256], len - len256); - - *retlen = len; - /* Reading the full OOB data drops us off of the end of the page, - * causing the flash device to go into busy mode, so we need - * to wait until ready 11.4.1 and Toshiba TC58256FT nands */ - - ret = NanD_WaitReady(nand, 1); - NAND_DISABLE_CE(nand); /* set pin high */ - - return ret; - -} - -/* write to the 16 bytes of oob data that correspond to a 512 byte - * page or 2 256-byte pages. - */ -static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, - size_t * retlen, const u_char * buf) -{ - int len256 = 0; - int i; - unsigned long nandptr = nand->IO_ADDR; - -#ifdef PSYCHO_DEBUG - printf("nand_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n", - (long)ofs, len, buf[0], buf[1], buf[2], buf[3], - buf[8], buf[9], buf[14],buf[15]); -#endif - - NAND_ENABLE_CE(nand); /* set pin low to enable chip */ - - /* Reset the chip */ - NanD_Command(nand, NAND_CMD_RESET); - - /* issue the Read2 command to set the pointer to the Spare Data Area. */ - NanD_Command(nand, NAND_CMD_READOOB); - if (nand->bus16) { - NanD_Address(nand, ADDR_COLUMN_PAGE, - ((ofs >> nand->page_shift) << nand->page_shift) + - ((ofs & (nand->oobblock - 1)) >> 1)); - } else { - NanD_Address(nand, ADDR_COLUMN_PAGE, ofs); - } - - /* update address for 2M x 8bit devices. OOB starts on the second */ - /* page to maintain compatibility with nand_read_ecc. */ - if (nand->page256) { - if (!(ofs & 0x8)) - ofs += 0x100; - else - ofs -= 0x8; - } - - /* issue the Serial Data In command to initial the Page Program process */ - NanD_Command(nand, NAND_CMD_SEQIN); - if (nand->bus16) { - NanD_Address(nand, ADDR_COLUMN_PAGE, - ((ofs >> nand->page_shift) << nand->page_shift) + - ((ofs & (nand->oobblock - 1)) >> 1)); - } else { - NanD_Address(nand, ADDR_COLUMN_PAGE, ofs); - } - - /* treat crossing 8-byte OOB data for 2M x 8bit devices */ - /* Note: datasheet says it should automaticaly wrap to the */ - /* next OOB block, but it didn't work here. mf. */ - if (nand->page256 && ofs + len > (ofs | 0x7) + 1) { - len256 = (ofs | 0x7) + 1 - ofs; - for (i = 0; i < len256; i++) - WRITE_NAND(buf[i], nandptr); - - NanD_Command(nand, NAND_CMD_PAGEPROG); - NanD_Command(nand, NAND_CMD_STATUS); -#ifdef NAND_NO_RB - { u_char ret_val; - do { - ret_val = READ_NAND(nandptr); /* wait till ready */ - } while ((ret_val & 0x40) != 0x40); - } -#endif - if (READ_NAND(nandptr) & 1) { - puts ("Error programming oob data\n"); - /* There was an error */ - NAND_DISABLE_CE(nand); /* set pin high */ - *retlen = 0; - return -1; - } - NanD_Command(nand, NAND_CMD_SEQIN); - NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff)); - } - - if (nand->bus16) { - for (i = len256; i < len; i += 2) { - WRITE_NAND(buf[i] + (buf[i+1] << 8), nandptr); - } - } else { - for (i = len256; i < len; i++) - WRITE_NAND(buf[i], nandptr); - } - - NanD_Command(nand, NAND_CMD_PAGEPROG); - NanD_Command(nand, NAND_CMD_STATUS); -#ifdef NAND_NO_RB - { u_char ret_val; - do { - ret_val = READ_NAND(nandptr); /* wait till ready */ - } while ((ret_val & 0x40) != 0x40); - } -#endif - if (READ_NAND(nandptr) & 1) { - puts ("Error programming oob data\n"); - /* There was an error */ - NAND_DISABLE_CE(nand); /* set pin high */ - *retlen = 0; - return -1; - } - - NAND_DISABLE_CE(nand); /* set pin high */ - *retlen = len; - return 0; - -} - -int nand_erase(struct nand_chip* nand, size_t ofs, size_t len, int clean) -{ - /* This is defined as a structure so it will work on any system - * using native endian jffs2 (the default). - */ - static struct jffs2_unknown_node clean_marker = { - JFFS2_MAGIC_BITMASK, - JFFS2_NODETYPE_CLEANMARKER, - 8 /* 8 bytes in this node */ - }; - unsigned long nandptr; - struct Nand *mychip; - int ret = 0; - - if (ofs & (nand->erasesize-1) || len & (nand->erasesize-1)) { - printf ("Offset and size must be sector aligned, erasesize = %d\n", - (int) nand->erasesize); - return -1; - } - - nandptr = nand->IO_ADDR; - - /* Select the NAND device */ -#ifdef CONFIG_OMAP1510 - archflashwp(0,0); -#endif -#ifdef CFG_NAND_WP - NAND_WP_OFF(); -#endif - NAND_ENABLE_CE(nand); /* set pin low */ - - /* Check the WP bit */ - NanD_Command(nand, NAND_CMD_STATUS); - if (!(READ_NAND(nand->IO_ADDR) & 0x80)) { - printf ("nand_write_ecc: Device is write protected!!!\n"); - ret = -1; - goto out; - } - - /* Check the WP bit */ - NanD_Command(nand, NAND_CMD_STATUS); - if (!(READ_NAND(nand->IO_ADDR) & 0x80)) { - printf ("%s: Device is write protected!!!\n", __FUNCTION__); - ret = -1; - goto out; - } - - /* FIXME: Do nand in the background. Use timers or schedule_task() */ - while(len) { - /*mychip = &nand->chips[shr(ofs, nand->chipshift)];*/ - mychip = &nand->chips[ofs >> nand->chipshift]; - - /* always check for bad block first, genuine bad blocks - * should _never_ be erased. - */ - if (ALLOW_ERASE_BAD_DEBUG || !check_block(nand, ofs)) { - /* Select the NAND device */ - NAND_ENABLE_CE(nand); /* set pin low */ - - NanD_Command(nand, NAND_CMD_ERASE1); - NanD_Address(nand, ADDR_PAGE, ofs); - NanD_Command(nand, NAND_CMD_ERASE2); - - NanD_Command(nand, NAND_CMD_STATUS); - -#ifdef NAND_NO_RB - { u_char ret_val; - do { - ret_val = READ_NAND(nandptr); /* wait till ready */ - } while ((ret_val & 0x40) != 0x40); - } -#endif - if (READ_NAND(nandptr) & 1) { - printf ("%s: Error erasing at 0x%lx\n", - __FUNCTION__, (long)ofs); - /* There was an error */ - ret = -1; - goto out; - } - if (clean) { - int n; /* return value not used */ - int p, l; - - /* clean marker position and size depend - * on the page size, since 256 byte pages - * only have 8 bytes of oob data - */ - if (nand->page256) { - p = NAND_JFFS2_OOB8_FSDAPOS; - l = NAND_JFFS2_OOB8_FSDALEN; - } else { - p = NAND_JFFS2_OOB16_FSDAPOS; - l = NAND_JFFS2_OOB16_FSDALEN; - } - - ret = nand_write_oob(nand, ofs + p, l, (size_t *)&n, - (u_char *)&clean_marker); - /* quit here if write failed */ - if (ret) - goto out; - } - } - ofs += nand->erasesize; - len -= nand->erasesize; - } - -out: - /* De-select the NAND device */ - NAND_DISABLE_CE(nand); /* set pin high */ -#ifdef CONFIG_OMAP1510 - archflashwp(0,1); -#endif -#ifdef CFG_NAND_WP - NAND_WP_ON(); -#endif - - return ret; -} - -static inline int nandcheck(unsigned long potential, unsigned long physadr) -{ - return 0; -} - -unsigned long nand_probe(unsigned long physadr) -{ - struct nand_chip *nand = NULL; - int i = 0, ChipID = 1; - -#ifdef CONFIG_MTD_NAND_ECC_JFFS2 - oob_config.ecc_pos[0] = NAND_JFFS2_OOB_ECCPOS0; - oob_config.ecc_pos[1] = NAND_JFFS2_OOB_ECCPOS1; - oob_config.ecc_pos[2] = NAND_JFFS2_OOB_ECCPOS2; - oob_config.ecc_pos[3] = NAND_JFFS2_OOB_ECCPOS3; - oob_config.ecc_pos[4] = NAND_JFFS2_OOB_ECCPOS4; - oob_config.ecc_pos[5] = NAND_JFFS2_OOB_ECCPOS5; - oob_config.eccvalid_pos = 4; -#else - oob_config.ecc_pos[0] = NAND_NOOB_ECCPOS0; - oob_config.ecc_pos[1] = NAND_NOOB_ECCPOS1; - oob_config.ecc_pos[2] = NAND_NOOB_ECCPOS2; - oob_config.ecc_pos[3] = NAND_NOOB_ECCPOS3; - oob_config.ecc_pos[4] = NAND_NOOB_ECCPOS4; - oob_config.ecc_pos[5] = NAND_NOOB_ECCPOS5; - oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS; -#endif - oob_config.badblock_pos = 5; - - for (i=0; iIO_ADDR = physadr; - nand->cache_page = -1; /* init the cache page */ - NanD_ScanChips(nand); - - if (nand->totlen == 0) { - /* no chips found, clean up and quit */ - memset((char *)nand, 0, sizeof(struct nand_chip)); - nand->ChipID = NAND_ChipID_UNKNOWN; - return (0); - } - - nand->ChipID = ChipID; - if (curr_device == -1) - curr_device = i; - - nand->data_buf = malloc (nand->oobblock + nand->oobsize); - if (!nand->data_buf) { - puts ("Cannot allocate memory for data structures.\n"); - return (0); - } - - return (nand->totlen); -} - -#ifdef CONFIG_MTD_NAND_ECC -/* - * Pre-calculated 256-way 1 byte column parity - */ -static const u_char nand_ecc_precalc_table[] = { - 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, - 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, - 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, - 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, - 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, - 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, - 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, - 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, - 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, - 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, - 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, - 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, - 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, - 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, - 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, - 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, - 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, - 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, - 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, - 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, - 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, - 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, - 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, - 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, - 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, - 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, - 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, - 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, - 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, - 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, - 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, - 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 -}; - - -/* - * Creates non-inverted ECC code from line parity - */ -static void nand_trans_result(u_char reg2, u_char reg3, - u_char *ecc_code) -{ - u_char a, b, i, tmp1, tmp2; - - /* Initialize variables */ - a = b = 0x80; - tmp1 = tmp2 = 0; - - /* Calculate first ECC byte */ - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - a >>= 1; - } - - /* Calculate second ECC byte */ - b = 0x80; - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - a >>= 1; - } - - /* Store two of the ECC bytes */ - ecc_code[0] = tmp1; - ecc_code[1] = tmp2; -} - -/* - * Calculate 3 byte ECC code for 256 byte block - */ -static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code) -{ - u_char idx, reg1, reg3; - int j; - - /* Initialize variables */ - reg1 = reg3 = 0; - ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; - - /* Build up column parity */ - for(j = 0; j < 256; j++) { - - /* Get CP0 - CP5 from table */ - idx = nand_ecc_precalc_table[dat[j]]; - reg1 ^= idx; - - /* All bit XOR = 1 ? */ - if (idx & 0x40) { - reg3 ^= (u_char) j; - } - } - - /* Create non-inverted ECC code from line parity */ - nand_trans_result((reg1 & 0x40) ? ~reg3 : reg3, reg3, ecc_code); - - /* Calculate final ECC code */ - ecc_code[0] = ~ecc_code[0]; - ecc_code[1] = ~ecc_code[1]; - ecc_code[2] = ((~reg1) << 2) | 0x03; -} - -/* - * Detect and correct a 1 bit error for 256 byte block - */ -static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc) -{ - u_char a, b, c, d1, d2, d3, add, bit, i; - - /* Do error detection */ - d1 = calc_ecc[0] ^ read_ecc[0]; - d2 = calc_ecc[1] ^ read_ecc[1]; - d3 = calc_ecc[2] ^ read_ecc[2]; - - if ((d1 | d2 | d3) == 0) { - /* No errors */ - return 0; - } else { - a = (d1 ^ (d1 >> 1)) & 0x55; - b = (d2 ^ (d2 >> 1)) & 0x55; - c = (d3 ^ (d3 >> 1)) & 0x54; - - /* Found and will correct single bit error in the data */ - if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { - c = 0x80; - add = 0; - a = 0x80; - for (i=0; i<4; i++) { - if (d1 & c) - add |= a; - c >>= 2; - a >>= 1; - } - c = 0x80; - for (i=0; i<4; i++) { - if (d2 & c) - add |= a; - c >>= 2; - a >>= 1; - } - bit = 0; - b = 0x04; - c = 0x80; - for (i=0; i<3; i++) { - if (d3 & c) - bit |= b; - c >>= 2; - b >>= 1; - } - b = 0x01; - a = dat[add]; - a ^= (b << bit); - dat[add] = a; - return 1; - } - else { - i = 0; - while (d1) { - if (d1 & 0x01) - ++i; - d1 >>= 1; - } - while (d2) { - if (d2 & 0x01) - ++i; - d2 >>= 1; - } - while (d3) { - if (d3 & 0x01) - ++i; - d3 >>= 1; - } - if (i == 1) { - /* ECC Code Error Correction */ - read_ecc[0] = calc_ecc[0]; - read_ecc[1] = calc_ecc[1]; - read_ecc[2] = calc_ecc[2]; - return 2; - } - else { - /* Uncorrectable Error */ - return -1; - } - } - } - - /* Should never happen */ - return -1; -} - -#endif - -#ifdef CONFIG_JFFS2_NAND - -int read_jffs2_nand(size_t start, size_t len, - size_t * retlen, u_char * buf, int nanddev) -{ - return nand_rw(nand_dev_desc + nanddev, NANDRW_READ | NANDRW_JFFS2, - start, len, retlen, buf); -} - -#endif /* CONFIG_JFFS2_NAND */ - - #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ + +#endif /* CFG_NAND_LEGACY */ diff --git a/common/cmd_net.c b/common/cmd_net.c index 2cb2c5d..9a2eebf 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -187,7 +187,8 @@ netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[]) return 1; } - if ((size = NetLoop(proto)) < 0) + size = NetLoop(proto); + if (size < 0) return 1; /* NetLoop ok, update environment */ diff --git a/common/cmd_pci.c b/common/cmd_pci.c index 4508546..a50ae29 100644 --- a/common/cmd_pci.c +++ b/common/cmd_pci.c @@ -89,10 +89,11 @@ void pciinfo(int BusNum, int ShortPCIListing) break; dev = PCI_BDF(BusNum, Device, Function); - pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID); if ((VendorID == 0xFFFF) || (VendorID == 0x0000)) - continue; + { + continue; + } if (!Function) pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType); diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index e804861..3df5ce3 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -27,12 +27,16 @@ /* * SCSI support. */ + +/* #define DEBUG */ + #include #include #include #include #include #include +#include #if (CONFIG_COMMANDS & CFG_CMD_SCSI) @@ -43,8 +47,18 @@ #else #define SCSI_DEV_ID CONFIG_SCSI_DEV_ID #endif +#elif defined CONFIG_SATA_ULI5288 + +#define SCSI_VEND_ID 0x10b9 +#define SCSI_DEV_ID 0x5288 + +#elif defined CONFIG_SATA_6121 + +#define SCSI_VEND_ID 0x11ab +#define SCSI_DEV_ID 0x6121 + #else -#error CONFIG_SCSI_SYM53C8XX must be defined +#error no scsi device defined #endif diff --git a/common/console.c b/common/console.c index 3c535d2..eb1268f 100644 --- a/common/console.c +++ b/common/console.c @@ -206,7 +206,14 @@ void putc (const char c) void puts (const char *s) { DECLARE_GLOBAL_DATA_PTR; - +//Patch by QNAP:Fix detect LCM +#if defined(TS419) + if(!mvGppValueGet(1,0x00002000)){ + //LCM + return; + } +#endif +///////////////////////////////////// #ifdef CONFIG_SILENT_CONSOLE if (gd->flags & GD_FLG_SILENT) return; diff --git a/common/docecc.c b/common/docecc.c index 79adb48..3928cfd 100644 --- a/common/docecc.c +++ b/common/docecc.c @@ -7,7 +7,7 @@ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: docecc.c,v 1.4 2001/10/02 15:05:13 dwmw2 Exp $ + * $Id: docecc.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * * 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 diff --git a/common/env_common.c b/common/env_common.c index 3201135..f90dc2c 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -258,7 +258,13 @@ void env_relocate (void) gd->env_valid = 1; } else { +#ifdef CONFIG_MARVELL + mvMPPConfigToSPI(); env_relocate_spec (); + mvMPPConfigToDefault(); +#else + env_relocate_spec (); +#endif } gd->env_addr = (ulong)&(env_ptr->data); diff --git a/common/env_flash.c b/common/env_flash.c index a2ea9c4..531638e 100644 --- a/common/env_flash.c +++ b/common/env_flash.c @@ -267,9 +267,17 @@ int env_init(void) if(flash_probe() == 0) goto bad_flash; #endif - if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { - gd->env_addr = (ulong)&(env_ptr->data); - gd->env_valid = 1; +#ifdef CONFIG_MARVELL + mvMPPConfigToSPI(); + if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { + gd->env_addr = (ulong)&(env_ptr->data); + gd->env_valid = 1; + mvMPPConfigToDefault(); +#else + if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { + gd->env_addr = (ulong)&(env_ptr->data); + gd->env_valid = 1; +#endif return(0); } #ifdef CONFIG_OMAP2420H4 diff --git a/common/env_nand.c b/common/env_nand.c index 60aba1e..51e87ab 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -2,7 +2,7 @@ * (C) Copyright 2004 * Jian Zhang, Texas Instruments, jzhang@ti.com. - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH @@ -36,35 +36,29 @@ #include #include #include -#include +#include +#include #if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_NAND)) == (CFG_CMD_ENV|CFG_CMD_NAND)) #define CMD_SAVEENV +#elif defined(CFG_ENV_OFFSET_REDUND) +#error Cannot use CFG_ENV_OFFSET_REDUND without CFG_CMD_ENV & CFG_CMD_NAND #endif -#if defined(CFG_ENV_SIZE_REDUND) -#error CFG_ENV_SIZE_REDUND not supported yet +#if defined(CFG_ENV_SIZE_REDUND) && (CFG_ENV_SIZE_REDUND != CFG_ENV_SIZE) +#error CFG_ENV_SIZE_REDUND should be the same as CFG_ENV_SIZE #endif -#if defined(CFG_ENV_ADDR_REDUND) -#error CFG_ENV_ADDR_REDUND and CFG_ENV_IS_IN_NAND not supported yet -#endif - - #ifdef CONFIG_INFERNO #error CONFIG_INFERNO not supported yet #endif -/* references to names in cmd_nand.c */ -#define NANDRW_READ 0x01 -#define NANDRW_WRITE 0x00 -#define NANDRW_JFFS2 0x02 -extern struct nand_chip nand_dev_desc[]; -int nand_rw (struct nand_chip* nand, int cmd, +int nand_legacy_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf); -int nand_erase(struct nand_chip* nand, size_t ofs, - size_t len, int clean); + +/* info for NAND chips, defined in drivers/nand/nand.c */ +extern nand_info_t nand_info[]; /* references to names in env_common.c */ extern uchar default_environment[]; @@ -82,13 +76,14 @@ env_t *env_ptr = 0; /* local functions */ +#if !defined(ENV_IS_EMBEDDED) static void use_default(void); +#endif +DECLARE_GLOBAL_DATA_PTR; uchar env_get_char_spec (int index) { - DECLARE_GLOBAL_DATA_PTR; - return ( *((uchar *)(gd->env_addr + index)) ); } @@ -98,62 +93,204 @@ uchar env_get_char_spec (int index) * Mark it OK for now. env_relocate() in env_common.c * will call our relocate function which will does * the real validation. + * + * When using a NAND boot image (like sequoia_nand), the environment + * can be embedded or attached to the U-Boot image in NAND flash. This way + * the SPL loads not only the U-Boot image from NAND but also the + * environment. */ int env_init(void) { - DECLARE_GLOBAL_DATA_PTR; +#if defined(ENV_IS_EMBEDDED) + ulong total; + int crc1_ok = 0, crc2_ok = 0; + env_t *tmp_env1, *tmp_env2; - gd->env_addr = (ulong)&default_environment[0]; + total = CFG_ENV_SIZE; + + tmp_env1 = env_ptr; + tmp_env2 = (env_t *)((ulong)env_ptr + CFG_ENV_SIZE); + + crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); + crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); + + if (!crc1_ok && !crc2_ok) + gd->env_valid = 0; + else if(crc1_ok && !crc2_ok) + gd->env_valid = 1; + else if(!crc1_ok && crc2_ok) + gd->env_valid = 2; + else { + /* both ok - check serial */ + if(tmp_env1->flags == 255 && tmp_env2->flags == 0) + gd->env_valid = 2; + else if(tmp_env2->flags == 255 && tmp_env1->flags == 0) + gd->env_valid = 1; + else if(tmp_env1->flags > tmp_env2->flags) + gd->env_valid = 1; + else if(tmp_env2->flags > tmp_env1->flags) + gd->env_valid = 2; + else /* flags are equal - almost impossible */ + gd->env_valid = 1; + } + + if (gd->env_valid == 1) + env_ptr = tmp_env1; + else if (gd->env_valid == 2) + env_ptr = tmp_env2; +#else /* ENV_IS_EMBEDDED */ + gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 1; +#if defined(CONFIG_MARVELL) +// gd->env_addr = CFG_ENV_ADDR; +#endif /* defined(CONFIG_MARVELL) */ +#endif /* ENV_IS_EMBEDDED */ return (0); } #ifdef CMD_SAVEENV +/* + * The legacy NAND code saved the environment in the first NAND device i.e., + * nand_dev_desc + 0. This is also the behaviour using the new NAND code. + */ +#ifdef CFG_ENV_OFFSET_REDUND int saveenv(void) { - int total, ret = 0; - puts ("Erasing Nand..."); - if (nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0)) - return 1; + ulong total; + int ret = 0; - puts ("Writing to Nand... "); - ret = nand_rw(nand_dev_desc + 0, - NANDRW_WRITE | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE, - &total, (u_char*)env_ptr); - if (ret || total != CFG_ENV_SIZE) + env_ptr->flags++; + total = CFG_ENV_SIZE; + + if(gd->env_valid == 1) { + puts ("Erasing redundant Nand..."); + if (nand_erase(&nand_info[0], + CFG_ENV_OFFSET_REDUND, CFG_ENV_SIZE)) + return 1; + puts ("Writing to redundant Nand... "); + ret = nand_write(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, + (u_char*) env_ptr); + } else { + puts ("Erasing Nand..."); + if (nand_erase(&nand_info[0], + CFG_ENV_OFFSET, CFG_ENV_SIZE)) + return 1; + + puts ("Writing to Nand... "); + ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, + (u_char*) env_ptr); + } + if (ret || total != CFG_ENV_SIZE) return 1; - puts ("done\n"); - return ret; + puts ("done\n"); + gd->env_valid = (gd->env_valid == 2 ? 1 : 2); + return ret; } +#else /* ! CFG_ENV_OFFSET_REDUND */ +int saveenv(void) +{ + ulong total; + int ret = 0; + + puts ("Erasing Nand..."); + if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) + return 1; + + puts ("Writing to Nand... "); + total = CFG_ENV_SIZE; + ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); + if (ret || total != CFG_ENV_SIZE) + return 1; + + puts ("done\n"); + return ret; +} +#endif /* CFG_ENV_OFFSET_REDUND */ #endif /* CMD_SAVEENV */ - +#ifdef CFG_ENV_OFFSET_REDUND void env_relocate_spec (void) { #if !defined(ENV_IS_EMBEDDED) - int ret, total; + ulong total; + int crc1_ok = 0, crc2_ok = 0; + env_t *tmp_env1, *tmp_env2; - ret = nand_rw(nand_dev_desc + 0, - NANDRW_READ | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE, - &total, (u_char*)env_ptr); + total = CFG_ENV_SIZE; + + tmp_env1 = (env_t *) malloc(CFG_ENV_SIZE); + tmp_env2 = (env_t *) malloc(CFG_ENV_SIZE); + + nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, + (u_char*) tmp_env1); + nand_read(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, + (u_char*) tmp_env2); + + crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); + crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); + + if(!crc1_ok && !crc2_ok) + return use_default(); + else if(crc1_ok && !crc2_ok) + gd->env_valid = 1; + else if(!crc1_ok && crc2_ok) + gd->env_valid = 2; + else { + /* both ok - check serial */ + if(tmp_env1->flags == 255 && tmp_env2->flags == 0) + gd->env_valid = 2; + else if(tmp_env2->flags == 255 && tmp_env1->flags == 0) + gd->env_valid = 1; + else if(tmp_env1->flags > tmp_env2->flags) + gd->env_valid = 1; + else if(tmp_env2->flags > tmp_env1->flags) + gd->env_valid = 2; + else /* flags are equal - almost impossible */ + gd->env_valid = 1; + + } + + free(env_ptr); + if(gd->env_valid == 1) { + env_ptr = tmp_env1; + free(tmp_env2); + } else { + env_ptr = tmp_env2; + free(tmp_env1); + } + +#endif /* ! ENV_IS_EMBEDDED */ +} +#else /* ! CFG_ENV_OFFSET_REDUND */ +/* + * The legacy NAND code saved the environment in the first NAND device i.e., + * nand_dev_desc + 0. This is also the behaviour using the new NAND code. + */ +void env_relocate_spec (void) +{ +#if !defined(ENV_IS_EMBEDDED) + ulong total; + int ret; + + total = CFG_ENV_SIZE; + ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); if (ret || total != CFG_ENV_SIZE) return use_default(); if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) return use_default(); #endif /* ! ENV_IS_EMBEDDED */ - } +#endif /* CFG_ENV_OFFSET_REDUND */ +#if !defined(ENV_IS_EMBEDDED) static void use_default() { - DECLARE_GLOBAL_DATA_PTR; - puts ("*** Warning - bad CRC or NAND, using default environment\n\n"); - if (default_environment_size > CFG_ENV_SIZE){ + if (default_environment_size > CFG_ENV_SIZE){ puts ("*** Error - default environment is too large\n\n"); return; } @@ -163,8 +300,9 @@ static void use_default() default_environment, default_environment_size); env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); - gd->env_valid = 1; + gd->env_valid = 1; } +#endif #endif /* CFG_ENV_IS_IN_NAND */ diff --git a/common/exports.c b/common/exports.c index 9858217..42406e0 100644 --- a/common/exports.c +++ b/common/exports.c @@ -28,6 +28,14 @@ void jumptable_init (void) gd->jt[XF_install_hdlr] = (void *) irq_install_handler; gd->jt[XF_free_hdlr] = (void *) irq_free_handler; #endif /* I386 || PPC */ +#ifdef CONFIG_MARVELL + gd->jt[XF_calloc] = (void *) calloc; + gd->jt[XF_realloc] = (void *) realloc; + gd->jt[XF_memalign] = (void *) memalign; +#ifndef MV_TINY_IMAGE + gd->jt[XF_mvGetRtcSec] = (void *) mvGetRtcSec; +#endif +#endif #if (CONFIG_COMMANDS & CFG_CMD_I2C) gd->jt[XF_i2c_write] = (void *) i2c_write; gd->jt[XF_i2c_read] = (void *) i2c_read; diff --git a/common/main.c b/common/main.c index f042f3a..68f947d 100644 --- a/common/main.c +++ b/common/main.c @@ -26,6 +26,10 @@ #include #include #include +#ifdef QNAPNAS +/* Richard Chen 20081219, QNAP for Recovery Button */ +#include +#endif /* QNAPNAS */ #ifdef CONFIG_MODEM_SUPPORT #include /* for free() prototype */ #endif @@ -218,10 +222,19 @@ static __inline__ int abortboot(int bootdelay) static int menukey = 0; #endif +#ifdef QNAPNAS +/* Richard Chen 20081217, QNAP for Recovery Button ****/ +static uint32_t recovery_button = 0; +#endif /* QNAPNAS */ + static __inline__ int abortboot(int bootdelay) { int abort = 0; +#ifdef QNAPNAS + /* Richard Chen 20081218, QNAP for recovery button */ + int recovery_state = 0; +#endif /* QNAPNAS */ #ifdef CONFIG_SILENT_CONSOLE { DECLARE_GLOBAL_DATA_PTR; @@ -253,7 +266,13 @@ static __inline__ int abortboot(int bootdelay) } } #endif - +#ifdef QNAPNAS + /* Richard Chen 20081218, QNAP for recovery button */ + if(QNAP_recovery_detect()) { + recovery_state = 1; + bootdelay=6; + } +#endif /* QNAPNAS */ while ((bootdelay > 0) && (!abort)) { int i; @@ -270,6 +289,23 @@ static __inline__ int abortboot(int bootdelay) # endif break; } + +#ifdef QNAPNAS + /* Richard Chen 20081218, QNAP for recovery button */ + if(QNAP_recovery_detect()) { + if(recovery_state == 0){ + recovery_state = 1; + bootdelay=6; + } + if(++recovery_button >= 500){ + abort = 1; + bootdelay = 0; + break; + } + } + else + recovery_button = 0; +#endif /* QNAPNAS */ udelay (10000); } @@ -278,6 +314,12 @@ static __inline__ int abortboot(int bootdelay) putc ('\n'); +#ifdef QNAPNAS + /* Richard Chen 20081217 Add for reset button */ + if(abort) { + printf("QNAP: Recovery Button pressed: %u\n", recovery_button); + } +#endif /* QNAPNAS */ #ifdef CONFIG_SILENT_CONSOLE { DECLARE_GLOBAL_DATA_PTR; @@ -412,6 +454,17 @@ void main_loop (void) debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : ""); +#if defined (CONFIG_MARVELL) && (defined(MV_88F6183) || defined(MV_88F6183L)) + /* 6183 UART work around - need incase uart pin's left unconnected */ + if (tstc()) + (void) getc(); /* consume input */ +#endif + +#ifdef QNAPNAS + /* Richard Chen 20081218, + * QNAP initiate the recovery facility */ + QNAP_recovery_init(); +#endif /* QNAPNAS */ if (bootdelay >= 0 && s && !abortboot (bootdelay)) { # ifdef CONFIG_AUTOBOOT_KEYED int prev = disable_ctrlc(1); /* disable Control C checking */ @@ -428,7 +481,22 @@ void main_loop (void) disable_ctrlc(prev); /* restore Control C checking */ # endif } + +#ifdef QNAPNAS + /* Richard Chen 20081218, + * QNAP initiate the recovery facility */ + if(recovery_button >= 500) { + int rc; + printf("Do Recovery ..\n"); + rc = QNAP_do_recovery(); + + if(!rc) { + s = "reset"; + run_command(s, 0); + } + } +#endif /* QNAPNAS */ # ifdef CONFIG_MENUKEY if (menukey == CONFIG_MENUKEY) { s = getenv("menucmd"); @@ -921,6 +989,19 @@ int run_command (const char *cmd, int flag) /* Extract arguments */ argc = parse_line (finaltoken, argv); + #ifdef CONFIG_MARVELL + if(enaMonExt()){ + if ((cmdtp = find_cmd(argv[0])) == NULL) { + int i; + argv[argc+1]= NULL; + for(i = argc; i > 0; i--){ + argv[i] = argv[i-1];} + argv[0] = "FSrun"; + argc++; + } + } + #endif + /* Look up command in command table */ if ((cmdtp = find_cmd(argv[0])) == NULL) { printf ("Unknown command '%s' - try 'help'\n", argv[0]); diff --git a/common/qnap_rcvr.c b/common/qnap_rcvr.c new file mode 100644 index 0000000..d843429 --- /dev/null +++ b/common/qnap_rcvr.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +#define mdelay(n) udelay((n) * 1000) + +#define ST_RCVR_MODE 0x01 +#define ST_DHCP_FAIL 0x02 +#define ST_TFTP_FAIL 0x04 +#define ST_RCVR_FAIL 0x08 +#define ST_RCVR_SUCCESS 0x10 + +static void rcvr_status_warn(int status) +{ + if(status & (ST_RCVR_MODE | ST_RCVR_SUCCESS)) { + /* set status red on */ + mvUartPutc(1,0x57); + /* beep two short buzzer */ + mvUartPutc(1,0x50); + mdelay(1000); + mvUartPutc(1,0x50); + printf("=> %s\n", + status & ST_RCVR_MODE ? "Enter Recovery Mode" : + "Going to restart ..."); + } + + if(status & (ST_DHCP_FAIL | ST_TFTP_FAIL | ST_RCVR_FAIL)) { + /* set status red flash */ + mvUartPutc(1,0x54); + /* beep one long buzzer */ + mvUartPutc(1,0x51); + mdelay(1000); + if(status & ST_TFTP_FAIL) { + /* beep one long buzzer */ + mvUartPutc(1,0x51); + mdelay(1000); + } + if(status & ST_TFTP_FAIL) { + /* beep one long buzzer */ + mvUartPutc(1,0x51); + mdelay(1000); + } + } +} + +int QNAP_do_recovery() +{ + char *s = NULL, + *tftpcmd = NULL, + *updcmd = NULL; + int rc = 0; + + rcvr_status_warn(ST_RCVR_MODE); + + s = "dhcp"; + rc = run_command(s, 0); + + if(rc > 0) { + tftpcmd = "tftpboot 0x800000 ${bootfile}"; + if((rc = run_command(tftpcmd, 0)) > 0) { + updcmd = "protect off bank 1; erase 0xf8200000 0xf8ffffff; cp.b 0xa00000 0xf8200000 e00000; protect on bank 1"; + rc = run_command(updcmd, 0); + if(rc > 0) { + printf("Recovery done successfully: %d\n", rc); + rcvr_status_warn(ST_RCVR_SUCCESS); + return 0; + } else { + printf("Recovery done error: %d\n", rc); + rcvr_status_warn(ST_RCVR_FAIL); + return -1; + } + } else { + printf("Tftp loading failed: %d\n", rc); + rcvr_status_warn(ST_TFTP_FAIL); + return -1; + } + } else { + printf("DHCP/BOOTP Failed, rc: %d\n", rc); + rcvr_status_warn(ST_DHCP_FAIL); + return -1; + } + return -1; +} + diff --git a/config.mk b/config.mk index d85ac36..dd5c2e4 100644 --- a/config.mk +++ b/config.mk @@ -118,7 +118,7 @@ OBJCFLAGS += --gap-fill=0xff gccincdir := $(shell $(CC) -print-file-name=include) -CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \ +CPPFLAGS += $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \ -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE) \ -I$(TOPDIR)/include \ -fno-builtin -ffreestanding -nostdinc -isystem \ @@ -183,7 +183,7 @@ export TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS %.s: %.S $(CPP) $(AFLAGS) -o $@ $(CURDIR)/$< %.o: %.S - $(CC) $(AFLAGS) -c -o $@ $(CURDIR)/$< + $(CC) $(AFLAGS) -c -o $@ $< %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/cpu/arm926ejs/Makefile b/cpu/arm926ejs/Makefile index 203278e..eff665c 100644 --- a/cpu/arm926ejs/Makefile +++ b/cpu/arm926ejs/Makefile @@ -22,6 +22,7 @@ # include $(TOPDIR)/config.mk +include $(TOPDIR)/board/mv_feroceon/$(BOARD)/mvRules.mk LIB = lib$(CPU).a diff --git a/cpu/arm926ejs/config.mk b/cpu/arm926ejs/config.mk index 8db4adb..1e6e113 100644 --- a/cpu/arm926ejs/config.mk +++ b/cpu/arm926ejs/config.mk @@ -21,14 +21,19 @@ # MA 02111-1307 USA # -PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ - -msoft-float -PLATFORM_CPPFLAGS += -march=armv4 -# ========================================================================= -# -# Supply options according to compiler version -# -# ========================================================================= -PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) -PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) +ifeq ($(CROSS_COMPILE),arm-linux-) + +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -mshort-load-bytes -msoft-float + +PLATFORM_CPPFLAGS += -mapcs-32 -march=armv5 + +else + +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -msoft-float + +PLATFORM_CPPFLAGS += -march=armv5t + +endif diff --git a/cpu/arm926ejs/cpu.c b/cpu/arm926ejs/cpu.c index f57c5a5..b7956d9 100644 --- a/cpu/arm926ejs/cpu.c +++ b/cpu/arm926ejs/cpu.c @@ -28,7 +28,6 @@ /* * CPU specific code */ - #include #include #include @@ -43,6 +42,7 @@ static unsigned long read_p15_c1 (void) : "=r" (value) : : "memory"); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); #ifdef MMU_DEBUG printf ("p15/c1 is = %08lx\n", value); @@ -112,20 +112,54 @@ int cleanup_before_linux (void) disable_interrupts (); +#ifdef CONFIG_MARVELL + /* turn off L2 Cache */ + asm ("mrc p15, 1, %0, c15, c1, 0":"=r" (i)); + i &= ~0x00400000; + asm ("mcr p15, 1, %0, c15, c1, 0": :"r" (i)); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); + /* Clean L2 Cache */ + asm ("mcr p15, 1, %0, c15, c9, 0": :"r" (i)); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); + /* Drain write buffer */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); +#endif + /* turn off I/D-cache */ asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); i &= ~(C1_DC | C1_IC); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + - /* flush I/D-cache */ - i = 0; - asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); + + /* Check if we are 926 or 946 */ + asm ("mrc p15, 0, %0, c0, c0, 0":"=r" (i)); + __asm__ __volatile__("nop;nop;nop;nop;nop;nop;nop"); + + + if (((i >> 4)&0xfff) == 0x926) + { + /* flush I/D-cache */ + i = 0; + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); + } + else + { + /* flush I/D-cache */ + i = 0; + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i)); + asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (i)); + } return (0); } int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { + extern void reset_cpu (ulong addr); + disable_interrupts (); reset_cpu (0); /*NOTREACHED*/ @@ -149,6 +183,21 @@ void icache_disable (void) cp_delay (); write_p15_c1 (reg & ~C1_IC); } +void dcache_disable (void) +{ + ulong reg; + + reg = read_p15_c1 (); + cp_delay (); + reg &= ~C1_DC; + write_p15_c1 (reg); + +} +int dcache_status (void) +{ + return (read_p15_c1 () & C1_DC) != 0; +} + int icache_status (void) { diff --git a/cpu/arm926ejs/interrupts.c b/cpu/arm926ejs/interrupts.c index 0457bff..24fda99 100644 --- a/cpu/arm926ejs/interrupts.c +++ b/cpu/arm926ejs/interrupts.c @@ -39,15 +39,23 @@ #include #include +extern void reset_cpu(ulong addr); #define TIMER_LOAD_VAL 0xffffffff /* macro to read the 32 bit timer */ #ifdef CONFIG_OMAP #define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+8)) #endif +#ifdef CONFIG_INTEGRATOR +#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+4)) +#endif #ifdef CONFIG_VERSATILE #define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+4)) #endif +#ifdef CONFIG_MARVELL +#include "cntmr/mvCntmr.h" +#define READ_TIMER (mvCntmrRead(UBOOT_CNTR)/(mvTclkGet()/1000)) +#endif #ifdef CONFIG_USE_IRQ /* enable IRQ interrupts */ @@ -202,7 +210,20 @@ int interrupt_init (void) val = MPUTIM_ST | MPUTIM_AR | MPUTIM_CLOCK_ENABLE | (CFG_PVT << MPUTIM_PTV_BIT); *((int32_t *) (CFG_TIMERBASE + CNTL_TIMER)) = val; #endif /* CONFIG_OMAP */ +#ifdef CONFIG_INTEGRATOR + /* Load timer with initial value */ + *(volatile ulong *)(CFG_TIMERBASE + 0) = TIMER_LOAD_VAL; + /* Set timer to be enabled, free-running, no interrupts, 256 divider */ + *(volatile ulong *)(CFG_TIMERBASE + 8) = 0x8C; +#endif /* CONFIG_INTEGRATOR */ +#ifdef CONFIG_MARVELL + /* init the counter */ + MV_CNTMR_CTRL cntmr; + cntmr.enable = 1; + cntmr.autoEnable = 1; + mvCntmrStart(UBOOT_CNTR, TIMER_LOAD_VAL, &cntmr); +#endif /* #ifdef CONFIG_MARVELL */ #ifdef CONFIG_VERSATILE *(volatile ulong *)(CFG_TIMERBASE + 0) = CFG_TIMER_RELOAD; /* TimerLoad */ *(volatile ulong *)(CFG_TIMERBASE + 4) = CFG_TIMER_RELOAD; /* TimerValue */ @@ -238,8 +259,11 @@ void set_timer (ulong t) void udelay (unsigned long usec) { ulong tmo, tmp; - - if(usec >= 1000){ /* if "big" number, spread normalization to seconds */ + if(usec >= 1000000){ /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000000; /* start to normalize for usec to ticks per sec */ + tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ + + }else if(usec >= 1000){ /* if "big" number, spread normalization to seconds */ tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ tmo /= 1000; /* finish normalize. */ @@ -278,7 +302,11 @@ ulong get_timer_masked (void) * (TLV-now) amount of time after passing though -1 * nts = new "advancing time stamp"...it could also roll and cause problems. */ +#ifdef CONFIG_MARVELL + timestamp += lastdec + (TIMER_LOAD_VAL/(mvTclkGet()/1000))- now; +#else timestamp += lastdec + TIMER_LOAD_VAL - now; +#endif } lastdec = now; diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index fc6b20b..c0e751f 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -3,10 +3,10 @@ * * Copyright (c) 2003 Texas Instruments * - * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * ----- Adapted for OMAP1610 from ARM925t code ------ * - * Copyright (c) 2001 Marius Gröger - * Copyright (c) 2002 Alex Züpke + * Copyright (c) 2001 Marius Gröger + * Copyright (c) 2002 Alex Züpke * Copyright (c) 2002 Gary Jennejohn * Copyright (c) 2003 Richard Woodruff * Copyright (c) 2003 Kshitij @@ -90,7 +90,7 @@ _fiq: * ************************************************************************* */ - +.globl _TEXT_BASE _TEXT_BASE: .word TEXT_BASE @@ -144,6 +144,15 @@ reset: #endif #ifndef CONFIG_SKIP_RELOCATE_UBOOT +#if defined(CONFIG_MARVELL) && defined(MV78200) + mov r0, #0 + mrc p15, 1, r0, c15, c1, 0 + /* Check if we are CPU0 or CPU1 */ + and r0, r0, #0x4000 + cmp r0, #0x4000 + beq slave_cpu_relocate +#endif + relocate: /* relocate U-Boot to RAM */ adr r0, _start /* r0 <- current position of code */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ @@ -165,7 +174,9 @@ copy_loop: /* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ +#ifndef CONFIG_MARVELL sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ +#endif sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) @@ -184,6 +195,19 @@ clbss_l:str r2, [r0] /* clear loop... */ ldr pc, _start_armboot +#if defined(CONFIG_MARVELL) && defined(MV78200) +/* Dummy relocate code for slave cpu + Create new stack +*/ +slave_cpu_relocate: + /* Set up the stack */ + ldr r0, _TEXT_BASE /* stack from uboot base (6MB) - first CPU (2MB)*/ + sub r0, r0, #CONFIG_STACKSIZE + sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ + sub sp, r0, #12 /* leave 3 words for abort-stack */ + ldr pc, _start_armboot +#endif + _start_armboot: .word start_armboot @@ -201,6 +225,17 @@ _start_armboot: cpu_init_crit: + + /* Check if we are 926 or 946 */ + mrc p15, 0, r0, c0, c0, 0 + mov r0, r0, LSR #4 + ldr r1, =0xfff + and r0, r0, r1 + ldr r1, =0x946 + cmp r0, r1 + beq cpu_946 + +cpu_926: /* * flush v4 I/D caches */ @@ -208,14 +243,30 @@ cpu_init_crit: mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + b cpu_continue + + +cpu_946: + + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 /* invalidate v4 I-cache */ + mcr p15, 0, r0, c7, c6, 0 /* flush D-Cache */ + + + + + +cpu_continue: + /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 - bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ - bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ + bic r0, r0, #0x00000007 /* 2:0 (CAM) */ orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ - orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ mcr p15, 0, r0, c1, c0, 0 /* @@ -225,6 +276,69 @@ cpu_init_crit: bl lowlevel_init /* go setup pll,mux,memory */ mov lr, ip /* restore link */ mov pc, lr /* back to my caller */ +/* + ************************************************************************* + * + * Flush DCache + * + ************************************************************************* + */ + +.globl _dcache_index_max +_dcache_index_max: + .word 0x0 + +.globl _dcache_index_inc +_dcache_index_inc: + .word 0x0 + +.globl _dcache_set_max +_dcache_set_max: + .word 0x0 + +.globl _dcache_set_index +_dcache_set_index: + .word 0x0 + + +#define s_max r0 +#define s_inc r1 +#define i_max r2 +#define i_inc r3 + +.globl cpu_dcache_flush_all +cpu_dcache_flush_all: + stmdb sp!, {r0-r3,ip} + + ldr i_max, _dcache_index_max + ldr i_inc, _dcache_index_inc + ldr s_max, _dcache_set_max + ldr s_inc, _dcache_set_index + +Lnext_set_inv: + orr ip, s_max, i_max +Lnext_index_inv: + mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */ + sub ip, ip, i_inc + tst ip, i_max /* Index 0 is last one */ + bne Lnext_index_inv /* Next index */ + mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */ + subs s_max, s_max, s_inc + bpl Lnext_set_inv /* Next set */ + ldmia sp!, {r0-r3,ip} + + mov pc, lr /* back to my caller */ + +.globl cpu_icache_flush_invalidate_all +cpu_icache_flush_invalidate_all: + stmdb sp!, {r0} + + ldr r0,=0 + mcr p15, 0, r0, c7, c5, 0 /* Flush Invalidate D and I caches */ + ldmia sp!, {r0} + + mov pc, lr /* back to my caller */ + /* ************************************************************************* * @@ -272,7 +386,11 @@ cpu_init_crit: stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 ldr r2, _armboot_start - sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) +#ifndef CONFIG_MARVELL + sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) +#else + sub r2, r2, #CONFIG_STACKSIZE +#endif sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack @ get values for "aborted" pc and cpsr (into parm regs) ldmia r2, {r2 - r3} @@ -306,7 +424,11 @@ cpu_init_crit: .macro get_bad_stack ldr r13, _armboot_start @ setup our mode stack - sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) +#ifndef CONFIG_MARVELL + sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) +#else + sub r13, r13, #CONFIG_STACKSIZE +#endif sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack str lr, [r13] @ save caller lr in position 0 of saved stack @@ -315,6 +437,9 @@ cpu_init_crit: mov r13, #MODE_SVC @ prepare SVC-Mode @ msr spsr_c, r13 msr spsr, r13 @ switch modes, make sure moves will execute +#ifdef CONFIG_MARVELL + ldr r13, _TEXT_BASE +#endif mov lr, pc @ capture return pc movs pc, lr @ jump to next instruction & switch modes. .endm @@ -393,13 +518,15 @@ fiq: #endif -# ifdef CONFIG_INTEGRATOR +#ifdef CONFIG_INTEGRATOR /* Satisfied by Integrator routine (AP or CP) */ #else .align 5 + +#ifndef CONFIG_MARVELL .globl reset_cpu reset_cpu: ldr r1, rstctl1 /* get clkm1 reset ctl */ @@ -412,5 +539,5 @@ _loop_forever: rstctl1: .word 0xfffece10 - +#endif /* CONFIG_MARVELL */ #endif /* #ifdef CONFIG_INTEGRATOR */ diff --git a/create_all_images.sh b/create_all_images.sh new file mode 100644 index 0000000..1ce07a6 --- /dev/null +++ b/create_all_images.sh @@ -0,0 +1,132 @@ +cd .. +mkdir images +cd images +mkdir DB-6281A-BP +mkdir DB-6192A-BP +mkdir RD-6281A +mkdir RD-6192A +cd DB-6281A-BP +mkdir LE +mkdir BE +cd LE +mkdir NAND +mkdir SPI +cd ../BE +mkdir NAND +mkdir SPI +cd ../../DB-6192A-BP +mkdir LE +mkdir BE +cd LE +mkdir NAND +mkdir SPI +cd ../BE +mkdir NAND +mkdir SPI +cd ../../RD-6281A +mkdir LE +mkdir BE +cd LE +mkdir NAND +mkdir SPI +cd ../BE +mkdir NAND +mkdir SPI +cd ../../RD-6192A +mkdir LE +mkdir BE +cd LE +mkdir SPI +cd ../BE +mkdir SPI +cd ../../../u-boot-3.4.* + +make mrproper +make db88f6281abp_config LE=1 NBOOT=1 +make -s +cp u-boot-db88f6281abp.bin ../images/DB-6281A-BP/LE/NAND/ +cp u-boot-db88f6281abp_400_nand.bin ../images/DB-6281A-BP/LE/NAND/ +cp u-boot-db88f6281abp_400_uart.bin ../images/DB-6281A-BP/LE/NAND/ + +make mrproper +make db88f6281abp_config LE=1 SPIBOOT=1 +make -s +cp u-boot-db88f6281abp.bin ../images/DB-6281A-BP/LE/SPI +cp u-boot-db88f6281abp_400_flash.bin ../images/DB-6281A-BP/LE/SPI +cp u-boot-db88f6281abp_400_uart.bin ../images/DB-6281A-BP/LE/SPI +make mrproper +make db88f6281abp_config BE=1 NBOOT=1 +make -s +cp u-boot-db88f6281abp.bin ../images/DB-6281A-BP/BE/NAND +cp u-boot-db88f6281abp_400_nand.bin ../images/DB-6281A-BP/BE/NAND +cp u-boot-db88f6281abp_400_uart.bin ../images/DB-6281A-BP/BE/NAND +make mrproper +make db88f6281abp_config BE=1 SPIBOOT=1 +make -s +cp u-boot-db88f6281abp.bin ../images/DB-6281A-BP/BE/SPI +cp u-boot-db88f6281abp_400_flash.bin ../images/DB-6281A-BP/BE/SPI +cp u-boot-db88f6281abp_400_uart.bin ../images/DB-6281A-BP/BE/SPI + +make mrproper +make db88f6192abp_config LE=1 NBOOT=1 +make -s +cp u-boot-db88f6192abp.bin ../images/DB-6192A-BP/LE/NAND +cp u-boot-db88f6192abp_200db_nand.bin ../images/DB-6192A-BP/LE/NAND +cp u-boot-db88f6192abp_200db_uart.bin ../images/DB-6192A-BP/LE/NAND +make mrproper +make db88f6192abp_config LE=1 SPIBOOT=1 +make -s +cp u-boot-db88f6192abp.bin ../images/DB-6192A-BP/LE/SPI +cp u-boot-db88f6192abp_200db_flash.bin ../images/DB-6192A-BP/LE/SPI +cp u-boot-db88f6192abp_200db_uart.bin ../images/DB-6192A-BP/LE/SPI +make mrproper +make db88f6192abp_config BE=1 NBOOT=1 +make -s +cp u-boot-db88f6192abp.bin ../images/DB-6192A-BP/BE/NAND +cp u-boot-db88f6192abp_200db_nand.bin ../images/DB-6192A-BP/BE/NAND +cp u-boot-db88f6192abp_200db_uart.bin ../images/DB-6192A-BP/BE/NAND +make mrproper +make db88f6192abp_config BE=1 SPIBOOT=1 +make -s +cp u-boot-db88f6192abp.bin ../images/DB-6192A-BP/BE/SPI +cp u-boot-db88f6192abp_200db_flash.bin ../images/DB-6192A-BP/BE/SPI +cp u-boot-db88f6192abp_200db_uart.bin ../images/DB-6192A-BP/BE/SPI + +make mrproper +make rd88f6281a_config LE=1 NBOOT=1 +make -s +cp u-boot-rd88f6281a.bin ../images/RD-6281A/LE/NAND +cp u-boot-rd88f6281a_400_nand.bin ../images/RD-6281A/LE/NAND +cp u-boot-rd88f6281a_400_uart.bin ../images/RD-6281A/LE/NAND +make mrproper +make rd88f6281a_config LE=1 SPIBOOT=1 +make -s +cp u-boot-rd88f6281a.bin ../images/RD-6281A/LE/SPI +cp u-boot-rd88f6281a_400_flash.bin ../images/RD-6281A/LE/SPI +cp u-boot-rd88f6281a_400_uart.bin ../images/RD-6281A/LE/SPI +make mrproper +make rd88f6281a_config BE=1 NBOOT=1 +make -s +cp u-boot-rd88f6281a.bin ../images/RD-6281A/BE/NAND +cp u-boot-rd88f6281a_400_nand.bin ../images/RD-6281A/BE/NAND +cp u-boot-rd88f6281a_400_uart.bin ../images/RD-6281A/BE/NAND +make mrproper +make rd88f6281a_config BE=1 SPIBOOT=1 +make -s +cp u-boot-rd88f6281a.bin ../images/RD-6281A/BE/SPI +cp u-boot-rd88f6281a_400_flash.bin ../images/RD-6281A/BE/SPI +cp u-boot-rd88f6281a_400_uart.bin ../images/RD-6281A/BE/SPI + +make mrproper +make mrproper +make rd88f6192a_config LE=1 SPIBOOT=1 +make -s +cp u-boot-rd88f6192a.bin ../images/RD-6192A/LE/SPI +cp u-boot-rd88f6192a_200rd_flash.bin ../images/RD-6192A/LE/SPI +cp u-boot-rd88f6192a_200rd_uart.bin ../images/RD-6192A/LE/SPI +make mrproper +make rd88f6192a_config BE=1 SPIBOOT=1 +make -s +cp u-boot-rd88f6192a.bin ../images/RD-6192A/BE/SPI +cp u-boot-rd88f6192a_200rd_flash.bin ../images/RD-6192A/BE/SPI +cp u-boot-rd88f6192a_200rd_uart.bin ../images/RD-6192A/BE/SPI diff --git a/disk/part_dos.c b/disk/part_dos.c index 133ee79..2cdfa40 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "part_dos.h" #if ((CONFIG_COMMANDS & CFG_CMD_IDE) || \ @@ -45,6 +46,7 @@ */ static inline int le32_to_int(unsigned char *le32) { + return ((le32[3] << 24) + (le32[2] << 16) + (le32[1] << 8) + @@ -71,8 +73,8 @@ static void print_one_part (dos_partition_t *p, int ext_part_sector, int part_nu static int test_block_type(unsigned char *buffer) { - if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) || - (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) { + if((buffer[DOS_PART_MAGIC_OFFSET + 0] != MBR_MAGIC_BYTE0) || + (buffer[DOS_PART_MAGIC_OFFSET + 1] != MBR_MAGIC_BYTE1) ) { return (-1); } /* no DOS Signature at all */ if(strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],"FAT",3)==0) @@ -86,8 +88,8 @@ int test_part_dos (block_dev_desc_t *dev_desc) unsigned char buffer[DEFAULT_SECTOR_SIZE]; if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) buffer) != 1) || - (buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) || - (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) { + (buffer[DOS_PART_MAGIC_OFFSET + 0] != MBR_MAGIC_BYTE0) || + (buffer[DOS_PART_MAGIC_OFFSET + 1] != MBR_MAGIC_BYTE1) ) { return (-1); } return (0); @@ -171,8 +173,8 @@ static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part dev_desc->dev, ext_part_sector); return -1; } - if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 || - buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) { + if (buffer[DOS_PART_MAGIC_OFFSET] != MBR_MAGIC_BYTE0 || + buffer[DOS_PART_MAGIC_OFFSET + 1] != MBR_MAGIC_BYTE1) { printf ("bad MBR sector signature 0x%02x%02x\n", buffer[DOS_PART_MAGIC_OFFSET], buffer[DOS_PART_MAGIC_OFFSET + 1]); @@ -189,6 +191,7 @@ static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part if ((pt->sys_ind != 0) && (part_num == which_part) && (is_extended(pt->sys_ind) == 0)) { + info->boot_ind = (pt->boot_ind == 0x80) ? 1 : 0; info->blksz = 512; info->start = ext_part_sector + le32_to_int (pt->start4); info->size = le32_to_int (pt->size4); diff --git a/disk/part_dos.h b/disk/part_dos.h index ac93f20..b35b5c0 100644 --- a/disk/part_dos.h +++ b/disk/part_dos.h @@ -39,6 +39,10 @@ #define DOS_MBR 0 #define DOS_PBR 1 +#define MBR_MAGIC_BYTE0 0x55 +#define MBR_MAGIC_BYTE1 0xAA + + typedef struct dos_partition { unsigned char boot_ind; /* 0x80 - active */ unsigned char head; /* starting head */ diff --git a/dramregs_200db_A.txt b/dramregs_200db_A.txt new file mode 100644 index 0000000..4587e43 --- /dev/null +++ b/dramregs_200db_A.txt @@ -0,0 +1,23 @@ +0xFFD100e0 0x1b1b1b9b +0xFFD20134 0xbbbbbbbb +0xFFD20138 0x00bbbbbb +0xFFD01400 0x43000618 +0xFFD01404 0x35143000 +0xFFD01408 0x11012227 +0xFFD0140C 0x00000819 +0xFFD01410 0x000000cc +0xFFD01414 0x00000000 +0xFFD01418 0x00000000 +0xFFD0141C 0x00000632 +0xFFD01420 0x00000042 +0xFFD01424 0x0000F0FF +0xFFD01504 0x0FFFFFF1 +0xFFD01508 0x10000000 +0xFFD0150C 0x0FFFFFF5 +0xFFD01514 0x00000000 +0xFFD0151C 0x00000000 +0xFFD01494 0x003C0000 +0xFFD01498 0x00000000 +0xFFD0149C 0x0000E80F +0xFFD01480 0x00000001 +0x0 0x0 diff --git a/dramregs_200rd_A.txt b/dramregs_200rd_A.txt new file mode 100644 index 0000000..2fd642e --- /dev/null +++ b/dramregs_200rd_A.txt @@ -0,0 +1,23 @@ +0xFFD100e0 0x1b1b1b9b +0xFFD20134 0xbbbbbbbb +0xFFD20138 0x00bbbbbb +0xFFD01400 0x43000618 +0xFFD01404 0x35143000 +0xFFD01408 0x11012227 +0xFFD0140C 0x00000819 +0xFFD01410 0x000000cd +0xFFD01414 0x00000000 +0xFFD01418 0x00000000 +0xFFD0141C 0x00000632 +0xFFD01420 0x00000042 +0xFFD01424 0x0000F0FF +0xFFD01504 0x0FFFFFF1 +0xFFD01508 0x10000000 +0xFFD0150C 0x0FFFFFF5 +0xFFD01514 0x00000000 +0xFFD0151C 0x00000000 +0xFFD01494 0x003C0000 +0xFFD01498 0x00000000 +0xFFD0149C 0x0000E80F +0xFFD01480 0x00000001 +0x0 0x0 diff --git a/dramregs_400_A.txt b/dramregs_400_A.txt new file mode 100644 index 0000000..615888e --- /dev/null +++ b/dramregs_400_A.txt @@ -0,0 +1,26 @@ +0xFFD100e0 0x1b1b1b9b +0xFFD20134 0xbbbbbbbb +0xFFD20138 0x00bbbbbb +0xFFD01400 0x43000c30 +0xFFD01404 0x39543000 +0xFFD01408 0x22125451 +0xFFD0140C 0x00000833 +0xFFD01410 0x000000cc +0xFFD01414 0x00000000 +0xFFD01418 0x00000000 +0xFFD0141C 0x00000C52 +0xFFD01420 0x00000042 +0xFFD01424 0x0000F1FF +0xFFD01428 0x00085520 +0xFFD0147C 0x00008552 +0xFFD01504 0x0FFFFFF1 +0xFFD01508 0x10000000 +0xFFD0150C 0x0FFFFFF5 +0xFFD01514 0x00000000 +0xFFD0151C 0x00000000 +0xFFD01494 0x003C0000 +0xFFD01498 0x00000000 +0xFFD0149C 0x0000F80F +0xFFD01480 0x00000001 +0x0 0x0 + diff --git a/drivers/Makefile b/drivers/Makefile index e6176ed..549182a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -38,13 +38,13 @@ OBJS = 3c589.o 5701rls.o ali512x.o \ omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o \ pcnet.o plb2800_eth.o \ ps2ser.o ps2mult.o pc_keyb.o \ - rtl8019.o rtl8139.o rtl8169.o \ + rtl8029.o rtl8019.o rtl8139.o rtl8169.o \ s3c4510b_eth.o s3c4510b_uart.o \ sed13806.o sed156x.o \ serial.o serial_max3100.o \ serial_pl010.o serial_pl011.o serial_xuartlite.o \ sl811_usb.o sm501.o smc91111.o smiLynxEM.o \ - status_led.o sym53c8xx.o \ + status_led.o sym53c8xx.o ahci.o\ ti_pci1410a.o tigon3.o tsec.o \ usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \ videomodes.o w83c553f.o \ diff --git a/drivers/ahci.c b/drivers/ahci.c new file mode 100644 index 0000000..fb7867f --- /dev/null +++ b/drivers/ahci.c @@ -0,0 +1,760 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * Author: Jason Jin + * Zhang Wei + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + * + * with the reference on libata and ahci drvier in kernel + * + */ +/* #define DEBUG */ +#include + +#ifdef CONFIG_SCSI_AHCI + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ahci_probe_ent *probe_ent = NULL; +hd_driveid_t *ataid[AHCI_MAX_PORTS]; + +#define writel_with_flush(a,b) do { writel(a,b); readl(b); } while (0) + + +static inline u32 ahci_port_base(u32 base, u32 port) +{ + return base + 0x100 + (port * 0x80); +} + + +static void ahci_setup_port(struct ahci_ioports *port, unsigned long base, + unsigned int port_idx) +{ + base = ahci_port_base(base, port_idx); + + port->cmd_addr = base; + port->scr_addr = base + PORT_SCR; +} + + +#define msleep(a) udelay(a * 1000) +#define ssleep(a) msleep(a * 1000) + +static int waiting_for_cmd_completed(volatile u8 *offset, + int timeout_msec, + u32 sign) +{ + int i; + u32 status; + + for (i = 0; ((status = readl(offset)) & sign) && i < timeout_msec; i++) + msleep(1); + + return (i < timeout_msec) ? 0 : -1; +} + + +static int ahci_host_init(struct ahci_probe_ent *probe_ent) +{ + pci_dev_t pdev = probe_ent->dev; + volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base; + u32 tmp, cap_save; + u16 tmp16; + int i, j; + volatile u8 *port_mmio; + unsigned short vendor; + + cap_save = readl(mmio + HOST_CAP); + cap_save &= ((1 << 28) | (1 << 17)); + cap_save |= (1 << 27); + + /* global controller reset */ + tmp = readl(mmio + HOST_CTL); + if ((tmp & HOST_RESET) == 0) + writel_with_flush(tmp | HOST_RESET, mmio + HOST_CTL); + + /* reset must complete within 1 second, or + * the hardware should be considered fried. + */ + ssleep(1); + + tmp = readl(mmio + HOST_CTL); + if (tmp & HOST_RESET) { + debug("controller reset failed (0x%x) addr (0x%x) \n", tmp, (mmio + HOST_CTL)); + return -1; + } + + writel_with_flush(HOST_AHCI_EN, mmio + HOST_CTL); + writel(cap_save, mmio + HOST_CAP); + writel_with_flush(0xf, mmio + HOST_PORTS_IMPL); + + pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor); + + if (vendor == PCI_VENDOR_ID_INTEL) { + u16 tmp16; + pci_read_config_word(pdev, 0x92, &tmp16); + tmp16 |= 0xf; + pci_write_config_word(pdev, 0x92, tmp16); + } + + probe_ent->cap = readl(mmio + HOST_CAP); + probe_ent->port_map = readl(mmio + HOST_PORTS_IMPL); + probe_ent->n_ports = (probe_ent->cap & 0x1f) + 1; + + debug("cap 0x%x port_map 0x%x n_ports %d\n", + probe_ent->cap, probe_ent->port_map, probe_ent->n_ports); + + for (i = 0; i < probe_ent->n_ports; i++) { + probe_ent->port[i].port_mmio = ahci_port_base((u32) mmio, i); + port_mmio = (u8 *) probe_ent->port[i].port_mmio; + ahci_setup_port(&probe_ent->port[i], (unsigned long)mmio, i); + + /* make sure port is not active */ + tmp = readl(port_mmio + PORT_CMD); + if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | + PORT_CMD_FIS_RX | PORT_CMD_START)) { + tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | + PORT_CMD_FIS_RX | PORT_CMD_START); + writel_with_flush(tmp, port_mmio + PORT_CMD); + + /* spec says 500 msecs for each bit, so + * this is slightly incorrect. + */ + msleep(500); + } + + /* writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD); Yotam */ + + j = 0; + while (j < 100) { + msleep(10); + tmp = readl(port_mmio + PORT_SCR_STAT); + if ((tmp & 0xf) == 0x3) + break; + j++; + } + + tmp = readl(port_mmio + PORT_SCR_ERR); + debug("PORT_SCR_ERR 0x%x\n", tmp); + writel(tmp, port_mmio + PORT_SCR_ERR); + + /* ack any pending irq events for this port */ + tmp = readl(port_mmio + PORT_IRQ_STAT); + debug("PORT_IRQ_STAT 0x%x\n", tmp); + if (tmp) + writel(tmp, port_mmio + PORT_IRQ_STAT); + + writel(1 << i, mmio + HOST_IRQ_STAT); + + /* set irq mask (enables interrupts) */ + /* writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); yotam */ + + /*register linkup ports */ + tmp = readl(port_mmio + PORT_SCR_STAT); + debug("Port %d status: 0x%x\n", i, tmp); + if ((tmp & 0xf) == 0x03) + probe_ent->link_port_map |= (0x01 << i); + } + + tmp = readl(mmio + HOST_CTL); + debug("HOST_CTL 0x%x\n", tmp); + /* writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); yotam */ + tmp = readl(mmio + HOST_CTL); + debug("HOST_CTL 0x%x\n", tmp); + + pci_read_config_word(pdev, PCI_COMMAND, &tmp16); + tmp |= PCI_COMMAND_MASTER; + pci_write_config_word(pdev, PCI_COMMAND, tmp16); + + return 0; +} + + +static void ahci_print_info(struct ahci_probe_ent *probe_ent) +{ + pci_dev_t pdev = probe_ent->dev; + volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base; + u32 vers, cap, impl, speed; + const char *speed_s; + u16 cc; + const char *scc_s; + + vers = readl(mmio + HOST_VERSION); + cap = probe_ent->cap; + impl = probe_ent->port_map; + + speed = (cap >> 20) & 0xf; + if (speed == 1) + speed_s = "1.5"; + else if (speed == 2) + speed_s = "3"; + else + speed_s = "?"; + + pci_read_config_word(pdev, 0x0a, &cc); + if (cc == 0x0101) + scc_s = "IDE"; + else if (cc == 0x0106) + scc_s = "SATA"; + else if (cc == 0x0104) + scc_s = "RAID"; + else + scc_s = "unknown"; + + printf("AHCI %02x%02x.%02x%02x " + "%u slots %u ports %s Gbps 0x%x impl %s mode\n", + (vers >> 24) & 0xff, + (vers >> 16) & 0xff, + (vers >> 8) & 0xff, + vers & 0xff, + ((cap >> 8) & 0x1f) + 1, (cap & 0x1f) + 1, speed_s, impl, scc_s); + + printf("flags: " + "%s%s%s%s%s%s" + "%s%s%s%s%s%s%s\n", + cap & (1 << 31) ? "64bit " : "", + cap & (1 << 30) ? "ncq " : "", + cap & (1 << 28) ? "ilck " : "", + cap & (1 << 27) ? "stag " : "", + cap & (1 << 26) ? "pm " : "", + cap & (1 << 25) ? "led " : "", + cap & (1 << 24) ? "clo " : "", + cap & (1 << 19) ? "nz " : "", + cap & (1 << 18) ? "only " : "", + cap & (1 << 17) ? "pmp " : "", + cap & (1 << 15) ? "pio " : "", + cap & (1 << 14) ? "slum " : "", + cap & (1 << 13) ? "part " : ""); +} + +#if (defined(CONFIG_MARVELL) && defined(__ARM__)) +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)pdev, a) +#define phys_to_bus(a) (a) +#else +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)pdev, a) +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)pdev, a) +#endif + +static int ahci_init_one(pci_dev_t pdev) +{ + u32 iobase, vendor, device, rmw; + int rc; + + memset((void *)ataid, 0, sizeof(hd_driveid_t *) * AHCI_MAX_PORTS); + + probe_ent = malloc(sizeof(probe_ent)); + memset(probe_ent, 0, sizeof(probe_ent)); + probe_ent->dev = pdev; + + pci_read_config_dword(pdev, AHCI_PCI_BAR, &iobase); + iobase &= ~0xf; + + probe_ent->host_flags = ATA_FLAG_SATA + | ATA_FLAG_NO_LEGACY + | ATA_FLAG_MMIO + | ATA_FLAG_PIO_DMA + | ATA_FLAG_NO_ATAPI; + probe_ent->pio_mask = 0x1f; + probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ + + probe_ent->mmio_base = bus_to_phys (iobase); + + /* Take from kernel: + * JMicron-specific fixup: + * make sure we're in AHCI mode + */ + pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor); + if (vendor == 0x197b) + pci_write_config_byte(pdev, 0x41, 0xa1); + + /* Take from kernel: + * Marvell specific fixup: + * Change SATA phy to scontroller mode + */ +/* + pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor); + printf ("ahci_match : vendor 0x%x\n",vendor); + if (vendor == 0x11ab) + { + pci_read_config_word(pdev, PCI_DEVICE_ID, &device); + device &= 0xffff; + printf ("ahci_match : device 0x%x\n",device); + + if ((device == 0x6121) || (device == 0x6145)) + { + printf ("ahci_match : Switching SATA phy to be controlled by Scontrol\n"); + pci_read_config_word(pdev, PCI_CB_SUBSYSTEM_VENDOR_ID, &rmw); + printf ("ahci_match addr 0x40 value 0x%x\n", rmw); +*/ +// rmw = rmw & 0xff3fffff; /* Clear bit 22 and 23 */ +/* printf ("ahci_match addr 0x40 value 0x%x\n", rmw); + pci_write_config_byte(pdev, PCI_CB_SUBSYSTEM_VENDOR_ID, rmw); + } + } +*/ + /* initialize adapter */ + rc = ahci_host_init(probe_ent); + if (rc) + goto err_out; + + ahci_print_info(probe_ent); + + return 0; + + err_out: + return rc; +} + + +#define MAX_DATA_BYTE_COUNT (4*1024*1024) + +static int ahci_fill_sg(u8 port, unsigned char *buf, int buf_len) +{ + struct ahci_ioports *pp = &(probe_ent->port[port]); + struct ahci_sg *ahci_sg = pp->cmd_tbl_sg; + u32 sg_count; + int i; + + sg_count = ((buf_len - 1) / MAX_DATA_BYTE_COUNT) + 1; + if (sg_count > AHCI_MAX_SG) { + printf("Error:Too much sg!\n"); + return -1; + } + + for (i = 0; i < sg_count; i++) { + ahci_sg->addr = + cpu_to_le32((u32) buf + i * MAX_DATA_BYTE_COUNT); + ahci_sg->addr_hi = 0; + ahci_sg->flags_size = cpu_to_le32(0x3fffff & + (buf_len < MAX_DATA_BYTE_COUNT + ? (buf_len - 1) + : (MAX_DATA_BYTE_COUNT - 1))); + ahci_sg++; + buf_len -= MAX_DATA_BYTE_COUNT; + } + + return sg_count; +} + + +static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts) +{ + pp->cmd_slot->opts = cpu_to_le32(opts); + pp->cmd_slot->status = 0; + pp->cmd_slot->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff); + pp->cmd_slot->tbl_addr_hi = 0; +} + + +static void ahci_set_feature(u8 port) +{ + struct ahci_ioports *pp = &(probe_ent->port[port]); + volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + u32 cmd_fis_len = 5; /* five dwords */ + u8 fis[20]; + + /*set feature */ + memset(fis, 0, 20); + fis[0] = 0x27; + fis[1] = 1 << 7; + fis[2] = ATA_CMD_SETF; + fis[3] = SETFEATURES_XFER; + fis[12] = __ilog2(probe_ent->udma_mask + 1) + 0x40 - 0x01; + + memcpy((unsigned char *)pp->cmd_tbl, fis, 20); + ahci_fill_cmd_slot(pp, cmd_fis_len); + writel(1, port_mmio + PORT_CMD_ISSUE); + readl(port_mmio + PORT_CMD_ISSUE); + + if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE, 150, 0x1)) { + printf("set feature error!\n"); + } +} + + +static int ahci_port_start(u8 port) +{ + struct ahci_ioports *pp = &(probe_ent->port[port]); + volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + u32 port_status; + u32 mem; + + debug("Enter start port: %d\n", port); + port_status = readl(port_mmio + PORT_SCR_STAT); + debug("Port %d status: %x\n", port, port_status); + if ((port_status & 0xf) != 0x03) { + printf("No Link on this port!\n"); + return -1; + } + + mem = (u32) malloc(AHCI_PORT_PRIV_DMA_SZ + 4096); + if (!mem) { + free(pp); + printf("No mem for table!\n"); + return -ENOMEM; + } + + mem = (mem + 0x800) & (~0x7ff); /* Aligned to 2048-bytes */ + memset((u8 *) mem, 0, AHCI_PORT_PRIV_DMA_SZ); + + /* + * First item in chunk of DMA memory: 32-slot command table, + * 32 bytes each in size + */ + pp->cmd_slot = (struct ahci_cmd_hdr *)mem; + debug("cmd_slot = 0x%x\n", pp->cmd_slot); + /* mem += (AHCI_CMD_SLOT_SZ + 224); */ + mem += 2048; + + /* + * Second item: Received-FIS area + */ + pp->rx_fis = mem; + /* mem += AHCI_RX_FIS_SZ; */ + mem += 1024; + + /* + * Third item: data area for storing a single command + * and its scatter-gather table + */ + pp->cmd_tbl = mem; + debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl); + + mem += AHCI_CMD_TBL_HDR; + pp->cmd_tbl_sg = (struct ahci_sg *)mem; + + writel_with_flush((u32) pp->cmd_slot, port_mmio + PORT_LST_ADDR); + + writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR); + +/* writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX | + PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP | + PORT_CMD_START, port_mmio + PORT_CMD); +*/ + writel_with_flush(PORT_CMD_FIS_RX | PORT_CMD_START | 0x20, port_mmio + PORT_CMD); + debug("Exit start port %d\n", port); + + return 0; +} + + +static int get_ahci_device_data(u8 port, u8 *fis, int fis_len, u8 *buf, + int buf_len) +{ + + struct ahci_ioports *pp = &(probe_ent->port[port]); + volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + u32 opts; + u32 port_status; + int sg_count; + int i; + + debug("Enter get_ahci_device_data: for port %d addr mmio 0x%x\n", port, port_mmio); + + if (port > probe_ent->n_ports) { + printf("Invaild port number %d\n", port); + return -1; + } + + port_status = readl(port_mmio + PORT_SCR_STAT); + if ((port_status & 0xf) != 0x03) { + debug("No Link on port %d!\n", port); + return -1; + } + + debug("Enter get_ahci_device_data: fis data\n"); + for (i=0; i < fis_len; i++) + { + debug("%p:%02x\n", &fis[i], fis[i]); + } + + memcpy((unsigned char *)pp->cmd_tbl, fis, fis_len); + + debug("Enter get_ahci_device_data: pp->cmd_tbl 0x%p \n",pp->cmd_tbl ); + for (i=0; i < fis_len; i++) + { + debug("%p:%02x\n", &(((unsigned char *)(pp->cmd_tbl))[i]), ((unsigned char *)(pp->cmd_tbl))[i]); + } + debug("Enter get_ahci_device_data: buf 0x%x buf_len 0x%x\n",buf,buf_len ); + sg_count = ahci_fill_sg(port, buf, buf_len); + opts = (fis_len >> 2) | (sg_count << 16); + ahci_fill_cmd_slot(pp, opts); + + writel_with_flush(1, port_mmio + PORT_CMD_ISSUE); + + if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE, 1500, 0x1)) { + printf("timeout exit!\n"); + return -1; + } + debug("get_ahci_device_data: %d byte transferred.\n", + pp->cmd_slot->status); + + return 0; +} + + +static char *ata_id_strcpy(u16 *target, u16 *src, int len) +{ + int i; + for (i = 0; i < len / 2; i++) + /* Swap 16bit for display - on memory this data is */ + /* in big endian */ + target[i] = __swab16(src[i]); + return (char *)target; +} + + +static void dump_ataid(hd_driveid_t *ataid) +{ + debug("(49)ataid->capability = 0x%x\n", ataid->capability); + debug("(53)ataid->field_valid =0x%x\n", ataid->field_valid); + debug("(60)ataid->lba_capacity =0x%x\n", ataid->lba_capacity); + debug("(63)ataid->dma_mword = 0x%x\n", ataid->dma_mword); + debug("(64)ataid->eide_pio_modes = 0x%x\n", ataid->eide_pio_modes); + debug("(75)ataid->queue_depth = 0x%x\n", ataid->queue_depth); + debug("(80)ataid->major_rev_num = 0x%x\n", ataid->major_rev_num); + debug("(81)ataid->minor_rev_num = 0x%x\n", ataid->minor_rev_num); + debug("(82)ataid->command_set_1 = 0x%x\n", ataid->command_set_1); + debug("(83)ataid->command_set_2 = 0x%x\n", ataid->command_set_2); + debug("(84)ataid->cfsse = 0x%x\n", ataid->cfsse); + debug("(85)ataid->cfs_enable_1 = 0x%x\n", ataid->cfs_enable_1); + debug("(86)ataid->cfs_enable_2 = 0x%x\n", ataid->cfs_enable_2); + debug("(87)ataid->csf_default = 0x%x\n", ataid->csf_default); + debug("(88)ataid->dma_ultra = 0x%x\n", ataid->dma_ultra); + debug("(93)ataid->hw_config = 0x%x\n", ataid->hw_config); +} + + +/* + * SCSI INQUIRY command operation. + */ +static int ata_scsiop_inquiry(ccb *pccb) +{ + u8 hdr[] = { + 0, + 0, + 0x5, /* claim SPC-3 version compatibility */ + 2, + 95 - 4, + }; + u8 fis[20]; + u8 *tmpid; + u8 port; + u16 i; + + /* Clean ccb data buffer */ + memset(pccb->pdata, 0, pccb->datalen); + + memcpy(pccb->pdata, hdr, sizeof(hdr)); + + if (pccb->datalen <= 35) + return 0; + + memset(fis, 0, 20); + /* Construct the FIS */ + fis[0] = 0x27; /* Host to device FIS. */ + fis[1] = 1 << 7; /* Command FIS. */ + fis[2] = ATA_CMD_IDENT; /* Command byte. */ + + /* Read id from sata */ + port = pccb->target; + if (!(tmpid = malloc(sizeof(hd_driveid_t)))) + return -ENOMEM; + + if (get_ahci_device_data(port, (u8 *) & fis, 20, + tmpid, sizeof(hd_driveid_t))) { + debug("scsi_ahci: SCSI inquiry command failure.\n"); + return -EIO; + } + + if (ataid[port]) + free(ataid[port]); + ataid[port] = (hd_driveid_t *) tmpid; + + short* tmp = (short *)tmpid; + + memcpy(&pccb->pdata[8], "ATA ", 8); + ata_id_strcpy((u16 *) &pccb->pdata[16], (u16 *)ataid[port]->model, 16); + ata_id_strcpy((u16 *) &pccb->pdata[32], (u16 *)ataid[port]->fw_rev, 4); + + dump_ataid(ataid[port]); + return 0; +} + + +/* + * SCSI READ10 command operation. + */ +static int ata_scsiop_read10(ccb * pccb) +{ + u64 lba = 0; + u32 len = 0; + u8 fis[20]; + + lba = (((u64) pccb->cmd[2]) << 24) | (((u64) pccb->cmd[3]) << 16) + | (((u64) pccb->cmd[4]) << 8) | ((u64) pccb->cmd[5]); + len = (((u32) pccb->cmd[7]) << 8) | ((u32) pccb->cmd[8]); + + /* For 10-byte and 16-byte SCSI R/W commands, transfer + * length 0 means transfer 0 block of data. + * However, for ATA R/W commands, sector count 0 means + * 256 or 65536 sectors, not 0 sectors as in SCSI. + * + * WARNING: one or two older ATA drives treat 0 as 0... + */ + if (!len) + return 0; + memset(fis, 0, 20); + + /* Construct the FIS */ + fis[0] = 0x27; /* Host to device FIS. */ + fis[1] = 1 << 7; /* Command FIS. */ + fis[2] = ATA_CMD_RD_DMA; /* Command byte. */ + + /* LBA address, only support LBA28 in this driver */ + fis[4] = pccb->cmd[5]; + fis[5] = pccb->cmd[4]; + fis[6] = pccb->cmd[3]; + fis[7] = (pccb->cmd[2] & 0x0f) | 0xe0; + + /* Sector Count */ + fis[12] = pccb->cmd[8]; + fis[13] = pccb->cmd[7]; + + /* Read from ahci */ + if (get_ahci_device_data(pccb->target, (u8 *) & fis, 20, + pccb->pdata, pccb->datalen)) { + debug("scsi_ahci: SCSI READ10 command failure.\n"); + return -EIO; + } + + return 0; +} + + +/* + * SCSI READ CAPACITY10 command operation. + */ +static int ata_scsiop_read_capacity10(ccb *pccb) +{ + u8 buf[8]; + + if (!ataid[pccb->target]) { + printf("scsi_ahci: SCSI READ CAPACITY10 command failure. " + "\tNo ATA info!\n" + "\tPlease run SCSI commmand INQUIRY firstly!\n"); + return -EPERM; + } + + memset(buf, 0, 8); + + /* Swap 32bit for display - on memory this data is */ + /* in little endian but this field in the buffer is in big endian format */ + *(u32 *) buf = __swab32(ataid[pccb->target]->lba_capacity); + + buf[6] = 512 >> 8; + buf[7] = 512 & 0xff; + + memcpy(pccb->pdata, buf, 8); + + return 0; +} + + +/* + * SCSI TEST UNIT READY command operation. + */ +static int ata_scsiop_test_unit_ready(ccb *pccb) +{ + return (ataid[pccb->target]) ? 0 : -EPERM; +} + + +int scsi_exec(ccb *pccb) +{ + int ret; + + switch (pccb->cmd[0]) { + case SCSI_READ10: + ret = ata_scsiop_read10(pccb); + break; + case SCSI_RD_CAPAC: + ret = ata_scsiop_read_capacity10(pccb); + break; + case SCSI_TST_U_RDY: + ret = ata_scsiop_test_unit_ready(pccb); + break; + case SCSI_INQUIRY: + ret = ata_scsiop_inquiry(pccb); + break; + default: + printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]); + return FALSE; + } + + if (ret) { + debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret); + return FALSE; + } + return TRUE; + +} + + +void scsi_low_level_init(int busdevfunc) +{ + int i; + u32 linkmap; + + ahci_init_one(busdevfunc); + + linkmap = probe_ent->link_port_map; + + for (i = 0; i < CFG_SCSI_MAX_SCSI_ID; i++) { + if (((linkmap >> i) & 0x01)) { + if (ahci_port_start((u8) i)) { + printf("Can not start port %d\n", i); + continue; + } + /* ahci_set_feature((u8) i); yotam */ + } + } +} + + +void scsi_bus_reset(void) +{ + /*Not implement*/ +} + + +void scsi_print_error(ccb * pccb) +{ + /*The ahci error info can be read in the ahci driver*/ +} +#endif diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index 4b7a110..f07c7e5 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -41,8 +41,9 @@ * */ + /* The DEBUG define must be before common to enable debugging */ -/* #define DEBUG */ +/* #define DEBUG */ #include #include @@ -61,14 +62,10 @@ * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet + * AMD CFI Specification, Release 2.0 December 1, 2001 + * AMD/Spansion Application Note: Migration from Single-byte to Three-byte + * Device IDs, Publication Number 25538 Revision A, November 8, 2001 * - * TODO - * - * Use Primary Extended Query table (PRI) and Alternate Algorithm Query - * Table (ALT) to determine if protection is available - * - * Add support for other command sets Use the PRI and ALT to determine command set - * Verify erase and program timeouts. */ #ifndef CFG_FLASH_BANKS_LIST @@ -104,6 +101,8 @@ #define AMD_CMD_ERASE_SECTOR 0x30 #define AMD_CMD_UNLOCK_START 0xAA #define AMD_CMD_UNLOCK_ACK 0x55 +#define AMD_CMD_WRITE_TO_BUFFER 0x25 +#define AMD_CMD_WRITE_BUFFER_CONFIRM 0x29 #define AMD_STATUS_TOGGLE 0x40 #define AMD_STATUS_ERROR 0x20 @@ -111,9 +110,14 @@ #define AMD_ADDR_START 0x555 #define AMD_ADDR_ACK 0x2AA +#define FLASH_OFFSET_MANUFACTURER_ID 0x00 +#define FLASH_OFFSET_DEVICE_ID 0x01 +#define FLASH_OFFSET_DEVICE_ID2 0x0E +#define FLASH_OFFSET_DEVICE_ID3 0x0F #define FLASH_OFFSET_CFI 0x55 #define FLASH_OFFSET_CFI_RESP 0x10 #define FLASH_OFFSET_PRIMARY_VENDOR 0x13 +#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR 0x15 /* extended query table primary addr */ #define FLASH_OFFSET_WTOUT 0x1F #define FLASH_OFFSET_WBTOUT 0x20 #define FLASH_OFFSET_ETOUT 0x21 @@ -131,18 +135,14 @@ #define FLASH_OFFSET_USER_PROTECTION 0x85 #define FLASH_OFFSET_INTEL_PROTECTION 0x81 - -#define FLASH_MAN_CFI 0x01000000 - -#define CFI_CMDSET_NONE 0 -#define CFI_CMDSET_INTEL_EXTENDED 1 -#define CFI_CMDSET_AMD_STANDARD 2 -#define CFI_CMDSET_INTEL_STANDARD 3 -#define CFI_CMDSET_AMD_EXTENDED 4 -#define CFI_CMDSET_MITSU_STANDARD 256 -#define CFI_CMDSET_MITSU_EXTENDED 257 -#define CFI_CMDSET_SST 258 - +#define CFI_CMDSET_NONE 0 +#define CFI_CMDSET_INTEL_EXTENDED 1 +#define CFI_CMDSET_AMD_STANDARD 2 +#define CFI_CMDSET_INTEL_STANDARD 3 +#define CFI_CMDSET_AMD_EXTENDED 4 +#define CFI_CMDSET_MITSU_STANDARD 256 +#define CFI_CMDSET_MITSU_EXTENDED 257 +#define CFI_CMDSET_SST 258 #ifdef CFG_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on UC100 */ # undef FLASH_CMD_RESET @@ -164,7 +164,7 @@ typedef union { volatile unsigned long long *llp; } cfiptr_t; -#define NUM_ERASE_REGIONS 4 +#define NUM_ERASE_REGIONS 4 /* max. number of erase regions */ /* use CFG_MAX_FLASH_BANKS_DETECT if defined */ #ifdef CFG_MAX_FLASH_BANKS_DETECT @@ -179,9 +179,13 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */ /*----------------------------------------------------------------------- * Functions */ - +extern int mv_flash_erase (flash_info_t *info, int s_first, int s_last); +extern void mv_flash_print_info (flash_info_t *info); +extern int mv_write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt); +extern int mv_flash_real_protect(flash_info_t *info, long sector, int prot); typedef unsigned long flash_sect_t; +unsigned long flash_add_base_addr (uint flash_index, ulong flash_base_addr); static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c); static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf); static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); @@ -189,11 +193,12 @@ static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect); static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); +static void flash_read_jedec_ids (flash_info_t * info); static int flash_detect_cfi (flash_info_t * info); -ulong flash_get_size (ulong base, int banknum); static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword); static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, ulong tout, char *prompt); +ulong flash_get_size (ulong base, int banknum); #if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE) static flash_info_t *flash_get_info(ulong base); #endif @@ -201,12 +206,27 @@ static flash_info_t *flash_get_info(ulong base); static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len); #endif +/*----------------------------------------------------------------------- + * Add base address to nor flash base address bank + */ +unsigned long flash_add_base_addr (uint flash_index, ulong flash_base_addr) +{ + bank_base[flash_index] = flash_base_addr; + + return 0; +} + /*----------------------------------------------------------------------- * create an address based on the offset and the port width */ inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset) { - return ((uchar *) (info->start[sect] + (offset * info->portwidth))); +#if defined(AMD_FLASH_16BIT_IN_8BIT_MODE) + int shift = 2; +#else + int shift = info->portwidth; +#endif + return ((uchar *) (info->start[sect] + (offset * shift))); } #ifdef DEBUG @@ -226,8 +246,13 @@ static void flash_printqry (flash_info_t * info, flash_sect_t sect) { cfiptr_t cptr; int x, y; +#if defined(AMD_FLASH_16BIT_IN_8BIT_MODE) + int shift = 2; +#else + int shift = info->portwidth; +#endif - for (x = 0; x < 0x40; x += 16U / info->portwidth) { + for (x = 0; x < 0x40; x += 16U / shift) { cptr.cp = flash_make_addr (info, sect, x + FLASH_OFFSET_CFI_RESP); @@ -256,8 +281,20 @@ inline uchar flash_read_uchar (flash_info_t * info, uint offset) { uchar *cp; +#ifdef DEBUG + int x; +#endif cp = flash_make_addr (info, 0, offset); -#if defined(__LITTLE_ENDIAN) + +#ifdef DEBUG + debug ("uchar addr is at %p info->portwidth = %d\n", cp, + info->portwidth); + for (x = 0; x < 1 * info->portwidth; x++) { + debug ("addr[%x] = 0x%x\n", x, cp[x]); + } +#endif + +#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) return (cp[0]); #else return (cp[info->portwidth - 1]); @@ -271,6 +308,11 @@ ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset) { uchar *addr; ushort retval; +#if defined(AMD_FLASH_16BIT_IN_8BIT_MODE) + int shift = 2; +#else + int shift = info->portwidth; +#endif #ifdef DEBUG int x; @@ -280,15 +322,15 @@ ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset) #ifdef DEBUG debug ("ushort addr is at %p info->portwidth = %d\n", addr, info->portwidth); - for (x = 0; x < 2 * info->portwidth; x++) { + for (x = 0; x < 2 * shift; x += shift) { debug ("addr[%x] = 0x%x\n", x, addr[x]); } #endif -#if defined(__LITTLE_ENDIAN) - retval = ((addr[(info->portwidth)] << 8) | addr[0]); +#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) + retval = ((addr[(shift)] << 8) | addr[0]); #else - retval = ((addr[(2 * info->portwidth) - 1] << 8) | - addr[info->portwidth - 1]); + retval = ((addr[(2 * shift) - 1] << 8) | + addr[shift - 1]); #endif debug ("retval = 0x%x\n", retval); @@ -296,7 +338,7 @@ ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset) } /*----------------------------------------------------------------------- - * read a long word by picking the least significant byte of each maiximum + * read a long word by picking the least significant byte of each maximum * port size word. Swap for ppc format. */ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset) @@ -304,6 +346,12 @@ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset) uchar *addr; ulong retval; +#if defined(AMD_FLASH_16BIT_IN_8BIT_MODE) + int shift = 2; +#else + int shift = info->portwidth; +#endif + #ifdef DEBUG int x; #endif @@ -312,18 +360,18 @@ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset) #ifdef DEBUG debug ("long addr is at %p info->portwidth = %d\n", addr, info->portwidth); - for (x = 0; x < 4 * info->portwidth; x++) { + for (x = 0; x < 4 * shift; x += shift) { debug ("addr[%x] = 0x%x\n", x, addr[x]); } #endif -#if defined(__LITTLE_ENDIAN) - retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) | - (addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8); +#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) + retval = (addr[0] << 16) | (addr[(shift)] << 24) | + (addr[(2 * shift)]) | (addr[(3 * shift)] << 8); #else - retval = (addr[(2 * info->portwidth) - 1] << 24) | - (addr[(info->portwidth) - 1] << 16) | - (addr[(4 * info->portwidth) - 1] << 8) | - addr[(3 * info->portwidth) - 1]; + retval = (addr[(2 * shift) - 1] << 24) | + (addr[(shift) - 1] << 16) | + (addr[(4 * shift) - 1] << 8) | + addr[(3 * shift) - 1]; #endif return retval; } @@ -334,7 +382,7 @@ unsigned long flash_init (void) { unsigned long size = 0; int i; - + /* Init: no FLASHes known */ for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { flash_info[i].flash_id = FLASH_UNKNOWN; @@ -343,6 +391,14 @@ unsigned long flash_init (void) #ifndef CFG_FLASH_QUIET_TEST printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", i, flash_info[i].size, flash_info[i].size << 20); +#endif /* CFG_FLASH_QUIET_TEST */ + } + else + { +#ifndef CFG_FLASH_QUIET_TEST + printf("******************************************************\n"); + printf ("## FLASH 0x%08lx on Bank %d - Size = 0x%08lx = %ld MB\n", + i, flash_info[i].flash_id, flash_info[i].size, flash_info[i].size << 20); #endif /* CFG_FLASH_QUIET_TEST */ } } @@ -401,7 +457,11 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) flash_sect_t sect; if (info->flash_id != FLASH_MAN_CFI) { - puts ("Can't erase unknown flash type - aborted\n"); +#if defined (CONFIG_MARVELL) + return mv_flash_erase(info, s_first, s_last); +#else + printf("missing or unknown FLASH type\n"); +#endif return 1; } if ((s_first < 0) || (s_first > s_last)) { @@ -463,14 +523,48 @@ void flash_print_info (flash_info_t * info) int i; if (info->flash_id != FLASH_MAN_CFI) { - puts ("missing or unknown FLASH type\n"); + +#if defined (CONFIG_MARVELL) + mv_flash_print_info(info); +#else + printf("missing or unknown FLASH type\n"); +#endif return; } printf ("CFI conformant FLASH (%d x %d)", (info->portwidth << 3), (info->chipwidth << 3)); - printf (" Size: %ld MB in %d Sectors\n", + + /* Check if flash size is less then 1 MB */ + if ( (info->size >> 20) == 0) + { + printf (" Size: %ld kB in %d Sectors\n", + info->size >> 10, info->sector_count); + } + else + { + printf (" Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count); + } + + switch (info->vendor) { + case CFI_CMDSET_INTEL_STANDARD: + printf ("Intel Standard"); + break; + case CFI_CMDSET_INTEL_EXTENDED: + printf ("Intel Extended"); + break; + case CFI_CMDSET_AMD_STANDARD: + printf ("AMD Standard"); + break; + case CFI_CMDSET_AMD_EXTENDED: + printf ("AMD Extended"); + break; + default: + printf ("Unknown (%d)", info->vendor); + break; + } + printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", info->erase_blk_tout, info->write_tout, @@ -537,6 +631,15 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) #ifdef CFG_FLASH_USE_BUFFER_WRITE int buffered_size; #endif + + if (info->flash_id != FLASH_MAN_CFI) { +#if defined (CONFIG_MARVELL) + return mv_write_buff(info, src, addr, cnt); +#else + printf("missing or unknown FLASH type\n"); +#endif + return 0; + } /* get lower aligned address */ /* get lower aligned address */ wp = (addr & ~(info->portwidth - 1)); @@ -611,6 +714,15 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) int flash_real_protect (flash_info_t * info, long sector, int prot) { int retcode = 0; + + if (info->flash_id != FLASH_MAN_CFI) { +#if defined (CONFIG_MARVELL) + mv_flash_real_protect(info, sector, prot); +#else + printf("missing or unknown FLASH type\n"); +#endif + return retcode; + } flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT); @@ -624,15 +736,6 @@ int flash_real_protect (flash_info_t * info, long sector, int prot) prot ? "protect" : "unprotect")) == 0) { info->protect[sector] = prot; - /* Intel's unprotect unprotects all locking */ - if (prot == 0) { - flash_sect_t i; - - for (i = 0; i < info->sector_count; i++) { - if (info->protect[i]) - flash_real_protect (info, i, 1); - } - } } return retcode; } @@ -729,7 +832,7 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, switch (info->vendor) { case CFI_CMDSET_INTEL_EXTENDED: case CFI_CMDSET_INTEL_STANDARD: - if ((retcode != ERR_OK) + if ((retcode == ERR_OK) && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) { retcode = ERR_INVAL; printf ("Flash %s error at address %lx\n", prompt, @@ -761,7 +864,7 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, */ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) { -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) unsigned short w; unsigned int l; unsigned long long ll; @@ -772,7 +875,7 @@ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) cword->c = c; break; case FLASH_CFI_16BIT: -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) w = c; w <<= 8; cword->w = (cword->w >> 8) | w; @@ -781,7 +884,7 @@ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) #endif break; case FLASH_CFI_32BIT: -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) l = c; l <<= 24; cword->l = (cword->l >> 8) | l; @@ -790,7 +893,7 @@ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) #endif break; case FLASH_CFI_64BIT: -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) ll = c; ll <<= 56; cword->ll = (cword->ll >> 8) | ll; @@ -810,7 +913,7 @@ static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf) int i; uchar *cp = (uchar *) cmdbuf; -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) for (i = info->portwidth; i > 0; i--) #else for (i = 1; i <= info->portwidth; i++) @@ -976,6 +1079,55 @@ static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uc return retval; } +/*----------------------------------------------------------------------- + * read jedec ids from device and set corresponding fields in info struct + * + * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct + * +*/ +static void flash_read_jedec_ids (flash_info_t * info) +{ + info->manufacturer_id = 0; + info->device_id = 0; + info->device_id2 = 0; + + switch (info->vendor) { + case CFI_CMDSET_INTEL_STANDARD: + case CFI_CMDSET_INTEL_EXTENDED: + flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); + flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID); + udelay(1000); /* some flash are slow to respond */ + info->manufacturer_id = flash_read_uchar (info, + FLASH_OFFSET_MANUFACTURER_ID); + info->device_id = flash_read_uchar (info, + FLASH_OFFSET_DEVICE_ID); + flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); + break; + case CFI_CMDSET_AMD_STANDARD: + case CFI_CMDSET_AMD_EXTENDED: + flash_write_cmd(info, 0, 0, AMD_CMD_RESET); + flash_unlock_seq(info, 0); + flash_write_cmd(info, 0, AMD_ADDR_START, FLASH_CMD_READ_ID); + udelay(1000); /* some flash are slow to respond */ + info->manufacturer_id = flash_read_uchar (info, + FLASH_OFFSET_MANUFACTURER_ID); + info->device_id = flash_read_uchar (info, + FLASH_OFFSET_DEVICE_ID); + if (info->device_id == 0x7E) { + /* AMD 3-byte (expanded) device ids */ + info->device_id2 = flash_read_uchar (info, + FLASH_OFFSET_DEVICE_ID2); + info->device_id2 <<= 8; + info->device_id2 |= flash_read_uchar (info, + FLASH_OFFSET_DEVICE_ID3); + } + flash_write_cmd(info, 0, 0, AMD_CMD_RESET); + break; + default: + break; + } +} + /*----------------------------------------------------------------------- * detect if flash is compatible with the Common Flash Interface (CFI) * http://www.jedec.org/download/search/jesd68.pdf @@ -988,7 +1140,7 @@ static int flash_detect_cfi (flash_info_t * info) for (info->portwidth = FLASH_CFI_8BIT; info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) { for (info->chipwidth = FLASH_CFI_BY8; - info->chipwidth <= info->portwidth; + info->chipwidth <= (info->portwidth); info->chipwidth <<= 1) { flash_write_cmd (info, 0, 0, info->cmd_reset); flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); @@ -1026,11 +1178,31 @@ ulong flash_get_size (ulong base, int banknum) uchar num_erase_regions; int erase_region_size; int erase_region_count; + int geometry_reversed = 0; + + info->ext_addr = 0; + info->cfi_version = 0; +#ifdef CFG_FLASH_PROTECTION + info->legacy_unlock = 0; +#endif info->start[0] = base; if (flash_detect_cfi (info)) { - info->vendor = flash_read_ushort (info, 0, FLASH_OFFSET_PRIMARY_VENDOR); + info->vendor = flash_read_ushort (info, 0, + FLASH_OFFSET_PRIMARY_VENDOR); + flash_read_jedec_ids (info); + flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); + num_erase_regions = flash_read_uchar (info, + FLASH_OFFSET_NUM_ERASE_REGIONS); + info->ext_addr = flash_read_ushort (info, 0, + FLASH_OFFSET_EXT_QUERY_T_P_ADDR); + if (info->ext_addr) { + info->cfi_version = (ushort) flash_read_uchar (info, + info->ext_addr + 3) << 8; + info->cfi_version |= (ushort) flash_read_uchar (info, + info->ext_addr + 4); + } #ifdef DEBUG flash_printqry (info, 0); #endif @@ -1039,21 +1211,52 @@ ulong flash_get_size (ulong base, int banknum) case CFI_CMDSET_INTEL_EXTENDED: default: info->cmd_reset = FLASH_CMD_RESET; +#ifdef CFG_FLASH_PROTECTION + /* read legacy lock/unlock bit from intel flash */ + if (info->ext_addr) { + info->legacy_unlock = flash_read_uchar (info, + info->ext_addr + 5) & 0x08; + } +#endif break; case CFI_CMDSET_AMD_STANDARD: case CFI_CMDSET_AMD_EXTENDED: info->cmd_reset = AMD_CMD_RESET; + /* check if flash geometry needs reversal */ + if (num_erase_regions <= 1) + break; + /* reverse geometry if top boot part */ + if (info->cfi_version < 0x3131) { + /* CFI < 1.1, try to guess from device id */ + if ((info->device_id & 0x80) != 0) { + geometry_reversed = 1; + } + break; + } + /* CFI >= 1.1, deduct from top/bottom flag */ + /* note: ext_addr is valid since cfi_version > 0 */ + if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) { + geometry_reversed = 1; + } break; } debug ("manufacturer is %d\n", info->vendor); + debug ("manufacturer id is 0x%x\n", info->manufacturer_id); + debug ("device id is 0x%x\n", info->device_id); + debug ("device id2 is 0x%x\n", info->device_id2); + debug ("cfi version is 0x%04x\n", info->cfi_version); + size_ratio = info->portwidth / info->chipwidth; + +#if !defined(AMD_FLASH_16BIT_IN_8BIT_MODE) /* if the chip is x8/x16 reduce the ratio by half */ if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) { size_ratio >>= 1; } - num_erase_regions = flash_read_uchar (info, FLASH_OFFSET_NUM_ERASE_REGIONS); +#endif + debug ("size_ratio %d port %d bits chip %d bits\n", size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); @@ -1066,7 +1269,12 @@ ulong flash_get_size (ulong base, int banknum) num_erase_regions, NUM_ERASE_REGIONS); break; } - tmp = flash_read_long (info, 0, + if (geometry_reversed) + tmp = flash_read_long (info, 0, + FLASH_OFFSET_ERASE_REGIONS + + (num_erase_regions - 1 - i) * 4); + else + tmp = flash_read_long (info, 0, FLASH_OFFSET_ERASE_REGIONS + i * 4); erase_region_size = @@ -1104,20 +1312,41 @@ ulong flash_get_size (ulong base, int banknum) info->buffer_size = (1 << flash_read_ushort (info, 0, FLASH_OFFSET_BUFFER_SIZE)); tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT); info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT))); - tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT); - info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT))); - tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT); - info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000; + tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT)) * + (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)); + info->buffer_write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */ + tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) * + (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT)); + info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */ info->flash_id = FLASH_MAN_CFI; + +#if !defined(AMD_FLASH_16BIT_IN_8BIT_MODE) if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) { info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */ } +#endif } flash_write_cmd (info, 0, 0, info->cmd_reset); + debug ("info->size = %d\n", + info->size); return (info->size); } +/* loop through the sectors from the highest address + * when the passed address is greater or equal to the sector address + * we have a match + */ +static flash_sect_t find_sector (flash_info_t * info, ulong addr) +{ + flash_sect_t sector; + + for (sector = info->sector_count - 1; sector >= 0; sector--) { + if (addr >= info->start[sector]) + break; + } + return sector; +} /*----------------------------------------------------------------------- */ @@ -1188,26 +1417,12 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest, if (flag) enable_interrupts (); - return flash_full_status_check (info, 0, info->write_tout, "write"); + return flash_full_status_check (info, find_sector (info, dest), + info->write_tout, "write"); } #ifdef CFG_FLASH_USE_BUFFER_WRITE -/* loop through the sectors from the highest address - * when the passed address is greater or equal to the sector address - * we have a match - */ -static flash_sect_t find_sector (flash_info_t * info, ulong addr) -{ - flash_sect_t sector; - - for (sector = info->sector_count - 1; sector >= 0; sector--) { - if (addr >= info->start[sector]) - break; - } - return sector; -} - static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len) { @@ -1216,66 +1431,106 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int retcode; volatile cfiptr_t src; volatile cfiptr_t dst; - /* buffered writes in the AMD chip set is not supported yet */ - if((info->vendor == CFI_CMDSET_AMD_STANDARD) || - (info->vendor == CFI_CMDSET_AMD_EXTENDED)) - return ERR_INVAL; - src.cp = cp; - dst.cp = (uchar *) dest; - sector = find_sector (info, dest); - flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); - flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); - if ((retcode = - flash_status_check (info, sector, info->buffer_write_tout, - "write to buffer")) == ERR_OK) { - /* reduce the number of loops by the width of the port */ - switch (info->portwidth) { - case FLASH_CFI_8BIT: - cnt = len; - break; - case FLASH_CFI_16BIT: - cnt = len >> 1; - break; - case FLASH_CFI_32BIT: - cnt = len >> 2; - break; - case FLASH_CFI_64BIT: - cnt = len >> 3; - break; - default: - return ERR_INVAL; - break; - } - flash_write_cmd (info, sector, 0, (uchar) cnt - 1); - while (cnt-- > 0) { + switch (info->vendor) { + case CFI_CMDSET_INTEL_STANDARD: + case CFI_CMDSET_INTEL_EXTENDED: + src.cp = cp; + dst.cp = (uchar *) dest; + sector = find_sector (info, dest); + flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); + flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); + if ((retcode = flash_status_check (info, sector, info->buffer_write_tout, + "write to buffer")) == ERR_OK) { + /* reduce the number of loops by the width of the port */ switch (info->portwidth) { case FLASH_CFI_8BIT: - *dst.cp++ = *src.cp++; + cnt = len; break; case FLASH_CFI_16BIT: - *dst.wp++ = *src.wp++; + cnt = len >> 1; break; case FLASH_CFI_32BIT: - *dst.lp++ = *src.lp++; + cnt = len >> 2; break; case FLASH_CFI_64BIT: - *dst.llp++ = *src.llp++; + cnt = len >> 3; break; default: return ERR_INVAL; break; } + flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + while (cnt-- > 0) { + switch (info->portwidth) { + case FLASH_CFI_8BIT: + *dst.cp++ = *src.cp++; + break; + case FLASH_CFI_16BIT: + *dst.wp++ = *src.wp++; + break; + case FLASH_CFI_32BIT: + *dst.lp++ = *src.lp++; + break; + case FLASH_CFI_64BIT: + *dst.llp++ = *src.llp++; + break; + default: + return ERR_INVAL; + break; + } + } + flash_write_cmd (info, sector, 0, + FLASH_CMD_WRITE_BUFFER_CONFIRM); + retcode = flash_full_status_check (info, sector, + info->buffer_write_tout, + "buffer write"); } - flash_write_cmd (info, sector, 0, - FLASH_CMD_WRITE_BUFFER_CONFIRM); - retcode = - flash_full_status_check (info, sector, - info->buffer_write_tout, - "buffer write"); + return retcode; + + case CFI_CMDSET_AMD_STANDARD: + case CFI_CMDSET_AMD_EXTENDED: + src.cp = cp; + dst.cp = (uchar *) dest; + sector = find_sector (info, dest); + + flash_unlock_seq(info,0); + flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER); + + switch (info->portwidth) { + case FLASH_CFI_8BIT: + cnt = len; + flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + while (cnt-- > 0) *dst.cp++ = *src.cp++; + break; + case FLASH_CFI_16BIT: + cnt = len >> 1; + flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + while (cnt-- > 0) *dst.wp++ = *src.wp++; + break; + case FLASH_CFI_32BIT: + cnt = len >> 2; + flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + while (cnt-- > 0) *dst.lp++ = *src.lp++; + break; + case FLASH_CFI_64BIT: + cnt = len >> 3; + flash_write_cmd (info, sector, 0, (uchar) cnt - 1); + while (cnt-- > 0) *dst.llp++ = *src.llp++; + break; + default: + return ERR_INVAL; + } + + flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); + retcode = flash_full_status_check (info, sector, info->buffer_write_tout, + "buffer write"); + return retcode; + + default: + debug ("Unknown Command Set\n"); + return ERR_INVAL; } - flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); - return retcode; } #endif /* CFG_FLASH_USE_BUFFER_WRITE */ #endif /* CFG_FLASH_CFI */ diff --git a/drivers/eepro100.c b/drivers/eepro100.c index 04c17f6..dcaca63 100644 --- a/drivers/eepro100.c +++ b/drivers/eepro100.c @@ -249,9 +249,12 @@ static int eepro100_send (struct eth_device *dev, volatile void *packet, static int eepro100_recv (struct eth_device *dev); static void eepro100_halt (struct eth_device *dev); -#if defined(CONFIG_E500) || defined(CONFIG_DB64360) || defined(CONFIG_DB64460) -#define bus_to_phys(a) (a) +#if defined(CONFIG_E500) || (defined(CONFIG_MARVELL) && defined(__ARM__)) +#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) #define phys_to_bus(a) (a) +#elif defined(CONFIG_MARVELL) && defined(__MIPS__) +#define bus_to_phys(a) (a | (0xa0000000)) +#define phys_to_bus(a) (a & ~(0xa0000000)) #else #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) diff --git a/drivers/nand/Makefile b/drivers/nand/Makefile new file mode 100644 index 0000000..87678a6 --- /dev/null +++ b/drivers/nand/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 $(TOPDIR)/config.mk + +LIB := $(obj)libnand.a + +COBJS := nand.o nand_base.o nand_ids.o nand_ecc.o nand_ecc_rs.o nand_bbt.o nand_util.o + +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/drivers/nand/diskonchip.c b/drivers/nand/diskonchip.c new file mode 100644 index 0000000..9bd83d6 --- /dev/null +++ b/drivers/nand/diskonchip.c @@ -0,0 +1,1787 @@ +/* + * drivers/mtd/nand/diskonchip.c + * + * (C) 2003 Red Hat, Inc. + * (C) 2004 Dan Brown + * (C) 2004 Kalev Lember + * + * Author: David Woodhouse + * Additional Diskonchip 2000 and Millennium support by Dan Brown + * Diskonchip Millennium Plus support by Kalev Lember + * + * Error correction code lifted from the old docecc code + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Copyright (C) 2000 Netgem S.A. + * converted to the generic Reed-Solomon library by Thomas Gleixner + * + * Interface to generic NAND code for M-Systems DiskOnChip devices + * + * $Id: diskonchip.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ + */ + +#include + +#if !defined(CFG_NAND_LEGACY) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Where to look for the devices? */ +#ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS +#define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0 +#endif + +static unsigned long __initdata doc_locations[] = { +#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) +#ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH + 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, + 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, + 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, + 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, + 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, +#else /* CONFIG_MTD_DOCPROBE_HIGH */ + 0xc8000, 0xca000, 0xcc000, 0xce000, + 0xd0000, 0xd2000, 0xd4000, 0xd6000, + 0xd8000, 0xda000, 0xdc000, 0xde000, + 0xe0000, 0xe2000, 0xe4000, 0xe6000, + 0xe8000, 0xea000, 0xec000, 0xee000, +#endif /* CONFIG_MTD_DOCPROBE_HIGH */ +#elif defined(__PPC__) + 0xe4000000, +#elif defined(CONFIG_MOMENCO_OCELOT) + 0x2f000000, + 0xff000000, +#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) + 0xff000000, +##else +#warning Unknown architecture for DiskOnChip. No default probe locations defined +#endif + 0xffffffff }; + +static struct mtd_info *doclist = NULL; + +struct doc_priv { + void __iomem *virtadr; + unsigned long physadr; + u_char ChipID; + u_char CDSNControl; + int chips_per_floor; /* The number of chips detected on each floor */ + int curfloor; + int curchip; + int mh0_page; + int mh1_page; + struct mtd_info *nextdoc; +}; + +/* Max number of eraseblocks to scan (from start of device) for the (I)NFTL + MediaHeader. The spec says to just keep going, I think, but that's just + silly. */ +#define MAX_MEDIAHEADER_SCAN 8 + +/* This is the syndrome computed by the HW ecc generator upon reading an empty + page, one with all 0xff for data and stored ecc code. */ +static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; +/* This is the ecc value computed by the HW ecc generator upon writing an empty + page, one with all 0xff for data. */ +static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; + +#define INFTL_BBT_RESERVED_BLOCKS 4 + +#define DoC_is_MillenniumPlus(doc) ((doc)->ChipID == DOC_ChipID_DocMilPlus16 || (doc)->ChipID == DOC_ChipID_DocMilPlus32) +#define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) +#define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) + +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); +static void doc200x_select_chip(struct mtd_info *mtd, int chip); + +static int debug=0; +module_param(debug, int, 0); + +static int try_dword=1; +module_param(try_dword, int, 0); + +static int no_ecc_failures=0; +module_param(no_ecc_failures, int, 0); + +#ifdef CONFIG_MTD_PARTITIONS +static int no_autopart=0; +module_param(no_autopart, int, 0); +#endif + +#ifdef MTD_NAND_DISKONCHIP_BBTWRITE +static int inftl_bbt_write=1; +#else +static int inftl_bbt_write=0; +#endif +module_param(inftl_bbt_write, int, 0); + +static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS; +module_param(doc_config_location, ulong, 0); +MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); + + +/* Sector size for HW ECC */ +#define SECTOR_SIZE 512 +/* The sector bytes are packed into NB_DATA 10 bit words */ +#define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / 10) +/* Number of roots */ +#define NROOTS 4 +/* First consective root */ +#define FCR 510 +/* Number of symbols */ +#define NN 1023 + +/* the Reed Solomon control structure */ +static struct rs_control *rs_decoder; + +/* + * The HW decoder in the DoC ASIC's provides us a error syndrome, + * which we must convert to a standard syndrom usable by the generic + * Reed-Solomon library code. + * + * Fabrice Bellard figured this out in the old docecc code. I added + * some comments, improved a minor bit and converted it to make use + * of the generic Reed-Solomon libary. tglx + */ +static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) +{ + int i, j, nerr, errpos[8]; + uint8_t parity; + uint16_t ds[4], s[5], tmp, errval[8], syn[4]; + + /* Convert the ecc bytes into words */ + ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); + ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); + ds[2] = ((ecc[2] & 0xf0) >> 4) | ((ecc[3] & 0x3f) << 4); + ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); + parity = ecc[1]; + + /* Initialize the syndrom buffer */ + for (i = 0; i < NROOTS; i++) + s[i] = ds[0]; + /* + * Evaluate + * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] + * where x = alpha^(FCR + i) + */ + for(j = 1; j < NROOTS; j++) { + if(ds[j] == 0) + continue; + tmp = rs->index_of[ds[j]]; + for(i = 0; i < NROOTS; i++) + s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; + } + + /* Calc s[i] = s[i] / alpha^(v + i) */ + for (i = 0; i < NROOTS; i++) { + if (syn[i]) + syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); + } + /* Call the decoder library */ + nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); + + /* Incorrectable errors ? */ + if (nerr < 0) + return nerr; + + /* + * Correct the errors. The bitpositions are a bit of magic, + * but they are given by the design of the de/encoder circuit + * in the DoC ASIC's. + */ + for(i = 0;i < nerr; i++) { + int index, bitpos, pos = 1015 - errpos[i]; + uint8_t val; + if (pos >= NB_DATA && pos < 1019) + continue; + if (pos < NB_DATA) { + /* extract bit position (MSB first) */ + pos = 10 * (NB_DATA - 1 - pos) - 6; + /* now correct the following 10 bits. At most two bytes + can be modified since pos is even */ + index = (pos >> 3) ^ 1; + bitpos = pos & 7; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = (uint8_t) (errval[i] >> (2 + bitpos)); + parity ^= val; + if (index < SECTOR_SIZE) + data[index] ^= val; + } + index = ((pos >> 3) + 1) ^ 1; + bitpos = (bitpos + 10) & 7; + if (bitpos == 0) + bitpos = 8; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = (uint8_t)(errval[i] << (8 - bitpos)); + parity ^= val; + if (index < SECTOR_SIZE) + data[index] ^= val; + } + } + } + /* If the parity is wrong, no rescue possible */ + return parity ? -1 : nerr; +} + +static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) +{ + volatile char dummy; + int i; + + for (i = 0; i < cycles; i++) { + if (DoC_is_Millennium(doc)) + dummy = ReadDOC(doc->virtadr, NOP); + else if (DoC_is_MillenniumPlus(doc)) + dummy = ReadDOC(doc->virtadr, Mplus_NOP); + else + dummy = ReadDOC(doc->virtadr, DOCStatus); + } + +} + +#define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) + +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ +static int _DoC_WaitReady(struct doc_priv *doc) +{ + void __iomem *docptr = doc->virtadr; + unsigned long timeo = jiffies + (HZ * 10); + + if(debug) printk("_DoC_WaitReady...\n"); + /* Out-of-line routine to wait for chip response */ + if (DoC_is_MillenniumPlus(doc)) { + while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { + if (time_after(jiffies, timeo)) { + printk("_DoC_WaitReady timed out.\n"); + return -EIO; + } + udelay(1); + cond_resched(); + } + } else { + while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { + if (time_after(jiffies, timeo)) { + printk("_DoC_WaitReady timed out.\n"); + return -EIO; + } + udelay(1); + cond_resched(); + } + } + + return 0; +} + +static inline int DoC_WaitReady(struct doc_priv *doc) +{ + void __iomem *docptr = doc->virtadr; + int ret = 0; + + if (DoC_is_MillenniumPlus(doc)) { + DoC_Delay(doc, 4); + + if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) + /* Call the out-of-line routine to wait */ + ret = _DoC_WaitReady(doc); + } else { + DoC_Delay(doc, 4); + + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) + /* Call the out-of-line routine to wait */ + ret = _DoC_WaitReady(doc); + DoC_Delay(doc, 2); + } + + if(debug) printk("DoC_WaitReady OK\n"); + return ret; +} + +static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + if(debug)printk("write_byte %02x\n", datum); + WriteDOC(datum, docptr, CDSNSlowIO); + WriteDOC(datum, docptr, 2k_CDSN_IO); +} + +static u_char doc2000_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + u_char ret; + + ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(doc, 2); + ret = ReadDOC(docptr, 2k_CDSN_IO); + if (debug) printk("read_byte returns %02x\n", ret); + return ret; +} + +static void doc2000_writebuf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + if (debug)printk("writebuf of %d bytes: ", len); + for (i=0; i < len; i++) { + WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); + if (debug && i < 16) + printk("%02x ", buf[i]); + } + if (debug) printk("\n"); +} + +static void doc2000_readbuf(struct mtd_info *mtd, + u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + if (debug)printk("readbuf of %d bytes: ", len); + + for (i=0; i < len; i++) { + buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); + } +} + +static void doc2000_readbuf_dword(struct mtd_info *mtd, + u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + if (debug) printk("readbuf_dword of %d bytes: ", len); + + if (unlikely((((unsigned long)buf)|len) & 3)) { + for (i=0; i < len; i++) { + *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); + } + } else { + for (i=0; i < len; i+=4) { + *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); + } + } +} + +static int doc2000_verifybuf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + for (i=0; i < len; i++) + if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) + return -EFAULT; + return 0; +} + +static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + uint16_t ret; + + doc200x_select_chip(mtd, nr); + doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); + this->write_byte(mtd, NAND_CMD_READID); + doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); + doc200x_hwcontrol(mtd, NAND_CTL_SETALE); + this->write_byte(mtd, 0); + doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); + + ret = this->read_byte(mtd) << 8; + ret |= this->read_byte(mtd); + + if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) { + /* First chip probe. See if we get same results by 32-bit access */ + union { + uint32_t dword; + uint8_t byte[4]; + } ident; + void __iomem *docptr = doc->virtadr; + + doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); + doc2000_write_byte(mtd, NAND_CMD_READID); + doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); + doc200x_hwcontrol(mtd, NAND_CTL_SETALE); + doc2000_write_byte(mtd, 0); + doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); + + ident.dword = readl(docptr + DoC_2k_CDSN_IO); + if (((ident.byte[0] << 8) | ident.byte[1]) == ret) { + printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n"); + this->read_buf = &doc2000_readbuf_dword; + } + } + + return ret; +} + +static void __init doc2000_count_chips(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + uint16_t mfrid; + int i; + + /* Max 4 chips per floor on DiskOnChip 2000 */ + doc->chips_per_floor = 4; + + /* Find out what the first chip is */ + mfrid = doc200x_ident_chip(mtd, 0); + + /* Find how many chips in each floor. */ + for (i = 1; i < 4; i++) { + if (doc200x_ident_chip(mtd, i) != mfrid) + break; + } + doc->chips_per_floor = i; + printk(KERN_DEBUG "Detected %d chips per floor.\n", i); +} + +static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +{ + struct doc_priv *doc = this->priv; + + int status; + + DoC_WaitReady(doc); + this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + DoC_WaitReady(doc); + status = (int)this->read_byte(mtd); + + return status; +} + +static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + WriteDOC(datum, docptr, CDSNSlowIO); + WriteDOC(datum, docptr, Mil_CDSN_IO); + WriteDOC(datum, docptr, WritePipeTerm); +} + +static u_char doc2001_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + /*ReadDOC(docptr, CDSNSlowIO); */ + /* 11.4.5 -- delay twice to allow extended length cycle */ + DoC_Delay(doc, 2); + ReadDOC(docptr, ReadPipeInit); + /*return ReadDOC(docptr, Mil_CDSN_IO); */ + return ReadDOC(docptr, LastDataRead); +} + +static void doc2001_writebuf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + for (i=0; i < len; i++) + WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); + /* Terminate write pipeline */ + WriteDOC(0x00, docptr, WritePipeTerm); +} + +static void doc2001_readbuf(struct mtd_info *mtd, + u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + /* Start read pipeline */ + ReadDOC(docptr, ReadPipeInit); + + for (i=0; i < len-1; i++) + buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); + + /* Terminate read pipeline */ + buf[i] = ReadDOC(docptr, LastDataRead); +} + +static int doc2001_verifybuf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + /* Start read pipeline */ + ReadDOC(docptr, ReadPipeInit); + + for (i=0; i < len-1; i++) + if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { + ReadDOC(docptr, LastDataRead); + return i; + } + if (buf[i] != ReadDOC(docptr, LastDataRead)) + return i; + return 0; +} + +static u_char doc2001plus_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + u_char ret; + + ReadDOC(docptr, Mplus_ReadPipeInit); + ReadDOC(docptr, Mplus_ReadPipeInit); + ret = ReadDOC(docptr, Mplus_LastDataRead); + if (debug) printk("read_byte returns %02x\n", ret); + return ret; +} + +static void doc2001plus_writebuf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + if (debug)printk("writebuf of %d bytes: ", len); + for (i=0; i < len; i++) { + WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); + if (debug && i < 16) + printk("%02x ", buf[i]); + } + if (debug) printk("\n"); +} + +static void doc2001plus_readbuf(struct mtd_info *mtd, + u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + if (debug)printk("readbuf of %d bytes: ", len); + + /* Start read pipeline */ + ReadDOC(docptr, Mplus_ReadPipeInit); + ReadDOC(docptr, Mplus_ReadPipeInit); + + for (i=0; i < len-2; i++) { + buf[i] = ReadDOC(docptr, Mil_CDSN_IO); + if (debug && i < 16) + printk("%02x ", buf[i]); + } + + /* Terminate read pipeline */ + buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); + if (debug && i < 16) + printk("%02x ", buf[len-2]); + buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); + if (debug && i < 16) + printk("%02x ", buf[len-1]); + if (debug) printk("\n"); +} + +static int doc2001plus_verifybuf(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + + if (debug)printk("verifybuf of %d bytes: ", len); + + /* Start read pipeline */ + ReadDOC(docptr, Mplus_ReadPipeInit); + ReadDOC(docptr, Mplus_ReadPipeInit); + + for (i=0; i < len-2; i++) + if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { + ReadDOC(docptr, Mplus_LastDataRead); + ReadDOC(docptr, Mplus_LastDataRead); + return i; + } + if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead)) + return len-2; + if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead)) + return len-1; + return 0; +} + +static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int floor = 0; + + if(debug)printk("select chip (%d)\n", chip); + + if (chip == -1) { + /* Disable flash internally */ + WriteDOC(0, docptr, Mplus_FlashSelect); + return; + } + + floor = chip / doc->chips_per_floor; + chip -= (floor * doc->chips_per_floor); + + /* Assert ChipEnable and deassert WriteProtect */ + WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect); + this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + + doc->curchip = chip; + doc->curfloor = floor; +} + +static void doc200x_select_chip(struct mtd_info *mtd, int chip) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int floor = 0; + + if(debug)printk("select chip (%d)\n", chip); + + if (chip == -1) + return; + + floor = chip / doc->chips_per_floor; + chip -= (floor * doc->chips_per_floor); + + /* 11.4.4 -- deassert CE before changing chip */ + doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); + + WriteDOC(floor, docptr, FloorSelect); + WriteDOC(chip, docptr, CDSNDeviceSelect); + + doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); + + doc->curchip = chip; + doc->curfloor = floor; +} + +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + switch(cmd) { + case NAND_CTL_SETNCE: + doc->CDSNControl |= CDSN_CTRL_CE; + break; + case NAND_CTL_CLRNCE: + doc->CDSNControl &= ~CDSN_CTRL_CE; + break; + case NAND_CTL_SETCLE: + doc->CDSNControl |= CDSN_CTRL_CLE; + break; + case NAND_CTL_CLRCLE: + doc->CDSNControl &= ~CDSN_CTRL_CLE; + break; + case NAND_CTL_SETALE: + doc->CDSNControl |= CDSN_CTRL_ALE; + break; + case NAND_CTL_CLRALE: + doc->CDSNControl &= ~CDSN_CTRL_ALE; + break; + case NAND_CTL_SETWP: + doc->CDSNControl |= CDSN_CTRL_WP; + break; + case NAND_CTL_CLRWP: + doc->CDSNControl &= ~CDSN_CTRL_WP; + break; + } + if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); + WriteDOC(doc->CDSNControl, docptr, CDSNControl); + /* 11.4.3 -- 4 NOPs after CSDNControl write */ + DoC_Delay(doc, 4); +} + +static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + /* + * Must terminate write pipeline before sending any commands + * to the device. + */ + if (command == NAND_CMD_PAGEPROG) { + WriteDOC(0x00, docptr, Mplus_WritePipeTerm); + WriteDOC(0x00, docptr, Mplus_WritePipeTerm); + } + + /* + * Write out the command to the device. + */ + if (command == NAND_CMD_SEQIN) { + int readcmd; + + if (column >= mtd->oobblock) { + /* OOB area */ + column -= mtd->oobblock; + readcmd = NAND_CMD_READOOB; + } else if (column < 256) { + /* First 256 bytes --> READ0 */ + readcmd = NAND_CMD_READ0; + } else { + column -= 256; + readcmd = NAND_CMD_READ1; + } + WriteDOC(readcmd, docptr, Mplus_FlashCmd); + } + WriteDOC(command, docptr, Mplus_FlashCmd); + WriteDOC(0, docptr, Mplus_WritePipeTerm); + WriteDOC(0, docptr, Mplus_WritePipeTerm); + + if (column != -1 || page_addr != -1) { + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (this->options & NAND_BUSWIDTH_16) + column >>= 1; + WriteDOC(column, docptr, Mplus_FlashAddress); + } + if (page_addr != -1) { + WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress); + WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); + /* One more address cycle for higher density devices */ + if (this->chipsize & 0x0c000000) { + WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); + printk("high density\n"); + } + } + WriteDOC(0, docptr, Mplus_WritePipeTerm); + WriteDOC(0, docptr, Mplus_WritePipeTerm); + /* deassert ALE */ + if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID) + WriteDOC(0, docptr, Mplus_FlashControl); + } + + /* + * program and erase have their own busy handlers + * status and sequential in needs no delay + */ + switch (command) { + + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + case NAND_CMD_ERASE2: + case NAND_CMD_SEQIN: + case NAND_CMD_STATUS: + return; + + case NAND_CMD_RESET: + if (this->dev_ready) + break; + udelay(this->chip_delay); + WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); + WriteDOC(0, docptr, Mplus_WritePipeTerm); + WriteDOC(0, docptr, Mplus_WritePipeTerm); + while ( !(this->read_byte(mtd) & 0x40)); + return; + + /* This applies to read commands */ + default: + /* + * If we don't have access to the busy pin, we apply the given + * command delay + */ + if (!this->dev_ready) { + udelay (this->chip_delay); + return; + } + } + + /* Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. */ + ndelay (100); + /* wait until command is processed */ + while (!this->dev_ready(mtd)); +} + +static int doc200x_dev_ready(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + if (DoC_is_MillenniumPlus(doc)) { + /* 11.4.2 -- must NOP four times before checking FR/B# */ + DoC_Delay(doc, 4); + if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { + if(debug) + printk("not ready\n"); + return 0; + } + if (debug)printk("was ready\n"); + return 1; + } else { + /* 11.4.2 -- must NOP four times before checking FR/B# */ + DoC_Delay(doc, 4); + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { + if(debug) + printk("not ready\n"); + return 0; + } + /* 11.4.2 -- Must NOP twice if it's ready */ + DoC_Delay(doc, 2); + if (debug)printk("was ready\n"); + return 1; + } +} + +static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +{ + /* This is our last resort if we couldn't find or create a BBT. Just + pretend all blocks are good. */ + return 0; +} + +static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + /* Prime the ECC engine */ + switch(mode) { + case NAND_ECC_READ: + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN, docptr, ECCConf); + break; + case NAND_ECC_WRITE: + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + break; + } +} + +static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + + /* Prime the ECC engine */ + switch(mode) { + case NAND_ECC_READ: + WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); + WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); + break; + case NAND_ECC_WRITE: + WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); + break; + } +} + +/* This code is only called on write */ +static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + unsigned char *ecc_code) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + int i; + int emptymatch = 1; + + /* flush the pipeline */ + if (DoC_is_2000(doc)) { + WriteDOC(doc->CDSNControl & ~CDSN_CTRL_FLASH_IO, docptr, CDSNControl); + WriteDOC(0, docptr, 2k_CDSN_IO); + WriteDOC(0, docptr, 2k_CDSN_IO); + WriteDOC(0, docptr, 2k_CDSN_IO); + WriteDOC(doc->CDSNControl, docptr, CDSNControl); + } else if (DoC_is_MillenniumPlus(doc)) { + WriteDOC(0, docptr, Mplus_NOP); + WriteDOC(0, docptr, Mplus_NOP); + WriteDOC(0, docptr, Mplus_NOP); + } else { + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + } + + for (i = 0; i < 6; i++) { + if (DoC_is_MillenniumPlus(doc)) + ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); + else + ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); + if (ecc_code[i] != empty_write_ecc[i]) + emptymatch = 0; + } + if (DoC_is_MillenniumPlus(doc)) + WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); + else + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); +#if 0 + /* If emptymatch=1, we might have an all-0xff data buffer. Check. */ + if (emptymatch) { + /* Note: this somewhat expensive test should not be triggered + often. It could be optimized away by examining the data in + the writebuf routine, and remembering the result. */ + for (i = 0; i < 512; i++) { + if (dat[i] == 0xff) continue; + emptymatch = 0; + break; + } + } + /* If emptymatch still =1, we do have an all-0xff data buffer. + Return all-0xff ecc value instead of the computed one, so + it'll look just like a freshly-erased page. */ + if (emptymatch) memset(ecc_code, 0xff, 6); +#endif + return 0; +} + +static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +{ + int i, ret = 0; + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + void __iomem *docptr = doc->virtadr; + volatile u_char dummy; + int emptymatch = 1; + + /* flush the pipeline */ + if (DoC_is_2000(doc)) { + dummy = ReadDOC(docptr, 2k_ECCStatus); + dummy = ReadDOC(docptr, 2k_ECCStatus); + dummy = ReadDOC(docptr, 2k_ECCStatus); + } else if (DoC_is_MillenniumPlus(doc)) { + dummy = ReadDOC(docptr, Mplus_ECCConf); + dummy = ReadDOC(docptr, Mplus_ECCConf); + dummy = ReadDOC(docptr, Mplus_ECCConf); + } else { + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); + } + + /* Error occured ? */ + if (dummy & 0x80) { + for (i = 0; i < 6; i++) { + if (DoC_is_MillenniumPlus(doc)) + calc_ecc[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); + else + calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); + if (calc_ecc[i] != empty_read_syndrome[i]) + emptymatch = 0; + } + /* If emptymatch=1, the read syndrome is consistent with an + all-0xff data and stored ecc block. Check the stored ecc. */ + if (emptymatch) { + for (i = 0; i < 6; i++) { + if (read_ecc[i] == 0xff) continue; + emptymatch = 0; + break; + } + } + /* If emptymatch still =1, check the data block. */ + if (emptymatch) { + /* Note: this somewhat expensive test should not be triggered + often. It could be optimized away by examining the data in + the readbuf routine, and remembering the result. */ + for (i = 0; i < 512; i++) { + if (dat[i] == 0xff) continue; + emptymatch = 0; + break; + } + } + /* If emptymatch still =1, this is almost certainly a freshly- + erased block, in which case the ECC will not come out right. + We'll suppress the error and tell the caller everything's + OK. Because it is. */ + if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); + if (ret > 0) + printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); + } + if (DoC_is_MillenniumPlus(doc)) + WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); + else + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + if (no_ecc_failures && (ret == -1)) { + printk(KERN_ERR "suppressing ECC failure\n"); + ret = 0; + } + return ret; +} + +/*u_char mydatabuf[528]; */ + +static struct nand_oobinfo doc200x_oobinfo = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 6, + .eccpos = {0, 1, 2, 3, 4, 5}, + .oobfree = { {8, 8} } +}; + +/* Find the (I)NFTL Media Header, and optionally also the mirror media header. + On sucessful return, buf will contain a copy of the media header for + further processing. id is the string to scan for, and will presumably be + either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media + header. The page #s of the found media headers are placed in mh0_page and + mh1_page in the DOC private structure. */ +static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, + const char *id, int findmirror) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift); + int ret; + size_t retlen; + + end = min(end, mtd->size); /* paranoia */ + for (offs = 0; offs < end; offs += mtd->erasesize) { + ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); + if (retlen != mtd->oobblock) continue; + if (ret) { + printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", + offs); + } + if (memcmp(buf, id, 6)) continue; + printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs); + if (doc->mh0_page == -1) { + doc->mh0_page = offs >> this->page_shift; + if (!findmirror) return 1; + continue; + } + doc->mh1_page = offs >> this->page_shift; + return 2; + } + if (doc->mh0_page == -1) { + printk(KERN_WARNING "DiskOnChip %s Media Header not found.\n", id); + return 0; + } + /* Only one mediaheader was found. We want buf to contain a + mediaheader on return, so we'll have to re-read the one we found. */ + offs = doc->mh0_page << this->page_shift; + ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); + if (retlen != mtd->oobblock) { + /* Insanity. Give up. */ + printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); + return 0; + } + return 1; +} + +static inline int __init nftl_partscan(struct mtd_info *mtd, + struct mtd_partition *parts) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + int ret = 0; + u_char *buf; + struct NFTLMediaHeader *mh; + const unsigned psize = 1 << this->page_shift; + unsigned blocks, maxblocks; + int offs, numheaders; + + buf = kmalloc(mtd->oobblock, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); + return 0; + } + if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out; + mh = (struct NFTLMediaHeader *) buf; + +/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */ +/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */ + printk(KERN_INFO " DataOrgID = %s\n" + " NumEraseUnits = %d\n" + " FirstPhysicalEUN = %d\n" + " FormattedSize = %d\n" + " UnitSizeFactor = %d\n", + mh->DataOrgID, mh->NumEraseUnits, + mh->FirstPhysicalEUN, mh->FormattedSize, + mh->UnitSizeFactor); +/*#endif */ + + blocks = mtd->size >> this->phys_erase_shift; + maxblocks = min(32768U, mtd->erasesize - psize); + + if (mh->UnitSizeFactor == 0x00) { + /* Auto-determine UnitSizeFactor. The constraints are: + - There can be at most 32768 virtual blocks. + - There can be at most (virtual block size - page size) + virtual blocks (because MediaHeader+BBT must fit in 1). + */ + mh->UnitSizeFactor = 0xff; + while (blocks > maxblocks) { + blocks >>= 1; + maxblocks = min(32768U, (maxblocks << 1) + psize); + mh->UnitSizeFactor--; + } + printk(KERN_WARNING "UnitSizeFactor=0x00 detected. Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFactor); + } + + /* NOTE: The lines below modify internal variables of the NAND and MTD + layers; variables with have already been configured by nand_scan. + Unfortunately, we didn't know before this point what these values + should be. Thus, this code is somewhat dependant on the exact + implementation of the NAND layer. */ + if (mh->UnitSizeFactor != 0xff) { + this->bbt_erase_shift += (0xff - mh->UnitSizeFactor); + mtd->erasesize <<= (0xff - mh->UnitSizeFactor); + printk(KERN_INFO "Setting virtual erase size to %d\n", mtd->erasesize); + blocks = mtd->size >> this->bbt_erase_shift; + maxblocks = min(32768U, mtd->erasesize - psize); + } + + if (blocks > maxblocks) { + printk(KERN_ERR "UnitSizeFactor of 0x%02x is inconsistent with device size. Aborting.\n", mh->UnitSizeFactor); + goto out; + } + + /* Skip past the media headers. */ + offs = max(doc->mh0_page, doc->mh1_page); + offs <<= this->page_shift; + offs += mtd->erasesize; + + /*parts[0].name = " DiskOnChip Boot / Media Header partition"; */ + /*parts[0].offset = 0; */ + /*parts[0].size = offs; */ + + parts[0].name = " DiskOnChip BDTL partition"; + parts[0].offset = offs; + parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift; + + offs += parts[0].size; + if (offs < mtd->size) { + parts[1].name = " DiskOnChip Remainder partition"; + parts[1].offset = offs; + parts[1].size = mtd->size - offs; + ret = 2; + goto out; + } + ret = 1; +out: + kfree(buf); + return ret; +} + +/* This is a stripped-down copy of the code in inftlmount.c */ +static inline int __init inftl_partscan(struct mtd_info *mtd, + struct mtd_partition *parts) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + int ret = 0; + u_char *buf; + struct INFTLMediaHeader *mh; + struct INFTLPartition *ip; + int numparts = 0; + int blocks; + int vshift, lastvunit = 0; + int i; + int end = mtd->size; + + if (inftl_bbt_write) + end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift); + + buf = kmalloc(mtd->oobblock, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); + return 0; + } + + if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out; + doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); + mh = (struct INFTLMediaHeader *) buf; + + mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); + mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); + mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions); + mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); + mh->FormatFlags = le32_to_cpu(mh->FormatFlags); + mh->PercentUsed = le32_to_cpu(mh->PercentUsed); + +/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */ +/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */ + printk(KERN_INFO " bootRecordID = %s\n" + " NoOfBootImageBlocks = %d\n" + " NoOfBinaryPartitions = %d\n" + " NoOfBDTLPartitions = %d\n" + " BlockMultiplerBits = %d\n" + " FormatFlgs = %d\n" + " OsakVersion = %d.%d.%d.%d\n" + " PercentUsed = %d\n", + mh->bootRecordID, mh->NoOfBootImageBlocks, + mh->NoOfBinaryPartitions, + mh->NoOfBDTLPartitions, + mh->BlockMultiplierBits, mh->FormatFlags, + ((unsigned char *) &mh->OsakVersion)[0] & 0xf, + ((unsigned char *) &mh->OsakVersion)[1] & 0xf, + ((unsigned char *) &mh->OsakVersion)[2] & 0xf, + ((unsigned char *) &mh->OsakVersion)[3] & 0xf, + mh->PercentUsed); +/*#endif */ + + vshift = this->phys_erase_shift + mh->BlockMultiplierBits; + + blocks = mtd->size >> vshift; + if (blocks > 32768) { + printk(KERN_ERR "BlockMultiplierBits=%d is inconsistent with device size. Aborting.\n", mh->BlockMultiplierBits); + goto out; + } + + blocks = doc->chips_per_floor << (this->chip_shift - this->phys_erase_shift); + if (inftl_bbt_write && (blocks > mtd->erasesize)) { + printk(KERN_ERR "Writeable BBTs spanning more than one erase block are not yet supported. FIX ME!\n"); + goto out; + } + + /* Scan the partitions */ + for (i = 0; (i < 4); i++) { + ip = &(mh->Partitions[i]); + ip->virtualUnits = le32_to_cpu(ip->virtualUnits); + ip->firstUnit = le32_to_cpu(ip->firstUnit); + ip->lastUnit = le32_to_cpu(ip->lastUnit); + ip->flags = le32_to_cpu(ip->flags); + ip->spareUnits = le32_to_cpu(ip->spareUnits); + ip->Reserved0 = le32_to_cpu(ip->Reserved0); + +/*#ifdef CONFIG_MTD_DEBUG_VERBOSE */ +/* if (CONFIG_MTD_DEBUG_VERBOSE >= 2) */ + printk(KERN_INFO " PARTITION[%d] ->\n" + " virtualUnits = %d\n" + " firstUnit = %d\n" + " lastUnit = %d\n" + " flags = 0x%x\n" + " spareUnits = %d\n", + i, ip->virtualUnits, ip->firstUnit, + ip->lastUnit, ip->flags, + ip->spareUnits); +/*#endif */ + +/* + if ((i == 0) && (ip->firstUnit > 0)) { + parts[0].name = " DiskOnChip IPL / Media Header partition"; + parts[0].offset = 0; + parts[0].size = mtd->erasesize * ip->firstUnit; + numparts = 1; + } +*/ + + if (ip->flags & INFTL_BINARY) + parts[numparts].name = " DiskOnChip BDK partition"; + else + parts[numparts].name = " DiskOnChip BDTL partition"; + parts[numparts].offset = ip->firstUnit << vshift; + parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift; + numparts++; + if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit; + if (ip->flags & INFTL_LAST) break; + } + lastvunit++; + if ((lastvunit << vshift) < end) { + parts[numparts].name = " DiskOnChip Remainder partition"; + parts[numparts].offset = lastvunit << vshift; + parts[numparts].size = end - parts[numparts].offset; + numparts++; + } + ret = numparts; +out: + kfree(buf); + return ret; +} + +static int __init nftl_scan_bbt(struct mtd_info *mtd) +{ + int ret, numparts; + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + struct mtd_partition parts[2]; + + memset((char *) parts, 0, sizeof(parts)); + /* On NFTL, we have to find the media headers before we can read the + BBTs, since they're stored in the media header eraseblocks. */ + numparts = nftl_partscan(mtd, parts); + if (!numparts) return -EIO; + this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | + NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | + NAND_BBT_VERSION; + this->bbt_td->veroffs = 7; + this->bbt_td->pages[0] = doc->mh0_page + 1; + if (doc->mh1_page != -1) { + this->bbt_md->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | + NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | + NAND_BBT_VERSION; + this->bbt_md->veroffs = 7; + this->bbt_md->pages[0] = doc->mh1_page + 1; + } else { + this->bbt_md = NULL; + } + + /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. + At least as nand_bbt.c is currently written. */ + if ((ret = nand_scan_bbt(mtd, NULL))) + return ret; + add_mtd_device(mtd); +#ifdef CONFIG_MTD_PARTITIONS + if (!no_autopart) + add_mtd_partitions(mtd, parts, numparts); +#endif + return 0; +} + +static int __init inftl_scan_bbt(struct mtd_info *mtd) +{ + int ret, numparts; + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + struct mtd_partition parts[5]; + + if (this->numchips > doc->chips_per_floor) { + printk(KERN_ERR "Multi-floor INFTL devices not yet supported.\n"); + return -EIO; + } + + if (DoC_is_MillenniumPlus(doc)) { + this->bbt_td->options = NAND_BBT_2BIT | NAND_BBT_ABSPAGE; + if (inftl_bbt_write) + this->bbt_td->options |= NAND_BBT_WRITE; + this->bbt_td->pages[0] = 2; + this->bbt_md = NULL; + } else { + this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | + NAND_BBT_VERSION; + if (inftl_bbt_write) + this->bbt_td->options |= NAND_BBT_WRITE; + this->bbt_td->offs = 8; + this->bbt_td->len = 8; + this->bbt_td->veroffs = 7; + this->bbt_td->maxblocks = INFTL_BBT_RESERVED_BLOCKS; + this->bbt_td->reserved_block_code = 0x01; + this->bbt_td->pattern = "MSYS_BBT"; + + this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | + NAND_BBT_VERSION; + if (inftl_bbt_write) + this->bbt_md->options |= NAND_BBT_WRITE; + this->bbt_md->offs = 8; + this->bbt_md->len = 8; + this->bbt_md->veroffs = 7; + this->bbt_md->maxblocks = INFTL_BBT_RESERVED_BLOCKS; + this->bbt_md->reserved_block_code = 0x01; + this->bbt_md->pattern = "TBB_SYSM"; + } + + /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. + At least as nand_bbt.c is currently written. */ + if ((ret = nand_scan_bbt(mtd, NULL))) + return ret; + memset((char *) parts, 0, sizeof(parts)); + numparts = inftl_partscan(mtd, parts); + /* At least for now, require the INFTL Media Header. We could probably + do without it for non-INFTL use, since all it gives us is + autopartitioning, but I want to give it more thought. */ + if (!numparts) return -EIO; + add_mtd_device(mtd); +#ifdef CONFIG_MTD_PARTITIONS + if (!no_autopart) + add_mtd_partitions(mtd, parts, numparts); +#endif + return 0; +} + +static inline int __init doc2000_init(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + + this->write_byte = doc2000_write_byte; + this->read_byte = doc2000_read_byte; + this->write_buf = doc2000_writebuf; + this->read_buf = doc2000_readbuf; + this->verify_buf = doc2000_verifybuf; + this->scan_bbt = nftl_scan_bbt; + + doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO; + doc2000_count_chips(mtd); + mtd->name = "DiskOnChip 2000 (NFTL Model)"; + return (4 * doc->chips_per_floor); +} + +static inline int __init doc2001_init(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + + this->write_byte = doc2001_write_byte; + this->read_byte = doc2001_read_byte; + this->write_buf = doc2001_writebuf; + this->read_buf = doc2001_readbuf; + this->verify_buf = doc2001_verifybuf; + + ReadDOC(doc->virtadr, ChipID); + ReadDOC(doc->virtadr, ChipID); + ReadDOC(doc->virtadr, ChipID); + if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) { + /* It's not a Millennium; it's one of the newer + DiskOnChip 2000 units with a similar ASIC. + Treat it like a Millennium, except that it + can have multiple chips. */ + doc2000_count_chips(mtd); + mtd->name = "DiskOnChip 2000 (INFTL Model)"; + this->scan_bbt = inftl_scan_bbt; + return (4 * doc->chips_per_floor); + } else { + /* Bog-standard Millennium */ + doc->chips_per_floor = 1; + mtd->name = "DiskOnChip Millennium"; + this->scan_bbt = nftl_scan_bbt; + return 1; + } +} + +static inline int __init doc2001plus_init(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + struct doc_priv *doc = this->priv; + + this->write_byte = NULL; + this->read_byte = doc2001plus_read_byte; + this->write_buf = doc2001plus_writebuf; + this->read_buf = doc2001plus_readbuf; + this->verify_buf = doc2001plus_verifybuf; + this->scan_bbt = inftl_scan_bbt; + this->hwcontrol = NULL; + this->select_chip = doc2001plus_select_chip; + this->cmdfunc = doc2001plus_command; + this->enable_hwecc = doc2001plus_enable_hwecc; + + doc->chips_per_floor = 1; + mtd->name = "DiskOnChip Millennium Plus"; + + return 1; +} + +static inline int __init doc_probe(unsigned long physadr) +{ + unsigned char ChipID; + struct mtd_info *mtd; + struct nand_chip *nand; + struct doc_priv *doc; + void __iomem *virtadr; + unsigned char save_control; + unsigned char tmp, tmpb, tmpc; + int reg, len, numchips; + int ret = 0; + + virtadr = ioremap(physadr, DOC_IOREMAP_LEN); + if (!virtadr) { + printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr); + return -EIO; + } + + /* It's not possible to cleanly detect the DiskOnChip - the + * bootup procedure will put the device into reset mode, and + * it's not possible to talk to it without actually writing + * to the DOCControl register. So we store the current contents + * of the DOCControl register's location, in case we later decide + * that it's not a DiskOnChip, and want to put it back how we + * found it. + */ + save_control = ReadDOC(virtadr, DOCControl); + + /* Reset the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + virtadr, DOCControl); + + /* Enable the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + virtadr, DOCControl); + + ChipID = ReadDOC(virtadr, ChipID); + + switch(ChipID) { + case DOC_ChipID_Doc2k: + reg = DoC_2k_ECCStatus; + break; + case DOC_ChipID_DocMil: + reg = DoC_ECCConf; + break; + case DOC_ChipID_DocMilPlus16: + case DOC_ChipID_DocMilPlus32: + case 0: + /* Possible Millennium Plus, need to do more checks */ + /* Possibly release from power down mode */ + for (tmp = 0; (tmp < 4); tmp++) + ReadDOC(virtadr, Mplus_Power); + + /* Reset the Millennium Plus ASIC */ + tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | + DOC_MODE_BDECT; + WriteDOC(tmp, virtadr, Mplus_DOCControl); + WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); + + mdelay(1); + /* Enable the Millennium Plus ASIC */ + tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | + DOC_MODE_BDECT; + WriteDOC(tmp, virtadr, Mplus_DOCControl); + WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); + mdelay(1); + + ChipID = ReadDOC(virtadr, ChipID); + + switch (ChipID) { + case DOC_ChipID_DocMilPlus16: + reg = DoC_Mplus_Toggle; + break; + case DOC_ChipID_DocMilPlus32: + printk(KERN_ERR "DiskOnChip Millennium Plus 32MB is not supported, ignoring.\n"); + default: + ret = -ENODEV; + goto notfound; + } + break; + + default: + ret = -ENODEV; + goto notfound; + } + /* Check the TOGGLE bit in the ECC register */ + tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; + tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; + tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; + if ((tmp == tmpb) || (tmp != tmpc)) { + printk(KERN_WARNING "Possible DiskOnChip at 0x%lx failed TOGGLE test, dropping.\n", physadr); + ret = -ENODEV; + goto notfound; + } + + for (mtd = doclist; mtd; mtd = doc->nextdoc) { + unsigned char oldval; + unsigned char newval; + nand = mtd->priv; + doc = nand->priv; + /* Use the alias resolution register to determine if this is + in fact the same DOC aliased to a new address. If writes + to one chip's alias resolution register change the value on + the other chip, they're the same chip. */ + if (ChipID == DOC_ChipID_DocMilPlus16) { + oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); + newval = ReadDOC(virtadr, Mplus_AliasResolution); + } else { + oldval = ReadDOC(doc->virtadr, AliasResolution); + newval = ReadDOC(virtadr, AliasResolution); + } + if (oldval != newval) + continue; + if (ChipID == DOC_ChipID_DocMilPlus16) { + WriteDOC(~newval, virtadr, Mplus_AliasResolution); + oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); + WriteDOC(newval, virtadr, Mplus_AliasResolution); /* restore it */ + } else { + WriteDOC(~newval, virtadr, AliasResolution); + oldval = ReadDOC(doc->virtadr, AliasResolution); + WriteDOC(newval, virtadr, AliasResolution); /* restore it */ + } + newval = ~newval; + if (oldval == newval) { + printk(KERN_DEBUG "Found alias of DOC at 0x%lx to 0x%lx\n", doc->physadr, physadr); + goto notfound; + } + } + + printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr); + + len = sizeof(struct mtd_info) + + sizeof(struct nand_chip) + + sizeof(struct doc_priv) + + (2 * sizeof(struct nand_bbt_descr)); + mtd = kmalloc(len, GFP_KERNEL); + if (!mtd) { + printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); + ret = -ENOMEM; + goto fail; + } + memset(mtd, 0, len); + + nand = (struct nand_chip *) (mtd + 1); + doc = (struct doc_priv *) (nand + 1); + nand->bbt_td = (struct nand_bbt_descr *) (doc + 1); + nand->bbt_md = nand->bbt_td + 1; + + mtd->priv = nand; + mtd->owner = THIS_MODULE; + + nand->priv = doc; + nand->select_chip = doc200x_select_chip; + nand->hwcontrol = doc200x_hwcontrol; + nand->dev_ready = doc200x_dev_ready; + nand->waitfunc = doc200x_wait; + nand->block_bad = doc200x_block_bad; + nand->enable_hwecc = doc200x_enable_hwecc; + nand->calculate_ecc = doc200x_calculate_ecc; + nand->correct_data = doc200x_correct_data; + + nand->autooob = &doc200x_oobinfo; + nand->eccmode = NAND_ECC_HW6_512; + nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; + + doc->physadr = physadr; + doc->virtadr = virtadr; + doc->ChipID = ChipID; + doc->curfloor = -1; + doc->curchip = -1; + doc->mh0_page = -1; + doc->mh1_page = -1; + doc->nextdoc = doclist; + + if (ChipID == DOC_ChipID_Doc2k) + numchips = doc2000_init(mtd); + else if (ChipID == DOC_ChipID_DocMilPlus16) + numchips = doc2001plus_init(mtd); + else + numchips = doc2001_init(mtd); + + if ((ret = nand_scan(mtd, numchips))) { + /* DBB note: i believe nand_release is necessary here, as + buffers may have been allocated in nand_base. Check with + Thomas. FIX ME! */ + /* nand_release will call del_mtd_device, but we haven't yet + added it. This is handled without incident by + del_mtd_device, as far as I can tell. */ + nand_release(mtd); + kfree(mtd); + goto fail; + } + + /* Success! */ + doclist = mtd; + return 0; + +notfound: + /* Put back the contents of the DOCControl register, in case it's not + actually a DiskOnChip. */ + WriteDOC(save_control, virtadr, DOCControl); +fail: + iounmap(virtadr); + return ret; +} + +static void release_nanddoc(void) +{ + struct mtd_info *mtd, *nextmtd; + struct nand_chip *nand; + struct doc_priv *doc; + + for (mtd = doclist; mtd; mtd = nextmtd) { + nand = mtd->priv; + doc = nand->priv; + + nextmtd = doc->nextdoc; + nand_release(mtd); + iounmap(doc->virtadr); + kfree(mtd); + } +} + +static int __init init_nanddoc(void) +{ + int i, ret = 0; + + /* We could create the decoder on demand, if memory is a concern. + * This way we have it handy, if an error happens + * + * Symbolsize is 10 (bits) + * Primitve polynomial is x^10+x^3+1 + * first consecutive root is 510 + * primitve element to generate roots = 1 + * generator polinomial degree = 4 + */ + rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); + if (!rs_decoder) { + printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); + return -ENOMEM; + } + + if (doc_config_location) { + printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location); + ret = doc_probe(doc_config_location); + if (ret < 0) + goto outerr; + } else { + for (i=0; (doc_locations[i] != 0xffffffff); i++) { + doc_probe(doc_locations[i]); + } + } + /* No banner message any more. Print a message if no DiskOnChip + found, so the user knows we at least tried. */ + if (!doclist) { + printk(KERN_INFO "No valid DiskOnChip devices found\n"); + ret = -ENODEV; + goto outerr; + } + return 0; +outerr: + free_rs(rs_decoder); + return ret; +} + +static void __exit cleanup_nanddoc(void) +{ + /* Cleanup the nand/DoC resources */ + release_nanddoc(); + + /* Free the reed solomon resources */ + if (rs_decoder) { + free_rs(rs_decoder); + } +} + +module_init(init_nanddoc); +module_exit(cleanup_nanddoc); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Woodhouse "); +MODULE_DESCRIPTION("M-Systems DiskOnChip 2000, Millennium and Millennium Plus device driver\n"); +#endif diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c new file mode 100644 index 0000000..ae5e8aa --- /dev/null +++ b/drivers/nand/nand.c @@ -0,0 +1,84 @@ +/* + * (C) Copyright 2005 + * 2N Telekomunikace, a.s. + * Ladislav Michl + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) + +#include +#include + +#ifndef CFG_NAND_BASE_LIST +#define CFG_NAND_BASE_LIST { CFG_NAND_BASE } +#endif + +int nand_curr_device = -1; +nand_info_t nand_info[CFG_MAX_NAND_DEVICE]; + +static struct nand_chip nand_chip[CFG_MAX_NAND_DEVICE]; +static ulong base_address[CFG_MAX_NAND_DEVICE] = CFG_NAND_BASE_LIST; + +static const char default_nand_name[] = "nand"; + +extern int board_nand_init(struct nand_chip *nand); + +static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, + ulong base_addr) +{ + mtd->priv = nand; + + nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; + if (board_nand_init(nand) == 0) { + if (nand_scan(mtd, 1) == 0) { + if (!mtd->name) + mtd->name = (char *)default_nand_name; + } else + mtd->name = NULL; + } else { + mtd->name = NULL; + mtd->size = 0; + } + +} + +void nand_init(void) +{ + int i; + unsigned int size = 0; + for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { + nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); + size += nand_info[i].size; + if (nand_curr_device == -1) + nand_curr_device = i; + } + printf("%lu MB\n", size / (1024 * 1024)); + +#ifdef CFG_NAND_SELECT_DEVICE + /* + * Select the chip in the board/cpu specific driver + */ + board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device); +#endif +} + +#endif diff --git a/drivers/nand/nand_base.c b/drivers/nand/nand_base.c new file mode 100644 index 0000000..12d1f39 --- /dev/null +++ b/drivers/nand/nand_base.c @@ -0,0 +1,2705 @@ +/* + * drivers/mtd/nand.c + * + * Overview: + * This is the generic MTD driver for NAND flash devices. It should be + * capable of working with almost all NAND chips currently available. + * Basic support for AG-AND chips is provided. + * + * Additional technical information is available on + * http://www.linux-mtd.infradead.org/tech/nand.html + * + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * 2002 Thomas Gleixner (tglx@linutronix.de) + * + * 02-08-2004 tglx: support for strange chips, which cannot auto increment + * pages on read / read_oob + * + * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes + * pointed this out, as he marked an auto increment capable chip + * as NOAUTOINCR in the board driver. + * Make reads over block boundaries work too + * + * 04-14-2004 tglx: first working version for 2k page size chips + * + * 05-19-2004 tglx: Basic support for Renesas AG-AND chips + * + * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared + * among multiple independend devices. Suggestions and initial patch + * from Ben Dooks + * + * Credits: + * David Woodhouse for adding multichip support + * + * Aleph One Ltd. and Toby Churchill Ltd. for supporting the + * rework for 2K page size chips + * + * TODO: + * Enable cached programming for 2k page size chips + * Check, if mtd->ecctype should be set to MTD_ECC_HW + * if we have HW ecc support. + * The AG-AND chips have nice features for speed improvement, + * which are not supported yet. Read / program 4 pages in one go. + * + * $Id: nand_base.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +/* XXX U-BOOT XXX */ +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MTD_PARTITIONS +#include +#endif + +#endif + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_JFFS2_NAND +#include +#endif + +/* Define default oob placement schemes for large and small page devices */ +static struct nand_oobinfo nand_oob_8 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 3, + .eccpos = {0, 1, 2}, + .oobfree = { {3, 2}, {6, 2} } +}; + +static struct nand_oobinfo nand_oob_16 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 6, + .eccpos = {0, 1, 2, 3, 6, 7}, + .oobfree = { {8, 8} } +}; + +/* RS ECC */ +/*static struct nand_oobinfo nand_oob_64_rs = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 40, + .eccpos = { + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63}, + .oobfree = {{6,18}} +};*/ + +static struct nand_oobinfo nand_oob_64 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 24, + .eccpos = { + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63}, + .oobfree = { {2, 38} } +}; + +/* This is used for padding purposes in nand_write_oob */ +static u_char ffchars[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +/* + * NAND low-level MTD interface functions + */ +static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len); +static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len); +static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len); + +static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); +static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); +static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); +static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf); +static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); +static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf); +/* XXX U-BOOT XXX */ +#if 0 +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t * retlen); +static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); +#endif +static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); +static void nand_sync (struct mtd_info *mtd); + +/* Some internal functions */ +static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, + struct nand_oobinfo *oobsel, int mode); +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, + u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode); +#else +#define nand_verify_pages(...) (0) +#endif + +static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); + +/** + * nand_release_device - [GENERIC] release chip + * @mtd: MTD device structure + * + * Deselect, release chip lock and wake up anyone waiting on the device + */ +/* XXX U-BOOT XXX */ +#if 0 +static void nand_release_device (struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + /* De-select the NAND device */ + this->select_chip(mtd, -1); + /* Do we have a hardware controller ? */ + if (this->controller) { + spin_lock(&this->controller->lock); + this->controller->active = NULL; + spin_unlock(&this->controller->lock); + } + /* Release the chip */ + spin_lock (&this->chip_lock); + this->state = FL_READY; + wake_up (&this->wq); + spin_unlock (&this->chip_lock); +} +#else +static void nand_release_device (struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + this->select_chip(mtd, -1); /* De-select the NAND device */ +} +#endif + +/** + * nand_read_byte - [DEFAULT] read one byte from the chip + * @mtd: MTD device structure + * + * Default read function for 8bit buswith + */ +static u_char nand_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + return readb(this->IO_ADDR_R); +} + +/** + * nand_write_byte - [DEFAULT] write one byte to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * Default write function for 8it buswith + */ +static void nand_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + writeb(byte, this->IO_ADDR_W); +} + +/** + * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip + * @mtd: MTD device structure + * + * Default read function for 16bit buswith with + * endianess conversion + */ +static u_char nand_read_byte16(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + return (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); +} + +/** + * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip + * @mtd: MTD device structure + * @byte: pointer to data byte to write + * + * Default write function for 16bit buswith with + * endianess conversion + */ +static void nand_write_byte16(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); +} + +/** + * nand_read_word - [DEFAULT] read one word from the chip + * @mtd: MTD device structure + * + * Default read function for 16bit buswith without + * endianess conversion + */ +static u16 nand_read_word(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + return readw(this->IO_ADDR_R); +} + +/** + * nand_write_word - [DEFAULT] write one word to the chip + * @mtd: MTD device structure + * @word: data word to write + * + * Default write function for 16bit buswith without + * endianess conversion + */ +static void nand_write_word(struct mtd_info *mtd, u16 word) +{ + struct nand_chip *this = mtd->priv; + writew(word, this->IO_ADDR_W); +} + +/** + * nand_select_chip - [DEFAULT] control CE line + * @mtd: MTD device structure + * @chip: chipnumber to select, -1 for deselect + * + * Default select function for 1 chip devices. + */ +static void nand_select_chip(struct mtd_info *mtd, int chip) +{ + struct nand_chip *this = mtd->priv; + switch(chip) { + case -1: + this->hwcontrol(mtd, NAND_CTL_CLRNCE); + break; + case 0: + this->hwcontrol(mtd, NAND_CTL_SETNCE); + break; + + default: + BUG(); + } +} + +/** + * nand_write_buf - [DEFAULT] write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + * + * Default write function for 8bit buswith + */ +static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + + for (i=0; iIO_ADDR_W); +} + +/** + * nand_read_buf - [DEFAULT] read chip data into buffer + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read + * + * Default read function for 8bit buswith + */ +static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + + for (i=0; iIO_ADDR_R); +} + +/** + * nand_verify_buf - [DEFAULT] Verify chip data against buffer + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare + * + * Default verify function for 8bit buswith + */ +static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + + for (i=0; iIO_ADDR_R)) + return -EFAULT; + + return 0; +} + +/** + * nand_write_buf16 - [DEFAULT] write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + * + * Default write function for 16bit buswith + */ +static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + u16 *p = (u16 *) buf; + len >>= 1; + + for (i=0; iIO_ADDR_W); + +} + +/** + * nand_read_buf16 - [DEFAULT] read chip data into buffer + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read + * + * Default read function for 16bit buswith + */ +static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + u16 *p = (u16 *) buf; + len >>= 1; + + for (i=0; iIO_ADDR_R); +} + +/** + * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare + * + * Default verify function for 16bit buswith + */ +static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + struct nand_chip *this = mtd->priv; + u16 *p = (u16 *) buf; + len >>= 1; + + for (i=0; iIO_ADDR_R)) + return -EFAULT; + + return 0; +} + +/** + * nand_block_bad - [DEFAULT] Read bad block marker from the chip + * @mtd: MTD device structure + * @ofs: offset from device start + * @getchip: 0, if the chip is already selected + * + * Check, if the block is bad. + */ +static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +{ + int page, chipnr, res = 0; + struct nand_chip *this = mtd->priv; + u16 bad; + + if (getchip) { + page = (int)(ofs >> this->page_shift); + chipnr = (int)(ofs >> this->chip_shift); + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_READING); + + /* Select the NAND device */ + this->select_chip(mtd, chipnr); + } else + page = (int) ofs; + + if (this->options & NAND_BUSWIDTH_16) { + this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); + bad = cpu_to_le16(this->read_word(mtd)); + if (this->badblockpos & 0x1) + bad >>= 1; + if ((bad & 0xFF) != 0xff) + res = 1; + } else { + this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask); + if (this->read_byte(mtd) != 0xff) + res = 1; + } + + if (getchip) { + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + } + + return res; +} + +/** + * nand_default_block_markbad - [DEFAULT] mark a block bad + * @mtd: MTD device structure + * @ofs: offset from device start + * + * This is the default implementation, which can be overridden by + * a hardware specific driver. +*/ +static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *this = mtd->priv; + u_char buf[2] = {0, 0}; + size_t retlen; + int block; + + /* Get block number */ + block = ((int) ofs) >> this->bbt_erase_shift; + this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + + /* Do we have a flash based bad block table ? */ + if (this->options & NAND_USE_FLASH_BBT) + return nand_update_bbt (mtd, ofs); + + /* We write two bytes, so we dont have to mess with 16 bit access */ + ofs += mtd->oobsize + (this->badblockpos & ~0x01); + return nand_write_oob (mtd, ofs , 2, &retlen, buf); +} + +/** + * nand_check_wp - [GENERIC] check if the chip is write protected + * @mtd: MTD device structure + * Check, if the device is write protected + * + * The function expects, that the device is already selected + */ +static int nand_check_wp (struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + /* Check the WP bit */ + this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); + return (this->read_byte(mtd) & 0x80) ? 0 : 1; +} + +/** + * nand_block_checkbad - [GENERIC] Check if a block is marked bad + * @mtd: MTD device structure + * @ofs: offset from device start + * @getchip: 0, if the chip is already selected + * @allowbbt: 1, if its allowed to access the bbt area + * + * Check, if the block is bad. Either by reading the bad block table or + * calling of the scan function. + */ +static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) +{ + struct nand_chip *this = mtd->priv; + + if (!this->bbt) + return this->block_bad(mtd, ofs, getchip); + + /* Return info from the table */ + return nand_isbad_bbt (mtd, ofs, allowbbt); +} + +/** + * nand_command - [DEFAULT] Send command to NAND device + * @mtd: MTD device structure + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none + * + * Send command to NAND device. This function is used for small page + * devices (256/512 Bytes per page) + */ +static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) +{ + register struct nand_chip *this = mtd->priv; + + /* Begin command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_SETCLE); + /* + * Write out the command to the device. + */ + if (command == NAND_CMD_SEQIN) { + int readcmd; + + if (column >= mtd->oobblock) { + /* OOB area */ + column -= mtd->oobblock; + readcmd = NAND_CMD_READOOB; + } else if (column < 256) { + /* First 256 bytes --> READ0 */ + readcmd = NAND_CMD_READ0; + } else { + column -= 256; + readcmd = NAND_CMD_READ1; + } + this->write_byte(mtd, readcmd); + } + this->write_byte(mtd, command); + + /* Set ALE and clear CLE to start address cycle */ + this->hwcontrol(mtd, NAND_CTL_CLRCLE); + + if (column != -1 || page_addr != -1) { + this->hwcontrol(mtd, NAND_CTL_SETALE); + + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (this->options & NAND_BUSWIDTH_16) + column >>= 1; + this->write_byte(mtd, column); + } + if (page_addr != -1) { + this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); + this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); + /* One more address cycle for devices > 32MiB */ + if (this->chipsize > (32 << 20)) + this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); + } + /* Latch in address */ + this->hwcontrol(mtd, NAND_CTL_CLRALE); + } + + /* + * program and erase have their own busy handlers + * status and sequential in needs no delay + */ + switch (command) { + + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + case NAND_CMD_ERASE2: + case NAND_CMD_SEQIN: + case NAND_CMD_STATUS: + return; + + case NAND_CMD_RESET: + if (this->dev_ready) + break; + udelay(this->chip_delay); + this->hwcontrol(mtd, NAND_CTL_SETCLE); + this->write_byte(mtd, NAND_CMD_STATUS); + this->hwcontrol(mtd, NAND_CTL_CLRCLE); + while ( !(this->read_byte(mtd) & 0x40)); + return; + + /* This applies to read commands */ + default: + /* + * If we don't have access to the busy pin, we apply the given + * command delay + */ + if (!this->dev_ready) { + udelay (this->chip_delay); + return; + } + } + + /* Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. */ + ndelay (100); + /* wait until command is processed */ + while (!this->dev_ready(mtd)); +} + +/** + * nand_command_lp - [DEFAULT] Send command to NAND large page device + * @mtd: MTD device structure + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none + * + * Send command to NAND device. This is the version for the new large page devices + * We dont have the seperate regions as we have in the small page devices. + * We must emulate NAND_CMD_READOOB to keep the code compatible. + * + */ +static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr) +{ + register struct nand_chip *this = mtd->priv; + + /* Emulate NAND_CMD_READOOB */ + if (command == NAND_CMD_READOOB) { + column += mtd->oobblock; + command = NAND_CMD_READ0; + } + + + /* Begin command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_SETCLE); + /* Write out the command to the device. */ + this->write_byte(mtd, command); + /* End command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_CLRCLE); + + if (column != -1 || page_addr != -1) { + this->hwcontrol(mtd, NAND_CTL_SETALE); + + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (this->options & NAND_BUSWIDTH_16) + column >>= 1; + this->write_byte(mtd, column & 0xff); + this->write_byte(mtd, column >> 8); + } + if (page_addr != -1) { + this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); + this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); + /* One more address cycle for devices > 128MiB */ + if (this->chipsize > (128 << 20)) + this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff)); + } + /* Latch in address */ + this->hwcontrol(mtd, NAND_CTL_CLRALE); + } + + /* + * program and erase have their own busy handlers + * status and sequential in needs no delay + */ + switch (command) { + + case NAND_CMD_CACHEDPROG: + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + case NAND_CMD_ERASE2: + case NAND_CMD_SEQIN: + case NAND_CMD_STATUS: + return; + + + case NAND_CMD_RESET: + if (this->dev_ready) + break; + udelay(this->chip_delay); + this->hwcontrol(mtd, NAND_CTL_SETCLE); + this->write_byte(mtd, NAND_CMD_STATUS); + this->hwcontrol(mtd, NAND_CTL_CLRCLE); + while ( !(this->read_byte(mtd) & 0x40)); + return; + + case NAND_CMD_READ0: + /* Begin command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_SETCLE); + /* Write out the start read command */ + this->write_byte(mtd, NAND_CMD_READSTART); + /* End command latch cycle */ + this->hwcontrol(mtd, NAND_CTL_CLRCLE); + /* Fall through into ready check */ + + /* This applies to read commands */ + default: + /* + * If we don't have access to the busy pin, we apply the given + * command delay + */ + if (!this->dev_ready) { + udelay (this->chip_delay); + return; + } + } + + /* Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. */ + ndelay (100); + /* wait until command is processed */ + while (!this->dev_ready(mtd)); +} + +/** + * nand_get_device - [GENERIC] Get chip for selected access + * @this: the nand chip descriptor + * @mtd: MTD device structure + * @new_state: the state which is requested + * + * Get the device and lock it for exclusive access + */ +/* XXX U-BOOT XXX */ +#if 0 +static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) +{ + struct nand_chip *active = this; + + DECLARE_WAITQUEUE (wait, current); + + /* + * Grab the lock and see if the device is available + */ +retry: + /* Hardware controller shared among independend devices */ + if (this->controller) { + spin_lock (&this->controller->lock); + if (this->controller->active) + active = this->controller->active; + else + this->controller->active = this; + spin_unlock (&this->controller->lock); + } + + if (active == this) { + spin_lock (&this->chip_lock); + if (this->state == FL_READY) { + this->state = new_state; + spin_unlock (&this->chip_lock); + return; + } + } + set_current_state (TASK_UNINTERRUPTIBLE); + add_wait_queue (&active->wq, &wait); + spin_unlock (&active->chip_lock); + schedule (); + remove_wait_queue (&active->wq, &wait); + goto retry; +} +#else +static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) {} +#endif + +/** + * nand_wait - [DEFAULT] wait until the command is done + * @mtd: MTD device structure + * @this: NAND chip structure + * @state: state to select the max. timeout value + * + * Wait for command done. This applies to erase and program only + * Erase can take up to 400ms and program up to 20ms according to + * general NAND and SmartMedia specs + * +*/ +/* XXX U-BOOT XXX */ +#if 0 +static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +{ + unsigned long timeo = jiffies; + int status; + + if (state == FL_ERASING) + timeo += (HZ * 400) / 1000; + else + timeo += (HZ * 20) / 1000; + + /* Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. */ + ndelay (100); + + if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) + this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); + else + this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); + + while (time_before(jiffies, timeo)) { + /* Check, if we were interrupted */ + if (this->state != state) + return 0; + + if (this->dev_ready) { + if (this->dev_ready(mtd)) + break; + } else { + if (this->read_byte(mtd) & NAND_STATUS_READY) + break; + } + yield (); + } + status = (int) this->read_byte(mtd); + return status; + + return 0; +} +#else +static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +{ + unsigned long timeo; + + if (state == FL_ERASING) + timeo = (CFG_HZ * 400) / 1000; + else + timeo = (CFG_HZ * 20) / 1000; + + if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) + this->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1); + else + this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + + reset_timer(); + + while (1) { + if (get_timer(0) > timeo) { + printf("Timeout!"); + return 0x01; + } + + if (this->dev_ready) { + if (this->dev_ready(mtd)) + break; + } else { + if (this->read_byte(mtd) & NAND_STATUS_READY) + break; + } + } +#ifdef PPCHAMELON_NAND_TIMER_HACK + reset_timer(); + while (get_timer(0) < 10); +#endif /* PPCHAMELON_NAND_TIMER_HACK */ + + return this->read_byte(mtd); +} +#endif + +/** + * nand_write_page - [GENERIC] write one page + * @mtd: MTD device structure + * @this: NAND chip structure + * @page: startpage inside the chip, must be called with (page & this->pagemask) + * @oob_buf: out of band data buffer + * @oobsel: out of band selecttion structre + * @cached: 1 = enable cached programming if supported by chip + * + * Nand_page_program function is used for write and writev ! + * This function will always program a full page of data + * If you call it with a non page aligned buffer, you're lost :) + * + * Cached programming is not supported yet. + */ +static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, + u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) +{ + int i, status; + u_char ecc_code[40] /*ecc_code[32]*/; /* RS ECC */ + int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; + uint *oob_config = oobsel->eccpos; + int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; + int eccbytes = 0; + + /* FIXME: Enable cached programming */ + cached = 0; + + /* Send command to begin auto page programming */ + this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); + + /* Write out complete page of data, take care of eccmode */ + switch (eccmode) { + /* No ecc, write all */ + case NAND_ECC_NONE: + printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); + this->write_buf(mtd, this->data_poi, mtd->oobblock); + break; + + /* Software ecc 3/256, write all */ + case NAND_ECC_SOFT: + for (; eccsteps; eccsteps--) { + this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); + /*for (i = 0; i < this->eccbytes; i++, eccidx++) RS ECC */ + for (i = 0; i < 3; i++, eccidx++) + oob_buf[oob_config[eccidx]] = ecc_code[i]; + datidx += this->eccsize; + } + this->write_buf(mtd, this->data_poi, mtd->oobblock); + break; + default: + eccbytes = this->eccbytes; + for (; eccsteps; eccsteps--) { + /* enable hardware ecc logic for write */ + this->enable_hwecc(mtd, NAND_ECC_WRITE); + this->write_buf(mtd, &this->data_poi[datidx], this->eccsize); + this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); + for (i = 0; i < eccbytes; i++, eccidx++) + oob_buf[oob_config[eccidx]] = ecc_code[i]; + /* If the hardware ecc provides syndromes then + * the ecc code must be written immidiately after + * the data bytes (words) */ + if (this->options & NAND_HWECC_SYNDROME) + this->write_buf(mtd, ecc_code, eccbytes); + datidx += this->eccsize; + } + break; + } + + /* Write out OOB data */ + if (this->options & NAND_HWECC_SYNDROME) + this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); + else + this->write_buf(mtd, oob_buf, mtd->oobsize); + + /* Send command to actually program the data */ + this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1); + + if (!cached) { + /* call wait ready function */ + status = this->waitfunc (mtd, this, FL_WRITING); + /* See if device thinks it succeeded */ + if (status & 0x01) { + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page); + return -EIO; + } + } else { + /* FIXME: Implement cached programming ! */ + /* wait until cache is ready*/ + /* status = this->waitfunc (mtd, this, FL_CACHEDRPG); */ + } + return 0; +} + +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE +/** + * nand_verify_pages - [GENERIC] verify the chip contents after a write + * @mtd: MTD device structure + * @this: NAND chip structure + * @page: startpage inside the chip, must be called with (page & this->pagemask) + * @numpages: number of pages to verify + * @oob_buf: out of band data buffer + * @oobsel: out of band selecttion structre + * @chipnr: number of the current chip + * @oobmode: 1 = full buffer verify, 0 = ecc only + * + * The NAND device assumes that it is always writing to a cleanly erased page. + * Hence, it performs its internal write verification only on bits that + * transitioned from 1 to 0. The device does NOT verify the whole page on a + * byte by byte basis. It is possible that the page was not completely erased + * or the page is becoming unusable due to wear. The read with ECC would catch + * the error later when the ECC page check fails, but we would rather catch + * it early in the page write stage. Better to write no data than invalid data. + */ +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, + u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) +{ + int i, j, datidx = 0, oobofs = 0, res = -EIO; + int eccsteps = this->eccsteps; + int hweccbytes; + u_char oobdata[64]; + + hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; + + /* Send command to read back the first page */ + this->cmdfunc (mtd, NAND_CMD_READ0, 0, page); + + for(;;) { + for (j = 0; j < eccsteps; j++) { + /* Loop through and verify the data */ + if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) { + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); + goto out; + } + datidx += mtd->eccsize; + /* Have we a hw generator layout ? */ + if (!hweccbytes) + continue; + if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) { + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); + goto out; + } + oobofs += hweccbytes; + } + + /* check, if we must compare all data or if we just have to + * compare the ecc bytes + */ + if (oobmode) { + if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) { + DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); + goto out; + } + } else { + /* Read always, else autoincrement fails */ + this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps); + + if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) { + int ecccnt = oobsel->eccbytes; + + for (i = 0; i < ecccnt; i++) { + int idx = oobsel->eccpos[i]; + if (oobdata[idx] != oob_buf[oobofs + idx] ) { + DEBUG (MTD_DEBUG_LEVEL0, + "%s: Failed ECC write " + "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i); + goto out; + } + } + } + } + oobofs += mtd->oobsize - hweccbytes * eccsteps; + page++; + numpages--; + + /* Apply delay or wait for ready/busy pin + * Do this before the AUTOINCR check, so no problems + * arise if a chip which does auto increment + * is marked as NOAUTOINCR by the board driver. + * Do this also before returning, so the chip is + * ready for the next command. + */ + if (!this->dev_ready) + udelay (this->chip_delay); + else + while (!this->dev_ready(mtd)); + + /* All done, return happy */ + if (!numpages) + return 0; + + + /* Check, if the chip supports auto page increment */ + if (!NAND_CANAUTOINCR(this)) + this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); + } + /* + * Terminate the read command. We come here in case of an error + * So we must issue a reset command. + */ +out: + this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1); + return res; +} +#endif + +/** + * nand_read - [MTD Interface] MTD compability function for nand_read_ecc + * @mtd: MTD device structure + * @from: offset to read from + * @len: number of bytes to read + * @retlen: pointer to variable to store the number of read bytes + * @buf: the databuffer to put data + * + * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL +*/ +static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) +{ + return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL); +} + + +/** + * nand_read_ecc - [MTD Interface] Read data with ECC + * @mtd: MTD device structure + * @from: offset to read from + * @len: number of bytes to read + * @retlen: pointer to variable to store the number of read bytes + * @buf: the databuffer to put data + * @oob_buf: filesystem supplied oob data buffer + * @oobsel: oob selection structure + * + * NAND read with ECC + */ +static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel) +{ + int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1; + int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; + struct nand_chip *this = mtd->priv; + u_char *data_poi, *oob_data = oob_buf; + u_char ecc_calc[40] /*ecc_calc[32]*/; /* RS ECC */ + u_char ecc_code[40] /*ecc_code[32]*/; /* RS ECC */ + int eccmode, eccsteps; + unsigned *oob_config; + int datidx; + int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; + int eccbytes; + int compareecc = 1; + int oobreadlen; + + + DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n"); + *retlen = 0; + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd ,FL_READING); + + /* use userspace supplied oobinfo, if zero */ + if (oobsel == NULL) + oobsel = &mtd->oobinfo; + + /* Autoplace of oob data ? Use the default placement scheme */ + if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) + oobsel = this->autooob; + + eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; + oob_config = oobsel->eccpos; + + /* Select the NAND device */ + chipnr = (int)(from >> this->chip_shift); + this->select_chip(mtd, chipnr); + + /* First we calculate the starting page */ + realpage = (int) (from >> this->page_shift); + page = realpage & this->pagemask; + + /* Get raw starting column */ + col = from & (mtd->oobblock - 1); + + end = mtd->oobblock; + ecc = this->eccsize; + eccbytes = this->eccbytes; + + if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) + compareecc = 0; + + oobreadlen = mtd->oobsize; + if (this->options & NAND_HWECC_SYNDROME) + oobreadlen -= oobsel->eccbytes; + + /* Loop until all data read */ + while (read < len) { + + int aligned = (!col && (len - read) >= end); + /* + * If the read is not page aligned, we have to read into data buffer + * due to ecc, else we read into return buffer direct + */ + if (aligned) + data_poi = &buf[read]; + else + data_poi = this->data_buf; + + /* Check, if we have this page in the buffer + * + * FIXME: Make it work when we must provide oob data too, + * check the usage of data_buf oob field + */ + if (realpage == this->pagebuf && !oob_buf) { + /* aligned read ? */ + if (aligned) + memcpy (data_poi, this->data_buf, end); + goto readdata; + } + + /* Check, if we must send the read command */ + if (sndcmd) { + this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); + sndcmd = 0; + } + + /* get oob area, if we have no oob buffer from fs-driver */ + if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE || + oobsel->useecc == MTD_NANDECC_AUTOPL_USR) + oob_data = &this->data_buf[end]; + + eccsteps = this->eccsteps; + + switch (eccmode) { + case NAND_ECC_NONE: { /* No ECC, Read in a page */ +/* XXX U-BOOT XXX */ +#if 0 + static unsigned long lastwhinge = 0; + if ((lastwhinge / HZ) != (jiffies / HZ)) { + printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n"); + lastwhinge = jiffies; + } +#else + puts("Reading data from NAND FLASH without ECC is not recommended\n"); +#endif + this->read_buf(mtd, data_poi, end); + break; + } + + case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ + this->read_buf(mtd, data_poi, end); + for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) + /* for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) RS ECC */ + this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); + break; + + default: + for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { + this->enable_hwecc(mtd, NAND_ECC_READ); + this->read_buf(mtd, &data_poi[datidx], ecc); + + /* HW ecc with syndrome calculation must read the + * syndrome from flash immidiately after the data */ + if (!compareecc) { + /* Some hw ecc generators need to know when the + * syndrome is read from flash */ + this->enable_hwecc(mtd, NAND_ECC_READSYN); + this->read_buf(mtd, &oob_data[i], eccbytes); + /* We calc error correction directly, it checks the hw + * generator for an error, reads back the syndrome and + * does the error correction on the fly */ + if (this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]) == -1) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " + "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); + ecc_failed++; + } + } else { + this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); + } + } + break; + } + + /* read oobdata */ + this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen); + + /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */ + if (!compareecc) + goto readoob; + + /* Pick the ECC bytes out of the oob data */ + for (j = 0; j < oobsel->eccbytes; j++) + ecc_code[j] = oob_data[oob_config[j]]; + + /* correct data, if neccecary */ + for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { + ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); + + /* Get next chunk of ecc bytes */ + j += eccbytes; + + /* Check, if we have a fs supplied oob-buffer, + * This is the legacy mode. Used by YAFFS1 + * Should go away some day + */ + if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { + int *p = (int *)(&oob_data[mtd->oobsize]); + p[i] = ecc_status; + } + + if (ecc_status == -1) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); + ecc_failed++; + } + } + + readoob: + /* check, if we have a fs supplied oob-buffer */ + if (oob_buf) { + /* without autoplace. Legacy mode used by YAFFS1 */ + switch(oobsel->useecc) { + case MTD_NANDECC_AUTOPLACE: + case MTD_NANDECC_AUTOPL_USR: + /* Walk through the autoplace chunks */ + for (i = 0, j = 0; j < mtd->oobavail; i++) { + int from = oobsel->oobfree[i][0]; + int num = oobsel->oobfree[i][1]; + memcpy(&oob_buf[oob], &oob_data[from], num); + j+= num; + } + oob += mtd->oobavail; + break; + case MTD_NANDECC_PLACE: + /* YAFFS1 legacy mode */ + oob_data += this->eccsteps * sizeof (int); + default: + oob_data += mtd->oobsize; + } + } + readdata: + /* Partial page read, transfer data into fs buffer */ + if (!aligned) { + for (j = col; j < end && read < len; j++) + buf[read++] = data_poi[j]; + this->pagebuf = realpage; + } else + read += mtd->oobblock; + + /* Apply delay or wait for ready/busy pin + * Do this before the AUTOINCR check, so no problems + * arise if a chip which does auto increment + * is marked as NOAUTOINCR by the board driver. + */ + if (!this->dev_ready) + udelay (this->chip_delay); + else + while (!this->dev_ready(mtd)); + + if (read == len) + break; + + /* For subsequent reads align to page boundary. */ + col = 0; + /* Increment page address */ + realpage++; + + page = realpage & this->pagemask; + /* Check, if we cross a chip boundary */ + if (!page) { + chipnr++; + this->select_chip(mtd, -1); + this->select_chip(mtd, chipnr); + } + /* Check, if the chip supports auto page increment + * or if we have hit a block boundary. + */ + if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) + sndcmd = 1; + } + + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + + /* + * Return success, if no ECC failures, else -EBADMSG + * fs driver will take care of that, because + * retlen == desired len and result == -EBADMSG + */ + *retlen = read; + return ecc_failed ? -EBADMSG : 0; +} + +/** + * nand_read_oob - [MTD Interface] NAND read out-of-band + * @mtd: MTD device structure + * @from: offset to read from + * @len: number of bytes to read + * @retlen: pointer to variable to store the number of read bytes + * @buf: the databuffer to put data + * + * NAND read out-of-band data from the spare area + */ +static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) +{ + int i, col, page, chipnr; + struct nand_chip *this = mtd->priv; + int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; + + DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Shift to get page */ + page = (int)(from >> this->page_shift); + chipnr = (int)(from >> this->chip_shift); + + /* Mask to get column */ + col = from & (mtd->oobsize - 1); + + /* Initialize return length value */ + *retlen = 0; + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n"); + *retlen = 0; + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd , FL_READING); + + /* Select the NAND device */ + this->select_chip(mtd, chipnr); + + /* Send the read command */ + this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask); + /* + * Read the data, if we read more than one page + * oob data, let the device transfer the data ! + */ + i = 0; + while (i < len) { + int thislen = mtd->oobsize - col; + thislen = min_t(int, thislen, len); + this->read_buf(mtd, &buf[i], thislen); + i += thislen; + + /* Apply delay or wait for ready/busy pin + * Do this before the AUTOINCR check, so no problems + * arise if a chip which does auto increment + * is marked as NOAUTOINCR by the board driver. + */ + if (!this->dev_ready) + udelay (this->chip_delay); + else + while (!this->dev_ready(mtd)); + + /* Read more ? */ + if (i < len) { + page++; + col = 0; + + /* Check, if we cross a chip boundary */ + if (!(page & this->pagemask)) { + chipnr++; + this->select_chip(mtd, -1); + this->select_chip(mtd, chipnr); + } + + /* Check, if the chip supports auto page increment + * or if we have hit a block boundary. + */ + if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) { + /* For subsequent page reads set offset to 0 */ + this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); + } + } + } + + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + + /* Return happy */ + *retlen = len; + return 0; +} + +/** + * nand_read_raw - [GENERIC] Read raw data including oob into buffer + * @mtd: MTD device structure + * @buf: temporary buffer + * @from: offset to read from + * @len: number of bytes to read + * @ooblen: number of oob data bytes to read + * + * Read raw data including oob into buffer + */ +int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen) +{ + struct nand_chip *this = mtd->priv; + int page = (int) (from >> this->page_shift); + int chip = (int) (from >> this->chip_shift); + int sndcmd = 1; + int cnt = 0; + int pagesize = mtd->oobblock + mtd->oobsize; + int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd , FL_READING); + + this->select_chip (mtd, chip); + + /* Add requested oob length */ + len += ooblen; + + while (len) { + if (sndcmd) + this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask); + sndcmd = 0; + + this->read_buf (mtd, &buf[cnt], pagesize); + + len -= pagesize; + cnt += pagesize; + page++; + + if (!this->dev_ready) + udelay (this->chip_delay); + else + while (!this->dev_ready(mtd)); + + /* Check, if the chip supports auto page increment */ + if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) + sndcmd = 1; + } + + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + return 0; +} + + +/** + * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer + * @mtd: MTD device structure + * @fsbuf: buffer given by fs driver + * @oobsel: out of band selection structre + * @autoplace: 1 = place given buffer into the oob bytes + * @numpages: number of pages to prepare + * + * Return: + * 1. Filesystem buffer available and autoplacement is off, + * return filesystem buffer + * 2. No filesystem buffer or autoplace is off, return internal + * buffer + * 3. Filesystem buffer is given and autoplace selected + * put data from fs buffer into internal buffer and + * retrun internal buffer + * + * Note: The internal buffer is filled with 0xff. This must + * be done only once, when no autoplacement happens + * Autoplacement sets the buffer dirty flag, which + * forces the 0xff fill before using the buffer again. + * +*/ +static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel, + int autoplace, int numpages) +{ + struct nand_chip *this = mtd->priv; + int i, len, ofs; + + /* Zero copy fs supplied buffer */ + if (fsbuf && !autoplace) + return fsbuf; + + /* Check, if the buffer must be filled with ff again */ + if (this->oobdirty) { + memset (this->oob_buf, 0xff, + mtd->oobsize << (this->phys_erase_shift - this->page_shift)); + this->oobdirty = 0; + } + + /* If we have no autoplacement or no fs buffer use the internal one */ + if (!autoplace || !fsbuf) + return this->oob_buf; + + /* Walk through the pages and place the data */ + this->oobdirty = 1; + ofs = 0; + while (numpages--) { + for (i = 0, len = 0; len < mtd->oobavail; i++) { + int to = ofs + oobsel->oobfree[i][0]; + int num = oobsel->oobfree[i][1]; + memcpy (&this->oob_buf[to], fsbuf, num); + len += num; + fsbuf += num; + } + ofs += mtd->oobavail; + } + return this->oob_buf; +} + +#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0 + +/** + * nand_write - [MTD Interface] compability function for nand_write_ecc + * @mtd: MTD device structure + * @to: offset to write to + * @len: number of bytes to write + * @retlen: pointer to variable to store the number of written bytes + * @buf: the data to write + * + * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL + * +*/ +static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) +{ + return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); +} + +/** + * nand_write_ecc - [MTD Interface] NAND write with ECC + * @mtd: MTD device structure + * @to: offset to write to + * @len: number of bytes to write + * @retlen: pointer to variable to store the number of written bytes + * @buf: the data to write + * @eccbuf: filesystem supplied oob data buffer + * @oobsel: oob selection structure + * + * NAND write with ECC + */ +static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel) +{ + int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; + int autoplace = 0, numpages, totalpages; + struct nand_chip *this = mtd->priv; + u_char *oobbuf, *bufstart; + int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); + + DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Initialize retlen, in case of early exit */ + *retlen = 0; + + /* Do not allow write past end of device */ + if ((to + len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); + return -EINVAL; + } + + /* reject writes, which are not page aligned */ + if (NOTALIGNED (to) || NOTALIGNED(len)) { + printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_WRITING); + + /* Calculate chipnr */ + chipnr = (int)(to >> this->chip_shift); + /* Select the NAND device */ + this->select_chip(mtd, chipnr); + + /* Check, if it is write protected */ + if (nand_check_wp(mtd)) + goto out; + + /* if oobsel is NULL, use chip defaults */ + if (oobsel == NULL) + oobsel = &mtd->oobinfo; + + /* Autoplace of oob data ? Use the default placement scheme */ + if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { + oobsel = this->autooob; + autoplace = 1; + } + if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) + autoplace = 1; + + /* Setup variables and oob buffer */ + totalpages = len >> this->page_shift; + page = (int) (to >> this->page_shift); + /* Invalidate the page cache, if we write to the cached page */ + if (page <= this->pagebuf && this->pagebuf < (page + totalpages)) + this->pagebuf = -1; + + /* Set it relative to chip */ + page &= this->pagemask; + startpage = page; + /* Calc number of pages we can write in one go */ + numpages = min (ppblock - (startpage & (ppblock - 1)), totalpages); + oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages); + bufstart = (u_char *)buf; + + /* Loop until all data is written */ + while (written < len) { + + this->data_poi = (u_char*) &buf[written]; + /* Write one page. If this is the last page to write + * or the last page in this block, then use the + * real pageprogram command, else select cached programming + * if supported by the chip. + */ + ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0)); + if (ret) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); + goto out; + } + /* Next oob page */ + oob += mtd->oobsize; + /* Update written bytes count */ + written += mtd->oobblock; + if (written == len) + goto cmp; + + /* Increment page address */ + page++; + + /* Have we hit a block boundary ? Then we have to verify and + * if verify is ok, we have to setup the oob buffer for + * the next pages. + */ + if (!(page & (ppblock - 1))){ + int ofs; + this->data_poi = bufstart; + ret = nand_verify_pages (mtd, this, startpage, + page - startpage, + oobbuf, oobsel, chipnr, (eccbuf != NULL)); + if (ret) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); + goto out; + } + *retlen = written; + bufstart = (u_char*) &buf[written]; + + ofs = autoplace ? mtd->oobavail : mtd->oobsize; + if (eccbuf) + eccbuf += (page - startpage) * ofs; + totalpages -= page - startpage; + numpages = min (totalpages, ppblock); + page &= this->pagemask; + startpage = page; + oob = 0; + this->oobdirty = 1; + oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, + autoplace, numpages); + /* Check, if we cross a chip boundary */ + if (!page) { + chipnr++; + this->select_chip(mtd, -1); + this->select_chip(mtd, chipnr); + } + } + } + /* Verify the remaining pages */ +cmp: + this->data_poi = bufstart; + ret = nand_verify_pages (mtd, this, startpage, totalpages, + oobbuf, oobsel, chipnr, (eccbuf != NULL)); + if (!ret) + *retlen = written; + else + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); + +out: + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + + return ret; +} + + +/** + * nand_write_oob - [MTD Interface] NAND write out-of-band + * @mtd: MTD device structure + * @to: offset to write to + * @len: number of bytes to write + * @retlen: pointer to variable to store the number of written bytes + * @buf: the data to write + * + * NAND write out-of-band + */ +static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) +{ + int column, page, status, ret = -EIO, chipnr; + struct nand_chip *this = mtd->priv; + + DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Shift to get page */ + page = (int) (to >> this->page_shift); + chipnr = (int) (to >> this->chip_shift); + + /* Mask to get column */ + column = to & (mtd->oobsize - 1); + + /* Initialize return length value */ + *retlen = 0; + + /* Do not allow write past end of page */ + if ((column + len) > mtd->oobsize) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_WRITING); + + /* Select the NAND device */ + this->select_chip(mtd, chipnr); + + /* Reset the chip. Some chips (like the Toshiba TC5832DC found + in one of my DiskOnChip 2000 test units) will clear the whole + data page too if we don't do this. I have no clue why, but + I seem to have 'fixed' it in the doc2000 driver in + August 1999. dwmw2. */ + this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + + /* Check, if it is write protected */ + if (nand_check_wp(mtd)) + goto out; + + /* Invalidate the page cache, if we write to the cached page */ + if (page == this->pagebuf) + this->pagebuf = -1; + + if (NAND_MUST_PAD(this)) { + /* Write out desired data */ + this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask); + /* prepad 0xff for partial programming */ + this->write_buf(mtd, ffchars, column); + /* write data */ + this->write_buf(mtd, buf, len); + /* postpad 0xff for partial programming */ + this->write_buf(mtd, ffchars, mtd->oobsize - (len+column)); + } else { + /* Write out desired data */ + this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask); + /* write data */ + this->write_buf(mtd, buf, len); + } + /* Send command to program the OOB data */ + this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1); + + status = this->waitfunc (mtd, this, FL_WRITING); + + /* See if device thinks it succeeded */ + if (status & 0x01) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page); + ret = -EIO; + goto out; + } + /* Return happy */ + *retlen = len; + +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + /* Send command to read back the data */ + this->cmdfunc (mtd, NAND_CMD_READOOB, column, page & this->pagemask); + + if (this->verify_buf(mtd, buf, len)) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page); + ret = -EIO; + goto out; + } +#endif + ret = 0; +out: + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + + return ret; +} + +/* XXX U-BOOT XXX */ +#if 0 +/** + * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc + * @mtd: MTD device structure + * @vecs: the iovectors to write + * @count: number of vectors + * @to: offset to write to + * @retlen: pointer to variable to store the number of written bytes + * + * NAND write with kvec. This just calls the ecc function + */ +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, + loff_t to, size_t * retlen) +{ + return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL)); +} + +/** + * nand_writev_ecc - [MTD Interface] write with iovec with ecc + * @mtd: MTD device structure + * @vecs: the iovectors to write + * @count: number of vectors + * @to: offset to write to + * @retlen: pointer to variable to store the number of written bytes + * @eccbuf: filesystem supplied oob data buffer + * @oobsel: oob selection structure + * + * NAND write with iovec with ecc + */ +static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, + loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) +{ + int i, page, len, total_len, ret = -EIO, written = 0, chipnr; + int oob, numpages, autoplace = 0, startpage; + struct nand_chip *this = mtd->priv; + int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); + u_char *oobbuf, *bufstart; + + /* Preset written len for early exit */ + *retlen = 0; + + /* Calculate total length of data */ + total_len = 0; + for (i = 0; i < count; i++) + total_len += (int) vecs[i].iov_len; + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); + + /* Do not allow write past end of page */ + if ((to + total_len) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n"); + return -EINVAL; + } + + /* reject writes, which are not page aligned */ + if (NOTALIGNED (to) || NOTALIGNED(total_len)) { + printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_WRITING); + + /* Get the current chip-nr */ + chipnr = (int) (to >> this->chip_shift); + /* Select the NAND device */ + this->select_chip(mtd, chipnr); + + /* Check, if it is write protected */ + if (nand_check_wp(mtd)) + goto out; + + /* if oobsel is NULL, use chip defaults */ + if (oobsel == NULL) + oobsel = &mtd->oobinfo; + + /* Autoplace of oob data ? Use the default placement scheme */ + if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { + oobsel = this->autooob; + autoplace = 1; + } + if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) + autoplace = 1; + + /* Setup start page */ + page = (int) (to >> this->page_shift); + /* Invalidate the page cache, if we write to the cached page */ + if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) + this->pagebuf = -1; + + startpage = page & this->pagemask; + + /* Loop until all kvec' data has been written */ + len = 0; + while (count) { + /* If the given tuple is >= pagesize then + * write it out from the iov + */ + if ((vecs->iov_len - len) >= mtd->oobblock) { + /* Calc number of pages we can write + * out of this iov in one go */ + numpages = (vecs->iov_len - len) >> this->page_shift; + /* Do not cross block boundaries */ + numpages = min (ppblock - (startpage & (ppblock - 1)), numpages); + oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); + bufstart = (u_char *)vecs->iov_base; + bufstart += len; + this->data_poi = bufstart; + oob = 0; + for (i = 1; i <= numpages; i++) { + /* Write one page. If this is the last page to write + * then use the real pageprogram command, else select + * cached programming if supported by the chip. + */ + ret = nand_write_page (mtd, this, page & this->pagemask, + &oobbuf[oob], oobsel, i != numpages); + if (ret) + goto out; + this->data_poi += mtd->oobblock; + len += mtd->oobblock; + oob += mtd->oobsize; + page++; + } + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } else { + /* We must use the internal buffer, read data out of each + * tuple until we have a full page to write + */ + int cnt = 0; + while (cnt < mtd->oobblock) { + if (vecs->iov_base != NULL && vecs->iov_len) + this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } + this->pagebuf = page; + this->data_poi = this->data_buf; + bufstart = this->data_poi; + numpages = 1; + oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); + ret = nand_write_page (mtd, this, page & this->pagemask, + oobbuf, oobsel, 0); + if (ret) + goto out; + page++; + } + + this->data_poi = bufstart; + ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0); + if (ret) + goto out; + + written += mtd->oobblock * numpages; + /* All done ? */ + if (!count) + break; + + startpage = page & this->pagemask; + /* Check, if we cross a chip boundary */ + if (!startpage) { + chipnr++; + this->select_chip(mtd, -1); + this->select_chip(mtd, chipnr); + } + } + ret = 0; +out: + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + + *retlen = written; + return ret; +} +#endif + +/** + * single_erease_cmd - [GENERIC] NAND standard block erase command function + * @mtd: MTD device structure + * @page: the page address of the block which will be erased + * + * Standard erase command for NAND chips + */ +static void single_erase_cmd (struct mtd_info *mtd, int page) +{ + struct nand_chip *this = mtd->priv; + /* Send commands to erase a block */ + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page); + this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1); +} + +/** + * multi_erease_cmd - [GENERIC] AND specific block erase command function + * @mtd: MTD device structure + * @page: the page address of the block which will be erased + * + * AND multi block erase command function + * Erase 4 consecutive blocks + */ +static void multi_erase_cmd (struct mtd_info *mtd, int page) +{ + struct nand_chip *this = mtd->priv; + /* Send commands to erase a block */ + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); + this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page); + this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1); +} + +/** + * nand_erase - [MTD Interface] erase block(s) + * @mtd: MTD device structure + * @instr: erase instruction + * + * Erase one ore more blocks + */ +static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + return nand_erase_nand (mtd, instr, 0); +} + +/** + * nand_erase_intern - [NAND Interface] erase block(s) + * @mtd: MTD device structure + * @instr: erase instruction + * @allowbbt: allow erasing the bbt area + * + * Erase one ore more blocks + */ +int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt) +{ + int page, len, status, pages_per_block, ret, chipnr; + struct nand_chip *this = mtd->priv; + + DEBUG (MTD_DEBUG_LEVEL3, + "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); + + /* Start address must align on block boundary */ + if (instr->addr & ((1 << this->phys_erase_shift) - 1)) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n"); + return -EINVAL; + } + + /* Length must align on block boundary */ + if (instr->len & ((1 << this->phys_erase_shift) - 1)) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n"); + return -EINVAL; + } + + /* Do not allow erase past end of device */ + if ((instr->len + instr->addr) > mtd->size) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n"); + return -EINVAL; + } + + instr->fail_addr = 0xffffffff; + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_ERASING); + + /* Shift to get first page */ + page = (int) (instr->addr >> this->page_shift); + chipnr = (int) (instr->addr >> this->chip_shift); + + /* Calculate pages in each block */ + pages_per_block = 1 << (this->phys_erase_shift - this->page_shift); + + /* Select the NAND device */ + this->select_chip(mtd, chipnr); + + /* Check the WP bit */ + /* Check, if it is write protected */ + if (nand_check_wp(mtd)) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n"); + instr->state = MTD_ERASE_FAILED; + goto erase_exit; + } + + /* Loop through the pages */ + len = instr->len; + + instr->state = MTD_ERASING; + + while (len) { +#ifndef NAND_ALLOW_ERASE_ALL + /* Check if we have a bad block, we do not erase bad blocks ! */ + if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) { + printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page); + instr->state = MTD_ERASE_FAILED; + goto erase_exit; + } +#endif + /* Invalidate the page cache, if we erase the block which contains + the current cached page */ + if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block)) + this->pagebuf = -1; + + this->erase_cmd (mtd, page & this->pagemask); + + status = this->waitfunc (mtd, this, FL_ERASING); + + /* See if block erase succeeded */ + if (status & 0x01) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page); + instr->state = MTD_ERASE_FAILED; + instr->fail_addr = (page << this->page_shift); + goto erase_exit; + } + + /* Increment page address and decrement length */ + len -= (1 << this->phys_erase_shift); + page += pages_per_block; + + /* Check, if we cross a chip boundary */ + if (len && !(page & this->pagemask)) { + chipnr++; + this->select_chip(mtd, -1); + this->select_chip(mtd, chipnr); + } + } + instr->state = MTD_ERASE_DONE; + +erase_exit: + + ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; + /* Do call back function */ + if (!ret) + mtd_erase_callback(instr); + + /* Deselect and wake up anyone waiting on the device */ + nand_release_device(mtd); + + /* Return more or less happy */ + return ret; +} + +/** + * nand_sync - [MTD Interface] sync + * @mtd: MTD device structure + * + * Sync is actually a wait for chip ready function + */ +static void nand_sync (struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n"); + + /* Grab the lock and see if the device is available */ + nand_get_device (this, mtd, FL_SYNCING); + /* Release it and go back */ + nand_release_device (mtd); +} + + +/** + * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad + * @mtd: MTD device structure + * @ofs: offset relative to mtd start + */ +static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs) +{ + /* Check for invalid offset */ + if (ofs > mtd->size) + return -EINVAL; + + return nand_block_checkbad (mtd, ofs, 1, 0); +} + +/** + * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad + * @mtd: MTD device structure + * @ofs: offset relative to mtd start + */ +static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *this = mtd->priv; + int ret; + + if ((ret = nand_block_isbad(mtd, ofs))) { + /* If it was bad already, return success and do nothing. */ + if (ret > 0) + return 0; + return ret; + } + + return this->block_markbad(mtd, ofs); +} + +/** + * nand_scan - [NAND Interface] Scan for the NAND device + * @mtd: MTD device structure + * @maxchips: Number of chips to scan for + * + * This fills out all the not initialized function pointers + * with the defaults. + * The flash ID is read and the mtd/chip structures are + * filled with the appropriate values. Buffers are allocated if + * they are not provided by the board driver + * + */ +int nand_scan (struct mtd_info *mtd, int maxchips) +{ + int i, j, nand_maf_id, nand_dev_id, busw; + struct nand_chip *this = mtd->priv; + + /* Get buswidth to select the correct functions*/ + busw = this->options & NAND_BUSWIDTH_16; + + /* check for proper chip_delay setup, set 20us if not */ + if (!this->chip_delay) + this->chip_delay = 20; + + /* check, if a user supplied command function given */ + if (this->cmdfunc == NULL) + this->cmdfunc = nand_command; + + /* check, if a user supplied wait function given */ + if (this->waitfunc == NULL) + this->waitfunc = nand_wait; + + if (!this->select_chip) + this->select_chip = nand_select_chip; + if (!this->write_byte) + this->write_byte = busw ? nand_write_byte16 : nand_write_byte; + if (!this->read_byte) + this->read_byte = busw ? nand_read_byte16 : nand_read_byte; + if (!this->write_word) + this->write_word = nand_write_word; + if (!this->read_word) + this->read_word = nand_read_word; + if (!this->block_bad) + this->block_bad = nand_block_bad; + if (!this->block_markbad) + this->block_markbad = nand_default_block_markbad; + if (!this->write_buf) + this->write_buf = busw ? nand_write_buf16 : nand_write_buf; + if (!this->read_buf) + this->read_buf = busw ? nand_read_buf16 : nand_read_buf; + if (!this->verify_buf) + this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; + if (!this->scan_bbt) + this->scan_bbt = nand_default_bbt; + + /* Select the device */ + this->select_chip(mtd, 0); + + /* Send the command for reading device ID */ + this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); + + /* Read manufacturer and device IDs */ + nand_maf_id = this->read_byte(mtd); + nand_dev_id = this->read_byte(mtd); + /* Print and store flash device information */ + for (i = 0; nand_flash_ids[i].name != NULL; i++) { + + if (nand_dev_id != nand_flash_ids[i].id) + continue; + + if (!mtd->name) mtd->name = nand_flash_ids[i].name; + this->chipsize = nand_flash_ids[i].chipsize << 20; + + /* New devices have all the information in additional id bytes */ + if (!nand_flash_ids[i].pagesize) { + int extid; + /* The 3rd id byte contains non relevant data ATM */ + extid = this->read_byte(mtd); + /* The 4th id byte is the important one */ + extid = this->read_byte(mtd); + /* Calc pagesize */ + mtd->oobblock = 1024 << (extid & 0x3); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock / 512); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); + extid >>= 2; + /* Get buswidth information */ + busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + + } else { + /* Old devices have this data hardcoded in the + * device id table */ + mtd->erasesize = nand_flash_ids[i].erasesize; + mtd->oobblock = nand_flash_ids[i].pagesize; + mtd->oobsize = mtd->oobblock / 32; + busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16; + } + + /* Check, if buswidth is correct. Hardware drivers should set + * this correct ! */ + if (busw != (this->options & NAND_BUSWIDTH_16)) { + printk (KERN_INFO "NAND device: Manufacturer ID:" + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, + nand_manuf_ids[i].name , mtd->name); + printk (KERN_WARNING + "NAND bus width %d instead %d bit\n", + (this->options & NAND_BUSWIDTH_16) ? 16 : 8, + busw ? 16 : 8); + this->select_chip(mtd, -1); + return 1; + } + + /* Calculate the address shift from the page size */ + this->page_shift = ffs(mtd->oobblock) - 1; + this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1; + this->chip_shift = ffs(this->chipsize) - 1; + + /* Set the bad block position */ + this->badblockpos = mtd->oobblock > 512 ? + NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; + + /* Get chip options, preserve non chip based options */ + this->options &= ~NAND_CHIPOPTIONS_MSK; + this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK; + /* Set this as a default. Board drivers can override it, if neccecary */ + this->options |= NAND_NO_AUTOINCR; + /* Check if this is a not a samsung device. Do not clear the options + * for chips which are not having an extended id. + */ + if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) + this->options &= ~NAND_SAMSUNG_LP_OPTIONS; + + /* Check for AND chips with 4 page planes */ + if (this->options & NAND_4PAGE_ARRAY) + this->erase_cmd = multi_erase_cmd; + else + this->erase_cmd = single_erase_cmd; + + /* Do not replace user supplied command function ! */ + if (mtd->oobblock > 512 && this->cmdfunc == nand_command) + this->cmdfunc = nand_command_lp; + + /* Try to identify manufacturer */ + for (j = 0; nand_manuf_ids[j].id != 0x0; j++) { + if (nand_manuf_ids[j].id == nand_maf_id) + break; + } + break; + } + + if (!nand_flash_ids[i].name) { +#ifndef CFG_NAND_QUIET_TEST + printk (KERN_WARNING "No NAND device found!!!\n"); +#endif + this->select_chip(mtd, -1); + return 1; + } + + for (i=1; i < maxchips; i++) { + this->select_chip(mtd, i); + + /* Send the command for reading device ID */ + this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); + + /* Read manufacturer and device IDs */ + if (nand_maf_id != this->read_byte(mtd) || + nand_dev_id != this->read_byte(mtd)) + break; + } + if (i > 1) + printk(KERN_INFO "%d NAND chips detected\n", i); + + /* Allocate buffers, if neccecary */ + if (!this->oob_buf) { + size_t len; + len = mtd->oobsize << (this->phys_erase_shift - this->page_shift); + this->oob_buf = kmalloc (len, GFP_KERNEL); + if (!this->oob_buf) { + printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n"); + return -ENOMEM; + } + this->options |= NAND_OOBBUF_ALLOC; + } + + if (!this->data_buf) { + size_t len; + len = mtd->oobblock + mtd->oobsize; + this->data_buf = kmalloc (len, GFP_KERNEL); + if (!this->data_buf) { + if (this->options & NAND_OOBBUF_ALLOC) + kfree (this->oob_buf); + printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n"); + return -ENOMEM; + } + this->options |= NAND_DATABUF_ALLOC; + } + + /* Store the number of chips and calc total size for mtd */ + this->numchips = i; + mtd->size = i * this->chipsize; + /* Convert chipsize to number of pages per chip -1. */ + this->pagemask = (this->chipsize >> this->page_shift) - 1; + /* Preset the internal oob buffer */ + memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift)); + + /* If no default placement scheme is given, select an + * appropriate one */ + if (!this->autooob) { + /* Select the appropriate default oob placement scheme for + * placement agnostic filesystems */ + switch (mtd->oobsize) { + case 8: + this->autooob = &nand_oob_8; + break; + case 16: + this->autooob = &nand_oob_16; + break; + case 64: + /* RS ECC */ + /*this->autooob = &nand_oob_64_rs;*/ + this->autooob = &nand_oob_64; + break; + default: + printk (KERN_WARNING "No oob scheme defined for oobsize %d\n", + mtd->oobsize); +/* BUG(); */ + } + } + + /* The number of bytes available for the filesystem to place fs dependend + * oob data */ + if (this->options & NAND_BUSWIDTH_16) { + mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2); + if (this->autooob->eccbytes & 0x01) + mtd->oobavail--; + } else + mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1); + + /* + * check ECC mode, default to software + * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize + * fallback to software ECC + */ + this->eccsize = 256; /* set default eccsize */ + this->eccbytes = 3; + + switch (this->eccmode) { + case NAND_ECC_HW12_2048: + if (mtd->oobblock < 2048) { + printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n", + mtd->oobblock); + this->eccmode = NAND_ECC_SOFT; + this->calculate_ecc = nand_calculate_ecc; + this->correct_data = nand_correct_data; + } else + this->eccsize = 2048; + break; + + case NAND_ECC_HW3_512: + case NAND_ECC_HW6_512: + case NAND_ECC_HW8_512: + if (mtd->oobblock == 256) { + printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); + this->eccmode = NAND_ECC_SOFT; + this->calculate_ecc = nand_calculate_ecc; + this->correct_data = nand_correct_data; + } else + this->eccsize = 512; /* set eccsize to 512 */ + break; + + case NAND_ECC_HW3_256: + break; + + case NAND_ECC_NONE: + printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); + this->eccmode = NAND_ECC_NONE; + break; + + case NAND_ECC_SOFT: + + this->calculate_ecc = nand_calculate_ecc; + this->correct_data = nand_correct_data; + /* RS ECC + if (mtd->oobblock < 2048) + { + this->calculate_ecc = nand_calculate_ecc; + this->correct_data = nand_correct_data; + } + else + { + this->calculate_ecc = nand_calculate_ecc_rs; + this->correct_data = nand_correct_data_rs; + this->eccsize = 2048; + this->eccbytes = 40; + }*/ + + break; + + default: + printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); +/* BUG(); */ + } + + /* Check hardware ecc function availability and adjust number of ecc bytes per + * calculation step + */ + switch (this->eccmode) { + case NAND_ECC_HW12_2048: + this->eccbytes += 4; + case NAND_ECC_HW8_512: + this->eccbytes += 2; + case NAND_ECC_HW6_512: + this->eccbytes += 3; + case NAND_ECC_HW3_512: + case NAND_ECC_HW3_256: + if (this->calculate_ecc && this->correct_data && this->enable_hwecc) + break; + printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); +/* BUG(); */ + } + + mtd->eccsize = this->eccsize; + + /* Set the number of read / write steps for one page to ensure ECC generation */ + switch (this->eccmode) { + case NAND_ECC_HW12_2048: + this->eccsteps = mtd->oobblock / 2048; + break; + case NAND_ECC_HW3_512: + case NAND_ECC_HW6_512: + case NAND_ECC_HW8_512: + this->eccsteps = mtd->oobblock / 512; + break; + case NAND_ECC_HW3_256: + case NAND_ECC_SOFT: + this->eccsteps = mtd->oobblock / 256; + /* RS ECC + if (mtd->oobblock < 2048) + this->eccsteps = mtd->oobblock / 256; + else + this->eccsteps = 1; /*mtd->oobblock / 2048*/ + break; + + case NAND_ECC_NONE: + this->eccsteps = 1; + break; + } + +/* XXX U-BOOT XXX */ +#if 0 + /* Initialize state, waitqueue and spinlock */ + this->state = FL_READY; + init_waitqueue_head (&this->wq); + spin_lock_init (&this->chip_lock); +#endif + + /* De-select the device */ + this->select_chip(mtd, -1); + + /* Invalidate the pagebuffer reference */ + this->pagebuf = -1; + + /* Fill in remaining MTD driver data */ + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; + mtd->ecctype = MTD_ECC_SW; + mtd->erase = nand_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = nand_read; + mtd->write = nand_write; + mtd->read_ecc = nand_read_ecc; + mtd->write_ecc = nand_write_ecc; + mtd->read_oob = nand_read_oob; + mtd->write_oob = nand_write_oob; +/* XXX U-BOOT XXX */ +#if 0 + mtd->readv = NULL; + mtd->writev = nand_writev; + mtd->writev_ecc = nand_writev_ecc; +#endif + mtd->sync = nand_sync; +/* XXX U-BOOT XXX */ +#if 0 + mtd->lock = NULL; + mtd->unlock = NULL; + mtd->suspend = NULL; + mtd->resume = NULL; +#endif + mtd->block_isbad = nand_block_isbad; + mtd->block_markbad = nand_block_markbad; + + /* and make the autooob the default one */ + memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); +/* XXX U-BOOT XXX */ +#if 0 + mtd->owner = THIS_MODULE; +#endif + /* Build bad block table */ + return this->scan_bbt (mtd); +} + +/** + * nand_release - [NAND Interface] Free resources held by the NAND device + * @mtd: MTD device structure + */ +void nand_release (struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + +#ifdef CONFIG_MTD_PARTITIONS + /* Deregister partitions */ + del_mtd_partitions (mtd); +#endif + /* Deregister the device */ +/* XXX U-BOOT XXX */ +#if 0 + del_mtd_device (mtd); +#endif + /* Free bad block table memory, if allocated */ + if (this->bbt) + kfree (this->bbt); + /* Buffer allocated by nand_scan ? */ + if (this->options & NAND_OOBBUF_ALLOC) + kfree (this->oob_buf); + /* Buffer allocated by nand_scan ? */ + if (this->options & NAND_DATABUF_ALLOC) + kfree (this->data_buf); +} + +#endif diff --git a/drivers/nand/nand_bbt.c b/drivers/nand/nand_bbt.c new file mode 100644 index 0000000..a0df869 --- /dev/null +++ b/drivers/nand/nand_bbt.c @@ -0,0 +1,1052 @@ +/* + * drivers/mtd/nand_bbt.c + * + * Overview: + * Bad block table support for the NAND driver + * + * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) + * + * $Id: nand_bbt.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ + * + * 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. + * + * Description: + * + * When nand_scan_bbt is called, then it tries to find the bad block table + * depending on the options in the bbt descriptor(s). If a bbt is found + * then the contents are read and the memory based bbt is created. If a + * mirrored bbt is selected then the mirror is searched too and the + * versions are compared. If the mirror has a greater version number + * than the mirror bbt is used to build the memory based bbt. + * If the tables are not versioned, then we "or" the bad block information. + * If one of the bbt's is out of date or does not exist it is (re)created. + * If no bbt exists at all then the device is scanned for factory marked + * good / bad blocks and the bad block tables are created. + * + * For manufacturer created bbts like the one found on M-SYS DOC devices + * the bbt is searched and read but never created + * + * The autogenerated bad block table is located in the last good blocks + * of the device. The table is mirrored, so it can be updated eventually. + * The table is marked in the oob area with an ident pattern and a version + * number which indicates which of both tables is more up to date. + * + * The table uses 2 bits per block + * 11b: block is good + * 00b: block is factory marked bad + * 01b, 10b: block is marked bad due to wear + * + * The memory bad block table uses the following scheme: + * 00b: block is good + * 01b: block is marked bad due to wear + * 10b: block is reserved (to protect the bbt area) + * 11b: block is factory marked bad + * + * Multichip devices like DOC store the bad block info per floor. + * + * Following assumptions are made: + * - bbts start at a page boundary, if autolocated on a block boundary + * - the space neccecary for a bbt in FLASH does not exceed a block boundary + * + */ + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) + +#include +#include +#include +#include + +#include + +/** + * check_pattern - [GENERIC] check if a pattern is in the buffer + * @buf: the buffer to search + * @len: the length of buffer to search + * @paglen: the pagelength + * @td: search pattern descriptor + * + * Check for a pattern at the given place. Used to search bad block + * tables and good / bad block identifiers. + * If the SCAN_EMPTY option is set then check, if all bytes except the + * pattern area contain 0xff + * +*/ +static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) +{ + int i, end; + uint8_t *p = buf; + + end = paglen + td->offs; + if (td->options & NAND_BBT_SCANEMPTY) { + for (i = 0; i < end; i++) { + if (p[i] != 0xff) + return -1; + } + } + p += end; + + /* Compare the pattern */ + for (i = 0; i < td->len; i++) { + if (p[i] != td->pattern[i]) + return -1; + } + + p += td->len; + end += td->len; + if (td->options & NAND_BBT_SCANEMPTY) { + for (i = end; i < len; i++) { + if (*p++ != 0xff) + return -1; + } + } + return 0; +} + +/** + * read_bbt - [GENERIC] Read the bad block table starting from page + * @mtd: MTD device structure + * @buf: temporary buffer + * @page: the starting page + * @num: the number of bbt descriptors to read + * @bits: number of bits per block + * @offs: offset in the memory table + * @reserved_block_code: Pattern to identify reserved blocks + * + * Read the bad block table starting from page. + * + */ +static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, + int bits, int offs, int reserved_block_code) +{ + int res, i, j, act = 0; + struct nand_chip *this = mtd->priv; + size_t retlen, len, totlen; + loff_t from; + uint8_t msk = (uint8_t) ((1 << bits) - 1); + + totlen = (num * bits) >> 3; + from = ((loff_t)page) << this->page_shift; + + while (totlen) { + len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); + res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); + if (res < 0) { + if (retlen != len) { + printk (KERN_INFO "nand_bbt: Error reading bad block table\n"); + return res; + } + printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); + } + + /* Analyse data */ + for (i = 0; i < len; i++) { + uint8_t dat = buf[i]; + for (j = 0; j < 8; j += bits, act += 2) { + uint8_t tmp = (dat >> j) & msk; + if (tmp == msk) + continue; + if (reserved_block_code && + (tmp == reserved_block_code)) { + printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n", + ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); + this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); + continue; + } + /* Leave it for now, if its matured we can move this + * message to MTD_DEBUG_LEVEL0 */ + printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", + ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); + /* Factory marked bad or worn out ? */ + if (tmp == 0) + this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); + else + this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); + } + } + totlen -= len; + from += len; + } + return 0; +} + +/** + * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @chip: read the table for a specific chip, -1 read all chips. + * Applies only if NAND_BBT_PERCHIP option is set + * + * Read the bad block table for all chips starting at a given page + * We assume that the bbt bits are in consecutive order. +*/ +static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) +{ + struct nand_chip *this = mtd->priv; + int res = 0, i; + int bits; + + bits = td->options & NAND_BBT_NRBITS_MSK; + if (td->options & NAND_BBT_PERCHIP) { + int offs = 0; + for (i = 0; i < this->numchips; i++) { + if (chip == -1 || chip == i) + res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code); + if (res) + return res; + offs += this->chipsize >> (this->bbt_erase_shift + 2); + } + } else { + res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code); + if (res) + return res; + } + return 0; +} + +/** + * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @md: descriptor for the bad block table mirror + * + * Read the bad block table(s) for all chips starting at a given page + * We assume that the bbt bits are in consecutive order. + * +*/ +static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, + struct nand_bbt_descr *md) +{ + struct nand_chip *this = mtd->priv; + + /* Read the primary version, if available */ + if (td->options & NAND_BBT_VERSION) { + nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); + td->version[0] = buf[mtd->oobblock + td->veroffs]; + printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); + } + + /* Read the mirror version, if available */ + if (md && (md->options & NAND_BBT_VERSION)) { + nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); + md->version[0] = buf[mtd->oobblock + md->veroffs]; + printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); + } + + return 1; +} + +/** + * create_bbt - [GENERIC] Create a bad block table by scanning the device + * @mtd: MTD device structure + * @buf: temporary buffer + * @bd: descriptor for the good/bad block search pattern + * @chip: create the table for a specific chip, -1 read all chips. + * Applies only if NAND_BBT_PERCHIP option is set + * + * Create a bad block table by scanning the device + * for the given good/bad block identify pattern + */ +static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) +{ + struct nand_chip *this = mtd->priv; + int i, j, numblocks, len, scanlen; + int startblock; + loff_t from; + size_t readlen, ooblen; + + if (bd->options & NAND_BBT_SCANALLPAGES) + len = 1 << (this->bbt_erase_shift - this->page_shift); + else { + if (bd->options & NAND_BBT_SCAN2NDPAGE) + len = 2; + else + len = 1; + } + scanlen = mtd->oobblock + mtd->oobsize; + readlen = len * mtd->oobblock; + ooblen = len * mtd->oobsize; + + if (chip == -1) { + /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it + * makes shifting and masking less painful */ + numblocks = mtd->size >> (this->bbt_erase_shift - 1); + startblock = 0; + from = 0; + } else { + if (chip >= this->numchips) { + printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", + chip + 1, this->numchips); + return; + } + numblocks = this->chipsize >> (this->bbt_erase_shift - 1); + startblock = chip * numblocks; + numblocks += startblock; + from = startblock << (this->bbt_erase_shift - 1); + } + + for (i = startblock; i < numblocks;) { + nand_read_raw (mtd, buf, from, readlen, ooblen); + for (j = 0; j < len; j++) { + if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { + this->bbt[i >> 3] |= 0x03 << (i & 0x6); + break; + } + } + i += 2; + from += (1 << this->bbt_erase_shift); + } +} + +/** + * search_bbt - [GENERIC] scan the device for a specific bad block table + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * + * Read the bad block table by searching for a given ident pattern. + * Search is preformed either from the beginning up or from the end of + * the device downwards. The search starts always at the start of a + * block. + * If the option NAND_BBT_PERCHIP is given, each chip is searched + * for a bbt, which contains the bad block information of this chip. + * This is neccecary to provide support for certain DOC devices. + * + * The bbt ident pattern resides in the oob area of the first page + * in a block. + */ +static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) +{ + struct nand_chip *this = mtd->priv; + int i, chips; + int bits, startblock, block, dir; + int scanlen = mtd->oobblock + mtd->oobsize; + int bbtblocks; + + /* Search direction top -> down ? */ + if (td->options & NAND_BBT_LASTBLOCK) { + startblock = (mtd->size >> this->bbt_erase_shift) -1; + dir = -1; + } else { + startblock = 0; + dir = 1; + } + + /* Do we have a bbt per chip ? */ + if (td->options & NAND_BBT_PERCHIP) { + chips = this->numchips; + bbtblocks = this->chipsize >> this->bbt_erase_shift; + startblock &= bbtblocks - 1; + } else { + chips = 1; + bbtblocks = mtd->size >> this->bbt_erase_shift; + } + + /* Number of bits for each erase block in the bbt */ + bits = td->options & NAND_BBT_NRBITS_MSK; + + for (i = 0; i < chips; i++) { + /* Reset version information */ + td->version[i] = 0; + td->pages[i] = -1; + /* Scan the maximum number of blocks */ + for (block = 0; block < td->maxblocks; block++) { + int actblock = startblock + dir * block; + /* Read first page */ + nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); + if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { + td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); + if (td->options & NAND_BBT_VERSION) { + td->version[i] = buf[mtd->oobblock + td->veroffs]; + } + break; + } + } + startblock += this->chipsize >> this->bbt_erase_shift; + } + /* Check, if we found a bbt for each requested chip */ + for (i = 0; i < chips; i++) { + if (td->pages[i] == -1) + printk (KERN_WARNING "Bad block table not found for chip %d\n", i); + else + printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); + } + return 0; +} + +/** + * search_read_bbts - [GENERIC] scan the device for bad block table(s) + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @md: descriptor for the bad block table mirror + * + * Search and read the bad block table(s) +*/ +static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, + struct nand_bbt_descr *td, struct nand_bbt_descr *md) +{ + /* Search the primary table */ + search_bbt (mtd, buf, td); + + /* Search the mirror table */ + if (md) + search_bbt (mtd, buf, md); + + /* Force result check */ + return 1; +} + + +/** + * write_bbt - [GENERIC] (Re)write the bad block table + * + * @mtd: MTD device structure + * @buf: temporary buffer + * @td: descriptor for the bad block table + * @md: descriptor for the bad block table mirror + * @chipsel: selector for a specific chip, -1 for all + * + * (Re)write the bad block table + * +*/ +static int write_bbt (struct mtd_info *mtd, uint8_t *buf, + struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) +{ + struct nand_chip *this = mtd->priv; + struct nand_oobinfo oobinfo; + struct erase_info einfo; + int i, j, res, chip = 0; + int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; + int nrchips, bbtoffs, pageoffs; + uint8_t msk[4]; + uint8_t rcode = td->reserved_block_code; + size_t retlen, len = 0; + loff_t to; + + if (!rcode) + rcode = 0xff; + /* Write bad block table per chip rather than per device ? */ + if (td->options & NAND_BBT_PERCHIP) { + numblocks = (int) (this->chipsize >> this->bbt_erase_shift); + /* Full device write or specific chip ? */ + if (chipsel == -1) { + nrchips = this->numchips; + } else { + nrchips = chipsel + 1; + chip = chipsel; + } + } else { + numblocks = (int) (mtd->size >> this->bbt_erase_shift); + nrchips = 1; + } + + /* Loop through the chips */ + for (; chip < nrchips; chip++) { + + /* There was already a version of the table, reuse the page + * This applies for absolute placement too, as we have the + * page nr. in td->pages. + */ + if (td->pages[chip] != -1) { + page = td->pages[chip]; + goto write; + } + + /* Automatic placement of the bad block table */ + /* Search direction top -> down ? */ + if (td->options & NAND_BBT_LASTBLOCK) { + startblock = numblocks * (chip + 1) - 1; + dir = -1; + } else { + startblock = chip * numblocks; + dir = 1; + } + + for (i = 0; i < td->maxblocks; i++) { + int block = startblock + dir * i; + /* Check, if the block is bad */ + switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) { + case 0x01: + case 0x03: + continue; + } + page = block << (this->bbt_erase_shift - this->page_shift); + /* Check, if the block is used by the mirror table */ + if (!md || md->pages[chip] != page) + goto write; + } + printk (KERN_ERR "No space left to write bad block table\n"); + return -ENOSPC; +write: + + /* Set up shift count and masks for the flash table */ + bits = td->options & NAND_BBT_NRBITS_MSK; + switch (bits) { + case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break; + case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break; + case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break; + case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; + default: return -EINVAL; + } + + bbtoffs = chip * (numblocks >> 2); + + to = ((loff_t) page) << this->page_shift; + + memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); + oobinfo.useecc = MTD_NANDECC_PLACEONLY; + + /* Must we save the block contents ? */ + if (td->options & NAND_BBT_SAVECONTENT) { + /* Make it block aligned */ + to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); + len = 1 << this->bbt_erase_shift; + res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); + if (res < 0) { + if (retlen != len) { + printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n"); + return res; + } + printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n"); + } + /* Calc the byte offset in the buffer */ + pageoffs = page - (int)(to >> this->page_shift); + offs = pageoffs << this->page_shift; + /* Preset the bbt area with 0xff */ + memset (&buf[offs], 0xff, (size_t)(numblocks >> sft)); + /* Preset the bbt's oob area with 0xff */ + memset (&buf[len + pageoffs * mtd->oobsize], 0xff, + ((len >> this->page_shift) - pageoffs) * mtd->oobsize); + if (td->options & NAND_BBT_VERSION) { + buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip]; + } + } else { + /* Calc length */ + len = (size_t) (numblocks >> sft); + /* Make it page aligned ! */ + len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1); + /* Preset the buffer with 0xff */ + memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize); + offs = 0; + /* Pattern is located in oob area of first page */ + memcpy (&buf[len + td->offs], td->pattern, td->len); + if (td->options & NAND_BBT_VERSION) { + buf[len + td->veroffs] = td->version[chip]; + } + } + + /* walk through the memory table */ + for (i = 0; i < numblocks; ) { + uint8_t dat; + dat = this->bbt[bbtoffs + (i >> 2)]; + for (j = 0; j < 4; j++ , i++) { + int sftcnt = (i << (3 - sft)) & sftmsk; + /* Do not store the reserved bbt blocks ! */ + buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt); + dat >>= 2; + } + } + + memset (&einfo, 0, sizeof (einfo)); + einfo.mtd = mtd; + einfo.addr = (unsigned long) to; + einfo.len = 1 << this->bbt_erase_shift; + res = nand_erase_nand (mtd, &einfo, 1); + if (res < 0) { + printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); + return res; + } + + res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); + if (res < 0) { + printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); + return res; + } + printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", + (unsigned int) to, td->version[chip]); + + /* Mark it as used */ + td->pages[chip] = page; + } + return 0; +} + +/** + * nand_memory_bbt - [GENERIC] create a memory based bad block table + * @mtd: MTD device structure + * @bd: descriptor for the good/bad block search pattern + * + * The function creates a memory based bbt by scanning the device + * for manufacturer / software marked good / bad blocks +*/ +static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + struct nand_chip *this = mtd->priv; + + /* Ensure that we only scan for the pattern and nothing else */ + bd->options = 0; + create_bbt (mtd, this->data_buf, bd, -1); + return 0; +} + +/** + * check_create - [GENERIC] create and write bbt(s) if neccecary + * @mtd: MTD device structure + * @buf: temporary buffer + * @bd: descriptor for the good/bad block search pattern + * + * The function checks the results of the previous call to read_bbt + * and creates / updates the bbt(s) if neccecary + * Creation is neccecary if no bbt was found for the chip/device + * Update is neccecary if one of the tables is missing or the + * version nr. of one table is less than the other +*/ +static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) +{ + int i, chips, writeops, chipsel, res; + struct nand_chip *this = mtd->priv; + struct nand_bbt_descr *td = this->bbt_td; + struct nand_bbt_descr *md = this->bbt_md; + struct nand_bbt_descr *rd, *rd2; + + /* Do we have a bbt per chip ? */ + if (td->options & NAND_BBT_PERCHIP) + chips = this->numchips; + else + chips = 1; + + for (i = 0; i < chips; i++) { + writeops = 0; + rd = NULL; + rd2 = NULL; + /* Per chip or per device ? */ + chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; + /* Mirrored table avilable ? */ + if (md) { + if (td->pages[i] == -1 && md->pages[i] == -1) { + writeops = 0x03; + goto create; + } + + if (td->pages[i] == -1) { + rd = md; + td->version[i] = md->version[i]; + writeops = 1; + goto writecheck; + } + + if (md->pages[i] == -1) { + rd = td; + md->version[i] = td->version[i]; + writeops = 2; + goto writecheck; + } + + if (td->version[i] == md->version[i]) { + rd = td; + if (!(td->options & NAND_BBT_VERSION)) + rd2 = md; + goto writecheck; + } + + if (((int8_t) (td->version[i] - md->version[i])) > 0) { + rd = td; + md->version[i] = td->version[i]; + writeops = 2; + } else { + rd = md; + td->version[i] = md->version[i]; + writeops = 1; + } + + goto writecheck; + + } else { + if (td->pages[i] == -1) { + writeops = 0x01; + goto create; + } + rd = td; + goto writecheck; + } +create: + /* Create the bad block table by scanning the device ? */ + if (!(td->options & NAND_BBT_CREATE)) + continue; + + /* Create the table in memory by scanning the chip(s) */ + create_bbt (mtd, buf, bd, chipsel); + + td->version[i] = 1; + if (md) + md->version[i] = 1; +writecheck: + /* read back first ? */ + if (rd) + read_abs_bbt (mtd, buf, rd, chipsel); + /* If they weren't versioned, read both. */ + if (rd2) + read_abs_bbt (mtd, buf, rd2, chipsel); + + /* Write the bad block table to the device ? */ + if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { + res = write_bbt (mtd, buf, td, md, chipsel); + if (res < 0) + return res; + } + + /* Write the mirror bad block table to the device ? */ + if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { + res = write_bbt (mtd, buf, md, td, chipsel); + if (res < 0) + return res; + } + } + return 0; +} + +/** + * mark_bbt_regions - [GENERIC] mark the bad block table regions + * @mtd: MTD device structure + * @td: bad block table descriptor + * + * The bad block table regions are marked as "bad" to prevent + * accidental erasures / writes. The regions are identified by + * the mark 0x02. +*/ +static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) +{ + struct nand_chip *this = mtd->priv; + int i, j, chips, block, nrblocks, update; + uint8_t oldval, newval; + + /* Do we have a bbt per chip ? */ + if (td->options & NAND_BBT_PERCHIP) { + chips = this->numchips; + nrblocks = (int)(this->chipsize >> this->bbt_erase_shift); + } else { + chips = 1; + nrblocks = (int)(mtd->size >> this->bbt_erase_shift); + } + + for (i = 0; i < chips; i++) { + if ((td->options & NAND_BBT_ABSPAGE) || + !(td->options & NAND_BBT_WRITE)) { + if (td->pages[i] == -1) continue; + block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); + block <<= 1; + oldval = this->bbt[(block >> 3)]; + newval = oldval | (0x2 << (block & 0x06)); + this->bbt[(block >> 3)] = newval; + if ((oldval != newval) && td->reserved_block_code) + nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1)); + continue; + } + update = 0; + if (td->options & NAND_BBT_LASTBLOCK) + block = ((i + 1) * nrblocks) - td->maxblocks; + else + block = i * nrblocks; + block <<= 1; + for (j = 0; j < td->maxblocks; j++) { + oldval = this->bbt[(block >> 3)]; + newval = oldval | (0x2 << (block & 0x06)); + this->bbt[(block >> 3)] = newval; + if (oldval != newval) update = 1; + block += 2; + } + /* If we want reserved blocks to be recorded to flash, and some + new ones have been marked, then we need to update the stored + bbts. This should only happen once. */ + if (update && td->reserved_block_code) + nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1)); + } +} + +/** + * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) + * @mtd: MTD device structure + * @bd: descriptor for the good/bad block search pattern + * + * The function checks, if a bad block table(s) is/are already + * available. If not it scans the device for manufacturer + * marked good / bad blocks and writes the bad block table(s) to + * the selected place. + * + * The bad block table memory is allocated here. It must be freed + * by calling the nand_free_bbt function. + * +*/ +int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + struct nand_chip *this = mtd->priv; + int len, res = 0; + uint8_t *buf; + struct nand_bbt_descr *td = this->bbt_td; + struct nand_bbt_descr *md = this->bbt_md; + + len = mtd->size >> (this->bbt_erase_shift + 2); + /* Allocate memory (2bit per block) */ + this->bbt = kmalloc (len, GFP_KERNEL); + if (!this->bbt) { + printk (KERN_ERR "nand_scan_bbt: Out of memory\n"); + return -ENOMEM; + } + /* Clear the memory bad block table */ + memset (this->bbt, 0x00, len); + + /* If no primary table decriptor is given, scan the device + * to build a memory based bad block table + */ + if (!td) + return nand_memory_bbt(mtd, bd); + + /* Allocate a temporary buffer for one eraseblock incl. oob */ + len = (1 << this->bbt_erase_shift); + len += (len >> this->page_shift) * mtd->oobsize; + buf = kmalloc (len, GFP_KERNEL); + if (!buf) { + printk (KERN_ERR "nand_bbt: Out of memory\n"); + kfree (this->bbt); + this->bbt = NULL; + return -ENOMEM; + } + + /* Is the bbt at a given page ? */ + if (td->options & NAND_BBT_ABSPAGE) { + res = read_abs_bbts (mtd, buf, td, md); + } else { + /* Search the bad block table using a pattern in oob */ + res = search_read_bbts (mtd, buf, td, md); + } + + if (res) + res = check_create (mtd, buf, bd); + + /* Prevent the bbt regions from erasing / writing */ + mark_bbt_region (mtd, td); + if (md) + mark_bbt_region (mtd, md); + + kfree (buf); + return res; +} + + +/** + * nand_update_bbt - [NAND Interface] update bad block table(s) + * @mtd: MTD device structure + * @offs: the offset of the newly marked block + * + * The function updates the bad block table(s) +*/ +int nand_update_bbt (struct mtd_info *mtd, loff_t offs) +{ + struct nand_chip *this = mtd->priv; + int len, res = 0, writeops = 0; + int chip, chipsel; + uint8_t *buf; + struct nand_bbt_descr *td = this->bbt_td; + struct nand_bbt_descr *md = this->bbt_md; + + if (!this->bbt || !td) + return -EINVAL; + + len = mtd->size >> (this->bbt_erase_shift + 2); + /* Allocate a temporary buffer for one eraseblock incl. oob */ + len = (1 << this->bbt_erase_shift); + len += (len >> this->page_shift) * mtd->oobsize; + buf = kmalloc (len, GFP_KERNEL); + if (!buf) { + printk (KERN_ERR "nand_update_bbt: Out of memory\n"); + return -ENOMEM; + } + + writeops = md != NULL ? 0x03 : 0x01; + + /* Do we have a bbt per chip ? */ + if (td->options & NAND_BBT_PERCHIP) { + chip = (int) (offs >> this->chip_shift); + chipsel = chip; + } else { + chip = 0; + chipsel = -1; + } + + td->version[chip]++; + if (md) + md->version[chip]++; + + /* Write the bad block table to the device ? */ + if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { + res = write_bbt (mtd, buf, td, md, chipsel); + if (res < 0) + goto out; + } + /* Write the mirror bad block table to the device ? */ + if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { + res = write_bbt (mtd, buf, md, td, chipsel); + } + +out: + kfree (buf); + return res; +} + +/* Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks + * + * The memory based patterns just + */ +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr smallpage_memorybased = { + .options = 0, + .offs = 5, + .len = 1, + .pattern = scan_ff_pattern +}; + +static struct nand_bbt_descr largepage_memorybased = { + .options = 0, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern +}; + +static struct nand_bbt_descr smallpage_flashbased = { + .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, + .offs = 5, + .len = 1, + .pattern = scan_ff_pattern +}; + +static struct nand_bbt_descr largepage_flashbased = { + .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern +}; + +static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 }; + +static struct nand_bbt_descr agand_flashbased = { + .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, + .offs = 0x20, + .len = 6, + .pattern = scan_agand_pattern +}; + +/* Generic flash bbt decriptors +*/ +static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; +static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; + +static struct nand_bbt_descr bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 8, + .len = 4, + .veroffs = 12, + .maxblocks = 4, + .pattern = bbt_pattern +}; + +static struct nand_bbt_descr bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, + .offs = 8, + .len = 4, + .veroffs = 12, + .maxblocks = 4, + .pattern = mirror_pattern +}; + +/** + * nand_default_bbt - [NAND Interface] Select a default bad block table for the device + * @mtd: MTD device structure + * + * This function selects the default bad block table + * support for the device and calls the nand_scan_bbt function + * +*/ +int nand_default_bbt (struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + /* Default for AG-AND. We must use a flash based + * bad block table as the devices have factory marked + * _good_ blocks. Erasing those blocks leads to loss + * of the good / bad information, so we _must_ store + * this information in a good / bad table during + * startup + */ + if (this->options & NAND_IS_AND) { + /* Use the default pattern descriptors */ + if (!this->bbt_td) { + this->bbt_td = &bbt_main_descr; + this->bbt_md = &bbt_mirror_descr; + } + this->options |= NAND_USE_FLASH_BBT; + return nand_scan_bbt (mtd, &agand_flashbased); + } + + + /* Is a flash based bad block table requested ? */ + if (this->options & NAND_USE_FLASH_BBT) { + /* Use the default pattern descriptors */ + if (!this->bbt_td) { + this->bbt_td = &bbt_main_descr; + this->bbt_md = &bbt_mirror_descr; + } + if (!this->badblock_pattern) { + this->badblock_pattern = (mtd->oobblock > 512) ? + &largepage_flashbased : &smallpage_flashbased; + } + } else { + this->bbt_td = NULL; + this->bbt_md = NULL; + if (!this->badblock_pattern) { + this->badblock_pattern = (mtd->oobblock > 512) ? + &largepage_memorybased : &smallpage_memorybased; + } + } + return nand_scan_bbt (mtd, this->badblock_pattern); +} + +/** + * nand_isbad_bbt - [NAND Interface] Check if a block is bad + * @mtd: MTD device structure + * @offs: offset in the device + * @allowbbt: allow access to bad block table region + * + */ +int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt) +{ + struct nand_chip *this = mtd->priv; + int block; + uint8_t res; + + /* Get block number * 2 */ + block = (int) (offs >> (this->bbt_erase_shift - 1)); + res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; + + DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", + (unsigned int)offs, res, block >> 1); + + switch ((int)res) { + case 0x00: return 0; + case 0x01: return 1; + case 0x02: return allowbbt ? 0 : 1; + } + return 1; +} + +#endif diff --git a/drivers/nand/nand_ecc.c b/drivers/nand/nand_ecc.c new file mode 100644 index 0000000..0801ada --- /dev/null +++ b/drivers/nand/nand_ecc.c @@ -0,0 +1,244 @@ +/* + * This file contains an ECC algorithm from Toshiba that detects and + * corrects 1 bit errors in a 256 byte block of data. + * + * drivers/mtd/nand/nand_ecc.c + * + * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) + * Toshiba America Electronics Components, Inc. + * + * $Id: nand_ecc.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 or (at your option) any + * later version. + * + * This file 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 file; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) + +#include +/* + * Pre-calculated 256-way 1 byte column parity + */ +static const u_char nand_ecc_precalc_table[] = { + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 +}; + + +/** + * nand_trans_result - [GENERIC] create non-inverted ECC + * @reg2: line parity reg 2 + * @reg3: line parity reg 3 + * @ecc_code: ecc + * + * Creates non-inverted ECC code from line parity + */ +static void nand_trans_result(u_char reg2, u_char reg3, + u_char *ecc_code) +{ + u_char a, b, i, tmp1, tmp2; + + /* Initialize variables */ + a = b = 0x80; + tmp1 = tmp2 = 0; + + /* Calculate first ECC byte */ + for (i = 0; i < 4; i++) { + if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ + tmp1 |= b; + b >>= 1; + if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ + tmp1 |= b; + b >>= 1; + a >>= 1; + } + + /* Calculate second ECC byte */ + b = 0x80; + for (i = 0; i < 4; i++) { + if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ + tmp2 |= b; + b >>= 1; + if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ + tmp2 |= b; + b >>= 1; + a >>= 1; + } + + /* Store two of the ECC bytes */ + ecc_code[0] = tmp1; + ecc_code[1] = tmp2; +} + +/** + * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block + * @mtd: MTD block structure + * @dat: raw data + * @ecc_code: buffer for ECC + */ +int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +{ + u_char idx, reg1, reg2, reg3; + int j; + + /* Initialize variables */ + reg1 = reg2 = reg3 = 0; + ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; + + /* Build up column parity */ + for(j = 0; j < 256; j++) { + + /* Get CP0 - CP5 from table */ + idx = nand_ecc_precalc_table[dat[j]]; + reg1 ^= (idx & 0x3f); + + /* All bit XOR = 1 ? */ + if (idx & 0x40) { + reg3 ^= (u_char) j; + reg2 ^= ~((u_char) j); + } + } + + /* Create non-inverted ECC code from line parity */ + nand_trans_result(reg2, reg3, ecc_code); + + /* Calculate final ECC code */ + ecc_code[0] = ~ecc_code[0]; + ecc_code[1] = ~ecc_code[1]; + ecc_code[2] = ((~reg1) << 2) | 0x03; + return 0; +} + +/** + * nand_correct_data - [NAND Interface] Detect and correct bit error(s) + * @mtd: MTD block structure + * @dat: raw data read from the chip + * @read_ecc: ECC from the chip + * @calc_ecc: the ECC calculated from raw data + * + * Detect and correct a 1 bit error for 256 byte block + */ +int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +{ + u_char a, b, c, d1, d2, d3, add, bit, i; + + /* Do error detection */ + d1 = calc_ecc[0] ^ read_ecc[0]; + d2 = calc_ecc[1] ^ read_ecc[1]; + d3 = calc_ecc[2] ^ read_ecc[2]; + + if ((d1 | d2 | d3) == 0) { + /* No errors */ + return 0; + } + else { + a = (d1 ^ (d1 >> 1)) & 0x55; + b = (d2 ^ (d2 >> 1)) & 0x55; + c = (d3 ^ (d3 >> 1)) & 0x54; + + /* Found and will correct single bit error in the data */ + if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { + c = 0x80; + add = 0; + a = 0x80; + for (i=0; i<4; i++) { + if (d1 & c) + add |= a; + c >>= 2; + a >>= 1; + } + c = 0x80; + for (i=0; i<4; i++) { + if (d2 & c) + add |= a; + c >>= 2; + a >>= 1; + } + bit = 0; + b = 0x04; + c = 0x80; + for (i=0; i<3; i++) { + if (d3 & c) + bit |= b; + c >>= 2; + b >>= 1; + } + b = 0x01; + a = dat[add]; + a ^= (b << bit); + dat[add] = a; + return 1; + } else { + i = 0; + while (d1) { + if (d1 & 0x01) + ++i; + d1 >>= 1; + } + while (d2) { + if (d2 & 0x01) + ++i; + d2 >>= 1; + } + while (d3) { + if (d3 & 0x01) + ++i; + d3 >>= 1; + } + if (i == 1) { + /* ECC Code Error Correction */ + read_ecc[0] = calc_ecc[0]; + read_ecc[1] = calc_ecc[1]; + read_ecc[2] = calc_ecc[2]; + return 2; + } + else { + /* Uncorrectable Error */ + return -1; + } + } + } + + /* Should never happen */ + return -1; +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */ diff --git a/drivers/nand/nand_ecc_rs.c b/drivers/nand/nand_ecc_rs.c new file mode 100644 index 0000000..ef526ff --- /dev/null +++ b/drivers/nand/nand_ecc_rs.c @@ -0,0 +1,518 @@ +/* + * This file contains an ECC algorithm from Toshiba that detects and + * corrects 1 bit errors in a 256 byte block of data. + * + * drivers/mtd/nand/nand_ecc.c + * + * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) + * Toshiba America Electronics Components, Inc. + * + * $Id: nand_ecc_rs.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 or (at your option) any + * later version. + * + * This file 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 file; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) + +#include +#include + +#define mm 10 /* RS code over GF(2**mm) - the size in bits of a symbol*/ +#define nn 1023 /* nn=2^mm -1 length of codeword */ +#define tt 4 /* number of errors that can be corrected */ +#define kk 1015 /* kk = number of information symbols kk = nn-2*tt */ + + +static char rs_initialized = 0; + +//typedef unsigned int gf; +typedef u_short tgf; /* data type of Galois Functions */ + +/* Primitive polynomials - irriducibile polynomial [ 1+x^3+x^10 ]*/ +short pp[mm+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }; + + +/* index->polynomial form conversion table */ +tgf alpha_to[nn + 1]; + +/* Polynomial->index form conversion table */ +tgf index_of[nn + 1]; + +/* Generator polynomial g(x) = 2*tt with roots @, @^2, .. ,@^(2*tt) */ +tgf Gg[nn - kk + 1]; + + +#define minimum(a,b) ((a) < (b) ? (a) : (b)) + +#define BLANK(a,n) {\ + short ci;\ + for(ci=0; ci<(n); ci++)\ + (a)[ci] = 0;\ + } + +#define COPY(a,b,n) {\ + short ci;\ + for(ci=(n)-1;ci >=0;ci--)\ + (a)[ci] = (b)[ci];\ + } +#define COPYDOWN(a,b,n) {\ + short ci;\ + for(ci=(n)-1;ci >=0;ci--)\ + (a)[ci] = (b)[ci];\ + } + + +/* generate GF(2^m) from the irreducible polynomial p(X) in p[0]..p[mm] + lookup tables: index->polynomial form alpha_to[] contains j=alpha^i; + polynomial form -> index form index_of[j=alpha^i] = i + alpha=2 is the primitive element of GF(2^m) +*/ + +void generate_gf(void) +{ + register int i, mask; + + mask = 1; + alpha_to[mm] = 0; + for (i = 0; i < mm; i++) { + alpha_to[i] = mask; + index_of[alpha_to[i]] = i; + if (pp[i] != 0) + alpha_to[mm] ^= mask; + mask <<= 1; + } + index_of[alpha_to[mm]] = mm; + + mask >>= 1; + for (i = mm + 1; i < nn; i++) { + if (alpha_to[i - 1] >= mask) + alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i - 1] ^ mask) << 1); + else + alpha_to[i] = alpha_to[i - 1] << 1; + index_of[alpha_to[i]] = i; + } + index_of[0] = nn; + alpha_to[nn] = 0; +} + + +/* + * Obtain the generator polynomial of the tt-error correcting, + * length nn = (2^mm -1) + * Reed Solomon code from the product of (X + @^i), i=1..2*tt +*/ +void gen_poly(void) +{ + register int i, j; + + Gg[0] = alpha_to[1]; /* primitive element*/ + Gg[1] = 1; /* g(x) = (X+@^1) initially */ + for (i = 2; i <= nn - kk; i++) { + Gg[i] = 1; + /* + * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by + * (@^i + x) + */ + for (j = i - 1; j > 0; j--) + if (Gg[j] != 0) + Gg[j] = Gg[j - 1] ^ alpha_to[((index_of[Gg[j]]) + i)%nn]; + else + Gg[j] = Gg[j - 1]; + Gg[0] = alpha_to[((index_of[Gg[0]]) + i) % nn]; + } + /* convert Gg[] to index form for quicker encoding */ + for (i = 0; i <= nn - kk; i++) + Gg[i] = index_of[Gg[i]]; +} + + +/* + * take the string of symbols in data[i], i=0..(k-1) and encode + * systematically to produce nn-kk parity symbols in bb[0]..bb[nn-kk-1] data[] + * is input and bb[] is output in polynomial form. Encoding is done by using + * a feedback shift register with appropriate connections specified by the + * elements of Gg[], which was generated above. Codeword is c(X) = + * data(X)*X**(nn-kk)+ b(X) + */ +char encode_rs(dtype data[kk], dtype bb[nn-kk]) +{ + register int i, j; + tgf feedback; + + BLANK(bb,nn-kk); + for (i = kk - 1; i >= 0; i--) { + if(data[i] > nn) + return -1; /* Illegal symbol */ + feedback = index_of[data[i] ^ bb[nn - kk - 1]]; + if (feedback != nn) { /* feedback term is non-zero */ + for (j = nn - kk - 1; j > 0; j--) + if (Gg[j] != nn) + bb[j] = bb[j - 1] ^ alpha_to[(Gg[j] + feedback)%nn]; + else + bb[j] = bb[j - 1]; + bb[0] = alpha_to[(Gg[0] + feedback)%nn]; + } else { + for (j = nn - kk - 1; j > 0; j--) + bb[j] = bb[j - 1]; + bb[0] = 0; + } + } + return 0; +} + + + + +/* assume we have received bits grouped into mm-bit symbols in data[i], + i=0..(nn-1), We first compute the 2*tt syndromes, then we use the + Berlekamp iteration to find the error location polynomial elp[i]. + If the degree of the elp is >tt, we cannot correct all the errors + and hence just put out the information symbols uncorrected. If the + degree of elp is <=tt, we get the roots, hence the inverse roots, + the error location numbers. If the number of errors located does not + equal the degree of the elp, we have more than tt errors and cannot + correct them. Otherwise, we then solve for the error value at the + error location and correct the error.The procedure is that found in + Lin and Costello.*/ + +int decode_rs(dtype data[nn]) +{ + int deg_lambda, el, deg_omega; + int i, j, r; + tgf q,tmp,num1,num2,den,discr_r; + tgf recd[nn]; + tgf lambda[nn-kk + 1], s[nn-kk + 1]; /* Err+Eras Locator poly + * and syndrome poly */ + tgf b[nn-kk + 1], t[nn-kk + 1], omega[nn-kk + 1]; + tgf root[nn-kk], reg[nn-kk + 1], loc[nn-kk]; + int syn_error, count; + + + + /* data[] is in polynomial form, copy and convert to index form */ + for (i = nn-1; i >= 0; i--){ + + if(data[i] > nn) + return -1; /* Illegal symbol */ + + recd[i] = index_of[data[i]]; + } + + /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x) + * namely @**(1+i), i = 0, ... ,(nn-kk-1) + */ + + syn_error = 0; + + for (i = 1; i <= nn-kk; i++) { + tmp = 0; + + for (j = 0; j < nn; j++) + if (recd[j] != nn) /* recd[j] in index form */ + tmp ^= alpha_to[(recd[j] + (1+i-1)*j)%nn]; + + syn_error |= tmp; /* set flag if non-zero syndrome => + * error */ + /* store syndrome in index form */ + s[i] = index_of[tmp]; + } + + if (!syn_error) { + /* + * if syndrome is zero, data[] is a codeword and there are no + * errors to correct. So return data[] unmodified + */ + return 0; + } + + BLANK(&lambda[1],nn-kk); + + lambda[0] = 1; + + for(i=0;i 0; j--) + if (reg[j] != nn) { + //reg[j] = modnn(reg[j] + j); + reg[j] = (reg[j] + j)%nn; + q ^= alpha_to[reg[j]]; + } + if (!q) { + /* store root (index-form) and error location number */ + root[count] = i; + loc[count] = nn - i; + count++; + } + } + +#ifdef DEBUG +/* + printf("\n Final error positions:\t"); + for (i = 0; i < count; i++) + printf("%d ", loc[i]); + printf("\n"); +*/ +#endif + + + + if (deg_lambda != count) { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + return -1; + } + /* + * Compute err evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**(nn-kk)). in index form. Also find deg(omega). + */ + + deg_omega = 0; + for (i = 0; i < nn-kk;i++){ + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for(;j >= 0; j--){ + if ((s[i + 1 - j] != nn) && (lambda[j] != nn)) + //tmp ^= alpha_to[modnn(s[i + 1 - j] + lambda[j])]; + tmp ^= alpha_to[(s[i + 1 - j] + lambda[j])%nn]; + } + if(tmp != 0) + deg_omega = i; + omega[i] = index_of[tmp]; + } + omega[nn-kk] = nn; + + + + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(1-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count-1; j >=0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != nn) + //num1 ^= alpha_to[modnn(omega[i] + i * root[j])]; + num1 ^= alpha_to[(omega[i] + i * root[j])%nn]; + } + //num2 = alpha_to[modnn(root[j] * (1 - 1) + nn)]; + num2 = alpha_to[(root[j] * (1 - 1) + nn)%nn]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = minimum(deg_lambda,nn-kk-1) & ~1; i >= 0; i -=2) { + if(lambda[i+1] != nn) + //den ^= alpha_to[modnn(lambda[i+1] + i * root[j])]; + den ^= alpha_to[(lambda[i+1] + i * root[j])%nn]; + } + if (den == 0) { +#ifdef DEBUG + printf("\n ERROR: denominator = 0\n"); +#endif + return -1; + } + /* Apply error to data */ + if (num1 != 0) { + //data[loc[j]] ^= alpha_to[modnn(index_of[num1] + index_of[num2] + nn - index_of[den])]; + data[loc[j]] ^= alpha_to[(index_of[num1] + index_of[num2] + nn - index_of[den])%nn]; + } + } + return count; +} + +/** + * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block + * @mtd: MTD block structure + * @dat: raw data + * @ecc_code: buffer for ECC + */ +int nand_calculate_ecc_rs(struct mtd_info *mtd, const u_char *data, u_char *ecc_code) +{ + int i,j; + u_short rsdata[nn]; + + /* Generate Tables in first run */ + if (!rs_initialized) { + generate_gf(); + gen_poly(); + rs_initialized = 1; + } + + for(i=512; i> 8) | ((rsdata[0x3F7+1]) << 2); + *(ecc_code+2+(j*10)) = ((rsdata[0x3F7+1]) >> 6) | ((rsdata[0x3F7+2]) << 4); + *(ecc_code+3+(j*10)) = ((rsdata[0x3F7+2]) >> 4) | ((rsdata[0x3F7+3]) << 6); + *(ecc_code+4+(j*10)) = ((rsdata[0x3F7+3]) >> 2); + *(ecc_code+5+(j*10)) = (unsigned char) rsdata[kk+4]; + *(ecc_code+6+(j*10)) = ((rsdata[0x3F7+4]) >> 8) | ((rsdata[0x3F7+1+4]) << 2); + *(ecc_code+7+(j*10)) = ((rsdata[0x3F7+1+4]) >> 6) | ((rsdata[0x3F7+2+4]) << 4); + *(ecc_code+8+(j*10)) = ((rsdata[0x3F7+2+4]) >> 4) | ((rsdata[0x3F7+3+4]) << 6); + *(ecc_code+9+(j*10)) = ((rsdata[0x3F7+3+4]) >> 2); + } + + return 0; +} + +/** + * nand_correct_data - [NAND Interface] Detect and correct bit error(s) + * @mtd: MTD block structure + * @dat: raw data read from the chip + * @store_ecc: ECC from the chip + * @calc_ecc: the ECC calculated from raw data + * + * Detect and correct a 1 bit error for 256 byte block + */ +int nand_correct_data_rs(struct mtd_info *mtd, u_char *data, u_char *store_ecc, u_char *calc_ecc) +{ + int ret,i,j; + u_short rsdata[nn]; + + /* Generate Tables in first run */ + if (!rs_initialized) { + generate_gf(); + gen_poly(); + rs_initialized = 1; + } + + for(i=512; i>2); + rsdata[kk+2] = ( (*(store_ecc+3+(j*10)) & 0x3F) <<4) | (*(store_ecc+2+(j*10))>>4); + rsdata[kk+3] = (*(store_ecc+4+(j*10)) <<2) | (*(store_ecc+3+(j*10))>>6); + + rsdata[kk+4] = ( (*(store_ecc+1+5+(j*10)) & 0x03) <<8) | (*(store_ecc+5+(j*10))); + rsdata[kk+5] = ( (*(store_ecc+2+5+(j*10)) & 0x0F) <<6) | (*(store_ecc+1+5+(j*10))>>2); + rsdata[kk+6] = ( (*(store_ecc+3+5+(j*10)) & 0x3F) <<4) | (*(store_ecc+2+5+(j*10))>>4); + rsdata[kk+7] = (*(store_ecc+4+5+(j*10)) <<2) | (*(store_ecc+3+5+(j*10))>>6); + + ret = decode_rs(rsdata); + + /* Check for excessive errors */ + if ((ret > tt) || (ret < 0)) + return -1; + + /* Copy corrected data */ + for (i=0; i<512; i++) + data[i+(j*512)] = (unsigned char) rsdata[i]; + } + + return 0; +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */ diff --git a/drivers/nand/nand_ids.c b/drivers/nand/nand_ids.c new file mode 100644 index 0000000..5ce4e16 --- /dev/null +++ b/drivers/nand/nand_ids.c @@ -0,0 +1,126 @@ +/* + * drivers/mtd/nandids.c + * + * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) + * + * $Id: nand_ids.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ + * + * 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 + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) + +#include + +/* +* Chip ID list +* +* Name. ID code, pagesize, chipsize in MegaByte, eraseblock size, +* options +* +* Pagesize; 0, 256, 512 +* 0 get this information from the extended chip ID ++ 256 256 Byte page size +* 512 512 Byte page size +*/ +struct nand_flash_dev nand_flash_ids[] = { + {"NAND 1MB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, + {"NAND 2MB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, + {"NAND 4MB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, + {"NAND 1MB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0}, + {"NAND 1MB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, + {"NAND 2MB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0}, + {"NAND 4MB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0}, + {"NAND 4MB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, + {"NAND 4MB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, + {"NAND 8MB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, + + {"NAND 8MB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, + {"NAND 8MB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, + {"NAND 8MB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, + {"NAND 8MB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, + + {"NAND 16MB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, + {"NAND 16MB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, + {"NAND 16MB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 16MB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 32MB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, + {"NAND 32MB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, + {"NAND 32MB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 32MB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 64MB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, + {"NAND 64MB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, + {"NAND 64MB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 64MB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 128MB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, + {"NAND 128MB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, + {"NAND 128MB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 128MB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 256MB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, + + /* These are the new chips with large page size. The pagesize + * and the erasesize is determined from the extended id bytes + */ + /* 1 Gigabit */ + {"NAND 128MB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 128MB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 128MB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 128MB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + + /* 2 Gigabit */ + {"NAND 256MB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 256MB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 256MB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 256MB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + + /* 4 Gigabit */ + {"NAND 512MB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 512MB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 512MB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 512MB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + + /* 8 Gigabit */ + {"NAND 1GB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 1GB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 1GB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 1GB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + + /* 16 Gigabit */ + {"NAND 2GB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 2GB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, + {"NAND 2GB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 2GB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + + /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! + * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes + * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 + * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go + * There are more speed improvements for reads and writes possible, but not implemented now + */ + {"AND 128MB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY}, + + {NULL,} +}; + +/* +* Manufacturer ID list +*/ +struct nand_manufacturers nand_manuf_ids[] = { + {NAND_MFR_TOSHIBA, "Toshiba"}, + {NAND_MFR_SAMSUNG, "Samsung"}, + {NAND_MFR_FUJITSU, "Fujitsu"}, + {NAND_MFR_NATIONAL, "National"}, + {NAND_MFR_RENESAS, "Renesas"}, + {NAND_MFR_STMICRO, "ST Micro"}, + {0x0, "Unknown"} +}; +#endif diff --git a/drivers/nand/nand_util.c b/drivers/nand/nand_util.c new file mode 100644 index 0000000..10bf036 --- /dev/null +++ b/drivers/nand/nand_util.c @@ -0,0 +1,862 @@ +/* + * drivers/nand/nand_util.c + * + * Copyright (C) 2006 by Weiss-Electronic GmbH. + * All rights reserved. + * + * @author: Guido Classen + * @descr: NAND Flash support + * @references: borrowed heavily from Linux mtd-utils code: + * flash_eraseall.c by Arcom Control System Ltd + * nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com) + * and Thomas Gleixner (tglx@linutronix.de) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) + +#include +#include +#include + +#include +#include + +typedef struct erase_info erase_info_t; +typedef struct mtd_info mtd_info_t; + +/* support only for native endian JFFS2 */ +#define cpu_to_je16(x) (x) +#define cpu_to_je32(x) (x) + +/*****************************************************************************/ +static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip) +{ + return 0; +} + +/** + * nand_erase_opts: - erase NAND flash with support for various options + * (jffs2 formating) + * + * @param meminfo NAND device to erase + * @param opts options, @see struct nand_erase_options + * @return 0 in case of success + * + * This code is ported from flash_eraseall.c from Linux mtd utils by + * Arcom Control System Ltd. + */ +int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts) +{ + struct jffs2_unknown_node cleanmarker; + int clmpos = 0; + int clmlen = 8; + erase_info_t erase; + ulong erase_length; + int isNAND; + int bbtest = 1; + int result; + int percent_complete = -1; + int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL; + const char *mtd_device = meminfo->name; + + memset(&erase, 0, sizeof(erase)); + + erase.mtd = meminfo; + erase.len = meminfo->erasesize; + erase.addr = opts->offset; + erase_length = opts->length; + + isNAND = meminfo->type == MTD_NANDFLASH ? 1 : 0; + + if (opts->jffs2) { + cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); + cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); + if (isNAND) { + struct nand_oobinfo *oobinfo = &meminfo->oobinfo; + + /* check for autoplacement */ + if (oobinfo->useecc == MTD_NANDECC_AUTOPLACE) { + /* get the position of the free bytes */ + if (!oobinfo->oobfree[0][1]) { + printf(" Eeep. Autoplacement selected " + "and no empty space in oob\n"); + return -1; + } + clmpos = oobinfo->oobfree[0][0]; + clmlen = oobinfo->oobfree[0][1]; + if (clmlen > 8) + clmlen = 8; + } else { + /* legacy mode */ + switch (meminfo->oobsize) { + case 8: + clmpos = 6; + clmlen = 2; + break; + case 16: + clmpos = 8; + clmlen = 8; + break; + case 64: + clmpos = 16; + clmlen = 8; + break; + } + } + + cleanmarker.totlen = cpu_to_je32(8); + } else { + cleanmarker.totlen = + cpu_to_je32(sizeof(struct jffs2_unknown_node)); + } + cleanmarker.hdr_crc = cpu_to_je32( + crc32_no_comp(0, (unsigned char *) &cleanmarker, + sizeof(struct jffs2_unknown_node) - 4)); + } + + /* scrub option allows to erase badblock. To prevent internal + * check from erase() method, set block check method to dummy + * and disable bad block table while erasing. + */ + if (opts->scrub) { + struct nand_chip *priv_nand = meminfo->priv; + + nand_block_bad_old = priv_nand->block_bad; + priv_nand->block_bad = nand_block_bad_scrub; + /* we don't need the bad block table anymore... + * after scrub, there are no bad blocks left! + */ + if (priv_nand->bbt) { + kfree(priv_nand->bbt); + } + priv_nand->bbt = NULL; + } + + for (; + erase.addr < opts->offset + erase_length; + erase.addr += meminfo->erasesize) { + + WATCHDOG_RESET (); + + if (!opts->scrub && bbtest) { + int ret = meminfo->block_isbad(meminfo, erase.addr); + if (ret > 0) { + if (!opts->quiet) + printf("\rSkipping bad block at " + "0x%08x " + " \n", + erase.addr); + continue; + + } else if (ret < 0) { + printf("\n%s: MTD get bad block failed: %d\n", + mtd_device, + ret); + return -1; + } + } + + result = meminfo->erase(meminfo, &erase); + if (result != 0) { + printf("\n%s: MTD Erase failure: %d\n", + mtd_device, result); + continue; + } + + /* format for JFFS2 ? */ + if (opts->jffs2) { + + /* write cleanmarker */ + if (isNAND) { + size_t written; + result = meminfo->write_oob(meminfo, + erase.addr + clmpos, + clmlen, + &written, + (unsigned char *) + &cleanmarker); + if (result != 0) { + printf("\n%s: MTD writeoob failure: %d\n", + mtd_device, result); + continue; + } + } else { + printf("\n%s: this erase routine only supports" + " NAND devices!\n", + mtd_device); + } + } + + if (!opts->quiet) { + int percent = (int) + ((unsigned long long) + (erase.addr+meminfo->erasesize-opts->offset) + * 100 / erase_length); + + /* output progress message only at whole percent + * steps to reduce the number of messages printed + * on (slow) serial consoles + */ + if (percent != percent_complete) { + percent_complete = percent; + + printf("\rErasing at 0x%x -- %3d%% complete.", + erase.addr, percent); + + if (opts->jffs2 && result == 0) + printf(" Cleanmarker written at 0x%x.", + erase.addr); + } + } + } + if (!opts->quiet) + printf("\n"); + + if (nand_block_bad_old) { + struct nand_chip *priv_nand = meminfo->priv; + + priv_nand->block_bad = nand_block_bad_old; + priv_nand->scan_bbt(meminfo); + } + + return 0; +} + +#define MAX_PAGE_SIZE 2048 +#define MAX_OOB_SIZE 64 + +/* + * buffer array used for writing data + */ +static unsigned char data_buf[MAX_PAGE_SIZE]; +static unsigned char oob_buf[MAX_OOB_SIZE]; + +/* OOB layouts to pass into the kernel as default */ +static struct nand_oobinfo none_oobinfo = { + .useecc = MTD_NANDECC_OFF, +}; + +static struct nand_oobinfo jffs2_oobinfo = { + .useecc = MTD_NANDECC_PLACE, + .eccbytes = 6, + .eccpos = { 0, 1, 2, 3, 6, 7 } +}; + +static struct nand_oobinfo yaffs_oobinfo = { + .useecc = MTD_NANDECC_PLACE, + .eccbytes = 6, + .eccpos = { 8, 9, 10, 13, 14, 15} +}; + +static struct nand_oobinfo autoplace_oobinfo = { + .useecc = MTD_NANDECC_AUTOPLACE +}; + +/** + * nand_write_opts: - write image to NAND flash with support for various options + * + * @param meminfo NAND device to erase + * @param opts write options (@see nand_write_options) + * @return 0 in case of success + * + * This code is ported from nandwrite.c from Linux mtd utils by + * Steven J. Hill and Thomas Gleixner. + */ +int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts) +{ + int imglen = 0; + int pagelen; + int baderaseblock; + int blockstart = -1; + loff_t offs; + int readlen; + int oobinfochanged = 0; + int percent_complete = -1; + struct nand_oobinfo old_oobinfo; + ulong mtdoffset = opts->offset; + ulong erasesize_blockalign; + u_char *buffer = opts->buffer; + size_t written; + int result; + + if (opts->pad && opts->writeoob) { + printf("Can't pad when oob data is present.\n"); + return -1; + } + + /* set erasesize to specified number of blocks - to match + * jffs2 (virtual) block size */ + if (opts->blockalign == 0) { + erasesize_blockalign = meminfo->erasesize; + } else { + erasesize_blockalign = meminfo->erasesize * opts->blockalign; + } + + /* make sure device page sizes are valid */ + if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512) + && !(meminfo->oobsize == 8 && meminfo->oobblock == 256) + && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) { + printf("Unknown flash (not normal NAND)\n"); + return -1; + } + + /* read the current oob info */ + memcpy(&old_oobinfo, &meminfo->oobinfo, sizeof(old_oobinfo)); + + /* write without ecc? */ + if (opts->noecc) { + memcpy(&meminfo->oobinfo, &none_oobinfo, + sizeof(meminfo->oobinfo)); + oobinfochanged = 1; + } + + /* autoplace ECC? */ + if (opts->autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) { + + memcpy(&meminfo->oobinfo, &autoplace_oobinfo, + sizeof(meminfo->oobinfo)); + oobinfochanged = 1; + } + + /* force OOB layout for jffs2 or yaffs? */ + if (opts->forcejffs2 || opts->forceyaffs) { + struct nand_oobinfo *oobsel = + opts->forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo; + + if (meminfo->oobsize == 8) { + if (opts->forceyaffs) { + printf("YAFSS cannot operate on " + "256 Byte page size\n"); + goto restoreoob; + } + /* Adjust number of ecc bytes */ + jffs2_oobinfo.eccbytes = 3; + } + + memcpy(&meminfo->oobinfo, oobsel, sizeof(meminfo->oobinfo)); + } + + /* get image length */ + imglen = opts->length; + pagelen = meminfo->oobblock + + ((opts->writeoob != 0) ? meminfo->oobsize : 0); + + /* check, if file is pagealigned */ + if ((!opts->pad) && ((imglen % pagelen) != 0)) { + printf("Input block length is not page aligned\n"); + goto restoreoob; + } + + /* check, if length fits into device */ + if (((imglen / pagelen) * meminfo->oobblock) + > (meminfo->size - opts->offset)) { + printf("Image %d bytes, NAND page %d bytes, " + "OOB area %u bytes, device size %u bytes\n", + imglen, pagelen, meminfo->oobblock, meminfo->size); + printf("Input block does not fit into device\n"); + goto restoreoob; + } + + if (!opts->quiet) + printf("\n"); + + /* get data from input and write to the device */ + while (imglen && (mtdoffset < meminfo->size)) { + + WATCHDOG_RESET (); + + /* + * new eraseblock, check for bad block(s). Stay in the + * loop to be sure if the offset changes because of + * a bad block, that the next block that will be + * written to is also checked. Thus avoiding errors if + * the block(s) after the skipped block(s) is also bad + * (number of blocks depending on the blockalign + */ + while (blockstart != (mtdoffset & (~erasesize_blockalign+1))) { + blockstart = mtdoffset & (~erasesize_blockalign+1); + offs = blockstart; + baderaseblock = 0; + + /* check all the blocks in an erase block for + * bad blocks */ + do { + int ret = meminfo->block_isbad(meminfo, offs); + + if (ret < 0) { + printf("Bad block check failed\n"); + goto restoreoob; + } + if (ret == 1) { + baderaseblock = 1; + if (!opts->quiet) + printf("\rBad block at 0x%lx " + "in erase block from " + "0x%x will be skipped\n", + (long) offs, + blockstart); + } + + if (baderaseblock) { + mtdoffset = blockstart + + erasesize_blockalign; + } + offs += erasesize_blockalign + / opts->blockalign; + } while (offs < blockstart + erasesize_blockalign); + } + + readlen = meminfo->oobblock; + if (opts->pad && (imglen < readlen)) { + readlen = imglen; + memset(data_buf + readlen, 0xff, + meminfo->oobblock - readlen); + } + + /* read page data from input memory buffer */ + memcpy(data_buf, buffer, readlen); + buffer += readlen; + + if (opts->writeoob) { + /* read OOB data from input memory block, exit + * on failure */ + memcpy(oob_buf, buffer, meminfo->oobsize); + buffer += meminfo->oobsize; + + /* write OOB data first, as ecc will be placed + * in there*/ + result = meminfo->write_oob(meminfo, + mtdoffset, + meminfo->oobsize, + &written, + (unsigned char *) + &oob_buf); + + if (result != 0) { + printf("\nMTD writeoob failure: %d\n", + result); + goto restoreoob; + } + imglen -= meminfo->oobsize; + } + + /* write out the page data */ + result = meminfo->write(meminfo, + mtdoffset, + meminfo->oobblock, + &written, + (unsigned char *) &data_buf); + + if (result != 0) { + printf("writing NAND page at offset 0x%lx failed\n", + mtdoffset); + goto restoreoob; + } + imglen -= readlen; + + if (!opts->quiet) { + int percent = (int) + ((unsigned long long) + (opts->length-imglen) * 100 + / opts->length); + /* output progress message only at whole percent + * steps to reduce the number of messages printed + * on (slow) serial consoles + */ + if (percent != percent_complete) { + printf("\rWriting data at 0x%x " + "-- %3d%% complete.", + mtdoffset, percent); + percent_complete = percent; + } + } + + mtdoffset += meminfo->oobblock; + } + + if (!opts->quiet) + printf("\n"); + +restoreoob: + if (oobinfochanged) { + memcpy(&meminfo->oobinfo, &old_oobinfo, + sizeof(meminfo->oobinfo)); + } + + if (imglen > 0) { + printf("Data did not fit into device, due to bad blocks\n"); + return -1; + } + + /* return happy */ + return 0; +} + +/** + * nand_read_opts: - read image from NAND flash with support for various options + * + * @param meminfo NAND device to erase + * @param opts read options (@see struct nand_read_options) + * @return 0 in case of success + * + */ +int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts) +{ + int imglen = opts->length; + int pagelen; + int baderaseblock; + int blockstart = -1; + int percent_complete = -1; + loff_t offs; + size_t readlen; + ulong mtdoffset = opts->offset; + u_char *buffer = opts->buffer; + int result; + + /* make sure device page sizes are valid */ + if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512) + && !(meminfo->oobsize == 8 && meminfo->oobblock == 256) + && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) { + printf("Unknown flash (not normal NAND)\n"); + return -1; + } + + pagelen = meminfo->oobblock + + ((opts->readoob != 0) ? meminfo->oobsize : 0); + + /* check, if length is not larger than device */ + if (((imglen / pagelen) * meminfo->oobblock) + > (meminfo->size - opts->offset)) { + printf("Image %d bytes, NAND page %d bytes, " + "OOB area %u bytes, device size %u bytes\n", + imglen, pagelen, meminfo->oobblock, meminfo->size); + printf("Input block is larger than device\n"); + return -1; + } + + if (!opts->quiet) + printf("\n"); + + /* get data from input and write to the device */ + while (imglen && (mtdoffset < meminfo->size)) { + + WATCHDOG_RESET (); + + /* + * new eraseblock, check for bad block(s). Stay in the + * loop to be sure if the offset changes because of + * a bad block, that the next block that will be + * written to is also checked. Thus avoiding errors if + * the block(s) after the skipped block(s) is also bad + * (number of blocks depending on the blockalign + */ + while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) { + blockstart = mtdoffset & (~meminfo->erasesize+1); + offs = blockstart; + baderaseblock = 0; + + /* check all the blocks in an erase block for + * bad blocks */ + do { + int ret = meminfo->block_isbad(meminfo, offs); + + if (ret < 0) { + printf("Bad block check failed\n"); + return -1; + } + if (ret == 1) { + baderaseblock = 1; + if (!opts->quiet) + printf("\rBad block at 0x%lx " + "in erase block from " + "0x%x will be skipped\n", + (long) offs, + blockstart); + } + + if (baderaseblock) { + mtdoffset = blockstart + + meminfo->erasesize; + } + offs += meminfo->erasesize; + + } while (offs < blockstart + meminfo->erasesize); + } + + + /* read page data to memory buffer */ + result = meminfo->read(meminfo, + mtdoffset, + meminfo->oobblock, + &readlen, + (unsigned char *) &data_buf); + + if (result != 0) { + printf("reading NAND page at offset 0x%lx failed\n", + mtdoffset); + return -1; + } + + if (imglen < readlen) { + readlen = imglen; + } + + memcpy(buffer, data_buf, readlen); + buffer += readlen; + imglen -= readlen; + + if (opts->readoob) { + result = meminfo->read_oob(meminfo, + mtdoffset, + meminfo->oobsize, + &readlen, + (unsigned char *) + &oob_buf); + + if (result != 0) { + printf("\nMTD readoob failure: %d\n", + result); + return -1; + } + + + if (imglen < readlen) { + readlen = imglen; + } + + memcpy(buffer, oob_buf, readlen); + + buffer += readlen; + imglen -= readlen; + } + + if (!opts->quiet) { + int percent = (int) + ((unsigned long long) + (opts->length-imglen) * 100 + / opts->length); + /* output progress message only at whole percent + * steps to reduce the number of messages printed + * on (slow) serial consoles + */ + if (percent != percent_complete) { + if (!opts->quiet) + printf("\rReading data from 0x%x " + "-- %3d%% complete.", + mtdoffset, percent); + percent_complete = percent; + } + } + + mtdoffset += meminfo->oobblock; + } + + if (!opts->quiet) + printf("\n"); + + if (imglen > 0) { + printf("Could not read entire image due to bad blocks\n"); + return -1; + } + + /* return happy */ + return 0; +} + +/****************************************************************************** + * Support for locking / unlocking operations of some NAND devices + *****************************************************************************/ + +#define NAND_CMD_LOCK 0x2a +#define NAND_CMD_LOCK_TIGHT 0x2c +#define NAND_CMD_UNLOCK1 0x23 +#define NAND_CMD_UNLOCK2 0x24 +#define NAND_CMD_LOCK_STATUS 0x7a + +/** + * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT + * state + * + * @param meminfo nand mtd instance + * @param tight bring device in lock tight mode + * + * @return 0 on success, -1 in case of error + * + * The lock / lock-tight command only applies to the whole chip. To get some + * parts of the chip lock and others unlocked use the following sequence: + * + * - Lock all pages of the chip using nand_lock(mtd, 0) (or the lockpre pin) + * - Call nand_unlock() once for each consecutive area to be unlocked + * - If desired: Bring the chip to the lock-tight state using nand_lock(mtd, 1) + * + * If the device is in lock-tight state software can't change the + * current active lock/unlock state of all pages. nand_lock() / nand_unlock() + * calls will fail. It is only posible to leave lock-tight state by + * an hardware signal (low pulse on _WP pin) or by power down. + */ +int nand_lock(nand_info_t *meminfo, int tight) +{ + int ret = 0; + int status; + struct nand_chip *this = meminfo->priv; + + /* select the NAND device */ + this->select_chip(meminfo, 0); + + this->cmdfunc(meminfo, + (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK), + -1, -1); + + /* call wait ready function */ + status = this->waitfunc(meminfo, this, FL_WRITING); + + /* see if device thinks it succeeded */ + if (status & 0x01) { + ret = -1; + } + + /* de-select the NAND device */ + this->select_chip(meminfo, -1); + return ret; +} + +/** + * nand_get_lock_status: - query current lock state from one page of NAND + * flash + * + * @param meminfo nand mtd instance + * @param offset page address to query (muss be page aligned!) + * + * @return -1 in case of error + * >0 lock status: + * bitfield with the following combinations: + * NAND_LOCK_STATUS_TIGHT: page in tight state + * NAND_LOCK_STATUS_LOCK: page locked + * NAND_LOCK_STATUS_UNLOCK: page unlocked + * + */ +int nand_get_lock_status(nand_info_t *meminfo, ulong offset) +{ + int ret = 0; + int chipnr; + int page; + struct nand_chip *this = meminfo->priv; + + /* select the NAND device */ + chipnr = (int)(offset >> this->chip_shift); + this->select_chip(meminfo, chipnr); + + + if ((offset & (meminfo->oobblock - 1)) != 0) { + printf ("nand_get_lock_status: " + "Start address must be beginning of " + "nand page!\n"); + ret = -1; + goto out; + } + + /* check the Lock Status */ + page = (int)(offset >> this->page_shift); + this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask); + + ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT + | NAND_LOCK_STATUS_LOCK + | NAND_LOCK_STATUS_UNLOCK); + + out: + /* de-select the NAND device */ + this->select_chip(meminfo, -1); + return ret; +} + +/** + * nand_unlock: - Unlock area of NAND pages + * only one consecutive area can be unlocked at one time! + * + * @param meminfo nand mtd instance + * @param start start byte address + * @param length number of bytes to unlock (must be a multiple of + * page size nand->oobblock) + * + * @return 0 on success, -1 in case of error + */ +int nand_unlock(nand_info_t *meminfo, ulong start, ulong length) +{ + int ret = 0; + int chipnr; + int status; + int page; + struct nand_chip *this = meminfo->priv; + printf ("nand_unlock: start: %08x, length: %d!\n", + (int)start, (int)length); + + /* select the NAND device */ + chipnr = (int)(start >> this->chip_shift); + this->select_chip(meminfo, chipnr); + + /* check the WP bit */ + this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1); + if ((this->read_byte(meminfo) & 0x80) == 0) { + printf ("nand_unlock: Device is write protected!\n"); + ret = -1; + goto out; + } + + if ((start & (meminfo->oobblock - 1)) != 0) { + printf ("nand_unlock: Start address must be beginning of " + "nand page!\n"); + ret = -1; + goto out; + } + + if (length == 0 || (length & (meminfo->oobblock - 1)) != 0) { + printf ("nand_unlock: Length must be a multiple of nand page " + "size!\n"); + ret = -1; + goto out; + } + + /* submit address of first page to unlock */ + page = (int)(start >> this->page_shift); + this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask); + + /* submit ADDRESS of LAST page to unlock */ + page += (int)(length >> this->page_shift) - 1; + this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask); + + /* call wait ready function */ + status = this->waitfunc(meminfo, this, FL_WRITING); + /* see if device thinks it succeeded */ + if (status & 0x01) { + /* there was an error */ + ret = -1; + goto out; + } + + out: + /* de-select the NAND device */ + this->select_chip(meminfo, -1); + return ret; +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) */ diff --git a/drivers/ns7520_eth.c b/drivers/ns7520_eth.c index a5a20df..8bc9b4e 100644 --- a/drivers/ns7520_eth.c +++ b/drivers/ns7520_eth.c @@ -2,7 +2,7 @@ * * Copyright (C) 2005 by Videon Central, Inc. * - * $Id$ + * $Id: ns7520_eth.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Arthur Shipkowski * @Descr: Ethernet driver for the NS7520. Uses polled Ethernet, like * the older netarmeth driver. Note that attempting to filter diff --git a/drivers/ns9750_eth.c b/drivers/ns9750_eth.c index 067ff8e..deec99e 100644 --- a/drivers/ns9750_eth.c +++ b/drivers/ns9750_eth.c @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_eth.c,v 1.2 2004/02/24 14:09:39 mpietrek Exp $ + * $Id: ns9750_eth.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @Descr: Ethernet driver for the NS9750. Uses DMA Engine with polling * interrupt status. But interrupts are not enabled. diff --git a/drivers/ns9750_serial.c b/drivers/ns9750_serial.c index aced3da..ef6a638 100644 --- a/drivers/ns9750_serial.c +++ b/drivers/ns9750_serial.c @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_serial.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * $Id: ns9750_serial.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @Descr: Serial driver for the NS9750. Only one UART is supported yet. * @References: [1] NS9750 Hardware Reference/December 2003 diff --git a/drivers/pci.c b/drivers/pci.c index 5360030..865398c 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -28,10 +28,9 @@ * PCI routines */ +/* #define DEBUG */ #include - #ifdef CONFIG_PCI - #include #include #include @@ -141,8 +140,9 @@ struct pci_controller *pci_bus_to_hose (int bus) for (hose = hose_head; hose; hose = hose->next) if (bus >= hose->first_busno && bus <= hose->last_busno) return hose; - +#ifndef CONFIG_MARVELL printf("pci_bus_to_hose() failed\n"); +#endif return NULL; } @@ -423,6 +423,8 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus) dev < PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1); dev += PCI_BDF(0,0,1)) { + +#ifndef CONFIG_MARVELL /* Skip our host bridge */ if ( dev == PCI_BDF(hose->first_busno,0,0) ) { #if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */ @@ -436,7 +438,7 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus) continue; /* Skip our host bridge */ #endif } - +#endif /* CONFIG_MARVELL */ if (PCI_FUNC(dev) && !found_multi) continue; diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c index 3302457..9171be7 100644 --- a/drivers/pci_auto.c +++ b/drivers/pci_auto.c @@ -19,7 +19,7 @@ #include -#undef DEBUG +/* #define DEBUG */ #ifdef DEBUG #define DEBUGF(x...) printf(x) #else @@ -53,14 +53,16 @@ int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned addr = ((res->bus_lower - 1) | (size - 1)) + 1; + DEBUGF("addr 0x%x size 0x%x\n",addr, size); + DEBUGF("res->bus_start 0x%x res->size 0x%x\n",res->bus_start, res->size); if (addr - res->bus_start + size > res->size) { - DEBUGF("No room in resource"); + DEBUGF("No room in resource\n"); goto error; } res->bus_lower = addr + size; - DEBUGF("address=0x%lx", addr); + DEBUGF("address=0x%lx\n", addr); *bar = addr; return 0; diff --git a/drivers/pci_indirect.c b/drivers/pci_indirect.c index e8f19f5..8860650 100644 --- a/drivers/pci_indirect.c +++ b/drivers/pci_indirect.c @@ -12,7 +12,8 @@ #include #ifdef CONFIG_PCI -#if (!defined(__I386__) && !defined(CONFIG_IXDP425)) +#ifndef __I386__ +#ifndef __ARM__ #include #include @@ -118,5 +119,6 @@ void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) hose->cfg_data = (unsigned char *) cfg_data; } +#endif /* __ARM__ */ #endif /* !__I386__ && !CONFIG_IXDP425 */ #endif /* CONFIG_PCI */ diff --git a/drivers/rtl8029.c b/drivers/rtl8029.c new file mode 100644 index 0000000..b883f3d --- /dev/null +++ b/drivers/rtl8029.c @@ -0,0 +1,356 @@ +/* + * Realtek 8029AS Ethernet + * (C) Copyright 2002-2003 + * Xue Ligong(lgxue@hotmail.com),Wang Kehao, ESLAB, whut.edu.cn + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * This code works in 8bit mode. + * If you need to work in 16bit mode, PLS change it! + */ + +#include +#include +#include +#include "rtl8029.h" +#include +#include "pci.h" + +#ifdef CONFIG_DRIVER_RTL8029 + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +struct eth_device *rtl8029_dev; + +/* packet page register access functions */ + + +static unsigned char get_reg (unsigned int regno) +{ + return (*(volatile unsigned char *) regno); +} + + +static void put_reg (unsigned int regno, unsigned char val) +{ + *(volatile unsigned char *) regno = val; +} + +static void eth_reset (void) +{ + unsigned char ucTemp; + + /* reset NIC */ + ucTemp = get_reg (RTL8029_RESET); + put_reg (RTL8029_RESET, ucTemp); + put_reg (RTL8029_INTERRUPTSTATUS, 0xff); + udelay (2000); /* wait for 2ms */ +} + +void rtl8029_get_enetaddr (uchar * addr) +{ + unsigned char i; + unsigned char temp; + + eth_reset (); + + put_reg (RTL8029_COMMAND, RTL8029_REMOTEDMARD); + put_reg (RTL8029_DATACONFIGURATION, 0x48); + put_reg (RTL8029_REMOTESTARTADDRESS0, 0x00); + put_reg (RTL8029_REMOTESTARTADDRESS1, 0x00); + put_reg (RTL8029_REMOTEBYTECOUNT0, 12); + put_reg (RTL8029_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8029_COMMAND, RTL8029_REMOTEDMARD); + printf ("MAC: "); + for (i = 0; i < 6; i++) { + temp = get_reg (RTL8029_DMA_DATA); + *addr++ = temp; + temp = get_reg (RTL8029_DMA_DATA); + printf ("%x:", temp); + } + + while ((!get_reg (RTL8029_INTERRUPTSTATUS) & 0x40)); + printf ("\b \n"); + put_reg (RTL8029_REMOTEBYTECOUNT0, 0x00); + put_reg (RTL8029_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8029_COMMAND, RTL8029_PAGE0); +} + + +void rtl8029_eth_halt (struct eth_device *dev) +{ + put_reg (RTL8029_COMMAND, 0x01); +} + +int rtl8029_eth_init (struct eth_device *dev,bd_t * bd) +{ + uchar *mac = (uchar *)dev->enetaddr; + + rtl8029_get_enetaddr(mac); + + eth_reset (); + put_reg (RTL8029_COMMAND, RTL8029_PAGE0STOP); + put_reg (RTL8029_DATACONFIGURATION, 0x48); + put_reg (RTL8029_REMOTEBYTECOUNT0, 0x00); + put_reg (RTL8029_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8029_RECEIVECONFIGURATION, 0x00); /*00; */ + put_reg (RTL8029_TRANSMITPAGE, RTL8029_TPSTART); + put_reg (RTL8029_TRANSMITCONFIGURATION, 0x02); + put_reg (RTL8029_PAGESTART, RTL8029_PSTART); + put_reg (RTL8029_BOUNDARY, RTL8029_PSTART); + put_reg (RTL8029_PAGESTOP, RTL8029_PSTOP); + put_reg (RTL8029_INTERRUPTSTATUS, 0xff); + put_reg (RTL8029_INTERRUPTMASK, 0x11); /*b; */ + put_reg (RTL8029_COMMAND, RTL8029_PAGE1STOP); + put_reg (RTL8029_PHYSICALADDRESS0, dev->enetaddr[0]); + put_reg (RTL8029_PHYSICALADDRESS1, dev->enetaddr[1]); + put_reg (RTL8029_PHYSICALADDRESS2, dev->enetaddr[2]); + put_reg (RTL8029_PHYSICALADDRESS3, dev->enetaddr[3]); + put_reg (RTL8029_PHYSICALADDRESS4, dev->enetaddr[4]); + put_reg (RTL8029_PHYSICALADDRESS5, dev->enetaddr[5]); + put_reg (RTL8029_MULTIADDRESS0, 0x00); + put_reg (RTL8029_MULTIADDRESS1, 0x00); + put_reg (RTL8029_MULTIADDRESS2, 0x00); + put_reg (RTL8029_MULTIADDRESS3, 0x00); + put_reg (RTL8029_MULTIADDRESS4, 0x00); + put_reg (RTL8029_MULTIADDRESS5, 0x00); + put_reg (RTL8029_MULTIADDRESS6, 0x00); + put_reg (RTL8029_MULTIADDRESS7, 0x00); + put_reg (RTL8029_CURRENT, RTL8029_PSTART); + put_reg (RTL8029_COMMAND, RTL8029_PAGE0); + put_reg (RTL8029_TRANSMITCONFIGURATION, 0xe0); /*58; */ + + + + return 1; +} + + +static unsigned char nic_to_pc (void) +{ + unsigned char rec_head_status; + unsigned char next_packet_pointer; + unsigned char packet_length0; + unsigned char packet_length1; + unsigned short rxlen = 0; + unsigned int i = 4; + unsigned char current_point; + unsigned char *addr; + + /* + * The RTL8029's first 4B is packet status,page of next packet + * and packet length(2B).So we receive the fist 4B. + */ + put_reg (RTL8029_REMOTESTARTADDRESS1, get_reg (RTL8029_BOUNDARY)); + put_reg (RTL8029_REMOTESTARTADDRESS0, 0x00); + put_reg (RTL8029_REMOTEBYTECOUNT1, 0x00); + put_reg (RTL8029_REMOTEBYTECOUNT0, 0x04); + + + + put_reg (RTL8029_COMMAND, RTL8029_REMOTEDMARD); + + rec_head_status = get_reg (RTL8029_DMA_DATA); + next_packet_pointer = get_reg (RTL8029_DMA_DATA); + packet_length0 = get_reg (RTL8029_DMA_DATA); + packet_length1 = get_reg (RTL8029_DMA_DATA); + + put_reg (RTL8029_COMMAND, RTL8029_PAGE0); + /*Packet length is in two 8bit registers */ + rxlen = packet_length1; + rxlen = (((rxlen << 8) & 0xff00) + packet_length0); + rxlen -= 4; + + + if (rxlen > PKTSIZE_ALIGN + PKTALIGN) + printf ("packet too big!\n"); + + /*Receive the packet */ + put_reg (RTL8029_REMOTESTARTADDRESS0, 0x04); + put_reg (RTL8029_REMOTESTARTADDRESS1, get_reg (RTL8029_BOUNDARY)); + + put_reg (RTL8029_REMOTEBYTECOUNT0, (rxlen & 0xff)); + put_reg (RTL8029_REMOTEBYTECOUNT1, ((rxlen >> 8) & 0xff)); + + + put_reg (RTL8029_COMMAND, RTL8029_REMOTEDMARD); + + for (addr = (unsigned char *) NetRxPackets[0], i = rxlen; i > 0; i--) + { + + *addr++ = get_reg (RTL8029_DMA_DATA); + } + /* Pass the packet up to the protocol layers. */ + NetReceive (NetRxPackets[0], rxlen); + + while (!(get_reg (RTL8029_INTERRUPTSTATUS)) & 0x40); /* wait for the op. */ + + /* + * To test whether the packets are all received,get the + * location of current point + */ + put_reg (RTL8029_COMMAND, RTL8029_PAGE1); + current_point = get_reg (RTL8029_CURRENT); + put_reg (RTL8029_COMMAND, RTL8029_PAGE0); + put_reg (RTL8029_BOUNDARY, next_packet_pointer); + return current_point; +} + +/* Get a data block via Ethernet */ +extern int rtl8029_eth_rx (struct eth_device *dev) +{ + unsigned char temp, current_point; + + put_reg (RTL8029_COMMAND, RTL8029_PAGE0); + + + while (1) { + temp = get_reg (RTL8029_INTERRUPTSTATUS); + + + if (temp & 0x90) { + /*overflow */ + put_reg (RTL8029_COMMAND, RTL8029_PAGE0STOP); + udelay (2000); + put_reg (RTL8029_REMOTEBYTECOUNT0, 0); + put_reg (RTL8029_REMOTEBYTECOUNT1, 0); + put_reg (RTL8029_TRANSMITCONFIGURATION, 2); + do { + current_point = nic_to_pc (); + } while (get_reg (RTL8029_BOUNDARY) != current_point); + + put_reg (RTL8029_TRANSMITCONFIGURATION, 0xe0); + } + + if (temp & 0x1) { + udelay (10 * 1000); + + /*packet received */ + do { + put_reg (RTL8029_INTERRUPTSTATUS, 0x01); + current_point = nic_to_pc (); + } while (get_reg (RTL8029_BOUNDARY) != current_point); + } + + if (!(temp & 0x1)) + return 0; + + + + + /* done and exit. */ + } +} + +/* Send a data block via Ethernet. */ +extern int rtl8029_eth_send (struct eth_device *dev,volatile void *packet, int length) +{ + volatile unsigned char *p; + unsigned int pn; + + pn = length; + p = (volatile unsigned char *) packet; + + while (get_reg (RTL8029_COMMAND) == RTL8029_TRANSMIT); + + put_reg (RTL8029_REMOTESTARTADDRESS0, 0); + put_reg (RTL8029_REMOTESTARTADDRESS1, RTL8029_TPSTART); + put_reg (RTL8029_REMOTEBYTECOUNT0, (pn & 0xff)); + put_reg (RTL8029_REMOTEBYTECOUNT1, ((pn >> 8) & 0xff)); + + put_reg (RTL8029_COMMAND, RTL8029_REMOTEDMAWR); + while (pn > 0) { + put_reg (RTL8029_DMA_DATA, *p++); + pn--; + } + + pn = length; + + while (pn < 60) { /*Padding */ + put_reg (RTL8029_DMA_DATA, 0); + pn++; + } + + while (!(get_reg (RTL8029_INTERRUPTSTATUS)) & 0x40); + + put_reg (RTL8029_INTERRUPTSTATUS, 0x40); + put_reg (RTL8029_TRANSMITPAGE, RTL8029_TPSTART); + put_reg (RTL8029_TRANSMITBYTECOUNT0, (pn & 0xff)); + put_reg (RTL8029_TRANSMITBYTECOUNT1, ((pn >> 8 & 0xff))); + put_reg (RTL8029_COMMAND, RTL8029_TRANSMIT); + + udelay (10 * 1000); + + return 0; +} + + +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029}, + {} +}; + +int rtl8029_initialize(bd_t *bis) +{ + pci_dev_t devno; + int card_number = 0; + + u32 iobase; + int idx=0; + + while(1){ + /* Find RTL8029 */ + if ((devno = pci_find_devices(supported, idx++)) < 0) + break; + + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); + iobase &= ~0xf; + + + debug ("rtl8029: REALTEK RTL8029 @0x%x\n", iobase); + + rtl8029_dev = (struct eth_device *)malloc(sizeof *rtl8029_dev); + + sprintf (rtl8029_dev->name, "RTL8029#%d", card_number); + + rtl8029_dev->priv = (void *) devno; + rtl8029_dev->iobase = (int)iobase; + rtl8029_dev->init = rtl8029_eth_init; + rtl8029_dev->halt = rtl8029_eth_halt; + rtl8029_dev->send = rtl8029_eth_send; + rtl8029_dev->recv = rtl8029_eth_rx; + + eth_register (rtl8029_dev); + + card_number++; + + pci_write_config_byte (devno, PCI_LATENCY_TIMER, 0x20); + + udelay (10 * 1000); + } + + return card_number; +} + + +#endif /* COMMANDS & CFG_NET */ + +#endif /* CONFIG_DRIVER_RTL8029 */ diff --git a/drivers/rtl8029.h b/drivers/rtl8029.h new file mode 100644 index 0000000..93f3ef9 --- /dev/null +++ b/drivers/rtl8029.h @@ -0,0 +1,119 @@ +/* + * Realtek 8029AS Ethernet + * (C) Copyright 2002-2003 + * Xue Ligong(lgxue@hotmail.com),Wang Kehao, ESLAB, whut.edu.cn + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * This code works in 8bit mode. + * If you need to work in 16bit mode, PLS change it! + */ + +#include +#include + + +#ifdef CONFIG_DRIVER_RTL8029 + +#define RTL8029_BASE rtl8029_dev->iobase + +#define RTL8029_REG_00 (RTL8029_BASE + 0x00) +#define RTL8029_REG_01 (RTL8029_BASE + 0x01) +#define RTL8029_REG_02 (RTL8029_BASE + 0x02) +#define RTL8029_REG_03 (RTL8029_BASE + 0x03) +#define RTL8029_REG_04 (RTL8029_BASE + 0x04) +#define RTL8029_REG_05 (RTL8029_BASE + 0x05) +#define RTL8029_REG_06 (RTL8029_BASE + 0x06) +#define RTL8029_REG_07 (RTL8029_BASE + 0x07) +#define RTL8029_REG_08 (RTL8029_BASE + 0x08) +#define RTL8029_REG_09 (RTL8029_BASE + 0x09) +#define RTL8029_REG_0a (RTL8029_BASE + 0x0a) +#define RTL8029_REG_0b (RTL8029_BASE + 0x0b) +#define RTL8029_REG_0c (RTL8029_BASE + 0x0c) +#define RTL8029_REG_0d (RTL8029_BASE + 0x0d) +#define RTL8029_REG_0e (RTL8029_BASE + 0x0e) +#define RTL8029_REG_0f (RTL8029_BASE + 0x0f) +#define RTL8029_REG_10 (RTL8029_BASE + 0x10) +#define RTL8029_REG_1f (RTL8029_BASE + 0x1f) + +#define RTL8029_COMMAND RTL8029_REG_00 +#define RTL8029_PAGESTART RTL8029_REG_01 +#define RTL8029_PAGESTOP RTL8029_REG_02 +#define RTL8029_BOUNDARY RTL8029_REG_03 +#define RTL8029_TRANSMITSTATUS RTL8029_REG_04 +#define RTL8029_TRANSMITPAGE RTL8029_REG_04 +#define RTL8029_TRANSMITBYTECOUNT0 RTL8029_REG_05 +#define RTL8029_NCR RTL8029_REG_05 +#define RTL8029_TRANSMITBYTECOUNT1 RTL8029_REG_06 +#define RTL8029_INTERRUPTSTATUS RTL8029_REG_07 +#define RTL8029_CURRENT RTL8029_REG_07 +#define RTL8029_REMOTESTARTADDRESS0 RTL8029_REG_08 +#define RTL8029_CRDMA0 RTL8029_REG_08 +#define RTL8029_REMOTESTARTADDRESS1 RTL8029_REG_09 +#define RTL8029_CRDMA1 RTL8029_REG_09 +#define RTL8029_REMOTEBYTECOUNT0 RTL8029_REG_0a +#define RTL8029_REMOTEBYTECOUNT1 RTL8029_REG_0b +#define RTL8029_RECEIVESTATUS RTL8029_REG_0c +#define RTL8029_RECEIVECONFIGURATION RTL8029_REG_0c +#define RTL8029_TRANSMITCONFIGURATION RTL8029_REG_0d +#define RTL8029_FAE_TALLY RTL8029_REG_0d +#define RTL8029_DATACONFIGURATION RTL8029_REG_0e +#define RTL8029_CRC_TALLY RTL8029_REG_0e +#define RTL8029_INTERRUPTMASK RTL8029_REG_0f +#define RTL8029_MISS_PKT_TALLY RTL8029_REG_0f +#define RTL8029_PHYSICALADDRESS0 RTL8029_REG_01 +#define RTL8029_PHYSICALADDRESS1 RTL8029_REG_02 +#define RTL8029_PHYSICALADDRESS2 RTL8029_REG_03 +#define RTL8029_PHYSICALADDRESS3 RTL8029_REG_04 +#define RTL8029_PHYSICALADDRESS4 RTL8029_REG_05 +#define RTL8029_PHYSICALADDRESS5 RTL8029_REG_06 +#define RTL8029_MULTIADDRESS0 RTL8029_REG_08 +#define RTL8029_MULTIADDRESS1 RTL8029_REG_09 +#define RTL8029_MULTIADDRESS2 RTL8029_REG_0a +#define RTL8029_MULTIADDRESS3 RTL8029_REG_0b +#define RTL8029_MULTIADDRESS4 RTL8029_REG_0c +#define RTL8029_MULTIADDRESS5 RTL8029_REG_0d +#define RTL8029_MULTIADDRESS6 RTL8029_REG_0e +#define RTL8029_MULTIADDRESS7 RTL8029_REG_0f +#define RTL8029_DMA_DATA RTL8029_REG_10 +#define RTL8029_RESET RTL8029_REG_1f + + +#define RTL8029_PAGE0 0x22 +#define RTL8029_PAGE1 0x62 +#define RTL8029_PAGE0DMAWRITE 0x12 +#define RTL8029_PAGE2DMAWRITE 0x92 +#define RTL8029_REMOTEDMAWR 0x12 +#define RTL8029_REMOTEDMARD 0x0A +#define RTL8029_ABORTDMAWR 0x32 +#define RTL8029_ABORTDMARD 0x2A +#define RTL8029_PAGE0STOP 0x21 +#define RTL8029_PAGE1STOP 0x61 +#define RTL8029_TRANSMIT 0x26 +#define RTL8029_TXINPROGRESS 0x04 +#define RTL8029_SEND 0x1A + +#define RTL8029_PSTART 0x4c +#define RTL8029_PSTOP 0x80 +#define RTL8029_TPSTART 0x40 + + +#endif /*end of CONFIG_DRIVER_RTL8029*/ diff --git a/drivers/s3c4510b_eth.h b/drivers/s3c4510b_eth.h index cbddba7..9840087 100644 --- a/drivers/s3c4510b_eth.h +++ b/drivers/s3c4510b_eth.h @@ -22,7 +22,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * - * MODULE: $Id:$ + * MODULE: $Id: s3c4510b_eth.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * Description: Ethernet interface * Runtime Env: ARM7TDMI * Change History: diff --git a/drivers/s3c4510b_uart.c b/drivers/s3c4510b_uart.c index 44b96a9..45e8edc 100644 --- a/drivers/s3c4510b_uart.c +++ b/drivers/s3c4510b_uart.c @@ -35,7 +35,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * MODULE: $Id:$ + * MODULE: $Id: s3c4510b_uart.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * Description: UART/Serial interface for Samsung S3C4510B SoC * Runtime Env: ARM7TDMI * Change History: diff --git a/drivers/sk98lin/Makefile b/drivers/sk98lin/Makefile index 8ee0e21..fcadc23 100644 --- a/drivers/sk98lin/Makefile +++ b/drivers/sk98lin/Makefile @@ -1,38 +1,91 @@ +#****************************************************************************** # -# (C) Copyright 2003 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# Name: skge.c +# Project: GEnesis, PCI Gigabit Ethernet Adapter +# Version: $Revision: 1.1.1.1 $ +# Date: $Date: 2008-12-15 11:39:21 $ +# Purpose: The main driver source module # -# See file CREDITS for list of people who contributed to this -# project. -# -# 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 -# -# File: drivers/sk98lin/Makefile -# -# Makefile for the SysKonnect SK-98xx device driver. -# -include $(TOPDIR)/config.mk +#****************************************************************************** +#****************************************************************************** +# +# (C)Copyright 1998-2002 SysKonnect GmbH. +# (C)Copyright 2002-2004 Marvell. +# +# Makefile for Marvell Yukon chipset and SysKonnect Gigabit Ethernet +# Server Adapter driver. (Kernel 2.4) +# +# Author: Mirko Lindner (mlindner@syskonnect.de) +# Ralph Roesler (rroesler@syskonnect.de) +# +# Address all question to: linux@syskonnect.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The information in this file is provided "AS IS" without warranty. +# +#****************************************************************************** + +#****************************************************************************** +# +# History: +# +# $Log: Makefile,v $ +# Revision 1.1.1.1 2008-12-15 11:39:21 wokes +# marvell 88f6281 u-boot +# +# Revision 1.1.1.1 2008/12/15 11:17:11 wokes +# marvell 88f6281 u-boot +# +# Revision 1.1.1.1 2008/12/15 11:05:16 wokes +# marvell 88f6281 u-boot +# +# Revision 1.9 2004/07/13 15:54:50 rroesler +# Add: file skethtool.c +# Fix: corrected header regarding copyright +# Fix: minor typos corrected +# +# Revision 1.8 2004/06/08 08:40:36 mlindner +# Fix: Add CONFIG_SK98LIN_ZEROCOPY as default value +# +# Revision 1.7 2004/06/03 16:06:56 mlindner +# Fix: Added compile flag SK_DIAG_SUPPORT +# +# Revision 1.6 2004/06/02 08:02:59 mlindner +# Add: Changed header information and inserted a GPL statement +# +# +#****************************************************************************** + + +include $(TOPDIR)/config.mk + LIB := libsk98lin.a -OBJS := skge.o skaddr.o skgehwt.o skgeinit.o skgepnmi.o skgesirq.o \ - ski2c.o sklm80.o skqueue.o skrlmt.o sktimer.o skvpd.o \ - skxmac2.o skcsum.o #skproc.o - -OBJS += uboot_skb.o uboot_drv.o +OBJS := \ + uboot_drv.o \ + uboot_skb.o \ + sky2.o \ + skge.o \ + sky2le.o \ + skdim.o \ + skaddr.o \ + skgehwt.o \ + skgeinit.o \ + skgesirq.o \ + sktwsi.o \ + sklm80.o \ + skqueue.o \ + skrlmt.o \ + sktimer.o \ + skvpd.o \ + skxmac2.o \ + skcsum.o \ +# skgepnmi.o # DBGDEF = \ # -DDEBUG @@ -81,21 +134,24 @@ endif # SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources # SK_DBGCAT_DRV_EVENT 0x08000000 driver events -EXTRA_CFLAGS += -I. -DSK_USE_CSUM $(DBGDEF) +#EXTRA_CFLAGS += -I. -DYUK2 -DYUKON -DGENESIS #-DSK_DIAG_SUPPORT $(DBGDEF) $(SKPARAM) +EXTRA_CFLAGS += -I. -DYUK2 -DYUKON #-DGENESIS -DSK_DIAG_SUPPORT $(DBGDEF) $(SKPARAM) CFLAGS += $(EXTRA_CFLAGS) - - -all: $(LIB) - -$(LIB): $(OBJS) + + +all: $(LIB) + +$(LIB): $(OBJS) $(AR) crv $@ $(OBJS) - + ######################################################################### - -.depend: Makefile $(OBJS:.o=.c) + +.depend: Makefile $(OBJS:.o=.c) $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ - + sinclude .depend - + ######################################################################### + + diff --git a/drivers/sk98lin/h/lm80.h b/drivers/sk98lin/h/lm80.h index 981a4ca..96eca1a 100644 --- a/drivers/sk98lin/h/lm80.h +++ b/drivers/sk98lin/h/lm80.h @@ -1,9 +1,9 @@ /****************************************************************************** * - * Name: lm80.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2002/04/25 11:04:10 $ + * Name: lm80.h + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Contains all defines for the LM80 Chip * (National Semiconductor). * @@ -11,7 +11,9 @@ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -19,25 +21,7 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: lm80.h,v $ - * Revision 1.4 2002/04/25 11:04:10 rschmidt - * Editorial changes - * - * Revision 1.3 1999/11/22 13:41:19 cgoos - * Changed license header to GPL. - * - * Revision 1.2 1999/03/12 13:26:51 malthoff - * remove __STDC__. - * - * Revision 1.1 1998/06/19 09:28:31 malthoff - * created. - * + * /LICENSE * ******************************************************************************/ @@ -55,8 +39,8 @@ extern "C" { * * All registers are 8 bit wide */ -#define LM80_CFG 0x00 /* Configuration Register */ -#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */ +#define LM80_CFG 0x00 /* Configuration Register */ +#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */ #define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */ #define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */ #define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */ @@ -93,8 +77,8 @@ extern "C" { #define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */ #define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */ #define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */ -#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */ -#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */ +#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */ +#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */ /* 0x3e - 0x3f reserved */ /* @@ -124,7 +108,7 @@ extern "C" { /* LM80_ISRC_2 Interrupt Status Register 2 */ /* LM80_IMSK_2 Interrupt Mask Register 2 */ -#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */ +#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */ #define LM80_IS_BTI (1<<1) /* state of BTI# pin */ #define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */ #define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */ @@ -143,7 +127,7 @@ extern "C" { #define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */ /* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */ -#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */ +#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */ #define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */ #define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */ #define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/ diff --git a/drivers/sk98lin/h/skaddr.h b/drivers/sk98lin/h/skaddr.h index 711f873..71c86fb 100644 --- a/drivers/sk98lin/h/skaddr.h +++ b/drivers/sk98lin/h/skaddr.h @@ -1,16 +1,18 @@ /****************************************************************************** * * Name: skaddr.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.26 $ - * Date: $Date: 2002/11/15 07:24:42 $ + * Project: Gigabit Ethernet Adapters, ADDR-Modul + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Header file for Address Management (MC, UC, Prom). * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2001 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,102 +20,7 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skaddr.h,v $ - * Revision 1.26 2002/11/15 07:24:42 tschilli - * SK_ADDR_EQUAL macro fixed. - * - * Revision 1.25 2002/06/10 13:55:18 tschilli - * Changes for handling YUKON. - * All changes are internally and not visible to the programmer - * using this module. - * - * Revision 1.24 2001/01/22 13:41:34 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.23 2000/08/10 11:27:50 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * - * Revision 1.22 2000/08/07 11:10:40 rassmann - * Editorial changes. - * - * Revision 1.21 2000/05/04 09:39:59 rassmann - * Editorial changes. - * Corrected multicast address hashing. - * - * Revision 1.20 1999/11/22 13:46:14 cgoos - * Changed license header to GPL. - * Allowing overwrite for SK_ADDR_EQUAL. - * - * Revision 1.19 1999/05/28 10:56:07 rassmann - * Editorial changes. - * - * Revision 1.18 1999/04/06 17:22:04 rassmann - * Added private "ActivePort". - * - * Revision 1.17 1999/01/14 16:18:19 rassmann - * Corrected multicast initialization. - * - * Revision 1.16 1999/01/04 10:30:36 rassmann - * SkAddrOverride only possible after SK_INIT_IO phase. - * - * Revision 1.15 1998/12/29 13:13:11 rassmann - * An address override is now preserved in the SK_INIT_IO phase. - * All functions return an int now. - * Extended parameter checking. - * - * Revision 1.14 1998/11/24 12:39:45 rassmann - * Reserved multicast entry for BPDU address. - * 13 multicast entries left for protocol. - * - * Revision 1.13 1998/11/13 17:24:32 rassmann - * Changed return value of SkAddrOverride to int. - * - * Revision 1.12 1998/11/13 16:56:19 rassmann - * Added macro SK_ADDR_COMPARE. - * Changed return type of SkAddrOverride to SK_BOOL. - * - * Revision 1.11 1998/10/28 18:16:35 rassmann - * Avoiding I/Os before SK_INIT_RUN level. - * Aligning InexactFilter. - * - * Revision 1.10 1998/10/22 11:39:10 rassmann - * Corrected signed/unsigned mismatches. - * - * Revision 1.9 1998/10/15 15:15:49 rassmann - * Changed Flags Parameters from SK_U8 to int. - * Checked with lint. - * - * Revision 1.8 1998/09/24 19:15:12 rassmann - * Code cleanup. - * - * Revision 1.7 1998/09/18 20:22:13 rassmann - * Added HW access. - * - * Revision 1.6 1998/09/04 19:40:20 rassmann - * Interface enhancements. - * - * Revision 1.5 1998/09/04 12:40:57 rassmann - * Interface cleanup. - * - * Revision 1.4 1998/09/04 12:14:13 rassmann - * Interface cleanup. - * - * Revision 1.3 1998/09/02 16:56:40 rassmann - * Updated interface. - * - * Revision 1.2 1998/08/27 14:26:09 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:31:08 rassmann - * First public version. + * /LICENSE * ******************************************************************************/ @@ -140,7 +47,6 @@ #define __INC_SKADDR_H #ifdef __cplusplus -#error C++ is not yet supported. extern "C" { #endif /* cplusplus */ @@ -206,7 +112,7 @@ extern "C" { /* Macros */ -#if 0 +#ifdef OLD_STUFF #ifndef SK_ADDR_EQUAL /* * "&" instead of "&&" allows better optimization on IA-64. @@ -231,16 +137,18 @@ extern "C" { #ifndef SK_ADDR_EQUAL #ifndef SK_ADDR_DWORD_COMPARE #define SK_ADDR_EQUAL(A1,A2) ( \ - (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \ - (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \ - (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \ - (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \ - (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \ - (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0])) + (((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \ + (((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \ + (((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \ + (((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \ + (((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \ + (((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0])) #else /* SK_ADDR_DWORD_COMPARE */ #define SK_ADDR_EQUAL(A1,A2) ( \ - (*(SK_U16 *)&(((SK_U8 *)(A1))[4]) == *(SK_U16 *)&(((SK_U8 *)(A2))[4])) && \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0]))) + (*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \ + *(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \ + (*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \ + *(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0]))) #endif /* SK_ADDR_DWORD_COMPARE */ #endif /* SK_ADDR_EQUAL */ @@ -356,6 +264,9 @@ extern int SkAddrXmacMcAdd( SK_MAC_ADDR *pMc, int Flags); +extern SK_U32 SkXmacMcHash( + unsigned char *pMc); + extern int SkAddrGmacMcAdd( SK_AC *pAC, SK_IOC IoC, @@ -363,6 +274,9 @@ extern int SkAddrGmacMcAdd( SK_MAC_ADDR *pMc, int Flags); +extern SK_U32 SkGmacMcHash( + unsigned char *pMc); + extern int SkAddrMcUpdate( SK_AC *pAC, SK_IOC IoC, @@ -382,7 +296,7 @@ extern int SkAddrOverride( SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - SK_MAC_ADDR *pNewAddr, + SK_MAC_ADDR SK_FAR *pNewAddr, int Flags); extern int SkAddrPromiscuousChange( @@ -401,13 +315,15 @@ extern int SkAddrGmacPromiscuousChange( SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - int NewPromMode); + int NewPromMode); +#ifndef SK_SLIM extern int SkAddrSwap( SK_AC *pAC, SK_IOC IoC, SK_U32 FromPortNumber, SK_U32 ToPortNumber); +#endif #else /* defined(SK_KR_PROTO)) */ diff --git a/drivers/sk98lin/h/skcsum.h b/drivers/sk98lin/h/skcsum.h index 2acae32..f0e1487 100644 --- a/drivers/sk98lin/h/skcsum.h +++ b/drivers/sk98lin/h/skcsum.h @@ -2,14 +2,15 @@ * * Name: skcsum.h * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx) - * Version: $Revision: 1.9 $ - * Date: $Date: 2001/02/06 11:21:39 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Store/verify Internet checksum in send/receive packets. * ******************************************************************************/ /****************************************************************************** * + * LICENSE: * (C)Copyright 1998-2001 SysKonnect GmbH. * * This program is free software; you can redistribute it and/or modify @@ -18,48 +19,7 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skcsum.h,v $ - * Revision 1.9 2001/02/06 11:21:39 rassmann - * Editorial changes. - * - * Revision 1.8 2001/02/06 11:15:36 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.7 2000/06/29 13:17:05 rassmann - * Corrected reception of a packet with UDP checksum == 0 (which means there - * is no UDP checksum). - * - * Revision 1.6 2000/02/28 12:33:44 cgoos - * Changed C++ style comments to C style. - * - * Revision 1.5 2000/02/21 12:10:05 cgoos - * Fixed license comment. - * - * Revision 1.4 2000/02/21 11:08:37 cgoos - * Merged changes back into common source. - * - * Revision 1.1 1999/07/26 14:47:49 mkarl - * changed from common source to windows specific source - * added return SKCS_STATUS_IP_CSUM_ERROR_UDP and - * SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester - * changes for Tx csum offload - * - * Revision 1.2 1998/09/04 12:16:34 mhaveman - * Checked in for Stephan to allow compilation. - * -Added definition SK_CSUM_EVENT_CLEAR_PROTO_STATS to clear statistic - * -Added prototype for SkCsEvent() - * - * Revision 1.1 1998/09/01 15:36:53 swolf - * initial revision - * - * 01-Sep-1998 sw Created. + * /LICENSE * ******************************************************************************/ @@ -130,7 +90,7 @@ * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok). * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok. * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok. - * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. + * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. */ #ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */ #define SKCS_STATUS int /* Define status type. */ @@ -199,9 +159,7 @@ typedef struct s_CsProtocolStatistics { typedef struct s_Csum { /* Enabled receive SK_PROTO_XXX bit flags. */ unsigned ReceiveFlags[SK_MAX_NETS]; -#ifdef TX_CSUM unsigned TransmitFlags[SK_MAX_NETS]; -#endif /* TX_CSUM */ /* The protocol statistics structure; one per supported protocol. */ SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS]; @@ -226,11 +184,11 @@ typedef struct s_CsPacketInfo { /* function prototypes ********************************************************/ -#ifndef SkCsCalculateChecksum +#ifndef SK_CS_CALCULATE_CHECKSUM extern unsigned SkCsCalculateChecksum( void *pData, unsigned Length); -#endif +#endif /* SK_CS_CALCULATE_CHECKSUM */ extern int SkCsEvent( SK_AC *pAc, diff --git a/drivers/sk98lin/h/skdebug.h b/drivers/sk98lin/h/skdebug.h index cf5b5ad..d17315f 100644 --- a/drivers/sk98lin/h/skdebug.h +++ b/drivers/sk98lin/h/skdebug.h @@ -1,81 +1,38 @@ /****************************************************************************** * * Name: skdebug.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.12 $ - * Date: $Date: 2002/07/15 15:37:13 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: SK specific DEBUG support * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2005 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skdebug.h,v $ - * Revision 1.12 2002/07/15 15:37:13 rschmidt - * Power Management support - * Editorial changes - * - * Revision 1.11 2002/04/25 11:04:39 rschmidt - * Editorial changes - * - * Revision 1.10 1999/11/22 13:47:40 cgoos - * Changed license header to GPL. - * - * Revision 1.9 1999/09/14 14:02:43 rwahl - * Added SK_DBGMOD_PECP. - * - * Revision 1.8 1998/11/25 08:31:54 gklug - * fix: no C++ comments allowed in common sources - * - * Revision 1.7 1998/11/24 16:47:24 swolf - * Driver may now define its own SK_DBG_MSG() (eg. in "h/skdrv1st.h"). - * - * Revision 1.6 1998/10/28 10:23:55 rassmann - * ADDED SK_DBGMOD_ADDR. - * - * Revision 1.5 1998/10/22 09:43:55 gklug - * add: CSUM module - * - * Revision 1.4 1998/10/01 07:54:44 gklug - * add: PNMI debug module - * - * Revision 1.3 1998/09/18 08:32:34 afischer - * Macros changed according ssr-spec.: - * SK_DBG_MODCHK -> SK_DBG_CHKMOD - * SK_DBG_CATCHK -> SK_DBG_CHKCAT - * - * Revision 1.2 1998/07/03 14:38:25 malthoff - * Add category SK_DBGCAT_FATAL. - * - * Revision 1.1 1998/06/19 13:39:01 malthoff - * created. - * + * /LICENSE * ******************************************************************************/ #ifndef __INC_SKDEBUG_H #define __INC_SKDEBUG_H +/* #define DEBUG */ #ifdef DEBUG #ifndef SK_DBG_MSG #define SK_DBG_MSG(pAC,comp,cat,arg) \ - if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \ - ((cat) & SK_DBG_CHKCAT(pAC)) ) { \ - SK_DBG_PRINTF arg ; \ + if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \ + ((cat) & SK_DBG_CHKCAT(pAC)) ) { \ + SK_DBG_PRINTF arg; \ } #endif #else @@ -103,6 +60,13 @@ #define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ #define SK_DBGMOD_PECP 0x00000100L /* PECP module */ #define SK_DBGMOD_POWM 0x00000200L /* Power Management module */ +#ifdef SK_ASF +#define SK_DBGMOD_ASF 0x00000400L /* ASF module */ +#endif +#ifdef SK_LBFO +#define SK_DBGMOD_LACP 0x00000800L /* link aggregation control protocol */ +#define SK_DBGMOD_FD 0x00001000L /* frame distributor (link aggregation) */ +#endif /* SK_LBFO */ /* Debug events */ diff --git a/drivers/sk98lin/h/skdrv1st.h b/drivers/sk98lin/h/skdrv1st.h index af34d7b..04c3ba6 100644 --- a/drivers/sk98lin/h/skdrv1st.h +++ b/drivers/sk98lin/h/skdrv1st.h @@ -2,15 +2,16 @@ * * Name: skdrv1st.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/02/25 14:16:40 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: First header file for driver and all other modules * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. * * 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 @@ -21,125 +22,51 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skdrv1st.h,v $ - * Revision 1.11 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.10 2002/10/02 12:46:02 mlindner - * Add: Support for Yukon - * - * Revision 1.9.2.2 2001/12/07 12:06:42 mlindner - * Fix: malloc -> slab changes - * - * Revision 1.9.2.1 2001/03/12 16:50:59 mlindner - * chg: kernel 2.4 adaption - * - * Revision 1.9 2001/01/22 14:16:04 mlindner - * added ProcFs functionality - * Dual Net functionality integrated - * Rlmt networks added - * - * Revision 1.8 2000/02/21 12:19:18 cgoos - * Added default for SK_DEBUG_CHKMOD/_CHKCAT - * - * Revision 1.7 1999/11/22 13:50:00 cgoos - * Changed license header to GPL. - * Added overwrite for several functions. - * Removed linux 2.0.x definitions. - * Removed PCI vendor ID definition (now in kernel). - * - * Revision 1.6 1999/07/27 08:03:33 cgoos - * Changed SK_IN/OUT macros to readX/writeX instead of memory - * accesses (necessary for ALPHA). - * - * Revision 1.5 1999/07/23 12:10:21 cgoos - * Removed SK_RLMT_SLOW_LOOKAHEAD define. - * - * Revision 1.4 1999/07/14 12:31:13 cgoos - * Added SK_RLMT_SLOW_LOOKAHEAD define. - * - * Revision 1.3 1999/04/07 10:12:54 cgoos - * Added check for KERNEL and OPTIMIZATION defines. - * - * Revision 1.2 1999/03/01 08:51:47 cgoos - * Fixed pcibios_read/write definitions. - * - * Revision 1.1 1999/02/16 07:40:49 cgoos - * First version. - * - * - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the first include file of the driver, which includes all - * neccessary system header files and some of the GEnesis header files. - * It also defines some basic items. - * - * Include File Hierarchy: - * - * see skge.c - * - ******************************************************************************/ - #ifndef __INC_SKDRV1ST_H #define __INC_SKDRV1ST_H -#if 0 +#if 0 /* uboot */ /* Check kernel version */ #include -#if (LINUX_VERSION_CODE > 0x020300) -#endif #endif typedef struct s_AC SK_AC; +/* Set card versions */ +#define SK_FAR + /* override some default functions with optimized linux functions */ #define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2) #define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4) #define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8) #define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2) -#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),2) -#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),2) - -#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) +#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),4) +#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),8) #define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6)) +#define SK_STRNCMP(s1,s2,len) strncmp(s1,s2,len) +#define SK_STRCPY(dest,src) strcpy(dest,src) -#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) -#warning You must compile this file with the correct options! -#warning See the last lines of the source file. -#error You must compile this driver with "-O". -#endif - -#if 0 -#include -#endif #include -#if 0 +#if 0 /* uboot */ #include #endif #include -#if 0 +#if 0 /* uboot */ #include #include #include #include #include #endif + #include #include #include -#if 0 + +#if 0 /* uboot */ #include #include #include @@ -149,6 +76,13 @@ typedef struct s_AC SK_AC; #include #endif +#define SK_CS_CALCULATE_CHECKSUM +#ifndef CONFIG_X86_64 +#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) +#else +#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff) +#endif + #include "h/sktypes.h" #include "h/skerror.h" #include "h/skdebug.h" @@ -157,29 +91,30 @@ typedef struct s_AC SK_AC; #include "u-boot_compat.h" +#ifndef SK_BMU_RX_WM_PEX +#define SK_BMU_RX_WM_PEX 0x80 +#endif + #ifdef __LITTLE_ENDIAN #define SK_LITTLE_ENDIAN #else #define SK_BIG_ENDIAN +#define SK_USE_REV_DESC #endif -#if 0 +#if 0 /* uboot */ #define SK_NET_DEVICE net_device #else -#define SK_NET_DEVICE eth_device +#define SK_NET_DEVICE eth_device #endif /* we use gethrtime(), return unit: nanoseconds */ -#if 0 -#define SK_TICKS_PER_SEC HZ -#else -#define SK_TICKS_PER_SEC CFG_HZ -#endif +#define SK_TICKS_PER_SEC 100 #define SK_MEM_MAPPED_IO -/* #define SK_RLMT_SLOW_LOOKAHEAD */ +// #define SK_RLMT_SLOW_LOOKAHEAD #define SK_MAX_MACS 2 #define SK_MAX_NETS 2 @@ -199,9 +134,9 @@ typedef struct s_DrvRlmtMbuf SK_MBUF; #define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2)) /* macros to access the adapter */ -#define SK_OUT8(b,a,v) writeb((v), ((b)+(a))) -#define SK_OUT16(b,a,v) writew((v), ((b)+(a))) -#define SK_OUT32(b,a,v) writel((v), ((b)+(a))) +#define SK_OUT8(b,a,v) writeb((v), ((b)+(a))) +#define SK_OUT16(b,a,v) writew((v), ((b)+(a))) +#define SK_OUT32(b,a,v) writel((v), ((b)+(a))) #define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a))) #define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a))) #define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a))) @@ -225,6 +160,7 @@ typedef struct s_DrvRlmtMbuf SK_MBUF; #define UINT32_C(a) __CONCAT__(a,UL) #define UINT64_C(a) __CONCAT__(a,ULL) +#define DEBUG #ifdef DEBUG #define SK_DBG_PRINTF printk #ifndef SK_DEBUG_CHKMOD @@ -262,3 +198,9 @@ extern void SkDbgPrintf(const char *format,...); extern void SkErrorLog(SK_AC*, int, int, char*); #endif + +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ diff --git a/drivers/sk98lin/h/skdrv2nd.h b/drivers/sk98lin/h/skdrv2nd.h index a311827..eb66424 100644 --- a/drivers/sk98lin/h/skdrv2nd.h +++ b/drivers/sk98lin/h/skdrv2nd.h @@ -1,16 +1,17 @@ /****************************************************************************** * - * Name: skdrv2nd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/02/25 14:16:40 $ - * Purpose: Second header file for driver and all other modules + * Name: skdrv2nd.h + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Second header file for driver and all other modules * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. * * 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 @@ -21,76 +22,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skdrv2nd.h,v $ - * Revision 1.15 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.14 2003/02/25 13:26:26 mlindner - * Add: Support for various vendors - * - * Revision 1.13 2002/10/02 12:46:02 mlindner - * Add: Support for Yukon - * - * Revision 1.12.2.2 2001/09/05 12:14:50 mlindner - * add: New hardware revision int - * - * Revision 1.12.2.1 2001/03/12 16:50:59 mlindner - * chg: kernel 2.4 adaption - * - * Revision 1.12 2001/03/01 12:52:15 mlindner - * Fixed ring size - * - * Revision 1.11 2001/02/19 13:28:02 mlindner - * Changed PNMI parameter values - * - * Revision 1.10 2001/01/22 14:16:04 mlindner - * added ProcFs functionality - * Dual Net functionality integrated - * Rlmt networks added - * - * Revision 1.1 2000/10/05 19:46:50 phargrov - * Add directory src/vipk_devs_nonlbl/vipk_sk98lin/ - * This is the SysKonnect SK-98xx Gigabit Ethernet driver, - * contributed by SysKonnect. - * - * Revision 1.9 2000/02/21 10:39:55 cgoos - * Added flag for jumbo support usage. - * - * Revision 1.8 1999/11/22 13:50:44 cgoos - * Changed license header to GPL. - * Fixed two comments. - * - * Revision 1.7 1999/09/28 12:38:21 cgoos - * Added CheckQueue to SK_AC. - * - * Revision 1.6 1999/07/27 08:04:05 cgoos - * Added checksumming variables to SK_AC. - * - * Revision 1.5 1999/03/29 12:33:26 cgoos - * Rreversed to fine lock granularity. - * - * Revision 1.4 1999/03/15 12:14:02 cgoos - * Added DriverLock to SK_AC. - * Removed other locks. - * - * Revision 1.3 1999/03/01 08:52:27 cgoos - * Changed pAC->PciDev declaration. - * - * Revision 1.2 1999/02/18 10:57:14 cgoos - * Removed SkDrvTimeStamp prototype. - * Fixed SkGeOsGetTime prototype. - * - * Revision 1.1 1999/02/16 07:41:01 cgoos - * First version. - * - * - * - ******************************************************************************/ - /****************************************************************************** * * Description: @@ -111,10 +42,11 @@ #include "h/skqueue.h" #include "h/skgehwt.h" #include "h/sktimer.h" -#include "h/ski2c.h" +#include "h/sktwsi.h" #include "h/skgepnmi.h" #include "h/skvpd.h" #include "h/skgehw.h" +#include "h/sky2le.h" #include "h/skgeinit.h" #include "h/skaddr.h" #include "h/skgesirq.h" @@ -122,123 +54,198 @@ #include "h/skrlmt.h" #include "h/skgedrv.h" -#define SK_PCI_ISCOMPLIANT(result, pdev) { \ - result = SK_FALSE; /* default */ \ - /* 3Com (0x10b7) */ \ - if (pdev->vendor == 0x10b7) { \ - /* Gigabit Ethernet Adapter (0x1700) */ \ - if ((pdev->device == 0x1700)) { \ - result = SK_TRUE; \ - } \ - /* SysKonnect (0x1148) */ \ - } else if (pdev->vendor == 0x1148) { \ - /* SK-98xx Gigabit Ethernet Server Adapter (0x4300) */ \ - /* SK-98xx V2 Gigabit Ethernet Adapter (0x4320) */ \ - if ((pdev->device == 0x4300) || \ - (pdev->device == 0x4320)) { \ - result = SK_TRUE; \ - } \ - /* D-Link (0x1186) */ \ - } else if (pdev->vendor == 0x1186) { \ - /* Gigabit Ethernet Adapter (0x4c00) */ \ - if ((pdev->device == 0x4c00)) { \ - result = SK_TRUE; \ - } \ - /* CNet (0x1371) */ \ - } else if (pdev->vendor == 0x1371) { \ - /* GigaCard Network Adapter (0x434e) */ \ - if ((pdev->device == 0x434e)) { \ - result = SK_TRUE; \ - } \ - /* Linksys (0x1737) */ \ - } else if (pdev->vendor == 0x1737) { \ - /* Gigabit Network Adapter (0x1032) */ \ - /* Gigabit Network Adapter (0x1064) */ \ - if ((pdev->device == 0x1032) || \ - (pdev->device == 0x1064)) { \ - result = SK_TRUE; \ - } \ - } else { \ - result = SK_FALSE; \ - } \ -} +/* Defines for the poll cotroller */ +#define SK_NETDUMP_POLL + +#ifdef SK_NETDUMP_POLL +#ifdef HAVE_POLL_CONTROLLER +#define SK_POLL_CONTROLLER +#define CONFIG_SK98LIN_NAPI +#elif CONFIG_NET_POLL_CONTROLLER +#define SK_POLL_CONTROLLER +#define CONFIG_SK98LIN_NAPI +#endif +#endif -extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned); -extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*); -extern SK_U64 SkOsGetTime(SK_AC*); -extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*); -extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*); -extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*); -extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32); -extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16); -extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8); -extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA); - -struct s_DrvRlmtMbuf { - SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */ - SK_U8 *pData; /* Data buffer (virtually contig.). */ - unsigned Size; /* Data buffer size. */ - unsigned Length; /* Length of packet (<= Size). */ - SK_U32 PortIdx; /* Receiving/transmitting port. */ -#ifdef SK_RLMT_MBUF_PRIVATE - SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */ -#endif /* SK_RLMT_MBUF_PRIVATE */ - struct sk_buff *pOs; /* Pointer to message block */ -}; +/****************************************************************************** + * + * Generic driver defines + * + ******************************************************************************/ +#define USE_TIST_FOR_RESET /* Use timestamp for reset */ +#define Y2_RECOVERY /* use specific recovery yukon2 functions */ +#if 0 // u-boot +#define Y2_LE_CHECK /* activate check for LE order */ +#define Y2_SYNC_CHECK /* activate check for receiver in sync */ +#endif +#define SK_YUKON2 /* Enable Yukon2 dual net support */ +#define USE_SK_TX_CHECKSUM /* use the tx hw checksum driver functionality */ +#define USE_SK_RX_CHECKSUM /* use the rx hw checksum driver functionality */ +#define USE_SK_TSO_FEATURE /* use TCP segmentation offload if possible */ +#define SK_COPY_THRESHOLD 50 /* threshold for copying small RX frames; + * 0 avoids copying, 9001 copies all */ +#define SK_MAX_CARD_PARAM 16 /* number of adapters that can be configured via + * command line params */ +//#define USE_TX_COMPLETE /* use of a transmit complete interrupt */ +#define Y2_RX_CHECK /* RX Check timestamp */ /* - * ioctl definitions + * use those defines for a compile-in version of the driver instead + * of command line parameters */ -#define SK_IOCTL_BASE (SIOCDEVPRIVATE) -#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0) -#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1) -#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2) +// #define LINK_SPEED_A {"Auto",} +// #define LINK_SPEED_B {"Auto",} +// #define AUTO_NEG_A {"Sense",} +// #define AUTO_NEG_B {"Sense"} +// #define DUP_CAP_A {"Both",} +// #define DUP_CAP_B {"Both",} +// #define FLOW_CTRL_A {"SymOrRem",} +// #define FLOW_CTRL_B {"SymOrRem",} +// #define ROLE_A {"Auto",} +// #define ROLE_B {"Auto",} +// #define PREF_PORT {"A",} +// #define CON_TYPE {"Auto",} +// #define RLMT_MODE {"CheckLinkState",} -typedef struct s_IOCTL SK_GE_IOCTL; +#ifdef Y2_RECOVERY +#define CHECK_TRANSMIT_TIMEOUT +#define Y2_RESYNC_WATERMARK 1000000L +#endif + +/****************************************************************************** + * + * Generic ISR defines + * + ******************************************************************************/ + +#define SkIsrRetVar void +#define SkIsrRetNone NULL +#define SkIsrRetHandled NULL + +#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) +#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb) +#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb) + +/****************************************************************************** + * + * Global function prototypes + * + ******************************************************************************/ + +extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned); +extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*); +extern SK_U64 SkOsGetTime(SK_AC*); +extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*); +extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*); +extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*); +extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32); +extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16); +extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8); +extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA); +extern int SkDrvEnterDiagMode(SK_AC *pAc); +extern int SkDrvLeaveDiagMode(SK_AC *pAc); + +/****************************************************************************** + * + * Linux specific RLMT buffer structure (SK_MBUF typedef in skdrv1st)! + * + ******************************************************************************/ + +struct s_DrvRlmtMbuf { + SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */ + SK_U8 *pData; /* Data buffer (virtually contig.). */ + unsigned Size; /* Data buffer size. */ + unsigned Length; /* Length of packet (<= Size). */ + SK_U32 PortIdx; /* Receiving/transmitting port. */ +#ifdef SK_RLMT_MBUF_PRIVATE + SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */ +#endif + struct sk_buff *pOs; /* Pointer to message block */ +}; + +/****************************************************************************** + * + * Linux specific TIME defines + * + ******************************************************************************/ + +#if SK_TICKS_PER_SEC == 100 +#define SK_PNMI_HUNDREDS_SEC(t) (t) +#else +#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t)*100)/(SK_TICKS_PER_SEC)) +#endif + +#define SkOsGetTimeCurrent(pAC, pUsec) {\ + static struct timeval prev_t; \ + struct timeval t;\ + do_gettimeofday(&t);\ + if (prev_t.tv_sec == t.tv_sec) { \ + if (prev_t.tv_usec > t.tv_usec) { \ + t.tv_usec = prev_t.tv_usec; \ + } else { \ + prev_t.tv_usec = t.tv_usec; \ + } \ + } else { \ + prev_t = t; \ + } \ + *pUsec = ((t.tv_sec*100L)+(t.tv_usec/10000));\ +} + +/****************************************************************************** + * + * Linux specific IOCTL defines and typedefs + * + ******************************************************************************/ + +#define SK_IOCTL_BASE (SIOCDEVPRIVATE) +#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0) +#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1) +#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2) +#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3) +#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4) + +typedef struct s_IOCTL SK_GE_IOCTL; struct s_IOCTL { char* pData; unsigned int Len; }; +/****************************************************************************** + * + * Generic sizes and length definitions + * + ******************************************************************************/ -/* - * define sizes of descriptor rings in bytes - */ - -#if 0 -#define TX_RING_SIZE (8*1024) -#define RX_RING_SIZE (24*1024) +#if 0 /* uboot */ +#define TX_RING_SIZE (24*1024) /* GEnesis/Yukon */ +#define RX_RING_SIZE (24*1024) /* GEnesis/Yukon */ #else -#define TX_RING_SIZE (10 * 40) -#define RX_RING_SIZE (10 * 40) +#define TX_RING_SIZE (10 * 40) +#define RX_RING_SIZE (10 * 40) #endif +#define RX_MAX_NBR_BUFFERS 128 /* Yukon-EC/-II */ +#define TX_MAX_NBR_BUFFERS 128 /* Yukon-EC/-II */ +#define MAXIMUM_LOW_ADDRESS 0xFFFFFFFF /* Max. low address */ -/* - * Buffer size for ethernet packets - */ -#define ETH_BUF_SIZE 1540 -#define ETH_MAX_MTU 1514 -#define ETH_MIN_MTU 60 -#define ETH_MULTICAST_BIT 0x01 -#define SK_JUMBO_MTU 9000 +#define ETH_BUF_SIZE 1560 /* multiples of 8 bytes */ +#define ETH_MAX_MTU 1514 +#define ETH_MIN_MTU 60 +#define ETH_MULTICAST_BIT 0x01 +#define SK_JUMBO_MTU 9000 -/* - * transmit priority selects the queue: LOW=asynchron, HIGH=synchron - */ -#define TX_PRIO_LOW 0 -#define TX_PRIO_HIGH 1 +#define TX_PRIO_LOW 0 /* asynchronous queue */ +#define TX_PRIO_HIGH 1 /* synchronous queue */ +#define DESCR_ALIGN 64 /* alignment of Rx/Tx descriptors */ -/* - * alignment of rx/tx descriptors - */ -#define DESCR_ALIGN 8 +/****************************************************************************** + * + * PNMI related definitions + * + ******************************************************************************/ -/* - * definitions for pnmi. TODO - */ #define SK_DRIVER_RESET(pAC, IoC) 0 #define SK_DRIVER_SENDEVENT(pAC, IoC) 0 #define SK_DRIVER_SELFTEST(pAC, IoC) 0 @@ -248,314 +255,665 @@ struct s_IOCTL { #define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0 -/* TX and RX descriptors *****************************************************/ +/****************************************************************************** + * + * Various offsets and sizes + * + ******************************************************************************/ + +#define SK_DRV_MODERATION_TIMER 1 /* id */ +#define SK_DRV_MODERATION_TIMER_LENGTH 1 /* 1 second */ + +#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6 +#define C_LEN_ETHERMAC_HEADER_SRC_ADDR 6 +#define C_LEN_ETHERMAC_HEADER_LENTYPE 2 +#define C_LEN_ETHERMAC_HEADER ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \ + (C_LEN_ETHERMAC_HEADER_SRC_ADDR) + \ + (C_LEN_ETHERMAC_HEADER_LENTYPE) ) + +#define C_LEN_ETHERMTU_MINSIZE 46 +#define C_LEN_ETHERMTU_MAXSIZE_STD 1500 +#define C_LEN_ETHERMTU_MAXSIZE_JUMBO 9000 + +#define C_LEN_ETHERNET_MINSIZE ( (C_LEN_ETHERMAC_HEADER) + \ + (C_LEN_ETHERMTU_MINSIZE) ) + +#define C_OFFSET_IPHEADER C_LEN_ETHERMAC_HEADER +#define C_OFFSET_IPHEADER_IPPROTO 9 +#define C_OFFSET_TCPHEADER_TCPCS 16 +#define C_OFFSET_UDPHEADER_UDPCS 6 + +#define C_OFFSET_IPPROTO ( (C_LEN_ETHERMAC_HEADER) + \ + (C_OFFSET_IPHEADER_IPPROTO) ) + +#define C_PROTO_ID_UDP 17 /* refer to RFC 790 or Stevens' */ +#define C_PROTO_ID_TCP 6 /* TCP/IP illustrated for details */ + +/****************************************************************************** + * + * Tx and Rx descriptor definitions + * + ******************************************************************************/ typedef struct s_RxD RXD; /* the receive descriptor */ - struct s_RxD { - volatile SK_U32 RBControl; /* Receive Buffer Control */ - SK_U32 VNextRxd; /* Next receive descriptor,low dword */ - SK_U32 VDataLow; /* Receive buffer Addr, low dword */ - SK_U32 VDataHigh; /* Receive buffer Addr, high dword */ - SK_U32 FrameStat; /* Receive Frame Status word */ - SK_U32 TimeStamp; /* Time stamp from XMAC */ - SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */ - SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */ - RXD *pNextRxd; /* Pointer to next Rxd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ + volatile SK_U32 RBControl; /* Receive Buffer Control */ + SK_U32 VNextRxd; /* Next receive descriptor,low dword */ + SK_U32 VDataLow; /* Receive buffer Addr, low dword */ + SK_U32 VDataHigh; /* Receive buffer Addr, high dword */ + SK_U32 FrameStat; /* Receive Frame Status word */ + SK_U32 TimeStamp; /* Time stamp from XMAC */ + SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */ + SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */ + RXD *pNextRxd; /* Pointer to next Rxd */ + struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ }; typedef struct s_TxD TXD; /* the transmit descriptor */ - struct s_TxD { - volatile SK_U32 TBControl; /* Transmit Buffer Control */ - SK_U32 VNextTxd; /* Next transmit descriptor,low dword */ - SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */ - SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */ - SK_U32 FrameStat; /* Transmit Frame Status Word */ - SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */ - SK_U16 TcpSumSt; /* TCP Sum Start */ - SK_U16 TcpSumWr; /* TCP Sum Write */ - SK_U32 TcpReserved; /* not used */ - TXD *pNextTxd; /* Pointer to next Txd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ + volatile SK_U32 TBControl; /* Transmit Buffer Control */ + SK_U32 VNextTxd; /* Next transmit descriptor,low dword */ + SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */ + SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */ + SK_U32 FrameStat; /* Transmit Frame Status Word */ + SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */ + SK_U16 TcpSumSt; /* TCP Sum Start */ + SK_U16 TcpSumWr; /* TCP Sum Write */ + SK_U32 TcpReserved; /* not used */ + TXD *pNextTxd; /* Pointer to next Txd */ + struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ }; +/****************************************************************************** + * + * Generic Yukon-II defines + * + ******************************************************************************/ -/* definition of flags in descriptor control field */ -#define RX_CTRL_OWN_BMU UINT32_C(0x80000000) -#define RX_CTRL_STF UINT32_C(0x40000000) -#define RX_CTRL_EOF UINT32_C(0x20000000) -#define RX_CTRL_EOB_IRQ UINT32_C(0x10000000) -#define RX_CTRL_EOF_IRQ UINT32_C(0x08000000) -#define RX_CTRL_DEV_NULL UINT32_C(0x04000000) -#define RX_CTRL_STAT_VALID UINT32_C(0x02000000) -#define RX_CTRL_TIME_VALID UINT32_C(0x01000000) -#define RX_CTRL_CHECK_DEFAULT UINT32_C(0x00550000) -#define RX_CTRL_CHECK_CSUM UINT32_C(0x00560000) -#define RX_CTRL_LEN_MASK UINT32_C(0x0000FFFF) +#define LE_SIZE sizeof(SK_HWLE) +#if 1 /* uboot */ +#define MAX_SKB_FRAGS 10 +#endif +#define MAX_NUM_FRAGS (MAX_SKB_FRAGS + 1) +#define MIN_LEN_OF_LE_TAB 128 +#define MAX_LEN_OF_LE_TAB 4096 +#define MAX_UNUSED_RX_LE_WORKING 8 +#if 1 /* Marvell - uboot:this increases the RX packets to 128-120 = 8*/ +#ifdef MAX_FRAG_OVERHEAD +#undef MAX_FRAG_OVERHEAD +#define MAX_FRAG_OVERHEAD 120 +#endif +#endif +// as we have a maximum of 16 physical fragments, +// maximum 1 ADDR64 per physical fragment +// maximum 4 LEs for VLAN, Csum, LargeSend, Packet +#define MIN_LE_FREE_REQUIRED ((16*2) + 4) +#define IS_GMAC(pAc) (!pAc->GIni.GIGenesis) +#ifdef USE_SYNC_TX_QUEUE +#define TXS_MAX_LE 256 +#else /* !USE_SYNC_TX_QUEUE */ +#define TXS_MAX_LE 0 +#endif -#define TX_CTRL_OWN_BMU UINT32_C(0x80000000) -#define TX_CTRL_STF UINT32_C(0x40000000) -#define TX_CTRL_EOF UINT32_C(0x20000000) -#define TX_CTRL_EOB_IRQ UINT32_C(0x10000000) -#define TX_CTRL_EOF_IRQ UINT32_C(0x08000000) -#define TX_CTRL_ST_FWD UINT32_C(0x04000000) -#define TX_CTRL_DISAB_CRC UINT32_C(0x02000000) -#define TX_CTRL_SOFTWARE UINT32_C(0x01000000) -#define TX_CTRL_CHECK_DEFAULT UINT32_C(0x00550000) -#define TX_CTRL_CHECK_CSUM UINT32_C(0x00560000) -#define TX_CTRL_LEN_MASK UINT32_C(0x0000FFFF) +#define ETHER_MAC_HDR_LEN (6+6+2) // MAC SRC ADDR, MAC DST ADDR, TYPE +#define IP_HDR_LEN 20 +#define TCP_CSUM_OFFS 0x10 +#define UDP_CSUM_OFFS 0x06 +#define TXA_MAX_LE 256 +#if 0 /* Marvell - uboot : set the RX LE to 128 */ +#define RX_MAX_LE 256 +#else +#define RX_MAX_LE 128 +#endif +#define ST_MAX_LE (SK_MAX_MACS)*((3*RX_MAX_LE)+(TXA_MAX_LE)+(TXS_MAX_LE)) + +#if (defined (Y2_RECOVERY) || defined (Y2_LE_CHECK)) +/* event for recovery from tx hang or rx out of sync */ +#define SK_DRV_RECOVER 17 +#endif +/****************************************************************************** + * + * Structures specific for Yukon-II + * + ******************************************************************************/ + +typedef struct s_frag SK_FRAG; +struct s_frag { + SK_FRAG *pNext; + char *pVirt; + SK_U64 pPhys; + unsigned int FragLen; +}; + +typedef struct s_packet SK_PACKET; +struct s_packet { + /* Common infos: */ + SK_PACKET *pNext; /* pointer for packet queues */ + unsigned int PacketLen; /* length of packet */ + unsigned int NumFrags; /* nbr of fragments (for Rx always 1) */ + SK_FRAG *pFrag; /* fragment list */ + SK_FRAG FragArray[MAX_NUM_FRAGS]; /* TX fragment array */ + unsigned int NextLE; /* next LE to use for the next packet */ + + /* Private infos: */ + struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ +}; + +typedef struct s_queue SK_PKT_QUEUE; +struct s_queue { + SK_PACKET *pHead; + SK_PACKET *pTail; +#if 0 /* uboot */ + spinlock_t QueueLock; /* serialize packet accesses */ +#endif +}; + +/******************************************************************************* + * + * Macros specific for Yukon-II queues + * + ******************************************************************************/ + +#define IS_Q_EMPTY(pQueue) ((pQueue)->pHead != NULL) ? SK_FALSE : SK_TRUE +#define IS_Q_LOCKED(pQueue) spin_is_locked(&((pQueue)->QueueLock)) + +#define PLAIN_POP_FIRST_PKT_FROM_QUEUE(pQueue, pPacket) { \ + if ((pQueue)->pHead != NULL) { \ + (pPacket) = (pQueue)->pHead; \ + (pQueue)->pHead = (pPacket)->pNext; \ + if ((pQueue)->pHead == NULL) { \ + (pQueue)->pTail = NULL; \ + } \ + (pPacket)->pNext = NULL; \ + } else { \ + (pPacket) = NULL; \ + } \ +} + +#define PLAIN_PUSH_PKT_AS_FIRST_IN_QUEUE(pQueue, pPacket) { \ + if ((pQueue)->pHead != NULL) { \ + (pPacket)->pNext = (pQueue)->pHead; \ + } else { \ + (pPacket)->pNext = NULL; \ + (pQueue)->pTail = (pPacket); \ + } \ + (pQueue)->pHead = (pPacket); \ +} + +#define PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(pQueue, pPacket) { \ + (pPacket)->pNext = NULL; \ + if ((pQueue)->pTail != NULL) { \ + (pQueue)->pTail->pNext = (pPacket); \ + } else { \ + (pQueue)->pHead = (pPacket); \ + } \ + (pQueue)->pTail = (pPacket); \ +} + +#define PLAIN_PUSH_MULTIPLE_PKT_AS_LAST_IN_QUEUE(pQueue,pPktGrpStart,pPktGrpEnd) { \ + if ((pPktGrpStart) != NULL) { \ + if ((pQueue)->pTail != NULL) { \ + (pQueue)->pTail->pNext = (pPktGrpStart); \ + } else { \ + (pQueue)->pHead = (pPktGrpStart); \ + } \ + (pQueue)->pTail = (pPktGrpEnd); \ + } \ +} + +/* Required: 'Flags' */ +#define POP_FIRST_PKT_FROM_QUEUE(pQueue, pPacket) { \ + spin_lock_irqsave(&((pQueue)->QueueLock), Flags); \ + if ((pQueue)->pHead != NULL) { \ + (pPacket) = (pQueue)->pHead; \ + (pQueue)->pHead = (pPacket)->pNext; \ + if ((pQueue)->pHead == NULL) { \ + (pQueue)->pTail = NULL; \ + } \ + (pPacket)->pNext = NULL; \ + } else { \ + (pPacket) = NULL; \ + } \ + spin_unlock_irqrestore(&((pQueue)->QueueLock), Flags); \ +} + +/* Required: 'Flags' */ +#define PUSH_PKT_AS_FIRST_IN_QUEUE(pQueue, pPacket) { \ + spin_lock_irqsave(&(pQueue)->QueueLock, Flags); \ + if ((pQueue)->pHead != NULL) { \ + (pPacket)->pNext = (pQueue)->pHead; \ + } else { \ + (pPacket)->pNext = NULL; \ + (pQueue)->pTail = (pPacket); \ + } \ + (pQueue)->pHead = (pPacket); \ + spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags); \ +} + +/* Required: 'Flags' */ +#define PUSH_PKT_AS_LAST_IN_QUEUE(pQueue, pPacket) { \ + (pPacket)->pNext = NULL; \ + spin_lock_irqsave(&(pQueue)->QueueLock, Flags); \ + if ((pQueue)->pTail != NULL) { \ + (pQueue)->pTail->pNext = (pPacket); \ + } else { \ + (pQueue)->pHead = (pPacket); \ + } \ + (pQueue)->pTail = (pPacket); \ + spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags); \ +} + +/* Required: 'Flags' */ +#define PUSH_MULTIPLE_PKT_AS_LAST_IN_QUEUE(pQueue,pPktGrpStart,pPktGrpEnd) { \ + if ((pPktGrpStart) != NULL) { \ + spin_lock_irqsave(&(pQueue)->QueueLock, Flags); \ + if ((pQueue)->pTail != NULL) { \ + (pQueue)->pTail->pNext = (pPktGrpStart); \ + } else { \ + (pQueue)->pHead = (pPktGrpStart); \ + } \ + (pQueue)->pTail = (pPktGrpEnd); \ + spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags); \ + } \ +} + +/* + *Check if the low address (32 bit) is near the 4G limit or over it. + * Set the high address to a wrong value. + * Doing so we force to write the ADDR64 LE. + */ +#define CHECK_LOW_ADDRESS( _HighAddress, _LowAddress , _Length) { \ + if ((~0-_LowAddress) <_Length) { \ + _HighAddress= MAXIMUM_LOW_ADDRESS; \ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, \ + ("High Address must be set for HW. LowAddr = %d Length = %d\n", \ + _LowAddress, _Length)); \ + } \ +} + +/******************************************************************************* + * + * Macros specific for Yukon-II queues (tist) + * + ******************************************************************************/ + +#ifdef USE_TIST_FOR_RESET +/* port is fully operational */ +#define SK_PSTATE_NOT_WAITING_FOR_TIST 0 +/* port in reset until any tist LE */ +#define SK_PSTATE_WAITING_FOR_ANY_TIST BIT_0 +/* port in reset until timer reaches pAC->MinTistLo */ +#define SK_PSTATE_WAITING_FOR_SPECIFIC_TIST BIT_1 +#define SK_PSTATE_PORT_SHIFT 4 +#define SK_PSTATE_PORT_MASK ((1 << SK_PSTATE_PORT_SHIFT) - 1) + +/* use this + Port to build OP_MOD_TXINDEX_NO_PORT_A|B */ +#define OP_MOD_TXINDEX 0x71 +/* opcode for a TX_INDEX LE in which Port A has to be ignored */ +#define OP_MOD_TXINDEX_NO_PORT_A 0x71 +/* opcode for a TX_INDEX LE in which Port B has to be ignored */ +#define OP_MOD_TXINDEX_NO_PORT_B 0x72 +/* opcode for LE to be ignored because port is still in reset */ +#define OP_MOD_LE 0x7F + +/* set tist wait mode Bit for port */ +#define SK_SET_WAIT_BIT_FOR_PORT(pAC, Bit, Port) \ + { \ + (pAC)->AdapterResetState |= ((Bit) << (SK_PSTATE_PORT_SHIFT * Port)); \ + } + +/* reset tist waiting for specified port */ +#define SK_CLR_STATE_FOR_PORT(pAC, Port) \ + { \ + (pAC)->AdapterResetState &= \ + ~(SK_PSTATE_PORT_MASK << (SK_PSTATE_PORT_SHIFT * Port)); \ + } + +/* return SK_TRUE when port is in reset waiting for tist */ +#define SK_PORT_WAITING_FOR_TIST(pAC, Port) \ + ((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \ + SK_PSTATE_PORT_MASK) != SK_PSTATE_NOT_WAITING_FOR_TIST) + +/* return SK_TRUE when port is in reset waiting for any tist */ +#define SK_PORT_WAITING_FOR_ANY_TIST(pAC, Port) \ + ((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \ + SK_PSTATE_WAITING_FOR_ANY_TIST) == SK_PSTATE_WAITING_FOR_ANY_TIST) + +/* return SK_TRUE when port is in reset waiting for a specific tist */ +#define SK_PORT_WAITING_FOR_SPECIFIC_TIST(pAC, Port) \ + ((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \ + SK_PSTATE_WAITING_FOR_SPECIFIC_TIST) == \ + SK_PSTATE_WAITING_FOR_SPECIFIC_TIST) + +/* return whether adapter is expecting a tist LE */ +#define SK_ADAPTER_WAITING_FOR_TIST(pAC) ((pAC)->AdapterResetState != 0) + +/* enable timestamp timer and force creation of tist LEs */ +#define Y2_ENABLE_TIST(IoC) \ + SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8) GMT_ST_START) + +/* disable timestamp timer and stop creation of tist LEs */ +#define Y2_DISABLE_TIST(IoC) \ + SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8) GMT_ST_STOP) + +/* get current value of timestamp timer */ +#define Y2_GET_TIST_LOW_VAL(IoC, pVal) \ + SK_IN32(IoC, GMAC_TI_ST_VAL, pVal) + +#endif -/* The offsets of registers in the TX and RX queue control io area ***********/ +/******************************************************************************* + * + * Used interrupt bits in the interrupts source register + * + ******************************************************************************/ -#define RX_Q_BUF_CTRL_CNT 0x00 -#define RX_Q_NEXT_DESCR_LOW 0x04 -#define RX_Q_BUF_ADDR_LOW 0x08 -#define RX_Q_BUF_ADDR_HIGH 0x0c -#define RX_Q_FRAME_STAT 0x10 -#define RX_Q_TIME_STAMP 0x14 -#define RX_Q_CSUM_1_2 0x18 -#define RX_Q_CSUM_START_1_2 0x1c -#define RX_Q_CUR_DESCR_LOW 0x20 -#define RX_Q_DESCR_HIGH 0x24 -#define RX_Q_CUR_ADDR_LOW 0x28 -#define RX_Q_CUR_ADDR_HIGH 0x2c -#define RX_Q_CUR_BYTE_CNT 0x30 -#define RX_Q_CTRL 0x34 -#define RX_Q_FLAG 0x38 -#define RX_Q_TEST1 0x3c -#define RX_Q_TEST2 0x40 -#define RX_Q_TEST3 0x44 +#define DRIVER_IRQS ((IS_IRQ_SW) | \ + (IS_R1_F) | (IS_R2_F) | \ + (IS_XS1_F) | (IS_XA1_F) | \ + (IS_XS2_F) | (IS_XA2_F)) -#define TX_Q_BUF_CTRL_CNT 0x00 -#define TX_Q_NEXT_DESCR_LOW 0x04 -#define TX_Q_BUF_ADDR_LOW 0x08 -#define TX_Q_BUF_ADDR_HIGH 0x0c -#define TX_Q_FRAME_STAT 0x10 -#define TX_Q_CSUM_START 0x14 -#define TX_Q_CSUM_START_POS 0x18 -#define TX_Q_RESERVED 0x1c -#define TX_Q_CUR_DESCR_LOW 0x20 -#define TX_Q_DESCR_HIGH 0x24 -#define TX_Q_CUR_ADDR_LOW 0x28 -#define TX_Q_CUR_ADDR_HIGH 0x2c -#define TX_Q_CUR_BYTE_CNT 0x30 -#define TX_Q_CTRL 0x34 -#define TX_Q_FLAG 0x38 -#define TX_Q_TEST1 0x3c -#define TX_Q_TEST2 0x40 -#define TX_Q_TEST3 0x44 +#define TX_COMPL_IRQS ((IS_XS1_B) | (IS_XS1_F) | \ + (IS_XA1_B) | (IS_XA1_F) | \ + (IS_XS2_B) | (IS_XS2_F) | \ + (IS_XA2_B) | (IS_XA2_F)) -/* definition of flags in the queue control field */ -#define RX_Q_CTRL_POLL_ON 0x00000080 -#define RX_Q_CTRL_POLL_OFF 0x00000040 -#define RX_Q_CTRL_STOP 0x00000020 -#define RX_Q_CTRL_START 0x00000010 -#define RX_Q_CTRL_CLR_I_PAR 0x00000008 -#define RX_Q_CTRL_CLR_I_EOB 0x00000004 -#define RX_Q_CTRL_CLR_I_EOF 0x00000002 -#define RX_Q_CTRL_CLR_I_ERR 0x00000001 +#define NAPI_DRV_IRQS ((IS_R1_F) | (IS_R2_F) | \ + (IS_XS1_F) | (IS_XA1_F)| \ + (IS_XS2_F) | (IS_XA2_F)) -#define TX_Q_CTRL_POLL_ON 0x00000080 -#define TX_Q_CTRL_POLL_OFF 0x00000040 -#define TX_Q_CTRL_STOP 0x00000020 -#define TX_Q_CTRL_START 0x00000010 -#define TX_Q_CTRL_CLR_I_EOB 0x00000004 -#define TX_Q_CTRL_CLR_I_EOF 0x00000002 -#define TX_Q_CTRL_CLR_I_ERR 0x00000001 +#define Y2_DRIVER_IRQS ((Y2_IS_STAT_BMU) | (Y2_IS_IRQ_SW) | (Y2_IS_POLL_CHK)) +#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \ + (IS_EXT_REG) |(IS_TIMINT) | \ + (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \ + (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \ + (IS_MAC1) |(IS_LNK_SYNC_M1)| \ + (IS_MAC2) |(IS_LNK_SYNC_M2)| \ + (IS_R1_C) |(IS_R2_C) | \ + (IS_XS1_C) |(IS_XA1_C) | \ + (IS_XS2_C) |(IS_XA2_C)) -/* Interrupt bits in the interrupts source register **************************/ -#define IRQ_HW_ERROR 0x80000000 -#define IRQ_RESERVED 0x40000000 -#define IRQ_PKT_TOUT_RX1 0x20000000 -#define IRQ_PKT_TOUT_RX2 0x10000000 -#define IRQ_PKT_TOUT_TX1 0x08000000 -#define IRQ_PKT_TOUT_TX2 0x04000000 -#define IRQ_I2C_READY 0x02000000 -#define IRQ_SW 0x01000000 -#define IRQ_EXTERNAL_REG 0x00800000 -#define IRQ_TIMER 0x00400000 -#define IRQ_MAC1 0x00200000 -#define IRQ_LINK_SYNC_C_M1 0x00100000 -#define IRQ_MAC2 0x00080000 -#define IRQ_LINK_SYNC_C_M2 0x00040000 -#define IRQ_EOB_RX1 0x00020000 -#define IRQ_EOF_RX1 0x00010000 -#define IRQ_CHK_RX1 0x00008000 -#define IRQ_EOB_RX2 0x00004000 -#define IRQ_EOF_RX2 0x00002000 -#define IRQ_CHK_RX2 0x00001000 -#define IRQ_EOB_SY_TX1 0x00000800 -#define IRQ_EOF_SY_TX1 0x00000400 -#define IRQ_CHK_SY_TX1 0x00000200 -#define IRQ_EOB_AS_TX1 0x00000100 -#define IRQ_EOF_AS_TX1 0x00000080 -#define IRQ_CHK_AS_TX1 0x00000040 -#define IRQ_EOB_SY_TX2 0x00000020 -#define IRQ_EOF_SY_TX2 0x00000010 -#define IRQ_CHK_SY_TX2 0x00000008 -#define IRQ_EOB_AS_TX2 0x00000004 -#define IRQ_EOF_AS_TX2 0x00000002 -#define IRQ_CHK_AS_TX2 0x00000001 +#define Y2_SPECIAL_IRQS ((Y2_IS_HW_ERR) |(Y2_IS_ASF) | \ + (Y2_IS_TWSI_RDY) |(Y2_IS_TIMINT) | \ + (Y2_IS_IRQ_PHY2) |(Y2_IS_IRQ_MAC2) | \ + (Y2_IS_CHK_RX2) |(Y2_IS_CHK_TXS2) | \ + (Y2_IS_CHK_TXA2) |(Y2_IS_IRQ_PHY1) | \ + (Y2_IS_IRQ_MAC1) |(Y2_IS_CHK_RX1) | \ + (Y2_IS_CHK_TXS1) |(Y2_IS_CHK_TXA1)) -#define DRIVER_IRQS (IRQ_SW | IRQ_EOF_RX1 | IRQ_EOF_RX2 | \ - IRQ_EOF_SY_TX1 | IRQ_EOF_AS_TX1 | \ - IRQ_EOF_SY_TX2 | IRQ_EOF_AS_TX2) +#define IRQ_MASK ((IS_IRQ_SW) | \ + (IS_R1_F) |(IS_R2_F) | \ + (IS_XS1_F) |(IS_XA1_F) | \ + (IS_XS2_F) |(IS_XA2_F) | \ + (IS_HW_ERR) |(IS_I2C_READY)| \ + (IS_EXT_REG) |(IS_TIMINT) | \ + (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \ + (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \ + (IS_MAC1) |(IS_MAC2) | \ + (IS_R1_C) |(IS_R2_C) | \ + (IS_XS1_C) |(IS_XA1_C) | \ + (IS_XS2_C) |(IS_XA2_C)) -#define SPECIAL_IRQS (IRQ_HW_ERROR | IRQ_PKT_TOUT_RX1 | IRQ_PKT_TOUT_RX2 | \ - IRQ_PKT_TOUT_TX1 | IRQ_PKT_TOUT_TX2 | \ - IRQ_I2C_READY | IRQ_EXTERNAL_REG | IRQ_TIMER | \ - IRQ_MAC1 | IRQ_LINK_SYNC_C_M1 | \ - IRQ_MAC2 | IRQ_LINK_SYNC_C_M2 | \ - IRQ_CHK_RX1 | IRQ_CHK_RX2 | \ - IRQ_CHK_SY_TX1 | IRQ_CHK_AS_TX1 | \ - IRQ_CHK_SY_TX2 | IRQ_CHK_AS_TX2) +#define Y2_IRQ_MASK ((Y2_DRIVER_IRQS) | (Y2_SPECIAL_IRQS)) -#define IRQ_MASK (IRQ_SW | IRQ_EOB_RX1 | IRQ_EOF_RX1 | \ - IRQ_EOB_RX2 | IRQ_EOF_RX2 | \ - IRQ_EOB_SY_TX1 | IRQ_EOF_SY_TX1 | \ - IRQ_EOB_AS_TX1 | IRQ_EOF_AS_TX1 | \ - IRQ_EOB_SY_TX2 | IRQ_EOF_SY_TX2 | \ - IRQ_EOB_AS_TX2 | IRQ_EOF_AS_TX2 | \ - IRQ_HW_ERROR | IRQ_PKT_TOUT_RX1 | IRQ_PKT_TOUT_RX2 | \ - IRQ_PKT_TOUT_TX1 | IRQ_PKT_TOUT_TX2 | \ - IRQ_I2C_READY | IRQ_EXTERNAL_REG | IRQ_TIMER | \ - IRQ_MAC1 | \ - IRQ_MAC2 | \ - IRQ_CHK_RX1 | IRQ_CHK_RX2 | \ - IRQ_CHK_SY_TX1 | IRQ_CHK_AS_TX1 | \ - IRQ_CHK_SY_TX2 | IRQ_CHK_AS_TX2) - -#define IRQ_HWE_MASK 0x00000FFF /* enable all HW irqs */ +#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */ +#define Y2_IRQ_HWE_MASK (Y2_HWE_ALL_MSK) /* enable all HW irqs */ typedef struct s_DevNet DEV_NET; struct s_DevNet { - int PortNr; - int NetNr; - int Mtu; - int Up; - SK_AC *pAC; -}; - -typedef struct s_TxPort TX_PORT; - -struct s_TxPort { - /* the transmit descriptor rings */ - caddr_t pTxDescrRing; /* descriptor area memory */ - SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */ - TXD *pTxdRingHead; /* Head of Tx rings */ - TXD *pTxdRingTail; /* Tail of Tx rings */ - TXD *pTxdRingPrev; /* descriptor sent previously */ - int TxdRingFree; /* # of free entrys */ -#if 0 - spinlock_t TxDesRingLock; /* serialize descriptor accesses */ + struct proc_dir_entry *proc; + int PortNr; + int NetNr; + int Mtu; + int Up; + char InitialDevName[20]; + SK_BOOL NetConsoleMode; +#ifdef Y2_RECOVERY +#if 0 // u-boot + struct timer_list KernelTimer; /* Kernel timer struct */ #endif - caddr_t HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ -}; - -typedef struct s_RxPort RX_PORT; - -struct s_RxPort { - /* the receive descriptor rings */ - caddr_t pRxDescrRing; /* descriptor area memory */ - SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */ - RXD *pRxdRingHead; /* Head of Rx rings */ - RXD *pRxdRingTail; /* Tail of Rx rings */ - RXD *pRxdRingPrev; /* descriptor given to BMU previously */ - int RxdRingFree; /* # of free entrys */ -#if 0 - spinlock_t RxDesRingLock; /* serialize descriptor accesses */ + int TransmitTimeoutTimer; /* Transmit timer */ + SK_BOOL TimerExpired; /* Transmit timer */ + SK_BOOL InRecover; /* Recover flag */ +#ifdef Y2_RX_CHECK + SK_U32 PreviousMACFifoRP; /* Backup of the FRP */ + SK_U32 PreviousMACFifoRLev; /* Backup of the FRL */ + SK_U32 PreviousRXFifoRP; /* Backup of the RX FRP */ + SK_U8 PreviousRXFifoRLev; /* Backup of the RX FRL */ + SK_U32 LastJiffies; /* Backup of the jiffies*/ #endif - int RxFillLimit; /* limit for buffers in ring */ - caddr_t HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ +#endif + SK_AC *pAC; +}; + +/******************************************************************************* + * + * Rx/Tx Port structures + * + ******************************************************************************/ + +typedef struct s_TxPort TX_PORT; +struct s_TxPort { /* the transmit descriptor rings */ + caddr_t pTxDescrRing; /* descriptor area memory */ + SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */ + TXD *pTxdRingHead; /* Head of Tx rings */ + TXD *pTxdRingTail; /* Tail of Tx rings */ + TXD *pTxdRingPrev; /* descriptor sent previously */ + int TxdRingPrevFree;/* previously # of free entrys */ + int TxdRingFree; /* # of free entrys */ +#if 0 /* uboot */ + spinlock_t TxDesRingLock; /* serialize descriptor accesses */ +#endif + caddr_t HwAddr; /* bmu registers address */ + int PortIndex; /* index number of port (0 or 1) */ + SK_PACKET *TransmitPacketTable; + SK_LE_TABLE TxALET; /* tx (async) list element table */ + SK_LE_TABLE TxSLET; /* tx (sync) list element table */ + SK_PKT_QUEUE TxQ_free; + SK_PKT_QUEUE TxAQ_waiting; + SK_PKT_QUEUE TxSQ_waiting; + SK_PKT_QUEUE TxAQ_working; + SK_PKT_QUEUE TxSQ_working; + unsigned LastDone; }; -typedef struct s_PerStrm PER_STRM; +typedef struct s_RxPort RX_PORT; +struct s_RxPort { /* the receive descriptor rings */ + caddr_t pRxDescrRing; /* descriptor area memory */ + SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */ + RXD *pRxdRingHead; /* Head of Rx rings */ + RXD *pRxdRingTail; /* Tail of Rx rings */ + RXD *pRxdRingPrev; /* descr given to BMU previously */ + int RxdRingFree; /* # of free entrys */ +#if 0 /* uboot */ + spinlock_t RxDesRingLock; /* serialize descriptor accesses */ +#endif + int RxFillLimit; /* limit for buffers in ring */ + caddr_t HwAddr; /* bmu registers address */ + int PortIndex; /* index number of port (0 or 1) */ + SK_BOOL UseRxCsum; /* use Rx checksumming (yes/no) */ + SK_PACKET *ReceivePacketTable; + SK_LE_TABLE RxLET; /* rx list element table */ + SK_PKT_QUEUE RxQ_working; + SK_PKT_QUEUE RxQ_waiting; + int RxBufSize; +}; + +/******************************************************************************* + * + * Interrupt masks used in combination with interrupt moderation + * + ******************************************************************************/ + +#define IRQ_EOF_AS_TX ((IS_XA1_F) | (IS_XA2_F)) +#define IRQ_EOF_SY_TX ((IS_XS1_F) | (IS_XS2_F)) +#define IRQ_MASK_TX_ONLY ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX)) +#define IRQ_MASK_RX_ONLY ((IS_R1_F) | (IS_R2_F)) +#define IRQ_MASK_SP_ONLY (SPECIAL_IRQS) +#define IRQ_MASK_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY)) +#define IRQ_MASK_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY)) +#define IRQ_MASK_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY)) +#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX)) + +#define IRQ_MASK_Y2_TX_ONLY (Y2_IS_STAT_BMU) +#define IRQ_MASK_Y2_RX_ONLY (Y2_IS_STAT_BMU) +#define IRQ_MASK_Y2_SP_ONLY (SPECIAL_IRQS) +#define IRQ_MASK_Y2_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY)) +#define IRQ_MASK_Y2_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY)) +#define IRQ_MASK_Y2_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY)) +#define IRQ_MASK_Y2_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX)) + +/******************************************************************************* + * + * Defines and typedefs regarding interrupt moderation + * + ******************************************************************************/ + +#define C_INT_MOD_NONE 1 +#define C_INT_MOD_STATIC 2 +#define C_INT_MOD_DYNAMIC 4 + +#define C_CLK_FREQ_GENESIS 53215000 /* or: 53.125 MHz */ +#define C_CLK_FREQ_YUKON 78215000 /* or: 78.125 MHz */ +#define C_CLK_FREQ_YUKON_EC 125000000 /* or: 125.000 MHz */ + +#define C_Y2_INTS_PER_SEC_DEFAULT 5000 +#define C_INTS_PER_SEC_DEFAULT 2000 +#define C_INT_MOD_IPS_LOWER_RANGE 30 /* in IRQs/second */ +#define C_INT_MOD_IPS_UPPER_RANGE 40000 /* in IRQs/second */ + +typedef struct s_DynIrqModInfo { + SK_U64 PrevPort0RxIntrCts; + SK_U64 PrevPort1RxIntrCts; + SK_U64 PrevPort0TxIntrCts; + SK_U64 PrevPort1TxIntrCts; + SK_U64 PrevPort0StatusLeIntrCts; + SK_U64 PrevPort1StatusLeIntrCts; + int MaxModIntsPerSec; /* Moderation Threshold */ + int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */ + int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */ + long MaskIrqModeration; /* IRQ Mask (eg. 'TxRx') */ + int IntModTypeSelect; /* Type (eg. 'dynamic') */ + int DynIrqModSampleInterval; /* expressed in seconds! */ + SK_TIMER ModTimer; /* Timer for dynamic mod. */ +} DIM_INFO; + +/******************************************************************************* + * + * Defines and typedefs regarding wake-on-lan + * + ******************************************************************************/ + +typedef struct s_WakeOnLanInfo { + SK_U32 SupportedWolOptions; /* e.g. WAKE_PHY... */ + SK_U32 ConfiguredWolOptions; /* e.g. WAKE_PHY... */ +} WOL_INFO; #define SK_ALLOC_IRQ 0x00000001 +#define DIAG_ACTIVE 1 +#define DIAG_NOTACTIVE 0 /**************************************************************************** + * * Per board structure / Adapter Context structure: - * Allocated within attach(9e) and freed within detach(9e). - * Contains all 'per device' necessary handles, flags, locks etc.: - */ + * Contains all 'per device' necessary handles, flags, locks etc.: + * + ******************************************************************************/ + struct s_AC { - SK_GEINIT GIni; /* GE init struct */ - SK_PNMI Pnmi; /* PNMI data struct */ - SK_VPD vpd; /* vpd data struct */ - SK_QUEUE Event; /* Event queue */ - SK_HWT Hwt; /* Hardware Timer control struct */ - SK_TIMCTRL Tim; /* Software Timer control struct */ - SK_I2C I2c; /* I2C relevant data structure */ - SK_ADDR Addr; /* for Address module */ - SK_CSUM Csum; /* for checksum module */ - SK_RLMT Rlmt; /* for rlmt module */ -#if 0 - spinlock_t SlowPathLock; /* Normal IRQ lock */ + SK_GEINIT GIni; /* GE init struct */ + SK_PNMI Pnmi; /* PNMI data struct */ + SK_VPD vpd; /* vpd data struct */ + SK_QUEUE Event; /* Event queue */ + SK_HWT Hwt; /* Hardware Timer ctrl struct */ + SK_TIMCTRL Tim; /* Software Timer ctrl struct */ + SK_I2C I2c; /* I2C relevant data structure*/ + SK_ADDR Addr; /* for Address module */ + SK_CSUM Csum; /* for checksum module */ + SK_RLMT Rlmt; /* for rlmt module */ +#if 0 /* uboot */ + spinlock_t SlowPathLock; /* Normal IRQ lock */ + spinlock_t InitLock; /* Init lock */ + spinlock_t TxQueueLock; /* TX Queue lock */ #endif - SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */ - int RlmtMode; /* link check mode to set */ - int RlmtNets; /* Number of nets */ - - SK_IOC IoBase; /* register set of adapter */ - int BoardLevel; /* level of active hw init (0-2) */ - char DeviceStr[80]; /* adapter string from vpd */ - SK_U32 AllocFlag; /* flag allocation of resources */ -#if 0 - struct pci_dev *PciDev; /* for access to pci config space */ - SK_U32 PciDevId; /* pci device id */ + SK_PNMI_STRUCT_DATA PnmiStruct; /* struct for all Pnmi-Data */ + int RlmtMode; /* link check mode to set */ + int RlmtNets; /* Number of nets */ + SK_IOC IoBase; /* register set of adapter */ + int BoardLevel; /* level of hw init (0-2) */ + char DeviceStr[80]; /* adapter string from vpd */ + SK_U32 AllocFlag; /* alloc flag of resources */ +#if 0 /* uboot */ + struct pci_dev *PciDev; /* for access to pci cfg space*/ + SK_U32 PciDevId; /* pci device id */ #else - int PciDev; + int PciDev; #endif - struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */ - char Name[30]; /* driver name */ - struct SK_NET_DEVICE *Next; /* link all devices (for clearing) */ - int RxBufSize; /* length of receive buffers */ -#if 0 - struct net_device_stats stats; /* linux 'netstat -i' statistics */ + struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */ + char Name[30]; /* driver name */ + struct SK_NET_DEVICE *Next; /* link all devs for cleanup */ + int RxBufSize; /* length of receive buffers */ +#if 0 /* uboot */ + struct net_device_stats stats; /* linux 'netstat -i' stats */ +#endif + int Index; /* internal board idx number */ + int RxQueueSize; /* memory used for RX queue */ + int TxSQueueSize; /* memory used for TXS queue */ + int TxAQueueSize; /* memory used for TXA queue */ + int PromiscCount; /* promiscuous mode counter */ + int AllMultiCount; /* allmulticast mode counter */ + int MulticCount; /* number of MC addresses used*/ + int HWRevision; /* Hardware revision */ + int ActivePort; /* the active XMAC port */ + int MaxPorts; /* number of activated ports */ + int TxDescrPerRing;/* # of descriptors TX ring */ + int RxDescrPerRing;/* # of descriptors RX ring */ + caddr_t pDescrMem; /* Ptr to the descriptor area */ + dma_addr_t pDescrMemDMA; /* PCI DMA address of area */ + SK_U32 PciState[16]; /* PCI state */ + TX_PORT TxPort[SK_MAX_MACS][2]; + RX_PORT RxPort[SK_MAX_MACS]; + SK_LE_TABLE StatusLETable; + unsigned SizeOfAlignedLETables; +#if 0 /* uboot */ + spinlock_t SetPutIndexLock; +#endif + int MaxUnusedRxLeWorking; + unsigned int CsOfs1; /* for checksum calculation */ + unsigned int CsOfs2; /* for checksum calculation */ + SK_U32 CsOfs; /* for checksum calculation */ + SK_BOOL CheckQueue; /* check event queue soon */ + DIM_INFO DynIrqModInfo; /* all data related to IntMod */ + WOL_INFO WolInfo; /* all info regarding WOL */ + int ChipsetType; /* 0=GENESIS; 1=Yukon */ + SK_BOOL LowLatency; /* LowLatency optimization on?*/ + SK_U32 DiagModeActive;/* is diag active? */ + SK_BOOL DiagFlowCtrl; /* for control purposes */ + SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for PNMI */ + SK_BOOL WasIfUp[SK_MAX_MACS]; +#ifdef USE_TIST_FOR_RESET + int AdapterResetState; + SK_U32 MinTistLo; + SK_U32 MinTistHi; +#endif +#ifdef Y2_RECOVERY + int LastPort; /* port for curr. handled rx */ + int LastOpc; /* last rx LEs opcode */ +#endif +#ifdef Y2_SYNC_CHECK + unsigned long FramesWithoutSyncCheck; /* since last check */ #endif - int Index; /* internal board index number */ - - /* adapter RAM sizes for queues of active port */ - int RxQueueSize; /* memory used for receive queue */ - int TxSQueueSize; /* memory used for sync. tx queue */ - int TxAQueueSize; /* memory used for async. tx queue */ - - int PromiscCount; /* promiscuous mode counter */ - int AllMultiCount; /* allmulticast mode counter */ - int MulticCount; /* number of different MC */ - /* addresses for this board */ - /* (may be more than HW can)*/ - - int HWRevision; /* Hardware revision */ - int ActivePort; /* the active XMAC port */ - int MaxPorts; /* number of activated ports */ - int TxDescrPerRing; /* # of descriptors per tx ring */ - int RxDescrPerRing; /* # of descriptors per rx ring */ - - caddr_t pDescrMem; /* Pointer to the descriptor area */ - dma_addr_t pDescrMemDMA; /* PCI DMA address of area */ - - /* the port structures with descriptor rings */ - TX_PORT TxPort[SK_MAX_MACS][2]; - RX_PORT RxPort[SK_MAX_MACS]; - - unsigned int CsOfs1; /* for checksum calculation */ - unsigned int CsOfs2; /* for checksum calculation */ - SK_U32 CsOfs; /* for checksum calculation */ - - SK_BOOL CheckQueue; /* check event queue soon */ - - /* Only for tests */ - int PortUp; - int PortDown; - }; -#endif /* __INC_SKDRV2ND_H */ + + +#endif + +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ diff --git a/drivers/sk98lin/h/skerror.h b/drivers/sk98lin/h/skerror.h index a454d9d..54d2950 100644 --- a/drivers/sk98lin/h/skerror.h +++ b/drivers/sk98lin/h/skerror.h @@ -1,49 +1,25 @@ /****************************************************************************** * * Name: skerror.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 2002/04/25 11:05:10 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: SK specific Error log support * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2004 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skerror.h,v $ - * Revision 1.5 2002/04/25 11:05:10 rschmidt - * Editorial changes - * - * Revision 1.4 1999/11/22 13:51:59 cgoos - * Changed license header to GPL. - * - * Revision 1.3 1999/09/14 14:04:42 rwahl - * Added error base SK_ERRBASE_PECP. - * Changed error base for driver. - * - * Revision 1.2 1998/08/11 11:15:41 gklug - * chg: comments - * - * Revision 1.1 1998/08/11 11:09:38 gklug - * add: error bases - * add: error Classes - * first version - * - * + * /LICENSE * ******************************************************************************/ @@ -61,7 +37,6 @@ #define SK_ERRCL_HW (1L<<4) /* Hardware Failure */ #define SK_ERRCL_COMM (1L<<5) /* Communication error */ - /* * Define Error Code Bases */ @@ -74,7 +49,9 @@ #define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */ #define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */ #define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */ -#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */ +#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */ #define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */ +#define SK_ERRBASE_ASF 1200 /* Base Error number for ASF */ #endif /* _INC_SKERROR_H_ */ + diff --git a/drivers/sk98lin/h/skgedrv.h b/drivers/sk98lin/h/skgedrv.h index 72ba9ce..968f080 100644 --- a/drivers/sk98lin/h/skgedrv.h +++ b/drivers/sk98lin/h/skgedrv.h @@ -1,50 +1,25 @@ /****************************************************************************** * * Name: skgedrv.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.6 $ - * Date: $Date: 2002/07/15 15:38:01 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Interface with the driver * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2006 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgedrv.h,v $ - * Revision 1.6 2002/07/15 15:38:01 rschmidt - * Power Management support - * Editorial changes - * - * Revision 1.5 2002/04/25 11:05:47 rschmidt - * Editorial changes - * - * Revision 1.4 1999/11/22 13:52:46 cgoos - * Changed license header to GPL. - * - * Revision 1.3 1998/12/01 13:31:39 cgoos - * SWITCH INTERN Event added. - * - * Revision 1.2 1998/11/25 08:28:38 gklug - * rmv: PORT SWITCH Event - * - * Revision 1.1 1998/09/29 06:14:07 gklug - * add: driver events (initial version) - * + * /LICENSE * ******************************************************************************/ @@ -59,7 +34,7 @@ * In case of the driver we put the definition of the events here. */ #define SK_DRV_PORT_RESET 1 /* The port needs to be reset */ -#define SK_DRV_NET_UP 2 /* The net is operational */ +#define SK_DRV_NET_UP 2 /* The net is operational */ #define SK_DRV_NET_DOWN 3 /* The net is down */ #define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */ #define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */ @@ -68,5 +43,13 @@ #define SK_DRV_PORT_FAIL 8 /* One port fails */ #define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */ #define SK_DRV_POWER_DOWN 10 /* Power down mode */ - -#endif /* __INC_SKGEDRV_H_ */ +#define SK_DRV_TIMER 11 /* Timer for free use */ +#ifdef SK_NO_RLMT +#define SK_DRV_LINK_UP 12 /* Link Up event for driver */ +#define SK_DRV_LINK_DOWN 13 /* Link Down event for driver */ +#endif +#define SK_DRV_DOWNSHIFT_DET 14 /* Downshift 4-Pair / 2-Pair (YUKON only) */ +#define SK_DRV_RX_OVERFLOW 15 /* Receive Overflow */ +#define SK_DRV_LIPA_NOT_AN_ABLE 16 /* Link Partner not Auto-Negotiation able */ +#define SK_DRV_PEX_LINK_WIDTH 17 /* PEX negotiated Link width not maximum */ +#endif /* __INC_SKGEDRV_H_ */ diff --git a/drivers/sk98lin/h/skgehw.h b/drivers/sk98lin/h/skgehw.h index 2c98427..ff19c91 100644 --- a/drivers/sk98lin/h/skgehw.h +++ b/drivers/sk98lin/h/skgehw.h @@ -1,226 +1,25 @@ /****************************************************************************** * * Name: skgehw.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.49 $ - * Date: $Date: 2003/01/28 09:43:49 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2006 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skgehw.h,v $ - * Revision 1.49 2003/01/28 09:43:49 rschmidt - * Added defines for PCI-Spec. 2.3 IRQ - * Added defines for CLK_RUN (YUKON-Lite) - * Editorial changes - * - * Revision 1.48 2002/12/05 10:25:11 rschmidt - * Added defines for Half Duplex Burst Mode On/Off - * Added defines for Rx GMAC FIFO Flush feature - * Editorial changes - * - * Revision 1.47 2002/11/12 17:01:31 rschmidt - * Added defines for WOL_CTL_DEFAULT - * Editorial changes - * - * Revision 1.46 2002/10/14 14:47:57 rschmidt - * Corrected bit mask for HW self test results - * Added defines for WOL Registers - * Editorial changes - * - * Revision 1.45 2002/10/11 09:25:22 mkarl - * Added bit mask for HW self test results. - * - * Revision 1.44 2002/08/16 14:44:36 rschmidt - * Added define GPC_HWCFG_GMII_FIB for YUKON Fiber - * - * Revision 1.43 2002/08/12 13:31:50 rschmidt - * Corrected macros for GMAC Address Registers: GM_INADDR(), - * GM_OUTADDR(), GM_INHASH, GM_OUTHASH. - * Editorial changes - * - * Revision 1.42 2002/08/08 15:37:56 rschmidt - * Added defines for Power Management Capabilities - * Editorial changes - * - * Revision 1.41 2002/07/23 16:02:25 rschmidt - * Added macro WOL_REG() to access WOL reg. (HW-Bug in YUKON 1st rev.) - * - * Revision 1.40 2002/07/15 15:41:37 rschmidt - * Added new defines for Power Management Cap. & Control - * Editorial changes - * - * Revision 1.39 2002/06/10 09:37:07 rschmidt - * Added macros for the ADDR-Modul - * - * Revision 1.38 2002/06/05 08:15:19 rschmidt - * Added defines for WOL Registers - * Editorial changes - * - * Revision 1.37 2002/04/25 11:39:23 rschmidt - * Added new defines for PCI Our Register 1 - * Added new registers and defines for YUKON (Rx FIFO, Tx FIFO, - * Time Stamp Timer, GMAC Control, GPHY Control,Link Control, - * GMAC IRQ Source and Mask, Wake-up Frame Pattern Match); - * Added new defines for Control/Status (VAUX available) - * Added Chip ID for YUKON - * Added define for descriptors with UDP ext. for YUKON - * Added macros to access the GMAC - * Added new Phy Type for Marvell 88E1011S (GPHY) - * Editorial changes - * - * Revision 1.36 2000/11/09 12:32:49 rassmann - * Renamed variables. - * - * Revision 1.35 2000/05/19 10:17:13 cgoos - * Added inactivity check in PHY_READ (in DEBUG mode only). - * - * Revision 1.34 1999/11/22 13:53:40 cgoos - * Changed license header to GPL. - * - * Revision 1.33 1999/08/27 11:17:10 malthoff - * It's more savely to put brackets around macro parameters. - * Brackets added for PHY_READ and PHY_WRITE. - * - * Revision 1.32 1999/05/19 07:31:01 cgoos - * Changes for 1000Base-T. - * Added HWAC_LINK_LED macro. - * - * Revision 1.31 1999/03/12 13:27:40 malthoff - * Remove __STDC__. - * - * Revision 1.30 1999/02/09 09:28:20 malthoff - * Add PCI_ERRBITS. - * - * Revision 1.29 1999/01/26 08:55:48 malthoff - * Bugfix: The 16 bit field relations inside the descriptor are - * endianess dependend if the descriptor reversal feature - * (PCI_REV_DESC bit in PCI_OUR_REG_2) is enabled. - * Drivers which use this feature has to set the define - * SK_USE_REV_DESC. - * - * Revision 1.28 1998/12/10 11:10:22 malthoff - * bug fix: IS_IRQ_STAT and IS_IRQ_MST_ERR has been twisted. - * - * Revision 1.27 1998/11/13 14:19:21 malthoff - * Bug Fix: The bit definition of B3_PA_CTRL has completely - * changed from HW Spec v1.3 to v1.5. - * - * Revision 1.26 1998/11/04 08:31:48 cgoos - * Fixed byte ordering in XM_OUTADDR/XM_OUTHASH macros. - * - * Revision 1.25 1998/11/04 07:16:25 cgoos - * Changed byte ordering in XM_INADDR/XM_INHASH again. - * - * Revision 1.24 1998/11/02 11:08:43 malthoff - * RxCtrl and TxCtrl must be volatile. - * - * Revision 1.23 1998/10/28 13:50:45 malthoff - * Fix: Endian support missing in XM_IN/OUT-ADDR/HASH macros. - * - * Revision 1.22 1998/10/26 08:01:36 malthoff - * RX_MFF_CTRL1 is split up into RX_MFF_CTRL1, - * RX_MFF_STAT_TO, and RX_MFF_TIST_TO. - * TX_MFF_CTRL1 is split up TX_MFF_CTRL1 and TX_MFF_WAF. - * - * Revision 1.21 1998/10/20 07:43:10 malthoff - * Fix: XM_IN/OUT/ADDR/HASH macros: - * The pointer must be casted. - * - * Revision 1.20 1998/10/19 15:53:59 malthoff - * Remove ML proto definitions. - * - * Revision 1.19 1998/10/16 14:40:17 gklug - * fix: typo B0_XM_IMSK regs - * - * Revision 1.18 1998/10/16 09:46:54 malthoff - * Remove temp defines for ML diag prototype. - * Fix register definition for B0_XM1_PHY_DATA, B0_XM1_PHY_DATA - * B0_XM2_PHY_DATA, B0_XM2_PHY_ADDR, B0_XA1_CSR, B0_XS1_CSR, - * B0_XS2_CSR, and B0_XA2_CSR. - * - * Revision 1.17 1998/10/14 06:03:14 cgoos - * Changed shifted constant to ULONG. - * - * Revision 1.16 1998/10/09 07:05:41 malthoff - * Rename ALL_PA_ENA_TO to PA_ENA_TO_ALL. - * - * Revision 1.15 1998/10/05 07:54:23 malthoff - * Split up RB_CTRL and it's bit definition into - * RB_CTRL, RB_TST1, and RB_TST2. - * Rename RB_RX_HTPP to RB_RX_LTPP. - * Add ALL_PA_ENA_TO. Modify F_WATER_MARK - * according to HW Spec. v1.5. - * Add MFF_TX_CTRL_DEF. - * - * Revision 1.14 1998/09/28 13:31:16 malthoff - * bug fix: B2_MAC_3 is 0x110 not 0x114 - * - * Revision 1.13 1998/09/24 14:42:56 malthoff - * Split the RX_MFF_TST into RX_MFF_CTRL2, - * RX_MFF_TST1, and RX_MFF_TST2. - * Rename RX_MFF_CTRL to RX_MFF_CTRL1. - * Add BMU bit CSR_SV_IDLE. - * Add macros PHY_READ() and PHY_WRITE(). - * Rename macro SK_ADDR() to SK_HW_ADDR() - * because of conflicts with the Address Module. - * - * Revision 1.12 1998/09/16 07:25:33 malthoff - * Change the parameter order in the XM_INxx and XM_OUTxx macros, - * to have the IoC as first parameter. - * - * Revision 1.11 1998/09/03 09:58:41 malthoff - * Rework the XM_xxx macros. Use {} instead of () to - * be compatible with SK_xxx macros which are defined - * with {}. - * - * Revision 1.10 1998/09/02 11:16:39 malthoff - * Temporary modify B2_I2C_SW to make tests with - * the GE/ML prototype. - * - * Revision 1.9 1998/08/19 09:11:49 gklug - * fix: struct are removed from c-source (see CCC) - * add: typedefs for all structs - * - * Revision 1.8 1998/08/18 08:27:27 malthoff - * Add some temporary workarounds to test GE - * sources with the ML. - * - * Revision 1.7 1998/07/03 14:42:26 malthoff - * bug fix: Correct macro XMA(). - * Add temporary workaround to access the PCI config space over I/O - * - * Revision 1.6 1998/06/23 11:30:36 malthoff - * Remove ';' with ',' in macors. - * - * Revision 1.5 1998/06/22 14:20:57 malthoff - * Add macro SK_ADDR(Base,Addr). - * - * Revision 1.4 1998/06/19 13:35:43 malthoff - * change 'pGec' with 'pAC' - * - * Revision 1.3 1998/06/17 14:58:16 cvs - * Lost keywords reinserted. - * - * Revision 1.1 1998/06/17 14:16:36 cvs - * created - * + * /LICENSE * ******************************************************************************/ @@ -316,6 +115,16 @@ extern "C" { #define SHIFT1(x) ((x) << 1) #define SHIFT0(x) ((x) << 0) +/* Macro for arbitrary alignment of a given pointer */ +#define ALIGN_ADDR( ADDRESS, GRANULARITY ) { \ + SK_UPTR addr = (SK_UPTR)(ADDRESS); \ + if (addr & ((GRANULARITY)-1)) { \ + addr += (GRANULARITY); \ + addr &= ~(SK_UPTR)((GRANULARITY)-1); \ + ADDRESS = (void *)addr; \ + }\ +} + /* * Configuration Space header * Since this module is used for different OS', those may be @@ -327,7 +136,7 @@ extern "C" { #define PCI_COMMAND 0x04 /* 16 bit Command */ #define PCI_STATUS 0x06 /* 16 bit Status */ #define PCI_REV_ID 0x08 /* 8 bit Revision ID */ -#if 0 +#if 0 /* uboot */ #define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */ #endif #define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */ @@ -336,32 +145,81 @@ extern "C" { #define PCI_BIST 0x0f /* 8 bit Built-in selftest */ #define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */ #define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */ - /* Byte 0x18..0x2b: reserved */ + /* Bytes 0x18..0x2b: reserved */ #define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */ #define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */ #define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */ -#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */ - /* Byte 35..3b: reserved */ +#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Pointer */ + /* Bytes 0x35..0x3b: reserved */ #define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */ #define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */ #define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */ #define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */ /* Device Dependent Region */ -#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */ -#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */ +#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */ +#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */ /* Power Management Region */ -#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */ -#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */ -#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */ -#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */ +#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */ +#define PCI_PM_NITEM 0x49 /* 8 bit PM Next Item Pointer */ +#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */ +#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */ /* Byte 0x4e: reserved */ -#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */ +#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */ /* VPD Region */ -#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */ -#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */ -#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */ -#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */ - /* Byte 0x58..0xff: reserved */ +#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */ +#define PCI_VPD_NITEM 0x51 /* 8 bit VPD Next Item Pointer */ +#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */ +#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */ + /* Bytes 0x58..0x59: reserved */ +#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */ + /* Bytes 0x5c..0xfc: used by Yukon-2 */ +#define PCI_MSI_CAP_ID 0x5c /* 8 bit MSI Capability ID Register */ +#define PCI_MSI_NITEM 0x5d /* 8 bit MSI Next Item Pointer */ +#define PCI_MSI_CTRL 0x5e /* 16 bit MSI Message Control */ +#define PCI_MSI_ADR_LO 0x60 /* 32 bit MSI Message Address (Lower) */ +#define PCI_MSI_ADR_HI 0x64 /* 32 bit MSI Message Address (Upper) */ +#define PCI_MSI_DATA 0x68 /* 16 bit MSI Message Data */ + /* Bytes 0x6a..0x6b: reserved */ +#define PCI_X_CAP_ID 0x6c /* 8 bit PCI-X Capability ID Register */ +#define PCI_X_NITEM 0x6d /* 8 bit PCI-X Next Item Pointer */ +#define PCI_X_COMMAND 0x6e /* 16 bit PCI-X Command */ +#define PCI_X_PE_STAT 0x70 /* 32 bit PCI-X / PE Status */ +#define PCI_CAL_CTRL 0x74 /* 16 bit PCI Calibration Control Register */ +#define PCI_CAL_STAT 0x76 /* 16 bit PCI Calibration Status Register */ +#define PCI_DISC_CNT 0x78 /* 16 bit PCI Discard Counter */ +#define PCI_RETRY_CNT 0x7a /* 8 bit PCI Retry Counter */ + /* Byte 0x7b: reserved */ +#define PCI_OUR_STATUS 0x7c /* 32 bit Adapter Status Register */ +#define PCI_OUR_REG_3 0x80 /* 32 bit Our Register 3 (Yukon-ECU only) */ +#define PCI_OUR_REG_4 0x84 /* 32 bit Our Register 4 (Yukon-ECU only) */ +#define PCI_OUR_REG_5 0x88 /* 32 bit Our Register 5 (Yukon-ECU only) */ + /* Bytes 0x8c..0xdf: reserved */ + +/* PCI Express Capability */ +#define PEX_CAP_ID 0xe0 /* 8 bit PEX Capability ID */ +#define PEX_NITEM 0xe1 /* 8 bit PEX Next Item Pointer */ +#define PEX_CAP_REG 0xe2 /* 16 bit PEX Capability Register */ +#define PEX_DEV_CAP 0xe4 /* 32 bit PEX Device Capabilities */ +#define PEX_DEV_CTRL 0xe8 /* 16 bit PEX Device Control */ +#define PEX_DEV_STAT 0xea /* 16 bit PEX Device Status */ +#define PEX_LNK_CAP 0xec /* 32 bit PEX Link Capabilities */ +#define PEX_LNK_CTRL 0xf0 /* 16 bit PEX Link Control */ +#define PEX_LNK_STAT 0xf2 /* 16 bit PEX Link Status */ + /* Bytes 0xf4..0xff: reserved */ + +/* PCI Express Extended Capabilities */ +#define PEX_ADV_ERR_REP 0x100 /* 32 bit PEX Advanced Error Reporting */ +#define PEX_UNC_ERR_STAT 0x104 /* 32 bit PEX Uncorr. Errors Status */ +#define PEX_UNC_ERR_MASK 0x108 /* 32 bit PEX Uncorr. Errors Mask */ +#define PEX_UNC_ERR_SEV 0x10c /* 32 bit PEX Uncorr. Errors Severity */ +#define PEX_COR_ERR_STAT 0x110 /* 32 bit PEX Correc. Errors Status */ +#define PEX_COR_ERR_MASK 0x114 /* 32 bit PEX Correc. Errors Mask */ +#define PEX_ADV_ERR_CAP_C 0x118 /* 32 bit PEX Advanced Error Cap./Ctrl */ +#define PEX_HEADER_LOG 0x11c /* 4x32 bit PEX Header Log Register */ + +/* PCI Express Ack Timer for 1x Link */ +#define PEX_ACK_LAT_TOX1 0x228 /* 16 bit PEX Ack Latency Timeout x1 */ +#define PEX_ACK_RPLY_TOX1 0x22a /* 16 bit PEX Ack Reply Timeout val x1 */ /* * I2C Address (PCI Config) @@ -369,7 +227,7 @@ extern "C" { * Note: The temperature and voltage sensors are relocated on a different * I2C bus. */ -#define I2C_ADDR_VPD 0xA0 /* I2C address for the VPD EEPROM */ +#define I2C_ADDR_VPD 0xa0 /* I2C address for the VPD EEPROM */ /* * Define Bits and Values of the registers @@ -382,13 +240,13 @@ extern "C" { #define PCI_ADSTEP BIT_7S /* Address Stepping */ #define PCI_PERREN BIT_6S /* Parity Report Response enable */ #define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */ -#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */ +#define PCI_MWIEN BIT_4S /* Memory write an inv cycl enable */ #define PCI_SCYCEN BIT_3S /* Special Cycle enable */ #define PCI_BMEN BIT_2S /* Bus Master enable */ #define PCI_MEMEN BIT_1S /* Memory Space Access enable */ #define PCI_IOEN BIT_0S /* I/O Space Access enable */ -#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\ +#define PCI_COMMAND_VAL (PCI_INT_DIS | PCI_SERREN | PCI_PERREN | \ PCI_BMEN | PCI_MEMEN | PCI_IOEN) /* PCI_STATUS 16 bit Status */ @@ -422,7 +280,7 @@ extern "C" { /* PCI_HEADER_T 8 bit Header Type */ #define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */ -#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */ +#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout (0=normal) */ /* PCI_BIST 8 bit Built-in selftest */ /* Built-in Self test not supported (optional) */ @@ -431,33 +289,42 @@ extern "C" { #define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */ #define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */ #define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */ -#define PCI_PREFEN BIT_3 /* Prefetchable */ -#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */ +#define PCI_PREFEN BIT_3 /* Prefetch enable */ +#define PCI_MEM_TYP_MSK (3L<<1) /* Bit 2.. 1: Memory Type Mask */ +#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */ + #define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */ #define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */ #define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */ -#define PCI_MEMSPACE BIT_0 /* Memory Space Indic. */ /* PCI_BASE_2ND 32 bit 2nd Base address */ #define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */ #define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */ - /* Bit 1: reserved */ + /* Bit 1: reserved */ #define PCI_IOSPACE BIT_0 /* I/O Space Indicator */ /* PCI_BASE_ROM 32 bit Expansion ROM Base Address */ -#define PCI_ROMBASE 0xfffe0000L /* Bit 31..17: ROM BASE address (1st)*/ -#define PCI_ROMBASZ (0x1cL<<14) /* Bit 16..14: Treat as BASE or SIZE */ +#define PCI_ROMBASE_MSK 0xfffe0000L /* Bit 31..17: ROM Base address */ +#define PCI_ROMBASE_SIZ (0x1cL<<14) /* Bit 16..14: Treat as Base or Size */ #define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */ - /* Bit 10.. 1: reserved */ + /* Bit 10.. 1: reserved */ #define PCI_ROMEN BIT_0 /* Address Decode enable */ /* Device Dependent Region */ /* PCI_OUR_REG_1 32 bit Our Register 1 */ - /* Bit 31..29: reserved */ -#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode */ -#define PCI_EN_CAL BIT_27 /* Enable PCI buffer strength calibr. */ -#define PCI_DIS_CAL BIT_26 /* Disable PCI buffer strength calibr. */ + /* Bit 31..29: reserved */ +#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode (YUKON only) */ +#define PCI_TEST_CAL BIT_27 /* Test PCI buffer calib. (YUKON only) */ +#define PCI_EN_CAL BIT_26 /* Enable PCI buffer calib. (YUKON only) */ #define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */ +/* Yukon-2 */ +#define PCI_Y2_PIG_ENA BIT_31 /* Enable Plug-in-Go (YUKON-2) */ +#define PCI_Y2_DLL_DIS BIT_30 /* Disable PCI DLL (YUKON-2) */ +#define PCI_Y2_PHY2_COMA BIT_29 /* Set PHY 2 to Coma Mode (YUKON-2) */ +#define PCI_Y2_PHY1_COMA BIT_28 /* Set PHY 1 to Coma Mode (YUKON-2) */ +#define PCI_Y2_PHY2_POWD BIT_27 /* Set PHY 2 to Power Down (YUKON-2) */ +#define PCI_Y2_PHY1_POWD BIT_26 /* Set PHY 1 to Power Down (YUKON-2) */ + /* Bit 25: reserved */ #define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */ #define PCI_EN_IO BIT_23 /* Mapping to I/O space */ #define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */ @@ -468,9 +335,10 @@ extern "C" { #define PCI_PAGE_32K (1L<<20) /* 32 k pages */ #define PCI_PAGE_64K (2L<<20) /* 64 k pages */ #define PCI_PAGE_128K (3L<<20) /* 128 k pages */ - /* Bit 19: reserved */ -#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */ + /* Bit 19: reserved */ +#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */ #define PCI_NOTAR BIT_15 /* No turnaround cycle */ +#define PCI_PEX_LEGNAT BIT_15 /* PEX PM legacy/native mode (YUKON-2) */ #define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */ #define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */ #define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */ @@ -480,13 +348,21 @@ extern "C" { #define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */ #define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */ #define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */ +#define PCI_CLS_OPT BIT_3 /* Cache Line Size opt. PCI-X (YUKON-2) */ +/* Yukon-EC Ultra only */ + /* Bit 14..10: reserved */ +#define PCI_PHY_LNK_TIM_MSK (3L<<8) /* Bit 9.. 8: GPHY Link Trigger Timer */ +#define PCI_ENA_L1_EVENT BIT_7 /* Enable PEX L1 Event */ +#define PCI_ENA_GPHY_LNK BIT_6 /* Enable PEX L1 on GPHY Link down */ +#define PCI_FORCE_PEX_L1 BIT_5 /* Force to PEX L1 */ + /* Bit 4.. 0: reserved */ /* PCI_OUR_REG_2 32 bit Our Register 2 */ #define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */ #define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */ #define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */ - /* Bit 13..12: reserved */ + /* Bit 13..12: reserved */ #define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */ #define PCI_PATCH_DIR_3 BIT_11 #define PCI_PATCH_DIR_2 BIT_10 @@ -498,22 +374,21 @@ extern "C" { #define PCI_EXT_PATCH_1 BIT_5 #define PCI_EXT_PATCH_0 BIT_4 #define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */ -#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */ - /* Bit 1: reserved */ +#define PCI_REV_DESC BIT_2 /* Reverse Descriptor Bytes */ + /* Bit 1: reserved */ #define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */ - -/* Power Management Region */ +/* Power Management (PM) Region */ /* PCI_PM_CAP_REG 16 bit Power Management Capabilities */ -#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */ -#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */ +#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event (PME) Supp. Mask */ +#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if VAUX) */ #define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */ #define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */ #define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */ #define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */ #define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */ #define PCI_PM_D1_SUP BIT_9S /* D1 Support */ - /* Bit 8.. 6: reserved */ + /* Bit 8.. 6: reserved */ #define PCI_PM_DSI BIT_5S /* Device Specific Initialization */ #define PCI_PM_APS BIT_4S /* Auxialiary Power Source */ #define PCI_PME_CLOCK BIT_3S /* PM Event Clock */ @@ -524,7 +399,7 @@ extern "C" { #define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */ #define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */ #define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */ - /* Bit 7.. 2: reserved */ + /* Bit 7.. 2: reserved */ #define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */ #define PCI_PM_STATE_D0 0 /* D0: Operational (default) */ @@ -535,7 +410,151 @@ extern "C" { /* VPD Region */ /* PCI_VPD_ADR_REG 16 bit VPD Address Register */ #define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */ -#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */ +#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD Address Mask */ + +/* PCI_OUR_STATUS 32 bit Adapter Status Register (Yukon-2) */ +#define PCI_OS_PCI64B BIT_31 /* Conventional PCI 64 bits Bus */ +#define PCI_OS_PCIX BIT_30 /* PCI-X Bus */ +#define PCI_OS_MODE_MSK (3L<<28) /* Bit 29..28: PCI-X Bus Mode Mask */ +#define PCI_OS_PCI66M BIT_27 /* PCI 66 MHz Bus */ +#define PCI_OS_PCI_X BIT_26 /* PCI/PCI-X Bus (0 = PEX) */ +#define PCI_OS_DLLE_MSK (3L<<24) /* Bit 25..24: DLL Status Indication */ +#define PCI_OS_DLLR_MSK (0xfL<<20) /* Bit 23..20: DLL Row Counters Values */ +#define PCI_OS_DLLC_MSK (0xfL<<16) /* Bit 19..16: DLL Col. Counters Values */ + /* Bit 15.. 8: reserved */ + +#define PCI_OS_SPEED(val) ((val & PCI_OS_MODE_MSK) >> 28) /* PCI-X Speed */ +/* possible values for the speed field of the register */ +#define PCI_OS_SPD_PCI 0 /* PCI Conventional Bus */ +#define PCI_OS_SPD_X66 1 /* PCI-X 66MHz Bus */ +#define PCI_OS_SPD_X100 2 /* PCI-X 100MHz Bus */ +#define PCI_OS_SPD_X133 3 /* PCI-X 133MHz Bus */ + +/* PCI_OUR_REG_3 32 bit Our Register 3 (Yukon-ECU only) */ + /* Bit 31..18: reserved */ +#define P_CLK_COR_REGS_D0_DIS BIT_17 /* Disable Clock Core Regs in D0 */ +#define P_CLK_PCI_REGS_D0_DIS BIT_16 /* Disable Clock PCI Regs in D0 */ +#define P_CLK_COR_YTB_ARB_DIS BIT_15 /* Disable Clock YTB Arbiter */ +#define P_CLK_MAC_LNK1_D3_DIS BIT_14 /* Disable Clock MAC Link1 in D3 */ +#define P_CLK_COR_LNK1_D0_DIS BIT_13 /* Disable Clock Core Link1 in D0 */ +#define P_CLK_MAC_LNK1_D0_DIS BIT_12 /* Disable Clock MAC Link1 in D0 */ +#define P_CLK_COR_LNK1_D3_DIS BIT_11 /* Disable Clock Core Link1 in D3 */ +#define P_CLK_PCI_MST_ARB_DIS BIT_10 /* Disable Clock PCI Master Arb. */ +#define P_CLK_COR_REGS_D3_DIS BIT_9 /* Disable Clock Core Regs in D3 */ +#define P_CLK_PCI_REGS_D3_DIS BIT_8 /* Disable Clock PCI Regs in D3 */ +#define P_CLK_REF_LNK1_GM_DIS BIT_7 /* Disable Clock Ref. Link1 GMAC */ +#define P_CLK_COR_LNK1_GM_DIS BIT_6 /* Disable Clock Core Link1 GMAC */ +#define P_CLK_PCI_COMMON_DIS BIT_5 /* Disable Clock PCI Common */ +#define P_CLK_COR_COMMON_DIS BIT_4 /* Disable Clock Core Common */ +#define P_CLK_PCI_LNK1_BMU_DIS BIT_3 /* Disable Clock PCI Link1 BMU */ +#define P_CLK_COR_LNK1_BMU_DIS BIT_2 /* Disable Clock Core Link1 BMU */ +#define P_CLK_PCI_LNK1_BIU_DIS BIT_1 /* Disable Clock PCI Link1 BIU */ +#define P_CLK_COR_LNK1_BIU_DIS BIT_0 /* Disable Clock Core Link1 BIU */ + +/* PCI_OUR_REG_4 32 bit Our Register 4 (Yukon-ECU only) */ +#define P_PEX_LTSSM_STAT_MSK (0x7fL<<25) /* Bit 31..25: PEX LTSSM Mask */ + /* (Link Training & Status State Machine) */ + /* Bit 24: reserved */ +#define P_TIMER_VALUE_MSK (0xffL<<16) /* Bit 23..16: Timer Value Mask */ +#define P_FORCE_ASPM_REQUEST BIT_15 /* Force ASPM Request (A1 only) */ + /* (Active State Power Management) */ + /* Bit 14..12: Force ASPM on Event */ +#define P_ASPM_GPHY_LINK_DOWN BIT_14 /* GPHY Link Down (A1 only) */ +#define P_ASPM_INT_FIFO_EMPTY BIT_13 /* Internal FIFO Empty (A1 only) */ +#define P_ASPM_CLKRUN_REQUEST BIT_12 /* CLKRUN Request (A1 only) */ + /* Bit 11.. 8: reserved */ +#define P_ASPM_FORCE_ASPM_L1 BIT_7 /* Force ASPM L1 Enable (A1b only) */ +#define P_ASPM_FORCE_ASPM_L0S BIT_6 /* Force ASPM L0s Enable (A1b only) */ +#define P_ASPM_FORCE_CLKREQ_PIN BIT_5 /* Force CLKREQn pin low (A1b only) */ +#define P_ASPM_FORCE_CLKREQ_ENA BIT_4 /* Force CLKREQ Enable (A1b only) */ +#define P_ASPM_CLKREQ_PAD_CTL BIT_3 /* CLKREQ PAD Control (A1 only) */ +#define P_ASPM_A1_MODE_SELECT BIT_2 /* A1 Mode Select (A1 only) */ +#define P_CLK_GATE_PEX_UNIT_ENA BIT_1 /* Enable Gate PEX Unit Clock */ +#define P_CLK_GATE_ROOT_COR_ENA BIT_0 /* Enable Gate Root Core Clock */ + +#define P_PEX_LTSSM_STAT(x) (SHIFT25(x) & P_PEX_LTSSM_STAT_MSK) +#define P_PEX_LTSSM_L1_STAT 0x34 +#define P_PEX_LTSSM_DET_STAT 0x01 + +#define P_ASPM_CONTROL_MSK (P_FORCE_ASPM_REQUEST | P_ASPM_GPHY_LINK_DOWN | \ + P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY) + +/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */ + /* Bit 31..27: reserved */ + /* Bit 26..16: Release Clock on Event */ +#define P_REL_PCIE_RST_DE_ASS BIT_26 /* PCIe Reset De-Asserted */ +#define P_REL_GPHY_REC_PACKET BIT_25 /* GPHY Received Packet */ +#define P_REL_INT_FIFO_N_EMPTY BIT_24 /* Internal FIFO Not Empty */ +#define P_REL_MAIN_PWR_AVAIL BIT_23 /* Main Power Available */ +#define P_REL_CLKRUN_REQ_REL BIT_22 /* CLKRUN Request Release */ +#define P_REL_PCIE_RESET_ASS BIT_21 /* PCIe Reset Asserted */ +#define P_REL_PME_ASSERTED BIT_20 /* PME Asserted */ +#define P_REL_PCIE_EXIT_L1_ST BIT_19 /* PCIe Exit L1 State */ +#define P_REL_LOADER_NOT_FIN BIT_18 /* EPROM Loader Not Finished */ +#define P_REL_PCIE_RX_EX_IDLE BIT_17 /* PCIe Rx Exit Electrical Idle State */ +#define P_REL_GPHY_LINK_UP BIT_16 /* GPHY Link Up */ + /* Bit 15..11: reserved */ + /* Bit 10.. 0: Mask for Gate Clock */ +#define P_GAT_PCIE_RST_DE_ASS BIT_10 /* PCIe Reset De-Asserted */ +#define P_GAT_GPHY_N_REC_PACKET BIT_9 /* GPHY Not Received Packet */ +#define P_GAT_INT_FIFO_EMPTY BIT_8 /* Internal FIFO Empty */ +#define P_GAT_MAIN_PWR_N_AVAIL BIT_7 /* Main Power Not Available */ +#define P_GAT_CLKRUN_REQ_REL BIT_6 /* CLKRUN Not Requested */ +#define P_GAT_PCIE_RESET_ASS BIT_5 /* PCIe Reset Asserted */ +#define P_GAT_PME_DE_ASSERTED BIT_4 /* PME De-Asserted */ +#define P_GAT_PCIE_ENTER_L1_ST BIT_3 /* PCIe Enter L1 State */ +#define P_GAT_LOADER_FINISHED BIT_2 /* EPROM Loader Finished */ +#define P_GAT_PCIE_RX_EL_IDLE BIT_1 /* PCIe Rx Electrical Idle State */ +#define P_GAT_GPHY_LINK_DOWN BIT_0 /* GPHY Link Down */ + +/* PEX_DEV_CTRL 16 bit PEX Device Control (Yukon-2) */ + /* Bit 15 reserved */ +#define PEX_DC_MAX_RRS_MSK (7<<12) /* Bit 14..12: Max. Read Request Size */ +#define PEX_DC_EN_NO_SNOOP BIT_11S /* Enable No Snoop */ +#define PEX_DC_EN_AUX_POW BIT_10S /* Enable AUX Power */ +#define PEX_DC_EN_PHANTOM BIT_9S /* Enable Phantom Functions */ +#define PEX_DC_EN_EXT_TAG BIT_8S /* Enable Extended Tag Field */ +#define PEX_DC_MAX_PLS_MSK (7<<5) /* Bit 7.. 5: Max. Payload Size Mask */ +#define PEX_DC_EN_REL_ORD BIT_4S /* Enable Relaxed Ordering */ +#define PEX_DC_EN_UNS_RQ_RP BIT_3S /* Enable Unsupported Request Reporting */ +#define PEX_DC_EN_FAT_ER_RP BIT_2S /* Enable Fatal Error Reporting */ +#define PEX_DC_EN_NFA_ER_RP BIT_1S /* Enable Non-Fatal Error Reporting */ +#define PEX_DC_EN_COR_ER_RP BIT_0S /* Enable Correctable Error Reporting */ + +#define PEX_DC_MAX_RD_RQ_SIZE(x) (SHIFT12(x) & PEX_DC_MAX_RRS_MSK) + +/* PEX_LNK_CAP 32 bit PEX Link Capabilities */ +#define PEX_CAP_MAX_WI_MSK (0x3f<<4) /* Bit 9.. 4: Max. Link Width Mask */ +#define PEX_CAP_MAX_SP_MSK 0x0f /* Bit 3.. 0: Max. Link Speed Mask */ + +/* PEX_LNK_CTRL 16 bit PEX Link Control (Yukon-2) */ +#define PEX_LC_CLK_PM_ENA BIT_8S /* Enable Clock Power Management (CLKREQ) */ + +/* PEX_LNK_STAT 16 bit PEX Link Status (Yukon-2) */ + /* Bit 15..13 reserved */ +#define PEX_LS_SLOT_CLK_CFG BIT_12S /* Slot Clock Config */ +#define PEX_LS_LINK_TRAIN BIT_11S /* Link Training */ +#define PEX_LS_TRAIN_ERROR BIT_10S /* Training Error */ +#define PEX_LS_LINK_WI_MSK (0x3f<<4) /* Bit 9.. 4: Neg. Link Width Mask */ +#define PEX_LS_LINK_SP_MSK 0x0f /* Bit 3.. 0: Link Speed Mask */ + +/* PEX_UNC_ERR_STAT 16 bit PEX Uncorrectable Errors Status (Yukon-2) */ + /* Bit 31..21 reserved */ +#define PEX_UNSUP_REQ BIT_20 /* Unsupported Request Error */ + /* ECRC Error (not supported) */ +#define PEX_MALFOR_TLP BIT_18 /* Malformed TLP */ +#define PEX_RX_OV BIT_17 /* Receiver Overflow (not supported) */ +#define PEX_UNEXP_COMP BIT_16 /* Unexpected Completion */ + /* Completer Abort (not supported) */ +#define PEX_COMP_TO BIT_14 /* Completion Timeout */ +#define PEX_FLOW_CTRL_P BIT_13 /* Flow Control Protocol Error */ +#define PEX_POIS_TLP BIT_12 /* Poisoned TLP */ + /* Bit 11.. 5: reserved */ +#define PEX_DATA_LINK_P BIT_4 /* Data Link Protocol Error */ + /* Bit 3.. 1: reserved */ + /* Training Error (not supported) */ + +#define PEX_FATAL_ERRORS (PEX_MALFOR_TLP | PEX_FLOW_CTRL_P | PEX_DATA_LINK_P) /* Control Register File (Address Map) */ @@ -544,15 +563,21 @@ extern "C" { */ #define B0_RAP 0x0000 /* 8 bit Register Address Port */ /* 0x0001 - 0x0003: reserved */ -#define B0_CTST 0x0004 /* 16 bit Control/Status register */ -#define B0_LED 0x0006 /* 8 Bit LED register */ +#define B0_CTST 0x0004 /* 16 bit Control/Status Register */ +#define B0_LED 0x0006 /* 8 Bit LED Register */ #define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */ #define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */ #define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */ #define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */ #define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */ -#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */ - /* 0x001c: reserved */ +#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg 1 */ + +/* Special ISR registers (Yukon-2 only) */ +#define B0_Y2_SP_ISRC2 0x001c /* 32 bit Special Interrupt Source Reg 2 */ +#define B0_Y2_SP_ISRC3 0x0020 /* 32 bit Special Interrupt Source Reg 3 */ +#define B0_Y2_SP_EISR 0x0024 /* 32 bit Enter ISR Register */ +#define B0_Y2_SP_LISR 0x0028 /* 32 bit Leave ISR Register */ +#define B0_Y2_SP_ICR 0x002c /* 32 bit Interrupt Control Register */ /* B0 XMAC 1 registers (GENESIS only) */ #define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/ @@ -574,7 +599,7 @@ extern "C" { #define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */ /* 0x0056 - 0x005f: reserved */ -/* BMU Control Status Registers */ +/* BMU Control Status Registers (Yukon and Genesis) */ #define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */ #define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */ #define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ @@ -592,7 +617,7 @@ extern "C" { /* * Bank 2 */ -/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */ +/* NA reg = 48 bit Network Address Register, 3x16 or 6x8 bit readable */ #define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */ /* 0x0106 - 0x0107: reserved */ #define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */ @@ -602,21 +627,30 @@ extern "C" { #define B2_CONN_TYP 0x0118 /* 8 bit Connector type */ #define B2_PMD_TYP 0x0119 /* 8 bit PMD type */ #define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */ -#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */ - /* Eprom registers are currently of no use */ +#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */ + /* Eprom registers */ #define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */ +/* Yukon and Genesis */ #define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */ #define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */ +/* Yukon-2 */ +#define B2_Y2_CLK_GATE 0x011d /* 8 bit Clock Gating (Yukon-2) */ +#define B2_Y2_HW_RES 0x011e /* 8 bit HW Resources (Yukon-2) */ + #define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */ + +/* Yukon and Genesis */ #define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */ #define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */ +/* Yukon-2 */ +#define B2_Y2_CLK_CTRL 0x0120 /* 32 bit Core Clock Frequency Control */ /* 0x0125 - 0x0127: reserved */ -#define B2_LD_CRTL 0x0128 /* 8 bit EPROM loader control register */ +#define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */ #define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */ /* 0x012a - 0x012f: reserved */ #define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */ #define B2_TI_VAL 0x0134 /* 32 bit Timer Value */ -#define B2_TI_CRTL 0x0138 /* 8 bit Timer Control */ +#define B2_TI_CTRL 0x0138 /* 8 bit Timer Control */ #define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */ /* 0x013a - 0x013f: reserved */ #define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/ @@ -641,6 +675,10 @@ extern "C" { #define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */ #define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */ #define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */ + +/* Yukon-2 */ +#define Y2_PEX_PHY_DATA 0x0170 /* 16 bit PEX PHY Data Register */ +#define Y2_PEX_PHY_ADDR 0x0172 /* 16 bit PEX PHY Address Register */ /* 0x017c - 0x017f: reserved */ /* @@ -650,9 +688,14 @@ extern "C" { #define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */ #define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */ #define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */ +#define B3_RAM_PARITY 0x018c /* 8 bit RAM Parity (Yukon-ECU A1) */ + +#define SELECT_RAM_BUFFER(rb, addr) (addr | (rb << 6)) /* Yukon-2 only */ + /* 0x018c - 0x018f: reserved */ /* RAM Interface Registers */ +/* Yukon-2: use SELECT_RAM_BUFFER() to access the RAM buffer */ /* * The HW-Spec. calls this registers Timeout Value 0..11. But this names are * not usable in SW. Please notice these are NOT real timeouts, these are @@ -719,8 +762,8 @@ extern "C" { /* 0x01ea - 0x01eb: reserved */ #define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */ /* 0x01ee - 0x01ef: reserved */ -#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */ -#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */ +#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */ +#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */ /* 0x01f4 - 0x01ff: reserved */ /* @@ -734,7 +777,16 @@ extern "C" { #define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */ #define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */ #define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */ - /* 0x0213 - 0x027f: reserved */ + /* 0x0213 - 0x021f: reserved */ + + /* RSS key registers for Yukon-2 Family */ +#define B4_RSS_KEY 0x0220 /* 4x32 bit RSS Key register (Yukon-2) */ + /* RSS key register offsets */ +#define KEY_IDX_0 0 /* offset for location of KEY 0 */ +#define KEY_IDX_1 4 /* offset for location of KEY 1 */ +#define KEY_IDX_2 8 /* offset for location of KEY 2 */ +#define KEY_IDX_3 12 /* offset for location of KEY 3 */ + /* 0x0280 - 0x0292: MAC 2 */ /* 0x0213 - 0x027f: reserved */ @@ -758,10 +810,10 @@ extern "C" { /* Queue Register Offsets, use Q_ADDR() to access */ #define Q_D 0x00 /* 8*32 bit Current Descriptor */ -#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */ -#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */ -#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */ -#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */ +#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low DWord */ +#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High DWord */ +#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low DWord */ +#define Q_AC_H 0x2c /* 32 bit Current Address Counter High DWord */ #define Q_BC 0x30 /* 32 bit Current Byte Counter */ #define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */ #define Q_F 0x38 /* 32 bit Flag Register */ @@ -772,8 +824,56 @@ extern "C" { #define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */ #define Q_T2 0x40 /* 32 bit Test Register 2 */ #define Q_T3 0x44 /* 32 bit Test Register 3 */ + +/* Yukon-2 */ +#define Q_DONE 0x24 /* 16 bit Done Index */ + +#define Q_WM 0x40 /* 16 bit FIFO Watermark */ +#define Q_AL 0x42 /* 8 bit FIFO Alignment */ + /* 0x43: reserved */ +/* RX Queue */ +#define Q_RX_RSP 0x44 /* 16 bit FIFO Read Shadow Pointer */ +#define Q_RX_RSL 0x46 /* 8 bit FIFO Read Shadow Level */ + /* 0x47: reserved */ +#define Q_RX_RP 0x48 /* 8 bit FIFO Read Pointer */ + /* 0x49: reserved */ +#define Q_RX_RL 0x4a /* 8 bit FIFO Read Level */ + /* 0x4b: reserved */ +#define Q_RX_WP 0x4c /* 8 bit FIFO Write Pointer */ +#define Q_RX_WSP 0x4d /* 8 bit FIFO Write Shadow Pointer */ +#define Q_RX_WL 0x4e /* 8 bit FIFO Write Level */ +#define Q_RX_WSL 0x4f /* 8 bit FIFO Write Shadow Level */ +/* TX Queue */ +#define Q_TX_WSP 0x44 /* 16 bit FIFO Write Shadow Pointer */ +#define Q_TX_WSL 0x46 /* 8 bit FIFO Write Shadow Level */ + /* 0x47: reserved */ +#define Q_TX_WP 0x48 /* 8 bit FIFO Write Pointer */ + /* 0x49: reserved */ +#define Q_TX_WL 0x4a /* 8 bit FIFO Write Level */ + /* 0x4b: reserved */ +#define Q_TX_RP 0x4c /* 8 bit FIFO Read Pointer */ + /* 0x4d: reserved */ +#define Q_TX_RL 0x4e /* 8 bit FIFO Read Level */ + /* 0x4f: reserved */ + /* 0x48 - 0x7f: reserved */ +/* Queue Prefetch Unit Offsets, use Y2_PREF_Q_ADDR() to address (Yukon-2 only)*/ +#define Y2_B8_PREF_REGS 0x0450 + +#define PREF_UNIT_CTRL_REG 0x00 /* 32 bit Prefetch Control register */ +#define PREF_UNIT_LAST_IDX_REG 0x04 /* 16 bit Last Index */ +#define PREF_UNIT_ADDR_LOW_REG 0x08 /* 32 bit List start addr, low part */ +#define PREF_UNIT_ADDR_HI_REG 0x0c /* 32 bit List start addr, high part*/ +#define PREF_UNIT_GET_IDX_REG 0x10 /* 16 bit Get Index */ +#define PREF_UNIT_PUT_IDX_REG 0x14 /* 16 bit Put Index */ +#define PREF_UNIT_FIFO_WP_REG 0x20 /* 8 bit FIFO write pointer */ +#define PREF_UNIT_FIFO_RP_REG 0x24 /* 8 bit FIFO read pointer */ +#define PREF_UNIT_FIFO_WM_REG 0x28 /* 8 bit FIFO watermark */ +#define PREF_UNIT_FIFO_LEV_REG 0x2c /* 8 bit FIFO level */ + +#define PREF_UNIT_MASK_IDX 0x0fff + /* * Bank 16 - 23 */ @@ -785,17 +885,17 @@ extern "C" { #define RB_END 0x04 /* 32 bit RAM Buffer End Address */ #define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */ #define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */ -#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */ -#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */ +#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Packet */ +#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Packet */ #define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */ #define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */ /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ #define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */ #define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */ -#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */ +#define RB_CTRL 0x28 /* 32 bit RAM Buffer Control Register */ #define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */ -#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */ - /* 0x2c - 0x7f: reserved */ +#define RB_TST2 0x2a /* 8 bit RAM Buffer Test Register 2 */ + /* 0x2b - 0x7f: reserved */ /* * Bank 24 @@ -805,7 +905,7 @@ extern "C" { * use MR_ADDR() to access */ #define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */ -#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */ +#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */ /* 0x0c08 - 0x0c0b: reserved */ #define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */ #define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */ @@ -830,20 +930,23 @@ extern "C" { #define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */ /* 0x0c3d - 0x0c3f: reserved */ -/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */ +/* Receive GMAC FIFO (YUKON and Yukon-2), use MR_ADDR() to access */ #define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */ #define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */ #define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */ #define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */ #define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */ - /* 0x0c54 - 0x0c5f: reserved */ -#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */ +#define RX_GMF_TR_THR 0x0c54 /* 32 bit Rx Truncation Threshold (Yukon-2) */ +#define RX_GMF_UP_THR 0x0c58 /* 16 bit Rx Upper Pause Thr (Yukon-EC_U) */ +#define RX_GMF_LP_THR 0x0c5a /* 16 bit Rx Lower Pause Thr (Yukon-EC_U) */ +#define RX_GMF_VLAN 0x0c5c /* 32 bit Rx VLAN Type Register (Yukon-2) */ +#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */ /* 0x0c64 - 0x0c67: reserved */ -#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */ +#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */ /* 0x0c6c - 0x0c6f: reserved */ -#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */ +#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */ /* 0x0c74 - 0x0c77: reserved */ -#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */ +#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */ /* 0x0c7c - 0x0c7f: reserved */ /* @@ -860,7 +963,7 @@ extern "C" { * use MR_ADDR() to access */ #define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */ -#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */ +#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */ #define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */ #define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */ #define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */ @@ -878,18 +981,19 @@ extern "C" { #define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */ /* 0x0d2a - 0x0d3f: reserved */ -/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */ +/* Transmit GMAC FIFO (YUKON and Yukon-2), use MR_ADDR() to access */ #define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */ -#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ +#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh. */ #define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */ - /* 0x0d4c - 0x0d5f: reserved */ -#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */ -#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */ + /* 0x0d4c - 0x0d5b: reserved */ +#define TX_GMF_VLAN 0x0d5c /* 32 bit Tx VLAN Type Register (Yukon-2) */ +#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */ +#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Pointer */ +#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */ /* 0x0d6c - 0x0d6f: reserved */ -#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */ -#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */ -#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */ +#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */ +#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */ +#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */ /* 0x0d7c - 0x0d7f: reserved */ /* @@ -915,12 +1019,84 @@ extern "C" { #define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */ /* 0x0e19: reserved */ #define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */ - /* 0x0e1b - 0x0e7f: reserved */ + /* 0x0e1b - 0x0e1f: reserved */ + +/* Polling Unit Registers (Yukon-2 only) */ +#define POLL_CTRL 0x0e20 /* 32 bit Polling Unit Control Reg */ +#define POLL_LAST_IDX 0x0e24 /* 16 bit Polling Unit List Last Index */ + /* 0x0e26 - 0x0e27: reserved */ +#define POLL_LIST_ADDR_LO 0x0e28 /* 32 bit Poll. List Start Addr (low) */ +#define POLL_LIST_ADDR_HI 0x0e2c /* 32 bit Poll. List Start Addr (high) */ + /* 0x0e30 - 0x0e3f: reserved */ + +/* ASF Subsystem Registers (Yukon-2 only) */ +#define B28_Y2_SMB_CONFIG 0x0e40 /* 32 bit ASF SMBus Config Register */ +#define B28_Y2_SMB_CSD_REG 0x0e44 /* 32 bit ASF SMB Control/Status/Data */ + /* 0x0e48 - 0x0e5f: reserved */ +#define B28_Y2_ASF_IRQ_V_BASE 0x0e60 /* 32 bit ASF IRQ Vector Base */ + /* 0x0e64 - 0x0e67: reserved */ +#define B28_Y2_ASF_STAT_CMD 0x0e68 /* 32 bit ASF Status and Command Reg */ +#define B28_Y2_ASF_HOST_COM 0x0e6c /* 32 bit ASF Host Communication Reg */ +#define B28_Y2_DATA_REG_1 0x0e70 /* 32 bit ASF/Host Data Register 1 */ +#define B28_Y2_DATA_REG_2 0x0e74 /* 32 bit ASF/Host Data Register 2 */ +#define B28_Y2_DATA_REG_3 0x0e78 /* 32 bit ASF/Host Data Register 3 */ +#define B28_Y2_DATA_REG_4 0x0e7c /* 32 bit ASF/Host Data Register 4 */ /* * Bank 29 */ - /* 0x0e80 - 0x0efc: reserved */ + +/* Status BMU Registers (Yukon-2 only)*/ +#define STAT_CTRL 0x0e80 /* 32 bit Status BMU Control Reg */ +#define STAT_LAST_IDX 0x0e84 /* 16 bit Status BMU Last Index */ + /* 0x0e85 - 0x0e86: reserved */ +#define STAT_LIST_ADDR_LO 0x0e88 /* 32 bit Status List Start Addr (low) */ +#define STAT_LIST_ADDR_HI 0x0e8c /* 32 bit Status List Start Addr (high) */ +#define STAT_TXA1_RIDX 0x0e90 /* 16 bit Status TxA1 Report Index Reg */ +#define STAT_TXS1_RIDX 0x0e92 /* 16 bit Status TxS1 Report Index Reg */ +#define STAT_TXA2_RIDX 0x0e94 /* 16 bit Status TxA2 Report Index Reg */ +#define STAT_TXS2_RIDX 0x0e96 /* 16 bit Status TxS2 Report Index Reg */ +#define STAT_TX_IDX_TH 0x0e98 /* 16 bit Status Tx Index Threshold Reg */ + /* 0x0e9a - 0x0e9b: reserved */ +#define STAT_PUT_IDX 0x0e9c /* 16 bit Status Put Index Reg */ + /* 0x0e9e - 0x0e9f: reserved */ + +/* FIFO Control/Status Registers (Yukon-2 only) */ +#define STAT_FIFO_WP 0x0ea0 /* 8 bit Status FIFO Write Pointer Reg */ + /* 0x0ea1 - 0x0ea3: reserved */ +#define STAT_FIFO_RP 0x0ea4 /* 8 bit Status FIFO Read Pointer Reg */ + /* 0x0ea5: reserved */ +#define STAT_FIFO_RSP 0x0ea6 /* 8 bit Status FIFO Read Shadow Ptr */ + /* 0x0ea7: reserved */ +#define STAT_FIFO_LEVEL 0x0ea8 /* 8 bit Status FIFO Level Reg */ + /* 0x0ea9: reserved */ +#define STAT_FIFO_SHLVL 0x0eaa /* 8 bit Status FIFO Shadow Level Reg */ + /* 0x0eab: reserved */ +#define STAT_FIFO_WM 0x0eac /* 8 bit Status FIFO Watermark Reg */ +#define STAT_FIFO_ISR_WM 0x0ead /* 8 bit Status FIFO ISR Watermark Reg */ + /* 0x0eae - 0x0eaf: reserved */ + +/* Level and ISR Timer Registers (Yukon-2 only) */ +#define STAT_LEV_TIMER_INI 0x0eb0 /* 32 bit Level Timer Init. Value Reg */ +#define STAT_LEV_TIMER_CNT 0x0eb4 /* 32 bit Level Timer Counter Reg */ +#define STAT_LEV_TIMER_CTRL 0x0eb8 /* 8 bit Level Timer Control Reg */ +#define STAT_LEV_TIMER_TEST 0x0eb9 /* 8 bit Level Timer Test Reg */ + /* 0x0eba - 0x0ebf: reserved */ +#define STAT_TX_TIMER_INI 0x0ec0 /* 32 bit Tx Timer Init. Value Reg */ +#define STAT_TX_TIMER_CNT 0x0ec4 /* 32 bit Tx Timer Counter Reg */ +#define STAT_TX_TIMER_CTRL 0x0ec8 /* 8 bit Tx Timer Control Reg */ +#define STAT_TX_TIMER_TEST 0x0ec9 /* 8 bit Tx Timer Test Reg */ + /* 0x0eca - 0x0ecf: reserved */ +#define STAT_ISR_TIMER_INI 0x0ed0 /* 32 bit ISR Timer Init. Value Reg */ +#define STAT_ISR_TIMER_CNT 0x0ed4 /* 32 bit ISR Timer Counter Reg */ +#define STAT_ISR_TIMER_CTRL 0x0ed8 /* 8 bit ISR Timer Control Reg */ +#define STAT_ISR_TIMER_TEST 0x0ed9 /* 8 bit ISR Timer Test Reg */ + /* 0x0eda - 0x0eff: reserved */ + +#define ST_LAST_IDX_MASK 0x007f /* Last Index Mask */ +#define ST_TXRP_IDX_MASK 0x0fff /* Tx Report Index Mask */ +#define ST_TXTH_IDX_MASK 0x0fff /* Tx Threshold Index Mask */ +#define ST_WM_IDX_MASK 0x3f /* FIFO Watermark Index Mask */ /* * Bank 30 @@ -944,11 +1120,9 @@ extern "C" { #define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */ #define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */ #define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */ -#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */ - -/* use this macro to access above registers */ -#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs)) - +#define WOL_PATT_PME 0x0f2a /* 8 bit WOL PME Match Enable (Yukon-2) */ +#define WOL_PATT_ASFM 0x0f2b /* 8 bit WOL ASF Match Enable (Yukon-2) */ +#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Pointer */ /* WOL Pattern Length Registers (YUKON only) */ @@ -966,11 +1140,22 @@ extern "C" { */ /* 0x0f80 - 0x0fff: reserved */ +/* WOL registers link 2 */ + +/* use this macro to access WOL registers */ +#define WOL_REG(Port, Reg) ((Reg) + ((Port)*0x80) + (pAC->GIni.GIWolOffs)) + /* * Bank 32 - 33 */ #define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */ +#define WOL_PATT_RAM_2 0x1400 /* WOL Pattern RAM Link 2 */ +/* use this macro to retrieve the pattern ram base address */ +#define WOL_PATT_RAM_BASE(Port) (WOL_PATT_RAM_1 + (Port)*0x400) + +/* offset to configuration space on Yukon-2 */ +#define Y2_CFG_SPC 0x1c00 /* * Bank 0x22 - 0x3f */ @@ -1002,13 +1187,27 @@ extern "C" { */ /* B0_RAP 8 bit Register Address Port */ /* Bit 7: reserved */ -#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */ +#define RAP_MSK 0x7f /* Bit 6..0: 0 = block 0,..,6f = block 6f */ -/* B0_CTST 16 bit Control/Status register */ +/* B0_CTST 24 bit Control/Status register */ + /* Bit 23..18: reserved */ +#define Y2_VMAIN_AVAIL BIT_17 /* VMAIN available (YUKON-2 only) */ +#define Y2_VAUX_AVAIL BIT_16 /* VAUX available (YUKON-2 only) */ +#define Y2_HW_WOL_ON BIT_15S /* HW WOL On (Yukon-EC Ultra A1 only) */ +#define Y2_HW_WOL_OFF BIT_14S /* HW WOL Off (Yukon-EC Ultra A1 only) */ +#define Y2_ASF_ENABLE BIT_13S /* ASF Unit Enable (YUKON-2 only) */ +#define Y2_ASF_DISABLE BIT_12S /* ASF Unit Disable (YUKON-2 only) */ +#define Y2_CLK_RUN_ENA BIT_11S /* CLK_RUN Enable (YUKON-2 only) */ +#define Y2_CLK_RUN_DIS BIT_10S /* CLK_RUN Disable (YUKON-2 only) */ +#define Y2_LED_STAT_ON BIT_9S /* Status LED On (YUKON-2 only) */ +#define Y2_LED_STAT_OFF BIT_8S /* Status LED Off (YUKON-2 only) */ + /* Bit 7.. 0: same as below */ + +/* B0_CTST 16 bit Control/Status register */ /* Bit 15..14: reserved */ -#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */ -#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */ -#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */ +#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN Hot m. (YUKON-Lite only) */ +#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN Reset (YUKON-Lite only) */ +#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN Enable (YUKON-Lite only) */ #define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */ #define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */ #define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */ @@ -1016,31 +1215,32 @@ extern "C" { #define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */ #define CS_STOP_DONE BIT_5S /* Stop Master is finished */ #define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */ -#define CS_MRST_CLR BIT_3S /* Clear Master reset */ -#define CS_MRST_SET BIT_2S /* Set Master reset */ -#define CS_RST_CLR BIT_1S /* Clear Software reset */ -#define CS_RST_SET BIT_0S /* Set Software reset */ +#define CS_MRST_CLR BIT_3S /* Clear Master Reset */ +#define CS_MRST_SET BIT_2S /* Set Master Reset */ +#define CS_RST_CLR BIT_1S /* Clear Software Reset */ +#define CS_RST_SET BIT_0S /* Set Software Reset */ -/* B0_LED 8 Bit LED register */ +/* B0_LED 8 Bit LED register (GENESIS only)*/ /* Bit 7.. 2: reserved */ -#define LED_STAT_ON BIT_1S /* Status LED on */ -#define LED_STAT_OFF BIT_0S /* Status LED off */ +#define LED_STAT_ON BIT_1S /* Status LED On */ +#define LED_STAT_OFF BIT_0S /* Status LED Off */ /* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ #define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */ -#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */ -#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */ -#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */ -#define PC_VAUX_ON BIT_3 /* Switch VAUX On */ -#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */ -#define PC_VCC_ON BIT_1 /* Switch VCC On */ -#define PC_VCC_OFF BIT_0 /* Switch VCC Off */ +#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */ +#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */ +#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */ +#define PC_VAUX_ON BIT_3 /* Switch VAUX On */ +#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */ +#define PC_VCC_ON BIT_1 /* Switch VCC On */ +#define PC_VCC_OFF BIT_0 /* Switch VCC Off */ -/* B0_ISRC 32 bit Interrupt Source Register */ -/* B0_IMSK 32 bit Interrupt Mask Register */ -/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ +/* Yukon and Genesis */ +/* B0_ISRC 32 bit Interrupt Source Register */ +/* B0_IMSK 32 bit Interrupt Mask Register */ +/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ /* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ -#define IS_ALL_MSK 0xbfffffffL /* All Interrupt bits */ +#define IS_ALL_MSK 0xbfffffffUL /* All Interrupt bits */ #define IS_HW_ERR BIT_31 /* Interrupt HW Error */ /* Bit 30: reserved */ #define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */ @@ -1081,12 +1281,58 @@ extern "C" { #define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */ #define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */ +/* Yukon-2 */ +/* B0_ISRC 32 bit Interrupt Source Register */ +/* B0_IMSK 32 bit Interrupt Mask Register */ +/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ +/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ +/* B0_Y2_SP_ISRC2 32 bit Special Interrupt Source Reg 2 */ +/* B0_Y2_SP_ISRC3 32 bit Special Interrupt Source Reg 3 */ +/* B0_Y2_SP_EISR 32 bit Enter ISR Reg */ +/* B0_Y2_SP_LISR 32 bit Leave ISR Reg */ +#define Y2_IS_PORT_MASK(Port, Mask) ((Mask) << (Port*8)) +#define Y2_IS_HW_ERR BIT_31 /* Interrupt HW Error */ +#define Y2_IS_STAT_BMU BIT_30 /* Status BMU Interrupt */ +#define Y2_IS_ASF BIT_29 /* ASF subsystem Interrupt */ + /* Bit 28: reserved */ +#define Y2_IS_POLL_CHK BIT_27 /* Check IRQ from polling unit */ +#define Y2_IS_TWSI_RDY BIT_26 /* IRQ on end of TWSI Tx */ +#define Y2_IS_IRQ_SW BIT_25 /* SW forced IRQ */ +#define Y2_IS_TIMINT BIT_24 /* IRQ from Timer */ + /* Bit 23..16 reserved */ + /* Link 2 Interrupts */ +#define Y2_IS_IRQ_PHY2 BIT_12 /* Interrupt from PHY 2 */ +#define Y2_IS_IRQ_MAC2 BIT_11 /* Interrupt from MAC 2 */ +#define Y2_IS_CHK_RX2 BIT_10 /* Descriptor error Rx 2 */ +#define Y2_IS_CHK_TXS2 BIT_9 /* Descriptor error TXS 2 */ +#define Y2_IS_CHK_TXA2 BIT_8 /* Descriptor error TXA 2 */ + /* Bit 7.. 5 reserved */ + /* Link 1 interrupts */ +#define Y2_IS_IRQ_PHY1 BIT_4 /* Interrupt from PHY 1 */ +#define Y2_IS_IRQ_MAC1 BIT_3 /* Interrupt from MAC 1 */ +#define Y2_IS_CHK_RX1 BIT_2 /* Descriptor error Rx 1 */ +#define Y2_IS_CHK_TXS1 BIT_1 /* Descriptor error TXS 1 */ +#define Y2_IS_CHK_TXA1 BIT_0 /* Descriptor error TXA 1 */ -/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ -/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ -/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ +#define Y2_IS_L1_MASK 0x0000001fUL /* IRQ Mask for port 1 */ + +#define Y2_IS_L2_MASK 0x00001f00UL /* IRQ Mask for port 2 */ + +#define Y2_IS_ALL_MSK 0xef001f1fUL /* All Interrupt bits */ + +/* B0_Y2_SP_ICR 32 bit Interrupt Control Register */ + /* Bit 31.. 4: reserved */ +#define Y2_IC_ISR_MASK BIT_3 /* ISR mask flag */ +#define Y2_IC_ISR_STAT BIT_2 /* ISR status flag */ +#define Y2_IC_LEAVE_ISR BIT_1 /* Leave ISR */ +#define Y2_IC_ENTER_ISR BIT_0 /* Enter ISR */ + +/* Yukon and Genesis */ +/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ +/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ +/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ #define IS_ERR_MSK 0x00000fffL /* All Error bits */ - /* Bit 31..14: reserved */ + /* Bit 31..14: reserved */ #define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */ #define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */ #define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */ @@ -1102,27 +1348,125 @@ extern "C" { #define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */ #define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */ -/* B2_CONN_TYP 8 bit Connector type */ -/* B2_PMD_TYP 8 bit PMD type */ +/* Yukon-2 */ +/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ +/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ +/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ + /* Bit: 31..30 reserved */ +#define Y2_IS_TIST_OV BIT_29 /* Time Stamp Timer overflow interrupt */ +#define Y2_IS_SENSOR BIT_28 /* Sensor interrupt */ +#define Y2_IS_MST_ERR BIT_27 /* Master error interrupt */ +#define Y2_IS_IRQ_STAT BIT_26 /* Status exception interrupt */ +#define Y2_IS_PCI_EXP BIT_25 /* PCI-Express interrupt */ +#define Y2_IS_PCI_NEXP BIT_24 /* Bus Abort detected */ + /* Bit: 23..14 reserved */ + /* Link 2 */ +#define Y2_IS_PAR_RD2 BIT_13 /* Read RAM parity error interrupt */ +#define Y2_IS_PAR_WR2 BIT_12 /* Write RAM parity error interrupt */ +#define Y2_IS_PAR_MAC2 BIT_11 /* MAC hardware fault interrupt */ +#define Y2_IS_PAR_RX2 BIT_10 /* Parity Error Rx Queue 2 */ +#define Y2_IS_TCP_TXS2 BIT_9 /* TCP length mismatch sync Tx queue IRQ */ +#define Y2_IS_TCP_TXA2 BIT_8 /* TCP length mismatch async Tx queue IRQ */ + /* Bit: 9.. 6 reserved */ + /* Link 1 */ +#define Y2_IS_PAR_RD1 BIT_5 /* Read RAM parity error interrupt */ +#define Y2_IS_PAR_WR1 BIT_4 /* Write RAM parity error interrupt */ +#define Y2_IS_PAR_MAC1 BIT_3 /* MAC hardware fault interrupt */ +#define Y2_IS_PAR_RX1 BIT_2 /* Parity Error Rx Queue 1 */ +#define Y2_IS_TCP_TXS1 BIT_1 /* TCP length mismatch sync Tx queue IRQ */ +#define Y2_IS_TCP_TXA1 BIT_0 /* TCP length mismatch async Tx queue IRQ */ + +#define Y2_HWE_L1_MASK (Y2_IS_PAR_RD1 | Y2_IS_PAR_WR1 | Y2_IS_PAR_MAC1 |\ + Y2_IS_PAR_RX1 | Y2_IS_TCP_TXS1| Y2_IS_TCP_TXA1) +#define Y2_HWE_L2_MASK (Y2_IS_PAR_RD2 | Y2_IS_PAR_WR2 | Y2_IS_PAR_MAC2 |\ + Y2_IS_PAR_RX2 | Y2_IS_TCP_TXS2| Y2_IS_TCP_TXA2) + +#define Y2_HWE_ALL_MSK (Y2_IS_TIST_OV | /* Y2_IS_SENSOR | */ Y2_IS_MST_ERR |\ + Y2_IS_IRQ_STAT | Y2_IS_PCI_EXP |\ + Y2_HWE_L1_MASK | Y2_HWE_L2_MASK) + +/* B2_CONN_TYP 8 bit Connector type */ +/* B2_PMD_TYP 8 bit PMD type */ /* Values of connector and PMD type comply to SysKonnect internal std */ -/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ +/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ #define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */ /* Bit 3.. 2: reserved */ #define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */ -#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/ +#define CFG_SNG_MAC BIT_0S /* MAC Config: 0 = 2 MACs; 1 = 1 MAC */ -/* B2_CHIP_ID 8 bit Chip Identification Number */ -#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */ -#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */ +/* B2_CHIP_ID 8 bit Chip Identification Number */ +#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */ +#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */ +#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */ +#define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */ +#define CHIP_ID_YUKON_XL 0xb3 /* Chip ID for YUKON-2 XL */ +#define CHIP_ID_YUKON_EC_U 0xb4 /* Chip ID for YUKON-2 EC Ultra */ +#define CHIP_ID_YUKON_EC 0xb6 /* Chip ID for YUKON-2 EC */ +#define CHIP_ID_YUKON_FE 0xb7 /* Chip ID for YUKON-2 FE */ -/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ -#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */ +#define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */ +#define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */ -/* B2_LD_CRTL 8 bit EPROM loader control register */ +#define CHIP_REV_YU_XL_A0 0 /* Chip Rev. for Yukon-2 A0 */ +#define CHIP_REV_YU_XL_A1 1 /* Chip Rev. for Yukon-2 A1 */ +#define CHIP_REV_YU_XL_A2 2 /* Chip Rev. for Yukon-2 A2 */ +#define CHIP_REV_YU_XL_A3 3 /* Chip Rev. for Yukon-2 A3 */ + +#define CHIP_REV_YU_EC_A1 0 /* Chip Rev. for Yukon-EC A0,A1 */ +#define CHIP_REV_YU_EC_A2 1 /* Chip Rev. for Yukon-EC A2 */ +#define CHIP_REV_YU_EC_A3 2 /* Chip Rev. for Yukon-EC A3 */ + +#define CHIP_REV_YU_EC_U_A0 1 /* Chip Rev. for Yukon-EC Ultra A0 */ +#define CHIP_REV_YU_EC_U_A1 2 /* Chip Rev. for Yukon-EC Ultra A1 */ + +/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ +#define Y2_STATUS_LNK2_INAC BIT_7S /* Status Link 2 inactiv (0 = activ) */ +#define Y2_CLK_GAT_LNK2_DIS BIT_6S /* Disable PHY clock for Link 2 */ +#define Y2_COR_CLK_LNK2_DIS BIT_5S /* Disable Core clock Link 2 */ +#define Y2_PCI_CLK_LNK2_DIS BIT_4S /* Disable PCI clock Link 2 */ +#define Y2_STATUS_LNK1_INAC BIT_3S /* Status Link 1 inactiv (0 = activ) */ +#define Y2_CLK_GAT_LNK1_DIS BIT_2S /* Disable PHY clock for Link 1 */ +#define Y2_COR_CLK_LNK1_DIS BIT_1S /* Disable Core clock Link 1 */ +#define Y2_PCI_CLK_LNK1_DIS BIT_0S /* Disable PCI clock Link 1 */ + +/* B2_Y2_HW_RES 8 bit HW Resources (Yukon-2 only) */ + /* Bit 7.. 6: reserved */ +#define CFG_PEX_PME_NATIVE BIT_5S /* PCI-E PME native mode select */ +#define CFG_LED_MODE_MSK (7<<2) /* Bit 4.. 2: LED Mode Mask */ +#define CFG_LINK_2_AVAIL BIT_1S /* Link 2 available */ +#define CFG_LINK_1_AVAIL BIT_0S /* Link 1 available */ + +#define CFG_LED_MODE(x) (((x) & CFG_LED_MODE_MSK) >> 2) +#define CFG_DUAL_MAC_MSK (CFG_LINK_2_AVAIL | CFG_LINK_1_AVAIL) + +#define CFG_LED_DUAL_ACT_LNK 1 /* Dual LED ACT/LNK mode */ +#define CFG_LED_LINK_MUX_P60 2 /* Link LED on pin 60 (Yukon-EC Ultra) */ + +/* B2_E_3 8 bit lower 4 bits used for HW self test result */ +#define B2_E3_RES_MASK 0x0f + +/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ +#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address Mask */ + +/* B2_Y2_CLK_CTRL 32 bit Core Clock Frequency Control Register (Yukon-2/EC) */ + /* Bit 31..24: reserved */ +/* Yukon-EC/FE */ +#define Y2_CLK_DIV_VAL_MSK (0xffL<<16) /* Bit 23..16: Clock Divisor Value */ +#define Y2_CLK_DIV_VAL(x) (SHIFT16(x) & Y2_CLK_DIV_VAL_MSK) +/* Yukon-2 */ +#define Y2_CLK_DIV_VAL2_MSK (7L<<21) /* Bit 23..21: Clock Divisor Value */ +#define Y2_CLK_SELECT2_MSK (0x1fL<<16) /* Bit 20..16: Clock Select */ +#define Y2_CLK_DIV_VAL_2(x) (SHIFT21(x) & Y2_CLK_DIV_VAL2_MSK) +#define Y2_CLK_SEL_VAL_2(x) (SHIFT16(x) & Y2_CLK_SELECT2_MSK) + /* Bit 15.. 2: reserved */ +#define Y2_CLK_DIV_ENA BIT_1S /* Enable Core Clock Division */ +#define Y2_CLK_DIV_DIS BIT_0S /* Disable Core Clock Division */ + +/* B2_LD_CTRL 8 bit EPROM loader control register */ /* Bits are currently reserved */ -/* B2_LD_TEST 8 bit EPROM loader test register */ +/* B2_LD_TEST 8 bit EPROM loader test register */ /* Bit 7.. 4: reserved */ #define LD_T_ON BIT_3S /* Loader Test mode on */ #define LD_T_OFF BIT_2S /* Loader Test mode off */ @@ -1132,16 +1476,16 @@ extern "C" { /* * Timer Section */ -/* B2_TI_CRTL 8 bit Timer control */ +/* B2_TI_CTRL 8 bit Timer control */ /* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ /* Bit 7.. 3: reserved */ #define TIM_START BIT_2S /* Start Timer */ #define TIM_STOP BIT_1S /* Stop Timer */ #define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */ -/* B2_TI_TEST 8 Bit Timer Test */ +/* B2_TI_TEST 8 Bit Timer Test */ /* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ -/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ +/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ /* Bit 7.. 3: reserved */ #define TIM_T_ON BIT_2S /* Test mode on */ #define TIM_T_OFF BIT_1S /* Test mode off */ @@ -1157,9 +1501,6 @@ extern "C" { #define DPT_START BIT_1S /* Start Descriptor Poll Timer */ #define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */ -/* B2_E_3 8 bit lower 4 bits used for HW self test result */ -#define B2_E3_RES_MASK 0x0f - /* B2_TST_CTRL1 8 bit Test Control Register 1 */ #define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */ #define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */ @@ -1172,24 +1513,24 @@ extern "C" { /* B2_TST_CTRL2 8 bit Test Control Register 2 */ /* Bit 7.. 4: reserved */ - /* force the following error on the next master read/write */ + /* force the following error on the next master read/write */ #define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */ #define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */ #define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */ #define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */ -/* B2_GP_IO 32 bit General Purpose I/O Register */ - /* Bit 31..26: reserved */ -#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=I/1=O */ -#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=I/1=O */ -#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=I/1=O */ -#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=I/1=O */ -#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=I/1=O */ -#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=I/1=O */ -#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=I/1=O */ -#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=I/1=O */ -#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=I/1=O */ -#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=I/1=O */ +/* B2_GP_IO 32 bit General Purpose I/O Register */ + /* Bit 31..26: reserved */ +#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */ +#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */ +#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=In/1=Out */ +#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=In/1=Out */ +#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=In/1=Out */ +#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=In/1=Out */ +#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=In/1=Out */ +#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=In/1=Out */ +#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=In/1=Out */ +#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=In/1=Out */ /* Bit 15..10: reserved */ #define GP_IO_9 BIT_9 /* IO_9 pin */ #define GP_IO_8 BIT_8 /* IO_8 pin */ @@ -1202,68 +1543,70 @@ extern "C" { #define GP_IO_1 BIT_1 /* IO_1 pin */ #define GP_IO_0 BIT_0 /* IO_0 pin */ -/* B2_I2C_CTRL 32 bit I2C HW Control Register */ +/* B2_I2C_CTRL 32 bit I2C HW Control Register */ #define I2C_FLAG BIT_31 /* Start read/write if WR */ #define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */ #define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */ - /* Bit 8.. 5: reserved */ + /* Bit 8.. 5: reserved */ #define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */ -#define I2C_DEV_SIZE (7L<<1) /* Bit 3.. 1: I2C Device Size */ -#define I2C_025K_DEV (0L<<1) /* 0: 256 Bytes or smal. */ -#define I2C_05K_DEV (1L<<1) /* 1: 512 Bytes */ -#define I2C_1K_DEV (2L<<1) /* 2: 1024 Bytes */ -#define I2C_2K_DEV (3L<<1) /* 3: 2048 Bytes */ -#define I2C_4K_DEV (4L<<1) /* 4: 4096 Bytes */ -#define I2C_8K_DEV (5L<<1) /* 5: 8192 Bytes */ -#define I2C_16K_DEV (6L<<1) /* 6: 16384 Bytes */ -#define I2C_32K_DEV (7L<<1) /* 7: 32768 Bytes */ +#define I2C_DEV_SIZE (7<<1) /* Bit 3.. 1: I2C Device Size */ +#define I2C_025K_DEV (0<<1) /* 0: 256 Bytes or smaller */ +#define I2C_05K_DEV (1<<1) /* 1: 512 Bytes */ +#define I2C_1K_DEV (2<<1) /* 2: 1024 Bytes */ +#define I2C_2K_DEV (3<<1) /* 3: 2048 Bytes */ +#define I2C_4K_DEV (4<<1) /* 4: 4096 Bytes */ +#define I2C_8K_DEV (5<<1) /* 5: 8192 Bytes */ +#define I2C_16K_DEV (6<<1) /* 6: 16384 Bytes */ +#define I2C_32K_DEV (7<<1) /* 7: 32768 Bytes */ #define I2C_STOP BIT_0 /* Interrupt I2C transfer */ -/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ +/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ /* Bit 31.. 1 reserved */ #define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */ -/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */ +/* B2_I2C_SW 32 bit (8 bit access) I2C SW Port Register */ /* Bit 7.. 3: reserved */ #define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */ -#define I2C_DATA BIT_1S /* I2C Data Port */ -#define I2C_CLK BIT_0S /* I2C Clock Port */ +#define I2C_DATA BIT_1S /* I2C Data Port */ +#define I2C_CLK BIT_0S /* I2C Clock Port */ -/* - * I2C Address - */ -#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/ +/* I2C Address */ +#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address (Volt and Temp) */ -/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ +/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ /* Bit 7.. 2: reserved */ #define BSC_START BIT_1S /* Start Blink Source Counter */ #define BSC_STOP BIT_0S /* Stop Blink Source Counter */ -/* B2_BSC_STAT 8 bit Blink Source Counter Status */ +/* B2_BSC_STAT 8 bit Blink Source Counter Status */ /* Bit 7.. 1: reserved */ #define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */ -/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ +/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ #define BSC_T_ON BIT_2S /* Test mode on */ #define BSC_T_OFF BIT_1S /* Test mode off */ #define BSC_T_STEP BIT_0S /* Test step */ +/* Y2_PEX_PHY_ADDR/DATA PEX PHY address and data reg (Yukon-2 only) */ +#define PEX_RD_ACCESS BIT_31 /* Access Mode Read = 1, Write = 0 */ +#define PEX_DB_ACCESS BIT_30 /* Access to debug register */ -/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ + +/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ /* Bit 31..19: reserved */ #define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ /* RAM Interface Registers */ -/* B3_RI_CTRL 16 bit RAM Iface Control Register */ +/* B3_RI_CTRL 16 bit RAM Interface Control Register */ /* Bit 15..10: reserved */ -#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */ -#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/ +#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */ +#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err */ /* Bit 7.. 2: reserved */ #define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */ #define RI_RST_SET BIT_0S /* Set RAM Interface Reset */ -/* B3_RI_TEST 8 bit RAM Iface Test Register */ +/* B3_RI_TEST 8 bit RAM Iface Test Register */ /* Bit 15.. 4: reserved */ #define RI_T_EV BIT_3S /* Timeout Event occured */ #define RI_T_ON BIT_2S /* Timeout Timer Test On */ @@ -1290,7 +1633,7 @@ extern "C" { #define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */ /* Packet Arbiter Registers */ -/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ +/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ /* Bit 15..14: reserved */ #define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */ #define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */ @@ -1313,7 +1656,7 @@ extern "C" { /* Rx/Tx Path related Arbiter Test Registers */ /* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */ /* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */ -/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ +/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ /* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */ #define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */ #define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */ @@ -1334,14 +1677,14 @@ extern "C" { /* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ -/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ -/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ -/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ +/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ +/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ +/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ +/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ /* Bit 31..24: reserved */ -#define TXA_MAX_VAL 0x00ffffffL /* Bit 23.. 0: Max TXA Timer/Cnt Val */ +#define TXA_MAX_VAL 0x00ffffffUL/* Bit 23.. 0: Max TXA Timer/Cnt Val */ -/* TXA_CTRL 8 bit Tx Arbiter Control Register */ +/* TXA_CTRL 8 bit Tx Arbiter Control Register */ #define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */ #define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */ #define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */ @@ -1351,7 +1694,7 @@ extern "C" { #define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */ #define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */ -/* TXA_TEST 8 bit Tx Arbiter Test Register */ +/* TXA_TEST 8 bit Tx Arbiter Test Register */ /* Bit 7.. 6: reserved */ #define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */ #define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */ @@ -1360,22 +1703,22 @@ extern "C" { #define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */ #define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */ -/* TXA_STAT 8 bit Tx Arbiter Status Register */ +/* TXA_STAT 8 bit Tx Arbiter Status Register */ /* Bit 7.. 1: reserved */ #define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */ -/* Q_BC 32 bit Current Byte Counter */ +/* Q_BC 32 bit Current Byte Counter */ /* Bit 31..16: reserved */ #define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */ -/* BMU Control Status Registers */ -/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ -/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ -/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ -/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ -/* Q_CSR 32 bit BMU Control/Status Register */ +/* BMU Control / Status Registers (Yukon and Genesis) */ +/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ +/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ +/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ +/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ +/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ +/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ +/* Q_CSR 32 bit BMU Control/Status Register */ /* Bit 31..25: reserved */ #define CSR_SV_IDLE BIT_24 /* BMU SM Idle */ /* Bit 23..22: reserved */ @@ -1409,28 +1752,63 @@ extern "C" { CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ CSR_TRANS_RUN) -/* Q_F 32 bit Flag Register */ +/* Rx BMU Control / Status Registers (Yukon-2) */ +#define BMU_IDLE BIT_31 /* BMU Idle State */ +#define BMU_RX_TCP_PKT BIT_30 /* Rx TCP Packet (when RSS Hash enabled) */ +#define BMU_RX_IP_PKT BIT_29 /* Rx IP Packet (when RSS Hash enabled) */ + /* Bit 28..16: reserved */ +#define BMU_ENA_RX_RSS_HASH BIT_15 /* Enable Rx RSS Hash */ +#define BMU_DIS_RX_RSS_HASH BIT_14 /* Disable Rx RSS Hash */ +#define BMU_ENA_RX_CHKSUM BIT_13 /* Enable Rx TCP/IP Checksum Check */ +#define BMU_DIS_RX_CHKSUM BIT_12 /* Disable Rx TCP/IP Checksum Check */ +#define BMU_CLR_IRQ_PAR BIT_11 /* Clear IRQ on Parity errors (Rx) */ +#define BMU_CLR_IRQ_TCP BIT_11 /* Clear IRQ on TCP segmen. error (Tx) */ +#define BMU_CLR_IRQ_CHK BIT_10 /* Clear IRQ Check */ +#define BMU_STOP BIT_9 /* Stop Rx/Tx Queue */ +#define BMU_START BIT_8 /* Start Rx/Tx Queue */ +#define BMU_FIFO_OP_ON BIT_7 /* FIFO Operational On */ +#define BMU_FIFO_OP_OFF BIT_6 /* FIFO Operational Off */ +#define BMU_FIFO_ENA BIT_5 /* Enable FIFO */ +#define BMU_FIFO_RST BIT_4 /* Reset FIFO */ +#define BMU_OP_ON BIT_3 /* BMU Operational On */ +#define BMU_OP_OFF BIT_2 /* BMU Operational Off */ +#define BMU_RST_CLR BIT_1 /* Clear BMU Reset (Enable) */ +#define BMU_RST_SET BIT_0 /* Set BMU Reset */ + +#define BMU_CLR_RESET (BMU_FIFO_RST | BMU_OP_OFF | BMU_RST_CLR) +#define BMU_OPER_INIT (BMU_CLR_IRQ_PAR | BMU_CLR_IRQ_CHK | BMU_START | \ + BMU_FIFO_ENA | BMU_OP_ON) + +/* Tx BMU Control / Status Registers (Yukon-2) */ + /* Bit 31: same as for Rx */ + /* Bit 30..14: reserved */ +#define BMU_TX_IPIDINCR_ON BIT_13 /* Enable IP ID Increment */ +#define BMU_TX_IPIDINCR_OFF BIT_12 /* Disable IP ID Increment */ +#define BMU_TX_CLR_IRQ_TCP BIT_11 /* Clear IRQ on TCP segm. length mism. */ + /* Bit 10..0: same as for Rx */ + +/* Q_F 32 bit Flag Register */ /* Bit 31..28: reserved */ #define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */ #define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ #define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */ #define F_WM_REACHED BIT_25 /* Watermark reached */ - /* reserved */ +#define F_M_RX_RAM_DIS BIT_24 /* MAC Rx RAM Read Port disable */ #define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */ /* Bit 15..11: reserved */ #define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */ -/* Q_T1 32 bit Test Register 1 */ +/* Q_T1 32 bit Test Register 1 */ /* Holds four State Machine control Bytes */ -#define SM_CRTL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ -#define SM_CRTL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ -#define SM_CRTL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ -#define SM_CRTL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ +#define SM_CTRL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ +#define SM_CTRL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ +#define SM_CTRL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ +#define SM_CTRL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ -/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ -/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ -/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ -/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ +/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ +/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ +/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ +/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ /* The control status byte of each machine looks like ... */ #define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */ @@ -1440,7 +1818,7 @@ extern "C" { #define SM_STEP BIT_0S /* Step the State Machine */ /* The encoding of the states is not supported by the Diagnostics Tool */ -/* Q_T2 32 bit Test Register 2 */ +/* Q_T2 32 bit Test Register 2 */ /* Bit 31.. 8: reserved */ #define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */ #define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */ @@ -1451,45 +1829,52 @@ extern "C" { #define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */ #define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */ -/* Q_T3 32 bit Test Register 3 */ +/* Q_T3 32 bit Test Register 3 */ /* Bit 31.. 7: reserved */ #define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */ /* Bit 3: reserved */ #define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */ +/* Queue Prefetch Unit Offsets, use Y2_PREF_Q_ADDR() to address (Yukon-2 only)*/ +/* PREF_UNIT_CTRL_REG 32 bit Prefetch Control register */ +#define PREF_UNIT_OP_ON BIT_3 /* prefetch unit operational */ +#define PREF_UNIT_OP_OFF BIT_2 /* prefetch unit not operational */ +#define PREF_UNIT_RST_CLR BIT_1 /* Clear Prefetch Unit Reset */ +#define PREF_UNIT_RST_SET BIT_0 /* Set Prefetch Unit Reset */ + /* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ -/* RB_START 32 bit RAM Buffer Start Address */ -/* RB_END 32 bit RAM Buffer End Address */ -/* RB_WP 32 bit RAM Buffer Write Pointer */ -/* RB_RP 32 bit RAM Buffer Read Pointer */ -/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ -/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ -/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ -/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ -/* RB_PC 32 bit RAM Buffer Packet Counter */ -/* RB_LEV 32 bit RAM Buffer Level Register */ +/* RB_START 32 bit RAM Buffer Start Address */ +/* RB_END 32 bit RAM Buffer End Address */ +/* RB_WP 32 bit RAM Buffer Write Pointer */ +/* RB_RP 32 bit RAM Buffer Read Pointer */ +/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ +/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ +/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ +/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ +/* RB_PC 32 bit RAM Buffer Packet Counter */ +/* RB_LEV 32 bit RAM Buffer Level Register */ /* Bit 31..19: reserved */ #define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ /* RB_TST2 8 bit RAM Buffer Test Register 2 */ - /* Bit 7.. 4: reserved */ -#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */ + /* Bit 7.. 4: reserved */ +#define RB_PC_DEC BIT_3S /* Packet Counter Decrement */ #define RB_PC_T_ON BIT_2S /* Packet Counter Test On */ -#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */ -#define RB_PC_INC BIT_0S /* Packet Counter Increm */ +#define RB_PC_T_OFF BIT_1S /* Packet Counter Test Off */ +#define RB_PC_INC BIT_0S /* Packet Counter Increment */ /* RB_TST1 8 bit RAM Buffer Test Register 1 */ /* Bit 7: reserved */ #define RB_WP_T_ON BIT_6S /* Write Pointer Test On */ #define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define RB_WP_INC BIT_4S /* Write Pointer Increm */ +#define RB_WP_INC BIT_4S /* Write Pointer Increment */ /* Bit 3: reserved */ #define RB_RP_T_ON BIT_2S /* Read Pointer Test On */ #define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */ -#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */ +#define RB_RP_INC BIT_0S /* Read Pointer Increment */ /* RB_CTRL 8 bit RAM Buffer Control Register */ - /* Bit 7.. 6: reserved */ + /* Bit 7.. 6: reserved */ #define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */ #define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */ #define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */ @@ -1497,20 +1882,35 @@ extern "C" { #define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */ #define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */ +/* Yukon-2 */ + /* Bit 31..20: reserved */ +#define RB_CNT_DOWN BIT_19 /* Packet Counter Decrement */ +#define RB_CNT_TST_ON BIT_18 /* Packet Counter Test On */ +#define RB_CNT_TST_OFF BIT_17 /* Packet Counter Test Off */ +#define RB_CNT_UP BIT_16 /* Packet Counter Increment */ + /* Bit 15: reserved */ +#define RB_WP_TST_ON BIT_14 /* Write Pointer Test On */ +#define RB_WP_TST_OFF BIT_13 /* Write Pointer Test Off */ +#define RB_WP_UP BIT_12 /* Write Pointer Increment */ + /* Bit 11: reserved */ +#define RB_RP_TST_ON BIT_10 /* Read Pointer Test On */ +#define RB_RP_TST_OFF BIT_9 /* Read Pointer Test Off */ +#define RB_RP_UP BIT_8 /* Read Pointer Increment */ + /* Receive and Transmit MAC FIFO Registers (GENESIS only) */ -/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ -/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ -/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ -/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ -/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ -/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ -/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ -/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ -/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ -/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ -/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ +/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ +/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ +/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ +/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ +/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ +/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ +/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ +/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ +/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ +/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ +/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ /* Bit 31.. 6: reserved */ #define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */ @@ -1556,9 +1956,9 @@ extern "C" { /* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ /* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ /* Bit 7: reserved */ -#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */ -#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */ -#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */ +#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Pointer Test On */ +#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Pointer Test Off */ +#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Pointer Increment */ #define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */ #define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */ #define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */ @@ -1569,7 +1969,7 @@ extern "C" { /* Bit 7: reserved */ #define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */ #define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define MFF_WP_INC BIT_4S /* Write Pointer Increm */ +#define MFF_WP_INC BIT_4S /* Write Pointer Increment */ /* Bit 3: reserved */ #define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */ #define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */ @@ -1588,12 +1988,16 @@ extern "C" { /* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ /* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ + /* Bit 7.. 3: reserved */ +#define LED_START BIT_2S /* Start Counter */ +#define LED_STOP BIT_1S /* Stop Counter */ +#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED On */ + /* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ /* Bit 7.. 3: reserved */ -#define LED_START BIT_2S /* Start Timer */ -#define LED_STOP BIT_1S /* Stop Timer */ -#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */ -#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */ +#define LNK_START BIT_2S /* Start Counter */ +#define LNK_STOP BIT_1S /* Stop Counter */ +#define LNK_CLR_IRQ BIT_0S /* Clear Link IRQ */ /* RX_LED_TST 8 bit Receive LED Cnt Test Register */ /* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ @@ -1604,86 +2008,142 @@ extern "C" { #define LED_T_STEP BIT_0S /* LED Counter Step */ /* LNK_LED_REG 8 bit Link LED Register */ - /* Bit 7.. 6: reserved */ + /* Bit 7.. 6: reserved */ #define LED_BLK_ON BIT_5S /* Link LED Blinking On */ #define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */ #define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */ #define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */ -#define LED_ON BIT_1S /* switch LED on */ -#define LED_OFF BIT_0S /* switch LED off */ +#define LED_ON BIT_1S /* Switch LED On */ +#define LED_OFF BIT_0S /* Switch LED Off */ /* Receive and Transmit GMAC FIFO Registers (YUKON only) */ /* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */ /* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */ -/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */ -/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */ -/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */ -/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */ +/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */ +/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */ +/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */ +/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */ /* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ /* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ -/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */ -/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */ -/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */ -/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */ -/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */ +/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */ +/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Pointer */ +/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */ +/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */ +/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */ +/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */ /* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ - /* Bits 31..15: reserved */ -#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */ -#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */ -#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */ + /* Bit 31..28 reserved */ +#define RX_TRUNC_ON BIT_27 /* Enable Packet Truncation */ +#define RX_TRUNC_OFF BIT_26 /* Disable Packet Truncation */ +#define RX_VLAN_STRIP_ON BIT_25 /* Enable VLAN Stripping */ +#define RX_VLAN_STRIP_OFF BIT_24 /* Disable VLAN Stripping */ + /* Bit 23..15 reserved */ +#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */ +#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */ +#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */ /* Bit 11: reserved */ -#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */ -#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */ -#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */ -#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */ -#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */ -#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */ -#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */ -#define GMF_OPER_ON BIT_3 /* Operational Mode On */ -#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */ -#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */ -#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */ +#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */ +#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */ +#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */ +#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */ +#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */ +#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */ +#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */ +#define GMF_OPER_ON BIT_3 /* Operational Mode On */ +#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */ +#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */ +#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */ -/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ - /* Bits 31..19: reserved */ -#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */ -#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */ -#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */ - /* Bits 15..7: same as for RX_GMF_CTRL_T */ -#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */ -#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */ -#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */ +/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test (YUKON and Yukon-2) */ +#define TX_STFW_DIS BIT_31 /* Disable Store & Forward (Yukon-EC Ultra) */ +#define TX_STFW_ENA BIT_30 /* Enable Store & Forward (Yukon-EC Ultra) */ + /* Bits 29..26: reserved */ +#define TX_VLAN_TAG_ON BIT_25 /* Enable VLAN tagging */ +#define TX_VLAN_TAG_OFF BIT_24 /* Disable VLAN tagging */ +#define TX_PCI_JUM_ENA BIT_23 /* Enable PCI Jumbo Mode (Yukon-EC Ultra) */ +#define TX_PCI_JUM_DIS BIT_22 /* Disable PCI Jumbo Mode (Yukon-EC Ultra) */ + /* Bits 21..19: reserved */ +#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */ +#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */ +#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */ + /* Bits 15..8: same as for RX_GMF_CTRL_T */ + /* Bit 7: reserved */ +#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */ +#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */ +#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */ /* Bits 3..0: same as for RX_GMF_CTRL_T */ #define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON) #define GMF_TX_CTRL_DEF GMF_OPER_ON +#define RX_GMF_AF_THR_MIN 0x0c /* Rx GMAC FIFO Almost Full Thresh. min. */ #define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */ -/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ - /* Bit 7.. 3: reserved */ -#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */ -#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */ -#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */ +/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ + /* Bit 7.. 3: reserved */ +#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */ +#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */ +#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */ +/* POLL_CTRL 32 bit Polling Unit control register (Yukon-2 only) */ + /* Bit 31.. 6: reserved */ +#define PC_CLR_IRQ_CHK BIT_5 /* Clear IRQ Check */ +#define PC_POLL_RQ BIT_4 /* Poll Request Start */ +#define PC_POLL_OP_ON BIT_3 /* Operational Mode On */ +#define PC_POLL_OP_OFF BIT_2 /* Operational Mode Off */ +#define PC_POLL_RST_CLR BIT_1 /* Clear Polling Unit Reset (Enable) */ +#define PC_POLL_RST_SET BIT_0 /* Set Polling Unit Reset */ + + +/* The bit definition of the following registers is still missing! */ +/* B28_Y2_SMB_CONFIG 32 bit ASF SMBus Config Register */ +/* B28_Y2_SMB_CSD_REG 32 bit ASF SMB Control/Status/Data */ +/* B28_Y2_ASF_IRQ_V_BASE 32 bit ASF IRQ Vector Base */ + +/* B28_Y2_ASF_STAT_CMD 32 bit ASF Status and Command Reg */ +/* This register is used by the host driver software */ + /* Bit 31.. 5 reserved */ +#define Y2_ASF_OS_PRES BIT_4S /* ASF operation system present */ +#define Y2_ASF_RESET BIT_3S /* ASF system in reset state */ +#define Y2_ASF_RUNNING BIT_2S /* ASF system operational */ +#define Y2_ASF_CLR_HSTI BIT_1S /* Clear ASF IRQ */ +#define Y2_ASF_IRQ BIT_0S /* Issue an IRQ to ASF system */ + +#define Y2_ASF_UC_STATE (3<<2) /* ASF uC State */ +#define Y2_ASF_CLK_HALT 0 /* ASF system clock stopped */ + +/* B28_Y2_ASF_HOST_COM 32 bit ASF Host Communication Reg */ +/* This register is used by the ASF firmware */ + /* Bit 31.. 2 reserved */ +#define Y2_ASF_CLR_ASFI BIT_1 /* Clear host IRQ */ +#define Y2_ASF_HOST_IRQ BIT_0 /* Issue an IRQ to HOST system */ + + +/* STAT_CTRL 32 bit Status BMU control register (Yukon-2 only) */ + /* Bit 7.. 5: reserved */ +#define SC_STAT_CLR_IRQ BIT_4 /* Status Burst IRQ clear */ +#define SC_STAT_OP_ON BIT_3 /* Operational Mode On */ +#define SC_STAT_OP_OFF BIT_2 /* Operational Mode Off */ +#define SC_STAT_RST_CLR BIT_1 /* Clear Status Unit Reset (Enable) */ +#define SC_STAT_RST_SET BIT_0 /* Set Status Unit Reset */ + /* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ /* Bits 31.. 8: reserved */ -#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */ -#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */ -#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */ -#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */ -#define GMC_PAUSE_ON BIT_3 /* Pause On */ -#define GMC_PAUSE_OFF BIT_2 /* Pause Off */ -#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */ -#define GMC_RST_SET BIT_0 /* Set GMAC Reset */ +#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */ +#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */ +#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */ +#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */ +#define GMC_PAUSE_ON BIT_3 /* Pause On */ +#define GMC_PAUSE_OFF BIT_2 /* Pause Off */ +#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */ +#define GMC_RST_SET BIT_0 /* Set GMAC Reset */ /* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ /* Bits 31..29: reserved */ #define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */ -#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */ +#define GPC_INT_POL BIT_27 /* IRQ Polarity is Active Low */ #define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */ #define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */ #define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */ @@ -1698,15 +2158,24 @@ extern "C" { #define GPC_ANEG_2 BIT_15 /* ANEG[2] */ #define GPC_ANEG_1 BIT_14 /* ANEG[1] */ #define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */ -#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */ -#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */ -#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */ -#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */ -#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */ +#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of PHY Addr */ +#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of PHY Addr */ +#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of PHY Addr */ +#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of PHY Addr */ +#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of PHY Addr */ /* Bits 7..2: reserved */ #define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */ #define GPC_RST_SET BIT_0 /* Set GPHY Reset */ +/* Yukon-EC Ultra only */ +#define GPC_LED_CONF_MSK (7<<6) /* Bit 8.. 6: GPHY LED Config */ +#define GPC_PD_125M_CLK_OFF BIT_5 /* Disable Power Down Clock 125 MHz */ +#define GPC_PD_125M_CLK_ON BIT_4 /* Enable Power Down Clock 125 MHz */ +#define GPC_DPLL_RST_SET BIT_3 /* Set GPHY's DPLL Reset */ +#define GPC_DPLL_RST_CLR BIT_2 /* Clear GPHY's DPLL Reset */ + /* (DPLL = Digital Phase Lock Loop) */ +#define GPC_LED_CONF_VAL(x) (SHIFT6(x) & GPC_LED_CONF_MSK) + #define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \ GPC_HWCFG_M_1 | GPC_HWCFG_M_0) @@ -1737,23 +2206,23 @@ extern "C" { /* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ /* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ -#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */ -#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */ -#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */ -#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */ -#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */ -#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */ +#define GM_IS_RX_CO_OV BIT_5S /* Receive Counter Overflow IRQ */ +#define GM_IS_TX_CO_OV BIT_4S /* Transmit Counter Overflow IRQ */ +#define GM_IS_TX_FF_UR BIT_3S /* Transmit FIFO Underrun */ +#define GM_IS_TX_COMPL BIT_2S /* Frame Transmission Complete */ +#define GM_IS_RX_FF_OR BIT_1S /* Receive FIFO Overrun */ +#define GM_IS_RX_COMPL BIT_0S /* Frame Reception Complete */ -#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \ +#define GMAC_DEF_MSK (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV | \ GM_IS_TX_FF_UR) -/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ +/* GMAC_LINK_CTRL 16 bit Link Control Reg (YUKON only) */ /* Bits 15.. 2: reserved */ -#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */ -#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */ +#define GMLC_RST_CLR BIT_1S /* Clear Link Reset */ +#define GMLC_RST_SET BIT_0S /* Set Link Reset */ -/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ +/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ #define WOL_CTL_LINK_CHG_OCC BIT_15S #define WOL_CTL_MAGIC_PKT_OCC BIT_14S #define WOL_CTL_PATTERN_OCC BIT_13S @@ -1776,15 +2245,19 @@ extern "C" { #define WOL_CTL_DEFAULT \ (WOL_CTL_DIS_PME_ON_LINK_CHG | \ - WOL_CTL_DIS_PME_ON_PATTERN | \ - WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ - WOL_CTL_DIS_LINK_CHG_UNIT | \ - WOL_CTL_DIS_PATTERN_UNIT | \ - WOL_CTL_DIS_MAGIC_PKT_UNIT) + WOL_CTL_DIS_PME_ON_PATTERN | \ + WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ + WOL_CTL_DIS_LINK_CHG_UNIT | \ + WOL_CTL_DIS_PATTERN_UNIT | \ + WOL_CTL_DIS_MAGIC_PKT_UNIT) -/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ +/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ #define WOL_CTL_PATT_ENA(x) (BIT_0 << (x)) +/* WOL_PATT_PME 8 bit WOL PME Match Enable (Yukon-2) */ +#define WOL_PATT_FORCE_PME BIT_7 /* Generates a PME */ +#define WOL_PATT_MATCH_PME_ALL 0x7f + #define SK_NUM_WOL_PATTERN 7 #define SK_PATTERN_PER_WORD 4 #define SK_BITMASK_PATTERN 7 @@ -1794,60 +2267,296 @@ extern "C" { #define WOL_LENGTH_SHIFT 8 +/* typedefs ******************************************************************/ + /* Receive and Transmit Descriptors ******************************************/ /* Transmit Descriptor struct */ typedef struct s_HwTxd { SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */ SK_U32 TxNext; /* Physical Address Pointer to the next TxD */ - SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */ - SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */ + SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower DWord */ + SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper DWord */ SK_U32 TxStat; /* Transmit Frame Status Word */ -#ifndef SK_USE_REV_DESC +#ifndef SK_USE_REV_DESC SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ SK_U16 TxRes1; /* 16 bit reserved field */ SK_U16 TxTcpWp; /* TCP Checksum Write Position */ SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ -#else /* SK_USE_REV_DESC */ +#else /* SK_USE_REV_DESC */ SK_U16 TxRes1; /* 16 bit reserved field */ SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ SK_U16 TxTcpWp; /* TCP Checksum Write Position */ -#endif /* SK_USE_REV_DESC */ +#endif /* SK_USE_REV_DESC */ SK_U32 TxRes2; /* 32 bit reserved field */ -} SK_HWTXD; +} __attribute__ ((packed)) SK_HWTXD; /* Marvell - uboot: should be packed */ /* Receive Descriptor struct */ typedef struct s_HwRxd { SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */ SK_U32 RxNext; /* Physical Address Pointer to the next RxD */ - SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */ - SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */ + SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower DWord */ + SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper DWord */ SK_U32 RxStat; /* Receive Frame Status Word */ SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */ -#ifndef SK_USE_REV_DESC - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ +#ifndef SK_USE_REV_DESC + SK_U16 RxTcpSum1; /* Rx TCP Checksum 1 */ + SK_U16 RxTcpSum2; /* Rx TCP Checksum 2 */ SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ -#else /* SK_USE_REV_DESC */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ +#else /* SK_USE_REV_DESC */ + SK_U16 RxTcpSum2; /* Rx TCP Checksum 2 */ + SK_U16 RxTcpSum1; /* Rx TCP Checksum 1 */ SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ -#endif /* SK_USE_REV_DESC */ -} SK_HWRXD; +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWRXD;/* Marvell - uboot: should be packed */ /* * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2) * should set the define SK_USE_REV_DESC. - * Structures are 'normaly' not endianess dependent. But in - * this case the SK_U16 fields are bound to bit positions inside the - * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord. + * Structures are 'normally' not endianess dependent. But in this case + * the SK_U16 fields are bound to bit positions inside the descriptor. + * RxTcpSum1 e.g. must start at bit 0 within the 7.th DWord. * The bit positions inside a DWord are of course endianess dependent and - * swaps if the DWord is swapped by the hardware. + * swap if the DWord is swapped by the hardware. */ +/* YUKON-2 descriptors ******************************************************/ + +typedef struct _TxChksum { +#ifndef SK_USE_REV_DESC + SK_U16 TxTcpWp; /* TCP Checksum Write Position */ + SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ +#else /* SK_USE_REV_DESC */ + SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ + SK_U16 TxTcpWp; /* TCP Checksum Write Position */ +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWTXCS;/* Marvell - uboot: should be packed */ + +typedef struct _LargeSend { +#ifndef SK_USE_REV_DESC + SK_U16 Length; /* Large Send Segment Length */ + SK_U16 Reserved; /* reserved */ +#else /* SK_USE_REV_DESC */ + SK_U16 Reserved; /* reserved */ + SK_U16 Length; /* Large Send Segment Length */ +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWTXLS;/* Marvell - uboot: should be packed */ + +typedef union u_HwTxBuf { + SK_U16 BufLen; /* Tx Buffer Length */ + SK_U16 VlanTag; /* VLAN Tag */ + SK_U16 InitCsum; /* Init. Checksum */ +} __attribute__ ((packed)) SK_HWTXBUF;/* Marvell - uboot: should be packed */ + + +/* Tx List Element structure */ +typedef struct s_HwLeTx { + union { + SK_U32 BufAddr; /* Tx LE Buffer Address high/low */ + SK_HWTXCS ChkSum; /* Tx LE TCP Checksum parameters */ + SK_HWTXLS LargeSend;/* Large Send length */ + } __attribute__ ((packed)) TxUn;/* Marvell - uboot: should be packed */ +#ifndef SK_USE_REV_DESC + SK_HWTXBUF Send; + SK_U8 ControlFlags; /* Tx LE Control field or Lock Number */ + SK_U8 Opcode; /* Tx LE Opcode field */ +#else /* SK_USE_REV_DESC */ + SK_U8 Opcode; /* Tx LE Opcode field */ + SK_U8 ControlFlags; /* Tx LE Control field or Lock Number */ + SK_HWTXBUF Send; +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWLETX;/* Marvell - uboot: should be packed */ + +typedef struct _RxChkSum{ +#ifndef SK_USE_REV_DESC + SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ + SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ +#else /* SK_USE_REV_DESC */ + SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ + SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWRXCS;/* Marvell - uboot: should be packed */ + +/* Rx List Element structure */ +typedef struct s_HwLeRx { + union { + SK_U32 BufAddr; /* Rx LE Buffer Address high/low */ + SK_HWRXCS ChkSum; /* Rx LE TCP Checksum parameters */ + } __attribute__ ((packed))RxUn;/* Marvell - uboot: should be packed */ +#ifndef SK_USE_REV_DESC + SK_U16 BufferLength; /* Rx LE Buffer Length field */ + SK_U8 ControlFlags; /* Rx LE Control field */ + SK_U8 Opcode; /* Rx LE Opcode field */ +#else /* SK_USE_REV_DESC */ + SK_U8 Opcode; /* Rx LE Opcode field */ + SK_U8 ControlFlags; /* Rx LE Control field */ + SK_U16 BufferLength; /* Rx LE Buffer Length field */ +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWLERX;/* Marvell - uboot: should be packed */ + +typedef struct s_StRxTCPChkSum { +#ifndef SK_USE_REV_DESC + SK_U16 RxTCPSum1; /* Rx TCP Checksum 1 */ + SK_U16 RxTCPSum2; /* Rx TCP Checksum 2 */ +#else /* SK_USE_REV_DESC */ + SK_U16 RxTCPSum2; /* Rx TCP Checksum 2 */ + SK_U16 RxTCPSum1; /* Rx TCP Checksum 1 */ +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWSTCS;/* Marvell - uboot: should be packed */ + +typedef struct s_StRxRssFlags { +#ifndef SK_USE_REV_DESC + SK_U8 FlagField; /* contains TCP and IP flags */ + SK_U8 reserved; /* reserved */ +#else /* SK_USE_REV_DESC */ + SK_U8 reserved; /* reserved */ + SK_U8 FlagField; /* contains TCP and IP flags */ +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWSTRSS;/* Marvell - uboot: should be packed */ + +/* bit definition of RSS LE bit 32/33 (SK_HWSTRSS.FlagField) */ + /* bit 7..2 reserved */ +#define RSS_TCP_FLAG BIT_1S /* RSS value related to TCP area */ +#define RSS_IP_FLAG BIT_0S /* RSS value related to IP area */ +/* StRxRssValue is valid if at least RSS_IP_FLAG is set */ +/* For protocol errors or other protocols an empty RSS LE is generated */ + +typedef union u_HwStBuf { + SK_U16 BufLen; /* Rx Buffer Length */ + SK_U16 VlanTag; /* VLAN Tag */ + SK_U16 StTxStatHi; /* Tx Queue Status (high) */ + SK_HWSTRSS Rss; /* Flag Field for TCP and IP protocol */ +} __attribute__ ((packed)) SK_HWSTBUF;/* Marvell - uboot: should be packed */ + +/* Status List Element structure */ +typedef struct s_HwLeSt { + union { + SK_U32 StRxStatWord; /* Rx Status Dword */ + SK_U32 StRxTimeStamp; /* Rx Timestamp */ + SK_HWSTCS StRxTCPCSum; /* Rx TCP Checksum */ + SK_U32 StTxStatLow; /* Tx Queue Status (low) */ + SK_U32 StRxRssValue; /* Rx RSS value */ + } __attribute__ ((packed)) StUn;/* Marvell - uboot: should be packed */ +#ifndef SK_USE_REV_DESC + SK_HWSTBUF Stat; + SK_U8 Link; /* Status LE Link field */ + SK_U8 Opcode; /* Status LE Opcode field */ +#else /* SK_USE_REV_DESC */ + SK_U8 Opcode; /* Status LE Opcode field */ + SK_U8 Link; /* Status LE Link field */ + SK_HWSTBUF Stat; +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWLEST;/* Marvell - uboot: should be packed */ + +/* Special Action List Element */ +typedef struct s_HwLeSa { +#ifndef SK_USE_REV_DESC + SK_U16 TxAIdxVld; /* Special Action LE TxA Put Index field */ + SK_U16 TxSIdxVld; /* Special Action LE TxS Put Index field */ + SK_U16 RxIdxVld; /* Special Action LE Rx Put Index field */ + SK_U8 Link; /* Special Action LE Link field */ + SK_U8 Opcode; /* Special Action LE Opcode field */ +#else /* SK_USE_REV_DESC */ + SK_U16 TxSIdxVld; /* Special Action LE TxS Put Index field */ + SK_U16 TxAIdxVld; /* Special Action LE TxA Put Index field */ + SK_U8 Opcode; /* Special Action LE Opcode field */ + SK_U8 Link; /* Special Action LE Link field */ + SK_U16 RxIdxVld; /* Special Action LE Rx Put Index field */ +#endif /* SK_USE_REV_DESC */ +} __attribute__ ((packed)) SK_HWLESA;/* Marvell - uboot: should be packed */ + +/* Common List Element union */ +typedef union u_HwLeTxRxSt { + /* Transmit List Element Structure */ + SK_HWLETX Tx; + /* Receive List Element Structure */ + SK_HWLERX Rx; + /* Status List Element Structure */ + SK_HWLEST St; + /* Special Action List Element Structure */ + SK_HWLESA Sa; + /* Full List Element */ + SK_U64 Full; +} SK_HWLE;__attribute__ ((packed)) SK_HWLE;/* Marvell - uboot: should be packed */ + +/* mask and shift value to get Tx async queue status for port 1 */ +#define STLE_TXA1_MSKL 0x00000fff +#define STLE_TXA1_SHIFTL 0 + +/* mask and shift value to get Tx sync queue status for port 1 */ +#define STLE_TXS1_MSKL 0x00fff000 +#define STLE_TXS1_SHIFTL 12 + +/* mask and shift value to get Tx async queue status for port 2 */ +#define STLE_TXA2_MSKL 0xff000000 +#define STLE_TXA2_SHIFTL 24 +#define STLE_TXA2_MSKH 0x000f +/* this one shifts up */ +#define STLE_TXA2_SHIFTH 8 + +/* mask and shift value to get Tx sync queue status for port 2 */ +#define STLE_TXS2_MSKL 0x00000000 +#define STLE_TXS2_SHIFTL 0 +#define STLE_TXS2_MSKH 0xfff0 +#define STLE_TXS2_SHIFTH 4 + +/* YUKON-2 bit values */ +#define HW_OWNER BIT_7 +#define SW_OWNER 0 + +#define PU_PUTIDX_VALID BIT_12 + +/* YUKON-2 Control flags */ +#define UDPTCP BIT_0S +#define CALSUM BIT_1S +#define WR_SUM BIT_2S +#define INIT_SUM BIT_3S +#define LOCK_SUM BIT_4S +#define INS_VLAN BIT_5S +#define FRC_STAT BIT_6S +#define EOP BIT_7S + +#define TX_LOCK BIT_8S +#define BUF_SEND BIT_9S +#define PACKET_SEND BIT_10S + +#define NO_WARNING BIT_14S +#define NO_UPDATE BIT_15S + +/* YUKON-2 Rx/Tx opcodes defines */ +#define OP_TCPWRITE 0x11 +#define OP_TCPSTART 0x12 +#define OP_TCPINIT 0x14 +#define OP_TCPLCK 0x18 +#define OP_TCPCHKSUM OP_TCPSTART +#define OP_TCPIS (OP_TCPINIT | OP_TCPSTART) +#define OP_TCPLW (OP_TCPLCK | OP_TCPWRITE) +#define OP_TCPLSW (OP_TCPLCK | OP_TCPSTART | OP_TCPWRITE) +#define OP_TCPLISW (OP_TCPLCK | OP_TCPINIT | OP_TCPSTART | OP_TCPWRITE) +#define OP_ADDR64 0x21 +#define OP_VLAN 0x22 +#define OP_ADDR64VLAN (OP_ADDR64 | OP_VLAN) +#define OP_LRGLEN 0x24 +#define OP_LRGLENVLAN (OP_LRGLEN | OP_VLAN) +#define OP_BUFFER 0x40 +#define OP_PACKET 0x41 +#define OP_LARGESEND 0x43 + +/* YUKON-2 STATUS opcodes defines */ +#define OP_RXSTAT 0x60 +#define OP_RXTIMESTAMP 0x61 +#define OP_RXVLAN 0x62 +#define OP_RXCHKS 0x64 +#define OP_RXCHKSVLAN (OP_RXCHKS | OP_RXVLAN) +#define OP_RXTIMEVLAN (OP_RXTIMESTAMP | OP_RXVLAN) +#define OP_RSS_HASH 0x65 +#define OP_TXINDEXLE 0x68 + +/* YUKON-2 SPECIAL opcodes defines */ +#define OP_PUTIDX 0x70 /* Descriptor Bit Definition */ /* TxCtrl Transmit Buffer Control Field */ @@ -1869,7 +2578,7 @@ typedef struct s_HwRxd { #define BMU_CHECK (0x55L<<16) /* Default BMU check */ #define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */ #define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */ -#define BMU_BBC 0xFFFFL /* Bit 15.. 0: Buffer Byte Counter */ +#define BMU_BBC 0xffffL /* Bit 15.. 0: Buffer Byte Counter */ /* TxStat Transmit Frame Status Word */ /* RxStat Receive Frame Status Word */ @@ -1880,20 +2589,13 @@ typedef struct s_HwRxd { * (see XMR_FS bits) */ -/* other defines *************************************************************/ - -/* - * FlashProm specification - */ -#define MAX_PAGES 0x20000L /* Every byte has a single page */ -#define MAX_FADDR 1 /* 1 byte per page */ -#define SKFDDI_PSZ 8 /* address PROM size */ - /* macros ********************************************************************/ -/* - * Receive and Transmit Queues - */ +/* Macro for accessing the key registers */ +#define RSS_KEY_ADDR(Port, KeyIndex) \ + ((B4_RSS_KEY | ( ((Port) == 0) ? 0 : 0x80)) + (KeyIndex)) + +/* Receive and Transmit Queues */ #define Q_R1 0x0000 /* Receive Queue 1 */ #define Q_R2 0x0080 /* Receive Queue 2 */ #define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */ @@ -1901,6 +2603,10 @@ typedef struct s_HwRxd { #define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */ #define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */ +#define Q_ASF_R1 0x100 /* ASF Rx Queue 1 */ +#define Q_ASF_R2 0x180 /* ASF Rx Queue 2 */ +#define Q_ASF_T1 0x140 /* ASF Tx Queue 1 */ +#define Q_ASF_T2 0x1c0 /* ASF Tx Queue 2 */ /* * Macro Q_ADDR() * @@ -1912,10 +2618,26 @@ typedef struct s_HwRxd { * Offs Queue register offset. * Values: Q_D, Q_DA_L ... Q_T2, Q_T3 * - * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal) + * usage SK_IN32(IoC, Q_ADDR(Q_R2, Q_BC), pVal) */ #define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs)) +/* + * Macro Y2_PREF_Q_ADDR() + * + * Use this macro to access the Prefetch Units of the receive and + * transmit queues of Yukon-2. + * + * para: + * Queue Queue to access. + * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, Q_XA2, + * Offs Queue register offset. + * Values: PREF_UNIT_CTRL_REG ... PREF_UNIT_FIFO_LEV_REG + * + * usage SK_IN16(IoC, Y2_Q_ADDR(Q_R2, PREF_UNIT_GET_IDX_REG), pVal) + */ +#define Y2_PREF_Q_ADDR(Queue, Offs) (Y2_B8_PREF_REGS + (Queue) + (Offs)) + /* * Macro RB_ADDR() * @@ -1927,16 +2649,14 @@ typedef struct s_HwRxd { * Offs Queue register offset. * Values: RB_START, RB_END ... RB_LEV, RB_CTRL * - * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal) + * usage SK_IN32(IoC, RB_ADDR(Q_R2, RB_RP), pVal) */ #define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs)) -/* - * MAC Related Registers - */ -#define MAC_1 0 /* belongs to the port near the slot */ -#define MAC_2 1 /* belongs to the port far away from the slot */ +/* MAC Related Registers */ +#define MAC_1 0 /* 1st port */ +#define MAC_2 1 /* 2nd port */ /* * Macro MR_ADDR() @@ -1950,19 +2670,10 @@ typedef struct s_HwRxd { * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG, * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST * - * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal) + * usage SK_IN32(IoC, MR_ADDR(MAC_1, TX_MFF_EA), pVal) */ #define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs)) -#ifdef SK_LITTLE_ENDIAN -#define XM_WORD_LO 0 -#define XM_WORD_HI 1 -#else /* !SK_LITTLE_ENDIAN */ -#define XM_WORD_LO 1 -#define XM_WORD_HI 0 -#endif /* !SK_LITTLE_ENDIAN */ - - /* * macros to access the XMAC (GENESIS only) * @@ -1987,22 +2698,31 @@ typedef struct s_HwRxd { #define XMA(Mac, Reg) \ ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1)) -#define XM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), XMA((Mac), (Reg)), (pVal)) +#define XM_IN16(IoC, Mac, Reg, pVal) \ + SK_IN16(IoC, XMA(Mac, Reg), pVal) -#define XM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (Val)) +#define XM_OUT16(IoC, Mac, Reg, Val) \ + SK_OUT16(IoC, XMA(Mac, Reg), Val) -#define XM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), XMA((Mac), (Reg)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_HI]); \ +#ifdef SK_LITTLE_ENDIAN + +#define XM_IN32(IoC, Mac, Reg, pVal) { \ + SK_IN16(IoC, XMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal)); \ + SK_IN16(IoC, XMA(Mac, (Reg) + 2), (SK_U16 SK_FAR *)(pVal) + 1); \ } +#else /* !SK_LITTLE_ENDIAN */ + +#define XM_IN32(IoC, Mac, Reg, pVal) { \ + SK_IN16(IoC, XMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal) + 1); \ + SK_IN16(IoC, XMA(Mac, (Reg) + 2), (SK_U16 SK_FAR *)(pVal)); \ +} + +#endif /* !SK_LITTLE_ENDIAN */ + #define XM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\ + SK_OUT16(IoC, XMA(Mac, Reg), (SK_U16)((Val) & 0xffffL)); \ + SK_OUT16(IoC, XMA(Mac, (Reg) + 2), (SK_U16)(((Val) >> 16) & 0xffffL)); \ } /* Remember: we are always writing to / reading from LITTLE ENDIAN memory */ @@ -2012,61 +2732,61 @@ typedef struct s_HwRxd { SK_U8 *pByte; \ pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg) + 2), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg) + 4), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ } #define XM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_U8 SK_FAR *pByte; \ + pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ (((SK_U16)(pByte[0]) & 0x00ff) | \ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ + SK_OUT16((IoC), XMA((Mac), (Reg) + 2), (SK_U16) \ (((SK_U16)(pByte[2]) & 0x00ff) | \ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ + SK_OUT16((IoC), XMA((Mac), (Reg) + 4), (SK_U16) \ (((SK_U16)(pByte[4]) & 0x00ff) | \ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ } #define XM_INHASH(IoC, Mac, Reg, pVal) { \ SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_U8 SK_FAR *pByte; \ + pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg) + 2), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg) + 4), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), XMA((Mac), (Reg) + 6), &Word); \ + pByte[6] = (SK_U8)(Word & 0x00ff); \ pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ } #define XM_OUTHASH(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_U8 SK_FAR *pByte; \ + pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ (((SK_U16)(pByte[0]) & 0x00ff)| \ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ + SK_OUT16((IoC), XMA((Mac), (Reg) + 2), (SK_U16) \ (((SK_U16)(pByte[2]) & 0x00ff)| \ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ + SK_OUT16((IoC), XMA((Mac), (Reg) + 4), (SK_U16) \ (((SK_U16)(pByte[4]) & 0x00ff)| \ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \ + SK_OUT16((IoC), XMA((Mac), (Reg) + 6), (SK_U16) \ (((SK_U16)(pByte[6]) & 0x00ff)| \ (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ } @@ -2076,12 +2796,12 @@ typedef struct s_HwRxd { * * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT) * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL) - * GM_IN32(), to read a 32 bit register (e.g. GM_) - * GM_OUT32(), to write a 32 bit register (e.g. GM_) + * GM_IN32(), to read a 32 bit register (e.g. GM_RXF_UC_OK) + * GM_OUT32(), to write a 32 bit register * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L) * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L) - * GM_INHASH(), to read the GM_MC_ADDR_H1 register - * GM_OUTHASH() to write the GM_MC_ADDR_H1 register + * GM_INHASH(), to read the hash registers (e.g. GM_MC_ADDR_H1..4) + * GM_OUTHASH() to write the hash registers (e.g. GM_MC_ADDR_H1..4) * * para: * Mac GMAC to access values: MAC_1 or MAC_2 @@ -2095,22 +2815,31 @@ typedef struct s_HwRxd { #define GMA(Mac, Reg) \ ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg)) -#define GM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), GMA((Mac), (Reg)), (pVal)) +#define GM_IN16(IoC, Mac, Reg, pVal) \ + SK_IN16(IoC, GMA(Mac, Reg), pVal) -#define GM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (Val)) +#define GM_OUT16(IoC, Mac, Reg, Val) \ + SK_OUT16(IoC, GMA(Mac, Reg), Val) -#define GM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), GMA((Mac), (Reg)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), \ - (SK_U16 *)&((SK_U16 *)(pVal))[XM_WORD_HI]); \ +#ifdef SK_LITTLE_ENDIAN + +#define GM_IN32(IoC, Mac, Reg, pVal) { \ + SK_IN16(IoC, GMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal)); \ + SK_IN16((IoC), GMA(Mac, (Reg) + 4), (SK_U16 SK_FAR *)(pVal) + 1); \ } +#else /* !SK_LITTLE_ENDIAN */ + +#define GM_IN32(IoC, Mac, Reg, pVal) { \ + SK_IN16(IoC, GMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal) + 1); \ + SK_IN16(IoC, GMA(Mac, (Reg) + 4), (SK_U16 SK_FAR *)(pVal)); \ +} + +#endif /* !SK_LITTLE_ENDIAN */ + #define GM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\ + SK_OUT16(IoC, GMA(Mac, Reg), (SK_U16)((Val) & 0xffffL)); \ + SK_OUT16(IoC, GMA(Mac, (Reg) + 4), (SK_U16)(((Val) >> 16) & 0xffffL)); \ } #define GM_INADDR(IoC, Mac, Reg, pVal) { \ @@ -2118,26 +2847,26 @@ typedef struct s_HwRxd { SK_U8 *pByte; \ pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg) + 4), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg) + 8), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ } #define GM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ + SK_U8 SK_FAR *pByte; \ + pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ (((SK_U16)(pByte[0]) & 0x00ff) | \ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ + SK_OUT16((IoC), GMA((Mac), (Reg) + 4), (SK_U16) \ (((SK_U16)(pByte[2]) & 0x00ff) | \ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ + SK_OUT16((IoC), GMA((Mac), (Reg) + 8), (SK_U16) \ (((SK_U16)(pByte[4]) & 0x00ff) | \ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ } @@ -2147,16 +2876,16 @@ typedef struct s_HwRxd { SK_U8 *pByte; \ pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ + pByte[0] = (SK_U8)(Word & 0x00ff); \ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg) + 4), &Word); \ + pByte[2] = (SK_U8)(Word & 0x00ff); \ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg) + 8), &Word); \ + pByte[4] = (SK_U8)(Word & 0x00ff); \ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ + SK_IN16((IoC), GMA((Mac), (Reg) + 12), &Word); \ + pByte[6] = (SK_U8)(Word & 0x00ff); \ pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ } @@ -2166,13 +2895,13 @@ typedef struct s_HwRxd { SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ (((SK_U16)(pByte[0]) & 0x00ff)| \ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ + SK_OUT16((IoC), GMA((Mac), (Reg) + 4), (SK_U16) \ (((SK_U16)(pByte[2]) & 0x00ff)| \ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ + SK_OUT16((IoC), GMA((Mac), (Reg) + 8), (SK_U16) \ (((SK_U16)(pByte[4]) & 0x00ff)| \ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \ + SK_OUT16((IoC), GMA((Mac), (Reg) + 12), (SK_U16) \ (((SK_U16)(pByte[6]) & 0x00ff)| \ (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ } @@ -2190,8 +2919,8 @@ typedef struct s_HwRxd { #define SK_PHY_BCOM 1 /* Broadcom BCM5400 */ #define SK_PHY_LONE 2 /* Level One LXT1000 */ #define SK_PHY_NAT 3 /* National DP83891 */ -#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */ -#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */ +#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1040S */ +#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1040S working on fiber */ /* * PHY addresses (bits 12..8 of PHY address reg) @@ -2220,30 +2949,30 @@ typedef struct s_HwRxd { * * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value); * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never - * comes back. This is checked in DEBUG mode. + * comes back. This is checked in DEBUG mode. */ #ifndef DEBUG #define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ + SK_U16 Mmu; \ \ XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ + do { \ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ + } \ } #else #define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ + SK_U16 Mmu; \ int __i = 0; \ \ XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ + do { \ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ __i++; \ if (__i > 100000) { \ @@ -2254,7 +2983,7 @@ typedef struct s_HwRxd { } \ } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ + } \ } #endif /* DEBUG */ @@ -2262,17 +2991,17 @@ typedef struct s_HwRxd { SK_U16 Mmu; \ \ if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ + do { \ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ + } \ XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \ if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ + do { \ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ + } \ } /* @@ -2281,12 +3010,14 @@ typedef struct s_HwRxd { * Use this macro to access PCI config register from the I/O space. * * para: + * pAC Pointer to adapter context * Addr PCI configuration register to access. * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG, * - * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal); + * usage SK_IN16(IoC, PCI_C(pAC, PCI_VENDOR_ID), pVal); */ -#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */ +#define PCI_C(p, Addr) \ + (((CHIP_ID_YUKON_2(p)) ? Y2_CFG_SPC : B7_CFG_SPC) + (Addr)) /* * Macro SK_HW_ADDR(Base, Addr) @@ -2298,15 +3029,15 @@ typedef struct s_HwRxd { * Addr Address offset * * usage: May be used in SK_INxx and SK_OUTxx macros - * #define SK_IN8(pAC, Addr, pVal) ...\ + * #define SK_IN8(IoC, Addr, pVal) ...\ * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr))) */ -#ifdef SK_MEM_MAPPED_IO +#ifdef SK_MEM_MAPPED_IO #define SK_HW_ADDR(Base, Addr) ((Base) + (Addr)) -#else /* SK_MEM_MAPPED_IO */ +#else /* SK_MEM_MAPPED_IO */ #define SK_HW_ADDR(Base, Addr) \ ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0))) -#endif /* SK_MEM_MAPPED_IO */ +#endif /* SK_MEM_MAPPED_IO */ #define SZ_LONG (sizeof(SK_U32)) @@ -2317,20 +3048,31 @@ typedef struct s_HwRxd { * para: * pAC Pointer to adapter context struct * IoC I/O context needed for SK I/O macros - * Port Port number + * Port Port number * Mode Mode to set for this LED */ #define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \ SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode); +#define SK_SET_GP_IO(IoC, Bit) { \ + SK_U32 DWord; \ + SK_IN32(IoC, B2_GP_IO, &DWord); \ + DWord |= ((GP_DIR_0 | GP_IO_0) << (Bit));\ + SK_OUT32(IoC, B2_GP_IO, DWord); \ +} -/* typedefs *******************************************************************/ +#define SK_CLR_GP_IO(IoC, Bit) { \ + SK_U32 DWord; \ + SK_IN32(IoC, B2_GP_IO, &DWord); \ + DWord &= ~((GP_DIR_0 | GP_IO_0) << (Bit));\ + SK_OUT32(IoC, B2_GP_IO, DWord); \ +} - -/* function prototypes ********************************************************/ +#define SK_GE_PCI_FIFO_SIZE 1600 /* PCI FIFO Size */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __INC_SKGEHW_H */ + diff --git a/drivers/sk98lin/h/skgehwt.h b/drivers/sk98lin/h/skgehwt.h index 8aa9edd..a9a7088 100644 --- a/drivers/sk98lin/h/skgehwt.h +++ b/drivers/sk98lin/h/skgehwt.h @@ -1,17 +1,17 @@ /****************************************************************************** * * Name: skhwt.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 1999/11/22 13:54:24 $ + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines for the hardware timer functions * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -22,32 +22,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skgehwt.h,v $ - * Revision 1.5 1999/11/22 13:54:24 cgoos - * Changed license header to GPL. - * - * Revision 1.4 1998/08/19 09:50:58 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.3 1998/08/14 07:09:29 gklug - * fix: chg pAc -> pAC - * - * Revision 1.2 1998/08/07 12:54:21 gklug - * fix: first compiled version - * - * Revision 1.1 1998/08/07 09:32:58 gklug - * first version - * - * - * - * - * - ******************************************************************************/ - /* * SKGEHWT.H contains all defines and types for the timer functions */ @@ -61,14 +35,14 @@ * - use in Adapters context name pAC->Hwt */ typedef struct s_Hwt { - SK_U32 TStart ; /* HWT start */ - SK_U32 TStop ; /* HWT stop */ - int TActive ; /* HWT: flag : active/inactive */ + SK_U32 TStart; /* HWT start */ + SK_U32 TStop; /* HWT stop */ + int TActive; /* HWT: flag : active/inactive */ } SK_HWT; extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc); extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time); extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc); -extern SK_U32 SkHwtRead(SK_AC *pAC,SK_IOC Ioc); +extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc); extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc); #endif /* _SKGEHWT_H_ */ diff --git a/drivers/sk98lin/h/skgei2c.h b/drivers/sk98lin/h/skgei2c.h index e639f73..afaede2 100644 --- a/drivers/sk98lin/h/skgei2c.h +++ b/drivers/sk98lin/h/skgei2c.h @@ -2,8 +2,8 @@ * * Name: skgei2c.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.23 $ - * Date: $Date: 2002/12/19 14:34:27 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Special GEnesis defines for TWSI * ******************************************************************************/ @@ -26,6 +26,15 @@ * History: * * $Log: skgei2c.h,v $ + * Revision 1.1.1.1 2008-12-15 11:39:21 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:11 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:16 wokes + * marvell 88f6281 u-boot + * * Revision 1.23 2002/12/19 14:34:27 rschmidt * Added cast in macros SK_I2C_SET_BIT() and SK_I2C_CLR_BIT() * Editorial changes (TWSI) diff --git a/drivers/sk98lin/h/skgeinit.h b/drivers/sk98lin/h/skgeinit.h index cdddef9..1f41f88 100644 --- a/drivers/sk98lin/h/skgeinit.h +++ b/drivers/sk98lin/h/skgeinit.h @@ -1,329 +1,25 @@ /****************************************************************************** * * Name: skgeinit.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.75 $ - * Date: $Date: 2003/02/05 13:36:39 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Structures and prototypes for the GE Init Module * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2006 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skgeinit.h,v $ - * Revision 1.75 2003/02/05 13:36:39 rschmidt - * Added define SK_FACT_78 for YUKON's Host Clock of 78.12 MHz - * Editorial changes - * - * Revision 1.74 2003/01/28 09:39:16 rschmidt - * Added entry GIYukonLite in s_GeInit structure - * Editorial changes - * - * Revision 1.73 2002/11/15 12:47:25 rschmidt - * Replaced error message SKERR_HWI_E024 for Cable Diagnostic with - * Rx queue error in SkGeStopPort(). - * - * Revision 1.72 2002/11/12 17:08:35 rschmidt - * Added entries for Cable Diagnostic to Port structure - * Added entries GIPciSlot64 and GIPciClock66 in s_GeInit structure - * Added error message for Cable Diagnostic - * Added prototypes for SkGmCableDiagStatus() - * Editorial changes - * - * Revision 1.71 2002/10/21 11:26:10 mkarl - * Changed interface of SkGeInitAssignRamToQueues(). - * - * Revision 1.70 2002/10/14 08:21:32 rschmidt - * Changed type of GICopperType, GIVauxAvail to SK_BOOL - * Added entry PRxOverCnt to Port structure - * Added entry GIYukon32Bit in s_GeInit structure - * Editorial changes - * - * Revision 1.69 2002/10/09 16:57:15 mkarl - * Added some constants and macros for SkGeInitAssignRamToQueues(). - * - * Revision 1.68 2002/09/12 08:58:51 rwahl - * Retrieve counters needed for XMAC errata workarounds directly because - * PNMI returns corrected counter values (e.g. #10620). - * - * Revision 1.67 2002/08/16 14:40:30 rschmidt - * Added entries GIGenesis and GICopperType in s_GeInit structure - * Added prototypes for SkMacHashing() - * Editorial changes - * - * Revision 1.66 2002/08/12 13:27:21 rschmidt - * Added defines for Link speed capabilities - * Added entry PLinkSpeedCap to Port structure - * Added entry GIVauxAvail in s_GeInit structure - * Added prototypes for SkMacPromiscMode() - * Editorial changes - * - * Revision 1.65 2002/08/08 15:46:18 rschmidt - * Added define SK_PHY_ACC_TO for PHY access timeout - * Added define SK_XM_RX_HI_WM for XMAC Rx High Watermark - * Added define SK_MIN_TXQ_SIZE for Min RAM Buffer Tx Queue Size - * Added entry PhyId1 to Port structure - * - * Revision 1.64 2002/07/23 16:02:56 rschmidt - * Added entry GIWolOffs in s_GeInit struct (HW-Bug in YUKON 1st rev.) - * Added prototypes for: SkGePhyRead(), SkGePhyWrite() - * - * Revision 1.63 2002/07/18 08:17:38 rwahl - * Corrected definitions for SK_LSPEED_xxx & SK_LSPEED_STAT_xxx. - * - * Revision 1.62 2002/07/17 18:21:55 rwahl - * Added SK_LSPEED_INDETERMINATED define. - * - * Revision 1.61 2002/07/17 17:16:03 rwahl - * - MacType now member of GIni struct. - * - Struct alignment to 32bit. - * - Editorial change. - * - * Revision 1.60 2002/07/15 18:23:39 rwahl - * Added GeMacFunc to GE Init structure. - * Added prototypes for SkXmUpdateStats(), SkGmUpdateStats(), - * SkXmMacStatistic(), SkGmMacStatistic(), SkXmResetCounter(), - * SkGmResetCounter(), SkXmOverflowStatus(), SkGmOverflowStatus(). - * Added defines for current link speed state. - * Added ERRMSG defintions for MacUpdateStat() & MacStatistics(). - * - * Revision 1.59 2002/07/15 15:40:22 rschmidt - * Added entry PLinkSpeedUsed to Port structure - * Editorial changes - * - * Revision 1.58 2002/06/10 09:36:30 rschmidt - * Editorial changes. - * - * Revision 1.57 2002/06/05 08:18:00 rschmidt - * Corrected alignment in Port Structure - * Added new prototypes for GMAC - * Editorial changes - * - * Revision 1.56 2002/04/25 11:38:12 rschmidt - * Added defines for Link speed values - * Added defines for Loopback parameters for MAC and PHY - * Removed entry PRxCmd from Port structure - * Added entry PLinkSpeed to Port structure - * Added entries GIChipId and GIChipRev to GE Init structure - * Removed entry GIAnyPortAct from GE Init structure - * Added prototypes for: SkMacInit(), SkMacInitPhy(), - * SkMacRxTxDisable(), SkMacSoftRst(), SkMacHardRst(), SkMacIrq(), - * SkMacIrqDisable(), SkMacFlushTxFifo(), SkMacFlushRxFifo(), - * SkMacAutoNegDone(), SkMacAutoNegLipaPhy(), SkMacSetRxTxEn(), - * SkXmPhyRead(), SkXmPhyRead(), SkGmPhyWrite(), SkGmPhyWrite(); - * Removed prototypes for static functions in SkXmac2.c - * Editorial changes - * - * Revision 1.55 2002/02/26 15:24:53 rwahl - * Fix: no link with manual configuration (#10673). The previous fix for - * #10639 was removed. So for RLMT mode = CLS the RLMT may switch to - * misconfigured port. It should not occur for the other RLMT modes. - * - * Revision 1.54 2002/01/18 16:52:52 rwahl - * Editorial corrections. - * - * Revision 1.53 2001/11/20 09:19:58 rwahl - * Reworked bugfix #10639 (no dependency to RLMT mode). - * - * Revision 1.52 2001/10/26 07:52:23 afischer - * Port switching bug in `check local link` mode - * - * Revision 1.51 2001/02/09 12:26:38 cgoos - * Inserted #ifdef DIAG for half duplex workaround timer. - * - * Revision 1.50 2001/02/07 07:56:40 rassmann - * Corrected copyright. - * - * Revision 1.49 2001/01/31 15:32:18 gklug - * fix: problem with autosensing an SR8800 switch - * add: counter for autoneg timeouts - * - * Revision 1.48 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.47 2000/10/18 12:22:40 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.46 2000/08/10 11:28:00 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * - * Revision 1.45 1999/11/22 13:56:19 cgoos - * Changed license header to GPL. - * - * Revision 1.44 1999/10/26 07:34:15 malthoff - * The define SK_LNK_ON has been lost in v1.41. - * - * Revision 1.43 1999/10/06 09:30:16 cgoos - * Changed SK_XM_THR_JUMBO. - * - * Revision 1.42 1999/09/16 12:58:26 cgoos - * Changed SK_LED_STANDY macro to be independent of HW link sync. - * - * Revision 1.41 1999/07/30 06:56:14 malthoff - * Correct comment for SK_MS_STAT_UNSET. - * - * Revision 1.40 1999/05/27 13:38:46 cgoos - * Added SK_BMU_TX_WM. - * Made SK_BMU_TX_WM and SK_BMU_RX_WM user-definable. - * Changed XMAC Tx treshold to max. values. - * - * Revision 1.39 1999/05/20 14:35:26 malthoff - * Remove prototypes for SkGeLinkLED(). - * - * Revision 1.38 1999/05/19 11:59:12 cgoos - * Added SK_MS_CAP_INDETERMINATED define. - * - * Revision 1.37 1999/05/19 07:32:33 cgoos - * Changes for 1000Base-T. - * LED-defines for HWAC_LINK_LED macro. - * - * Revision 1.36 1999/04/08 14:00:24 gklug - * add:Port struct field PLinkResCt - * - * Revision 1.35 1999/03/25 07:43:07 malthoff - * Add error string for SKERR_HWI_E018MSG. - * - * Revision 1.34 1999/03/12 16:25:57 malthoff - * Remove PPollRxD and PPollTxD. - * Add SKERR_HWI_E017MSG. and SK_DPOLL_MAX. - * - * Revision 1.33 1999/03/12 13:34:41 malthoff - * Add Autonegotiation error codes. - * Change defines for parameter Mode in SkXmSetRxCmd(). - * Replace __STDC__ by SK_KR_PROTO. - * - * Revision 1.32 1999/01/25 14:40:20 mhaveman - * Added new return states for the virtual management port if multiple - * ports are active but differently configured. - * - * Revision 1.31 1998/12/11 15:17:02 gklug - * add: Link partnet autoneg states : Unknown Manual and Auto-negotiation - * - * Revision 1.30 1998/12/07 12:17:04 gklug - * add: Link Partner auto-negotiation flag - * - * Revision 1.29 1998/12/01 10:54:42 gklug - * add: variables for XMAC Errata - * - * Revision 1.28 1998/12/01 10:14:15 gklug - * add: PIsave saves the Interrupt status word - * - * Revision 1.27 1998/11/26 15:24:52 mhaveman - * Added link status states SK_LMODE_STAT_AUTOHALF and - * SK_LMODE_STAT_AUTOFULL which are used by PNMI. - * - * Revision 1.26 1998/11/26 14:53:01 gklug - * add:autoNeg Timeout variable - * - * Revision 1.25 1998/11/26 08:58:50 gklug - * add: Link Mode configuration (AUTO Sense mode) - * - * Revision 1.24 1998/11/24 13:30:27 gklug - * add: PCheckPar to port struct - * - * Revision 1.23 1998/11/18 13:23:26 malthoff - * Add SK_PKT_TO_MAX. - * - * Revision 1.22 1998/11/18 13:19:54 gklug - * add: PPrevShorts and PLinkBroken to port struct for WA XMAC Errata #C1 - * - * Revision 1.21 1998/10/26 08:02:57 malthoff - * Add GIRamOffs. - * - * Revision 1.20 1998/10/19 07:28:37 malthoff - * Add prototype for SkGeInitRamIface(). - * - * Revision 1.19 1998/10/14 14:47:48 malthoff - * SK_TIMER should not be defined for Diagnostics. - * Add SKERR_HWI_E015MSG and SKERR_HWI_E016MSG. - * - * Revision 1.18 1998/10/14 14:00:03 gklug - * add: timer to port struct for workaround of Errata #2 - * - * Revision 1.17 1998/10/14 11:23:09 malthoff - * Add prototype for SkXmAutoNegDone(). - * Fix SkXmSetRxCmd() prototype statement. - * - * Revision 1.16 1998/10/14 05:42:29 gklug - * add: HWLinkUp flag to Port struct - * - * Revision 1.15 1998/10/09 08:26:33 malthoff - * Rename SK_RB_ULPP_B to SK_RB_LLPP_B. - * - * Revision 1.14 1998/10/09 07:11:13 malthoff - * bug fix: SK_FACT_53 is 85 not 117. - * Rework time out init values. - * Add GIPortUsage and corresponding defines. - * Add some error log messages. - * - * Revision 1.13 1998/10/06 14:13:14 malthoff - * Add prototype for SkGeLoadLnkSyncCnt(). - * - * Revision 1.12 1998/10/05 11:29:53 malthoff - * bug fix: A comment was not closed. - * - * Revision 1.11 1998/10/05 08:01:59 malthoff - * Add default Timeout- Threshold- and - * Watermark constants. Add QRam start and end - * variables. Also add vars to store the polling - * mode and receive command. Add new Error Log - * Messages and function prototypes. - * - * Revision 1.10 1998/09/28 13:34:48 malthoff - * Add mode bits for LED functions. - * Move Autoneg and Flow Ctrl bits from shgesirq.h - * Add the required Error Log Entries - * and Function Prototypes. - * - * Revision 1.9 1998/09/16 14:38:41 malthoff - * Rework the SK_LNK_xxx defines. - * Add error log message defines. - * Add prototypes for skxmac2.c - * - * Revision 1.8 1998/09/11 05:29:18 gklug - * add: init state of a port - * - * Revision 1.7 1998/09/08 08:35:52 gklug - * add: defines of the Init Levels - * - * Revision 1.6 1998/09/03 13:48:42 gklug - * add: Link strati, capabilities to Port struct - * - * Revision 1.5 1998/09/03 13:30:59 malthoff - * Add SK_LNK_BLINK and SK_LNK_PERM. - * - * Revision 1.4 1998/09/03 09:55:31 malthoff - * Add constants for parameters Dir and RstMode - * when calling SkGeStopPort(). - * Rework the prototype section. - * Add Queue Address offsets PRxQOff, PXsQOff, and PXaQOff. - * Remove Ioc with IoC. - * - * Revision 1.3 1998/08/19 09:11:54 gklug - * fix: struct are removed from c-source (see CCC) - * add: typedefs for all structs - * - * Revision 1.2 1998/07/28 12:38:26 malthoff - * The prototypes got the parameter 'IoC'. - * - * Revision 1.1 1998/07/23 09:50:24 malthoff - * Created. + * /LICENSE * ******************************************************************************/ @@ -336,6 +32,8 @@ extern "C" { /* defines ********************************************************************/ +#define SK_TEST_VAL 0x11335577UL + /* modifying Link LED behaviour (used with SkGeLinkLED()) */ #define SK_LNK_OFF LED_OFF #define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) @@ -360,17 +58,20 @@ extern "C" { #define SK_LED_TST 2 /* Counter and Timer constants, for a host clock of 62.5 MHz */ -#define SK_XMIT_DUR 0x002faf08L /* 50 ms */ -#define SK_BLK_DUR 0x01dcd650L /* 500 ms */ +#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */ +#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */ -#define SK_DPOLL_DEF 0x00ee6b28L /* 250 ms at 62.5 MHz */ +#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz (Genesis) */ +#define SK_DPOLL_DEF_Y2 0x0000124fUL /* 75 us (Yukon-2) */ -#define SK_DPOLL_MAX 0x00ffffffL /* 268 ms at 62.5 MHz */ - /* 215 ms at 78.12 MHz */ +#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */ + /* 215 ms at 78.12 MHz (Yukon) */ #define SK_FACT_62 100 /* is given in percent */ -#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ +#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ #define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ +#define SK_FACT_100 161 /* on YUKON-FE: 100 MHz */ +#define SK_FACT_125 202 /* on YUKON-EC: 125 MHz */ /* Timeout values */ #define SK_MAC_TO_53 72 /* MAC arbiter timeout */ @@ -385,11 +86,23 @@ extern "C" { #define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */ #define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */ +/* Threshold values for Yukon-EC Ultra */ +#define SK_ECU_ULPP 0x0080 /* Upper Pause Threshold (multiples of 8) */ +#define SK_ECU_LLPP 0x0060 /* Lower Pause Threshold (multiples of 8) */ +#define SK_ECU_AE_THR 0x0180 /* Almost Empty Threshold */ +#define SK_ECU_TXFF_LEV 0x01a0 /* Tx BMU FIFO Level */ + #ifndef SK_BMU_RX_WM -#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */ +#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */ #endif + #ifndef SK_BMU_TX_WM -#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */ +#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */ +#endif + +/* performance sensitive drivers should set this define to 0x80 */ +#ifndef SK_BMU_RX_WM_PEX +#define SK_BMU_RX_WM_PEX 0x600 /* BMU Rx Watermark for PEX */ #endif /* XMAC II Rx High Watermark */ @@ -401,37 +114,31 @@ extern "C" { #define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */ #define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */ -/* values for GIPortUsage */ +/* values for PortUsage */ #define SK_RED_LINK 1 /* redundant link usage */ #define SK_MUL_LINK 2 /* multiple link usage */ #define SK_JUMBO_LINK 3 /* driver uses jumbo frames */ /* Minimum RAM Buffer Rx Queue Size */ -#define SK_MIN_RXQ_SIZE 16 /* 16 kB */ +#define SK_MIN_RXQ_SIZE (((pAC)->GIni.GIYukon2) ? 10 : 16) /* 10/16 kB */ /* Minimum RAM Buffer Tx Queue Size */ -#define SK_MIN_TXQ_SIZE 16 /* 16 kB */ +#define SK_MIN_TXQ_SIZE (((pAC)->GIni.GIYukon2) ? 10 : 16) /* 10/16 kB */ -/* Queue Size units */ -#define QZ_UNITS 0x7 +/* Queue Size units (Genesis/Yukon) */ +#define QZ_UNITS 7 #define QZ_STEP 8 +/* Queue Size units (Yukon-2) */ +#define QZ_STEP_Y2 1 + /* Percentage of queue size from whole memory */ /* 80 % for receive */ -#define RAM_QUOTA_RX 80L -/* 0% for sync transfer */ -#define RAM_QUOTA_SYNC 0L +#define RAM_QUOTA_RX 80 +/* 0 % for sync transfer */ +#define RAM_QUOTA_SYNC 0 /* the rest (20%) is taken for async transfer */ -/* Get the rounded queue size in Bytes in 8k steps */ -#define ROUND_QUEUE_SIZE(SizeInBytes) \ - ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \ - ~(QZ_STEP-1)) - -/* Get the rounded queue size in KBytes in 8k steps */ -#define ROUND_QUEUE_SIZE_KB(Kilobytes) \ - ROUND_QUEUE_SIZE((Kilobytes) * 1024L) - /* Types of RAM Buffer Queues */ #define SK_RX_SRAM_Q 1 /* small receive queue */ #define SK_RX_BRAM_Q 2 /* big receive queue */ @@ -470,11 +177,11 @@ extern "C" { /* Link Speed Capabilities */ -#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */ -#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */ -#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */ -#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */ +#define SK_LSPEED_CAP_AUTO BIT_0S /* Automatic resolution */ +#define SK_LSPEED_CAP_10MBPS BIT_1S /* 10 Mbps */ +#define SK_LSPEED_CAP_100MBPS BIT_2S /* 100 Mbps */ +#define SK_LSPEED_CAP_1000MBPS BIT_3S /* 1000 Mbps */ +#define SK_LSPEED_CAP_INDETERMINATED BIT_4S /* indeterminated */ /* Link Speed Parameter */ #define SK_LSPEED_AUTO 1 /* Automatic resolution */ @@ -492,11 +199,11 @@ extern "C" { /* Link Capability Parameter */ -#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */ -#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */ -#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */ -#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */ -#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */ +#define SK_LMODE_CAP_HALF BIT_0S /* Half Duplex Mode */ +#define SK_LMODE_CAP_FULL BIT_1S /* Full Duplex Mode */ +#define SK_LMODE_CAP_AUTOHALF BIT_2S /* AutoHalf Duplex Mode */ +#define SK_LMODE_CAP_AUTOFULL BIT_3S /* AutoFull Duplex Mode */ +#define SK_LMODE_CAP_INDETERMINATED BIT_4S /* indeterminated */ /* Link Mode Current State */ #define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */ @@ -507,7 +214,7 @@ extern "C" { #define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */ /* Flow Control Mode Parameter (and capabilities) */ -#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */ +#define SK_FLOW_MODE_NONE 1 /* No Flow Control */ #define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */ #define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */ #define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or @@ -523,10 +230,10 @@ extern "C" { #define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */ /* Master/Slave Mode Capabilities */ -#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_MS_CAP_MASTER (1<<1) /* This station is master */ -#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */ -#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */ +#define SK_MS_CAP_AUTO BIT_0S /* Automatic resolution */ +#define SK_MS_CAP_MASTER BIT_1S /* This station is master */ +#define SK_MS_CAP_SLAVE BIT_2S /* This station is slave */ +#define SK_MS_CAP_INDETERMINATED BIT_3S /* indeterminated */ /* Set Master/Slave Mode Parameter (and capabilities) */ #define SK_MS_MODE_AUTO 1 /* Automatic resolution */ @@ -536,30 +243,30 @@ extern "C" { /* Master/Slave Status Parameter */ #define SK_MS_STAT_UNSET 1 /* The M/S status is not set */ -#define SK_MS_STAT_MASTER 2 /* This station is Master */ -#define SK_MS_STAT_SLAVE 3 /* This station is Dlave */ +#define SK_MS_STAT_MASTER 2 /* This station is master */ +#define SK_MS_STAT_SLAVE 3 /* This station is slave */ #define SK_MS_STAT_FAULT 4 /* M/S resolution failed */ #define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */ -/* parameter 'Mode' when calling SkXmSetRxCmd() */ -#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */ -#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */ -#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */ -#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */ -#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */ -#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */ -#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */ -#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */ -#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */ -#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */ +/* parameter 'Mode' when calling SkMacSetRxCmd() */ +#define SK_STRIP_FCS_ON BIT_0S /* Enable FCS stripping of Rx frames */ +#define SK_STRIP_FCS_OFF BIT_1S /* Disable FCS stripping of Rx frames */ +#define SK_STRIP_PAD_ON BIT_2S /* Enable pad byte stripping of Rx fr */ +#define SK_STRIP_PAD_OFF BIT_3S /* Disable pad byte stripping of Rx fr */ +#define SK_LENERR_OK_ON BIT_4S /* Don't chk fr for in range len error */ +#define SK_LENERR_OK_OFF BIT_5S /* Check frames for in range len error */ +#define SK_BIG_PK_OK_ON BIT_6S /* Don't set Rx Error bit for big frames */ +#define SK_BIG_PK_OK_OFF BIT_7S /* Set Rx Error bit for big frames */ +#define SK_SELF_RX_ON BIT_8S /* Enable Rx of own packets */ +#define SK_SELF_RX_OFF BIT_9S /* Disable Rx of own packets */ /* parameter 'Para' when calling SkMacSetRxTxEn() */ -#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */ -#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */ -#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */ -#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */ -#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */ -#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */ +#define SK_MAC_LOOPB_ON BIT_0S /* Enable MAC Loopback Mode */ +#define SK_MAC_LOOPB_OFF BIT_1S /* Disable MAC Loopback Mode */ +#define SK_PHY_LOOPB_ON BIT_2S /* Enable PHY Loopback Mode */ +#define SK_PHY_LOOPB_OFF BIT_3S /* Disable PHY Loopback Mode */ +#define SK_PHY_FULLD_ON BIT_4S /* Enable GMII Full Duplex */ +#define SK_PHY_FULLD_OFF BIT_5S /* Disable GMII Full Duplex */ /* States of PState */ #define SK_PRT_RESET 0 /* the port is reset */ @@ -567,9 +274,28 @@ extern "C" { #define SK_PRT_INIT 2 /* the port is initialized */ #define SK_PRT_RUN 3 /* the port has an active link */ +/* PHY power down modes */ +#define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */ +#define PHY_PM_DEEP_SLEEP 1 /* Coma mode --> minimal power */ +#define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */ +#define PHY_PM_ENERGY_DETECT 3 /* Energy detect */ +#define PHY_PM_ENERGY_DETECT_PLUS 4 /* Energy detect plus */ + +/* PCI Bus Types */ +#define SK_PCI_BUS BIT_0S /* normal PCI bus */ +#define SK_PCIX_BUS BIT_1S /* PCI-X bus */ +#define SK_PEX_BUS BIT_2S /* PCI-Express bus */ + /* Default receive frame limit for Workaround of XMAC Errata */ #define SK_DEF_RX_WA_LIM SK_CONSTU64(100) +/* values for GILedBlinkCtrl (LED Blink Control) */ +#define SK_ACT_LED_BLINK BIT_0S /* Active LED blinking */ +#define SK_DUP_LED_NORMAL BIT_1S /* Duplex LED normal */ +#define SK_LED_LINK100_ON BIT_2S /* Link 100M LED on */ +#define SK_DUAL_LED_ACT_LNK BIT_3S /* Dual LED ACT/LNK configuration */ +#define SK_LED_LINK_MUX_P60 BIT_4S /* Link LED muxed to pin 60 */ + /* Link Partner Status */ #define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */ #define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */ @@ -581,18 +307,174 @@ extern "C" { /* Max. Auto-neg. timeouts before link detection in sense mode is reset */ #define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */ + +/****************************************************************************** + * + * HW_FEATURE() macro + */ + +/* DWORD 0: Features */ +#define HWF_FORCE_AUTO_NEG 0x04000000UL /* Force Auto-Negotiation */ +#define HWF_CLK_GATING_ENABLE 0x02000000UL /* Enable Clock Gating */ +#define HWF_RED_CORE_CLK_SUP 0x01000000UL /* Reduced Core Clock supp. */ +#define HWF_SYNC_TX_SUP 0x00800000UL /* Synch. Tx Queue available */ +#define HWF_SINGLE_PORT_DEVICE 0x00400000UL /* Device has only one LAN IF */ +#define HWF_JUMBO_FRAMES_SUP 0x00200000UL /* Jumbo Frames supported */ +#define HWF_TX_TCP_CSUM_SUP 0x00100000UL /* TCP Tx checksum supported */ +#define HWF_TX_UDP_CSUM_SUP 0x00080000UL /* UDP Tx checksum supported */ +#define HWF_RX_CSUM_SUP 0x00040000UL /* RX checksum supported */ +#define HWF_TCP_SEGM_SUP 0x00020000UL /* TCP segmentation supported */ +#define HWF_RSS_HASH_SUP 0x00010000UL /* RSS Hash supported */ +#define HWF_PORT_VLAN_SUP 0x00008000UL /* VLAN can be config per port*/ +#define HWF_ROLE_PARAM_SUP 0x00004000UL /* Role parameter supported */ +#define HWF_LOW_PMODE_SUP 0x00002000UL /* Low Power Mode supported */ +#define HWF_ENERGIE_DEMO_SUP 0x00001000UL /* Energy Detect mode supp. */ +#define HWF_SPEED1000_SUP 0x00000800UL /* Line Speed 1000 supported */ +#define HWF_SPEED100_SUP 0x00000400UL /* Line Speed 100 supported */ +#define HWF_SPEED10_SUP 0x00000200UL /* Line Speed 10 supported */ +#define HWF_AUTONEGSENSE_SUP 0x00000100UL /* Autoneg Sense supported */ +#define HWF_PHY_LOOPB_MD_SUP 0x00000080UL /* PHY loopback mode supp. */ +#define HWF_ASF_SUP 0x00000040UL /* ASF support possible */ +#define HWF_QS_STEPS_1KB 0x00000020UL /* The Rx/Tx queues can be */ + /* configured with 1 kB res. */ +#define HWF_OWN_RAM_PER_PORT 0x00000010UL /* Each port has a separate */ + /* RAM buffer */ +#define HWF_MIN_LED_IF 0x00000008UL /* Minimal LED interface */ + /* (e.g. for Yukon-EC) */ +#define HWF_LIST_ELEMENTS_USED 0x00000004UL /* HW uses list elements */ + /* (otherwise desc. are used) */ +#define HWF_GMAC_INSIDE 0x00000002UL /* Device contains GMAC */ +#define HWF_TWSI_PRESENT 0x00000001UL /* TWSI sensor bus present */ + +/*-RMV- DWORD 1: Deviations */ +#define HWF_WA_DEV_4200 0x10200000UL /*-RMV- 4.200 (D3 Blue Screen)*/ +#define HWF_WA_DEV_4185CS 0x10100000UL /*-RMV- 4.185 (ECU 100 CS cal)*/ +#define HWF_WA_DEV_4185 0x10080000UL /*-RMV- 4.185 (ECU Tx h check)*/ +#define HWF_WA_DEV_4167 0x10040000UL /*-RMV- 4.167 (Rx OvSize Hang)*/ +#define HWF_WA_DEV_4152 0x10020000UL /*-RMV- 4.152 (RSS issue) */ +#define HWF_WA_DEV_4115 0x10010000UL /*-RMV- 4.115 (Rx MAC FIFO) */ +#define HWF_WA_DEV_4109 0x10008000UL /*-RMV- 4.109 (BIU hang) */ +#define HWF_WA_DEV_483 0x10004000UL /*-RMV- 4.83 (Rx TCP wrong) */ +#define HWF_WA_DEV_479 0x10002000UL /*-RMV- 4.79 (Rx BMU hang II) */ +#define HWF_WA_DEV_472 0x10001000UL /*-RMV- 4.72 (GPHY2 MDC clk) */ +#define HWF_WA_DEV_463 0x10000800UL /*-RMV- 4.63 (Rx BMU hang I) */ +#define HWF_WA_DEV_427 0x10000400UL /*-RMV- 4.27 (Tx Done Rep) */ +#define HWF_WA_DEV_42 0x10000200UL /*-RMV- 4.2 (pref unit burst) */ +#define HWF_WA_DEV_46 0x10000100UL /*-RMV- 4.6 (CPU crash II) */ +#define HWF_WA_DEV_43_418 0x10000080UL /*-RMV- 4.3 & 4.18 (PCI unexp */ + /*-RMV- compl&Stat BMU deadl) */ +#define HWF_WA_DEV_420 0x10000040UL /*-RMV- 4.20 (Status BMU ov) */ +#define HWF_WA_DEV_423 0x10000020UL /*-RMV- 4.23 (TCP Segm Hang) */ +#define HWF_WA_DEV_424 0x10000010UL /*-RMV- 4.24 (MAC reg overwr) */ +#define HWF_WA_DEV_425 0x10000008UL /*-RMV- 4.25 (Magic packet */ + /*-RMV- with odd offset) */ +#define HWF_WA_DEV_428 0x10000004UL /*-RMV- 4.28 (Poll-U &BigEndi)*/ +#define HWF_WA_FIFO_FLUSH_YLA0 0x10000002UL /*-RMV- dis Rx GMAC FIFO Flush*/ + /*-RMV- for Yu-L Rev. A0 only */ +#define HWF_WA_COMA_MODE 0x10000001UL /*-RMV- Coma Mode WA req */ + +/* DWORD 2: still unused */ +/* DWORD 3: still unused */ + + +/* + * HW_FEATURE() - returns whether the feature is serviced or not + */ +#define HW_FEATURE(pAC, ReqFeature) \ + (((pAC)->GIni.HwF.Features[((ReqFeature) & 0x30000000UL) >> 28] &\ + ((ReqFeature) & 0x0fffffffUL)) != 0) + +#define HW_FEAT_LIST 0 +#define HW_DEV_LIST 1 + +#define SET_HW_FEATURE_MASK(pAC, List, OffMaskValue, OnMaskValue) { \ + if ((List) == HW_FEAT_LIST || (List) == HW_DEV_LIST) { \ + (pAC)->GIni.HwF.OffMask[List] = (OffMaskValue); \ + (pAC)->GIni.HwF.OnMask[List] = (OnMaskValue); \ + } \ +} + +/* driver access macros for GIni structure ***********************************/ + +#define CHIP_ID_YUKON_2(pAC) ((pAC)->GIni.GIYukon2) + +#define HW_SYNC_TX_SUPPORTED(pAC) \ + ((pAC)->GIni.GIChipId != CHIP_ID_YUKON_EC && \ + (pAC)->GIni.GIChipId != CHIP_ID_YUKON_FE && \ + (pAC)->GIni.GIChipId != CHIP_ID_YUKON_EC_U) + +#define HW_MS_TO_TICKS(pAC, MsTime) \ + ((MsTime) * (62500L/100) * (pAC)->GIni.GIHstClkFact) + +#if 0 +/* still under construction */ +#define HW_IS_SINGLE_PORT(pAC) ((pAC)->GIni.GIMacsFound == 1) +#define HW_NUMBER_OF_PORTS(pAC) ((pAC)->GIni.GIMacsFound) + +#define HW_TX_UDP_CSUM_SUPPORTED(pAC) \ + ((((pAC)->GIni.GIChipId >= CHIP_ID_YUKON) && ((pAC)->GIni.GIChipRev != 0)) + +#define HW_DEFAULT_LINESPEED(pAC) \ + ((!(pAC)->GIni.GIGenesis && (pAC)->GIni.GICopperType) ? \ + SK_LSPEED_AUTO : SK_LSPEED_1000MBPS) + +#define HW_ROLE_PARAM_SUPPORTED(pAC) ((pAC)->GIni.GICopperType) + +#define HW_SPEED1000_SUPPORTED(pAC, Port) \ + ((pAC)->GIni.GP[Port].PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) + +#define HW_SPEED100_SUPPORTED(pAC, Port) \ + ((pAC)->GIni.GP[Port].PLinkSpeedCap & SK_LSPEED_CAP_100MBPS) + +#define HW_SPEED10_SUPPORTED(pAC, Port) \ + ((pAC)->GIni.GP[Port].PLinkSpeedCap & SK_LSPEED_CAP_10MBPS) + +#define HW_AUTONEGSENSE_SUPPORTED(pAC) ((pAC)->GIni.GP[0].PhyType==SK_PHY_XMAC) + +#define HW_FREQ_TO_CARD_TICKS(pAC, AdapterClkSpeed, Freq) \ + (((AdapterClkSpeed / 100) * (pAC)->GIni.GIHstClkFact) / Freq) + +#define HW_IS_LINK_UP(pAC, Port) ((pAC)->GIni.GP[Port].PHWLinkUp) +#define HW_LINK_SPEED_USED(pAC, Port) ((pAC)->GIni.GP[Port].PLinkSpeedUsed) +#define HW_RAM_SIZE(pAC) ((pAC)->GIni.GIRamSize) + +#define HW_PHY_LP_MODE_SUPPORTED(pAC) (pAC0->??? +#define HW_ASF_ACTIVE(pAC) ??? +#define RAWIO_OUT32(pAC, pAC->RegIrqMask, pAC->GIni.GIValIrqMask)... + +/* macro to check whether Tx checksum is supported */ +#define HW_TX_CSUM_SUPPORTED(pAC) ((pAC)->GIni.GIChipId != CHIP_ID_GENESIS) + +BMU_UDP_CHECK : BMU_TCP_CHECK; + +/* macro for - Own Bit mirrored to DWORD7 (Yukon LP receive descriptor) */ +#endif /* 0 */ + + /* structures *****************************************************************/ +/* + * HW Feature structure + */ +typedef struct s_HwFeatures { + SK_U32 Features[4]; /* Feature list */ + SK_U32 OffMask[4]; /* Off Mask */ + SK_U32 OnMask[4]; /* On Mask */ +} SK_HW_FEATURES; + /* * MAC specific functions */ typedef struct s_GeMacFunc { - int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 StatAddr, SK_U32 *pVal); - int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 IStatus, SK_U64 *pVal); + int (*pFnMacUpdateStats)(SK_AC *, SK_IOC, unsigned int); + int (*pFnMacStatistic)(SK_AC *, SK_IOC, unsigned int, SK_U16, SK_U32 SK_FAR *); + int (*pFnMacResetCounter)(SK_AC *, SK_IOC, unsigned int); + int (*pFnMacOverflow)(SK_AC *, SK_IOC, unsigned int, SK_U16, SK_U64 SK_FAR *); + void (*pSkGeSirqIsr)(SK_AC *, SK_IOC, SK_U32); +#ifdef SK_DIAG + int (*pFnMacPhyRead)(SK_AC *, SK_IOC, int, int, SK_U16 SK_FAR *); + int (*pFnMacPhyWrite)(SK_AC *, SK_IOC, int, int, SK_U16); +#endif /* SK_DIAG */ } SK_GEMACFUNC; /* @@ -602,8 +484,8 @@ typedef struct s_GePort { #ifndef SK_DIAG SK_TIMER PWaTimer; /* Workaround Timer */ SK_TIMER HalfDupChkTimer; -#endif /* SK_DIAG */ - SK_U32 PPrevShorts; /* Previous short Counter checking */ +#endif /* !SK_DIAG */ + SK_U32 PPrevShorts; /* Previous Short Counter checking */ SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */ SK_U64 PPrevRx; /* Previous RxOk Counter checking */ SK_U64 PRxLim; /* Previous RxOk Counter checking */ @@ -625,12 +507,14 @@ typedef struct s_GePort { int PXsQOff; /* Synchronous Tx Queue Address Offset */ int PXaQOff; /* Asynchronous Tx Queue Address Offset */ int PhyType; /* PHY used on this port */ + int PState; /* Port status (reset, stop, init, run) */ + int PPortUsage; /* Driver Port Usage */ SK_U16 PhyId1; /* PHY Id1 on this port */ SK_U16 PhyAddr; /* MDIO/MDC PHY address */ SK_U16 PIsave; /* Saved Interrupt status word */ SK_U16 PSsave; /* Saved PHY status word */ + SK_U16 PGmANegAdv; /* Saved GPhy AutoNegAdvertisment register */ SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */ - SK_BOOL PState; /* Is port initialized ? */ SK_BOOL PLinkBroken; /* Is Link broken ? */ SK_BOOL PCheckPar; /* Do we check for parity errors ? */ SK_BOOL HalfDupTimerActive; @@ -638,7 +522,7 @@ typedef struct s_GePort { SK_U8 PLinkModeConf; /* Link Mode configured */ SK_U8 PLinkMode; /* Link Mode currently used */ SK_U8 PLinkModeStatus;/* Link Mode Status */ - SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */ + SK_U8 PLinkSpeedCap; /* Link Speed Capabilities (10/100/1000 Mbps) */ SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */ SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */ SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */ @@ -647,11 +531,21 @@ typedef struct s_GePort { SK_U8 PMSCap; /* Master/Slave Capabilities */ SK_U8 PMSMode; /* Master/Slave Mode */ SK_U8 PMSStatus; /* Master/Slave Status */ - SK_U8 PAutoNegFail; /* Auto-negotiation fail flag */ + SK_BOOL PAutoNegFail; /* Auto-negotiation fail flag */ SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */ SK_U8 PCableLen; /* Cable Length */ SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */ SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */ + SK_U8 PPhyPowerState; /* PHY current power state */ + int PMacColThres; /* MAC Collision Threshold */ + int PMacJamLen; /* MAC Jam length */ + int PMacJamIpgVal; /* MAC Jam IPG */ + int PMacJamIpgData; /* MAC IPG Jam to Data */ + int PMacBackOffLim; /* MAC Back-off Limit */ + int PMacDataBlind; /* MAC Data Blinder */ + int PMacIpgData; /* MAC Data IPG */ + SK_U16 PMacAddr[3]; /* MAC address */ + SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */ } SK_GEPORT; /* @@ -659,26 +553,41 @@ typedef struct s_GePort { * (has to be included in the adapter context) */ typedef struct s_GeInit { + int GIChipId; /* Chip Identification Number */ + int GIChipRev; /* Chip Revision Number */ SK_U8 GIPciHwRev; /* PCI HW Revision Number */ - SK_U8 GIChipId; /* Chip Identification Number */ - SK_U8 GIChipRev; /* Chip Revision Number */ + SK_U8 GIPciBus; /* PCI Bus Type (PCI / PCI-X / PCI-Express) */ + SK_U8 GIPciMode; /* PCI / PCI-X Mode @ Clock */ + SK_U8 GIPexWidth; /* PCI-Express Negotiated Link Width */ SK_BOOL GIGenesis; /* Genesis adapter ? */ + SK_BOOL GIYukon; /* YUKON family (1 and 2) */ + SK_BOOL GIYukonLite; /* YUKON-Lite chip */ + SK_BOOL GIYukon2; /* YUKON-2 chip (-XL, -EC or -FE) */ + SK_U8 GIConTyp; /* Connector Type */ + SK_U8 GIPmdTyp; /* PMD Type */ SK_BOOL GICopperType; /* Copper Type adapter ? */ SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */ SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */ SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */ SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */ - SK_BOOL GIYukonLite; /* YUKON-Lite chip */ + SK_BOOL GIAsfEnabled; /* ASF subsystem enabled */ + SK_BOOL GIAsfRunning; /* ASF subsystem running */ + SK_U16 GILedBlinkCtrl; /* LED Blink Control */ int GIMacsFound; /* Number of MACs found on this adapter */ int GIMacType; /* MAC Type used on this adapter */ - int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */ - int GIPortUsage; /* Driver Port Usage */ + int GIChipCap; /* Adapter's Capabilities */ + int GIHwResInfo; /* HW Resources / Application Information */ + int GIHstClkFact; /* Host Clock Factor (HstClk / 62.5 * 100) */ int GILevel; /* Initialization Level completed */ int GIRamSize; /* The RAM size of the adapter in kB */ int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */ SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */ SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */ + SK_U32 GIValIrqMask; /* Value for Interrupt Mask */ + SK_U32 GIValHwIrqMask; /* Value for HWE Interrupt Mask */ + SK_U32 GITimeStampCnt; /* Time Stamp High Counter (YUKON only) */ SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */ + SK_HW_FEATURES HwF; /* HW Features struct */ SK_GEMACFUNC GIFunc; /* MAC depedent functions */ } SK_GEINIT; @@ -696,7 +605,7 @@ typedef struct s_GeInit { #define SKERR_HWI_E005 (SKERR_HWI_E004+1) #define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports" #define SKERR_HWI_E006 (SKERR_HWI_E005+1) -#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state" +#define SKERR_HWI_E006MSG "SkGeInit() called with illegal Chip Id" #define SKERR_HWI_E007 (SKERR_HWI_E006+1) #define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode" #define SKERR_HWI_E008 (SKERR_HWI_E007+1) @@ -712,11 +621,11 @@ typedef struct s_GeInit { #define SKERR_HWI_E013 (SKERR_HWI_E012+1) #define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue" #define SKERR_HWI_E014 (SKERR_HWI_E013+1) -#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified" +#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown PortUsage specified" #define SKERR_HWI_E015 (SKERR_HWI_E014+1) -#define SKERR_HWI_E015MSG "Illegal Link mode parameter" +#define SKERR_HWI_E015MSG "Illegal Link Mode parameter" #define SKERR_HWI_E016 (SKERR_HWI_E015+1) -#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter" +#define SKERR_HWI_E016MSG "Illegal Flow Control Mode parameter" #define SKERR_HWI_E017 (SKERR_HWI_E016+1) #define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal" #define SKERR_HWI_E018 (SKERR_HWI_E017+1) @@ -726,15 +635,19 @@ typedef struct s_GeInit { #define SKERR_HWI_E020 (SKERR_HWI_E019+1) #define SKERR_HWI_E020MSG "Illegal Master/Slave parameter" #define SKERR_HWI_E021 (SKERR_HWI_E020+1) -#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter" -#define SKERR_HWI_E022 (SKERR_HWI_E021+1) -#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address" +#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter" +#define SKERR_HWI_E022 (SKERR_HWI_E021+1) +#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address" #define SKERR_HWI_E023 (SKERR_HWI_E022+1) #define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small" #define SKERR_HWI_E024 (SKERR_HWI_E023+1) #define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)" #define SKERR_HWI_E025 (SKERR_HWI_E024+1) -#define SKERR_HWI_E025MSG "" +#define SKERR_HWI_E025MSG "Link Partner not Auto-Neg. able" +#define SKERR_HWI_E026 (SKERR_HWI_E025+1) +#define SKERR_HWI_E026MSG "PEX negotiated Link width not max." +#define SKERR_HWI_E027 (SKERR_HWI_E026+1) +#define SKERR_HWI_E027MSG "" /* function prototypes ********************************************************/ @@ -743,6 +656,24 @@ typedef struct s_GeInit { /* * public functions in skgeinit.c */ +extern void SkGePortVlan( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); + +extern void SkGeRxRss( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); + +extern void SkGeRxCsum( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_BOOL Enable); + extern void SkGePollRxD( SK_AC *pAC, SK_IOC IoC, @@ -807,9 +738,22 @@ extern void SkGeInitRamIface( extern int SkGeInitAssignRamToQueues( SK_AC *pAC, - int ActivePort, + int Port, SK_BOOL DualNet); +extern void DoInitRamQueue( + SK_AC *pAC, + SK_IOC IoC, + int QuIoOffs, + SK_U32 QuStartAddr, + SK_U32 QuEndAddr, + int QuType); + +extern int SkYuk2RestartRxBmu( + SK_AC *pAC, + SK_IOC IoC, + int Port); + /* * public functions in skxmac2.c */ @@ -828,6 +772,11 @@ extern void SkMacHardRst( SK_IOC IoC, int Port); +extern void SkMacClearRst( + SK_AC *pAC, + SK_IOC IoC, + int Port); + extern void SkXmInitMac( SK_AC *pAC, SK_IOC IoC, @@ -875,13 +824,13 @@ extern void SkMacAutoNegLipaPhy( int Port, SK_U16 IStatus); -extern void SkMacSetRxTxEn( +extern void SkMacSetRxTxEn( SK_AC *pAC, SK_IOC IoC, int Port, int Para); -extern int SkMacRxTxEnable( +extern int SkMacRxTxEnable( SK_AC *pAC, SK_IOC IoC, int Port); @@ -898,42 +847,28 @@ extern void SkMacHashing( int Port, SK_BOOL Enable); -extern void SkXmPhyRead( +extern int SkXmPhyRead( SK_AC *pAC, SK_IOC IoC, int Port, int Addr, - SK_U16 *pVal); + SK_U16 SK_FAR *pVal); -extern void SkXmPhyWrite( +extern int SkXmPhyWrite( SK_AC *pAC, SK_IOC IoC, int Port, int Addr, SK_U16 Val); -extern void SkGmPhyRead( +extern int SkGmPhyRead( SK_AC *pAC, SK_IOC IoC, int Port, int Addr, - SK_U16 *pVal); + SK_U16 SK_FAR *pVal); -extern void SkGmPhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkGePhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 *pVal); - -extern void SkGePhyWrite( +extern int SkGmPhyWrite( SK_AC *pAC, SK_IOC IoC, int Port, @@ -978,14 +913,14 @@ extern int SkXmMacStatistic( SK_IOC IoC, unsigned int Port, SK_U16 StatAddr, - SK_U32 *pVal); + SK_U32 SK_FAR *pVal); extern int SkGmMacStatistic( SK_AC *pAC, SK_IOC IoC, unsigned int Port, SK_U16 StatAddr, - SK_U32 *pVal); + SK_U32 SK_FAR *pVal); extern int SkXmResetCounter( SK_AC *pAC, @@ -1001,15 +936,15 @@ extern int SkXmOverflowStatus( SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 IStatus, - SK_U64 *pStatus); + SK_U16 IStatus, + SK_U64 SK_FAR *pStatus); extern int SkGmOverflowStatus( SK_AC *pAC, SK_IOC IoC, unsigned int Port, SK_U16 MacStatus, - SK_U64 *pStatus); + SK_U64 SK_FAR *pStatus); extern int SkGmCableDiagStatus( SK_AC *pAC, @@ -1017,7 +952,34 @@ extern int SkGmCableDiagStatus( int Port, SK_BOOL StartTest); +#ifdef SK_PHY_LP_MODE +extern int SkGmEnterLowPowerMode( + SK_AC *pAC, + SK_IOC IoC, + int Port, + SK_U8 Mode); + +extern int SkGmLeaveLowPowerMode( + SK_AC *pAC, + SK_IOC IoC, + int Port); +#endif /* SK_PHY_LP_MODE */ + #ifdef SK_DIAG +extern void SkGePhyRead( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 *pVal); + +extern void SkGePhyWrite( + SK_AC *pAC, + SK_IOC IoC, + int Port, + int Addr, + SK_U16 Val); + extern void SkMacSetRxCmd( SK_AC *pAC, SK_IOC IoC, @@ -1057,32 +1019,36 @@ extern int SkGeInitPort(); extern void SkGeXmitLED(); extern void SkGeInitRamIface(); extern int SkGeInitAssignRamToQueues(); +extern void SkGePortVlan(); +extern void SkGeRxCsum(); +extern void SkGeRxRss(); +extern void DoInitRamQueue(); +extern int SkYuk2RestartRxBmu(); /* * public functions in skxmac2.c */ -extern void SkMacRxTxDisable(); +extern void SkMacRxTxDisable(); extern void SkMacSoftRst(); extern void SkMacHardRst(); -extern void SkMacInitPhy(); -extern int SkMacRxTxEnable(); -extern void SkMacPromiscMode(); -extern void SkMacHashing(); -extern void SkMacIrqDisable(); +extern void SkMacClearRst(); +extern void SkMacInitPhy(); +extern int SkMacRxTxEnable(); +extern void SkMacPromiscMode(); +extern void SkMacHashing(); +extern void SkMacIrqDisable(); extern void SkMacFlushTxFifo(); extern void SkMacFlushRxFifo(); extern void SkMacIrq(); extern int SkMacAutoNegDone(); extern void SkMacAutoNegLipaPhy(); -extern void SkMacSetRxTxEn(); -extern void SkGePhyRead(); -extern void SkGePhyWrite(); +extern void SkMacSetRxTxEn(); extern void SkXmInitMac(); -extern void SkXmPhyRead(); -extern void SkXmPhyWrite(); +extern int SkXmPhyRead(); +extern int SkXmPhyWrite(); extern void SkGmInitMac(); -extern void SkGmPhyRead(); -extern void SkGmPhyWrite(); +extern int SkGmPhyRead(); +extern int SkGmPhyWrite(); extern void SkXmClrExactAddr(); extern void SkXmInitDupMd(); extern void SkXmInitPauseMd(); @@ -1096,18 +1062,25 @@ extern int SkGmResetCounter(); extern int SkXmOverflowStatus(); extern int SkGmOverflowStatus(); extern int SkGmCableDiagStatus(); +#ifdef SK_PHY_LP_MODE +extern int SkGmEnterLowPowerMode(); +extern int SkGmLeaveLowPowerMode(); +#endif /* SK_PHY_LP_MODE */ #ifdef SK_DIAG +extern void SkGePhyRead(); +extern void SkGePhyWrite(); extern void SkMacSetRxCmd(); extern void SkMacCrcGener(); extern void SkMacTimeStamp(); extern void SkXmSendCont(); #endif /* SK_DIAG */ -#endif /* SK_KR_PROTO */ +#endif /* SK_KR_PROTO */ #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* __INC_SKGEINIT_H_ */ -#endif /* __INC_SKGEINIT_H_ */ diff --git a/drivers/sk98lin/h/skgepnm2.h b/drivers/sk98lin/h/skgepnm2.h index 5c44f47..c3cfc40 100644 --- a/drivers/sk98lin/h/skgepnm2.h +++ b/drivers/sk98lin/h/skgepnm2.h @@ -2,15 +2,17 @@ * * Name: skgepnm2.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.34 $ - * Date: $Date: 2002/12/16 09:05:18 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines for Private Network Management Interface * ****************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2001 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,148 +20,23 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ -/***************************************************************************** - * - * History: - * - * $Log: skgepnm2.h,v $ - * Revision 1.34 2002/12/16 09:05:18 tschilli - * Code for VCT handling added. - * - * Revision 1.33 2002/09/10 09:00:03 rwahl - * Adapted boolean definitions according sktypes. - * - * Revision 1.32 2002/08/09 09:47:01 rwahl - * Added write-only flag to oid access defines. - * Editorial changes. - * - * Revision 1.31 2002/07/17 19:23:18 rwahl - * - Replaced MAC counter definitions by enumeration. - * - Added definition SK_PNMI_MAC_TYPES. - * - Added chipset defnition for Yukon. - * - * Revision 1.30 2001/02/06 10:03:41 mkunz - * - Pnmi V4 dual net support added. Interface functions and macros extended - * - Vpd bug fixed - * - OID_SKGE_MTU added - * - * Revision 1.29 2001/01/22 13:41:37 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.28 2000/08/03 15:12:48 rwahl - * - Additional comment for MAC statistic data structure. - * - * Revision 1.27 2000/08/01 16:10:18 rwahl - * - Added mac statistic data structure for StatRxLongFrame counter. - * - * Revision 1.26 2000/03/31 13:51:34 rwahl - * Added SK_UPTR cast to offset calculation for PNMI struct fields; - * missing cast caused compiler warnings by Win64 compiler. - * - * Revision 1.25 1999/11/22 13:57:41 cgoos - * Changed license header to GPL. - * Allowing overwrite for SK_PNMI_STORE/_READ defines. - * - * Revision 1.24 1999/04/13 15:11:11 mhaveman - * Changed copyright. - * - * Revision 1.23 1999/01/28 15:07:12 mhaveman - * Changed default threshold for port switches per hour from 10 - * to 240 which means 4 switches per minute. This fits better - * the granularity of 32 for the port switch estimate - * counter. - * - * Revision 1.22 1999/01/05 12:52:30 mhaveman - * Removed macro SK_PNMI_MICRO_SEC. - * - * Revision 1.21 1999/01/05 12:50:34 mhaveman - * Enlarged macro definition SK_PNMI_HUNDREDS_SEC() so that no 64-bit - * arithmetic is necessary if SK_TICKS_PER_SEC is 100. - * - * Revision 1.20 1998/12/09 14:02:53 mhaveman - * Defined macro SK_PNMI_DEF_RLMT_CHG_THRES for default port switch - * threshold. - * - * Revision 1.19 1998/12/03 11:28:41 mhaveman - * Removed SK_PNMI_CHECKPTR macro. - * - * Revision 1.18 1998/12/03 11:21:00 mhaveman - * -Added pointer check macro SK_PNMI_CHECKPTR - * -Added macros SK_PNMI_VPD_ARR_SIZE and SK_PNMI_VPD_STR_SIZE for - * VPD key evaluation. - * - * Revision 1.17 1998/11/20 13:20:33 mhaveman - * Fixed bug in SK_PNMI_SET_STAT macro. ErrorStatus was not correctly set. - * - * Revision 1.16 1998/11/20 08:08:49 mhaveman - * Macro SK_PNMI_CHECKFLAGS has got a if clause. - * - * Revision 1.15 1998/11/03 13:53:40 mhaveman - * Fixed alignment problem in macor SK_PNMI_SET_STAT macro. - * - * Revision 1.14 1998/10/30 15:50:13 mhaveman - * Added macro SK_PNMI_MICRO_SEC() - * - * Revision 1.13 1998/10/30 12:32:20 mhaveman - * Added forgotten cast in SK_PNMI_READ_U32 macro. - * - * Revision 1.12 1998/10/29 15:40:26 mhaveman - * -Changed SK_PNMI_TRAP_SENSOR_LEN because SensorDescr has now - * variable string length. - * -Defined SK_PNMI_CHECKFLAGS macro - * - * Revision 1.11 1998/10/29 08:53:34 mhaveman - * Removed SK_PNMI_RLM_XXX table indexed because these counters need - * not been saved over XMAC resets. - * - * Revision 1.10 1998/10/28 08:48:20 mhaveman - * -Added macros for storage according to alignment - * -Changed type of Instance to SK_U32 because of VPD - * -Removed trap structures. Not needed because of alignment problem - * -Changed type of Action form SK_U8 to int - * - * Revision 1.9 1998/10/21 13:34:45 mhaveman - * Shit, mismatched calculation of SK_PNMI_HUNDREDS_SEC. Corrected. - * - * Revision 1.8 1998/10/21 13:24:58 mhaveman - * Changed calculation of hundreds of seconds. - * - * Revision 1.7 1998/10/20 07:31:41 mhaveman - * Made type changes to unsigned int where possible. - * - * Revision 1.6 1998/09/04 17:04:05 mhaveman - * Added Sync counters to offset storage to provided settled values on - * port switch. - * - * Revision 1.5 1998/09/04 12:45:35 mhaveman - * Removed dummies for SK_DRIVER_ macros. They should be added by driver - * writer in skdrv2nd.h. - * - * Revision 1.4 1998/09/04 11:59:50 mhaveman - * Everything compiles now. Driver Macros for counting still missing. - * - * Revision 1.3 1998/08/24 12:01:35 mhaveman - * Intermediate state. - * - * Revision 1.2 1998/08/17 07:51:40 mhaveman - * Intermediate state. - * - * Revision 1.1 1998/08/11 09:08:40 mhaveman - * Intermediate state. - * - ****************************************************************************/ - #ifndef _SKGEPNM2_H_ #define _SKGEPNM2_H_ /* * General definitions */ -#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */ -#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */ +#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */ +#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */ +#define SK_PNMI_CHIPSET_YUKON_LITE 3 /* YUKON-Lite (Rev. A1-A3) */ +#define SK_PNMI_CHIPSET_YUKON_LP 4 /* YUKON-LP */ +#define SK_PNMI_CHIPSET_YUKON_XL 5 /* YUKON-2 XL */ +#define SK_PNMI_CHIPSET_YUKON_EC 6 /* YUKON-2 EC */ +#define SK_PNMI_CHIPSET_YUKON_FE 7 /* YUKON-2 FE */ #define SK_PNMI_BUS_PCI 1 /* PCI bus*/ @@ -200,9 +77,9 @@ /* * VCT internal status values */ -#define SK_PNMI_VCT_PENDING 32 -#define SK_PNMI_VCT_TEST_DONE 64 -#define SK_PNMI_VCT_LINK 128 +#define SK_PNMI_VCT_PENDING 0x20 +#define SK_PNMI_VCT_TEST_DONE 0x40 +#define SK_PNMI_VCT_LINK 0x80 /* * Internal table definitions @@ -277,7 +154,7 @@ enum SK_MACSTATS { SK_PNMI_HTX_SYNC, SK_PNMI_HTX_SYNC_OCTET, SK_PNMI_HTX_RESERVED, - + SK_PNMI_HRX, SK_PNMI_HRX_OCTET, SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET, @@ -315,9 +192,9 @@ enum SK_MACSTATS { SK_PNMI_HRX_1023, SK_PNMI_HRX_MAX, SK_PNMI_HRX_LONGFRAMES, - + SK_PNMI_HRX_RESERVED, - + SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */ }; @@ -359,11 +236,13 @@ typedef struct s_PnmiStatAddr { /* * Time macros */ +#ifndef SK_PNMI_HUNDREDS_SEC #if SK_TICKS_PER_SEC == 100 #define SK_PNMI_HUNDREDS_SEC(t) (t) #else #define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC)) -#endif +#endif /* !SK_TICKS_PER_SEC */ +#endif /* !SK_PNMI_HUNDREDS_SEC */ /* * Macros to work around alignment problems @@ -451,7 +330,7 @@ typedef struct s_PnmiStatAddr { vSt, \ pAC->Pnmi.MacUpdatedFlag, \ pAC->Pnmi.RlmtUpdatedFlag, \ - pAC->Pnmi.SirqUpdatedFlag))}} + pAC->Pnmi.SirqUpdatedFlag));}} #else /* !DEBUG */ diff --git a/drivers/sk98lin/h/skgepnmi.h b/drivers/sk98lin/h/skgepnmi.h index 7532313..a86ceed 100644 --- a/drivers/sk98lin/h/skgepnmi.h +++ b/drivers/sk98lin/h/skgepnmi.h @@ -1,16 +1,18 @@ /***************************************************************************** * * Name: skgepnmi.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.59 $ - * Date: $Date: 2002/12/16 14:03:50 $ + * Project: Gigabit Ethernet Adapters, PNMI-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines for Private Network Management Interface * ****************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2001 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,218 +20,10 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ -/***************************************************************************** - * - * History: - * - * $Log: skgepnmi.h,v $ - * Revision 1.59 2002/12/16 14:03:50 tschilli - * New defines for VCT added. - * - * Revision 1.58 2002/12/16 09:04:59 tschilli - * Code for VCT handling added. - * - * Revision 1.57 2002/09/26 12:41:05 tschilli - * SK_PNMI_PORT BufPort entry in struct SK_PNMI added. - * - * Revision 1.56 2002/08/16 11:10:41 rwahl - * - Replaced c++ comment. - * - * Revision 1.55 2002/08/09 15:40:21 rwahl - * Editorial change (renamed ConfSpeedCap). - * - * Revision 1.54 2002/08/09 11:06:07 rwahl - * Added OID_SKGE_SPEED_CAP. - * - * Revision 1.53 2002/08/09 09:45:28 rwahl - * Added support for NDIS OID_PNP_xxx. - * Editorial changes. - * - * Revision 1.52 2002/08/06 17:54:07 rwahl - * - Added speed cap to PNMI config struct. - * - * Revision 1.51 2002/07/17 19:19:26 rwahl - * - Added OID_SKGE_SPEED_MODE and OID_SKGE_SPEED_STATUS. - * - Added SK_PNMI_CNT_RX_PMACC_ERR() & SK_PNMI_CNT_RX_LONGFRAMES(). - * - Added speed mode & status to PNMI config struct. - * - Editorial changes. - * - * Revision 1.50 2002/05/22 08:59:37 rwahl - * Added string definitions for error msgs. - * - * Revision 1.49 2001/11/20 09:23:50 rwahl - * - pnmi struct: reordered and aligned to 32bit. - * - * Revision 1.48 2001/02/23 14:34:24 mkunz - * Changed macro PHYS2INST. Added pAC to Interface - * - * Revision 1.47 2001/02/07 08:28:23 mkunz - * - Added Oids: OID_SKGE_DIAG_ACTION - * OID_SKGE_DIAG_RESULT - * OID_SKGE_MULTICAST_LIST - * OID_SKGE_CURRENT_PACKET_FILTER - * OID_SKGE_INTERMEDIATE_SUPPORT - * - Changed value of OID_SKGE_MTU - * - * Revision 1.46 2001/02/06 10:01:41 mkunz - * - Pnmi V4 dual net support added. Interface functions and macros extended - * - Vpd bug fixed - * - OID_SKGE_MTU added - * - * Revision 1.45 2001/01/22 13:41:37 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.44 2000/09/07 07:35:27 rwahl - * - removed NDIS counter specific data type. - * - fixed spelling for OID_SKGE_RLMT_PORT_PREFERRED. - * - * Revision 1.43 2000/08/04 11:41:08 rwahl - * - Fixed compiler warning (port is always >= 0) for macros - * SK_PNMI_CNT_RX_LONGFRAMES & SK_PNMI_CNT_SYNC_OCTETS - * - * Revision 1.42 2000/08/03 15:14:07 rwahl - * - Corrected error in driver macros addressing a physical port. - * - * Revision 1.41 2000/08/01 16:22:29 rwahl - * - Changed MDB version to 3.1. - * - Added definitions for StatRxLongFrames counter. - * - Added macro to be used by driver to count long frames received. - * - Added directive to control width (default = 32bit) of NDIS statistic - * counters (SK_NDIS_64BIT_CTR). - * - * Revision 1.40 2000/03/31 13:51:34 rwahl - * Added SK_UPTR cast to offset calculation for PNMI struct fields; - * missing cast caused compiler warnings by Win64 compiler. - * - * Revision 1.39 1999/12/06 10:09:47 rwahl - * Added new error log message. - * - * Revision 1.38 1999/11/22 13:57:55 cgoos - * Changed license header to GPL. - * - * Revision 1.37 1999/09/14 14:25:32 rwahl - * Set MDB version for 1000Base-T (sensors, Master/Slave) changes. - * - * Revision 1.36 1999/05/20 09:24:56 cgoos - * Changes for 1000Base-T (sensors, Master/Slave). - * - * Revision 1.35 1999/04/13 15:10:51 mhaveman - * Replaced RLMT macros SK_RLMT_CHECK_xxx again by those of PNMI to - * grant unified interface. But PNMI macros will store the same - * value as RLMT macros. - * - * Revision 1.34 1999/04/13 15:03:49 mhaveman - * -Changed copyright - * -Removed SK_PNMI_RLMT_MODE_CHK_xxx macros. Those of RLMT should be - * used. - * - * Revision 1.33 1999/03/23 10:41:02 mhaveman - * Changed comments. - * - * Revision 1.32 1999/01/25 15:01:33 mhaveman - * Added support for multiple simultaniously active ports. - * - * Revision 1.31 1999/01/19 10:06:26 mhaveman - * Added new error log message. - * - * Revision 1.30 1999/01/05 10:34:49 mhaveman - * Fixed little error in RlmtChangeEstimate calculation. - * - * Revision 1.29 1999/01/05 09:59:41 mhaveman - * Redesigned port switch average calculation to avoid 64bit - * arithmetic. - * - * Revision 1.28 1998/12/08 10:05:48 mhaveman - * Defined macro SK_PNMI_MIN_STRUCT_SIZE. - * - * Revision 1.27 1998/12/03 14:39:35 mhaveman - * Fixed problem that LSTAT was enumerated wrong. - * - * Revision 1.26 1998/12/03 11:19:51 mhaveman - * Changed contents of errlog message SK_PNMI_ERR016MSG - * - * Revision 1.25 1998/12/01 10:40:04 mhaveman - * Changed size of SensorNumber, ChecksumNumber and RlmtPortNumber in - * SK_PNMI_STRUCT_DATA to be conform with OID definition. - * - * Revision 1.24 1998/11/20 08:09:27 mhaveman - * Added macros to convert between logical, physical port indexes and - * instances. - * - * Revision 1.23 1998/11/10 13:41:13 mhaveman - * Needed to change interface, because NT driver needs a return value - * of needed buffer space on TOO_SHORT errors. Therefore all - * SkPnmiGet/Preset/Set functions now have a pointer to the length - * parameter, where the needed space on error is returned. - * - * Revision 1.22 1998/11/03 12:05:51 mhaveman - * Added pAC parameter to counter macors. - * - * Revision 1.21 1998/11/02 10:47:36 mhaveman - * Added syslog messages for internal errors. - * - * Revision 1.20 1998/10/30 15:49:36 mhaveman - * -Removed unused SK_PNMI_UTILIZATION_BASE and EstOldCnt. - * -Redefined SK_PNMI_CHG_EST_BASE to hundreds of seconds. - * - * Revision 1.19 1998/10/29 15:38:44 mhaveman - * Changed string lengths of PNMI_STRUCT_DATA structure because - * string OIDs are now encoded with leading length ocetet. - * - * Revision 1.18 1998/10/29 08:52:27 mhaveman - * -Added byte to strings in PNMI_STRUCT_DATA structure. - * -Shortened SK_PNMI_RLMT structure to SK_MAX_MACS elements. - * - * Revision 1.17 1998/10/28 08:49:50 mhaveman - * -Changed type of Instance back to SK_U32 because of VPD - * -Changed type from SK_U8 to char of PciBusSpeed, PciBusWidth, PMD, - * and Connector. - * - * Revision 1.16 1998/10/22 10:42:31 mhaveman - * -Removed (SK_U32) casts for OIDs - * -excluded NDIS OIDs when they are already defined with ifndef _NDIS_ - * - * Revision 1.15 1998/10/20 13:56:28 mhaveman - * Headerfile includes now directly other header files to comile correctly. - * - * Revision 1.14 1998/10/20 07:31:09 mhaveman - * Made type changes to unsigned int where possible. - * - * Revision 1.13 1998/10/19 10:53:13 mhaveman - * -Casted OID definitions to SK_U32 - * -Renamed RlmtMAC... to RlmtPort... - * -Changed wrong type of VpdEntriesList from SK_U32 to char * - * - * Revision 1.12 1998/10/13 07:42:27 mhaveman - * -Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA - * -Removed old cvs history entries - * -Renamed MacNumber to PortNumber - * - * Revision 1.11 1998/10/07 10:55:24 mhaveman - * -Added OID_MDB_VERSION. Therefore was a renumbering of the VPD OIDs - * necessary. - * -Added OID_GEN_ Ids to support the windows driver. - * - * Revision 1.10 1998/09/30 13:41:10 mhaveman - * Renamed some OIDs to reduce usage of 'MAC' which is replaced by 'PORT'. - * - * Revision 1.9 1998/09/04 17:06:17 mhaveman - * -Added SyncCounter as macro. - * -Renamed OID_SKGE_.._NO_DESCR_CTS to OID_SKGE_.._NO_BUF_CTS. - * -Added macros for driver description and version strings. - * - * Revision 1.8 1998/09/04 14:36:52 mhaveman - * Added OIDs and Structure to access value of macro counters which are - * counted by the driver. - * - * Revision 1.7 1998/09/04 11:59:36 mhaveman - * Everything compiles now. Driver Macros for counting still missing. - * - ****************************************************************************/ - #ifndef _SKGEPNMI_H_ #define _SKGEPNMI_H_ @@ -239,7 +33,7 @@ #include "h/sktypes.h" #include "h/skerror.h" #include "h/sktimer.h" -#include "h/ski2c.h" +#include "h/sktwsi.h" #include "h/skaddr.h" #include "h/skrlmt.h" #include "h/skvpd.h" @@ -249,7 +43,6 @@ */ #define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */ - /* * Event definitions */ @@ -262,16 +55,13 @@ #define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */ #define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */ #define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */ - #define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */ #define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */ #define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */ #define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */ #define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */ -#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets - 1 = single net; 2 = dual net */ -#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */ - +#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* Number of nets (1 or 2). */ +#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */ /* * Return values @@ -284,7 +74,7 @@ #define SK_PNMI_ERR_UNKNOWN_OID 5 #define SK_PNMI_ERR_UNKNOWN_INST 6 #define SK_PNMI_ERR_UNKNOWN_NET 7 - +#define SK_PNMI_ERR_NOT_SUPPORTED 10 /* * Return values of driver reset function SK_DRIVER_RESET() and @@ -293,19 +83,17 @@ #define SK_PNMI_ERR_OK 0 #define SK_PNMI_ERR_FAIL 1 - /* * Return values of driver test function SK_DRIVER_SELFTEST() */ #define SK_PNMI_TST_UNKNOWN (1 << 0) -#define SK_PNMI_TST_TRANCEIVER (1 << 1) +#define SK_PNMI_TST_TRANCEIVER (1 << 1) #define SK_PNMI_TST_ASIC (1 << 2) #define SK_PNMI_TST_SENSOR (1 << 3) -#define SK_PNMI_TST_POWERMGMT (1 << 4) +#define SK_PNMI_TST_POWERMGMT (1 << 4) #define SK_PNMI_TST_PCI (1 << 5) #define SK_PNMI_TST_MAC (1 << 6) - /* * RLMT specific definitions */ @@ -355,7 +143,7 @@ /* #define OID_802_3_MULTICAST_LIST 0x01010103 */ /* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */ /* #define OID_802_3_MAC_OPTIONS 0x01010105 */ - + #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 #define OID_802_3_XMIT_ONE_COLLISION 0x01020102 #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 @@ -389,7 +177,7 @@ #define OID_SKGE_VPD_VALUE 0xFF010106 #define OID_SKGE_VPD_ACCESS 0xFF010107 #define OID_SKGE_VPD_ACTION 0xFF010108 - + #define OID_SKGE_PORT_NUMBER 0xFF010110 #define OID_SKGE_DEVICE_TYPE 0xFF010111 #define OID_SKGE_DRIVER_DESCR 0xFF010112 @@ -430,13 +218,25 @@ #define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141 #define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142 #define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143 -#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160 + +#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150 +#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151 +#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152 +#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153 +#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154 +#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155 + +#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160 +#define OID_SKGE_SET_TEAM_MAC_ADDRESS 0xFF010161 +#define OID_SKGE_DEVICE_INFORMATION 0xFF010162 #define OID_SKGE_SPEED_CAP 0xFF010170 #define OID_SKGE_SPEED_MODE 0xFF010171 #define OID_SKGE_SPEED_STATUS 0xFF010172 -#define OID_SKGE_SENSOR_NUMBER 0xFF020100 +#define OID_SKGE_BOARDLEVEL 0xFF010180 + +#define OID_SKGE_SENSOR_NUMBER 0xFF020100 #define OID_SKGE_SENSOR_INDEX 0xFF020101 #define OID_SKGE_SENSOR_DESCR 0xFF020102 #define OID_SKGE_SENSOR_TYPE 0xFF020103 @@ -527,13 +327,6 @@ #define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168 #define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169 -#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150 -#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151 -#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152 -#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153 -#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154 -#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155 - #define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170 #define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171 #define OID_SKGE_TX_RETRY 0xFF020172 @@ -554,27 +347,98 @@ #define OID_SKGE_ALL_DATA 0xFF020190 /* Defines for VCT. */ -#define OID_SKGE_VCT_GET 0xFF020200 -#define OID_SKGE_VCT_SET 0xFF020201 -#define OID_SKGE_VCT_STATUS 0xFF020202 +#define OID_SKGE_VCT_GET 0xFF020200 +#define OID_SKGE_VCT_SET 0xFF020201 +#define OID_SKGE_VCT_STATUS 0xFF020202 +#define OID_SKGE_VCT_CAPABILITIES 0xFF020203 + +#ifdef SK_DIAG_SUPPORT +/* Defines for driver DIAG mode. */ +#define OID_SKGE_DIAG_MODE 0xFF020204 +#endif /* SK_DIAG_SUPPORT */ + +/* New OIDs */ +#define OID_SKGE_DRIVER_RELDATE 0xFF020210 +#define OID_SKGE_DRIVER_FILENAME 0xFF020211 +#define OID_SKGE_CHIPID 0xFF020212 +#define OID_SKGE_RAMSIZE 0xFF020213 +#define OID_SKGE_VAUXAVAIL 0xFF020214 +#define OID_SKGE_PHY_TYPE 0xFF020215 +#define OID_SKGE_PHY_LP_MODE 0xFF020216 + +/* + * Added for new DualNet IM driver V2 + * these OIDs should later be in pnmi.h + */ +#define OID_SKGE_MAC_COUNT 0xFF020217 +#define OID_SKGE_DUALNET_MODE 0xFF020218 +#define OID_SKGE_SET_TAGHEADER 0xFF020219 + +#ifdef SK_ASF +/* Defines for ASF */ +#define OID_SKGE_ASF 0xFF02021a +#define OID_SKGE_ASF_STORE_CONFIG 0xFF02021b +#define OID_SKGE_ASF_ENA 0xFF02021c +#define OID_SKGE_ASF_RETRANS 0xFF02021d +#define OID_SKGE_ASF_RETRANS_INT 0xFF02021e +#define OID_SKGE_ASF_HB_ENA 0xFF02021f +#define OID_SKGE_ASF_HB_INT 0xFF020220 +#define OID_SKGE_ASF_WD_ENA 0xFF020221 +#define OID_SKGE_ASF_WD_TIME 0xFF020222 +#define OID_SKGE_ASF_IP_SOURCE 0xFF020223 +#define OID_SKGE_ASF_MAC_SOURCE 0xFF020224 +#define OID_SKGE_ASF_IP_DEST 0xFF020225 +#define OID_SKGE_ASF_MAC_DEST 0xFF020226 +#define OID_SKGE_ASF_COMMUNITY_NAME 0xFF020227 +#define OID_SKGE_ASF_RSP_ENA 0xFF020228 +#define OID_SKGE_ASF_RETRANS_COUNT_MIN 0xFF020229 +#define OID_SKGE_ASF_RETRANS_COUNT_MAX 0xFF02022a +#define OID_SKGE_ASF_RETRANS_INT_MIN 0xFF02022b +#define OID_SKGE_ASF_RETRANS_INT_MAX 0xFF02022c +#define OID_SKGE_ASF_HB_INT_MIN 0xFF02022d +#define OID_SKGE_ASF_HB_INT_MAX 0xFF02022e +#define OID_SKGE_ASF_WD_TIME_MIN 0xFF02022f +#define OID_SKGE_ASF_WD_TIME_MAX 0xFF020230 +#define OID_SKGE_ASF_HB_CAP 0xFF020231 +#define OID_SKGE_ASF_WD_TIMER_RES 0xFF020232 +#define OID_SKGE_ASF_GUID 0xFF020233 +#define OID_SKGE_ASF_KEY_OP 0xFF020234 +#define OID_SKGE_ASF_KEY_ADM 0xFF020235 +#define OID_SKGE_ASF_KEY_GEN 0xFF020236 +#define OID_SKGE_ASF_CAP 0xFF020237 +#define OID_SKGE_ASF_PAR_1 0xFF020238 +#define OID_SKGE_ASF_OVERALL_OID 0xFF020239 +#endif /* SK_ASF */ + + +// Defined for yukon2 path only +#define OID_SKGE_UPPER_MINIPORT 0xFF02023D + + +#ifdef SK_ASF +/* Defines for ASF */ +#define OID_SKGE_ASF_FWVER_OID 0xFF020240 +#define OID_SKGE_ASF_ACPI_OID 0xFF020241 +#define OID_SKGE_ASF_SMBUS_OID 0xFF020242 +#endif /* SK_ASF */ /* VCT struct to store a backup copy of VCT data after a port reset. */ typedef struct s_PnmiVct { SK_U8 VctStatus; - SK_U8 PCableLen; - SK_U32 PMdiPairLen[4]; - SK_U8 PMdiPairSts[4]; + SK_U8 CableLen; + SK_U32 MdiPairLen[4]; + SK_U8 MdiPairSts[4]; } SK_PNMI_VCT; /* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */ -#define SK_PNMI_VCT_NONE 0 -#define SK_PNMI_VCT_OLD_VCT_DATA 1 -#define SK_PNMI_VCT_NEW_VCT_DATA 2 -#define SK_PNMI_VCT_OLD_DSP_DATA 4 -#define SK_PNMI_VCT_NEW_DSP_DATA 8 -#define SK_PNMI_VCT_RUNNING 16 +#define SK_PNMI_VCT_NONE 0x00 +#define SK_PNMI_VCT_OLD_VCT_DATA 0x01 +#define SK_PNMI_VCT_NEW_VCT_DATA 0x02 +#define SK_PNMI_VCT_OLD_DSP_DATA 0x04 +#define SK_PNMI_VCT_NEW_DSP_DATA 0x08 +#define SK_PNMI_VCT_RUNNING 0x10 /* VCT cable test status. */ @@ -582,7 +446,12 @@ typedef struct s_PnmiVct { #define SK_PNMI_VCT_SHORT_CABLE 1 #define SK_PNMI_VCT_OPEN_CABLE 2 #define SK_PNMI_VCT_TEST_FAIL 3 -#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4 +#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4 +#define SK_PNMI_VCT_NOT_PRESENT 5 + +/* VCT capabilities (needed for OID_SKGE_VCT_CAPABILITIES. */ +#define SK_PNMI_VCT_SUPPORTED 1 +#define SK_PNMI_VCT_NOT_SUPPORTED 0 #define OID_SKGE_TRAP_SEN_WAR_LOW 500 #define OID_SKGE_TRAP_SEN_WAR_UPP 501 @@ -594,6 +463,22 @@ typedef struct s_PnmiVct { #define OID_SKGE_TRAP_RLMT_PORT_UP 523 #define OID_SKGE_TRAP_RLMT_SEGMENTATION 524 +#ifdef SK_DIAG_SUPPORT +/* Defines for driver DIAG mode. */ +#define SK_DIAG_ATTACHED 2 +#define SK_DIAG_RUNNING 1 +#define SK_DIAG_IDLE 0 +#endif /* SK_DIAG_SUPPORT */ + +/* + * Generic PNMI IOCTL subcommand definitions. + */ +#define SK_GET_SINGLE_VAR 1 +#define SK_SET_SINGLE_VAR 2 +#define SK_PRESET_SINGLE_VAR 3 +#define SK_GET_FULL_MIB 4 +#define SK_SET_FULL_MIB 5 +#define SK_PRESET_FULL_MIB 6 /* * Define error numbers and messages for syslog @@ -627,7 +512,7 @@ typedef struct s_PnmiVct { #define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14) #define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys" #define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15) -#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small" +#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys too small" #define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16) #define SK_PNMI_ERR016MSG "Vpd: Key string too long" #define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17) @@ -669,9 +554,9 @@ typedef struct s_PnmiVct { #define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36) #define SK_PNMI_ERR036MSG "" #define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37) -#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0" +#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event returned not 0" #define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38) -#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0" +#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event returned not 0" #define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39) #define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID" #define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40) @@ -689,9 +574,9 @@ typedef struct s_PnmiVct { #define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46) #define SK_PNMI_ERR046MSG "Monitor: Unknown OID" #define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47) -#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0" +#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returned not 0" #define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48) -#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0" +#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returned not 0" #define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49) #define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!" #define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50) @@ -700,6 +585,14 @@ typedef struct s_PnmiVct { #define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious" #define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52) #define SK_PNMI_ERR052MSG "" +#define SK_PNMI_ERR053 (SK_ERRBASE_PNMI + 53) +#define SK_PNMI_ERR053MSG "General: Driver release date not initialized" +#define SK_PNMI_ERR054 (SK_ERRBASE_PNMI + 54) +#define SK_PNMI_ERR054MSG "General: Driver release date string too long" +#define SK_PNMI_ERR055 (SK_ERRBASE_PNMI + 55) +#define SK_PNMI_ERR055MSG "General: Driver file name not initialized" +#define SK_PNMI_ERR056 (SK_ERRBASE_PNMI + 56) +#define SK_PNMI_ERR056MSG "General: Driver file name string too long" /* * Management counter macros called by the driver @@ -710,6 +603,11 @@ typedef struct s_PnmiVct { #define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \ (char *)(v)) +#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v) ((pAC)->Pnmi.pDriverReleaseDate = \ + (char *)(v)) + +#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v) ((pAC)->Pnmi.pDriverFileName = \ + (char *)(v)) #define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \ { \ @@ -886,6 +784,8 @@ typedef struct s_PnmiConf { char ConfMacFactoryAddr[6]; SK_U8 ConfPMD; SK_U8 ConfConnector; + SK_U32 ConfPhyType; + SK_U32 ConfPhyMode; SK_U8 ConfLinkCapability; SK_U8 ConfLinkMode; SK_U8 ConfLinkModeStatus; @@ -934,9 +834,14 @@ typedef struct s_PnmiStrucData { SK_U32 DeviceType; char DriverDescr[SK_PNMI_STRINGLEN1]; char DriverVersion[SK_PNMI_STRINGLEN2]; + char DriverReleaseDate[SK_PNMI_STRINGLEN1]; + char DriverFileName[SK_PNMI_STRINGLEN1]; char HwDescr[SK_PNMI_STRINGLEN1]; char HwVersion[SK_PNMI_STRINGLEN2]; SK_U16 Chipset; + SK_U32 ChipId; + SK_U8 VauxAvail; + SK_U32 RamSize; SK_U32 MtuSize; SK_U32 Action; SK_U32 TestResult; @@ -981,23 +886,25 @@ typedef struct s_PnmiStrucData { } SK_PNMI_STRUCT_DATA; #define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA)) + +/* The ReturnStatus field must be located before VpdFreeBytes! */ #define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\ &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes)) - /* - * ReturnStatus field - * must be located - * before VpdFreeBytes - */ /* * Various definitions */ +#define SK_PNMI_EVT_TIMER_CHECK 28125000L /* 28125 ms */ + +#define SK_PNMI_VCT_TIMER_CHECK 4000000L /* 4 sec. */ + #define SK_PNMI_MAX_PROTOS 3 -#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum - * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK - * for check while init phase 1 - */ +/* + * SK_PNMI_CNT_NO must have the value of the enum SK_PNMI_MAX_IDX. + * Define SK_PNMI_CHECK to check this during init level SK_INIT_IO. + */ +#define SK_PNMI_CNT_NO 66 /* * Estimate data structure @@ -1010,14 +917,6 @@ typedef struct s_PnmiEstimate { } SK_PNMI_ESTIMATE; -/* - * VCT timer data structure - */ -typedef struct s_VctTimer { - SK_TIMER VctTimer; -} SK_PNMI_VCT_TIMER; - - /* * PNMI specific adapter context structure */ @@ -1060,6 +959,8 @@ typedef struct s_PnmiData { char *pDriverDescription; char *pDriverVersion; + char *pDriverReleaseDate; + char *pDriverFileName; int MacUpdatedFlag; int RlmtUpdatedFlag; @@ -1086,29 +987,35 @@ typedef struct s_PnmiData { unsigned int TrapQueueEnd; unsigned int TrapBufPad; unsigned int TrapUnique; - SK_U8 VctStatus[SK_MAX_MACS]; - SK_PNMI_VCT VctBackup[SK_MAX_MACS]; - SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS]; + SK_U8 VctStatus[SK_MAX_MACS]; + SK_PNMI_VCT VctBackup[SK_MAX_MACS]; + SK_TIMER VctTimeout[SK_MAX_MACS]; +#ifdef SK_DIAG_SUPPORT + SK_U32 DiagAttached; +#endif /* SK_DIAG_SUPPORT */ + SK_BOOL VpdKeyReadError; } SK_PNMI; /* * Function prototypes */ -extern int SkPnmiInit(SK_AC *pAc, SK_IOC IoC, int level); -extern int SkPnmiGetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, void* pBuf, +extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level); +extern int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf, unsigned int* pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiPreSetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, +extern int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiSetVar(SK_AC *pAc, SK_IOC IoC, SK_U32 Id, void* pBuf, +extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiGetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, +extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiPreSetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, +extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiSetStruct(SK_AC *pAc, SK_IOC IoC, void* pBuf, +extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiEvent(SK_AC *pAc, SK_IOC IoC, SK_U32 Event, +extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param); +extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf, + unsigned int * pLen, SK_U32 NetIndex); #endif diff --git a/drivers/sk98lin/h/skgesirq.h b/drivers/sk98lin/h/skgesirq.h index fc001b2..598947c 100644 --- a/drivers/sk98lin/h/skgesirq.h +++ b/drivers/sk98lin/h/skgesirq.h @@ -1,124 +1,40 @@ /****************************************************************************** * * Name: skgesirq.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.26 $ - * Date: $Date: 2002/10/14 09:52:36 $ - * Purpose: SK specific Gigabit Ethernet special IRQ functions + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Gigabit Ethernet special IRQ functions * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2005 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * $Log: skgesirq.h,v $ - * Revision 1.26 2002/10/14 09:52:36 rschmidt - * Added SKERR_SIRQ_E023 and SKERR_SIRQ_E023 for GPHY (Yukon) - * Editorial changes - * - * Revision 1.25 2002/07/15 18:15:52 rwahl - * Editorial changes. - * - * Revision 1.24 2002/07/15 15:39:21 rschmidt - * Corrected define for SKERR_SIRQ_E022 - * Editorial changes - * - * Revision 1.23 2002/04/25 11:09:45 rschmidt - * Removed declarations for SkXmInitPhy(), SkXmRxTxEnable() - * Editorial changes - * - * Revision 1.22 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.21 2000/10/18 12:22:40 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.20 1999/12/06 10:00:44 cgoos - * Added SET event for role. - * - * Revision 1.19 1999/11/22 13:58:26 cgoos - * Changed license header to GPL. - * - * Revision 1.18 1999/05/19 07:32:59 cgoos - * Changes for 1000Base-T. - * - * Revision 1.17 1999/03/12 13:29:31 malthoff - * Move Autonegotiation Error Codes to skgeinit.h. - * - * Revision 1.16 1999/03/08 10:11:28 gklug - * add: AutoNegDone return codes - * - * Revision 1.15 1998/11/18 13:20:53 gklug - * add: different timeouts for active and non-active links - * - * Revision 1.14 1998/11/04 07:18:14 cgoos - * Added prototype for SkXmRxTxEnable. - * - * Revision 1.13 1998/10/21 05:52:23 gklug - * add: parameter DoLoop to InitPhy function - * - * Revision 1.12 1998/10/19 06:45:03 cgoos - * Added prototype for SkXmInitPhy. - * - * Revision 1.11 1998/10/15 14:34:10 gklug - * add: WA_TIME is 500 msec - * - * Revision 1.10 1998/10/14 14:49:41 malthoff - * Remove err log defines E021 and E022. They are - * defined in skgeinit.h now. - * - * Revision 1.9 1998/10/14 14:00:39 gklug - * add: error logs for init phys - * - * Revision 1.8 1998/10/14 05:44:05 gklug - * add: E020 - * - * Revision 1.7 1998/10/02 06:24:58 gklug - * add: error messages - * - * Revision 1.6 1998/10/01 07:54:45 gklug - * add: PNMI debug module - * - * Revision 1.5 1998/09/28 13:36:31 malthoff - * Move the bit definitions for Autonegotiation - * and Flow Control to skgeinit.h. - * - * Revision 1.4 1998/09/15 12:29:34 gklug - * add: error logs - * - * Revision 1.3 1998/09/03 13:54:02 gklug - * add: function prototypes - * - * Revision 1.2 1998/09/03 10:24:36 gklug - * add: Events send by PNMI - * add: parameter definition for Flow Control etc. - * - * Revision 1.1 1998/08/27 11:50:27 gklug - * initial revision - * + * /LICENSE * ******************************************************************************/ #ifndef _INC_SKGESIRQ_H_ #define _INC_SKGESIRQ_H_ +/* Define return codes of SkGePortCheckUp and CheckShort */ +#define SK_HW_PS_NONE 0 /* No action needed */ +#define SK_HW_PS_RESTART 1 /* Restart needed */ +#define SK_HW_PS_LINK 2 /* Link Up actions needed */ + /* * Define the Event the special IRQ/INI module can handle */ -#define SK_HWEV_WATIM 1 /* Timeout for WA errata #2 XMAC */ +#define SK_HWEV_WATIM 1 /* Timeout for WA Errata #2 XMAC */ #define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */ #define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */ #define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */ @@ -129,10 +45,10 @@ #define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */ #define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */ -#define SK_WA_ACT_TIME (5000000L) /* 5 sec */ -#define SK_WA_INA_TIME (100000L) /* 100 msec */ +#define SK_WA_ACT_TIME 1000000UL /* 1000 msec (1 sec) */ +#define SK_WA_INA_TIME 100000UL /* 100 msec */ -#define SK_HALFDUP_CHK_TIME (10000L) /* 10 msec */ +#define SK_HALFDUP_CHK_TIME 10000UL /* 10 msec */ /* * Define the error numbers and messages @@ -160,9 +76,9 @@ #define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1) #define SKERR_SIRQ_E011MSG "CHECK failure XA2" #define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1) -#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error" +#define SKERR_SIRQ_E012MSG "Unexpected IRQ Master error" #define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1) -#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error" +#define SKERR_SIRQ_E013MSG "Unexpected IRQ Status error" #define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1) #define SKERR_SIRQ_E014MSG "Parity error on RAM (read)" #define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1) @@ -185,10 +101,37 @@ #define SKERR_SIRQ_E023MSG "Auto-negotiation error" #define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1) #define SKERR_SIRQ_E024MSG "FIFO overflow error" +#define SKERR_SIRQ_E025 (SKERR_SIRQ_E024+1) +#define SKERR_SIRQ_E025MSG "2 Pair Downshift detected" +#define SKERR_SIRQ_E026 (SKERR_SIRQ_E025+1) +#define SKERR_SIRQ_E026MSG "Uncorrectable PCI Express error" +#define SKERR_SIRQ_E027 (SKERR_SIRQ_E026+1) +#define SKERR_SIRQ_E027MSG "PCI Bus Abort detected" +#define SKERR_SIRQ_E028 (SKERR_SIRQ_E027+1) +#define SKERR_SIRQ_E028MSG "Parity error on RAM 1 (read)" +#define SKERR_SIRQ_E029 (SKERR_SIRQ_E028+1) +#define SKERR_SIRQ_E029MSG "Parity error on RAM 1 (write)" +#define SKERR_SIRQ_E030 (SKERR_SIRQ_E029+1) +#define SKERR_SIRQ_E030MSG "Parity error on RAM 2 (read)" +#define SKERR_SIRQ_E031 (SKERR_SIRQ_E030+1) +#define SKERR_SIRQ_E031MSG "Parity error on RAM 2 (write)" +#define SKERR_SIRQ_E032 (SKERR_SIRQ_E031+1) +#define SKERR_SIRQ_E032MSG "TCP segmentation error async. queue 1" +#define SKERR_SIRQ_E033 (SKERR_SIRQ_E032+1) +#define SKERR_SIRQ_E033MSG "TCP segmentation error sync. queue 1" +#define SKERR_SIRQ_E034 (SKERR_SIRQ_E033+1) +#define SKERR_SIRQ_E034MSG "TCP segmentation error async. queue 2" +#define SKERR_SIRQ_E035 (SKERR_SIRQ_E034+1) +#define SKERR_SIRQ_E035MSG "TCP segmentation error sync. queue 2" +#define SKERR_SIRQ_E036 (SKERR_SIRQ_E035+1) +#define SKERR_SIRQ_E036MSG "CHECK failure polling unit" extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); extern void SkHWLinkUp(SK_AC *pAC, SK_IOC IoC, int Port); extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port); +extern void SkGeYuSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); +extern void SkYuk2SirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); #endif /* _INC_SKGESIRQ_H_ */ + diff --git a/drivers/sk98lin/h/skgetwsi.h b/drivers/sk98lin/h/skgetwsi.h new file mode 100644 index 0000000..6b201ad --- /dev/null +++ b/drivers/sk98lin/h/skgetwsi.h @@ -0,0 +1,243 @@ +/****************************************************************************** + * + * Name: skgetwsi.h + * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Special defines for TWSI + * + ******************************************************************************/ + +/****************************************************************************** + * + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2004 Marvell. + * + * 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. + * The information in this file is provided "AS IS" without warranty. + * /LICENSE + * + ******************************************************************************/ + +/* + * SKGETWSI.H contains all SK-98xx specific defines for the TWSI handling + */ + +#ifndef _INC_SKGETWSI_H_ +#define _INC_SKGETWSI_H_ + +/* + * Macros to access the B2_I2C_CTRL + */ +#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \ + SK_OUT32(IoC, B2_I2C_CTRL,\ + (flag ? 0x80000000UL : 0x0L) | \ + (((SK_U32)reg << 16) & I2C_ADDR) | \ + (((SK_U32)dev << 9) & I2C_DEV_SEL) | \ + (dev_size & I2C_DEV_SIZE) | \ + ((burst << 4) & I2C_BURST_LEN)) + +#define SK_I2C_STOP(IoC) { \ + SK_U32 I2cCtrl; \ + SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \ + SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \ +} + +#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl) + +/* + * Macros to access the TWSI SW Registers + */ +#define SK_I2C_SET_BIT(IoC, SetBits) { \ + SK_U8 OrgBits; \ + SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ + SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \ +} + +#define SK_I2C_CLR_BIT(IoC, ClrBits) { \ + SK_U8 OrgBits; \ + SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ + SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \ +} + +#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw) + +/* + * define the possible sensor states + */ +#define SK_SEN_IDLE 0 /* Idle: sensor not read */ +#define SK_SEN_VALUE 1 /* Value Read cycle */ +#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */ + +/* + * Conversion factor to convert read Voltage sensor to milli Volt + * Conversion factor to convert read Temperature sensor to 10th degree Celsius + */ +#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */ +#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */ +#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */ + +/* + * formula: counter = (22500*60)/(rpm * divisor * pulses/2) + * assuming: 6500rpm, 4 pulses, divisor 1 + */ +#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2)) + +/* + * Define sensor management data + * Maximum is reached on Genesis copper dual port and Yukon-64 + * Board specific maximum is in pAC->I2c.MaxSens + */ +#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */ +#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */ + +/* + * To watch the state machine (SM) use the timer in two ways + * instead of one as hitherto + */ +#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */ +#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */ + +/* + * Defines for the individual thresholds + */ + +#define C_PLUS_20 120 / 100 +#define C_PLUS_15 115 / 100 +#define C_PLUS_10 110 / 100 +#define C_PLUS_5 105 / 100 +#define C_MINUS_5 95 / 100 +#define C_MINUS_10 90 / 100 +#define C_MINUS_15 85 / 100 + +/* Temperature sensor */ +#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */ +#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */ +#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */ +#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */ + +/* VCC which should be 5 V */ +#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */ +#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */ +#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */ +#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */ + +/* + * VIO may be 5 V or 3.3 V. Initialization takes two parts: + * 1. Initialize lowest lower limit and highest higher limit. + * 2. After the first value is read correct the upper or the lower limit to + * the appropriate C constant. + * + * Warning limits are +-5% of the exepected voltage. + * Error limits are +-10% of the expected voltage. + */ + +/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */ + +#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */ +#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */ + /* 5000 mVolt */ +#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */ +#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */ + +#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */ + +/* correction values for the second pass */ +#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */ +#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */ + /* 3300 mVolt */ +#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */ +#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */ + +/* + * VDD voltage + */ +#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */ +#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */ +#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */ +#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */ + +/* + * PHY PLL 3V3 voltage + */ +#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */ +#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */ +#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */ +#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */ + +/* + * VAUX (YUKON only) + */ +#define SK_SEN_VAUX_3V3_VAL 3300 /* Voltage VAUX 3.3 Volt */ + +#define SK_SEN_VAUX_3V3_HIGH_ERR (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_PLUS_10) +#define SK_SEN_VAUX_3V3_HIGH_WARN (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_PLUS_5) +#define SK_SEN_VAUX_3V3_LOW_WARN (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_MINUS_5) +#define SK_SEN_VAUX_3V3_LOW_ERR (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_MINUS_10) + +#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */ + +/* + * PHY 2V5 voltage + */ +#define SK_SEN_PHY_2V5_VAL 2500 /* Voltage PHY 2.5 Volt */ + +#define SK_SEN_PHY_2V5_HIGH_ERR (SK_I32)(SK_SEN_PHY_2V5_VAL * C_PLUS_10) +#define SK_SEN_PHY_2V5_HIGH_WARN (SK_I32)(SK_SEN_PHY_2V5_VAL * C_PLUS_5) +#define SK_SEN_PHY_2V5_LOW_WARN (SK_I32)(SK_SEN_PHY_2V5_VAL * C_MINUS_5) +#define SK_SEN_PHY_2V5_LOW_ERR (SK_I32)(SK_SEN_PHY_2V5_VAL * C_MINUS_10) + +/* + * ASIC Core 1V5 voltage (YUKON only) + */ +#define SK_SEN_CORE_1V5_VAL 1500 /* Voltage ASIC Core 1.5 Volt */ + +#define SK_SEN_CORE_1V5_HIGH_ERR (SK_I32)(SK_SEN_CORE_1V5_VAL * C_PLUS_10) +#define SK_SEN_CORE_1V5_HIGH_WARN (SK_I32)(SK_SEN_CORE_1V5_VAL * C_PLUS_5) +#define SK_SEN_CORE_1V5_LOW_WARN (SK_I32)(SK_SEN_CORE_1V5_VAL * C_MINUS_5) +#define SK_SEN_CORE_1V5_LOW_ERR (SK_I32)(SK_SEN_CORE_1V5_VAL * C_MINUS_10) + +/* + * ASIC Core 1V2 (1V3) voltage (YUKON-2 only) + */ +#define SK_SEN_CORE_1V2_VAL 1200 /* Voltage ASIC Core 1.2 Volt */ + +#define SK_SEN_CORE_1V2_HIGH_ERR (SK_I32)(SK_SEN_CORE_1V2_VAL * C_PLUS_20) +#define SK_SEN_CORE_1V2_HIGH_WARN (SK_I32)(SK_SEN_CORE_1V2_VAL * C_PLUS_15) +#define SK_SEN_CORE_1V2_LOW_WARN (SK_I32)(SK_SEN_CORE_1V2_VAL * C_MINUS_5) +#define SK_SEN_CORE_1V2_LOW_ERR (SK_I32)(SK_SEN_CORE_1V2_VAL * C_MINUS_10) + +#define SK_SEN_CORE_1V3_VAL 1300 /* Voltage ASIC Core 1.3 Volt */ + +#define SK_SEN_CORE_1V3_HIGH_ERR (SK_I32)(SK_SEN_CORE_1V3_VAL * C_PLUS_15) +#define SK_SEN_CORE_1V3_HIGH_WARN (SK_I32)(SK_SEN_CORE_1V3_VAL * C_PLUS_10) +#define SK_SEN_CORE_1V3_LOW_WARN (SK_I32)(SK_SEN_CORE_1V3_VAL * C_MINUS_5) +#define SK_SEN_CORE_1V3_LOW_ERR (SK_I32)(SK_SEN_CORE_1V3_VAL * C_MINUS_10) + +/* + * FAN 1 speed + */ +/* assuming: 6500rpm +-15%, 4 pulses, + * warning at: 80 % + * error at: 70 % + * no upper limit + */ +#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */ +#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */ +#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */ +#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */ + +/* + * Some Voltages need dynamic thresholds + */ +#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */ +#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */ +#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */ + +extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); +#endif /* n_INC_SKGETWSI_H */ + diff --git a/drivers/sk98lin/h/ski2c.h b/drivers/sk98lin/h/ski2c.h index 5ffaf6e..9a4d1dc 100644 --- a/drivers/sk98lin/h/ski2c.h +++ b/drivers/sk98lin/h/ski2c.h @@ -2,8 +2,8 @@ * * Name: ski2c.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.34 $ - * Date: $Date: 2003/01/28 09:11:21 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines to access Voltage and Temperature Sensor * ******************************************************************************/ @@ -26,6 +26,15 @@ * History: * * $Log: ski2c.h,v $ + * Revision 1.1.1.1 2008-12-15 11:39:21 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:11 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:16 wokes + * marvell 88f6281 u-boot + * * Revision 1.34 2003/01/28 09:11:21 rschmidt * Editorial changes * diff --git a/drivers/sk98lin/h/skqueue.h b/drivers/sk98lin/h/skqueue.h index bce20a7..c940655 100644 --- a/drivers/sk98lin/h/skqueue.h +++ b/drivers/sk98lin/h/skqueue.h @@ -1,17 +1,17 @@ /****************************************************************************** * * Name: skqueue.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.14 $ - * Date: $Date: 2002/03/15 10:52:13 $ + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines for the Event queue * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -22,60 +22,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skqueue.h,v $ - * Revision 1.14 2002/03/15 10:52:13 mkunz - * Added event classes for link aggregation - * - * Revision 1.13 1999/11/22 13:59:05 cgoos - * Changed license header to GPL. - * - * Revision 1.12 1998/09/08 08:48:01 gklug - * add: init level handling - * - * Revision 1.11 1998/09/03 14:15:11 gklug - * add: CSUM and HWAC Eventclass and function. - * fix: pParaPtr according to CCC - * - * Revision 1.10 1998/08/20 12:43:03 gklug - * add: typedef SK_QUEUE - * - * Revision 1.9 1998/08/19 09:50:59 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.8 1998/08/18 07:00:01 gklug - * fix: SK_PTR not defined use void * instead. - * - * Revision 1.7 1998/08/17 13:43:19 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.6 1998/08/14 07:09:30 gklug - * fix: chg pAc -> pAC - * - * Revision 1.5 1998/08/11 14:26:44 gklug - * chg: Event Dispatcher returns now int. - * - * Revision 1.4 1998/08/11 12:15:21 gklug - * add: Error numbers of skqueue module - * - * Revision 1.3 1998/08/07 12:54:23 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:34:00 gklug - * adapt structure defs to CCC - * add: prototypes for functions - * - * Revision 1.1 1998/07/30 14:52:12 gklug - * Initial version. - * Defines Event Classes, Event structs and queue management variables. - * - * - * - ******************************************************************************/ - /* * SKQUEUE.H contains all defines and types for the event queue */ @@ -89,7 +35,7 @@ */ #define SKGE_DRV 1 /* Driver Event Class */ #define SKGE_RLMT 2 /* RLMT Event Class */ -#define SKGE_I2C 3 /* i2C Event Class */ +#define SKGE_I2C 3 /* I2C Event Class */ #define SKGE_PNMI 4 /* PNMI Event Class */ #define SKGE_CSUM 5 /* Checksum Event Class */ #define SKGE_HWAC 6 /* Hardware Access Event Class */ @@ -99,6 +45,9 @@ #define SKGE_RSF 11 /* RSF Aggregation Event Class */ #define SKGE_MARKER 12 /* MARKER Aggregation Event Class */ #define SKGE_FD 13 /* FD Distributor Event Class */ +#ifdef SK_ASF +#define SKGE_ASF 14 /* ASF Event Class */ +#endif /* * define event queue as circular buffer @@ -118,25 +67,25 @@ typedef union u_EvPara { * Event Queue * skqueue.c * events are class/value pairs - * class is addressee, e.g. RMT, PCM etc. + * class is addressee, e.g. RLMT, PNMI etc. * value is command, e.g. line state change, ring op change etc. */ typedef struct s_EventElem { - SK_U32 Class ; /* Event class */ - SK_U32 Event ; /* Event value */ - SK_EVPARA Para ; /* Event parameter */ + SK_U32 Class; /* Event class */ + SK_U32 Event; /* Event value */ + SK_EVPARA Para; /* Event parameter */ } SK_EVENTELEM; typedef struct s_Queue { SK_EVENTELEM EvQueue[SK_MAX_EVENT]; - SK_EVENTELEM *EvPut ; - SK_EVENTELEM *EvGet ; + SK_EVENTELEM *EvPut; + SK_EVENTELEM *EvGet; } SK_QUEUE; extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level); extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event, SK_EVPARA Para); -extern int SkEventDispatcher(SK_AC *pAC,SK_IOC Ioc); +extern int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc); /* Define Error Numbers and messages */ @@ -144,4 +93,11 @@ extern int SkEventDispatcher(SK_AC *pAC,SK_IOC Ioc); #define SKERR_Q_E001MSG "Event queue overflow" #define SKERR_Q_E002 (SKERR_Q_E001+1) #define SKERR_Q_E002MSG "Undefined event class" +#define SKERR_Q_E003 (SKERR_Q_E001+2) +#define SKERR_Q_E003MSG "Event queued in Init Level 0" +#define SKERR_Q_E004 (SKERR_Q_E001+3) +#define SKERR_Q_E004MSG "Error Reported from Event Fuction (Queue Blocked)" +#define SKERR_Q_E005 (SKERR_Q_E001+4) +#define SKERR_Q_E005MSG "Event scheduler called in Init Level 0 or 1" #endif /* _SKQUEUE_H_ */ + diff --git a/drivers/sk98lin/h/skrlmt.h b/drivers/sk98lin/h/skrlmt.h index 04d025b..947491c 100644 --- a/drivers/sk98lin/h/skrlmt.h +++ b/drivers/sk98lin/h/skrlmt.h @@ -2,15 +2,17 @@ * * Name: skrlmt.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.35 $ - * Date: $Date: 2003/01/31 14:12:41 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Header file for Redundant Link ManagemenT. * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2001 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,131 +20,7 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skrlmt.h,v $ - * Revision 1.35 2003/01/31 14:12:41 mkunz - * single port adapter runs now with two identical MAC addresses - * - * Revision 1.34 2002/09/23 15:13:41 rwahl - * Editorial changes. - * - * Revision 1.33 2001/07/03 12:16:48 mkunz - * New Flag ChgBcPrio (Change priority of last broadcast received) - * - * Revision 1.32 2001/02/14 14:06:31 rassmann - * Editorial changes. - * - * Revision 1.31 2001/02/05 14:25:26 rassmann - * Prepared RLMT for transparent operation. - * - * Revision 1.30 2001/01/22 13:41:39 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.29 2000/11/17 08:58:00 rassmann - * Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event. - * - * Revision 1.28 2000/11/09 12:24:34 rassmann - * Editorial changes. - * - * Revision 1.27 1999/11/22 13:59:56 cgoos - * Changed license header to GPL. - * - * Revision 1.26 1999/10/04 14:01:19 rassmann - * Corrected reaction to reception of BPDU frames (#10441). - * - * Revision 1.25 1999/07/20 12:53:39 rassmann - * Fixed documentation errors for lookahead macros. - * - * Revision 1.24 1999/05/28 11:15:56 rassmann - * Changed behaviour to reflect Design Spec v1.2. - * Controlling Link LED(s). - * Introduced RLMT Packet Version field in RLMT Packet. - * Newstyle lookahead macros (checking meta-information before looking at - * the packet). - * - * Revision 1.23 1999/01/28 12:50:42 rassmann - * Not using broadcast time stamps in CheckLinkState mode. - * - * Revision 1.22 1999/01/27 14:13:04 rassmann - * Monitoring broadcast traffic. - * Switching more reliably and not too early if switch is - * configured for spanning tree. - * - * Revision 1.21 1998/12/08 13:11:25 rassmann - * Stopping SegTimer at RlmtStop. - * - * Revision 1.20 1998/11/24 12:37:33 rassmann - * Implemented segmentation check. - * - * Revision 1.19 1998/11/17 13:43:06 rassmann - * Handling (logical) tx failure. - * Sending packet on logical address after PORT_SWITCH. - * - * Revision 1.18 1998/11/13 16:56:56 rassmann - * Added macro version of SkRlmtLookaheadPacket. - * - * Revision 1.17 1998/11/06 18:06:05 rassmann - * Corrected timing when RLMT checks fail. - * Clearing tx counter earlier in periodical checks. - * - * Revision 1.16 1998/11/03 13:53:50 rassmann - * RLMT should switch now (at least in mode 3). - * - * Revision 1.15 1998/10/22 11:39:52 rassmann - * Corrected signed/unsigned mismatches. - * Corrected receive list handling and address recognition. - * - * Revision 1.14 1998/10/15 15:16:36 rassmann - * Finished Spanning Tree checking. - * Checked with lint. - * - * Revision 1.13 1998/09/24 19:16:08 rassmann - * Code cleanup. - * Introduced Timer for PORT_DOWN due to no RX. - * - * Revision 1.12 1998/09/16 11:09:52 rassmann - * Syntax corrections. - * - * Revision 1.11 1998/09/15 11:28:50 rassmann - * Syntax corrections. - * - * Revision 1.10 1998/09/14 17:07:38 rassmann - * Added code for port checking via LAN. - * Changed Mbuf definition. - * - * Revision 1.9 1998/09/07 11:14:15 rassmann - * Syntax corrections. - * - * Revision 1.8 1998/09/07 09:06:08 rassmann - * Syntax corrections. - * - * Revision 1.7 1998/09/04 19:41:34 rassmann - * Syntax corrections. - * Started entering code for checking local links. - * - * Revision 1.6 1998/09/04 12:14:28 rassmann - * Interface cleanup. - * - * Revision 1.5 1998/09/02 16:55:29 rassmann - * Updated to reflect new DRV/HWAC/RLMT interface. - * - * Revision 1.4 1998/09/02 07:26:02 afischer - * typedef for SK_RLMT_PORT - * - * Revision 1.3 1998/08/27 14:29:03 rassmann - * Code cleanup. - * - * Revision 1.2 1998/08/27 14:26:25 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:29:10 rassmann - * First public version. + * /LICENSE * ******************************************************************************/ @@ -169,7 +47,6 @@ #define __INC_SKRLMT_H #ifdef __cplusplus -#error C++ is not yet supported. extern "C" { #endif /* cplusplus */ @@ -296,28 +173,28 @@ unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */ *(pNumBytes) = 0; \ } \ else {\ - if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \ - *(pNumBytes) = 0; \ - } \ - else if (IsBc) { \ - if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \ - *(pNumBytes) = 6; \ - *(pOffset) = 6; \ - } \ - else { \ - *(pNumBytes) = 0; \ - } \ - } \ - else { \ - if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pNumBytes) = 0; \ - } \ - else { \ - *(pNumBytes) = 6; \ - *(pOffset) = 0; \ - } \ - } \ + if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \ + *(pNumBytes) = 0; \ + } \ + else if (IsBc) { \ + if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \ + *(pNumBytes) = 6; \ + *(pOffset) = 6; \ + } \ + else { \ + *(pNumBytes) = 0; \ + } \ + } \ + else { \ + if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \ + /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ + *(pNumBytes) = 0; \ + } \ + else { \ + *(pNumBytes) = 6; \ + *(pOffset) = 0; \ + } \ + } \ } \ } @@ -516,9 +393,9 @@ typedef struct s_Rlmt { /* ----- Private part ----- */ SK_BOOL CheckSwitch; - SK_BOOL RlmtOff; /* set to zero if the Mac addresses - are equal or the second one - is zero */ + SK_BOOL RlmtOff; /* set to zero if the Mac addresses + are equal or the second one + is zero */ SK_U16 Align01; } SK_RLMT; diff --git a/drivers/sk98lin/h/sktimer.h b/drivers/sk98lin/h/sktimer.h index 36f8ccb..ad5d4ca 100644 --- a/drivers/sk98lin/h/sktimer.h +++ b/drivers/sk98lin/h/sktimer.h @@ -1,17 +1,17 @@ /****************************************************************************** * * Name: sktimer.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.9 $ - * Date: $Date: 1999/11/22 14:00:29 $ + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines for the timer functions * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -22,42 +22,6 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: sktimer.h,v $ - * Revision 1.9 1999/11/22 14:00:29 cgoos - * Changed license header to GPL. - * - * Revision 1.8 1998/09/08 08:48:02 gklug - * add: init level handling - * - * Revision 1.7 1998/08/20 12:31:29 gklug - * fix: SK_TIMCTRL needs to be defined - * - * Revision 1.6 1998/08/19 09:51:00 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.5 1998/08/17 13:43:21 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.4 1998/08/14 07:09:31 gklug - * fix: chg pAc -> pAC - * - * Revision 1.3 1998/08/07 12:54:24 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:35:29 gklug - * add: Timer control struct for Adapters context - * add: function prototypes - * - * Revision 1.1 1998/08/05 11:27:01 gklug - * First version: adapted from SMT - * - * - ******************************************************************************/ - /* * SKTIMER.H contains all defines and types for the timer functions */ @@ -75,25 +39,25 @@ typedef struct s_Timer SK_TIMER; struct s_Timer { - SK_TIMER *TmNext ; /* linked list */ - SK_U32 TmClass ; /* Timer Event class */ - SK_U32 TmEvent ; /* Timer Event value */ - SK_EVPARA TmPara ; /* Timer Event parameter */ - SK_U32 TmDelta ; /* delta time */ - int TmActive ; /* flag : active/inactive */ -} ; + SK_TIMER *TmNext; /* linked list */ + SK_U32 TmClass; /* Timer Event class */ + SK_U32 TmEvent; /* Timer Event value */ + SK_EVPARA TmPara; /* Timer Event parameter */ + SK_U32 TmDelta; /* delta time */ + int TmActive; /* flag: active/inactive */ +}; /* * Timer control struct. * - use in Adapters context name pAC->Tim */ typedef struct s_TimCtrl { - SK_TIMER *StQueue ; /* Head of Timer queue */ -} SK_TIMCTRL ; + SK_TIMER *StQueue; /* Head of Timer queue */ +} SK_TIMCTRL; -extern void SkTimerInit(SK_AC *pAC,SK_IOC Ioc, int Level); -extern void SkTimerStop(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer); -extern void SkTimerStart(SK_AC *pAC,SK_IOC Ioc,SK_TIMER *pTimer, - SK_U32 Time,SK_U32 Class,SK_U32 Event,SK_EVPARA Para); -extern void SkTimerDone(SK_AC *pAC,SK_IOC Ioc); +extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level); +extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer); +extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer, + SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para); +extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc); #endif /* _SKTIMER_H_ */ diff --git a/drivers/sk98lin/h/sktwsi.h b/drivers/sk98lin/h/sktwsi.h new file mode 100644 index 0000000..6c88bf3 --- /dev/null +++ b/drivers/sk98lin/h/sktwsi.h @@ -0,0 +1,179 @@ +/****************************************************************************** + * + * Name: sktwsi.h + * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Defines to access Voltage and Temperature Sensor + * + ******************************************************************************/ + +/****************************************************************************** + * + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2003 Marvell. + * + * 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. + * + * The information in this file is provided "AS IS" without warranty. + * /LICENSE + * + ******************************************************************************/ + +/* + * SKTWSI.H contains all TWSI specific defines + */ + +#ifndef _SKTWSI_H_ +#define _SKTWSI_H_ + +typedef struct s_Sensor SK_SENSOR; + +#include "h/skgetwsi.h" + +/* + * Define the TWSI events. + */ +#define SK_I2CEV_IRQ 1 /* IRQ happened Event */ +#define SK_I2CEV_TIM 2 /* Timeout event */ +#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */ + +/* + * Define READ and WRITE Constants. + */ +#define I2C_READ 0 +#define I2C_WRITE 1 +#define I2C_BURST 1 +#define I2C_SINGLE 0 + +#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0) +#define SKERR_I2C_E001MSG "Sensor index unknown" +#define SKERR_I2C_E002 (SKERR_I2C_E001+1) +#define SKERR_I2C_E002MSG "TWSI: transfer does not complete" +#define SKERR_I2C_E003 (SKERR_I2C_E002+1) +#define SKERR_I2C_E003MSG "LM80: NAK on device send" +#define SKERR_I2C_E004 (SKERR_I2C_E003+1) +#define SKERR_I2C_E004MSG "LM80: NAK on register send" +#define SKERR_I2C_E005 (SKERR_I2C_E004+1) +#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send" +#define SKERR_I2C_E006 (SKERR_I2C_E005+1) +#define SKERR_I2C_E006MSG "Unknown event" +#define SKERR_I2C_E007 (SKERR_I2C_E006+1) +#define SKERR_I2C_E007MSG "LM80 read out of state" +#define SKERR_I2C_E008 (SKERR_I2C_E007+1) +#define SKERR_I2C_E008MSG "Unexpected sensor read completed" +#define SKERR_I2C_E009 (SKERR_I2C_E008+1) +#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range" +#define SKERR_I2C_E010 (SKERR_I2C_E009+1) +#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range" +#define SKERR_I2C_E011 (SKERR_I2C_E010+1) +#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range" +#define SKERR_I2C_E012 (SKERR_I2C_E011+1) +#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range" +#define SKERR_I2C_E013 (SKERR_I2C_E012+1) +#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor" +#define SKERR_I2C_E014 (SKERR_I2C_E013+1) +#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range" +#define SKERR_I2C_E015 (SKERR_I2C_E014+1) +#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range" +#define SKERR_I2C_E016 (SKERR_I2C_E015+1) +#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete" + +/* + * Define Timeout values + */ +#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */ +#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */ +#define SK_I2C_TIM_WATCH 1000000L /* 1 second */ + +/* + * Define trap and error log hold times + */ +#ifndef SK_SEN_ERR_TR_HOLD +#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC) +#endif +#ifndef SK_SEN_ERR_LOG_HOLD +#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC) +#endif +#ifndef SK_SEN_WARN_TR_HOLD +#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC) +#endif +#ifndef SK_SEN_WARN_LOG_HOLD +#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC) +#endif + +/* + * Defines for SenType + */ +#define SK_SEN_UNKNOWN 0 +#define SK_SEN_TEMP 1 +#define SK_SEN_VOLT 2 +#define SK_SEN_FAN 3 + +/* + * Define for the SenErrorFlag + */ +#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */ +#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */ +#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */ +#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */ +#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */ + +/* + * Define the Sensor struct + */ +struct s_Sensor { + char *SenDesc; /* Description */ + int SenType; /* Voltage or Temperature */ + SK_I32 SenValue; /* Current value of the sensor */ + SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */ + SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */ + SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */ + SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */ + int SenErrFlag; /* Sensor indicated an error */ + SK_BOOL SenInit; /* Is sensor initialized ? */ + SK_U64 SenErrCts; /* Error trap counter */ + SK_U64 SenWarnCts; /* Warning trap counter */ + SK_U64 SenBegErrTS; /* Begin error timestamp */ + SK_U64 SenBegWarnTS; /* Begin warning timestamp */ + SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */ + SK_U64 SenLastErrLogTS; /* Last error log timestamp */ + SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */ + SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */ + int SenState; /* Sensor State (see HW specific include) */ + int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen); + /* Sensors read function */ + SK_U16 SenReg; /* Register Address for this sensor */ + SK_U8 SenDev; /* Device Selection for this sensor */ +}; + +typedef struct s_I2c { + SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */ + int CurrSens; /* Which sensor is currently queried */ + int MaxSens; /* Max. number of sensors */ + int TimerMode; /* Use the timer also to watch the state machine */ + int InitLevel; /* Initialized Level */ +#ifndef SK_DIAG + int DummyReads; /* Number of non-checked dummy reads */ + SK_TIMER SenTimer; /* Sensors timer */ +#endif /* !SK_DIAG */ +} SK_I2C; + +extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); +extern int SkI2cWrite(SK_AC *pAC, SK_IOC IoC, SK_U32 Data, int Dev, int Size, + int Reg, int Burst); +extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); +#ifdef SK_DIAG +extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg, + int Burst); +#else /* !SK_DIAG */ +extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); +extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC); +extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC); +#endif /* !SK_DIAG */ +#endif /* n_SKTWSI_H */ + diff --git a/drivers/sk98lin/h/sktypes.h b/drivers/sk98lin/h/sktypes.h index e657016..d10e748 100644 --- a/drivers/sk98lin/h/sktypes.h +++ b/drivers/sk98lin/h/sktypes.h @@ -2,15 +2,16 @@ * * Name: sktypes.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.3 $ - * Date: $Date: 2003/02/25 14:16:40 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Define data types for Linux * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. * * 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 @@ -20,68 +21,29 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ - - /***************************************************************************** - * - * History: - * - * $Log: sktypes.h,v $ - * Revision 1.3 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.2 1999/11/22 14:01:58 cgoos - * Changed license header to GPL. - * Now using Linux' fixed size types instead of standard types. - * - * Revision 1.1 1999/02/16 07:41:40 cgoos - * First version. - * - * - * - *****************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * In this file, all data types that are needed by the common modules - * are mapped to Linux data types. - * - * - * Include File Hierarchy: - * - * - ******************************************************************************/ - + #ifndef __INC_SKTYPES_H #define __INC_SKTYPES_H +#define SK_I8 s8 /* 8 bits (1 byte) signed */ +#define SK_U8 u8 /* 8 bits (1 byte) unsigned */ +#define SK_I16 s16 /* 16 bits (2 bytes) signed */ +#define SK_U16 u16 /* 16 bits (2 bytes) unsigned */ +#define SK_I32 s32 /* 32 bits (4 bytes) signed */ +#define SK_U32 u32 /* 32 bits (4 bytes) unsigned */ +#define SK_I64 s64 /* 64 bits (8 bytes) signed */ +#define SK_U64 u64 /* 64 bits (8 bytes) unsigned */ -/* defines *******************************************************************/ +#define SK_UPTR ulong /* casting pointer <-> integral */ -/* - * Data types with a specific size. 'I' = signed, 'U' = unsigned. - */ -#define SK_I8 s8 -#define SK_U8 u8 -#define SK_I16 s16 -#define SK_U16 u16 -#define SK_I32 s32 -#define SK_U32 u32 -#define SK_I64 s64 -#define SK_U64 u64 - -#define SK_UPTR ulong /* casting pointer <-> integral */ - -/* -* Boolean type. -*/ -#define SK_BOOL SK_U8 -#define SK_FALSE 0 -#define SK_TRUE (!SK_FALSE) - -/* typedefs *******************************************************************/ - -/* function prototypes ********************************************************/ +#define SK_BOOL SK_U8 +#define SK_FALSE 0 +#define SK_TRUE (!SK_FALSE) #endif /* __INC_SKTYPES_H */ + +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ diff --git a/drivers/sk98lin/h/skversion.h b/drivers/sk98lin/h/skversion.h index ef46685..99ff3fd 100644 --- a/drivers/sk98lin/h/skversion.h +++ b/drivers/sk98lin/h/skversion.h @@ -1,16 +1,17 @@ /****************************************************************************** * - * Name: version.h + * Name: skversion.h * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2003/02/25 14:16:40 $ - * Purpose: SK specific Error log support + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: specific version strings and numbers * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. * * 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 @@ -21,32 +22,15 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * $Log: skversion.h,v $ - * Revision 1.4 2003/02/25 14:16:40 mlindner - * Fix: Copyright statement - * - * Revision 1.3 2003/02/25 13:30:18 mlindner - * Add: Support for various vendors - * - * Revision 1.1.2.1 2001/09/05 13:38:30 mlindner - * Removed FILE description - * - * Revision 1.1 2001/03/06 09:25:00 mlindner - * first version - * +#define BOOT_STRING "sk98lin: Network Device Driver v8.32.2.3\n" \ + "(C)Copyright 1999-2006 Marvell(R)." +#define VER_STRING "8.32.2.3" +#define PATCHLEVEL "02" +#define DRIVER_FILE_NAME "sk98lin" +#define DRIVER_REL_DATE "Apr-27-2006" + +/******************************************************************************* * + * End of file * ******************************************************************************/ - - -static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; -static const char SysKonnectBuildNumber[] = - "@(#)SK-BUILD: 6.05 PL: 01"; - -#define BOOT_STRING "sk98lin: Network Device Driver v6.05\n" \ - "(C)Copyright 1999-2003 Marvell(R)." - -#define VER_STRING "6.05" diff --git a/drivers/sk98lin/h/skvpd.h b/drivers/sk98lin/h/skvpd.h index 1be34c5..2f32de9 100644 --- a/drivers/sk98lin/h/skvpd.h +++ b/drivers/sk98lin/h/skvpd.h @@ -1,90 +1,26 @@ /****************************************************************************** * * Name: skvpd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/01/13 10:39:38 $ + * Project: Gigabit Ethernet Adapters, VPD-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines and Macros for VPD handling * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2004 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skvpd.h,v $ - * Revision 1.15 2003/01/13 10:39:38 rschmidt - * Replaced define for PCI device Id for YUKON with GENESIS - * Editorial changes - * - * Revision 1.14 2002/11/14 15:18:10 gheinig - * Added const specifier to key and buf parameters for VpdPara,VpdRead - * and VpdWrite. This is necessary for the Diag 7 GUI API - * - * Revision 1.13 2002/10/14 15:58:18 rschmidt - * Added entry in rom_size struct s_vpd - * Editorial changes - * - * Revision 1.12 2002/09/09 14:43:51 mkarl - * added PCI Id of Yukon for reading VPD in diag before the adapter has - * been initialized - * editorial changes - * - * Revision 1.11 2002/07/26 13:19:16 mkarl - * added support for Yukon - * added vpd_size to VPD struct - * - * Revision 1.10 2000/08/10 11:29:07 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * Removed unused function VpdWriteDword() (#if 0). - * Made VpdReadKeyword() available for SKDIAG only. - * - * Revision 1.9 1999/11/22 14:02:27 cgoos - * Changed license header to GPL. - * - * Revision 1.8 1999/03/11 14:26:40 malthoff - * Replace __STDC__ with SK_KR_PROTO. - * - * Revision 1.7 1998/10/28 07:27:17 gklug - * rmv: SWAP macros - * add: VPD_IN/OUT8 macros - * chg: interface definition - * - * Revision 1.6 1998/10/22 10:03:44 gklug - * fix: use SK_OUT16 instead of SK_OUTW - * - * Revision 1.5 1998/10/14 07:05:31 cgoos - * Changed constants in SK_SWAP_32 to UL. - * - * Revision 1.4 1998/08/19 08:14:09 gklug - * fix: remove struct keyword as much as possible from the C-code (see CCC) - * - * Revision 1.3 1998/08/18 08:18:56 malthoff - * Modify VPD in and out macros for SK_DIAG - * - * Revision 1.2 1998/07/03 14:49:08 malthoff - * Add VPD_INxx() and VPD_OUTxx() macros for the Diagnostics tool. - * - * Revision 1.1 1998/06/19 14:08:03 malthoff - * Created. - * - * - ******************************************************************************/ - /* * skvpd.h contains Diagnostic specific defines for VPD handling */ @@ -95,7 +31,7 @@ /* * Define Resource Type Identifiers and VPD keywords */ -#define RES_ID 0x82 /* Resource Type ID String (Product Name) */ +#define RES_ID 0x82 /* Resource Type ID String (Product Name) */ #define RES_VPD_R 0x90 /* start of VPD read only area */ #define RES_VPD_W 0x91 /* start of VPD read/write area */ #define RES_END 0x78 /* Resource Type End Tag */ @@ -104,14 +40,16 @@ #define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */ #endif /* VPD_NAME */ #define VPD_PN "PN" /* Adapter Part Number */ -#define VPD_EC "EC" /* Adapter Engineering Level */ +#define VPD_EC "EC" /* Adapter Engineering Level */ #define VPD_MN "MN" /* Manufacture ID */ #define VPD_SN "SN" /* Serial Number */ #define VPD_CP "CP" /* Extended Capability */ #define VPD_RV "RV" /* Checksum and Reserved */ -#define VPD_YA "YA" /* Asset Tag Identifier */ +#define VPD_YA "YA" /* Asset Tag Identifier */ #define VPD_VL "VL" /* First Error Log Message (SK specific) */ #define VPD_VF "VF" /* Second Error Log Message (SK specific) */ +#define VPD_VB "VB" /* Boot Agent ROM Configuration (SK specific) */ +#define VPD_VE "VE" /* EFI UNDI Configuration (SK specific) */ #define VPD_RW "RW" /* Remaining Read / Write Area */ /* 'type' values for vpd_setup_para() */ @@ -119,7 +57,7 @@ #define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */ /* 'op' values for vpd_setup_para() */ -#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */ +#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */ #define OWR_KEY 2 /* overwrite key if already exists */ /* @@ -128,18 +66,18 @@ #define VPD_DEV_ID_GENESIS 0x4300 -#define VPD_SIZE_YUKON 256 -#define VPD_SIZE_GENESIS 512 -#define VPD_SIZE 512 +#define VPD_SIZE_YUKON 256 +#define VPD_SIZE_GENESIS 512 +#define VPD_SIZE 512 #define VPD_READ 0x0000 #define VPD_WRITE 0x8000 #define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE) -#define VPD_GET_RES_LEN(p) ((unsigned int) \ - (* (SK_U8 *)&(p)[1]) |\ - ((* (SK_U8 *)&(p)[2]) << 8)) -#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2])) +#define VPD_GET_RES_LEN(p) ((unsigned int)\ + (*(SK_U8 *)&(p)[1]) |\ + ((*(SK_U8 *)&(p)[2]) << 8)) +#define VPD_GET_VPD_LEN(p) ((unsigned int)(*(SK_U8 *)&(p)[2])) #define VPD_GET_VAL(p) ((char *)&(p)[3]) #define VPD_MAX_LEN 50 @@ -190,7 +128,7 @@ typedef struct s_vpd_key { /* * System specific VPD macros */ -#ifndef SKDIAG +#ifndef SK_DIAG #ifndef VPD_DO_IO #define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val) #define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val) @@ -199,61 +137,61 @@ typedef struct s_vpd_key { #define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal) #define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal) #else /* VPD_DO_IO */ -#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val) -#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val) -#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(Addr),Val) -#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal) -#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal) -#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal) +#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(pAC,Addr),Val) +#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(pAC,Addr),Val) +#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(pAC,Addr),Val) +#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(pAC,Addr),pVal) +#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(pAC,Addr),pVal) +#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(pAC,Addr),pVal) #endif /* VPD_DO_IO */ -#else /* SKDIAG */ +#else /* SK_DIAG */ #define VPD_OUT8(pAC,Ioc,Addr,Val) { \ if ((pAC)->DgT.DgUseCfgCycle) \ SkPciWriteCfgByte(pAC,Addr,Val); \ else \ - SK_OUT8(pAC,PCI_C(Addr),Val); \ + SK_OUT8(pAC,PCI_C(pAC,Addr),Val); \ } #define VPD_OUT16(pAC,Ioc,Addr,Val) { \ if ((pAC)->DgT.DgUseCfgCycle) \ SkPciWriteCfgWord(pAC,Addr,Val); \ else \ - SK_OUT16(pAC,PCI_C(Addr),Val); \ + SK_OUT16(pAC,PCI_C(pAC,Addr),Val); \ } #define VPD_OUT32(pAC,Ioc,Addr,Val) { \ if ((pAC)->DgT.DgUseCfgCycle) \ SkPciWriteCfgDWord(pAC,Addr,Val); \ else \ - SK_OUT32(pAC,PCI_C(Addr),Val); \ + SK_OUT32(pAC,PCI_C(pAC,Addr),Val); \ } #define VPD_IN8(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ + if ((pAC)->DgT.DgUseCfgCycle) \ SkPciReadCfgByte(pAC,Addr,pVal); \ else \ - SK_IN8(pAC,PCI_C(Addr),pVal); \ + SK_IN8(pAC,PCI_C(pAC,Addr),pVal); \ } #define VPD_IN16(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ + if ((pAC)->DgT.DgUseCfgCycle) \ SkPciReadCfgWord(pAC,Addr,pVal); \ else \ - SK_IN16(pAC,PCI_C(Addr),pVal); \ + SK_IN16(pAC,PCI_C(pAC,Addr),pVal); \ } #define VPD_IN32(pAC,Ioc,Addr,pVal) { \ if ((pAC)->DgT.DgUseCfgCycle) \ SkPciReadCfgDWord(pAC,Addr,pVal); \ else \ - SK_IN32(pAC,PCI_C(Addr),pVal); \ + SK_IN32(pAC,PCI_C(pAC,Addr),pVal); \ } -#endif /* nSKDIAG */ +#endif /* SK_DIAG */ /* function prototypes ********************************************************/ #ifndef SK_KR_PROTO -#ifdef SKDIAG +#ifdef SK_DIAG extern SK_U32 VpdReadDWord( SK_AC *pAC, SK_IOC IoC, int addr); -#endif /* SKDIAG */ +#endif /* SK_DIAG */ extern int VpdSetupPara( SK_AC *pAC, @@ -304,7 +242,12 @@ extern void VpdErrLog( SK_IOC IoC, char *msg); -#ifdef SKDIAG +int VpdInit( + SK_AC *pAC, + SK_IOC IoC); + +#if defined(SK_DIAG) || defined(SK_ASF) + extern int VpdReadBlock( SK_AC *pAC, SK_IOC IoC, @@ -318,7 +261,9 @@ extern int VpdWriteBlock( char *buf, int addr, int len); -#endif /* SKDIAG */ + +#endif /* SK_DIAG || SK_ASF */ + #else /* SK_KR_PROTO */ extern SK_U32 VpdReadDWord(); extern int VpdSetupPara(); @@ -333,3 +278,4 @@ extern void VpdErrLog(); #endif /* SK_KR_PROTO */ #endif /* __INC_SKVPD_H_ */ + diff --git a/drivers/sk98lin/h/sky2le.h b/drivers/sk98lin/h/sky2le.h new file mode 100644 index 0000000..e61f20f --- /dev/null +++ b/drivers/sk98lin/h/sky2le.h @@ -0,0 +1,893 @@ +/****************************************************************************** + * + * Name: sky2le.h + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Common list element definitions and access macros. + * + ******************************************************************************/ + +/****************************************************************************** + * + * LICENSE: + * (C)Copyright 2003-2004 Marvell + * + * 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. + * The information in this file is provided "AS IS" without warranty. + * /LICENSE + * + ******************************************************************************/ + +#ifndef __INC_SKY2LE_H +#define __INC_SKY2LE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* defines ********************************************************************/ + +#define MIN_LEN_OF_LE_TAB 128 +#define MAX_LEN_OF_LE_TAB 4096 +#ifdef USE_POLLING_UNIT +#define NUM_LE_POLLING_UNIT 2 +#endif +#define MAX_FRAG_OVERHEAD 10 + +/* Macro for aligning a given value */ +#define SK_ALIGN_SIZE(Value, Alignment, AlignedVal) { \ + (AlignedVal) = (((Value) + (Alignment) - 1) & (~((Alignment) - 1)));\ +} + +/****************************************************************************** + * + * LE2DWord() - Converts the given Little Endian value to machine order value + * + * Description: + * This function converts the Little Endian value received as an argument to + * the machine order value. + * + * Returns: + * The converted value + * + */ + +#ifdef SK_LITTLE_ENDIAN + +#ifndef SK_USE_REV_DESC +#define LE2DWord(value) (value) +#else /* SK_USE_REV_DESC */ +#define LE2DWord(value) \ + ((((value)<<24L) & 0xff000000L) + \ + (((value)<< 8L) & 0x00ff0000L) + \ + (((value)>> 8L) & 0x0000ff00L) + \ + (((value)>>24L) & 0x000000ffL)) +#endif /* SK_USE_REV_DESC */ + +#else /* !SK_LITTLE_ENDIAN */ + +#ifndef SK_USE_REV_DESC +#define LE2DWord(value) \ + ((((value)<<24L) & 0xff000000L) + \ + (((value)<< 8L) & 0x00ff0000L) + \ + (((value)>> 8L) & 0x0000ff00L) + \ + (((value)>>24L) & 0x000000ffL)) +#else /* SK_USE_REV_DESC */ +#define LE2DWord(value) (value) +#endif /* SK_USE_REV_DESC */ + +#endif /* !SK_LITTLE_ENDIAN */ + +/****************************************************************************** + * + * DWord2LE() - Converts the given value to a Little Endian value + * + * Description: + * This function converts the value received as an argument to a Little Endian + * value on Big Endian machines. If the machine running the code is Little + * Endian, then no conversion is done. + * + * Returns: + * The converted value + * + */ + +#ifdef SK_LITTLE_ENDIAN + +#ifndef SK_USE_REV_DESC +#define DWord2LE(value) (value) +#else /* SK_USE_REV_DESC */ +#define DWord2LE(value) \ + ((((value)<<24L) & 0xff000000L) + \ + (((value)<< 8L) & 0x00ff0000L) + \ + (((value)>> 8L) & 0x0000ff00L) + \ + (((value)>>24L) & 0x000000ffL)) +#endif /* SK_USE_REV_DESC */ + +#else /* !SK_LITTLE_ENDIAN */ + +#ifndef SK_USE_REV_DESC +#define DWord2LE(value) \ + ((((value)<<24L) & 0xff000000L) + \ + (((value)<< 8L) & 0x00ff0000L) + \ + (((value)>> 8L) & 0x0000ff00L) + \ + (((value)>>24L) & 0x000000ffL)) +#else /* SK_USE_REV_DESC */ +#define DWord2LE(value) (value) +#endif /* SK_USE_REV_DESC */ +#endif /* !SK_LITTLE_ENDIAN */ + +/****************************************************************************** + * + * LE2Word() - Converts the given Little Endian value to machine order value + * + * Description: + * This function converts the Little Endian value received as an argument to + * the machine order value. + * + * Returns: + * The converted value + * + */ + +#ifdef SK_LITTLE_ENDIAN +#ifndef SK_USE_REV_DESC +#define LE2Word(value) (value) +#else /* SK_USE_REV_DESC */ +#define LE2Word(value) \ + ((((value)<< 8L) & 0xff00) + \ + (((value)>> 8L) & 0x00ff)) +#endif /* SK_USE_REV_DESC */ + +#else /* !SK_LITTLE_ENDIAN */ +#ifndef SK_USE_REV_DESC +#define LE2Word(value) \ + ((((value)<< 8L) & 0xff00) + \ + (((value)>> 8L) & 0x00ff)) +#else /* SK_USE_REV_DESC */ +#define LE2Word(value) (value) +#endif /* SK_USE_REV_DESC */ +#endif /* !SK_LITTLE_ENDIAN */ + +/****************************************************************************** + * + * Word2LE() - Converts the given value to a Little Endian value + * + * Description: + * This function converts the value received as an argument to a Little Endian + * value on Big Endian machines. If the machine running the code is Little + * Endian, then no conversion is done. + * + * Returns: + * The converted value + * + */ + +#ifdef SK_LITTLE_ENDIAN +#ifndef SK_USE_REV_DESC +#define Word2LE(value) (value) +#else /* SK_USE_REV_DESC */ +#define Word2LE(value) \ + ((((value)<< 8L) & 0xff00) + \ + (((value)>> 8L) & 0x00ff)) +#endif /* SK_USE_REV_DESC */ + +#else /* !SK_LITTLE_ENDIAN */ +#ifndef SK_USE_REV_DESC +#define Word2LE(value) \ + ((((value)<< 8L) & 0xff00) + \ + (((value)>> 8L) & 0x00ff)) +#else /* SK_USE_REV_DESC */ +#define Word2LE(value) (value) +#endif /* SK_USE_REV_DESC */ +#endif /* !SK_LITTLE_ENDIAN */ + +/****************************************************************************** + * + * Transmit list element macros + * + */ + +#define TXLE_SET_ADDR(pLE, Addr) \ + ((pLE)->Tx.TxUn.BufAddr = DWord2LE(Addr)) +#define TXLE_SET_LSLEN(pLE, Len) \ + ((pLE)->Tx.TxUn.LargeSend.Length = Word2LE(Len)) +#define TXLE_SET_STACS(pLE, Start) \ + ((pLE)->Tx.TxUn.ChkSum.TxTcpSp = Word2LE(Start)) +#define TXLE_SET_WRICS(pLE, Write) \ + ((pLE)->Tx.TxUn.ChkSum.TxTcpWp = Word2LE(Write)) +#define TXLE_SET_INICS(pLE, Ini) ((pLE)->Tx.Send.InitCsum = Word2LE(Ini)) +#define TXLE_SET_LEN(pLE, Len) ((pLE)->Tx.Send.BufLen = Word2LE(Len)) +#define TXLE_SET_VLAN(pLE, Vlan) ((pLE)->Tx.Send.VlanTag = Word2LE(Vlan)) +#define TXLE_SET_LCKCS(pLE, Lock) ((pLE)->Tx.ControlFlags = (Lock)) +#define TXLE_SET_CTRL(pLE, Ctrl) ((pLE)->Tx.ControlFlags = (Ctrl)) +#define TXLE_SET_OPC(pLE, Opc) ((pLE)->Tx.Opcode = (Opc)) + +#define TXLE_GET_ADDR(pLE) LE2DWord((pLE)->Tx.TxUn.BufAddr) +#define TXLE_GET_LSLEN(pLE) LE2Word((pLE)->Tx.TxUn.LargeSend.Length) +#define TXLE_GET_STACS(pLE) LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpSp) +#define TXLE_GET_WRICS(pLE) LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpWp) +#define TXLE_GET_INICS(pLE) LE2Word((pLE)->Tx.Send.InitCsum) +#define TXLE_GET_LEN(pLE) LE2Word((pLE)->Tx.Send.BufLen) +#define TXLE_GET_VLAN(pLE) LE2Word((pLE)->Tx.Send.VlanTag) +#define TXLE_GET_LCKCS(pLE) ((pLE)->Tx.ControlFlags) +#define TXLE_GET_CTRL(pLE) ((pLE)->Tx.ControlFlags) +#define TXLE_GET_OPC(pLE) ((pLE)->Tx.Opcode) + +/****************************************************************************** + * + * Receive list element macros + * + */ + +#define RXLE_SET_ADDR(pLE, Addr) \ + ((pLE)->Rx.RxUn.BufAddr = (SK_U32) DWord2LE(Addr)) +#define RXLE_SET_STACS2(pLE, Offs) \ + ((pLE)->Rx.RxUn.ChkSum.RxTcpSp2 = Word2LE(Offs)) +#define RXLE_SET_STACS1(pLE, Offs) \ + ((pLE)->Rx.RxUn.ChkSum.RxTcpSp1 = Word2LE(Offs)) +#define RXLE_SET_LEN(pLE, Len) ((pLE)->Rx.BufferLength = Word2LE(Len)) +#define RXLE_SET_CTRL(pLE, Ctrl) ((pLE)->Rx.ControlFlags = (Ctrl)) +#define RXLE_SET_OPC(pLE, Opc) ((pLE)->Rx.Opcode = (Opc)) + +#define RXLE_GET_ADDR(pLE) LE2DWord((pLE)->Rx.RxUn.BufAddr) +#define RXLE_GET_STACS2(pLE) LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp2) +#define RXLE_GET_STACS1(pLE) LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp1) +#define RXLE_GET_LEN(pLE) LE2Word((pLE)->Rx.BufferLength) +#define RXLE_GET_CTRL(pLE) ((pLE)->Rx.ControlFlags) +#define RXLE_GET_OPC(pLE) ((pLE)->Rx.Opcode) + +/****************************************************************************** + * + * Status list element macros + * + */ + +#define STLE_SET_OPC(pLE, Opc) ((pLE)->St.Opcode = (Opc)) + +#define STLE_GET_FRSTATUS(pLE) LE2DWord((pLE)->St.StUn.StRxStatWord) +#define STLE_GET_TIST(pLE) LE2DWord((pLE)->St.StUn.StRxTimeStamp) +#define STLE_GET_TCP1(pLE) LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum1) +#define STLE_GET_TCP2(pLE) LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum2) +#define STLE_GET_LEN(pLE) LE2Word((pLE)->St.Stat.BufLen) +#define STLE_GET_VLAN(pLE) LE2Word((pLE)->St.Stat.VlanTag) +#define STLE_GET_LINK(pLE) ((pLE)->St.Link) +#define STLE_GET_OPC(pLE) ((pLE)->St.Opcode) +#define STLE_GET_DONE_IDX(pLE,LowVal,HighVal) { \ + (LowVal) = LE2DWord((pLE)->St.StUn.StTxStatLow); \ + (HighVal) = LE2Word((pLE)->St.Stat.StTxStatHi); \ +} + +#define STLE_GET_RSS(pLE) LE2DWord((pLE)->St.StUn.StRxRssValue) +#define STLE_GET_IPBIT(pLE) ((pLE)->St.Stat.Rss.FlagField & RSS_IP_FLAG) +#define STLE_GET_TCPBIT(pLE) ((pLE)->St.Stat.Rss.FlagField & RSS_TCP_FLAG) + + +/* I always take both values as a paramter to avoid typos */ +#define STLE_GET_DONE_IDX_TXA1(LowVal,HighVal) \ + (((LowVal) & STLE_TXA1_MSKL) >> STLE_TXA1_SHIFTL) +#define STLE_GET_DONE_IDX_TXS1(LowVal,HighVal) \ + ((LowVal & STLE_TXS1_MSKL) >> STLE_TXS1_SHIFTL) +#define STLE_GET_DONE_IDX_TXA2(LowVal,HighVal) \ + (((LowVal & STLE_TXA2_MSKL) >> STLE_TXA2_SHIFTL) + \ + ((HighVal & STLE_TXA2_MSKH) << STLE_TXA2_SHIFTH)) +#define STLE_GET_DONE_IDX_TXS2(LowVal,HighVal) \ + ((HighVal & STLE_TXS2_MSKH) >> STLE_TXS2_SHIFTH) + + +#define SK_Y2_RXSTAT_CHECK_PKT(Len, RxStat, IsOk) { \ + (IsOk) = (((RxStat) & GMR_FS_RX_OK) != 0) && \ + (((RxStat) & GMR_FS_ANY_ERR) == 0); \ + \ + if ((IsOk) && ((SK_U16)(((RxStat) & GMR_FS_LEN_MSK) >> \ + GMR_FS_LEN_SHIFT) != (Len))) { \ + /* length in MAC status differs from length in LE */\ + (IsOk) = SK_FALSE; \ + } \ +} + + +/****************************************************************************** + * + * Polling unit list element macros + * + * NOTE: the Idx must be <= 0xfff and PU_PUTIDX_VALID makes them valid + * + */ + +#ifdef USE_POLLING_UNIT + +#define POLE_SET_OPC(pLE, Opc) ((pLE)->Sa.Opcode = (Opc)) +#define POLE_SET_LINK(pLE, Port) ((pLE)->Sa.Link = (Port)) +#define POLE_SET_RXIDX(pLE, Idx) ((pLE)->Sa.RxIdxVld = Word2LE(Idx)) +#define POLE_SET_TXAIDX(pLE, Idx) ((pLE)->Sa.TxAIdxVld = Word2LE(Idx)) +#define POLE_SET_TXSIDX(pLE, Idx) ((pLE)->Sa.TxSIdxVld = Word2LE(Idx)) + +#define POLE_GET_OPC(pLE) ((pLE)->Sa.Opcode) +#define POLE_GET_LINK(pLE) ((pLE)->Sa.Link) +#define POLE_GET_RXIDX(pLE) LE2Word((pLE)->Sa.RxIdxVld) +#define POLE_GET_TXAIDX(pLE) LE2Word((pLE)->Sa.TxAIdxVld) +#define POLE_GET_TXSIDX(pLE) LE2Word((pLE)->Sa.TxSIdxVld) + +#endif /* USE_POLLING_UNIT */ + +/****************************************************************************** + * + * Debug macros for list elements + * + */ + +#ifdef DEBUG + +#define SK_DBG_DUMP_RX_LE(pLE) { \ + SK_U8 Opcode; \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=== RX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\ + ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \ + ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (16bit) %04x %04x %04x %04x\n", \ + ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \ + ((SK_U16 *) pLE)[3])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (32bit) %08x %08x\n", \ + ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \ + Opcode = RXLE_GET_OPC(pLE); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \ + "Hardware" : "Software")); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOpc: 0x%x ",Opcode)); \ + switch (Opcode & (~HW_OWNER)) { \ + case OP_BUFFER: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_BUFFER\n")); \ + break; \ + case OP_PACKET: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_PACKET\n")); \ + break; \ + case OP_ADDR64: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_ADDR64\n")); \ + break; \ + case OP_TCPSTART: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TCPPAR\n")); \ + break; \ + case SW_OWNER: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tunused LE\n")); \ + break; \ + default: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tunknown Opcode!!!\n")); \ + break; \ + } \ + if ((Opcode & OP_BUFFER) == OP_BUFFER) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tControl: 0x%x\n", RXLE_GET_CTRL(pLE))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tBufLen: 0x%x\n", RXLE_GET_LEN(pLE))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tLowAddr: 0x%x\n", RXLE_GET_ADDR(pLE))); \ + } \ + if ((Opcode & OP_ADDR64) == OP_ADDR64) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tHighAddr: 0x%x\n", RXLE_GET_ADDR(pLE))); \ + } \ + if ((Opcode & OP_TCPSTART) == OP_TCPSTART) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTCP Sum Start 1 : 0x%x\n", RXLE_GET_STACS1(pLE))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTCP Sum Start 2 : 0x%x\n", RXLE_GET_STACS2(pLE))); \ + } \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=====================\n")); \ +} + +#define SK_DBG_DUMP_TX_LE(pLE) { \ + SK_U8 Opcode; \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=== TX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\ + ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \ + ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (16bit) %04x %04x %04x %04x\n", \ + ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \ + ((SK_U16 *) pLE)[3])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (32bit) %08x %08x\n", \ + ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \ + Opcode = TXLE_GET_OPC(pLE); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \ + "Hardware" : "Software")); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOpc: 0x%x ",Opcode)); \ + switch (Opcode & (~HW_OWNER)) { \ + case OP_TCPCHKSUM: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TCPCHKSUM\n")); \ + break; \ + case OP_TCPIS: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TCPIS\n")); \ + break; \ + case OP_TCPLCK: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TCPLCK\n")); \ + break; \ + case OP_TCPLW: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TCPLW\n")); \ + break; \ + case OP_TCPLSW: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TCPLSW\n")); \ + break; \ + case OP_TCPLISW: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TCPLISW\n")); \ + break; \ + case OP_ADDR64: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_ADDR64\n")); \ + break; \ + case OP_VLAN: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_VLAN\n")); \ + break; \ + case OP_ADDR64VLAN: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_ADDR64VLAN\n")); \ + break; \ + case OP_LRGLEN: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_LRGLEN\n")); \ + break; \ + case OP_LRGLENVLAN: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_LRGLENVLAN\n")); \ + break; \ + case OP_BUFFER: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_BUFFER\n")); \ + break; \ + case OP_PACKET: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_PACKET\n")); \ + break; \ + case OP_LARGESEND: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_LARGESEND\n")); \ + break; \ + case SW_OWNER: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tunused LE\n")); \ + break; \ + default: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tunknown Opcode!!!\n")); \ + break; \ + } \ + if ((Opcode & OP_BUFFER) == OP_BUFFER) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tControl: 0x%x\n", TXLE_GET_CTRL(pLE))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tBufLen: 0x%x\n", TXLE_GET_LEN(pLE))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tLowAddr: 0x%x\n", TXLE_GET_ADDR(pLE))); \ + } \ + if ((Opcode & OP_ADDR64) == OP_ADDR64) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tHighAddr: 0x%x\n", TXLE_GET_ADDR(pLE))); \ + } \ + if ((Opcode & OP_VLAN) == OP_VLAN) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tVLAN Id: 0x%x\n", TXLE_GET_VLAN(pLE))); \ + } \ + if ((Opcode & OP_LRGLEN) == OP_LRGLEN) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tLarge send length: 0x%x\n", TXLE_GET_LSLEN(pLE))); \ + } \ + if ((Opcode &(~HW_OWNER)) <= OP_ADDR64) { \ + if ((Opcode & OP_TCPWRITE) == OP_TCPWRITE) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTCP Sum Write: 0x%x\n", TXLE_GET_WRICS(pLE))); \ + } \ + if ((Opcode & OP_TCPSTART) == OP_TCPSTART) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTCP Sum Start: 0x%x\n", TXLE_GET_STACS(pLE))); \ + } \ + if ((Opcode & OP_TCPINIT) == OP_TCPINIT) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTCP Sum Init: 0x%x\n", TXLE_GET_INICS(pLE))); \ + } \ + if ((Opcode & OP_TCPLCK) == OP_TCPLCK) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTCP Sum Lock: 0x%x\n", TXLE_GET_LCKCS(pLE))); \ + } \ + } \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=====================\n")); \ +} + +#define SK_DBG_DUMP_ST_LE(pLE) { \ + SK_U8 Opcode; \ + SK_U16 HighVal; \ + SK_U32 LowVal; \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=== ST_LIST_ELEMENT @addr: %p contains: %02x %02x %02x %02x %02x %02x %02x %02x\n",\ + pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\ + ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \ + ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (16bit) %04x %04x %04x %04x\n", \ + ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \ + ((SK_U16 *) pLE)[3])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (32bit) %08x %08x\n", \ + ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \ + Opcode = STLE_GET_OPC(pLE); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == SW_OWNER) ? \ + "Hardware" : "Software")); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOpc: 0x%x", Opcode)); \ + Opcode &= (~HW_OWNER); \ + switch (Opcode) { \ + case OP_RXSTAT: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_RXSTAT\n")); \ + break; \ + case OP_RXTIMESTAMP: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_RXTIMESTAMP\n")); \ + break; \ + case OP_RXVLAN: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_RXVLAN\n")); \ + break; \ + case OP_RXCHKS: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_RXCHKS\n")); \ + break; \ + case OP_RXCHKSVLAN: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_RXCHKSVLAN\n")); \ + break; \ + case OP_RXTIMEVLAN: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_RXTIMEVLAN\n")); \ + break; \ + case OP_RSS_HASH: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_RSS_HASH\n")); \ + break; \ + case OP_TXINDEXLE: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_TXINDEXLE\n")); \ + break; \ + case HW_OWNER: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tunused LE\n")); \ + break; \ + default: \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tunknown status list element!!!\n")); \ + break; \ + } \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tPort: %c\n", 'A' + STLE_GET_LINK(pLE))); \ + if (Opcode == OP_RXSTAT) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tFrameLen: 0x%x\n", STLE_GET_LEN(pLE))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tFrameStat: 0x%x\n", STLE_GET_FRSTATUS(pLE))); \ + } \ + if ((Opcode & OP_RXVLAN) == OP_RXVLAN) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tVLAN Id: 0x%x\n", STLE_GET_VLAN(pLE))); \ + } \ + if ((Opcode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTimestamp: 0x%x\n", STLE_GET_TIST(pLE))); \ + } \ + if ((Opcode & OP_RXCHKS) == OP_RXCHKS) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTCP: 0x%x 0x%x\n", STLE_GET_TCP1(pLE), \ + STLE_GET_TCP2(pLE))); \ + } \ + if (Opcode == OP_TXINDEXLE) { \ + STLE_GET_DONE_IDX(pLE, LowVal, HighVal); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTx Index TxA1: 0x%x\n", \ + STLE_GET_DONE_IDX_TXA1(LowVal,HighVal))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTx Index TxS1: 0x%x\n", \ + STLE_GET_DONE_IDX_TXS1(LowVal,HighVal))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTx Index TxA2: 0x%x\n", \ + STLE_GET_DONE_IDX_TXA2(LowVal,HighVal))); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTx Index TxS2: 0x%x\n", \ + STLE_GET_DONE_IDX_TXS2(LowVal,HighVal))); \ + } \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=====================\n")); \ +} + +#ifdef USE_POLLING_UNIT +#define SK_DBG_DUMP_PO_LE(pLE) { \ + SK_U8 Opcode; \ + SK_U16 Idx; \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=== PO_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \ + pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\ + ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \ + ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (16bit) %04x %04x %04x %04x\n", \ + ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \ + ((SK_U16 *) pLE)[3])); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\t (32bit) %08x %08x\n", \ + ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \ + Opcode = POLE_GET_OPC(pLE); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \ + "Hardware" : "Software")); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOpc: 0x%x ",Opcode)); \ + if ((Opcode & ~HW_OWNER) == OP_PUTIDX) { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tOP_PUTIDX\n")); \ + } \ + else { \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tunknown Opcode!!!\n")); \ + } \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tPort %c\n", 'A' + POLE_GET_LINK(pLE))); \ + Idx = POLE_GET_TXAIDX(pLE); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTxA Index is 0x%X and %svalid\n", Idx, \ + (Idx & PU_PUTIDX_VALID) ? "" : "not ")); \ + Idx = POLE_GET_TXSIDX(pLE); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tTxS Index is 0x%X and %svalid\n", Idx, \ + (Idx & PU_PUTIDX_VALID) ? "" : "not ")); \ + Idx = POLE_GET_RXIDX(pLE); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("\tRx Index is 0x%X and %svalid\n", Idx, \ + (Idx & PU_PUTIDX_VALID) ? "" : "not ")); \ + SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \ + ("=====================\n")); \ +} +#endif /* USE_POLLING_UNIT */ + +#else /* !DEBUG */ + +#define SK_DBG_DUMP_RX_LE(pLE) +#define SK_DBG_DUMP_TX_LE(pLE) +#define SK_DBG_DUMP_ST_LE(pLE) +#define SK_DBG_DUMP_PO_LE(pLE) + +#endif /* !DEBUG */ + +/****************************************************************************** + * + * Macros for listelement tables + * + * + */ + +#define LE_SIZE sizeof(SK_HWLE) +#define LE_TAB_SIZE(NumElements) ((NumElements) * LE_SIZE) + +/* Number of unused list elements in table + * this macro always returns the number of free listelements - 1 + * this way we want to guarantee that always one LE remains unused + */ +#define NUM_FREE_LE_IN_TABLE(pTable) \ + ( ((pTable)->Put >= (pTable)->Done) ? \ + (NUM_LE_IN_TABLE(pTable) - (pTable)->Put + (pTable)->Done - 1) :\ + ((pTable)->Done - (pTable)->Put - 1) ) + +/* total number of list elements in table */ +#define NUM_LE_IN_TABLE(pTable) ((pTable)->Num) + +/* get next unused Rx list element */ +#define GET_RX_LE(pLE, pTable) { \ + pLE = &(pTable)->pLETab[(pTable)->Put]; \ + (pTable)->Put = ((pTable)->Put + 1) & (NUM_LE_IN_TABLE(pTable) - 1);\ +} + +/* get next unused Tx list element */ +#define GET_TX_LE(pLE, pTable) GET_RX_LE(pLE, pTable) + +/* get next status list element expected to be finished by hw */ +#define GET_ST_LE(pLE, pTable) { \ + pLE = &(pTable)->pLETab[(pTable)->Done]; \ + (pTable)->Done = ((pTable)->Done +1) & (NUM_LE_IN_TABLE(pTable) - 1);\ +} + +#ifdef USE_POLLING_UNIT +/* get next polling unit list element for port */ +#define GET_PO_LE(pLE, pTable, Port) { \ + pLE = &(pTable)->pLETab[(Port)]; \ +} +#endif /* USE_POLLING_UNIT */ + +#define GET_PUT_IDX(pTable) ((pTable)->Put) + +#define UPDATE_HWPUT_IDX(pTable) {(pTable)->HwPut = (pTable)->Put; } + +/* + * get own bit of next status LE + * if the result is != 0 there has been at least one status LE finished + */ +#define OWN_OF_FIRST_LE(pTable) \ + (STLE_GET_OPC(&(pTable)->pLETab[(pTable)->Done]) & HW_OWNER) + +#define SET_DONE_INDEX(pTable, Idx) (pTable)->Done = (Idx); + +#define GET_DONE_INDEX(pTable) ((pTable)->Done) + +#ifdef SAFE_BUT_SLOW + +/* check own bit of LE before current done idx */ +#define CHECK_STLE_OVERFLOW(pTable, IsOk) { \ + unsigned i; \ + if ((i = (pTable)->Done) == 0) { \ + i = NUM_LE_IN_TABLE(pTable); \ + } \ + else { \ + i = i - 1; \ + } \ + if (STLE_GET_OPC(&(pTable)->pLETab[i]) == HW_OWNER) { \ + (IsOk) = SK_TRUE; \ + } \ + else { \ + (IsOk) = SK_FALSE; \ + } \ + } + + +/* + * for Yukon-2 the hardware is not polling the list elements, so it + * is not necessary to change the own-bit of Rx or Tx LEs before + * reusing them + * but it might make debugging easier if one simply can see whether + * a LE has been worked on + */ + +#define CLEAR_LE_OWN(pTable, Idx) \ + STLE_SET_OPC(&(pTable)->pLETab[(Idx)], SW_OWNER) + +/* + * clear all own bits starting from old done index up to the LE before + * the new done index + */ +#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To) { \ + int i; \ + i = (pTable)->Done; \ + while (i != To) { \ + CLEAR_LE_OWN(pTable, i); \ + i = (i + 1) & (NUM_LE_IN_TABLE(pTable) - 1); \ + } \ + } + +#else /* !SAFE_BUT_SLOW */ + +#define CHECK_STLE_OVERFLOW(pTable, IsOk) +#define CLEAR_LE_OWN(pTable, Idx) +#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To) + +#endif /* !SAFE_BUT_SLOW */ + + +/* typedefs *******************************************************************/ + +typedef struct s_LetRxTx { + SK_U16 VlanId; /* VLAN Id given down last time */ + SK_U16 TcpWp; /* TCP Checksum Write Position */ + SK_U16 TcpSp1; /* TCP Checksum Calculation Start Position 1 */ + SK_U16 TcpSp2; /* TCP Checksum Calculation Start Position 2 */ + SK_U16 MssValue; /* Maximum Segment Size */ + SK_U16 Reserved1; /* reserved word for furture extensions */ + SK_U16 Reserved2; /* reserved word for furture extensions */ + SK_U16 Reserved3; /* reserved word for furture extensions */ +} SK_LET_RX_TX; + +typedef struct s_LetStat { + SK_U32 RxTimeStamp; /* Receive Timestamp */ + SK_U32 RssHashValue; /* RSS Hash Value */ + SK_BOOL RssIsIp; /* RSS Hash Value: IP packet detected */ + SK_BOOL RssIsTcp; /* RSS Hash Value: IP+TCP packet detected */ + SK_U16 VlanId; /* VLAN Id given received by Status BMU */ + SK_U16 TcpSum1; /* TCP checksum 1 (status BMU) */ + SK_U16 TcpSum2; /* TCP checksum 2 (status BMU) */ +} SK_LET_STAT; + +typedef union s_LetBmuSpec { + SK_LET_RX_TX RxTx; /* Rx/Tx BMU specific variables */ + SK_LET_STAT Stat; /* Status BMU specific variables */ +} SK_LET_BMU_S; + +typedef struct s_le_table { + /* all LE's between Done and HWPut are owned by the hardware */ + /* all LE's between Put and Done can be used from Software */ + /* all LE's between HWPut and Put are currently processed in DriverSend */ + unsigned Done; /* done index - consumed from HW and available */ + unsigned Put; /* put index - to be given to hardware */ + unsigned HwPut; /* put index actually given to hardware */ + unsigned Num; /* total number of list elements */ + SK_HWLE *pLETab; /* virtual address of list element table */ + SK_U32 pPhyLETABLow; /* physical address of list element table */ + SK_U32 pPhyLETABHigh; /* physical address of list element table */ + /* values to remember in order to save some LEs */ + SK_U32 BufHighAddr; /* high addr given down last time */ + SK_LET_BMU_S Bmu; /* contains BMU specific information */ + SK_U32 private; /* driver private variable free usable */ + SK_U16 TcpInitCsum; /* Init. Checksum */ +} SK_LE_TABLE; + +/* function prototypes ********************************************************/ + +#ifndef SK_KR_PROTO + +/* + * public functions in sky2le.c + */ +extern void SkGeY2SetPutIndex( + SK_AC *pAC, + SK_IOC IoC, + SK_U32 StartAddrPrefetchUnit, + SK_LE_TABLE *pLETab); + +extern void SkGeY2InitPrefetchUnit( + SK_AC *pAC, + SK_IOC IoC, + unsigned int Queue, + SK_LE_TABLE *pLETab); + +extern void SkGeY2InitStatBmu( + SK_AC *pAC, + SK_IOC IoC, + SK_LE_TABLE *pLETab); + +extern void SkGeY2InitPollUnit( + SK_AC *pAC, + SK_IOC IoC, + SK_LE_TABLE *pLETab); + +extern void SkGeY2InitSingleLETable( + SK_AC *pAC, + SK_LE_TABLE *pLETab, + unsigned int NumLE, + void *pVMem, + SK_U32 PMemLowAddr, + SK_U32 PMemHighAddr); + +#else /* SK_KR_PROTO */ +extern void SkGeY2SetPutIndex(); +extern void SkGeY2InitPrefetchUnit(); +extern void SkGeY2InitStatBmu(); +extern void SkGeY2InitPollUnit(); +extern void SkGeY2InitSingleLETable(); +#endif /* SK_KR_PROTO */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __INC_SKY2LE_H */ + diff --git a/drivers/sk98lin/h/xmac_ii.h b/drivers/sk98lin/h/xmac_ii.h index 2ef903a..d02256f 100644 --- a/drivers/sk98lin/h/xmac_ii.h +++ b/drivers/sk98lin/h/xmac_ii.h @@ -1,201 +1,25 @@ /****************************************************************************** * * Name: xmac_ii.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.46 $ - * Date: $Date: 2003/01/28 09:47:45 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Defines and Macros for Gigabit Ethernet Controller * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2006 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: xmac_ii.h,v $ - * Revision 1.46 2003/01/28 09:47:45 rschmidt - * Added defines for copper MDI/MDIX configuration - * Added defines for LED Control Register - * Editorial changes - * - * Revision 1.45 2002/12/10 14:35:13 rschmidt - * Corrected defines for Extended PHY Specific Control - * Added defines for Ext. PHY Specific Ctrl 2 Reg. (Fiber specific) - * - * Revision 1.44 2002/12/09 14:58:41 rschmidt - * Added defines for Ext. PHY Specific Ctrl Reg. (downshift feature) - * Added 'GMR_FS_UN_SIZE'-Bit to Rx GMAC FIFO Flush Mask - * - * Revision 1.43 2002/12/05 10:14:45 rschmidt - * Added define for GMAC's Half Duplex Burst Mode - * Added define for Rx GMAC FIFO Flush Mask (default) - * - * Revision 1.42 2002/11/12 16:48:19 rschmidt - * Added defines for Cable Diagnostic Register (GPHY) - * Editorial changes - * - * Revision 1.41 2002/10/21 11:20:22 rschmidt - * Added bit GMR_FS_GOOD_FC to GMR_FS_ANY_ERR - * Editorial changes - * - * Revision 1.40 2002/10/14 14:54:14 rschmidt - * Added defines for GPHY Specific Status and GPHY Interrupt Status - * Added bits PHY_M_IS_AN_ERROR and PHY_M_IS_FIFO_ERROR to PHY_M_DEF_MSK - * Editorial changes - * - * Revision 1.39 2002/10/10 15:53:44 mkarl - * added some bit definitions for link speed status and LED's - * - * Revision 1.38 2002/08/21 16:23:46 rschmidt - * Added defines for PHY Specific Ctrl Reg - * Editorial changes - * - * Revision 1.37 2002/08/16 14:50:33 rschmidt - * Added defines for Auto-Neg. Advertisement YUKON Fiber (88E1011S only) - * Changed define PHY_M_DEF_MSK for GPHY IRQ Mask - * Editorial changes - * - * Revision 1.36 2002/08/12 13:21:10 rschmidt - * Added defines for different Broadcom PHY Ids - * - * Revision 1.35 2002/08/08 15:58:01 rschmidt - * Added defines for Manual LED Override register (YUKON) - * Editorial changes - * - * Revision 1.34 2002/07/31 17:23:36 rwahl - * Added define GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR). - * - * Revision 1.33 2002/07/23 16:03:37 rschmidt - * Added defines for GPHY registers - * Editorial changes - * - * Revision 1.32 2002/07/15 18:14:37 rwahl - * Added GMAC MIB counters definitions. - * Editorial changes. - * - * Revision 1.31 2002/07/15 15:42:50 rschmidt - * Removed defines from PHY specific reg. which are - * common to all PHYs - * Added defines for GMAC MIB Counters - * Editorial changes - * - * Revision 1.30 2002/06/05 08:22:12 rschmidt - * Changed defines for GMAC Rx Control Register and Rx Status - * Editorial changes - * - * Revision 1.29 2002/04/25 11:43:56 rschmidt - * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res. - * Added new registers and defines for YUKON (GMAC, GPHY) - * Added Receive Frame Status Encoding for YUKON - * Editorial changes - * - * Revision 1.28 2000/11/09 12:32:49 rassmann - * Renamed variables. - * - * Revision 1.27 2000/05/17 11:00:46 malthoff - * Add bit for enable/disable power management in BCOM chip. - * - * Revision 1.26 1999/11/22 14:03:00 cgoos - * Changed license header to GPL. - * - * Revision 1.25 1999/08/12 19:19:38 malthoff - * Add PHY_B_AC_TX_TST bit according to BCOM A1 errata sheet. - * - * Revision 1.24 1999/07/30 11:27:21 cgoos - * Fixed a missing end-of-comment. - * - * Revision 1.23 1999/07/30 07:03:31 malthoff - * Cut some long comments. - * Correct the XMAC PHY ID definitions. - * - * Revision 1.22 1999/05/19 07:33:18 cgoos - * Changes for 1000Base-T. - * - * Revision 1.21 1999/03/25 07:46:11 malthoff - * Add XM_HW_CFG, XM_TS_READ, and XM_TS_LOAD registers. - * - * Revision 1.20 1999/03/12 13:36:09 malthoff - * Remove __STDC__. - * - * Revision 1.19 1998/12/10 12:22:54 gklug - * fix: RX_PAGE must be in interrupt mask - * - * Revision 1.18 1998/12/10 10:36:36 gklug - * fix: swap of pause bits - * - * Revision 1.17 1998/11/18 13:21:45 gklug - * fix: Default interrupt mask - * - * Revision 1.16 1998/10/29 15:53:21 gklug - * fix: Default mask uses ASS (GP0) signal - * - * Revision 1.15 1998/10/28 13:52:52 malthoff - * Add new bits in RX_CMD register. - * - * Revision 1.14 1998/10/19 15:34:53 gklug - * fix: typos - * - * Revision 1.13 1998/10/14 07:19:03 malthoff - * bug fix: Every define which describes bit 31 - * must be declared as unsigned long 'UL'. - * fix bit definitions of PHY_AN_RFB and PHY_AN_PAUSE. - * Remove ANP defines. Rework the RFB defines. - * - * Revision 1.12 1998/10/14 06:22:44 cgoos - * Changed shifted constant to ULONG. - * - * Revision 1.11 1998/10/14 05:43:26 gklug - * add: shift pause coding - * fix: PAUSE bits definition - * - * Revision 1.10 1998/10/13 09:19:21 malthoff - * Again change XMR_FS_ANY_ERR because of new info from XaQti. - * - * Revision 1.9 1998/10/09 07:58:30 malthoff - * Add XMR_FS_FCS_ERR to XMR_FS_ANY_ERR. - * - * Revision 1.8 1998/10/09 07:18:17 malthoff - * bug fix of a bug fix: XM_PAUSE_MODE and XM_DEF_MODE - * are not inverted! Bug XM_DEF_MSK is inverted. - * - * Revision 1.7 1998/10/05 08:04:32 malthoff - * bug fix: XM_PAUSE_MODE and XM_DEF_MODE - * must be inverted declarations. - * - * Revision 1.6 1998/09/28 13:38:18 malthoff - * Add default modes and masks XM_DEF_MSK, - * XM_PAUSE_MODE and XM_DEF_MODE - * - * Revision 1.5 1998/09/16 14:42:04 malthoff - * Bug Fix: XM_GP_PORT is a 32 bit (not a 16 bit) register. - * - * Revision 1.4 1998/08/20 14:59:47 malthoff - * Rework this file after reading the XaQti data sheet - * "Differences between Rev. B2 & Rev. C XMAC II". - * This file is now 100% XMAC II Rev. C complained. - * - * Revision 1.3 1998/06/29 12:18:23 malthoff - * Correct XMR_FS_ANY_ERR definition. - * - * Revision 1.2 1998/06/29 12:10:56 malthoff - * Add define XMR_FS_ANY_ERR. - * - * Revision 1.1 1998/06/19 13:37:17 malthoff - * created. - * + * /LICENSE * ******************************************************************************/ @@ -548,18 +372,18 @@ extern "C" { /* Bit 16..6: reserved */ #define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */ #define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */ -#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */ +#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */ #define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */ #define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */ -#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */ +#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */ /* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ /* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ -#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ -#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/ -#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/ -#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/ +#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov */ +#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov */ +#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov */ +#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov */ #define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */ #define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */ #define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */ @@ -567,9 +391,9 @@ extern "C" { #define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */ /* Bit 22: reserved */ #define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */ -#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/ +#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov */ #define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */ -#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/ +#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov */ #define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */ /* Bit 16: reserved */ #define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */ @@ -578,57 +402,57 @@ extern "C" { #define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */ #define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */ #define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */ -#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/ +#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov */ #define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */ #define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ -#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ -#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/ +#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov */ +#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame Cnt Ov */ #define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */ #define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */ -#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/ -#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/ -#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */ +#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low Cnt Ov */ +#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK High Cnt Ov */ +#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received OK Ov */ #define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) /* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ /* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ /* Bit 31..26: reserved */ -#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ -#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/ -#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/ -#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/ +#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov */ +#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov */ +#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov */ +#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov */ #define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */ #define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */ #define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */ #define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */ -#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/ +#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov */ #define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ #define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */ #define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */ #define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */ -#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/ +#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov */ #define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */ #define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */ -#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/ -#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ +#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov */ +#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov */ #define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */ #define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */ #define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */ #define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */ #define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */ -#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/ -#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/ -#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */ +#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low Cnt Ov */ +#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK High Cnt Ov */ +#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx OK Ov */ #define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) /* * Receive Frame Status Encoding */ -#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */ -#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/ -#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/ +#define XMR_FS_LEN_MSK (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */ +#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: Tagged wh 2Lev VLAN ID */ +#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: Tagged wh 1Lev VLAN ID */ #define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */ #define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */ #define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */ @@ -646,6 +470,8 @@ extern "C" { #define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */ #define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */ +#define XMR_FS_LEN_SHIFT 18 + /* * XMR_FS_ERR will be set if * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, @@ -665,10 +491,10 @@ extern "C" { #define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ #define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ #define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */ +#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ #define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ +#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* 0x09 - 0x0e: reserved */ #define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */ #define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */ @@ -682,19 +508,19 @@ extern "C" { #define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ #define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ #define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ +#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ #define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ +#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* Broadcom-specific registers */ -#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ +#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ #define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ /* 0x0b - 0x0e: reserved */ #define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ #define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */ #define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */ #define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */ -#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carr Sense Cnt */ +#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carrier Sense Cnt */ #define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */ /* 0x15 - 0x17: reserved */ #define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */ @@ -713,29 +539,37 @@ extern "C" { #define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ #define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ #define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ +#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ #define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link P Reg */ +#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* Marvel-specific registers */ -#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ +#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ #define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ /* 0x0b - 0x0e: reserved */ #define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */ -#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */ +#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Control Reg */ +#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Status Reg */ #define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */ #define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ #define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */ #define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */ #define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */ - /* 0x17: reserved */ +#define PHY_MARV_PORT_IRQ 0x17 /* 16 bit r/o Port 0 IRQ (88E1111 only) */ #define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */ #define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */ #define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */ #define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */ #define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */ - /* 0x1d - 0x1f: reserved */ +#define PHY_MARV_PAGE_ADDR 0x1d /* 16 bit r/w Extended Page Address Reg */ +#define PHY_MARV_PAGE_DATA 0x1e /* 16 bit r/w Extended Page Data Reg */ + +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ +#define PHY_MARV_FE_LED_PAR 0x16 /* 16 bit r/w LED Parallel Select Reg. */ +#define PHY_MARV_FE_LED_SER 0x17 /* 16 bit r/w LED Stream Select S. LED */ +#define PHY_MARV_FE_VCT_TX 0x1a /* 16 bit r/w VCT Reg. for TXP/N Pins */ +#define PHY_MARV_FE_VCT_RX 0x1b /* 16 bit r/o VCT Reg. for RXP/N Pins */ +#define PHY_MARV_FE_SPEC_2 0x1c /* 16 bit r/w Specific Control Reg. 2 */ /*----------------------------------------------------------------------------*/ /* @@ -746,14 +580,14 @@ extern "C" { #define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ #define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ #define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ +#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ #define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ #define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner*/ +#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ /* Level One-specific registers */ -#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/ +#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ #define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ + /* 0x0b - 0x0e: reserved */ #define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ #define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/ #define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */ @@ -762,7 +596,7 @@ extern "C" { #define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */ #define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */ #define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */ - /* 0x17 -0x1c: reserved */ + /* 0x17 - 0x1c: reserved */ /*----------------------------------------------------------------------------*/ /* @@ -780,14 +614,14 @@ extern "C" { /* National-specific registers */ #define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ #define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ + /* 0x0b - 0x0e: reserved */ #define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */ #define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */ #define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */ #define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */ #define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */ #define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */ - /* 0x15 -0x18: reserved */ + /* 0x15 - 0x18: reserved */ #define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */ @@ -795,24 +629,25 @@ extern "C" { /* * PHY bit definitions - * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are - * Xmac/Broadcom/LevelOne/National-specific. + * Bits defined as PHY_X_..., PHY_B_..., PHY_L_..., PHY_N_... or PHY_M_... are + * XMAC/Broadcom/LevelOne/National/Marvell-specific. * All other are general. */ /***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/ /***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/ +/***** PHY_MARV_CTRL 16 bit r/w PHY Status Register *****/ /***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/ #define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */ #define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */ -#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */ +#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: Speed select, lower bit */ #define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */ -#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */ -#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */ -#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */ +#define PHY_CT_PDOWN (1<<11) /* Bit 11: Power Down Mode */ +#define PHY_CT_ISOL (1<<10) /* Bit 10: Isolate Mode */ +#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */ #define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */ -#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */ -#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */ +#define PHY_CT_COL_TST (1<<7) /* Bit 7: Collision Test enabled */ +#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: Speed select, upper bit */ /* Bit 5..0: reserved */ #define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */ @@ -825,25 +660,25 @@ extern "C" { /***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/ /***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/ /* Bit 15..9: reserved */ - /* (BC/L1) 100/10 Mbps cap bits ignored*/ + /* (BC/L1) 100/10 Mbps cap bits ignored */ #define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */ /* Bit 7: reserved */ -#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */ +#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: Preamble Suppression */ #define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */ #define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */ #define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */ #define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */ -#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */ +#define PHY_ST_JAB_DET (1<<1) /* Bit 1: Jabber Detected */ #define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */ -/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */ +/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */ +/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */ +/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */ +/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */ #define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */ #define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */ -#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */ +#define PHY_I1_REV_MSK 0xf /* Bit 3.. 0: Revision Number */ /* different Broadcom PHY Ids */ #define PHY_BCOM_ID1_A1 0x6041 @@ -851,11 +686,21 @@ extern "C" { #define PHY_BCOM_ID1_C0 0x6044 #define PHY_BCOM_ID1_C5 0x6047 +/* different Marvell PHY Ids */ +#define PHY_MARV_ID0_VAL 0x0141 /* Marvell Unique Identifier */ + +#define PHY_MARV_ID1_B0 0x0C23 /* Yukon (PHY 88E1040 Rev.C0) */ +#define PHY_MARV_ID1_B2 0x0C25 /* Yukon-Plus (PHY 88E1040 Rev.D0) */ +#define PHY_MARV_ID1_C2 0x0CC2 /* Yukon-EC (PHY 88E1111 Rev.B1) */ +#define PHY_MARV_ID1_Y2 0x0C91 /* Yukon-XL (PHY 88E1112 Rev.B0) */ +#define PHY_MARV_ID1_FE 0x0C83 /* Yukon-FE (PHY 88E3082 Rev.A1) */ +#define PHY_MARV_ID1_ECU 0x0CB0 /* Yukon-ECU (PHY 88E1149 Rev.B2?) */ + /***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ /***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ #define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */ -#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */ +#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */ #define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */ /* Bit 11.. 9: reserved */ #define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */ @@ -901,27 +746,20 @@ extern "C" { /***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ /* Bit 15..4: reserved */ -#define PHY_AN_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ -#define PHY_AN_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ -#define PHY_AN_RX_PG (1<<1) /* Bit 1: Page Received */ +#define PHY_ANE_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ +#define PHY_ANE_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ +#define PHY_ANE_RX_PG (1<<1) /* Bit 1: Page Received */ /* Bit 0: reserved */ /***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..5: reserved */ -#define PHY_B_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - /***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ -#define PHY_L_AN_BP (1<<5) /* Bit 5: Base Page Indication */ -#define PHY_L_AN_PDF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_AN_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_AN_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_AN_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_B_AN_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - +/***** PHY_MARV_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ + /* Bit 15..5: reserved */ +#define PHY_ANE_PAR_DF (1<<4) /* Bit 4: Parallel Detection Fault */ +/* PHY_ANE_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ +/* PHY_ANE_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ +/* PHY_ANE_RX_PG (see XMAC) Bit 1: Page Received */ +#define PHY_ANE_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Able */ /***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/ /***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/ @@ -930,9 +768,9 @@ extern "C" { /***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/ /***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/ #define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */ -#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack 1, for receiving a message*/ +#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack1, for receiving a message */ #define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */ -#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack 2, comply with msg content*/ +#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack2, comply with msg content */ #define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */ #define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */ @@ -950,7 +788,7 @@ extern "C" { #define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */ #define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */ #define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */ -#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability missmatch */ +#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability mismatch */ /* Bit 2..0: reserved */ /* * Remote Fault Bits (PHY_X_AN_RFB) encoding @@ -982,6 +820,7 @@ extern "C" { /* Bit 7..0: reserved */ /***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ #define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ #define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ #define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ @@ -1009,7 +848,7 @@ extern "C" { #define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */ #define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */ #define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */ -#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */ +#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Enable LED Traffic Mode */ #define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */ #define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */ #define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */ @@ -1123,7 +962,7 @@ extern "C" { #define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ #define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ #define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/ +#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */ #define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ #define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ /* Bit 9..8: reserved */ @@ -1163,7 +1002,7 @@ extern "C" { #define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */ #define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */ #define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */ -#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */ +#define PHY_L_QS_LLE (7<<4) /* Bit 6..4: Line Length Estim. */ #define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */ #define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */ #define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */ @@ -1175,8 +1014,8 @@ extern "C" { #define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */ /* Bit 12: not described */ #define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */ -#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used*/ -#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade*/ +#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used */ +#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade */ #define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */ #define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */ #define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */ @@ -1211,9 +1050,8 @@ extern "C" { /* Bit 9..0: not described */ /***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/ -#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */ -#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */ - +#define PHY_L_CIM_ISOL (0xff<<8) /* Bit 15..8: Isolate Count */ +#define PHY_L_CIM_FALSE_CAR 0xff /* Bit 7..0: False Carrier Count */ /* * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding @@ -1223,7 +1061,6 @@ extern "C" { #define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ #define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ - /* * National-Specific */ @@ -1267,23 +1104,25 @@ extern "C" { * Marvell-Specific */ /***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/ -#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */ -#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */ -#define PHY_M_AN_RF BIT_13 /* Remote Fault */ - /* Bit 12: reserved */ -#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */ -#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */ -#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */ -#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */ -#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */ -#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */ +/***** PHY_MARV_AUNE_LP 16 bit r/w Link Partner Ability Reg *****/ +#define PHY_M_AN_NXT_PG BIT_15S /* Request Next Page */ +#define PHY_M_AN_ACK BIT_14S /* (ro) Acknowledge Received */ +#define PHY_M_AN_RF BIT_13S /* Remote Fault */ + /* Bit 12: reserved */ +#define PHY_M_AN_ASP BIT_11S /* Asymmetric Pause */ +#define PHY_M_AN_PC BIT_10S /* MAC Pause implemented */ +#define PHY_M_AN_100_T4 BIT_9S /* Not cap. 100Base-T4 (always 0) */ +#define PHY_M_AN_100_FD BIT_8S /* Advertise 100Base-TX Full Duplex */ +#define PHY_M_AN_100_HD BIT_7S /* Advertise 100Base-TX Half Duplex */ +#define PHY_M_AN_10_FD BIT_6S /* Advertise 10Base-TX Full Duplex */ +#define PHY_M_AN_10_HD BIT_5S /* Advertise 10Base-TX Half Duplex */ +#define PHY_M_AN_SEL_MSK (0x1f<<4) /* Bit 4.. 0: Selector Field Mask */ -/* special defines for FIBER (88E1011S only) */ -#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */ -#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */ -#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */ -#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */ +/* special defines for FIBER (88E1040S only) */ +#define PHY_M_AN_ASP_X BIT_8S /* Asymmetric Pause */ +#define PHY_M_AN_PC_X BIT_7S /* MAC Pause implemented */ +#define PHY_M_AN_1000X_AHD BIT_6S /* Advertise 10000Base-X Half Duplex */ +#define PHY_M_AN_1000X_AFD BIT_5S /* Advertise 10000Base-X Full Duplex */ /* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ #define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */ @@ -1293,102 +1132,168 @@ extern "C" { /***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ #define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */ -#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */ -#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */ -#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ +#define PHY_M_1000C_MSE BIT_12S /* Manual Master/Slave Enable */ +#define PHY_M_1000C_MSC BIT_11S /* M/S Configuration (1=Master) */ +#define PHY_M_1000C_MPD BIT_10S /* Multi-Port Device */ +#define PHY_M_1000C_AFD BIT_9S /* Advertise Full Duplex */ +#define PHY_M_1000C_AHD BIT_8S /* Advertise Half Duplex */ /* Bit 7..0: reserved */ /***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ +#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */ +#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */ +#define PHY_M_PC_ASS_CRS_TX BIT_11S /* Assert CRS on Transmit */ +#define PHY_M_PC_FL_GOOD BIT_10S /* Force Link Good */ +#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */ +#define PHY_M_PC_ENA_EXT_D BIT_7S /* Enable Ext. Distance (10BT) */ +#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */ +#define PHY_M_PC_DIS_125CLK BIT_4S /* Disable 125 CLK */ +#define PHY_M_PC_MAC_POW_UP BIT_3S /* MAC Power up */ +#define PHY_M_PC_SQE_T_ENA BIT_2S /* SQE Test Enabled */ +#define PHY_M_PC_POL_R_DIS BIT_1S /* Polarity Reversal Disabled */ +#define PHY_M_PC_DIS_JABBER BIT_0S /* Disable Jabber */ -#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */ -#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */ -#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */ -#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */ -#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */ -#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */ -#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */ -#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */ -#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */ -#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */ -#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */ -#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */ +#define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */ +#define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */ -#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x) -#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */ +#define PHY_M_PC_MDI_XMODE(x) (SHIFT5(x) & PHY_M_PC_MDIX_MSK) + +#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */ #define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */ #define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */ +/* for Yukon-2/-EC Ultra Gigabit Ethernet PHY (88E1112/88E1149 only) */ +#define PHY_M_PC_DIS_LINK_P BIT_15S /* Disable Link Pulses */ +#define PHY_M_PC_DSC_MSK (7<<12) /* Bit 14..12: Downshift Counter */ +#define PHY_M_PC_DOWN_S_ENA BIT_11S /* Downshift Enable */ + /* !!! Errata in spec. (1 = disable) */ + +#define PHY_M_PC_DSC(x) (SHIFT12(x) & PHY_M_PC_DSC_MSK) + /* 000=1x; 001=2x; 010=3x; 011=4x */ + /* 100=5x; 101=6x; 110=7x; 111=8x */ + +/* for Yukon-EC Ultra Gigabit Ethernet PHY (88E1149 only) */ + /* Bit 4: reserved */ +#define PHY_M_PC_COP_TX_DIS BIT_3S /* Copper Transmitter Disable */ +#define PHY_M_PC_POW_D_ENA BIT_2S /* Power Down Enable */ + +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ +#define PHY_M_PC_ENA_DTE_DT BIT_15S /* Enable Data Terminal Equ. (DTE) Detect */ +#define PHY_M_PC_ENA_ENE_DT BIT_14S /* Enable Energy Detect (sense & pulse) */ +#define PHY_M_PC_DIS_NLP_CK BIT_13S /* Disable Normal Link Puls (NLP) Check */ +#define PHY_M_PC_ENA_LIP_NP BIT_12S /* Enable Link Partner Next Page Reg. */ +#define PHY_M_PC_DIS_NLP_GN BIT_11S /* Disable Normal Link Puls Generation */ + +#define PHY_M_PC_DIS_SCRAMB BIT_9S /* Disable Scrambler */ +#define PHY_M_PC_DIS_FEFI BIT_8S /* Disable Far End Fault Indic. (FEFI) */ + +#define PHY_M_PC_SH_TP_SEL BIT_6S /* Shielded Twisted Pair Select */ +#define PHY_M_PC_RX_FD_MSK (3<<2) /* Bit 3.. 2: Rx FIFO Depth Mask */ + /***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ -#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */ -#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */ -#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */ -#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */ -#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */ -#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */ -#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */ -#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */ -#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */ -#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */ -#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */ -#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */ -#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */ -#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */ -#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */ -#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */ +#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */ +#define PHY_M_PS_SPEED_1000 BIT_15S /* 10 = 1000 Mbps */ +#define PHY_M_PS_SPEED_100 BIT_14S /* 01 = 100 Mbps */ +#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */ +#define PHY_M_PS_FULL_DUP BIT_13S /* Full Duplex */ +#define PHY_M_PS_PAGE_REC BIT_12S /* Page Received */ +#define PHY_M_PS_SPDUP_RES BIT_11S /* Speed & Duplex Resolved */ +#define PHY_M_PS_LINK_UP BIT_10S /* Link Up */ +#define PHY_M_PS_CABLE_MSK (7<<7) /* Bit 9.. 7: Cable Length Mask */ +#define PHY_M_PS_MDI_X_STAT BIT_6S /* MDI Crossover Stat (1=MDIX) */ +#define PHY_M_PS_DOWNS_STAT BIT_5S /* Downshift Status (1=downsh.) */ +#define PHY_M_PS_ENDET_STAT BIT_4S /* Energy Detect Status (1=act) */ +#define PHY_M_PS_TX_P_EN BIT_3S /* Tx Pause Enabled */ +#define PHY_M_PS_RX_P_EN BIT_2S /* Rx Pause Enabled */ +#define PHY_M_PS_POL_REV BIT_1S /* Polarity Reversed */ +#define PHY_M_PS_JABBER BIT_0S /* Jabber */ #define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ +#define PHY_M_PS_DTE_DETECT BIT_15S /* Data Terminal Equipment (DTE) Detected */ +#define PHY_M_PS_RES_SPEED BIT_14S /* Resolved Speed (1=100 Mbps, 0=10 Mbps */ + /***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ /***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */ -#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */ -#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */ -#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */ -#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */ -#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */ -#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */ -#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */ -#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */ -#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */ -#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */ -#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */ - /* Bit 3..2: reserved */ -#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */ -#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */ +#define PHY_M_IS_AN_ERROR BIT_15S /* Auto-Negotiation Error */ +#define PHY_M_IS_LSP_CHANGE BIT_14S /* Link Speed Changed */ +#define PHY_M_IS_DUP_CHANGE BIT_13S /* Duplex Mode Changed */ +#define PHY_M_IS_AN_PR BIT_12S /* Page Received */ +#define PHY_M_IS_AN_COMPL BIT_11S /* Auto-Negotiation Completed */ +#define PHY_M_IS_LST_CHANGE BIT_10S /* Link Status Changed */ +#define PHY_M_IS_SYMB_ERROR BIT_9S /* Symbol Error */ +#define PHY_M_IS_FALSE_CARR BIT_8S /* False Carrier */ +#define PHY_M_IS_FIFO_ERROR BIT_7S /* FIFO Overflow/Underrun Error */ +#define PHY_M_IS_MDI_CHANGE BIT_6S /* MDI Crossover Changed */ +#define PHY_M_IS_DOWNSH_DET BIT_5S /* Downshift Detected */ +#define PHY_M_IS_END_CHANGE BIT_4S /* Energy Detect Changed */ + /* Bit 3: reserved */ +#define PHY_M_IS_DTE_CHANGE BIT_2S /* DTE Power Det. Status Changed */ + /* (88E1111 only) */ +#define PHY_M_IS_POL_CHANGE BIT_1S /* Polarity Changed */ +#define PHY_M_IS_JABBER BIT_0S /* Jabber */ #define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \ - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) + PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR | \ + PHY_M_IS_END_CHANGE) /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ -#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */ -#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */ +#define PHY_M_EC_ENA_BC_EXT BIT_15S /* Enable Block Carr. Ext. (88E1111 only) */ +#define PHY_M_EC_ENA_LIN_LB BIT_14S /* Enable Line Loopback (88E1111 only) */ + /* Bit 13: reserved */ +#define PHY_M_EC_DIS_LINK_P BIT_12S /* Disable Link Pulses (88E1111 only) */ +#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master Downshift Counter */ + /* (88E1040 Rev.C0 only) */ +#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave Downshift Counter */ + /* (88E1040 Rev.C0 only) */ +#define PHY_M_EC_DSC_MSK_2 (7<<9) /* Bit 11.. 9: Downshift Counter */ + /* (88E1040 Rev.D0 and higher) */ +#define PHY_M_EC_DOWN_S_ENA BIT_8S /* Downshift Enable (88E1040 Rev.D0 and */ + /* 88E1111 !!! Errata in spec. (1=dis.) */ +#define PHY_M_EC_RX_TIM_CT BIT_7S /* RGMII Rx Timing Control*/ #define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */ +#define PHY_M_EC_FIB_AN_ENA BIT_3S /* Fiber Auto-Neg. Enable 88E1040S only) */ +#define PHY_M_EC_DTE_D_ENA BIT_2S /* DTE Detect Enable (88E1111 only) */ +#define PHY_M_EC_TX_TIM_CT BIT_1S /* RGMII Tx Timing Control */ +#define PHY_M_EC_TRANS_DIS BIT_0S /* Transmitter Disable (88E1111 only) */ -#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */ +#define PHY_M_EC_M_DSC(x) (SHIFT10(x) & PHY_M_EC_M_DSC_MSK) + /* 00=1x; 01=2x; 10=3x; 11=4x */ +#define PHY_M_EC_S_DSC(x) (SHIFT8(x) & PHY_M_EC_S_DSC_MSK) + /* 00=dis; 01=1x; 10=2x; 11=3x */ +#define PHY_M_EC_MAC_S(x) (SHIFT4(x) & PHY_M_EC_MAC_S_MSK) + /* 01X=0; 110=2.5; 111=25 (MHz) */ +#define PHY_M_EC_DSC_2(x) (SHIFT9(x) & PHY_M_EC_DSC_MSK_2) + /* 000=1x; 001=2x; 010=3x; 011=4x */ + /* 100=5x; 101=6x; 110=7x; 111=8x */ #define MAC_TX_CLK_0_MHZ 2 #define MAC_TX_CLK_2_5_MHZ 6 #define MAC_TX_CLK_25_MHZ 7 /***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ -#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */ -#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */ -#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */ -#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */ - /* Bit 7.. 5: reserved */ -#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */ -#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */ -#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */ -#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */ +#define PHY_M_LEDC_DIS_LED BIT_15S /* Disable LED */ +#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */ +#define PHY_M_LEDC_F_INT BIT_11S /* Force Interrupt */ +#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */ +#define PHY_M_LEDC_DP_C_LSB BIT_7S /* Duplex Control (LSB, 88E1111 only) */ +#define PHY_M_LEDC_TX_C_LSB BIT_6S /* Tx Control (LSB, 88E1111 only) */ +#define PHY_M_LEDC_LK_C_MSK (7<<3) /* Bit 5.. 3: Link Control Mask */ + /* (88E1111 only) */ + /* Bit 7.. 5: reserved (88E1040 only) */ +#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */ + /* (88E1040 only) */ +#define PHY_M_LEDC_DP_CTRL BIT_2S /* Duplex Control */ +#define PHY_M_LEDC_DP_C_MSB BIT_2S /* Duplex Control (MSB, 88E1111 only) */ +#define PHY_M_LEDC_RX_CTRL BIT_1S /* Rx Activity / Link */ +#define PHY_M_LEDC_TX_CTRL BIT_0S /* Tx Activity / Link */ +#define PHY_M_LEDC_TX_C_MSB BIT_0S /* Tx Control (MSB, 88E1111 only) */ -#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */ +#define PHY_M_LED_PULS_DUR(x) (SHIFT12(x) & PHY_M_LEDC_PULS_MSK) -#define PULS_NO_STR 0 /* no pulse stretching */ -#define PULS_21MS 1 /* 21 ms to 42 ms */ +#define PULS_NO_STR 0 /* no pulse stretching */ +#define PULS_21MS 1 /* 21 ms to 42 ms */ #define PULS_42MS 2 /* 42 ms to 84 ms */ #define PULS_84MS 3 /* 84 ms to 170 ms */ #define PULS_170MS 4 /* 170 ms to 340 ms */ @@ -1396,7 +1301,7 @@ extern "C" { #define PULS_670MS 6 /* 670 ms to 1.3 s */ #define PULS_1300MS 7 /* 1.3 s to 2.7 s */ -#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */ +#define PHY_M_LED_BLINK_RT(x) (SHIFT8(x) & PHY_M_LEDC_BL_R_MSK) #define BLINK_42MS 0 /* 42 ms */ #define BLINK_84MS 1 /* 84 ms */ @@ -1406,6 +1311,8 @@ extern "C" { /* values 5 - 7: reserved */ /***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ +#define PHY_M_LED_MO_SGMII(x) SHIFT14(x) /* Bit 15..14: SGMII AN Timer */ + /* Bit 13..12: reserved */ #define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */ #define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */ #define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */ @@ -1419,18 +1326,35 @@ extern "C" { #define MO_LED_ON 3 /***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ - /* Bit 15.. 7: reserved */ -#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */ -#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */ -#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */ -#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */ + /* Bit 15.. 7: reserved */ +#define PHY_M_EC2_FI_IMPED BIT_6S /* Fiber Input Impedance */ +#define PHY_M_EC2_FO_IMPED BIT_5S /* Fiber Output Impedance */ +#define PHY_M_EC2_FO_M_CLK BIT_4S /* Fiber Mode Clock Enable */ +#define PHY_M_EC2_FO_BOOST BIT_3S /* Fiber Output Boost */ #define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */ +/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ +#define PHY_M_FC_AUTO_SEL BIT_15S /* Fiber/Copper Auto Sel. Dis. */ +#define PHY_M_FC_AN_REG_ACC BIT_14S /* Fiber/Copper AN Reg. Access */ +#define PHY_M_FC_RESOLUTION BIT_13S /* Fiber/Copper Resolution */ +#define PHY_M_SER_IF_AN_BP BIT_12S /* Ser. IF AN Bypass Enable */ +#define PHY_M_SER_IF_BP_ST BIT_11S /* Ser. IF AN Bypass Status */ +#define PHY_M_IRQ_POLARITY BIT_10S /* IRQ polarity */ +#define PHY_M_DIS_AUT_MED BIT_9S /* Disable Aut. Medium Reg. Selection */ + /* (88E1111 only) */ + /* Bit 9.. 4: reserved (88E1040 only) */ +#define PHY_M_UNDOC1 BIT_7S /* undocumented bit !! */ +#define PHY_M_DTE_POW_STAT BIT_4S /* DTE Power Status (88E1111 only) */ +#define PHY_M_MODE_MASK 0xf /* Bit 3.. 0: copy of HWCFG MODE[3:0] */ + /***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ -#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */ -#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */ - /* Bit 12.. 8: reserved */ -#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */ +#define PHY_M_CABD_ENA_TEST BIT_15S /* Enable Test (Page 0) */ +#define PHY_M_CABD_DIS_WAIT BIT_15S /* Disable Waiting Period (Page 1) */ + /* (88E1111 only) */ +#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status Mask */ +#define PHY_M_CABD_AMPL_MSK (0x1f<<8) /* Bit 12.. 8: Amplitude Mask */ + /* (88E1111 only) */ +#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance Mask */ /* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ #define CABD_STAT_NORMAL 0 @@ -1438,6 +1362,79 @@ extern "C" { #define CABD_STAT_OPEN 2 #define CABD_STAT_FAIL 3 +/* for 10/100 Fast Ethernet PHY (88E3082 only) */ +/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/ + /* Bit 15..12: reserved (used internally) */ +#define PHY_M_FELP_LED2_MSK (0xf<<8) /* Bit 11.. 8: LED2 Mask (LINK) */ +#define PHY_M_FELP_LED1_MSK (0xf<<4) /* Bit 7.. 4: LED1 Mask (ACT) */ +#define PHY_M_FELP_LED0_MSK 0xf /* Bit 3.. 0: LED0 Mask (SPEED) */ + +#define PHY_M_FELP_LED2_CTRL(x) (SHIFT8(x) & PHY_M_FELP_LED2_MSK) +#define PHY_M_FELP_LED1_CTRL(x) (SHIFT4(x) & PHY_M_FELP_LED1_MSK) +#define PHY_M_FELP_LED0_CTRL(x) (SHIFT0(x) & PHY_M_FELP_LED0_MSK) + +#define LED_PAR_CTRL_COLX 0x00 +#define LED_PAR_CTRL_ERROR 0x01 +#define LED_PAR_CTRL_DUPLEX 0x02 +#define LED_PAR_CTRL_DP_COL 0x03 +#define LED_PAR_CTRL_SPEED 0x04 +#define LED_PAR_CTRL_LINK 0x05 +#define LED_PAR_CTRL_TX 0x06 +#define LED_PAR_CTRL_RX 0x07 +#define LED_PAR_CTRL_ACT 0x08 +#define LED_PAR_CTRL_LNK_RX 0x09 +#define LED_PAR_CTRL_LNK_AC 0x0a +#define LED_PAR_CTRL_ACT_BL 0x0b +#define LED_PAR_CTRL_TX_BL 0x0c +#define LED_PAR_CTRL_RX_BL 0x0d +#define LED_PAR_CTRL_COL_BL 0x0e +#define LED_PAR_CTRL_INACT 0x0f + +/***** PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/ +#define PHY_M_FESC_DIS_WAIT BIT_2S /* Disable TDR Waiting Period */ +#define PHY_M_FESC_ENA_MCLK BIT_1S /* Enable MAC Rx Clock in sleep mode */ +#define PHY_M_FESC_SEL_CL_A BIT_0S /* Select Class A driver (100B-TX) */ + +/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ +/***** PHY_MARV_PHY_CTRL (page 1) 16 bit r/w Fiber Specific Ctrl *****/ +#define PHY_M_FIB_FORCE_LNK BIT_10S /* Force Link Good */ +#define PHY_M_FIB_SIGD_POL BIT_9S /* SIGDET Polarity */ +#define PHY_M_FIB_TX_DIS BIT_3S /* Transmitter Disable */ + +/***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/ +#define PHY_M_MAC_MD_MSK (7<<7) /* Bit 9.. 7: Mode Select Mask */ +#define PHY_M_MAC_GMIF_PUP BIT_3S /* GMII Power Up (88E1149 only) */ + +#define PHY_M_MAC_MD_AUTO 3 /* Auto Copper/1000Base-X */ +#define PHY_M_MAC_MD_COPPER 5 /* Copper only */ +#define PHY_M_MAC_MD_1000BX 7 /* 1000Base-X only */ +#define PHY_M_MAC_MODE_SEL(x) (SHIFT7(x) & PHY_M_MAC_MD_MSK) + +/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ +#define PHY_M_LEDC_LOS_MSK (0xf<<12) /* Bit 15..12: LOS LED Ctrl. Mask */ +#define PHY_M_LEDC_INIT_MSK (0xf<<8) /* Bit 11.. 8: INIT LED Ctrl. Mask */ +#define PHY_M_LEDC_STA1_MSK (0xf<<4) /* Bit 7.. 4: STAT1 LED Ctrl. Mask */ +#define PHY_M_LEDC_STA0_MSK 0xf /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ + +#define PHY_M_LEDC_LOS_CTRL(x) (SHIFT12(x) & PHY_M_LEDC_LOS_MSK) +#define PHY_M_LEDC_INIT_CTRL(x) (SHIFT8(x) & PHY_M_LEDC_INIT_MSK) +#define PHY_M_LEDC_STA1_CTRL(x) (SHIFT4(x) & PHY_M_LEDC_STA1_MSK) +#define PHY_M_LEDC_STA0_CTRL(x) (SHIFT0(x) & PHY_M_LEDC_STA0_MSK) + +/***** PHY_MARV_PHY_STAT (page 3) 16 bit r/w Polarity Control Reg. *****/ +#define PHY_M_POLC_LS1M_MSK (0xf<<12) /* Bit 15..12: LOS,STAT1 Mix % Mask */ +#define PHY_M_POLC_IS0M_MSK (0xf<<8) /* Bit 11.. 8: INIT,STAT0 Mix % Mask */ +#define PHY_M_POLC_LOS_MSK (0x3<<6) /* Bit 7.. 6: LOS Pol. Ctrl. Mask */ +#define PHY_M_POLC_INIT_MSK (0x3<<4) /* Bit 5.. 4: INIT Pol. Ctrl. Mask */ +#define PHY_M_POLC_STA1_MSK (0x3<<2) /* Bit 3.. 2: STAT1 Pol. Ctrl. Mask */ +#define PHY_M_POLC_STA0_MSK 0x3 /* Bit 1.. 0: STAT0 Pol. Ctrl. Mask */ + +#define PHY_M_POLC_LS1_P_MIX(x) (SHIFT12(x) & PHY_M_POLC_LS1M_MSK) +#define PHY_M_POLC_IS0_P_MIX(x) (SHIFT8(x) & PHY_M_POLC_IS0M_MSK) +#define PHY_M_POLC_LOS_CTRL(x) (SHIFT6(x) & PHY_M_POLC_LOS_MSK) +#define PHY_M_POLC_INIT_CTRL(x) (SHIFT4(x) & PHY_M_POLC_INIT_MSK) +#define PHY_M_POLC_STA1_CTRL(x) (SHIFT2(x) & PHY_M_POLC_STA1_MSK) +#define PHY_M_POLC_STA0_CTRL(x) (SHIFT0(x) & PHY_M_POLC_STA0_MSK) /* * GMAC registers @@ -1460,7 +1457,7 @@ extern "C" { #define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */ #define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */ #define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */ -#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow Control */ +#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow-Control */ #define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */ #define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */ @@ -1523,7 +1520,7 @@ extern "C" { #define GM_RXF_SHT \ (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */ #define GM_RXE_FRAG \ - (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Receeived with FCS Err */ + (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Received with FCS Err */ #define GM_RXF_64B \ (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */ #define GM_RXF_127B \ @@ -1598,133 +1595,159 @@ extern "C" { */ /* GM_GP_STAT 16 bit r/o General Purpose Status Register */ - -#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */ -#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */ -#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow Control Mode Disabled */ -#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */ -#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */ -#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */ -#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */ -#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */ - /* Bit 7..6: reserved */ -#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */ -#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ -#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */ -#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow Control Mode Disabled */ -#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */ - /* Bit 0: reserved */ +#define GM_GPSR_SPEED BIT_15S /* Port Speed (1 = 100 Mbps) */ +#define GM_GPSR_DUPLEX BIT_14S /* Duplex Mode (1 = Full) */ +#define GM_GPSR_FC_TX_DIS BIT_13S /* Tx Flow-Control Mode Disabled */ +#define GM_GPSR_LINK_UP BIT_12S /* Link Up Status */ +#define GM_GPSR_PAUSE BIT_11S /* Pause State */ +#define GM_GPSR_TX_ACTIVE BIT_10S /* Tx in Progress */ +#define GM_GPSR_EXC_COL BIT_9S /* Excessive Collisions Occured */ +#define GM_GPSR_LAT_COL BIT_8S /* Late Collisions Occured */ + /* Bit 7.. 6: reserved */ +#define GM_GPSR_PHY_ST_CH BIT_5S /* PHY Status Change */ +#define GM_GPSR_GIG_SPEED BIT_4S /* Gigabit Speed (1 = 1000 Mbps) */ +#define GM_GPSR_PART_MODE BIT_3S /* Partition mode */ +#define GM_GPSR_FC_RX_DIS BIT_2S /* Rx Flow-Control Mode Disabled */ + /* Bit 2.. 0: reserved */ /* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ - /* Bit 15: reserved */ -#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */ -#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow Control Mode */ -#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */ -#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */ -#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */ -#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */ -#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */ -#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */ -#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */ -#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */ -#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow Control Mode */ -#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */ -#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update for Duplex */ -#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update for Flow-c. */ -#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update for Speed */ +#define GM_GPCR_RMII_PH_ENA BIT_15S /* Enable RMII for PHY (Yukon-FE only) */ +#define GM_GPCR_RMII_LB_ENA BIT_14S /* Enable RMII Loopback (Yukon-FE only) */ +#define GM_GPCR_FC_TX_DIS BIT_13S /* Disable Tx Flow-Control Mode */ +#define GM_GPCR_TX_ENA BIT_12S /* Enable Transmit */ +#define GM_GPCR_RX_ENA BIT_11S /* Enable Receive */ + /* Bit 10: reserved */ +#define GM_GPCR_LOOP_ENA BIT_9S /* Enable MAC Loopback Mode */ +#define GM_GPCR_PART_ENA BIT_8S /* Enable Partition Mode */ +#define GM_GPCR_GIGS_ENA BIT_7S /* Gigabit Speed (1000 Mbps) */ +#define GM_GPCR_FL_PASS BIT_6S /* Force Link Pass */ +#define GM_GPCR_DUP_FULL BIT_5S /* Full Duplex Mode */ +#define GM_GPCR_FC_RX_DIS BIT_4S /* Disable Rx Flow-Control Mode */ +#define GM_GPCR_SPEED_100 BIT_3S /* Port Speed 100 Mbps */ +#define GM_GPCR_AU_DUP_DIS BIT_2S /* Disable Auto-Update Duplex */ +#define GM_GPCR_AU_FCT_DIS BIT_1S /* Disable Auto-Update Flow-C. */ +#define GM_GPCR_AU_SPD_DIS BIT_0S /* Disable Auto-Update Speed */ #define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) #define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\ GM_GPCR_AU_SPD_DIS) /* GM_TX_CTRL 16 bit r/w Transmit Control Register */ +#define GM_TXCR_FORCE_JAM BIT_15S /* Force Jam / Flow-Control */ +#define GM_TXCR_CRC_DIS BIT_14S /* Disable insertion of CRC */ +#define GM_TXCR_PAD_DIS BIT_13S /* Disable padding of packets */ +#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold Mask */ + /* Bit 9.. 8: reserved */ +#define GM_TXCR_PAD_PAT_MSK 0xff /* Bit 7.. 0: Padding Pattern Mask */ + /* (Yukon-2 only) */ -#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */ -#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */ -#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */ -#define GM_TXCR_COL_THR (4<<10) /* Bit 12..10: Collision Threshold */ +#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK) + +#define TX_COL_DEF 0x04 /* GM_RX_CTRL 16 bit r/w Receive Control Register */ -#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */ -#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */ -#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */ -#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */ +#define GM_RXCR_UCF_ENA BIT_15S /* Enable Unicast filtering */ +#define GM_RXCR_MCF_ENA BIT_14S /* Enable Multicast filtering */ +#define GM_RXCR_CRC_DIS BIT_13S /* Remove 4-byte CRC */ +#define GM_RXCR_PASS_FC BIT_12S /* Pass FC packets to FIFO (Yukon-1 only) */ + /* Bit 11.. 0: reserved */ /* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ -#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */ -#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */ -#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */ - /* Bit 3..0: reserved */ -#define JAM_LEN_VAL(x) SHIFT14(x) -#define JAM_IPG_VAL(x) SHIFT9(x) -#define IPG_JAM_DATA(x) SHIFT4(x) +#define GM_TXPA_JAMLEN_MSK (3<<14) /* Bit 15..14: Jam Length Mask */ +#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13.. 9: Jam IPG Mask */ +#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8.. 4: IPG Jam to Data Mask */ +#define GM_TXPA_BO_LIM_MSK 0x0f /* Bit 3.. 0: Backoff Limit Mask */ + /* (Yukon-2 only) */ + +#define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK) +#define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK) +#define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK) +#define TX_BACK_OFF_LIM(x) ((x) & GM_TXPA_BO_LIM_MSK) + +#define TX_JAM_LEN_DEF 0x03 +#define TX_JAM_IPG_DEF 0x0b +#define TX_IPG_JAM_DEF 0x1c +#define TX_BOF_LIM_DEF 0x04 /* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ #define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder */ -#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive transmit trials */ -#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Length) */ -#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Length) */ - /* Bit 7..5: reserved */ -#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ + /* r/o on Yukon, r/w on Yukon-EC */ +#define GM_SMOD_LIMIT_4 BIT_10S /* 4 consecutive Tx trials */ +#define GM_SMOD_VLAN_ENA BIT_9S /* Enable VLAN (Max. Frame Len) */ +#define GM_SMOD_JUMBO_ENA BIT_8S /* Enable Jumbo (Max. Frame Len) */ + /* Bit 7.. 5: reserved */ +#define GM_SMOD_IPG_MSK 0x1f /* Bit 4.. 0: Inter-Packet Gap (IPG) */ -#define DATA_BLIND_VAL(x) SHIFT11(x) -#define DATA_BLIND_FAST_ETH 0x1c -#define DATA_BLIND_GIGABIT 4 +#define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK) +#define IPG_DATA_VAL(x) ((x) & GM_SMOD_IPG_MSK) -#define IPG_VAL_FAST_ETH 0x1e -#define IPG_VAL_GIGABIT 6 +#define DATA_BLIND_DEF 0x04 +#define IPG_DATA_DEF 0x1e /* GM_SMI_CTRL 16 bit r/w SMI Control Register */ +#define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */ +#define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */ +#define GM_SMI_CT_OP_RD BIT_5S /* OpCode Read (0=Write)*/ +#define GM_SMI_CT_RD_VAL BIT_4S /* Read Valid (Read completed) */ +#define GM_SMI_CT_BUSY BIT_3S /* Busy (Operation in progress) */ + /* Bit 2.. 0: reserved */ -#define GM_SMI_CT_PHY_AD(x) SHIFT11(x) -#define GM_SMI_CT_REG_AD(x) SHIFT6(x) -#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/ -#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */ -#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */ - /* Bit 2..0: reserved */ +#define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK) +#define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK) /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ - /* Bit 15..6: reserved */ -#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */ -#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */ - /* Bit 3..0: reserved */ + /* Bit 15.. 6: reserved */ +#define GM_PAR_MIB_CLR BIT_5S /* Set MIB Clear Counter Mode */ +#define GM_PAR_MIB_TST BIT_4S /* MIB Load Counter (Test Mode) */ + /* Bit 3.. 0: reserved */ /* Receive Frame Status Encoding */ -#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */ +#define GMR_FS_LEN_MSK (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */ /* Bit 15..14: reserved */ -#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */ -#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */ -#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */ -#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */ -#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */ -#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */ -#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */ -#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */ -#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */ -#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */ -#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */ +#define GMR_FS_VLAN BIT_13 /* VLAN Packet */ +#define GMR_FS_JABBER BIT_12 /* Jabber Packet */ +#define GMR_FS_UN_SIZE BIT_11 /* Undersize Packet */ +#define GMR_FS_MC BIT_10 /* Multicast Packet */ +#define GMR_FS_BC BIT_9 /* Broadcast Packet */ +#define GMR_FS_RX_OK BIT_8 /* Receive OK (Good Packet) */ +#define GMR_FS_GOOD_FC BIT_7 /* Good Flow-Control Packet */ +#define GMR_FS_BAD_FC BIT_6 /* Bad Flow-Control Packet */ +#define GMR_FS_MII_ERR BIT_5 /* MII Error */ +#define GMR_FS_LONG_ERR BIT_4 /* Too Long Packet */ +#define GMR_FS_FRAGMENT BIT_3 /* Fragment */ /* Bit 2: reserved */ -#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */ -#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */ +#define GMR_FS_CRC_ERR BIT_1 /* CRC Error */ +#define GMR_FS_RX_FF_OV BIT_0 /* Rx FIFO Overflow */ + +#define GMR_FS_LEN_SHIFT 16 /* * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) */ -#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \ - GMR_FS_LONG_ERR | \ +#ifdef SK_DIAG +#define GMR_FS_ANY_ERR ( \ + GMR_FS_RX_FF_OV | \ + GMR_FS_CRC_ERR | \ + GMR_FS_FRAGMENT | \ GMR_FS_MII_ERR | \ GMR_FS_BAD_FC | \ GMR_FS_GOOD_FC | \ GMR_FS_JABBER) - -/* Rx GMAC FIFO Flush Mask (default) */ -#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \ +#else +#define GMR_FS_ANY_ERR ( \ GMR_FS_RX_FF_OV | \ + GMR_FS_CRC_ERR | \ + GMR_FS_FRAGMENT | \ + GMR_FS_LONG_ERR | \ GMR_FS_MII_ERR | \ GMR_FS_BAD_FC | \ GMR_FS_GOOD_FC | \ GMR_FS_UN_SIZE | \ GMR_FS_JABBER) +#endif + +/* Rx GMAC FIFO Flush Mask (default) */ +#define RX_FF_FL_DEF_MSK GMR_FS_ANY_ERR /* typedefs *******************************************************************/ @@ -1736,3 +1759,4 @@ extern "C" { #endif /* __cplusplus */ #endif /* __INC_XMAC_H */ + diff --git a/drivers/sk98lin/skaddr.c b/drivers/sk98lin/skaddr.c index ed79c04..86e540e 100644 --- a/drivers/sk98lin/skaddr.c +++ b/drivers/sk98lin/skaddr.c @@ -1,16 +1,18 @@ /****************************************************************************** * * Name: skaddr.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.48 $ - * Date: $Date: 2003/02/12 17:09:37 $ + * Project: Gigabit Ethernet Adapters, ADDR-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode. * ******************************************************************************/ /****************************************************************************** * + * LICENSE: * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. * * 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 @@ -18,183 +20,7 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skaddr.c,v $ - * Revision 1.48 2003/02/12 17:09:37 tschilli - * Fix in SkAddrOverride() to set both (physical and logical) MAC addresses - * in case that both addresses are identical. - * - * Revision 1.47 2002/09/17 06:31:10 tschilli - * Handling of SK_PROM_MODE_ALL_MC flag in SkAddrGmacMcUpdate() - * and SkAddrGmacPromiscuousChange() fixed. - * Editorial changes. - * - * Revision 1.46 2002/08/22 07:55:41 tschilli - * New function SkGmacMcHash() for GMAC multicast hashing algorithm added. - * Editorial changes. - * - * Revision 1.45 2002/08/15 12:29:35 tschilli - * SkAddrGmacMcUpdate() and SkAddrGmacPromiscuousChange() changed. - * - * Revision 1.44 2002/08/14 12:18:03 rschmidt - * Replaced direct handling of MAC Hashing (XMAC and GMAC) - * with routine SkMacHashing(). - * Replaced wrong 3rd para 'i' with 'PortNumber' in SkMacPromiscMode(). - * - * Revision 1.43 2002/08/13 09:37:43 rschmidt - * Corrected some SK_DBG_MSG outputs. - * Replaced wrong 2nd para pAC with IoC in SkMacPromiscMode(). - * Editorial changes. - * - * Revision 1.42 2002/08/12 11:24:36 rschmidt - * Remove setting of logical MAC address GM_SRC_ADDR_2 in SkAddrInit(). - * Replaced direct handling of MAC Promiscuous Mode (XMAC and GMAC) - * with routine SkMacPromiscMode(). - * Editorial changes. - * - * Revision 1.41 2002/06/10 13:52:18 tschilli - * Changes for handling YUKON. - * All changes are internally and not visible to the programmer - * using this module. - * - * Revision 1.40 2001/02/14 14:04:59 rassmann - * Editorial changes. - * - * Revision 1.39 2001/01/30 10:30:04 rassmann - * Editorial changes. - * - * Revision 1.38 2001/01/25 16:26:52 rassmann - * Ensured that logical address overrides are done on net's active port. - * - * Revision 1.37 2001/01/22 13:41:34 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.36 2000/08/07 11:10:39 rassmann - * Editorial changes. - * - * Revision 1.35 2000/05/04 09:38:41 rassmann - * Editorial changes. - * Corrected multicast address hashing. - * - * Revision 1.34 1999/11/22 13:23:44 cgoos - * Changed license header to GPL. - * - * Revision 1.33 1999/05/28 10:56:06 rassmann - * Editorial changes. - * - * Revision 1.32 1999/03/31 10:59:20 rassmann - * Returning Success instead of DupAddr if address shall be overridden - * with same value. - * - * Revision 1.31 1999/01/14 16:18:17 rassmann - * Corrected multicast initialization. - * - * Revision 1.30 1999/01/04 10:30:35 rassmann - * SkAddrOverride only possible after SK_INIT_IO phase. - * - * Revision 1.29 1998/12/29 13:13:10 rassmann - * An address override is now preserved in the SK_INIT_IO phase. - * All functions return an int now. - * Extended parameter checking. - * - * Revision 1.28 1998/12/01 11:45:53 rassmann - * Code cleanup. - * - * Revision 1.27 1998/12/01 09:22:49 rassmann - * SkAddrMcAdd and SkAddrMcUpdate returned SK_MC_FILTERING_INEXACT - * too often. - * - * Revision 1.26 1998/11/24 12:39:44 rassmann - * Reserved multicast entry for BPDU address. - * 13 multicast entries left for protocol. - * - * Revision 1.25 1998/11/17 16:54:23 rassmann - * Using exact match for up to 14 multicast addresses. - * Still receiving all multicasts if more addresses are added. - * - * Revision 1.24 1998/11/13 17:24:31 rassmann - * Changed return value of SkAddrOverride to int. - * - * Revision 1.23 1998/11/13 16:56:18 rassmann - * Added macro SK_ADDR_COMPARE. - * Changed return type of SkAddrOverride to SK_BOOL. - * - * Revision 1.22 1998/11/04 17:06:17 rassmann - * Corrected McUpdate and PromiscuousChange functions. - * - * Revision 1.21 1998/10/29 14:34:04 rassmann - * Clearing SK_ADDR struct at startup. - * - * Revision 1.20 1998/10/28 18:16:34 rassmann - * Avoiding I/Os before SK_INIT_RUN level. - * Aligning InexactFilter. - * - * Revision 1.19 1998/10/28 11:29:28 rassmann - * Programming physical address in SkAddrMcUpdate. - * Corrected programming of exact match entries. - * - * Revision 1.18 1998/10/28 10:34:48 rassmann - * Corrected reading of physical addresses. - * - * Revision 1.17 1998/10/28 10:26:13 rassmann - * Getting ports' current MAC addresses from EPROM now. - * Added debug output. - * - * Revision 1.16 1998/10/27 16:20:12 rassmann - * Reading MAC address byte by byte. - * - * Revision 1.15 1998/10/22 11:39:09 rassmann - * Corrected signed/unsigned mismatches. - * - * Revision 1.14 1998/10/19 17:12:35 rassmann - * Syntax corrections. - * - * Revision 1.13 1998/10/19 17:02:19 rassmann - * Now reading permanent MAC addresses from CRF. - * - * Revision 1.12 1998/10/15 15:15:48 rassmann - * Changed Flags Parameters from SK_U8 to int. - * Checked with lint. - * - * Revision 1.11 1998/09/24 19:15:12 rassmann - * Code cleanup. - * - * Revision 1.10 1998/09/18 20:18:54 rassmann - * Added HW access. - * Implemented swapping. - * - * Revision 1.9 1998/09/16 11:32:00 rassmann - * Including skdrv1st.h again. :( - * - * Revision 1.8 1998/09/16 11:09:34 rassmann - * Syntax corrections. - * - * Revision 1.7 1998/09/14 17:06:34 rassmann - * Minor changes. - * - * Revision 1.6 1998/09/07 08:45:41 rassmann - * Syntax corrections. - * - * Revision 1.5 1998/09/04 19:40:19 rassmann - * Interface enhancements. - * - * Revision 1.4 1998/09/04 12:14:12 rassmann - * Interface cleanup. - * - * Revision 1.3 1998/09/02 16:56:40 rassmann - * Updated interface. - * - * Revision 1.2 1998/08/27 14:26:09 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:30:22 rassmann - * First public version. + * /LICENSE * ******************************************************************************/ @@ -219,18 +45,17 @@ ******************************************************************************/ #include - + #ifdef CONFIG_SK98 -#ifndef lint +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "@(#) $Id: skaddr.c,v 1.48 2003/02/12 17:09:37 tschilli Exp $ (C) SysKonnect."; -#endif /* !defined(lint) */ + "@(#) $Id: skaddr.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif /* DEBUG ||!LINT || !SK_SLIM */ #define __SKADDR_C #ifdef __cplusplus -#error C++ is not yet supported. extern "C" { #endif /* cplusplus */ @@ -239,11 +64,10 @@ extern "C" { /* defines ********************************************************************/ - #define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */ #define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */ #define HASH_BITS 6 /* #bits in hash */ -#define SK_MC_BIT 0x01 +#define SK_MC_BIT 0x01 /* Error numbers and messages. */ @@ -260,12 +84,12 @@ extern "C" { /* 64-bit hash values with all bits set. */ -SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; +SK_U16 OnesHash[4] = {0xffff, 0xffff, 0xffff, 0xffff}; /* local variables ************************************************************/ #ifdef DEBUG -static int Next0[SK_MAX_MACS] = {0, 0}; +static int Next0[SK_MAX_MACS] = {0}; #endif /* DEBUG */ /* functions ******************************************************************/ @@ -317,7 +141,7 @@ int Level) /* initialization level */ switch (Level) { case SK_INIT_DATA: - SK_MEMSET((char *) &pAC->Addr, 0, sizeof(SK_ADDR)); + SK_MEMSET((char *)&pAC->Addr, (SK_U8)0, (SK_U16)sizeof(SK_ADDR)); for (i = 0; i < SK_MAX_MACS; i++) { pAPort = &pAC->Addr.Port[i]; @@ -340,9 +164,58 @@ int Level) /* initialization level */ break; case SK_INIT_IO: +#ifdef CONFIG_MARVELL + + /* marvell update the mac address */ + /* we will do this change only if we are prpmc board + and that is only when pci arbiter is disabled */ + + { + extern int mvBoardNameGet(char *pNameBuff); + + static char boardName[30]; + mvBoardNameGet(boardName); + + if ((strcmp(boardName,"DB-88F5181-DDR1-PRPMC") == 0) || + (strcmp(boardName,"DB-88F5181-DDR1-MNG") == 0) || + (strcmp(boardName,"DB-88F5X81-DDR1-MNG") == 0) || + (strcmp(boardName,"DB-88F6183L-BP") == 0) || + (strcmp(boardName,"RD-MV78X00-H3C") == 0) || + (strcmp(boardName,"DB-88F1281-DDR2") == 0)) + { + extern unsigned char yuk_enetaddr[6]; + + int i; + + /* enable write*/ + SK_OUT8(pAC->IoBase, B2_TST_CTRL1, 0x2); + + for (i=0 ; i< 6 ; i++) + { + + SK_OUT8(pAC->IoBase, B2_MAC_1 + i, (SK_U8)yuk_enetaddr[i]); + SK_OUT8(pAC->IoBase, B2_MAC_2 + i, (SK_U8)yuk_enetaddr[i]); + SK_OUT8(pAC->IoBase, B2_MAC_3 + i, (SK_U8)yuk_enetaddr[i]); + + pAC->Addr.Net[0].CurrentMacAddress.a[i] = yuk_enetaddr[i]; + pAC->Addr.Net[0].PermanentMacAddress.a[i] = yuk_enetaddr[i]; + + } + + /* disable write*/ + SK_OUT8(pAC->IoBase, B2_TST_CTRL1, 0x1); + + + } + } + +#endif + +#ifndef SK_NO_RLMT for (i = 0; i < SK_MAX_NETS; i++) { pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort; } +#endif /* !SK_NO_RLMT */ #ifdef xDEBUG for (i = 0; i < SK_MAX_MACS; i++) { if (pAC->Addr.Port[i].NextExactMatchRlmt < @@ -369,11 +242,11 @@ int Level) /* initialization level */ pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] = pAC->Addr.Net[0].CurrentMacAddress; #if SK_MAX_NETS > 1 - /* Set logical MAC address for net 2 to (log | 3). */ + /* Set logical MAC address for net 2 to. */ if (!pAC->Addr.Net[1].CurrentMacAddressSet) { pAC->Addr.Net[1].PermanentMacAddress = pAC->Addr.Net[0].PermanentMacAddress; - pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3; + pAC->Addr.Net[1].PermanentMacAddress.a[5] += 1; /* Set the current logical MAC address to the permanent one. */ pAC->Addr.Net[1].CurrentMacAddress = pAC->Addr.Net[1].PermanentMacAddress; @@ -391,7 +264,7 @@ int Level) /* initialization level */ pAC->Addr.Net[i].PermanentMacAddress.a[2], pAC->Addr.Net[i].PermanentMacAddress.a[3], pAC->Addr.Net[i].PermanentMacAddress.a[4], - pAC->Addr.Net[i].PermanentMacAddress.a[5])) + pAC->Addr.Net[i].PermanentMacAddress.a[5])); SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", @@ -401,7 +274,7 @@ int Level) /* initialization level */ pAC->Addr.Net[i].CurrentMacAddress.a[2], pAC->Addr.Net[i].CurrentMacAddress.a[3], pAC->Addr.Net[i].CurrentMacAddress.a[4], - pAC->Addr.Net[i].CurrentMacAddress.a[5])) + pAC->Addr.Net[i].CurrentMacAddress.a[5])); } #endif /* DEBUG */ @@ -426,13 +299,16 @@ int Level) /* initialization level */ /* Set port's current physical MAC address. */ OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { XM_OUTADDR(IoC, i, XM_SA, OutAddr); } - else { +#endif /* GENESIS */ +#ifdef YUKON + if (!pAC->GIni.GIGenesis) { GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr); } +#endif /* YUKON */ #ifdef DEBUG SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", @@ -441,7 +317,7 @@ int Level) /* initialization level */ pAPort->PermanentMacAddress.a[2], pAPort->PermanentMacAddress.a[3], pAPort->PermanentMacAddress.a[4], - pAPort->PermanentMacAddress.a[5])) + pAPort->PermanentMacAddress.a[5])); SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", @@ -450,13 +326,62 @@ int Level) /* initialization level */ pAPort->CurrentMacAddress.a[2], pAPort->CurrentMacAddress.a[3], pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ + pAPort->CurrentMacAddress.a[5])); +#endif /* DEBUG */ } /* pAC->Addr.InitDone = SK_INIT_IO; */ break; case SK_INIT_RUN: + + #ifdef CONFIG_MARVELL + + /* marvell update the mac address */ + /* we will do this change only if we are prpmc board + and that is only when pci arbiter is disabled */ + + { + extern int mvBoardNameGet(char *pNameBuff); + + static char boardName[30]; + mvBoardNameGet(boardName); + + if ((strcmp(boardName,"DB-88F5181-DDR1-PRPMC") == 0) || + (strcmp(boardName,"DB-88F5181-DDR1-MNG") == 0) || + (strcmp(boardName,"DB-88F5X81-DDR1-MNG") == 0) || + (strcmp(boardName,"DB-88F6183L-BP") == 0) || + (strcmp(boardName,"RD-MV78X00-H3C") == 0) || + (strcmp(boardName,"DB-88F1281-DDR2") == 0)) + { + extern unsigned char yuk_enetaddr[6]; + + int i; + + /* enable write*/ + SK_OUT8(pAC->IoBase, B2_TST_CTRL1, 0x2); + + for (i=0 ; i< 6 ; i++) + { + + SK_OUT8(pAC->IoBase, B2_MAC_1 + i, (SK_U8)yuk_enetaddr[i]); + SK_OUT8(pAC->IoBase, B2_MAC_2 + i, (SK_U8)yuk_enetaddr[i]); + SK_OUT8(pAC->IoBase, B2_MAC_3 + i, (SK_U8)yuk_enetaddr[i]); + + pAC->Addr.Net[0].CurrentMacAddress.a[i] = yuk_enetaddr[i]; + pAC->Addr.Net[0].PermanentMacAddress.a[i] = yuk_enetaddr[i]; + + } + + /* disable write*/ + SK_OUT8(pAC->IoBase, B2_TST_CTRL1, 0x1); + + + } + } + + + #endif + #ifdef xDEBUG for (i = 0; i < SK_MAX_MACS; i++) { if (pAC->Addr.Port[i].NextExactMatchRlmt < @@ -477,6 +402,7 @@ int Level) /* initialization level */ } /* SkAddrInit */ +#ifndef SK_SLIM /****************************************************************************** * @@ -512,18 +438,25 @@ int Flags) /* permanent/non-perm, sw-only */ return (SK_ADDR_ILLEGAL_PORT); } - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + if (pAC->GIni.GIGenesis) { +#ifdef GENESIS ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags); +#endif } else { +#ifdef YUKON ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags); +#endif } return (ReturnCode); } /* SkAddrMcClear */ +#endif /* !SK_SLIM */ +#ifndef SK_SLIM +#ifdef GENESIS /****************************************************************************** * * SkAddrXmacMcClear - clear the multicast table @@ -575,8 +508,11 @@ int Flags) /* permanent/non-perm, sw-only */ return (SK_ADDR_SUCCESS); } /* SkAddrXmacMcClear */ +#endif /* GENESIS */ +#endif /* !SK_SLIM */ - +#ifndef SK_SLIM +#ifdef YUKON /****************************************************************************** * * SkAddrGmacMcClear - clear the multicast table @@ -615,7 +551,7 @@ int Flags) /* permanent/non-perm, sw-only */ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])); #endif /* DEBUG */ /* Clear InexactFilter */ @@ -632,7 +568,6 @@ int Flags) /* permanent/non-perm, sw-only */ /* Clear InexactRlmtFilter. */ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0; - } } else { /* not permanent => DRV */ @@ -657,7 +592,7 @@ int Flags) /* permanent/non-perm, sw-only */ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) + pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])); #endif /* DEBUG */ if (!(Flags & SK_MC_SW_ONLY)) { @@ -667,9 +602,10 @@ int Flags) /* permanent/non-perm, sw-only */ return (SK_ADDR_SUCCESS); } /* SkAddrGmacMcClear */ +#endif /* YUKON */ #ifndef SK_ADDR_CHEAT - +#ifdef GENESIS /****************************************************************************** * * SkXmacMcHash - hash multicast address @@ -706,8 +642,9 @@ unsigned char *pMc) /* Multicast address */ return (Crc & ((1 << HASH_BITS) - 1)); } /* SkXmacMcHash */ +#endif /* GENESIS */ - +#ifdef YUKON /****************************************************************************** * * SkGmacMcHash - hash multicast address @@ -765,8 +702,8 @@ unsigned char *pMc) /* Multicast address */ return (Crc & ((1 << HASH_BITS) - 1)); } /* SkGmacMcHash */ - -#endif /* not SK_ADDR_CHEAT */ +#endif /* YUKON */ +#endif /* !SK_ADDR_CHEAT */ /****************************************************************************** * @@ -805,18 +742,22 @@ int Flags) /* permanent/non-permanent */ return (SK_ADDR_ILLEGAL_PORT); } - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + if (pAC->GIni.GIGenesis) { +#ifdef GENESIS ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); +#endif } else { +#ifdef YUKON ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); +#endif } return (ReturnCode); } /* SkAddrMcAdd */ - +#ifdef GENESIS /****************************************************************************** * * SkAddrXmacMcAdd - add a multicast address to a port @@ -896,7 +837,7 @@ int Flags) /* permanent/non-permanent */ } else { if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses. */ + /* Hashing only possible with multicast addresses */ return (SK_MC_ILLEGAL_ADDRESS); } #ifndef SK_ADDR_CHEAT @@ -926,8 +867,9 @@ int Flags) /* permanent/non-permanent */ } } /* SkAddrXmacMcAdd */ +#endif /* GENESIS */ - +#ifdef YUKON /****************************************************************************** * * SkAddrGmacMcAdd - add a multicast address to a port @@ -959,7 +901,7 @@ int Flags) /* permanent/non-permanent */ #endif /* !defined(SK_ADDR_CHEAT) */ if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses. */ + /* Hashing only possible with multicast addresses */ return (SK_MC_ILLEGAL_ADDRESS); } @@ -979,6 +921,7 @@ int Flags) /* permanent/non-permanent */ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; } + #ifdef DEBUG SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", @@ -989,7 +932,7 @@ int Flags) /* permanent/non-permanent */ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4], pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5], pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7])) + pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7])); #endif /* DEBUG */ } else { /* not permanent => DRV */ @@ -1003,6 +946,7 @@ int Flags) /* permanent/non-permanent */ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; } + #ifdef DEBUG SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", @@ -1013,7 +957,7 @@ int Flags) /* permanent/non-permanent */ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4], pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5], pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7])) + pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7])); #endif /* DEBUG */ } @@ -1028,7 +972,8 @@ int Flags) /* permanent/non-permanent */ return (SK_MC_FILTERING_INEXACT); } /* SkAddrGmacMcAdd */ - +#endif /* YUKON */ +#endif /* !SK_SLIM */ /****************************************************************************** * @@ -1059,24 +1004,31 @@ SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber) /* Port Number */ { - int ReturnCode; + int ReturnCode = SK_ADDR_ILLEGAL_PORT; +#if (!defined(SK_SLIM) || defined(DEBUG)) if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { return (SK_ADDR_ILLEGAL_PORT); } +#endif /* !SK_SLIM || DEBUG */ - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber); } - else { +#endif /* GENESIS */ +#ifdef YUKON + if (!pAC->GIni.GIGenesis) { ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber); } - +#endif /* YUKON */ return (ReturnCode); } /* SkAddrMcUpdate */ +#ifdef GENESIS + /****************************************************************************** * * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address @@ -1109,14 +1061,14 @@ SK_U32 PortNumber) /* Port Number */ SK_ADDR_PORT *pAPort; SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber)) + ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber)); pAPort = &pAC->Addr.Port[PortNumber]; #ifdef DEBUG SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ + ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])); +#endif /* DEBUG */ /* Start with 0 to also program the logical MAC address. */ for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { @@ -1154,7 +1106,7 @@ SK_U32 PortNumber) /* Port Number */ XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } else if (Inexact != 0) { @@ -1162,11 +1114,11 @@ SK_U32 PortNumber) /* Port Number */ XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]); /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } else { /* Disable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_FALSE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE); } if (pAPort->PromMode != SK_PROM_MODE_NONE) { @@ -1204,9 +1156,9 @@ SK_U32 PortNumber) /* Port Number */ pAPort->Exact[i].a[2], pAPort->Exact[i].a[3], pAPort->Exact[i].a[4], - pAPort->Exact[i].a[5])) + pAPort->Exact[i].a[5])); } -#endif /* DEBUG */ +#endif /* DEBUG */ /* Determine return value. */ if (Inexact == 0 && pAPort->PromMode == 0) { @@ -1218,6 +1170,9 @@ SK_U32 PortNumber) /* Port Number */ } /* SkAddrXmacMcUpdate */ +#endif /* GENESIS */ + +#ifdef YUKON /****************************************************************************** * @@ -1245,21 +1200,24 @@ SK_AC *pAC, /* adapter context */ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber) /* Port Number */ { +#ifndef SK_SLIM SK_U32 i; SK_U8 Inexact; +#endif /* not SK_SLIM */ SK_U16 *OutAddr; SK_ADDR_PORT *pAPort; SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber)) + ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber)); pAPort = &pAC->Addr.Port[PortNumber]; #ifdef DEBUG SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ + ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])); +#endif /* DEBUG */ +#ifndef SK_SLIM for (Inexact = 0, i = 0; i < 8; i++) { Inexact |= pAPort->InexactFilter.Bytes[i]; } @@ -1274,16 +1232,27 @@ SK_U32 PortNumber) /* Port Number */ GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } else { /* Enable Hashing. */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } if (pAPort->PromMode != SK_PROM_MODE_NONE) { (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); } +#else /* SK_SLIM */ + + /* Set all bits in 64-bit hash register. */ + GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); + + /* Enable Hashing */ + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); + + (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); + +#endif /* SK_SLIM */ /* Set port's current physical MAC address. */ OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; @@ -1301,7 +1270,7 @@ SK_U32 PortNumber) /* Port Number */ pAPort->Exact[0].a[2], pAPort->Exact[0].a[3], pAPort->Exact[0].a[4], - pAPort->Exact[0].a[5])) + pAPort->Exact[0].a[5])); SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", @@ -1310,9 +1279,10 @@ SK_U32 PortNumber) /* Port Number */ pAPort->CurrentMacAddress.a[2], pAPort->CurrentMacAddress.a[3], pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ + pAPort->CurrentMacAddress.a[5])); +#endif /* DEBUG */ +#ifndef SK_SLIM /* Determine return value. */ if (Inexact == 0 && pAPort->PromMode == 0) { return (SK_MC_FILTERING_EXACT); @@ -1320,9 +1290,15 @@ SK_U32 PortNumber) /* Port Number */ else { return (SK_MC_FILTERING_INEXACT); } +#else /* SK_SLIM */ + return (SK_MC_FILTERING_INEXACT); +#endif /* SK_SLIM */ } /* SkAddrGmacMcUpdate */ +#endif /* YUKON */ + +#ifndef SK_NO_MAO /****************************************************************************** * @@ -1342,23 +1318,29 @@ SK_U32 PortNumber) /* Port Number */ * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before. */ int SkAddrOverride( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pNewAddr, /* new MAC address */ -int Flags) /* logical/physical MAC address */ +SK_AC *pAC, /* adapter context */ +SK_IOC IoC, /* I/O context */ +SK_U32 PortNumber, /* Port Number */ +SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */ +int Flags) /* logical/physical MAC address */ { +#ifndef SK_NO_RLMT SK_EVPARA Para; +#endif /* !SK_NO_RLMT */ SK_U32 NetNumber; SK_U32 i; - SK_U16 *OutAddr; + SK_U16 SK_FAR *OutAddr; +#ifndef SK_NO_RLMT NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber; - +#else + NetNumber = 0; +#endif /* SK_NO_RLMT */ +#if (!defined(SK_SLIM) || defined(DEBUG)) if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { return (SK_ADDR_ILLEGAL_PORT); } - +#endif /* !SK_SLIM || DEBUG */ if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) { return (SK_ADDR_MULTICAST_ADDRESS); } @@ -1374,11 +1356,11 @@ int Flags) /* logical/physical MAC address */ return (SK_ADDR_TOO_EARLY); } } - +#ifndef SK_NO_RLMT /* Set PortNumber to number of net's active port. */ PortNumber = pAC->Rlmt.Net[NetNumber]. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; - +#endif /* !SK_NO_RLMT */ pAC->Addr.Port[PortNumber].Exact[0] = pAC->Addr.Net[NetNumber].CurrentMacAddress; @@ -1393,11 +1375,11 @@ int Flags) /* logical/physical MAC address */ return (SK_ADDR_TOO_EARLY); } } - +#ifndef SK_NO_RLMT /* Set PortNumber to number of net's active port. */ PortNumber = pAC->Rlmt.Net[NetNumber]. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; - +#endif /* !SK_NO_RLMT */ for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) { pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0; } @@ -1406,45 +1388,70 @@ int Flags) /* logical/physical MAC address */ (void) SkAddrMcUpdate(pAC, IoC, PortNumber); } else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */ - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { if (!pAC->Addr.Port[i].CurrentMacAddressSet) { return (SK_ADDR_TOO_EARLY); } + } + /* + * In dual net mode it should be possible to set all MAC + * addresses independently. Therefore the equality checks + * against the locical address of the same port and the + * physical address of the other port are suppressed here. + */ +#ifndef SK_NO_RLMT + if (pAC->Rlmt.NumNets == 1) { +#endif /* SK_NO_RLMT */ if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - if (i == PortNumber) { - return (SK_ADDR_SUCCESS); - } - else { - return (SK_ADDR_DUPLICATE_ADDRESS); + pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { + return (SK_ADDR_DUPLICATE_ADDRESS); + } + + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + if (SK_ADDR_EQUAL(pNewAddr->a, + pAC->Addr.Port[i].CurrentMacAddress.a)) { + if (i == PortNumber) { + return (SK_ADDR_SUCCESS); + } + else { + return (SK_ADDR_DUPLICATE_ADDRESS); + } } } +#ifndef SK_NO_RLMT } + else { + if (SK_ADDR_EQUAL(pNewAddr->a, + pAC->Addr.Port[PortNumber].CurrentMacAddress.a)) { + return (SK_ADDR_SUCCESS); + } + } +#endif /* SK_NO_RLMT */ pAC->Addr.Port[PortNumber].PreviousMacAddress = pAC->Addr.Port[PortNumber].CurrentMacAddress; pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; /* Change port's physical MAC address. */ - OutAddr = (SK_U16 *) pNewAddr; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + OutAddr = (SK_U16 SK_FAR *) pNewAddr; +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); } - else { +#endif /* GENESIS */ +#ifdef YUKON + if (!pAC->GIni.GIGenesis) { GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); } +#endif /* YUKON */ +#ifndef SK_NO_RLMT /* Report address change to RLMT. */ Para.Para32[0] = PortNumber; Para.Para32[0] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); +#endif /* !SK_NO_RLMT */ } else { /* Logical MAC address. */ if (SK_ADDR_EQUAL(pNewAddr->a, @@ -1456,13 +1463,27 @@ int Flags) /* logical/physical MAC address */ if (!pAC->Addr.Port[i].CurrentMacAddressSet) { return (SK_ADDR_TOO_EARLY); } - - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } } + /* + * In dual net mode on Yukon-2 adapters the physical address + * of port 0 and the logical address of port 1 are equal - in + * this case the equality check of the physical address leads + * to an error and is suppressed here. + */ +#ifndef SK_NO_RLMT + if (pAC->Rlmt.NumNets == 1) { +#endif /* SK_NO_RLMT */ + for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { + if (SK_ADDR_EQUAL(pNewAddr->a, + pAC->Addr.Port[i].CurrentMacAddress.a)) { + return (SK_ADDR_DUPLICATE_ADDRESS); + } + } +#ifndef SK_NO_RLMT + } +#endif /* SK_NO_RLMT */ + /* * In case that the physical and the logical MAC addresses are equal * we must also change the physical MAC address here. @@ -1476,16 +1497,19 @@ int Flags) /* logical/physical MAC address */ pAC->Addr.Port[PortNumber].CurrentMacAddress; pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; +#ifndef SK_NO_RLMT /* Report address change to RLMT. */ Para.Para32[0] = PortNumber; Para.Para32[0] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); +#endif /* !SK_NO_RLMT */ } +#ifndef SK_NO_RLMT /* Set PortNumber to number of net's active port. */ PortNumber = pAC->Rlmt.Net[NetNumber]. Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; - +#endif /* !SK_NO_RLMT */ pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr; pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr; #ifdef DEBUG @@ -1496,7 +1520,7 @@ int Flags) /* logical/physical MAC address */ pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2], pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3], pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5])) + pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5])); SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n", @@ -1505,17 +1529,18 @@ int Flags) /* logical/physical MAC address */ pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2], pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3], pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5])) -#endif /* DEBUG */ + pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5])); +#endif /* DEBUG */ - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); + /* Write address to first exact match entry of active port. */ + (void)SkAddrMcUpdate(pAC, IoC, PortNumber); } return (SK_ADDR_SUCCESS); } /* SkAddrOverride */ +#endif /* SK_NO_MAO */ /****************************************************************************** * @@ -1545,23 +1570,32 @@ SK_IOC IoC, /* I/O context */ SK_U32 PortNumber, /* port whose promiscuous mode changes */ int NewPromMode) /* new promiscuous mode */ { - int ReturnCode; + int ReturnCode = SK_ADDR_ILLEGAL_PORT; +#if (!defined(SK_SLIM) || defined(DEBUG)) if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { return (SK_ADDR_ILLEGAL_PORT); } +#endif /* !SK_SLIM || DEBUG */ - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ReturnCode = SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + ReturnCode = + SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); } - else { - ReturnCode = SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); +#endif /* GENESIS */ +#ifdef YUKON + if (!pAC->GIni.GIGenesis) { + ReturnCode = + SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); } +#endif /* YUKON */ return (ReturnCode); } /* SkAddrPromiscuousChange */ +#ifdef GENESIS /****************************************************************************** * @@ -1606,6 +1640,7 @@ int NewPromMode) /* new promiscuous mode */ for (Inexact = 0xFF, i = 0; i < 8; i++) { Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; } + if (Inexact == 0xFF) { CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); } @@ -1640,7 +1675,7 @@ int NewPromMode) /* new promiscuous mode */ XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } else if ((CurPromMode & SK_PROM_MODE_ALL_MC) && !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */ @@ -1649,7 +1684,7 @@ int NewPromMode) /* new promiscuous mode */ } if (Inexact == 0) { /* Disable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_FALSE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE); } else { /* Set 64-bit hash register to InexactFilter. */ @@ -1657,25 +1692,28 @@ int NewPromMode) /* new promiscuous mode */ &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } } if ((NewPromMode & SK_PROM_MODE_LLC) && !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ /* Set the MAC in Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE); + SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE); } else if ((CurPromMode & SK_PROM_MODE_LLC) && !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */ /* Clear Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE); + SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE); } return (SK_ADDR_SUCCESS); } /* SkAddrXmacPromiscuousChange */ +#endif /* GENESIS */ + +#ifdef YUKON /****************************************************************************** * @@ -1717,6 +1755,9 @@ int NewPromMode) /* new promiscuous mode */ CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); } + /* dummy read after GM_IN16() */ + SK_IN16(IoC, B0_RAP, &ReceiveControl); + pAC->Addr.Port[PortNumber].PromMode = NewPromMode; if (NewPromMode == CurPromMode) { @@ -1730,7 +1771,7 @@ int NewPromMode) /* new promiscuous mode */ GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); /* Enable Hashing */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } if ((CurPromMode & SK_PROM_MODE_ALL_MC) && @@ -1741,26 +1782,29 @@ int NewPromMode) /* new promiscuous mode */ &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); /* Enable Hashing. */ - SkMacHashing(pAC, IoC, PortNumber, SK_TRUE); + SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); } if ((NewPromMode & SK_PROM_MODE_LLC) && !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ /* Set the MAC to Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_TRUE); + SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE); } else if ((CurPromMode & SK_PROM_MODE_LLC) && !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */ /* Clear Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, PortNumber, SK_FALSE); + SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE); } return (SK_ADDR_SUCCESS); } /* SkAddrGmacPromiscuousChange */ +#endif /* YUKON */ + +#ifndef SK_SLIM /****************************************************************************** * @@ -1832,7 +1876,7 @@ SK_U32 ToPortNumber) /* Port2 Index */ pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode; pAC->Addr.Port[ToPortNumber].PromMode = i; - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + if (pAC->GIni.GIGenesis) { DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt; pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt = pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt; @@ -1872,8 +1916,10 @@ SK_U32 ToPortNumber) /* Port2 Index */ } /* SkAddrSwap */ +#endif /* !SK_SLIM */ + #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* CONFIG_SK98 */ +#endif diff --git a/drivers/sk98lin/skcsum.c b/drivers/sk98lin/skcsum.c index a5dc572..e00c07c 100644 --- a/drivers/sk98lin/skcsum.c +++ b/drivers/sk98lin/skcsum.c @@ -2,15 +2,16 @@ * * Name: skcsum.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.10 $ - * Date: $Date: 2002/04/11 10:02:04 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Store/verify Internet checksum in send/receive packets. * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2001 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2003 SysKonnect GmbH. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,68 +19,19 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skcsum.c,v $ - * Revision 1.10 2002/04/11 10:02:04 rwahl - * Fix in SkCsGetSendInfo(): - * - function did not return ProtocolFlags in every case. - * - pseudo header csum calculated wrong for big endian. - * - * Revision 1.9 2001/06/13 07:42:08 gklug - * fix: NetNumber was wrong in CLEAR_STAT event - * add: check for good NetNumber in Clear STAT - * - * Revision 1.8 2001/02/06 11:15:36 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.7 2000/06/29 13:17:05 rassmann - * Corrected reception of a packet with UDP checksum == 0 (which means there - * is no UDP checksum). - * - * Revision 1.6 2000/02/21 12:35:10 cgoos - * Fixed license header comment. - * - * Revision 1.5 2000/02/21 11:05:19 cgoos - * Merged changes back to common source. - * Fixed rx path for BIG ENDIAN architecture. - * - * Revision 1.1 1999/07/26 15:28:12 mkarl - * added return SKCS_STATUS_IP_CSUM_ERROR_UDP and - * SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester - * changed from common source to windows specific source - * therefore restarting with v1.0 - * - * Revision 1.3 1999/05/10 08:39:33 mkarl - * prevent overflows in SKCS_HTON16 - * fixed a bug in pseudo header checksum calculation - * added some comments - * - * Revision 1.2 1998/10/22 11:53:28 swolf - * Now using SK_DBG_MSG. - * - * Revision 1.1 1998/09/01 15:35:41 swolf - * initial revision - * - * 13-May-1998 sw Created. - * - ******************************************************************************/ - #include - + #ifdef CONFIG_SK98 + #ifdef SK_USE_CSUM /* Check if CSUM is to be used. */ #ifndef lint -static const char SysKonnectFileId[] = "@(#)" - "$Id: skcsum.c,v 1.10 2002/04/11 10:02:04 rwahl Exp $" - " (C) SysKonnect."; +static const char SysKonnectFileId[] = + "@(#) $Id: skcsum.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) SysKonnect."; #endif /* !lint */ /****************************************************************************** @@ -111,8 +63,8 @@ static const char SysKonnectFileId[] = "@(#)" * * "h/skdrv1st.h" * "h/skcsum.h" - * "h/sktypes.h" - * "h/skqueue.h" + * "h/sktypes.h" + * "h/skqueue.h" * "h/skdrv2nd.h" * ******************************************************************************/ @@ -177,7 +129,7 @@ static const char SysKonnectFileId[] = "@(#)" * little/big endian conversion on little endian machines only. */ #ifdef SK_LITTLE_ENDIAN -#define SKCS_HTON16(Val16) (((unsigned) (Val16) >> 8) | (((Val16) & 0xFF) << 8)) +#define SKCS_HTON16(Val16) (((unsigned) (Val16) >> 8) | (((Val16) & 0xff) << 8)) #endif /* SK_LITTLE_ENDIAN */ #ifdef SK_BIG_ENDIAN #define SKCS_HTON16(Val16) (Val16) @@ -208,7 +160,7 @@ static const char SysKonnectFileId[] = "@(#)" * zero.) * * Note: - * There is a bug in the ASIC which may lead to wrong checksums. + * There is a bug in the GENESIS ASIC which may lead to wrong checksums. * * Arguments: * pAc - A pointer to the adapter context struct. @@ -261,7 +213,6 @@ static const char SysKonnectFileId[] = "@(#)" * has been specified in the 'ProtocolFlags', the 16-bit Internet Checksum * of the TCP or UDP pseudo header is returned here. */ -#if 0 void SkCsGetSendInfo( SK_AC *pAc, /* Adapter context struct. */ void *pIpHeader, /* IP header. */ @@ -427,7 +378,7 @@ int NetNumber) /* Net number */ SKCS_OFS_IP_DESTINATION_ADDRESS + 2) + (unsigned long) SKCS_HTON16(NextLevelProtocol) + (unsigned long) SKCS_HTON16(IpDataLength); - + /* Add-in any carries. */ SKCS_OC_ADD(PseudoHeaderChecksum, PseudoHeaderChecksum, 0); @@ -602,13 +553,13 @@ int NetNumber) /* Net number */ * us to check upper-layer checksums, because we cannot do any further * processing of the packet without a valid IP checksum. */ - + /* Get the next level protocol identifier. */ - + NextLevelProtocol = *(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL); - if (IpHeaderChecksum != 0xFFFF) { + if (IpHeaderChecksum != 0xffff) { pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++; /* the NDIS tester wants to know the upper level protocol too */ if (NextLevelProtocol == SKCS_PROTO_ID_TCP) { @@ -680,7 +631,7 @@ int NetNumber) /* Net number */ *(SK_U16*)SKCS_IDX(pIpHeader, IpHeaderLength + 6) == 0x0000) { NextLevelProtoStats->RxOkCts++; - + return (SKCS_STATUS_IP_CSUM_OK_NO_UDP); } @@ -726,7 +677,7 @@ int NetNumber) /* Net number */ /* Check if the TCP/UDP checksum is ok. */ - if ((unsigned) NextLevelProtocolChecksum == 0xFFFF) { + if ((unsigned) NextLevelProtocolChecksum == 0xffff) { /* TCP/UDP checksum ok. */ @@ -735,7 +686,7 @@ int NetNumber) /* Net number */ return (NextLevelProtocol == SKCS_PROTO_ID_TCP ? SKCS_STATUS_TCP_CSUM_OK : SKCS_STATUS_UDP_CSUM_OK); } - + /* TCP/UDP checksum error. */ NextLevelProtoStats->RxErrCts++; @@ -743,7 +694,6 @@ int NetNumber) /* Net number */ return (NextLevelProtocol == SKCS_PROTO_ID_TCP ? SKCS_STATUS_TCP_CSUM_ERROR : SKCS_STATUS_UDP_CSUM_ERROR); } /* SkCsGetReceiveInfo */ -#endif /****************************************************************************** @@ -794,7 +744,7 @@ int NetNumber) *pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE; } /* SkCsSetReceiveFlags */ -#ifndef SkCsCalculateChecksum +#ifndef SK_CS_CALCULATE_CHECKSUM /****************************************************************************** * @@ -859,7 +809,7 @@ unsigned Length) /* Length of data. */ return ((unsigned) Checksum); } /* SkCsCalculateChecksum */ -#endif /* SkCsCalculateChecksum */ +#endif /* SK_CS_CALCULATE_CHECKSUM */ /****************************************************************************** * @@ -909,12 +859,12 @@ SK_EVPARA Param) /* Event dependent parameter. */ NetNumber = (int)Param.Para32[0]; if (ProtoIndex < 0) { /* Clear for all protocols. */ if (NetNumber >= 0) { - memset(&pAc->Csum.ProtoStats[NetNumber][0], 0, + SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][0], 0, sizeof(pAc->Csum.ProtoStats[NetNumber])); } } else { /* Clear for individual protocol. */ - memset(&pAc->Csum.ProtoStats[NetNumber][ProtoIndex], 0, + SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][ProtoIndex], 0, sizeof(pAc->Csum.ProtoStats[NetNumber][ProtoIndex])); } break; @@ -926,4 +876,4 @@ SK_EVPARA Param) /* Event dependent parameter. */ #endif /* SK_USE_CSUM */ -#endif /* CONFIG_SK98 */ +#endif diff --git a/drivers/sk98lin/skdim.c b/drivers/sk98lin/skdim.c new file mode 100644 index 0000000..d48fc25 --- /dev/null +++ b/drivers/sk98lin/skdim.c @@ -0,0 +1,400 @@ +/****************************************************************************** + * + * Name: skdim.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: All functions regardig interrupt moderation + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. + * + * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet + * Server Adapters. + * + * Author: Ralph Roesler (rroesler@syskonnect.de) + * Mirko Lindner (mlindner@syskonnect.de) + * + * Address all question to: linux@syskonnect.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + *****************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +/****************************************************************************** + * + * Local Function Prototypes + * + *****************************************************************************/ + +static SK_U64 getIsrCalls(SK_AC *pAC); +static SK_BOOL isIntModEnabled(SK_AC *pAC); +static void setCurrIntCtr(SK_AC *pAC); +static void enableIntMod(SK_AC *pAC); +static void disableIntMod(SK_AC *pAC); + +#define M_DIMINFO pAC->DynIrqModInfo + +/****************************************************************************** + * + * Global Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * SkDimModerate - Moderates the IRQs depending on the current needs + * + * Description: + * Moderation of IRQs depends on the number of occurred IRQs with + * respect to the previous moderation cycle. + * + * Returns: N/A + * + */ +void SkDimModerate( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_U64 IsrCalls = getIsrCalls(pAC); + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> SkDimModerate\n")); + + if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { + if (isIntModEnabled(pAC)) { + if (IsrCalls < M_DIMINFO.MaxModIntsPerSecLowerLimit) { + disableIntMod(pAC); + } + } else { + if (IsrCalls > M_DIMINFO.MaxModIntsPerSecUpperLimit) { + enableIntMod(pAC); + } + } + } + setCurrIntCtr(pAC); + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== SkDimModerate\n")); +} + +/***************************************************************************** + * + * SkDimStartModerationTimer - Starts the moderation timer + * + * Description: + * Dynamic interrupt moderation is regularly checked using the + * so-called moderation timer. This timer is started with this function. + * + * Returns: N/A + */ +void SkDimStartModerationTimer( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_EVPARA EventParam; /* Event struct for timer event */ + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("==> SkDimStartModerationTimer\n")); + + if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { + SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); + EventParam.Para32[0] = SK_DRV_MODERATION_TIMER; + SkTimerStart(pAC, pAC->IoBase, + &pAC->DynIrqModInfo.ModTimer, + pAC->DynIrqModInfo.DynIrqModSampleInterval * 1000000, + SKGE_DRV, SK_DRV_TIMER, EventParam); + } + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("<== SkDimStartModerationTimer\n")); +} + +/***************************************************************************** + * + * SkDimEnableModerationIfNeeded - Enables or disables any moderationtype + * + * Description: + * This function effectively initializes the IRQ moderation of a network + * adapter. Depending on the configuration, this might be either static + * or dynamic. If no moderation is configured, this function will do + * nothing. + * + * Returns: N/A + */ +void SkDimEnableModerationIfNeeded( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("==> SkDimEnableModerationIfNeeded\n")); + + if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_NONE) { + if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) { + enableIntMod(pAC); + } else { /* must be C_INT_MOD_DYNAMIC */ + SkDimStartModerationTimer(pAC); + } + } + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("<== SkDimEnableModerationIfNeeded\n")); +} + +/***************************************************************************** + * + * SkDimDisableModeration - disables moderation if it is enabled + * + * Description: + * Disabling of the moderation requires that is enabled already. + * + * Returns: N/A + */ +void SkDimDisableModeration( +SK_AC *pAC, /* pointer to adapter control context */ +int CurrentModeration) /* type of current moderation */ +{ + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("==> SkDimDisableModeration\n")); + + if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_NONE) { + if (CurrentModeration == C_INT_MOD_STATIC) { + disableIntMod(pAC); + } else { /* must be C_INT_MOD_DYNAMIC */ + SkTimerStop(pAC, pAC->IoBase, &M_DIMINFO.ModTimer); + disableIntMod(pAC); + } + } + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("<== SkDimDisableModeration\n")); +} + +/****************************************************************************** + * + * Local Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * getIsrCalls - evaluate the number of IRQs handled in mod interval + * + * Description: + * Depending on the selected moderation mask, this function will return + * the number of interrupts handled in the previous moderation interval. + * This evaluated number is based on the current number of interrupts + * stored in PNMI-context and the previous stored interrupts. + * + * Returns: + * the number of IRQs handled + */ +static SK_U64 getIsrCalls( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_U64 RxPort0IntDiff = 0, RxPort1IntDiff = 0; + SK_U64 TxPort0IntDiff = 0, TxPort1IntDiff = 0; + SK_U64 StatusPort0IntDiff = 0, StatusPort1IntDiff = 0; + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>getIsrCalls\n")); + + if (!CHIP_ID_YUKON_2(pAC)) { + if ((M_DIMINFO.MaskIrqModeration == IRQ_MASK_TX_ONLY) || + (M_DIMINFO.MaskIrqModeration == IRQ_MASK_SP_TX)) { + if (pAC->GIni.GIMacsFound == 2) { + TxPort1IntDiff = + pAC->Pnmi.Port[1].TxIntrCts - + M_DIMINFO.PrevPort1TxIntrCts; + } + TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - + M_DIMINFO.PrevPort0TxIntrCts; + } else if ((M_DIMINFO.MaskIrqModeration == IRQ_MASK_RX_ONLY) || + (M_DIMINFO.MaskIrqModeration == IRQ_MASK_SP_RX)) { + if (pAC->GIni.GIMacsFound == 2) { + RxPort1IntDiff = + pAC->Pnmi.Port[1].RxIntrCts - + M_DIMINFO.PrevPort1RxIntrCts; + } + RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - + M_DIMINFO.PrevPort0RxIntrCts; + } else { + if (pAC->GIni.GIMacsFound == 2) { + RxPort1IntDiff = + pAC->Pnmi.Port[1].RxIntrCts - + M_DIMINFO.PrevPort1RxIntrCts; + TxPort1IntDiff = + pAC->Pnmi.Port[1].TxIntrCts - + M_DIMINFO.PrevPort1TxIntrCts; + } + RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - + M_DIMINFO.PrevPort0RxIntrCts; + TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - + M_DIMINFO.PrevPort0TxIntrCts; + } + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("==>getIsrCalls (!CHIP_ID_YUKON_2)\n")); + return (RxPort0IntDiff + RxPort1IntDiff + + TxPort0IntDiff + TxPort1IntDiff); + } + + /* + ** We have a Yukon2 compliant chipset if we come up to here + ** + if (pAC->GIni.GIMacsFound == 2) { + StatusPort1IntDiff = pAC->Pnmi.Port[1].StatusLeIntrCts - + M_DIMINFO.PrevPort1StatusIntrCts; + } + StatusPort0IntDiff = pAC->Pnmi.Port[0].StatusLeIntrCts - + M_DIMINFO.PrevPort0StatusIntrCts; + */ + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("==>getIsrCalls (CHIP_ID_YUKON_2)\n")); + return (StatusPort0IntDiff + StatusPort1IntDiff); +} + +/***************************************************************************** + * + * setCurrIntCtr - stores the current number of interrupts + * + * Description: + * Stores the current number of occurred interrupts in the adapter + * context. This is needed to evaluate the umber of interrupts within + * the moderation interval. + * + * Returns: N/A + * + */ +static void setCurrIntCtr( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>setCurrIntCtr\n")); + + if (!CHIP_ID_YUKON_2(pAC)) { + if (pAC->GIni.GIMacsFound == 2) { + M_DIMINFO.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts; + M_DIMINFO.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts; + } + M_DIMINFO.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts; + M_DIMINFO.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts; + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("<== setCurrIntCtr (!CHIP_ID_YUKON_2)\n")); + return; + } + + /* + ** We have a Yukon2 compliant chipset if we come up to here + ** + if (pAC->GIni.GIMacsFound == 2) { + M_DIMINFO.PrevPort1StatusIntrCts = pAC->Pnmi.Port[1].StatusLeIntrCts; + } + M_DIMINFO.PrevPort0StatusIntrCts = pAC->Pnmi.Port[0].StatusLeIntrCts; + */ + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("<== setCurrIntCtr (CHIP_ID_YUKON_2)\n")); +} + +/***************************************************************************** + * + * isIntModEnabled - returns the current state of interrupt moderation + * + * Description: + * This function retrieves the current value of the interrupt moderation + * command register. Its content determines whether any moderation is + * running or not. + * + * Returns: + * SK_TRUE : IRQ moderation is currently active + * SK_FALSE: No IRQ moderation is active + */ +static SK_BOOL isIntModEnabled( +SK_AC *pAC) /* pointer to adapter control context */ +{ + unsigned long CtrCmd; + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>isIntModEnabled\n")); + + SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd); + if ((CtrCmd & TIM_START) == TIM_START) { + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("<== isIntModEnabled (SK_TRUE)\n")); + return SK_TRUE; + } + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG, + ("<== isIntModEnabled (SK_FALSE)\n")); + return SK_FALSE; +} + +/***************************************************************************** + * + * enableIntMod - enables the interrupt moderation + * + * Description: + * Enabling the interrupt moderation is done by putting the desired + * moderation interval in the B2_IRQM_INI register, specifying the + * desired maks in the B2_IRQM_MSK register and finally starting the + * IRQ moderation timer using the B2_IRQM_CTRL register. + * + * Returns: N/A + * + */ +static void enableIntMod( +SK_AC *pAC) /* pointer to adapter control context */ +{ + unsigned long ModBase; + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> enableIntMod\n")); + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + ModBase = C_CLK_FREQ_GENESIS / M_DIMINFO.MaxModIntsPerSec; + } else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) { + ModBase = C_CLK_FREQ_YUKON_EC / M_DIMINFO.MaxModIntsPerSec; + } else { + ModBase = C_CLK_FREQ_YUKON / M_DIMINFO.MaxModIntsPerSec; + } + + SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); + SK_OUT32(pAC->IoBase, B2_IRQM_MSK, M_DIMINFO.MaskIrqModeration); + SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== enableIntMod\n")); +} + +/***************************************************************************** + * + * disableIntMod - disables the interrupt moderation + * + * Description: + * Disabling the interrupt moderation is done by stopping the + * IRQ moderation timer using the B2_IRQM_CTRL register. + * + * Returns: N/A + * + */ +static void disableIntMod( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> disableIntMod\n")); + + SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP); + + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== disableIntMod\n")); +} + +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ + +#endif diff --git a/drivers/sk98lin/skethtool.c b/drivers/sk98lin/skethtool.c new file mode 100644 index 0000000..c3761d3 --- /dev/null +++ b/drivers/sk98lin/skethtool.c @@ -0,0 +1,1364 @@ +/****************************************************************************** + * + * Name: skethtool.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: All functions regarding ethtool handling + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. + * + * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet + * Server Adapters. + * + * Author: Ralph Roesler (rroesler@syskonnect.de) + * Mirko Lindner (mlindner@syskonnect.de) + * + * Address all question to: linux@syskonnect.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + *****************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" +#include "h/skversion.h" +#if 0 /* uboot */ +#include +#include +#include +#endif + +/****************************************************************************** + * + * External Functions and Data + * + *****************************************************************************/ + +extern void SkDimDisableModeration(SK_AC *pAC, int CurrentModeration); +extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); + +/****************************************************************************** + * + * Defines + * + *****************************************************************************/ + +#ifndef ETHT_STATSTRING_LEN +#define ETHT_STATSTRING_LEN 32 +#endif + +#define SK98LIN_STAT(m) sizeof(((SK_AC *)0)->m),offsetof(SK_AC, m) + +#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ + SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \ + SUPPORTED_TP) + +#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ + ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \ + ADVERTISED_TP) + +#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \ + SUPPORTED_FIBRE | \ + SUPPORTED_Autoneg) + +#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \ + ADVERTISED_FIBRE | \ + ADVERTISED_Autoneg) + +/****************************************************************************** + * + * Local Function Prototypes + * + *****************************************************************************/ + +#ifdef ETHTOOL_GSET +static void getSettings(SK_AC *pAC, int port, struct ethtool_cmd *ecmd); +#endif +#ifdef ETHTOOL_SSET +static int setSettings(SK_AC *pAC, int port, struct ethtool_cmd *ecmd); +#endif +#ifdef ETHTOOL_GPAUSEPARAM +static void getPauseParams(SK_AC *pAC, int port, struct ethtool_pauseparam *epause); +#endif +#ifdef ETHTOOL_SPAUSEPARAM +static int setPauseParams(SK_AC *pAC, int port, struct ethtool_pauseparam *epause); +#endif +#ifdef ETHTOOL_GDRVINFO +static void getDriverInfo(SK_AC *pAC, int port, struct ethtool_drvinfo *edrvinfo); +#endif +#ifdef ETHTOOL_PHYS_ID +static int startLocateNIC(SK_AC *pAC, int port, struct ethtool_value *blinkSecs); +static void toggleLeds(unsigned long ptr); +#endif +#ifdef ETHTOOL_GCOALESCE +static void getModerationParams(SK_AC *pAC, int port, struct ethtool_coalesce *ecoalesc); +#endif +#ifdef ETHTOOL_SCOALESCE +static int setModerationParams(SK_AC *pAC, int port, struct ethtool_coalesce *ecoalesc); +#endif +#ifdef ETHTOOL_GWOL +static void getWOLsettings(SK_AC *pAC, int port, struct ethtool_wolinfo *ewol); +#endif +#ifdef ETHTOOL_SWOL +static int setWOLsettings(SK_AC *pAC, int port, struct ethtool_wolinfo *ewol); +#endif + +static int getPortNumber(struct net_device *netdev, struct ifreq *ifr); + +/****************************************************************************** + * + * Local Variables + * + *****************************************************************************/ + +struct sk98lin_stats { + char stat_string[ETHT_STATSTRING_LEN]; + int sizeof_stat; + int stat_offset; +}; + +static struct sk98lin_stats sk98lin_etht_stats_port0[] = { + { "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOkCts) }, + { "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOkCts) }, + { "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOctetsOkCts) }, + { "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOctetsOkCts) }, + { "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) }, + { "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) }, + { "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) }, + { "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) }, + { "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMulticastOkCts) }, + { "collisions" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) }, + { "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxRuntCts) }, + { "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFifoOverflowCts) }, + { "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFcsCts) }, + { "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFramingCts) }, + { "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxShortsCts) }, + { "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxTooLongCts) }, + { "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCextCts) }, + { "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxSymbolCts) }, + { "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxIRLengthCts) }, + { "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCarrierCts) }, + { "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxJabberCts) }, + { "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMissedCts) }, + { "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) }, + { "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) }, + { "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxFifoUnderrunCts) }, + { "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) } , + { "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) } +}; + +static struct sk98lin_stats sk98lin_etht_stats_port1[] = { + { "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOkCts) }, + { "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOkCts) }, + { "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOctetsOkCts) }, + { "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOctetsOkCts) }, + { "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) }, + { "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) }, + { "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) }, + { "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) }, + { "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMulticastOkCts) }, + { "collisions" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) }, + { "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxRuntCts) }, + { "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFifoOverflowCts) }, + { "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFcsCts) }, + { "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFramingCts) }, + { "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxShortsCts) }, + { "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxTooLongCts) }, + { "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCextCts) }, + { "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxSymbolCts) }, + { "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxIRLengthCts) }, + { "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCarrierCts) }, + { "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxJabberCts) }, + { "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMissedCts) }, + { "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) }, + { "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) }, + { "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxFifoUnderrunCts) }, + { "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) } , + { "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) } +}; + +#define SK98LIN_STATS_LEN sizeof(sk98lin_etht_stats_port0) / sizeof(struct sk98lin_stats) + +static int nbrBlinkQuarterSeconds; +static int currentPortIndex; +static SK_BOOL isLocateNICrunning = SK_FALSE; +static SK_BOOL isDualNetCard = SK_FALSE; +static SK_BOOL doSwitchLEDsOn = SK_FALSE; +static SK_BOOL boardWasDown[2] = { SK_FALSE, SK_FALSE }; +static struct timer_list locateNICtimer; + +/****************************************************************************** + * + * Global Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * SkEthIoctl - IOCTL entry point for all ethtool queries + * + * Description: + * Any IOCTL request that has to deal with the ethtool command tool is + * dispatched via this function. + * + * Returns: + * ==0: everything fine, no error + * !=0: the return value is the error code of the failure + */ +int SkEthIoctl( +struct net_device *netdev, /* the pointer to netdev structure */ +struct ifreq *ifr) /* what interface the request refers to? */ +{ + DEV_NET *pNet = (DEV_NET*) netdev->priv; + SK_AC *pAC = pNet->pAC; + void *pAddr = ifr->ifr_data; + int port = getPortNumber(netdev, ifr); + SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct; + SK_U32 Size = sizeof(SK_PNMI_STRUCT_DATA); + SK_U32 cmd; + struct sk98lin_stats *sk98lin_etht_stats = + (port == 0) ? sk98lin_etht_stats_port0 : sk98lin_etht_stats_port1; + + if (get_user(cmd, (uint32_t *) pAddr)) { + return -EFAULT; + } + + switch(cmd) { +#ifdef ETHTOOL_GSET + case ETHTOOL_GSET: { + struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + getSettings(pAC, port, &ecmd); + if(copy_to_user(pAddr, &ecmd, sizeof(ecmd))) { + return -EFAULT; + } + return 0; + } + break; +#endif +#ifdef ETHTOOL_SSET + case ETHTOOL_SSET: { + struct ethtool_cmd ecmd; + if(copy_from_user(&ecmd, pAddr, sizeof(ecmd))) { + return -EFAULT; + } + return setSettings(pAC, port, &ecmd); + } + break; +#endif +#ifdef ETHTOOL_GLINK + case ETHTOOL_GLINK: { + struct ethtool_value edata = { ETHTOOL_GLINK }; + edata.data = netif_carrier_ok(netdev); + if (copy_to_user(pAddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } +#endif +#ifdef ETHTOOL_GDRVINFO + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo drvinfo = { ETHTOOL_GDRVINFO }; + getDriverInfo(pAC, port, &drvinfo); + if(copy_to_user(pAddr, &drvinfo, sizeof(drvinfo))) { + return -EFAULT; + } + return 0; + } + break; +#endif +#ifdef ETHTOOL_GSTRINGS + case ETHTOOL_GSTRINGS: { + struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; + char *strings = NULL; + int err = 0; + if(copy_from_user(&gstrings, pAddr, sizeof(gstrings))) { + return -EFAULT; + } + switch(gstrings.string_set) { +#ifdef ETHTOOL_GSTATS + case ETH_SS_STATS: { + int i; + gstrings.len = SK98LIN_STATS_LEN; + if ((strings = kmalloc(SK98LIN_STATS_LEN*ETHT_STATSTRING_LEN,GFP_KERNEL)) == NULL) { + return -ENOMEM; + } + for(i=0; i < SK98LIN_STATS_LEN; i++) { + memcpy(&strings[i * ETHT_STATSTRING_LEN], + &(sk98lin_etht_stats[i].stat_string), + ETHT_STATSTRING_LEN); + } + } + break; +#endif + default: + return -EOPNOTSUPP; + } + if(copy_to_user(pAddr, &gstrings, sizeof(gstrings))) { + err = -EFAULT; + } + pAddr = (void *) ((unsigned long int) pAddr + offsetof(struct ethtool_gstrings, data)); + if(!err && copy_to_user(pAddr, strings, gstrings.len * ETH_GSTRING_LEN)) { + err = -EFAULT; + } + kfree(strings); + return err; + } +#endif +#ifdef ETHTOOL_GSTATS + case ETHTOOL_GSTATS: { + struct { + struct ethtool_stats eth_stats; + uint64_t data[SK98LIN_STATS_LEN]; + } stats = { {ETHTOOL_GSTATS, SK98LIN_STATS_LEN} }; + int i; + + if (netif_running(pAC->dev[port])) { + SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, port); + } + for(i = 0; i < SK98LIN_STATS_LEN; i++) { + if (netif_running(pAC->dev[port])) { + stats.data[i] = (sk98lin_etht_stats[i].sizeof_stat == + sizeof(uint64_t)) ? + *(uint64_t *)((char *)pAC + + sk98lin_etht_stats[i].stat_offset) : + *(uint32_t *)((char *)pAC + + sk98lin_etht_stats[i].stat_offset); + } else { + stats.data[i] = (sk98lin_etht_stats[i].sizeof_stat == + sizeof(uint64_t)) ? (uint64_t) 0 : (uint32_t) 0; + } + } + if(copy_to_user(pAddr, &stats, sizeof(stats))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_PHYS_ID + case ETHTOOL_PHYS_ID: { + struct ethtool_value blinkSecs; + if(copy_from_user(&blinkSecs, pAddr, sizeof(blinkSecs))) { + return -EFAULT; + } + return startLocateNIC(pAC, port, &blinkSecs); + } +#endif +#ifdef ETHTOOL_GPAUSEPARAM + case ETHTOOL_GPAUSEPARAM: { + struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM }; + getPauseParams(pAC, port, &epause); + if(copy_to_user(pAddr, &epause, sizeof(epause))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_SPAUSEPARAM + case ETHTOOL_SPAUSEPARAM: { + struct ethtool_pauseparam epause; + if(copy_from_user(&epause, pAddr, sizeof(epause))) { + return -EFAULT; + } + return setPauseParams(pAC, port, &epause); + } +#endif +#ifdef ETHTOOL_GSG + case ETHTOOL_GSG: { + struct ethtool_value edata = { ETHTOOL_GSG }; + edata.data = (netdev->features & NETIF_F_SG) != 0; + if (copy_to_user(pAddr, &edata, sizeof(edata))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_SSG + case ETHTOOL_SSG: { + struct ethtool_value edata; + if (copy_from_user(&edata, pAddr, sizeof(edata))) { + return -EFAULT; + } + if (pAC->ChipsetType) { /* Don't handle if Genesis */ + if (edata.data) { + netdev->features |= NETIF_F_SG; + } else { + netdev->features &= ~NETIF_F_SG; + } + } + return 0; + } +#endif +#ifdef ETHTOOL_GRXCSUM + case ETHTOOL_GRXCSUM: { + struct ethtool_value edata = { ETHTOOL_GRXCSUM }; + edata.data = pAC->RxPort[port].UseRxCsum; + if (copy_to_user(pAddr, &edata, sizeof(edata))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_SRXCSUM + case ETHTOOL_SRXCSUM: { + struct ethtool_value edata; + if (copy_from_user(&edata, pAddr, sizeof(edata))) { + return -EFAULT; + } + pAC->RxPort[port].UseRxCsum = edata.data; + return 0; + } +#endif +#ifdef ETHTOOL_GTXCSUM + case ETHTOOL_GTXCSUM: { + struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + edata.data = ((netdev->features & NETIF_F_IP_CSUM) != 0); + if (copy_to_user(pAddr, &edata, sizeof(edata))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_STXCSUM + case ETHTOOL_STXCSUM: { + struct ethtool_value edata; + if (copy_from_user(&edata, pAddr, sizeof(edata))) { + return -EFAULT; + } + if (pAC->ChipsetType) { /* Don't handle if Genesis */ + if (edata.data) { + netdev->features |= NETIF_F_IP_CSUM; + } else { + netdev->features &= ~NETIF_F_IP_CSUM; + } + } + return 0; + } +#endif +#ifdef ETHTOOL_NWAY_RST + case ETHTOOL_NWAY_RST: { + if(netif_running(netdev)) { + (*netdev->stop)(netdev); + (*netdev->open)(netdev); + } + return 0; + } +#endif +#ifdef NETIF_F_TSO +#ifdef ETHTOOL_GTSO + case ETHTOOL_GTSO: { + struct ethtool_value edata = { ETHTOOL_GTSO }; + edata.data = (netdev->features & NETIF_F_TSO) != 0; + if (copy_to_user(pAddr, &edata, sizeof(edata))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_STSO + case ETHTOOL_STSO: { + struct ethtool_value edata; + if (CHIP_ID_YUKON_2(pAC)) { + if (copy_from_user(&edata, pAddr, sizeof(edata))) { + return -EFAULT; + } + if (edata.data) { + netdev->features |= NETIF_F_TSO; + } else { + netdev->features &= ~NETIF_F_TSO; + } + return 0; + } + return -EOPNOTSUPP; + } +#endif +#endif +#ifdef ETHTOOL_GCOALESCE + case ETHTOOL_GCOALESCE: { + struct ethtool_coalesce ecoalesc = { ETHTOOL_GCOALESCE }; + getModerationParams(pAC, port, &ecoalesc); + if(copy_to_user(pAddr, &ecoalesc, sizeof(ecoalesc))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_SCOALESCE + case ETHTOOL_SCOALESCE: { + struct ethtool_coalesce ecoalesc; + if(copy_from_user(&ecoalesc, pAddr, sizeof(ecoalesc))) { + return -EFAULT; + } + return setModerationParams(pAC, port, &ecoalesc); + } +#endif +#ifdef ETHTOOL_GWOL + case ETHTOOL_GWOL: { + struct ethtool_wolinfo ewol = { ETHTOOL_GWOL }; + getWOLsettings(pAC, port, &ewol); + if(copy_to_user(pAddr, &ewol, sizeof(ewol))) { + return -EFAULT; + } + return 0; + } +#endif +#ifdef ETHTOOL_SWOL + case ETHTOOL_SWOL: { + struct ethtool_wolinfo ewol; + if(copy_from_user(&ewol, pAddr, sizeof(ewol))) { + return -EFAULT; + } + return setWOLsettings(pAC, port, &ewol); + } +#endif + default: + return -EOPNOTSUPP; + } +} /* SkEthIoctl() */ + +/****************************************************************************** + * + * Local Functions + * + *****************************************************************************/ + +#ifdef ETHTOOL_GSET +/***************************************************************************** + * + * getSettings - retrieves the current settings of the selected adapter + * + * Description: + * The current configuration of the selected adapter is returned. + * This configuration involves a)speed, b)duplex and c)autoneg plus + * a number of other variables. + * + * Returns: N/A + * + */ +static void getSettings( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_cmd *ecmd) /* mandatory command structure for results */ +{ + SK_GEPORT *pPort = &pAC->GIni.GP[port]; + + static int DuplexAutoNegConfMap[9][3]= { + { -1 , -1 , -1 }, + { 0 , -1 , -1 }, + { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE }, + { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE }, + { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE }, + { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE }, + { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE }, + { SK_LMODE_AUTOSENSE , -1 , -1 }, + { SK_LMODE_INDETERMINATED, -1 , -1 } + }; + + static int SpeedConfMap[6][2] = { + { 0 , -1 }, + { SK_LSPEED_AUTO , -1 }, + { SK_LSPEED_10MBPS , SPEED_10 }, + { SK_LSPEED_100MBPS , SPEED_100 }, + { SK_LSPEED_1000MBPS , SPEED_1000 }, + { SK_LSPEED_INDETERMINATED, -1 } + }; + + static int AdvSpeedMap[6][2] = { + { 0 , -1 }, + { SK_LSPEED_AUTO , -1 }, + { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full }, + { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full }, + { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full}, + { SK_LSPEED_INDETERMINATED, -1 } + }; + + ecmd->phy_address = port; + ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1]; + ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1]; + ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2]; + ecmd->transceiver = XCVR_INTERNAL; + + if (pAC->GIni.GICopperType) { + ecmd->port = PORT_TP; + ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg); + if (pAC->GIni.GIGenesis) { + ecmd->supported &= ~(SUPPORTED_10baseT_Half); + ecmd->supported &= ~(SUPPORTED_10baseT_Full); + ecmd->supported &= ~(SUPPORTED_100baseT_Half); + ecmd->supported &= ~(SUPPORTED_100baseT_Full); + } else { + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + ecmd->supported &= ~(SUPPORTED_1000baseT_Half); + } + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { + ecmd->supported &= ~(SUPPORTED_1000baseT_Half); + ecmd->supported &= ~(SUPPORTED_1000baseT_Full); + } + } + if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) { + ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1]; + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + ecmd->advertising &= ~(SUPPORTED_1000baseT_Half); + } + } else { + ecmd->advertising = ecmd->supported; + } + if (ecmd->autoneg == AUTONEG_ENABLE) { + ecmd->advertising |= ADVERTISED_Autoneg; + } else { + ecmd->advertising = ADVERTISED_TP; + } + } else { + ecmd->port = PORT_FIBRE; + ecmd->supported = (SUPP_FIBRE_ALL); + ecmd->advertising = (ADV_FIBRE_ALL); + } +} +#endif + +#ifdef ETHTOOL_SSET +/***************************************************************************** + * + * setSettings - configures the settings of a selected adapter + * + * Description: + * Possible settings that may be altered are a)speed, b)duplex or + * c)autonegotiation. + * + * Returns: + * ==0: everything fine, no error + * !=0: the return value is the error code of the failure + */ +static int setSettings( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_cmd *ecmd) /* command structure containing settings */ +{ + DEV_NET *pNet = (DEV_NET *) pAC->dev[port]->priv; + SK_U32 Instance; + char Buf[4]; + unsigned int Len = 1; + int Ret; + + if (port == 0) { + Instance = (pAC->RlmtNets == 2) ? 1 : 2; + } else { + Instance = (pAC->RlmtNets == 2) ? 2 : 3; + } + + if (((ecmd->autoneg == AUTONEG_DISABLE) || (ecmd->autoneg == AUTONEG_ENABLE)) && + ((ecmd->duplex == DUPLEX_FULL) || (ecmd->duplex == DUPLEX_HALF))) { + if (ecmd->autoneg == AUTONEG_DISABLE) { + if (ecmd->duplex == DUPLEX_FULL) { + *Buf = (char) SK_LMODE_FULL; + } else { + *Buf = (char) SK_LMODE_HALF; + } + } else { + if (ecmd->duplex == DUPLEX_FULL) { + *Buf = (char) SK_LMODE_AUTOFULL; + } else { + *Buf = (char) SK_LMODE_AUTOHALF; + } + } + + Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, + &Buf, &Len, Instance, pNet->NetNr); + + if (Ret != SK_PNMI_ERR_OK) { + return -EINVAL; + } + } else if (ecmd->autoneg == AUTONEG_ENABLE) { + /* Set default values */ + *Buf = (char) SK_LMODE_AUTOFULL; + Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, + &Buf, &Len, Instance, pNet->NetNr); + } + + if ((ecmd->speed == SPEED_1000) || + (ecmd->speed == SPEED_100) || + (ecmd->speed == SPEED_10)) { + if (ecmd->autoneg == AUTONEG_ENABLE) { + *Buf = (char) SK_LSPEED_AUTO; + } else if (ecmd->speed == SPEED_1000) { + *Buf = (char) SK_LSPEED_1000MBPS; + } else if (ecmd->speed == SPEED_100) { + *Buf = (char) SK_LSPEED_100MBPS; + } else { + *Buf = (char) SK_LSPEED_10MBPS; + } + + Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, + &Buf, &Len, Instance, pNet->NetNr); + + if (Ret != SK_PNMI_ERR_OK) { + return -EINVAL; + } + } else if (ecmd->autoneg == AUTONEG_ENABLE) { + *Buf = (char) SK_LSPEED_AUTO; + Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, + &Buf, &Len, Instance, pNet->NetNr); + } else { + return -EINVAL; + } + + return 0; +} +#endif + +#ifdef ETHTOOL_GPAUSEPARAM +/***************************************************************************** + * + * getPauseParams - retrieves the pause parameters + * + * Description: + * All current pause parameters of a selected adapter are placed + * in the passed ethtool_pauseparam structure and are returned. + * + * Returns: N/A + * + */ +static void getPauseParams( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_pauseparam *epause) /* pause parameter struct for result */ +{ + SK_GEPORT *pPort = &pAC->GIni.GP[port]; + + epause->rx_pause = 0; + epause->tx_pause = 0; + + if (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND) { + epause->tx_pause = 1; + } + if ((pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) || + (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM)) { + epause->tx_pause = 1; + epause->rx_pause = 1; + } + + if ((epause->rx_pause == 0) && (epause->tx_pause == 0)) { + epause->autoneg = SK_FALSE; + } else { + epause->autoneg = SK_TRUE; + } +} +#endif + +#ifdef ETHTOOL_SPAUSEPARAM +/***************************************************************************** + * + * setPauseParams - configures the pause parameters of an adapter + * + * Description: + * This function sets the Rx or Tx pause parameters + * + * Returns: + * ==0: everything fine, no error + * !=0: the return value is the error code of the failure + */ +static int setPauseParams( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_pauseparam *epause) /* pause parameter struct with params */ +{ + SK_GEPORT *pPort = &pAC->GIni.GP[port]; + DEV_NET *pNet = (DEV_NET *) pAC->dev[port]->priv; + int PrevSpeedVal = pPort->PLinkSpeedUsed; + + SK_U32 Instance; + char Buf[4]; + int Ret; + SK_BOOL prevAutonegValue = SK_TRUE; + int prevTxPause = 0; + int prevRxPause = 0; + unsigned int Len = 1; + + if (port == 0) { + Instance = (pAC->RlmtNets == 2) ? 1 : 2; + } else { + Instance = (pAC->RlmtNets == 2) ? 2 : 3; + } + + /* + ** we have to determine the current settings to see if + ** the operator requested any modification of the flow + ** control parameters... + */ + if (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND) { + prevTxPause = 1; + } + if ((pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) || + (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM)) { + prevTxPause = 1; + prevRxPause = 1; + } + + if ((prevRxPause == 0) && (prevTxPause == 0)) { + prevAutonegValue = SK_FALSE; + } + + + /* + ** perform modifications regarding the changes + ** requested by the operator + */ + if (epause->autoneg != prevAutonegValue) { + if (epause->autoneg == AUTONEG_DISABLE) { + *Buf = (char) SK_FLOW_MODE_NONE; + } else { + *Buf = (char) SK_FLOW_MODE_SYMMETRIC; + } + } else { + if(epause->rx_pause && epause->tx_pause) { + *Buf = (char) SK_FLOW_MODE_SYMMETRIC; + } else if (epause->rx_pause && !epause->tx_pause) { + *Buf = (char) SK_FLOW_MODE_SYM_OR_REM; + } else if(!epause->rx_pause && epause->tx_pause) { + *Buf = (char) SK_FLOW_MODE_LOC_SEND; + } else { + *Buf = (char) SK_FLOW_MODE_NONE; + } + } + + Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE, + &Buf, &Len, Instance, pNet->NetNr); + + if (Ret != SK_PNMI_ERR_OK) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL, + ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", Ret)); + } else { + Len = 1; /* set buffer length to correct value */ + } + + /* + ** It may be that autoneg has been disabled! Therefore + ** set the speed to the previously used value... + */ + *Buf = (char) PrevSpeedVal; + + Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, + &Buf, &Len, Instance, pNet->NetNr); + + if (Ret != SK_PNMI_ERR_OK) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL, + ("ethtool (sk98lin): error setting speed (%i)\n", Ret)); + } + return 0; +} +#endif + +#ifdef ETHTOOL_GCOALESCE +/***************************************************************************** + * + * getModerationParams - retrieves the IRQ moderation settings + * + * Description: + * All current IRQ moderation settings of a selected adapter are placed + * in the passed ethtool_coalesce structure and are returned. + * + * Returns: N/A + * + */ +static void getModerationParams( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_coalesce *ecoalesc) /* IRQ moderation struct for results */ +{ + DIM_INFO *Info = &pAC->DynIrqModInfo; + SK_BOOL UseTxIrqModeration = SK_FALSE; + SK_BOOL UseRxIrqModeration = SK_FALSE; + + if (Info->IntModTypeSelect != C_INT_MOD_NONE) { + if (CHIP_ID_YUKON_2(pAC)) { + UseRxIrqModeration = SK_TRUE; + UseTxIrqModeration = SK_TRUE; + } else { + if ((Info->MaskIrqModeration == IRQ_MASK_RX_ONLY) || + (Info->MaskIrqModeration == IRQ_MASK_SP_RX) || + (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) { + UseRxIrqModeration = SK_TRUE; + } + if ((Info->MaskIrqModeration == IRQ_MASK_TX_ONLY) || + (Info->MaskIrqModeration == IRQ_MASK_SP_TX) || + (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) { + UseTxIrqModeration = SK_TRUE; + } + } + + if (UseRxIrqModeration) { + ecoalesc->rx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec; + } + if (UseTxIrqModeration) { + ecoalesc->tx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec; + } + if (Info->IntModTypeSelect == C_INT_MOD_DYNAMIC) { + ecoalesc->rate_sample_interval = Info->DynIrqModSampleInterval; + if (UseRxIrqModeration) { + ecoalesc->use_adaptive_rx_coalesce = 1; + ecoalesc->rx_coalesce_usecs_low = + 1000000 / Info->MaxModIntsPerSecLowerLimit; + ecoalesc->rx_coalesce_usecs_high = + 1000000 / Info->MaxModIntsPerSecUpperLimit; + } + if (UseTxIrqModeration) { + ecoalesc->use_adaptive_tx_coalesce = 1; + ecoalesc->tx_coalesce_usecs_low = + 1000000 / Info->MaxModIntsPerSecLowerLimit; + ecoalesc->tx_coalesce_usecs_high = + 1000000 / Info->MaxModIntsPerSecUpperLimit; + } + } + } +} +#endif + +#ifdef ETHTOOL_SCOALESCE +/***************************************************************************** + * + * setModerationParams - configures the IRQ moderation of an adapter + * + * Description: + * Depending on the desired IRQ moderation parameters, either a) static, + * b) dynamic or c) no moderation is configured. + * + * Returns: + * ==0: everything fine, no error + * !=0: the return value is the error code of the failure + * + * Notes: + * The supported timeframe for the coalesced interrupts ranges from + * 33.333us (30 IntsPerSec) down to 25us (40.000 IntsPerSec). + * Any requested value that is not in this range will abort the request! + */ +static int setModerationParams( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_coalesce *ecoalesc) /* IRQ moderation struct with params */ +{ + DIM_INFO *Info = &pAC->DynIrqModInfo; + int PrevModeration = Info->IntModTypeSelect; + + Info->IntModTypeSelect = C_INT_MOD_NONE; /* initial default */ + + if ((ecoalesc->rx_coalesce_usecs) || (ecoalesc->tx_coalesce_usecs)) { + if (ecoalesc->rx_coalesce_usecs) { + if ((ecoalesc->rx_coalesce_usecs < 25) || + (ecoalesc->rx_coalesce_usecs > 33333)) { + return -EINVAL; + } + } + if (ecoalesc->tx_coalesce_usecs) { + if ((ecoalesc->tx_coalesce_usecs < 25) || + (ecoalesc->tx_coalesce_usecs > 33333)) { + return -EINVAL; + } + } + if (!CHIP_ID_YUKON_2(pAC)) { + if ((Info->MaskIrqModeration == IRQ_MASK_SP_RX) || + (Info->MaskIrqModeration == IRQ_MASK_SP_TX) || + (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) { + Info->MaskIrqModeration = IRQ_MASK_SP_ONLY; + } + } + Info->IntModTypeSelect = C_INT_MOD_STATIC; + if (ecoalesc->rx_coalesce_usecs) { + Info->MaxModIntsPerSec = + 1000000 / ecoalesc->rx_coalesce_usecs; + if (!CHIP_ID_YUKON_2(pAC)) { + if (Info->MaskIrqModeration == IRQ_MASK_TX_ONLY) { + Info->MaskIrqModeration = IRQ_MASK_TX_RX; + } + if (Info->MaskIrqModeration == IRQ_MASK_SP_ONLY) { + Info->MaskIrqModeration = IRQ_MASK_SP_RX; + } + if (Info->MaskIrqModeration == IRQ_MASK_SP_TX) { + Info->MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } + } else { + Info->MaskIrqModeration = Y2_IRQ_MASK; + } + } + if (ecoalesc->tx_coalesce_usecs) { + Info->MaxModIntsPerSec = + 1000000 / ecoalesc->tx_coalesce_usecs; + if (!CHIP_ID_YUKON_2(pAC)) { + if (Info->MaskIrqModeration == IRQ_MASK_RX_ONLY) { + Info->MaskIrqModeration = IRQ_MASK_TX_RX; + } + if (Info->MaskIrqModeration == IRQ_MASK_SP_ONLY) { + Info->MaskIrqModeration = IRQ_MASK_SP_TX; + } + if (Info->MaskIrqModeration == IRQ_MASK_SP_RX) { + Info->MaskIrqModeration = IRQ_MASK_RX_TX_SP; + } + } else { + Info->MaskIrqModeration = Y2_IRQ_MASK; + } + } + } + if ((ecoalesc->rate_sample_interval) || + (ecoalesc->rx_coalesce_usecs_low) || + (ecoalesc->tx_coalesce_usecs_low) || + (ecoalesc->rx_coalesce_usecs_high)|| + (ecoalesc->tx_coalesce_usecs_high)) { + if (ecoalesc->rate_sample_interval) { + if ((ecoalesc->rate_sample_interval < 1) || + (ecoalesc->rate_sample_interval > 10)) { + return -EINVAL; + } + } + if (ecoalesc->rx_coalesce_usecs_low) { + if ((ecoalesc->rx_coalesce_usecs_low < 25) || + (ecoalesc->rx_coalesce_usecs_low > 33333)) { + return -EINVAL; + } + } + if (ecoalesc->rx_coalesce_usecs_high) { + if ((ecoalesc->rx_coalesce_usecs_high < 25) || + (ecoalesc->rx_coalesce_usecs_high > 33333)) { + return -EINVAL; + } + } + if (ecoalesc->tx_coalesce_usecs_low) { + if ((ecoalesc->tx_coalesce_usecs_low < 25) || + (ecoalesc->tx_coalesce_usecs_low > 33333)) { + return -EINVAL; + } + } + if (ecoalesc->tx_coalesce_usecs_high) { + if ((ecoalesc->tx_coalesce_usecs_high < 25) || + (ecoalesc->tx_coalesce_usecs_high > 33333)) { + return -EINVAL; + } + } + + Info->IntModTypeSelect = C_INT_MOD_DYNAMIC; + if (ecoalesc->rate_sample_interval) { + Info->DynIrqModSampleInterval = + ecoalesc->rate_sample_interval; + } + if (ecoalesc->rx_coalesce_usecs_low) { + Info->MaxModIntsPerSecLowerLimit = + 1000000 / ecoalesc->rx_coalesce_usecs_low; + } + if (ecoalesc->tx_coalesce_usecs_low) { + Info->MaxModIntsPerSecLowerLimit = + 1000000 / ecoalesc->tx_coalesce_usecs_low; + } + if (ecoalesc->rx_coalesce_usecs_high) { + Info->MaxModIntsPerSecUpperLimit = + 1000000 / ecoalesc->rx_coalesce_usecs_high; + } + if (ecoalesc->tx_coalesce_usecs_high) { + Info->MaxModIntsPerSecUpperLimit = + 1000000 / ecoalesc->tx_coalesce_usecs_high; + } + } + + if ((PrevModeration == C_INT_MOD_NONE) && + (Info->IntModTypeSelect != C_INT_MOD_NONE)) { + SkDimEnableModerationIfNeeded(pAC); + } + if (PrevModeration != C_INT_MOD_NONE) { + SkDimDisableModeration(pAC, PrevModeration); + if (Info->IntModTypeSelect != C_INT_MOD_NONE) { + SkDimEnableModerationIfNeeded(pAC); + } + } + + return 0; +} +#endif + +#ifdef ETHTOOL_GWOL +/***************************************************************************** + * + * getWOLsettings - retrieves the WOL settings of the selected adapter + * + * Description: + * All current WOL settings of a selected adapter are placed in the + * passed ethtool_wolinfo structure and are returned to the caller. + * + * Returns: N/A + * + */ +static void getWOLsettings( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_wolinfo *ewol) /* mandatory WOL structure for results */ +{ + ewol->supported = pAC->WolInfo.SupportedWolOptions; + ewol->wolopts = pAC->WolInfo.ConfiguredWolOptions; + + return; +} +#endif + +#ifdef ETHTOOL_SWOL +/***************************************************************************** + * + * setWOLsettings - configures the WOL settings of a selected adapter + * + * Description: + * The WOL settings of a selected adapter are configured regarding + * the parameters in the passed ethtool_wolinfo structure. + * Note that currently only wake on magic packet is supported! + * + * Returns: + * ==0: everything fine, no error + * !=0: the return value is the error code of the failure + */ +static int setWOLsettings( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_wolinfo *ewol) /* WOL structure containing settings */ +{ + if (((ewol->wolopts & WAKE_MAGIC) == WAKE_MAGIC) || (ewol->wolopts == 0)) { + pAC->WolInfo.ConfiguredWolOptions = ewol->wolopts; + return 0; + } + return -EFAULT; +} +#endif + +#ifdef ETHTOOL_GDRVINFO +/***************************************************************************** + * + * getDriverInfo - returns generic driver and adapter information + * + * Description: + * Generic driver information is returned via this function, such as + * the name of the driver, its version and and firmware version. + * In addition to this, the location of the selected adapter is + * returned as a bus info string (e.g. '01:05.0'). + * + * Returns: N/A + * + */ +static void getDriverInfo( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_drvinfo *edrvinfo) /* mandatory info structure for results */ +{ + char versionString[32]; + + snprintf(versionString, 32, "%s (%s)", VER_STRING, PATCHLEVEL); + strncpy(edrvinfo->driver, DRIVER_FILE_NAME , 32); + strncpy(edrvinfo->version, versionString , 32); + strncpy(edrvinfo->fw_version, "N/A", 32); + strncpy(edrvinfo->bus_info, pci_name(pAC->PciDev), 32); + +#ifdef ETHTOOL_GSTATS + edrvinfo->n_stats = SK98LIN_STATS_LEN; +#endif +} +#endif + +#ifdef ETHTOOL_PHYS_ID +/***************************************************************************** + * + * startLocateNIC - start the locate NIC feature of the elected adapter + * + * Description: + * This function is used if the user want to locate a particular NIC. + * All LEDs are regularly switched on and off, so the NIC can easily + * be identified. + * + * Returns: + * ==0: everything fine, no error, locateNIC test was started + * !=0: one locateNIC test runs already + * + */ +static int startLocateNIC( +SK_AC *pAC, /* pointer to adapter control context */ +int port, /* the port of the selected adapter */ +struct ethtool_value *blinkSecs) /* how long the LEDs should blink in seconds */ +{ + struct SK_NET_DEVICE *pDev = pAC->dev[port]; + int OtherPort = (port) ? 0 : 1; + struct SK_NET_DEVICE *pOtherDev = pAC->dev[OtherPort]; + + if (isLocateNICrunning) { + return -EFAULT; + } + isLocateNICrunning = SK_TRUE; + currentPortIndex = port; + isDualNetCard = (pDev != pOtherDev) ? SK_TRUE : SK_FALSE; + + if (netif_running(pAC->dev[port])) { + boardWasDown[0] = SK_FALSE; + } else { + (*pDev->open)(pDev); + boardWasDown[0] = SK_TRUE; + } + + if (isDualNetCard) { + if (netif_running(pAC->dev[OtherPort])) { + boardWasDown[1] = SK_FALSE; + } else { + (*pOtherDev->open)(pOtherDev); + boardWasDown[1] = SK_TRUE; + } + } + + if ((blinkSecs->data < 1) || (blinkSecs->data > 30)) { + blinkSecs->data = 3; /* three seconds default */ + } + nbrBlinkQuarterSeconds = 4*blinkSecs->data; + + init_timer(&locateNICtimer); + locateNICtimer.function = toggleLeds; + locateNICtimer.data = (unsigned long) pAC; + locateNICtimer.expires = jiffies + HZ; /* initially 1sec */ + add_timer(&locateNICtimer); + + return 0; +} + +/***************************************************************************** + * + * toggleLeds - Changes the LED state of an adapter + * + * Description: + * This function changes the current state of all LEDs of an adapter so + * that it can be located by a user. If the requested time interval for + * this test has elapsed, this function cleans up everything that was + * temporarily setup during the locate NIC test. This involves of course + * also closing or opening any adapter so that the initial board state + * is recovered. + * + * Returns: N/A + * + */ +static void toggleLeds( +unsigned long ptr) /* holds the pointer to adapter control context */ +{ + SK_AC *pAC = (SK_AC *) ptr; + int port = currentPortIndex; + SK_IOC IoC = pAC->IoBase; + struct SK_NET_DEVICE *pDev = pAC->dev[port]; + int OtherPort = (port) ? 0 : 1; + struct SK_NET_DEVICE *pOtherDev = pAC->dev[OtherPort]; + + SK_U16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) | + PHY_M_LED_MO_10(MO_LED_ON) | + PHY_M_LED_MO_100(MO_LED_ON) | + PHY_M_LED_MO_1000(MO_LED_ON) | + PHY_M_LED_MO_RX(MO_LED_ON)); + SK_U16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) | + PHY_M_LED_MO_10(MO_LED_OFF) | + PHY_M_LED_MO_100(MO_LED_OFF) | + PHY_M_LED_MO_1000(MO_LED_OFF) | + PHY_M_LED_MO_RX(MO_LED_OFF)); + + nbrBlinkQuarterSeconds--; + if (nbrBlinkQuarterSeconds <= 0) { + (*pDev->stop)(pDev); + if (isDualNetCard) { + (*pOtherDev->stop)(pOtherDev); + } + + if (!boardWasDown[0]) { + (*pDev->open)(pDev); + } + if (isDualNetCard) { + (*pOtherDev->open)(pOtherDev); + } + isDualNetCard = SK_FALSE; + isLocateNICrunning = SK_FALSE; + return; + } + + doSwitchLEDsOn = (doSwitchLEDsOn) ? SK_FALSE : SK_TRUE; + if (doSwitchLEDsOn) { + if (pAC->GIni.GIGenesis) { + SK_OUT8(IoC,MR_ADDR(port,LNK_LED_REG),(SK_U8)SK_LNK_ON); + SkGeYellowLED(pAC,IoC,LED_ON >> 1); + SkGeXmitLED(pAC,IoC,MR_ADDR(port,RX_LED_INI),SK_LED_TST); + if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) { + SkXmPhyWrite(pAC,IoC,port,PHY_BCOM_P_EXT_CTRL,PHY_B_PEC_LED_ON); + } else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) { + SkXmPhyWrite(pAC,IoC,port,PHY_LONE_LED_CFG,0x0800); + } else { + SkGeXmitLED(pAC,IoC,MR_ADDR(port,TX_LED_INI),SK_LED_TST); + } + } else { + SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_CTRL,0); + SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_OVER,YukLedOn); + } + } else { + if (pAC->GIni.GIGenesis) { + SK_OUT8(IoC,MR_ADDR(port,LNK_LED_REG),(SK_U8)SK_LNK_OFF); + SkGeYellowLED(pAC,IoC,LED_OFF >> 1); + SkGeXmitLED(pAC,IoC,MR_ADDR(port,RX_LED_INI),SK_LED_DIS); + if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) { + SkXmPhyWrite(pAC,IoC,port,PHY_BCOM_P_EXT_CTRL,PHY_B_PEC_LED_OFF); + } else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) { + SkXmPhyWrite(pAC,IoC,port,PHY_LONE_LED_CFG,PHY_L_LC_LEDT); + } else { + SkGeXmitLED(pAC,IoC,MR_ADDR(port,TX_LED_INI),SK_LED_DIS); + } + } else { + SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_CTRL,0); + SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_OVER,YukLedOff); + } + } + + locateNICtimer.function = toggleLeds; + locateNICtimer.data = (unsigned long) pAC; + locateNICtimer.expires = jiffies + (HZ/4); /* 250ms */ + add_timer(&locateNICtimer); +} +#endif + +/***************************************************************************** + * + * getPortNumber - evaluates the port number of an interface + * + * Description: + * It may be that the current interface refers to one which is located + * on a dual net adapter. Hence, this function will return the correct + * port for further use. + * + * Returns: + * the port number that corresponds to the selected adapter + * + */ +static int getPortNumber( +struct net_device *netdev, /* the pointer to netdev structure */ +struct ifreq *ifr) /* what interface the request refers to? */ +{ + DEV_NET *pNet = (DEV_NET*) netdev->priv; + SK_AC *pAC = pNet->pAC; + + if (pAC->dev[1] != pAC->dev[0]) { + if (!strcmp(pAC->dev[1]->name, ifr->ifr_name)) { + return 1; /* port index 1 */ + } + } + return 0; +} + +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ + +#endif diff --git a/drivers/sk98lin/skge.c b/drivers/sk98lin/skge.c index 61a6094..52b9928 100644 --- a/drivers/sk98lin/skge.c +++ b/drivers/sk98lin/skge.c @@ -1,47 +1,26 @@ /****************************************************************************** * - * Name: skge.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.46 $ - * Date: $Date: 2003/02/25 14:16:36 $ - * Purpose: The main driver source module + * Name: skge.c + * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: The main driver source module * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. * - * Driver for SysKonnect Gigabit Ethernet Server Adapters: + * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet + * Server Adapters. * - * SK-9871 (single link 1000Base-ZX) - * SK-9872 (dual link 1000Base-ZX) - * SK-9861 (single link 1000Base-SX, VF45 Volition Plug) - * SK-9862 (dual link 1000Base-SX, VF45 Volition Plug) - * SK-9841 (single link 1000Base-LX) - * SK-9842 (dual link 1000Base-LX) - * SK-9843 (single link 1000Base-SX) - * SK-9844 (dual link 1000Base-SX) - * SK-9821 (single link 1000Base-T) - * SK-9822 (dual link 1000Base-T) - * SK-9881 (single link 1000Base-SX V2 LC) - * SK-9871 (single link 1000Base-ZX V2) - * SK-9861 (single link 1000Base-SX V2, VF45 Volition Plug) - * SK-9841 (single link 1000Base-LX V2) - * SK-9843 (single link 1000Base-SX V2) - * SK-9821 (single link 1000Base-T V2) - * - * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and - * SysKonnects GEnesis Solaris driver - * Author: Christoph Goos (cgoos@syskonnect.de) - * Mirko Lindner (mlindner@syskonnect.de) + * Author: Mirko Lindner (mlindner@syskonnect.de) + * Ralph Roesler (rroesler@syskonnect.de) * * Address all question to: linux@syskonnect.de * - * The technical manual for the adapters is available from SysKonnect's - * web pages: www.syskonnect.com - * Goto "Support" and search Knowledge Base for "manual". - * * 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 @@ -51,368 +30,106 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skge.c,v $ - * Revision 1.46 2003/02/25 14:16:36 mlindner - * Fix: Copyright statement - * - * Revision 1.45 2003/02/25 13:25:55 mlindner - * Add: Performance improvements - * Add: Support for various vendors - * Fix: Init function - * - * Revision 1.44 2003/01/09 09:25:26 mlindner - * Fix: Remove useless init_module/cleanup_module forward declarations - * - * Revision 1.43 2002/11/29 08:42:41 mlindner - * Fix: Boot message - * - * Revision 1.42 2002/11/28 13:30:23 mlindner - * Add: New frame check - * - * Revision 1.41 2002/11/27 13:55:18 mlindner - * Fix: Drop wrong csum packets - * Fix: Initialize proc_entry after hw check - * - * Revision 1.40 2002/10/31 07:50:37 tschilli - * Function SkGeInitAssignRamToQueues() from common module inserted. - * Autonegotiation is set to ON for all adapters. - * LinkSpeedUsed is used in link up status report. - * Role parameter will show up for 1000 Mbps links only. - * GetConfiguration() inserted after init level 1 in SkGeChangeMtu(). - * All return values of SkGeInit() and SkGeInitPort() are checked. - * - * Revision 1.39 2002/10/02 12:56:05 mlindner - * Add: Support for Yukon - * Add: Support for ZEROCOPY, scatter-gather and hw checksum - * Add: New transmit ring function (use SG and TCP/UDP hardware checksumming) - * Add: New init function - * Add: Speed check and setup - * Add: Merge source for kernel 2.2.x and 2.4.x - * Add: Opcode check for tcp - * Add: Frame length check - * Fix: Transmit complete interrupt - * Fix: Interrupt moderation - * - * Revision 1.29.2.13 2002/01/14 12:44:52 mlindner - * Fix: Rlmt modes - * - * Revision 1.29.2.12 2001/12/07 12:06:18 mlindner - * Fix: malloc -> slab changes - * - * Revision 1.29.2.11 2001/12/06 15:19:20 mlindner - * Add: DMA attributes - * Fix: Module initialisation - * Fix: pci_map_single and pci_unmap_single replaced - * - * Revision 1.29.2.10 2001/12/06 09:56:50 mlindner - * Corrected some printk's - * - * Revision 1.29.2.9 2001/09/05 12:15:34 mlindner - * Add: LBFO Changes - * Fix: Counter Errors (Jumbo == to long errors) - * Fix: Changed pAC->PciDev declaration - * Fix: too short counters - * - * Revision 1.29.2.8 2001/06/25 12:10:44 mlindner - * fix: ReceiveIrq() changed. - * - * Revision 1.29.2.7 2001/06/25 08:07:05 mlindner - * fix: RLMT locking in ReceiveIrq() changed. - * - * Revision 1.29.2.6 2001/05/21 07:59:29 mlindner - * fix: MTU init problems - * - * Revision 1.29.2.5 2001/05/08 11:25:08 mlindner - * fix: removed VLAN error message - * - * Revision 1.29.2.4 2001/05/04 13:31:43 gklug - * fix: do not handle eth_copy on bad fragments received. - * - * Revision 1.29.2.3 2001/04/23 08:06:43 mlindner - * Fix: error handling - * - * Revision 1.29.2.2 2001/03/15 12:04:54 mlindner - * Fixed memory problem - * - * Revision 1.29.2.1 2001/03/12 16:41:44 mlindner - * add: procfs function - * add: dual-net function - * add: RLMT networks - * add: extended PNMI features - * - * Kernel 2.4.x specific: - * Revision 1.xx 2000/09/12 13:31:56 cgoos - * Fixed missign "dev=NULL in skge_probe. - * Added counting for jumbo frames (corrects error statistic). - * Removed VLAN tag check (enables VLAN support). - * - * Kernel 2.2.x specific: - * Revision 1.29 2000/02/21 13:31:56 cgoos - * Fixed "unused" warning for UltraSPARC change. - * - * Partially kernel 2.2.x specific: - * Revision 1.28 2000/02/21 10:32:36 cgoos - * Added fixes for UltraSPARC. - * Now printing RlmtMode and PrefPort setting at startup. - * Changed XmitFrame return value. - * Fixed rx checksum calculation for BIG ENDIAN systems. - * Fixed rx jumbo frames counted as ierrors. - * - * - * Revision 1.27 1999/11/25 09:06:28 cgoos - * Changed base_addr to unsigned long. - * - * Revision 1.26 1999/11/22 13:29:16 cgoos - * Changed license header to GPL. - * Changes for inclusion in linux kernel (2.2.13). - * Removed 2.0.x defines. - * Changed SkGeProbe to skge_probe. - * Added checks in SkGeIoctl. - * - * Revision 1.25 1999/10/07 14:47:52 cgoos - * Changed 984x to 98xx. - * - * Revision 1.24 1999/09/30 07:21:01 cgoos - * Removed SK_RLMT_SLOW_LOOKAHEAD option. - * Giving spanning tree packets also to OS now. - * - * Revision 1.23 1999/09/29 07:36:50 cgoos - * Changed assignment for IsBc/IsMc. - * - * Revision 1.22 1999/09/28 12:57:09 cgoos - * Added CheckQueue also to Single-Port-ISR. - * - * Revision 1.21 1999/09/28 12:42:41 cgoos - * Changed parameter strings for RlmtMode. - * - * Revision 1.20 1999/09/28 12:37:57 cgoos - * Added CheckQueue for fast delivery of RLMT frames. - * - * Revision 1.19 1999/09/16 07:57:25 cgoos - * Copperfield changes. - * - * Revision 1.18 1999/09/03 13:06:30 cgoos - * Fixed RlmtMode=CheckSeg bug: wrong DEV_KFREE_SKB in RLMT_SEND caused - * double allocated skb's. - * FrameStat in ReceiveIrq was accessed via wrong Rxd. - * Queue size for async. standby Tx queue was zero. - * FillRxLimit of 0 could cause problems with ReQueue, changed to 1. - * Removed debug output of checksum statistic. - * - * Revision 1.17 1999/08/11 13:55:27 cgoos - * Transmit descriptor polling was not reenabled after SkGePortInit. - * - * Revision 1.16 1999/07/27 15:17:29 cgoos - * Added some "\n" in output strings (removed while debuging...). - * - * Revision 1.15 1999/07/23 12:09:30 cgoos - * Performance optimization, rx checksumming, large frame support. - * - * Revision 1.14 1999/07/14 11:26:27 cgoos - * Removed Link LED settings (now in RLMT). - * Added status output at NET UP. - * Fixed SMP problems with Tx and SWITCH running in parallel. - * Fixed return code problem at RLMT_SEND event. - * - * Revision 1.13 1999/04/07 10:11:42 cgoos - * Fixed Single Port problems. - * Fixed Multi-Adapter problems. - * Always display startup string. - * - * Revision 1.12 1999/03/29 12:26:37 cgoos - * Reversed locking to fine granularity. - * Fixed skb double alloc problem (caused by incorrect xmit return code). - * Enhanced function descriptions. - * - * Revision 1.11 1999/03/15 13:10:51 cgoos - * Changed device identifier in output string to ethX. - * - * Revision 1.10 1999/03/15 12:12:34 cgoos - * Changed copyright notice. - * - * Revision 1.9 1999/03/15 12:10:17 cgoos - * Changed locking to one driver lock. - * Added check of SK_AC-size (for consistency with library). - * - * Revision 1.8 1999/03/08 11:44:02 cgoos - * Fixed missing dev->tbusy in SkGeXmit. - * Changed large frame (jumbo) buffer number. - * Added copying of short frames. - * - * Revision 1.7 1999/03/04 13:26:57 cgoos - * Fixed spinlock calls for SMP. - * - * Revision 1.6 1999/03/02 09:53:51 cgoos - * Added descriptor revertion for big endian machines. - * - * Revision 1.5 1999/03/01 08:50:59 cgoos - * Fixed SkGeChangeMtu. - * Fixed pci config space accesses. - * - * Revision 1.4 1999/02/18 15:48:44 cgoos - * Corrected some printk's. - * - * Revision 1.3 1999/02/18 12:45:55 cgoos - * Changed SK_MAX_CARD_PARAM to default 16 - * - * Revision 1.2 1999/02/18 10:55:32 cgoos - * Removed SkGeDrvTimeStamp function. - * Printing "ethX:" before adapter type at adapter init. - * - * - * 10-Feb-1999 cg Created, based on Linux' acenic.c, 3c59x.c and - * SysKonnects GEnesis Solaris driver - * - ******************************************************************************/ - -/****************************************************************************** - * - * Possible compiler options (#define xxx / -Dxxx): - * - * debugging can be enable by changing SK_DEBUG_CHKMOD and - * SK_DEBUG_CHKCAT in makefile (described there). - * - ******************************************************************************/ - /****************************************************************************** * * Description: * - * This is the main module of the Linux GE driver. + * All source files in this sk98lin directory except of the sk98lin + * Linux specific files * - * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h - * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters. - * Those are used for drivers on multiple OS', so some thing may seem - * unnecessary complicated on Linux. Please do not try to 'clean up' - * them without VERY good reasons, because this will make it more - * difficult to keep the Linux driver in synchronisation with the - * other versions. + * - skdim.c + * - skethtool.c + * - skge.c + * - skproc.c + * - sky2.c + * - Makefile + * - h/skdrv1st.h + * - h/skdrv2nd.h + * - h/sktypes.h + * - h/skversion.h * - * Include file hierarchy: + * are part of SysKonnect's common modules for the SK-9xxx adapters. * - * + * Those common module files which are not Linux specific are used to + * build drivers on different OS' (e.g. Windows, MAC OS) so that those + * drivers are based on the same set of files * - * "h/skdrv1st.h" - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * those three depending on kernel version used: - * - * - * - * - * - * "h/skerror.h" - * "h/skdebug.h" - * "h/sktypes.h" - * "h/lm80.h" - * "h/xmac_ii.h" - * - * "h/skdrv2nd.h" - * "h/skqueue.h" - * "h/skgehwt.h" - * "h/sktimer.h" - * "h/ski2c.h" - * "h/skgepnmi.h" - * "h/skvpd.h" - * "h/skgehw.h" - * "h/skgeinit.h" - * "h/skaddr.h" - * "h/skgesirq.h" - * "h/skcsum.h" - * "h/skrlmt.h" + * At a first glance, this seems to complicate things unnescessarily on + * Linux, but please do not try to 'clean up' them without VERY good + * reasons, because this will make it more difficult to keep the sk98lin + * driver for Linux in synchronisation with the other drivers running on + * other operating systems. * ******************************************************************************/ - +/*#define DEBUG*/ #include - #ifdef CONFIG_SK98 #include "h/skversion.h" -#if 0 + +#if 0 /* uboot */ #include #include +#include +#endif + +#ifdef CONFIG_PROC_FS #include #endif + #include "h/skdrv1st.h" #include "h/skdrv2nd.h" -/* defines ******************************************************************/ +/******************************************************************************* + * + * Defines + * + ******************************************************************************/ + /* for debuging on x86 only */ /* #define BREAKPOINT() asm(" int $3"); */ -/* use the scatter-gather functionality with sendfile() */ -#if 0 -#define SK_ZEROCOPY + +/* Set blink mode*/ +#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \ + SK_DUP_LED_NORMAL | \ + SK_LED_LINK100_ON) + +#define CLEAR_AND_START_RX(Port) SK_OUT8(pAC->IoBase, RxQueueAddr[(Port)]+Q_CSR, CSR_START | CSR_IRQ_CL_F) +#define CLEAR_TX_IRQ(Port,Prio) SK_OUT8(pAC->IoBase, TxQueueAddr[(Port)][(Prio)]+Q_CSR, CSR_IRQ_CL_F) + + +/******************************************************************************* + * + * Local Function Prototypes + * + ******************************************************************************/ + +#if 0 /* uboot */ +static int __devinit sk98lin_init_device(struct pci_dev *pdev, const struct pci_device_id *ent); +static void sk98lin_remove_device(struct pci_dev *pdev); +#endif +#ifdef CONFIG_PM +static int sk98lin_suspend(struct pci_dev *pdev, u32 state); +static int sk98lin_resume(struct pci_dev *pdev); +static void SkEnableWOMagicPacket(SK_AC *pAC, SK_IOC IoC, SK_MAC_ADDR MacAddr); +#endif +#ifdef Y2_RECOVERY +static void SkGeHandleKernelTimer(unsigned long ptr); +void SkGeCheckTimer(DEV_NET *pNet); +static SK_BOOL CheckRXCounters(DEV_NET *pNet); +static void CheckRxPath(DEV_NET *pNet); #endif - -/* use of a transmit complete interrupt */ -#define USE_TX_COMPLETE - -/* use interrupt moderation (for tx complete only) */ -#define USE_INT_MOD -#define INTS_PER_SEC 1000 - -/* - * threshold for copying small receive frames - * set to 0 to avoid copying, set to 9001 to copy all frames - */ -#define SK_COPY_THRESHOLD 50 - -/* number of adapters that can be configured via command line params */ -#define SK_MAX_CARD_PARAM 16 - - -/* - * use those defines for a compile-in version of the driver instead - * of command line parameters - */ -/* #define LINK_SPEED_A {"Auto", } */ -/* #define LINK_SPEED_B {"Auto", } */ -/* #define AUTO_NEG_A {"Sense", } */ -/* #define AUTO_NEG_B {"Sense", } */ -/* #define DUP_CAP_A {"Both", } */ -/* #define DUP_CAP_B {"Both", } */ -/* #define FLOW_CTRL_A {"SymOrRem", } */ -/* #define FLOW_CTRL_B {"SymOrRem", } */ -/* #define ROLE_A {"Auto", } */ -/* #define ROLE_B {"Auto", } */ -/* #define PREF_PORT {"A", } */ -/* #define RLMT_MODE {"CheckLinkState", } */ - -#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) -#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb) -#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb) - -/* function prototypes ******************************************************/ static void FreeResources(struct SK_NET_DEVICE *dev); static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC); static SK_BOOL BoardAllocMem(SK_AC *pAC); static void BoardFreeMem(SK_AC *pAC); static void BoardInitMem(SK_AC *pAC); -static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, - int*, SK_BOOL); - -#if 0 -static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); -static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); +static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, int*, SK_BOOL); +#if 0 /* uboot */ +static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); +static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); static int SkGeOpen(struct SK_NET_DEVICE *dev); static int SkGeClose(struct SK_NET_DEVICE *dev); static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); @@ -421,439 +138,1368 @@ static void SkGeSetRxMode(struct SK_NET_DEVICE *dev); static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev); static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd); #else -void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); -void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); +SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); +SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); int SkGeOpen(struct SK_NET_DEVICE *dev); int SkGeClose(struct SK_NET_DEVICE *dev); int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); #endif static void GetConfiguration(SK_AC*); +#if 0 /* uboot */ static void ProductStr(SK_AC*); +#endif static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*); static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*); static void FillRxRing(SK_AC*, RX_PORT*); static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*); -#if 0 +#ifdef CONFIG_SK98LIN_NAPI +static int SkGePoll(struct net_device *dev, int *budget); +static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL, int*, int); +#else +#if 0 /* uboot */ static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); #else void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); #endif -static void ClearAndStartRx(SK_AC*, int); -static void ClearTxIrq(SK_AC*, int, int); +#endif +#ifdef SK_POLL_CONTROLLER +static void SkGeNetPoll(struct SK_NET_DEVICE *dev); +#endif static void ClearRxRing(SK_AC*, RX_PORT*); static void ClearTxRing(SK_AC*, TX_PORT*); -#if 0 -static void SetQueueSizes(SK_AC *pAC); - +#if 0 /* uboot */ static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu); #endif static void PortReInitBmu(SK_AC*, int); -#if 0 +#if 0 /* uboot */ static int SkGeIocMib(DEV_NET*, unsigned int, int); +static int SkGeInitPCI(SK_AC *pAC); +static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName); +#endif +static int SkDrvInitAdapter(SK_AC *pAC, int devNbr); +static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr); +extern void SkLocalEventQueue( SK_AC *pAC, + SK_U32 Class, + SK_U32 Event, + SK_U32 Param1, + SK_U32 Param2, + SK_BOOL Flag); +extern void SkLocalEventQueue64( SK_AC *pAC, + SK_U32 Class, + SK_U32 Event, + SK_U64 Param, + SK_BOOL Flag); +#if 0 /* uboot */ static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*); #endif -/*Extern */ +/******************************************************************************* + * + * Extern Function Prototypes + * + ******************************************************************************/ -/* external Proc function */ -extern int proc_read( - char *buffer, - char **buffer_location, - off_t offset, - int buffer_length, - int *eof, - void *data); +extern SK_BOOL SkY2AllocateResources(SK_AC *pAC); +extern void SkY2FreeResources(SK_AC *pAC); +extern void SkY2AllocateRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port); +extern void SkY2FreeRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port); +extern void SkY2FreeTxBuffers(SK_AC *pAC,SK_IOC IoC,int Port); +extern SkIsrRetVar SkY2Isr(int irq,void *dev_id,struct pt_regs *ptregs); +extern int SkY2Xmit(struct sk_buff *skb,struct SK_NET_DEVICE *dev); +extern void SkY2PortStop(SK_AC *pAC,SK_IOC IoC,int Port,int Dir,int RstMode); +extern void SkY2PortStart(SK_AC *pAC,SK_IOC IoC,int Port); +extern int SkY2RlmtSend(SK_AC *pAC,int PortNr,struct sk_buff *pMessage); +extern void SkY2RestartStatusUnit(SK_AC *pAC); +extern void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port); +#ifdef CONFIG_SK98LIN_NAPI +extern int SkY2Poll(struct net_device *dev, int *budget); +#endif + +extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); +extern void SkDimStartModerationTimer(SK_AC *pAC); +extern void SkDimModerate(SK_AC *pAC); + + +#if 0/* uboot */ +extern int SkEthIoctl(struct net_device *netdev, struct ifreq *ifr); +#endif + +#ifdef CONFIG_PROC_FS +static const char SK_Root_Dir_entry[] = "sk98lin"; +static struct proc_dir_entry *pSkRootDir; +extern struct file_operations sk_proc_fops; +#endif #ifdef DEBUG static void DumpMsg(struct sk_buff*, char*); static void DumpData(char*, int); static void DumpLong(char*, int); #endif -void dump_frag( SK_U8 *data, int length); /* global variables *********************************************************/ -#if 0 +#if 0 /* uboot */ static const char *BootString = BOOT_STRING; #endif struct SK_NET_DEVICE *SkGeRootDev = NULL; -static int probed __initdata = 0; +static SK_BOOL DoPrintInterfaceChange = SK_TRUE; /* local variables **********************************************************/ static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; +#if 0 /* uboot */ +static int sk98lin_max_boards_found = 0; +#endif - -/* local variables **********************************************************/ -const char SK_Root_Dir_entry[8]; - -#if 0 +#ifdef CONFIG_PROC_FS static struct proc_dir_entry *pSkRootDir; #endif -static struct pci_device_id supported[] = { - {PCI_VENDOR_ID_3COM, 0x1700}, - {PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE}, - {PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU}, - {} + + +#if 0 /* uboot */ +static struct pci_device_id sk98lin_pci_tbl[] __devinitdata = { +/* { pci_vendor_id, pci_device_id, * SAMPLE ENTRY! * + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, */ + { 0x10b7, 0x1700, /* 3Com (10b7), Gigabit Ethernet Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x10b7, 0x80eb, /* 3Com (10b7), 3Com 3C940B Gigabit LOM Ethernet Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1148, 0x4300, /* SysKonnect (1148), SK-98xx Gigabit Ethernet Server Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1148, 0x4320, /* SysKonnect (1148), SK-98xx V2.0 Gigabit Ethernet Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1148, 0x9000, /* SysKonnect (1148), SK-9Sxx 10/100/1000Base-T Server Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1148, 0x9E00, /* SysKonnect (1148), SK-9Exx 10/100/1000Base-T Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1186, 0x4b00, /* D-Link (1186), Gigabit Ethernet Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1186, 0x4b01, /* D-Link (1186), Gigabit Ethernet Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1186, 0x4b02, /* D-Link (1186), Gigabit Ethernet Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1186, 0x4c00, /* D-Link (1186), Gigabit Ethernet Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4320, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4340, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4341, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4342, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4343, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4344, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4345, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4346, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4347, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4350, /* Marvell (11ab), Fast Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4351, /* Marvell (11ab), Fast Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4352, /* Marvell (11ab), Fast Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4356, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4360, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4361, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4362, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4363, /* Marvell (11ab), Marvell */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4364, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4366, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4367, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x4368, /* Marvell (11ab), Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x11ab, 0x5005, /* Marvell (11ab), Belkin */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1371, 0x434e, /* CNet (1371), GigaCard Network Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1737, 0x1032, /* Linksys (1737), Gigabit Network Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0x1737, 0x1064, /* Linksys (1737), Gigabit Network Adapter */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, sk98lin_pci_tbl); + +static struct pci_driver sk98lin_driver = { + .name = DRIVER_FILE_NAME, + .id_table = sk98lin_pci_tbl, + .probe = sk98lin_init_device, + .remove = __devexit_p(sk98lin_remove_device), +#ifdef CONFIG_PM + .suspend = sk98lin_suspend, + .resume = sk98lin_resume +#endif }; +#else + +static struct pci_device_id supported[] = { +/* { pci_vendor_id, pci_device_id, * SAMPLE ENTRY! * + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, */ + { 0x10b7, 0x1700, /* 3Com (10b7), Gigabit Ethernet Adapter */}, + { 0x1148, 0x4300, /* SysKonnect (1148), SK-98xx Gigabit Ethernet Server Adapter */}, + { 0x1148, 0x4320, /* SysKonnect (1148), SK-98xx V2.0 Gigabit Ethernet Adapter */}, + { 0x1148, 0x4340, /* SysKonnect (1148), SK-9Sxx 10/100/1000Base-T Server Adapter */}, + { 0x1148, 0x9000, /* SysKonnect (1148), SK-9Sxx 10/100/1000Base-T Server Adapter */}, + { 0x1148, 0x9E00, /* SysKonnect (1148), SK-9Exx 10/100/1000Base-T Adapter */}, + { 0x1186, 0x4c00, /* D-Link (1186), Gigabit Ethernet Adapter */}, + { 0x11ab, 0x4320, /* Marvell (11ab), Gigabit Ethernet Controller */}, + { 0x11ab, 0x4350, /* Marvell (11ab), Fast Ethernet Controller */}, + { 0x11ab, 0x4351, /* Marvell (11ab), Fast Ethernet Controller */}, + { 0x11ab, 0x4360, /* Marvell (11ab), Gigabit Ethernet Controller */}, + { 0x11ab, 0x4361, /* Marvell (11ab), Gigabit Ethernet Controller */}, + { 0x11ab, 0x4362, /* Marvell (11ab), Gigabit Ethernet Controller */}, + { 0x11ab, 0x4363, /* Marvell (11ab), Gigabit Ethernet Controller */}, + { 0x11ab, 0x5005, /* Marvell (11ab), Belkin */}, + { 0x1371, 0x434e, /* CNet (1371), GigaCard Network Adapter */}, + { 0x1737, 0x1032, /* Linksys (1737), Gigabit Network Adapter */}, + { 0x1737, 0x1064, /* Linksys (1737), Gigabit Network Adapter */}, + { } +}; + +#endif + +#if 0 /***************************************************************************** * - * skge_probe - find all SK-98xx adapters + * sk98lin_init_device - initialize the adapter * * Description: - * This function scans the PCI bus for SK-98xx adapters. Resources for - * each adapter are allocated and the adapter is brought into Init 1 + * This function initializes the adapter. Resources for + * the adapter are allocated and the adapter is brought into Init 1 * state. * * Returns: * 0, if everything is ok * !=0, on error */ -#if 0 -static int __init skge_probe (void) -#else -int skge_probe (struct eth_device ** ret_dev) -#endif +static int __devinit sk98lin_init_device(struct pci_dev *pdev, + const struct pci_device_id *ent) + { -#if 0 - int proc_root_initialized = 0; -#endif - int boards_found = 0; -#if 0 - int vendor_flag = SK_FALSE; -#endif + static SK_BOOL sk98lin_boot_string = SK_FALSE; + static SK_BOOL sk98lin_proc_entry = SK_FALSE; + static int sk98lin_boards_found = 0; SK_AC *pAC; DEV_NET *pNet = NULL; -#if 0 - struct proc_dir_entry *pProcFile; - struct pci_dev *pdev = NULL; - unsigned long base_address; -#else - u32 base_address; -#endif struct SK_NET_DEVICE *dev = NULL; -#if 0 - SK_BOOL DeviceFound = SK_FALSE; + int retval; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *pProcFile; #endif - SK_BOOL BootStringCount = SK_FALSE; -#if 1 - pci_dev_t devno; + int pci_using_dac; + +#if 0 /* uboot */ + retval = pci_enable_device(pdev); + if (retval) { + printk(KERN_ERR "Cannot enable PCI device, " + "aborting.\n"); + return retval; + } #endif - if (probed) + dev = NULL; + pNet = NULL; + + + /* INSERT * We have to find the power-management capabilities */ + /* Find power-management capability. */ + + pci_using_dac = 0; /* Set 32 bit DMA per default */ + /* Configure DMA attributes. */ + retval = pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL); + if (!retval) { + pci_using_dac = 1; + } else { + retval = pci_set_dma_mask(pdev, (u64) 0xffffffff); + if (retval) { + printk(KERN_ERR "No usable DMA configuration, " + "aborting.\n"); + return retval; + } + } + + + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { + printk(KERN_ERR "Unable to allocate etherdev " + "structure!\n"); return -ENODEV; - probed++; + } - if (!pci_present()) /* is PCI support present? */ + pNet = dev->priv; + pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); + if (pNet->pAC == NULL){ + free_netdev(dev); + printk(KERN_ERR "Unable to allocate adapter " + "structure!\n"); return -ENODEV; + } -#if 0 - while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) -#else - while((devno = pci_find_devices (supported, boards_found)) >= 0) + + /* Print message */ + if (!sk98lin_boot_string) { + /* set display flag to TRUE so that */ + /* we only display this string ONCE */ + sk98lin_boot_string = SK_TRUE; + printk("%s\n", BootString); + } + + memset(pNet->pAC, 0, sizeof(SK_AC)); + pAC = pNet->pAC; + pAC->PciDev = pdev; + pAC->PciDevId = pdev->device; + pAC->dev[0] = dev; + pAC->dev[1] = dev; + sprintf(pAC->Name, "SysKonnect SK-98xx"); + pAC->CheckQueue = SK_FALSE; + + dev->irq = pdev->irq; + retval = SkGeInitPCI(pAC); + if (retval) { + printk("SKGE: PCI setup failed: %i\n", retval); + free_netdev(dev); + return -ENODEV; + } + + SET_MODULE_OWNER(dev); + + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + dev->flags &= ~IFF_RUNNING; +#ifdef SK_POLL_CONTROLLER + dev->poll_controller = SkGeNetPoll; #endif - { + SET_NETDEV_DEV(dev, &pdev->dev); - dev = NULL; - pNet = NULL; + pAC->Index = sk98lin_boards_found; + if (SkGeBoardInit(dev, pAC)) { + free_netdev(dev); + return -ENODEV; + } else { + ProductStr(pAC); + } -#if 0 - SK_PCI_ISCOMPLIANT(vendor_flag, pdev); - if (!vendor_flag) - continue; + if (pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; + + /* shifter to later moment in time... */ + if (CHIP_ID_YUKON_2(pAC)) { + dev->hard_start_xmit = &SkY2Xmit; +#ifdef CONFIG_SK98LIN_NAPI + dev->poll = &SkY2Poll; + dev->weight = 64; #endif - -/* if ((pdev->vendor != PCI_VENDOR_ID_SYSKONNECT) && - ((pdev->device != PCI_DEVICE_ID_SYSKONNECT_GE) || - (pdev->device != PCI_DEVICE_ID_SYSKONNECT_YU))){ - continue; - } -*/ -#if 0 - /* Configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) && - pci_set_dma_mask(pdev, (u64) 0xffffffff)) - continue; -#endif - - -#if 0 - if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } -#else - dev = malloc (sizeof *dev); - memset(dev, 0, sizeof(*dev)); - dev->priv = malloc(sizeof(DEV_NET)); -#endif - - if (dev->priv == NULL) { - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - - pNet = dev->priv; - pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); - if (pNet->pAC == NULL){ - kfree(dev->priv); - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } - - /* Print message */ - if (!BootStringCount) { - /* set display flag to TRUE so that */ - /* we only display this string ONCE */ - BootStringCount = SK_TRUE; -#ifdef SK98_INFO - printk("%s\n", BootString); -#endif - } - - memset(pNet->pAC, 0, sizeof(SK_AC)); - pAC = pNet->pAC; -#if 0 - pAC->PciDev = pdev; - pAC->PciDevId = pdev->device; - pAC->dev[0] = dev; - pAC->dev[1] = dev; -#else - pAC->PciDev = devno; - ret_dev[0] = pAC->dev[0] = dev; - ret_dev[1] = pAC->dev[1] = dev; -#endif - sprintf(pAC->Name, "SysKonnect SK-98xx"); - pAC->CheckQueue = SK_FALSE; - - pNet->Mtu = 1500; - pNet->Up = 0; -#if 0 - dev->irq = pdev->irq; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; + } else { dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; -#endif - -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* Use only if yukon hardware */ - /* SK and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif - -#if 0 - /* - * Dummy value. - */ - dev->base_addr = 42; - pci_set_master(pdev); - - pci_set_master(pdev); - base_address = pci_resource_start (pdev, 0); -#else - pci_write_config_dword(devno, - PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, - &base_address); -#endif - -#ifdef SK_BIG_ENDIAN - /* - * On big endian machines, we use the adapter's aibility of - * reading the descriptors as big endian. - */ - { - SK_U32 our2; - SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); - our2 |= PCI_REV_DESC; - SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); - } -#endif - - /* - * Remap the regs into kernel space. - */ -#if 0 - pAC->IoBase = (char*)ioremap(base_address, 0x4000); -#else - pAC->IoBase = (char*)pci_mem_to_phys(devno, base_address); -#endif - - if (!pAC->IoBase){ - printk(KERN_ERR "%s: Unable to map I/O register, " - "SK 98xx No. %i will be disabled.\n", - dev->name, boards_found); - kfree(dev); - break; - } - - pAC->Index = boards_found; - if (SkGeBoardInit(dev, pAC)) { - FreeResources(dev); - kfree(dev); - continue; - } - -#if 0 - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); -#else - memcpy((caddr_t) &dev->enetaddr, - (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); -#endif - -#if 0 - /* First adapter... Create proc and print message */ - if (!DeviceFound) { - DeviceFound = SK_TRUE; - SK_MEMCPY(&SK_Root_Dir_entry, BootString, - sizeof(SK_Root_Dir_entry) - 1); - - /*Create proc (directory)*/ - if(!proc_root_initialized) { - pSkRootDir = create_proc_entry(SK_Root_Dir_entry, - S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net); - proc_root_initialized = 1; - } - - pSkRootDir->owner = THIS_MODULE; - } - - - /* Create proc file */ - pProcFile = create_proc_entry(dev->name, - S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, - pSkRootDir); - - - pProcFile->read_proc = proc_read; - pProcFile->write_proc = NULL; - pProcFile->nlink = 1; - pProcFile->size = sizeof(dev->name + 1); - pProcFile->data = (void *)pProcFile; -#endif - - pNet->PortNr = 0; - pNet->NetNr = 0; - -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif - - boards_found++; - - /* More then one port found */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { -#if 0 - if ((dev = init_etherdev(NULL, sizeof(DEV_NET))) == 0) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } -#else - dev = malloc (sizeof *dev); - memset(dev, 0, sizeof(*dev)); - dev->priv = malloc(sizeof(DEV_NET)); -#endif - - pAC->dev[1] = dev; - pNet = dev->priv; - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - pNet->Mtu = 1500; - pNet->Up = 0; - -#if 0 - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; -#endif - -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif - -#if 0 - pProcFile = create_proc_entry(dev->name, - S_IFREG | S_IXUSR | S_IWGRP | S_IROTH, - pSkRootDir); - - - pProcFile->read_proc = proc_read; - pProcFile->write_proc = NULL; - pProcFile->nlink = 1; - pProcFile->size = sizeof(dev->name + 1); - pProcFile->data = (void *)pProcFile; -#endif - -#if 0 - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); -#else - memcpy((caddr_t) &dev->enetaddr, - (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); -#endif - - printk("%s: %s\n", dev->name, pAC->DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - - } - - - /* Save the hardware revision */ - pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + - (pAC->GIni.GIPciHwRev & 0x0F); - - /* - * This is bollocks, but we need to tell the net-init - * code that it shall go for the next device. - */ -#if 0 -#ifndef MODULE - dev->base_addr = 0; -#endif +#ifdef CONFIG_SK98LIN_NAPI + dev->poll = &SkGePoll; + dev->weight = 64; #endif } - /* - * If we're at this point we're going through skge_probe() for - * the first time. Return success (0) if we've initialized 1 - * or more boards. Otherwise, return failure (-ENODEV). - */ +#ifdef NETIF_F_TSO +#ifdef USE_SK_TSO_FEATURE + if ((CHIP_ID_YUKON_2(pAC)) && + (pAC->GIni.GIChipId != CHIP_ID_YUKON_EC_U)) { + dev->features |= NETIF_F_TSO; + } +#endif +#endif +#ifdef CONFIG_SK98LIN_ZEROCOPY + if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) + dev->features |= NETIF_F_SG; +#endif +#ifdef USE_SK_TX_CHECKSUM + if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) + dev->features |= NETIF_F_IP_CSUM; +#endif +#ifdef USE_SK_RX_CHECKSUM + pAC->RxPort[0].UseRxCsum = SK_TRUE; + if (pAC->GIni.GIMacsFound == 2 ) { + pAC->RxPort[1].UseRxCsum = SK_TRUE; + } +#endif - return boards_found; + /* Save the hardware revision */ + pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + + (pAC->GIni.GIPciHwRev & 0x0F); + + /* Set driver globals */ + pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; + pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; + + SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); + SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), + sizeof(SK_PNMI_STRUCT_DATA)); + + /* Register net device */ + retval = register_netdev(dev); + if (retval) { + printk(KERN_ERR "SKGE: Could not register device.\n"); + FreeResources(dev); + free_netdev(dev); + return retval; + } + + /* Save initial device name */ + strcpy(pNet->InitialDevName, dev->name); + + /* Set network to off */ + netif_stop_queue(dev); + netif_carrier_off(dev); + + /* Print adapter specific string from vpd and config settings */ + printk("%s: %s\n", pNet->InitialDevName, pAC->DeviceStr); + printk(" PrefPort:%c RlmtMode:%s\n", + 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, + (pAC->RlmtMode==0) ? "Check Link State" : + ((pAC->RlmtMode==1) ? "Check Link State" : + ((pAC->RlmtMode==3) ? "Check Local Port" : + ((pAC->RlmtMode==7) ? "Check Segmentation" : + ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); + + SkGeYellowLED(pAC, pAC->IoBase, 1); + + memcpy((caddr_t) &dev->dev_addr, + (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); + + /* First adapter... Create proc and print message */ +#ifdef CONFIG_PROC_FS + if (!sk98lin_proc_entry) { + sk98lin_proc_entry = SK_TRUE; + SK_MEMCPY(&SK_Root_Dir_entry, BootString, + sizeof(SK_Root_Dir_entry) - 1); + + /*Create proc (directory)*/ + if(!pSkRootDir) { + pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net); + if (!pSkRootDir) { + printk(KERN_WARNING "%s: Unable to create /proc/net/%s", + dev->name, SK_Root_Dir_entry); + } else { + pSkRootDir->owner = THIS_MODULE; + } + } + } + + /* Create proc file */ + if (pSkRootDir && + (pProcFile = create_proc_entry(pNet->InitialDevName, S_IRUGO, + pSkRootDir))) { + pProcFile->proc_fops = &sk_proc_fops; + pProcFile->data = dev; + } + +#endif + + pNet->PortNr = 0; + pNet->NetNr = 0; + + sk98lin_boards_found++; + pci_set_drvdata(pdev, dev); + + /* More then one port found */ + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { + if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) { + printk(KERN_ERR "Unable to allocate etherdev " + "structure!\n"); + return -ENODEV; + } + + pAC->dev[1] = dev; + pNet = dev->priv; + pNet->PortNr = 1; + pNet->NetNr = 1; + pNet->pAC = pAC; + + if (CHIP_ID_YUKON_2(pAC)) { + dev->hard_start_xmit = &SkY2Xmit; +#ifdef CONFIG_SK98LIN_NAPI + dev->poll = &SkY2Poll; + dev->weight = 64; +#endif + } else { + dev->hard_start_xmit = &SkGeXmit; +#ifdef CONFIG_SK98LIN_NAPI + dev->poll = &SkGePoll; + dev->weight = 64; +#endif + } + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + dev->flags &= ~IFF_RUNNING; +#ifdef SK_POLL_CONTROLLER + dev->poll_controller = SkGeNetPoll; +#endif + +#ifdef NETIF_F_TSO +#ifdef USE_SK_TSO_FEATURE + if ((CHIP_ID_YUKON_2(pAC)) && + (pAC->GIni.GIChipId != CHIP_ID_YUKON_EC_U)) { + dev->features |= NETIF_F_TSO; + } +#endif +#endif +#ifdef CONFIG_SK98LIN_ZEROCOPY + /* Don't handle if Genesis chipset */ + if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) + dev->features |= NETIF_F_SG; +#endif +#ifdef USE_SK_TX_CHECKSUM + /* Don't handle if Genesis chipset */ + if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) + dev->features |= NETIF_F_IP_CSUM; +#endif + + if (register_netdev(dev)) { + printk(KERN_ERR "SKGE: Could not register device.\n"); + free_netdev(dev); + pAC->dev[1] = pAC->dev[0]; + } else { + + /* Save initial device name */ + strcpy(pNet->InitialDevName, dev->name); + + /* Set network to off */ + netif_stop_queue(dev); + netif_carrier_off(dev); + + +#ifdef CONFIG_PROC_FS + if (pSkRootDir + && (pProcFile = create_proc_entry(pNet->InitialDevName, + S_IRUGO, pSkRootDir))) { + pProcFile->proc_fops = &sk_proc_fops; + pProcFile->data = dev; + } +#endif + + memcpy((caddr_t) &dev->dev_addr, + (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); + + printk("%s: %s\n", pNet->InitialDevName, pAC->DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); + } + } + + pAC->Index = sk98lin_boards_found; + sk98lin_max_boards_found = sk98lin_boards_found; + return 0; +} + + + +/***************************************************************************** + * + * SkGeInitPCI - Init the PCI resources + * + * Description: + * This function initialize the PCI resources and IO + * + * Returns: N/A + * + */ +int SkGeInitPCI(SK_AC *pAC) +{ + struct SK_NET_DEVICE *dev = pAC->dev[0]; + struct pci_dev *pdev = pAC->PciDev; + int retval; + + if (pci_enable_device(pdev) != 0) { + return 1; + } + + dev->mem_start = pci_resource_start (pdev, 0); + pci_set_master(pdev); + + if (pci_request_regions(pdev, DRIVER_FILE_NAME) != 0) { + retval = 2; + goto out_disable; + } + +#if defined (SK_BIG_ENDIAN) + + /* + * On big endian machines, we use the adapter's aibility of + * reading the descriptors as big endian. + */ + if (CHIP_ID_YUKON_2(pAC)) + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 |= PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } + else + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 |= PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } +#else + + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 &= ~PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } + + +#endif + + /* + * Remap the regs into kernel space. + */ + pAC->IoBase = (char*)ioremap_nocache(dev->mem_start, 0x4000); + + if (!pAC->IoBase){ + retval = 3; + goto out_release; + } + + return 0; + + out_release: + pci_release_regions(pdev); + out_disable: + pci_disable_device(pdev); + return retval; +} + +#else +/***************************************************************************** + * + * skge_probe - find all SK-98xx adapters + * + * Description: + * This function scans the PCI bus for SK-98xx adapters. Resources for + * each adapter are allocated and the adapter is brought into Init 1 + * state. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +static int probed __initdata = 0; + +int skge_probe (struct eth_device ** ret_dev) +{ + int boards_found = 0; + SK_AC *pAC; + DEV_NET *pNet = NULL; + u32 base_address; + struct SK_NET_DEVICE *dev = NULL; + SK_BOOL BootStringCount = SK_FALSE; + pci_dev_t devno; + + if (probed) + return -ENODEV; + probed++; + + if (!pci_present()) /* is PCI support present? */ + return -ENODEV; + + while(1) + { + if((devno = pci_find_devices (supported, boards_found)) < 0) { + break; + } + + + dev = NULL; + pNet = NULL; + + + dev = malloc (sizeof (struct SK_NET_DEVICE)); + memset(dev, 0, sizeof(struct SK_NET_DEVICE)); + dev->priv = malloc(sizeof(DEV_NET)); + + if (dev->priv == NULL) { + printk(KERN_ERR "Unable to allocate adapter " + "structure!\n"); + break; + } + + pNet = dev->priv; + pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); + if (pNet->pAC == NULL){ + kfree(dev->priv); + printf("kfree: dev->priv1=0x%x\n",dev->priv); + printk(KERN_ERR "Unable to allocate adapter " + "structure!\n"); + + #if 1 /* Marvell - uboot */ + return -ENODEV; + #endif + /*break;*/ + } + + /* Print message */ + if (!BootStringCount) { + /* set display flag to TRUE so that */ + /* we only display this string ONCE */ + BootStringCount = SK_TRUE; +#ifdef SK98_INFO + printk("%s\n", BootString); +#endif + } + + memset(pNet->pAC, 0, sizeof(SK_AC)); + pAC = pNet->pAC; + pAC->PciDev = devno; + ret_dev[boards_found] = pAC->dev[0] = dev; + sprintf(pAC->Name, "SysKonnect SK-98xx"); + pAC->CheckQueue = SK_FALSE; + + pNet->Mtu = 1500; + pNet->Up = 0; + +#ifdef SK_ZEROCOPY + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + /* Use only if yukon hardware */ + /* SK and ZEROCOPY - fly baby... */ + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + } +#endif + + pci_write_config_dword(devno, + PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, + &base_address); + + + /* + * Remap the regs into kernel space. + */ + pAC->IoBase =((char*)pci_mem_to_phys(devno, base_address)); + + #if 1/* Marvell - uboot : make it aligned */ + pAC->IoBase = (SK_IOC)((unsigned int)pAC->IoBase & 0xFFFFFFF0); + #endif + + + + if (!pAC->IoBase){ + printk(KERN_ERR "%s: Unable to map I/O register, " + "SK 98xx No. %i will be disabled.\n", + dev->name, boards_found); + kfree(dev); + printf("kfree: dev3=0x%x\n",dev); + break; + } + + + + pAC->Index = boards_found; + if (SkGeBoardInit(dev, pAC)) { + FreeResources(dev); + kfree(dev); + printf("kfree: dev4=0x%x\n",dev); + continue; + } + + + memcpy((caddr_t) &dev->enetaddr, + (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); + + + + + pNet->PortNr = 0; + pNet->NetNr = 0; + + boards_found++; + + /* More then one port found */ + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { + printk(" NEVER TESTED \n"); + dev = malloc (sizeof(struct SK_NET_DEVICE)); + memcpy(dev, pAC->dev[0], sizeof(struct SK_NET_DEVICE)); + dev->priv = malloc(sizeof(DEV_NET)); + memcpy(dev->priv, pAC->dev[0]->priv, sizeof(DEV_NET)); + + ret_dev[1] = pAC->dev[1] = dev; + boards_found++; + + pNet = dev->priv; + pNet->PortNr = 1; + pNet->NetNr = 1; + pNet->pAC = pAC; + pNet->Mtu = 1500; + pNet->Up = 0; + + memcpy((caddr_t) &dev->enetaddr, + (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); + + printk("%s: %s\n", dev->name, pAC->DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); + + } + + + + + + /* Save the hardware revision */ + pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + + (pAC->GIni.GIPciHwRev & 0x0F); +#if 0 + + printk(" PrefPort:%c RlmtMode:%s\n", + 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, + (pAC->RlmtMode==0) ? "Check Link State" : + ((pAC->RlmtMode==1) ? "Check Link State" : + ((pAC->RlmtMode==3) ? "Check Local Port" : + ((pAC->RlmtMode==7) ? "Check Segmentation" : + ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); + + SkGeYellowLED(pAC, pAC->IoBase, 1); +#endif + +#if defined (SK_BIG_ENDIAN) + + /* + * On big endian machines, we use the adapter's aibility of + * reading the descriptors as big endian. + */ + if (CHIP_ID_YUKON_2(pAC)) + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 |= PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } + else + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 |= PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } +#else + + { + SK_U32 our2; + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 &= ~PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } + + +#endif + + + } + + + + /* + * If we're at this point we're going through skge_probe() for + * the first time. Return success (0) if we've initialized 1 + * or more boards. Otherwise, return failure (-ENODEV). + */ + + return boards_found; } /* skge_probe */ +#endif + +#ifdef Y2_RECOVERY +/***************************************************************************** + * + * SkGeHandleKernelTimer - Handle the kernel timer requests + * + * Description: + * If the requested time interval for the timer has elapsed, + * this function checks the link state. + * + * Returns: N/A + * + */ +static void SkGeHandleKernelTimer( +unsigned long ptr) /* holds the pointer to adapter control context */ +{ + DEV_NET *pNet = (DEV_NET*) ptr; + SkGeCheckTimer(pNet); +} + +/***************************************************************************** + * + * sk98lin_check_timer - Resume the the card + * + * Description: + * This function checks the kernel timer + * + * Returns: N/A + * + */ +void SkGeCheckTimer( +DEV_NET *pNet) /* holds the pointer to adapter control context */ +{ + SK_AC *pAC = pNet->pAC; + SK_BOOL StartTimer = SK_TRUE; + + if (pNet->InRecover) + return; + if (pNet->TimerExpired) + return; + pNet->TimerExpired = SK_TRUE; + +#define TXPORT pAC->TxPort[pNet->PortNr][TX_PRIO_LOW] +#define RXPORT pAC->RxPort[pNet->PortNr] + + if ( (CHIP_ID_YUKON_2(pAC)) && + (netif_running(pAC->dev[pNet->PortNr]))) { + +#ifdef Y2_RX_CHECK + if (HW_FEATURE(pAC, HWF_WA_DEV_4167)) { + /* Checks the RX path */ + CheckRxPath(pNet); + } +#endif + + /* Checkthe transmitter */ + if (!(IS_Q_EMPTY(&TXPORT.TxAQ_working))) { + if (TXPORT.LastDone != TXPORT.TxALET.Done) { + TXPORT.LastDone = TXPORT.TxALET.Done; + pNet->TransmitTimeoutTimer = 0; + } else { + pNet->TransmitTimeoutTimer++; + if (pNet->TransmitTimeoutTimer >= 10) { + pNet->TransmitTimeoutTimer = 0; +#ifdef CHECK_TRANSMIT_TIMEOUT + StartTimer = SK_FALSE; + SkLocalEventQueue(pAC, SKGE_DRV, + SK_DRV_RECOVER,pNet->PortNr,-1,SK_FALSE); +#endif + } + } + } + +#ifdef CHECK_TRANSMIT_TIMEOUT +// if (!timer_pending(&pNet->KernelTimer)) { +#if 0 //u-boot + pNet->KernelTimer.expires = jiffies + (HZ/4); /* 100ms */ + add_timer(&pNet->KernelTimer); +#endif + pNet->TimerExpired = SK_FALSE; + +// } +#endif + } +} + + +/***************************************************************************** +* +* CheckRXCounters - Checks the the statistics for RX path hang +* +* Description: +* This function is called periodical by a timer. +* +* Notes: +* +* Function Parameters: +* +* Returns: +* Traffic status +* +*/ +static SK_BOOL CheckRXCounters( +DEV_NET *pNet) /* holds the pointer to adapter control context */ +{ +#if 0 // u-boot + SK_AC *pAC = pNet->pAC; +#endif + SK_BOOL bStatus = SK_FALSE; + + /* Variable used to store the MAC RX FIFO RP, RPLev*/ + SK_U32 MACFifoRP = 0; + SK_U32 MACFifoRLev = 0; + + /* Variable used to store the PCI RX FIFO RP, RPLev*/ + SK_U32 RXFifoRP = 0; + SK_U8 RXFifoRLev = 0; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> CheckRXCounters()\n")); + + /*Check if statistic counters hangs*/ +#if 0 // u-boot + if (pNet->LastJiffies == pAC->dev[pNet->PortNr]->last_rx) { + /* Now read the values of read pointer/level from MAC RX FIFO again */ + SK_IN32(pAC->IoBase, MR_ADDR(pNet->PortNr, RX_GMF_RP), &MACFifoRP); + SK_IN32(pAC->IoBase, MR_ADDR(pNet->PortNr, RX_GMF_RLEV), &MACFifoRLev); + + /* Now read the values of read pointer/level from RX FIFO again */ + SK_IN8(pAC->IoBase, Q_ADDR(pAC->GIni.GP[pNet->PortNr].PRxQOff, Q_RX_RP), &RXFifoRP); + SK_IN8(pAC->IoBase, Q_ADDR(pAC->GIni.GP[pNet->PortNr].PRxQOff, Q_RX_RL), &RXFifoRLev); + + /* Check if the MAC RX hang */ + if ((MACFifoRP == pNet->PreviousMACFifoRP) && + (pNet->PreviousMACFifoRP != 0) && + (MACFifoRLev >= pNet->PreviousMACFifoRLev)){ + bStatus = SK_TRUE; + } + + /* Check if the PCI RX hang */ + if ((RXFifoRP == pNet->PreviousRXFifoRP) && + (pNet->PreviousRXFifoRP != 0) && + (RXFifoRLev >= pNet->PreviousRXFifoRLev)){ + /*Set the flag to indicate that the RX FIFO hangs*/ + bStatus = SK_TRUE; + } + } + + /* Store now the values of counters for next check */ + pNet->LastJiffies = pAC->dev[pNet->PortNr]->last_rx; +#endif + + + /* Store the values of read pointer/level from MAC RX FIFO for next test */ + pNet->PreviousMACFifoRP = MACFifoRP; + pNet->PreviousMACFifoRLev = MACFifoRLev; + + /* Store the values of read pointer/level from RX FIFO for next test */ + pNet->PreviousRXFifoRP = RXFifoRP; + pNet->PreviousRXFifoRLev = RXFifoRLev; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== CheckRXCounters()\n")); + + return bStatus; +} + +/***************************************************************************** +* +* CheckRxPath - Checks if the RX path +* +* Description: +* This function is called periodical by a timer. +* +* Notes: +* +* Function Parameters: +* +* Returns: +* None. +* +*/ +static void CheckRxPath( +DEV_NET *pNet) /* holds the pointer to adapter control context */ +{ + unsigned long Flags; /* for the spin locks */ + /* Initialize the pAC structure.*/ + SK_AC *pAC = pNet->pAC; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> CheckRxPath()\n")); + + /*If the statistics are not changed then could be an RX problem */ + if (CheckRXCounters(pNet)){ + /* + * First we try the simple solution by resetting the Level Timer + */ + + /* Stop Level Timer of Status BMU */ + SK_OUT8(pAC->IoBase, STAT_LEV_TIMER_CTRL, TIM_STOP); + + /* Start Level Timer of Status BMU */ + SK_OUT8(pAC->IoBase, STAT_LEV_TIMER_CTRL, TIM_START); + + if (!CheckRXCounters(pNet)) { + return; + } + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + SkLocalEventQueue(pAC, SKGE_DRV, + SK_DRV_RECOVER,pNet->PortNr,-1,SK_TRUE); + + /* Reset the fifo counters */ + pNet->PreviousMACFifoRP = 0; + pNet->PreviousMACFifoRLev = 0; + pNet->PreviousRXFifoRP = 0; + pNet->PreviousRXFifoRLev = 0; + + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== CheckRxPath()\n")); +} + + + +#endif + + +#ifdef CONFIG_PM +/***************************************************************************** + * + * sk98lin_resume - Resume the the card + * + * Description: + * This function resumes the card into the D0 state + * + * Returns: N/A + * + */ +static int sk98lin_resume( +struct pci_dev *pdev) /* the device that is to resume */ +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + SK_U16 PmCtlSts; + + /* Set the power state to D0 */ + pci_set_power_state(pdev, 0); + pci_restore_state(pdev, pAC->PciState); + + pci_enable_device(pdev); + pci_set_master(pdev); + + pci_enable_wake(pdev, 3, 0); + pci_enable_wake(pdev, 4, 0); + + SK_OUT8(pAC->IoBase, RX_GMF_CTRL_T, (SK_U8)GMF_RST_CLR); + + /* Set the adapter power state to D0 */ + SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts); + PmCtlSts &= ~(PCI_PM_STATE_D3); /* reset all DState bits */ + PmCtlSts |= PCI_PM_STATE_D0; + SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PmCtlSts); + + /* Reinit the adapter and start the port again */ + pAC->BoardLevel = SK_INIT_DATA; + SkDrvLeaveDiagMode(pAC); + + if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) || + (CHIP_ID_YUKON_2(pAC)) ) { + pAC->StatusLETable.Done = 0; + pAC->StatusLETable.Put = 0; + pAC->StatusLETable.HwPut = 0; + SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable); + } + + return 0; +} + +/***************************************************************************** + * + * sk98lin_suspend - Suspend the card + * + * Description: + * This function suspends the card into a defined state + * + * Returns: N/A + * + */ +static int sk98lin_suspend( +struct pci_dev *pdev, /* pointer to the device that is to suspend */ +u32 state) /* what power state is desired by Linux? */ +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + SK_U16 PciPMControlStatus; + SK_U16 PciPMCapabilities; + SK_MAC_ADDR MacAddr; + int i; + + /* GEnesis and first yukon revs do not support power management */ + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + if (pAC->GIni.GIChipRev == 0) { + return 0; /* power management not supported */ + } + } + + if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { + return 0; /* not supported for this chipset */ + } + + if (pAC->WolInfo.ConfiguredWolOptions == 0) { + return 0; /* WOL possible, but disabled via ethtool */ + } + + if(netif_running(dev)) { + netif_stop_queue(dev); /* stop device if running */ + } + + /* read the PM control/status register from the PCI config space */ + SK_IN16(pAC->IoBase, PCI_C(pAC, PCI_PM_CTL_STS), &PciPMControlStatus); + + /* read the power management capabilities from the config space */ + SK_IN16(pAC->IoBase, PCI_C(pAC, PCI_PM_CAP_REG), &PciPMCapabilities); + + /* Enable WakeUp with Magic Packet - get MAC address from adapter */ + for (i = 0; i < SK_MAC_ADDR_LEN; i++) { + /* virtual address: will be used for data */ + SK_IN8(pAC->IoBase, (B2_MAC_1 + i), &MacAddr.a[i]); + } + + SkDrvEnterDiagMode(pAC); + SkEnableWOMagicPacket(pAC, pAC->IoBase, MacAddr); + + pci_enable_wake(pdev, 3, 1); + pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */ + pci_save_state(pdev, pAC->PciState); + pci_disable_device(pdev); // NEW + pci_set_power_state(pdev, state); /* set the state */ + + return 0; +} + + +/****************************************************************************** + * + * SkEnableWOMagicPacket - Enable Wake on Magic Packet on the adapter + * + * Context: + * init, pageable + * the adapter should be de-initialized before calling this function + * + * Returns: + * nothing + */ + +static void SkEnableWOMagicPacket( +SK_AC *pAC, /* Adapter Control Context */ +SK_IOC IoC, /* I/O control context */ +SK_MAC_ADDR MacAddr) /* MacAddr expected in magic packet */ +{ + SK_U16 Word; + SK_U32 DWord; + int i; + int HwPortIndex; + int Port = 0; + + /* use Port 0 as long as we do not have any dual port cards which support WOL */ + HwPortIndex = 0; + DWord = 0; + + SK_OUT16(IoC, 0x0004, 0x0002); /* clear S/W Reset */ + SK_OUT16(IoC, 0x0f10, 0x0002); /* clear Link Reset */ + + /* + * PHY Configuration: + * Autonegotioation is enalbed, advertise 10 HD, 10 FD, + * 100 HD, and 100 FD. + */ + if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) || + (pAC->GIni.GIChipId == CHIP_ID_YUKON) || + (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) || + (CHIP_ID_YUKON_2(pAC)) ) { + + SK_OUT8(IoC, 0x0007, 0xa9); /* enable VAUX */ + + /* WA code for COMA mode */ + /* Only for yukon plus based chipsets rev A3 */ + if (pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { + SK_IN32(IoC, B2_GP_IO, &DWord); + DWord |= GP_DIR_9; /* set to output */ + DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ + SK_OUT32(IoC, B2_GP_IO, DWord); /* clear PHY reset */ + } + + if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) || + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + SK_OUT32(IoC, 0x0f04, 0x01f04001); /* set PHY reset */ + SK_OUT32(IoC, 0x0f04, 0x01f04002); /* clear PHY reset */ + } else { + SK_OUT8(IoC, 0x0f04, 0x02); /* clear PHY reset */ + } + + SK_OUT8(IoC, 0x0f00, 0x02); /* clear MAC reset */ + SkGmPhyWrite(pAC, IoC, Port, 4, 0x01e1); /* advertise 10/100 HD/FD */ + SkGmPhyWrite(pAC, IoC, Port, 9, 0x0000); /* do not advertise 1000 HD/FD */ + SkGmPhyWrite(pAC, IoC, Port, 00, 0xB300); /* 100 MBit, disable Autoneg */ + } else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { + SK_OUT8(IoC, 0x0007, 0xa9); /* enable VAUX */ + SK_OUT8(IoC, 0x0f04, 0x02); /* clear PHY reset */ + SK_OUT8(IoC, 0x0f00, 0x02); /* clear MAC reset */ + SkGmPhyWrite(pAC, IoC, Port, 16, 0x0130); /* Enable Automatic Crossover */ + SkGmPhyWrite(pAC, IoC, Port, 00, 0xB300); /* 100 MBit, disable Autoneg */ + } + + + /* + * MAC Configuration: + * Set the MAC to 100 HD and enable the auto update features + * for Speed, Flow Control and Duplex Mode. + * If autonegotiation completes successfully the + * MAC takes the link parameters from the PHY. + * If the link partner doesn't support autonegotiation + * the MAC can receive magic packets if the link partner + * uses 100 HD. + */ + SK_OUT16(IoC, 0x2804, 0x3832); + + + /* + * Set Up Magic Packet parameters + */ + for (i = 0; i < 6; i+=2) { /* set up magic packet MAC address */ + SK_IN16(IoC, 0x100 + i, &Word); + SK_OUT16(IoC, 0xf24 + i, Word); + } + + SK_OUT16(IoC, 0x0f20, 0x0208); /* enable PME on magic packet */ + /* and on wake up frame */ + + /* + * Set up PME generation + */ + /* set PME legacy mode */ + /* Only for PCI express based chipsets */ + if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) || + (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) || + (CHIP_ID_YUKON_2(pAC))) { + SkPciReadCfgDWord(pAC, 0x40, &DWord); + DWord |= 0x8000; + SkPciWriteCfgDWord(pAC, 0x40, DWord); + } + + SK_OUT8(IoC, RX_GMF_CTRL_T, (SK_U8)GMF_RST_SET); + + /* clear PME status and switch adapter to DState */ + SkPciReadCfgWord(pAC, 0x4c, &Word); + Word |= 0x103; + SkPciWriteCfgWord(pAC, 0x4c, Word); +} /* SkEnableWOMagicPacket */ +#endif + /***************************************************************************** * @@ -864,7 +1510,7 @@ int skge_probe (struct eth_device ** ret_dev) * frees the desriptor ring. * * Returns: N/A - * + * */ static void FreeResources(struct SK_NET_DEVICE *dev) { @@ -876,7 +1522,11 @@ SK_AC *pAC; pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; AllocFlag = pAC->AllocFlag; -#if 0 +#if 0 /* uboot */ + if (pAC->PciDev) { + pci_release_regions(pAC->PciDev); + } + if (AllocFlag & SK_ALLOC_IRQ) { free_irq(dev->irq, dev); } @@ -884,43 +1534,40 @@ SK_AC *pAC; iounmap(pAC->IoBase); } #endif - if (pAC->pDescrMem) { + +#if 0 /* Marvell- uboot */ + + if (CHIP_ID_YUKON_2(pAC)) { + SkY2FreeResources(pAC); + } else { BoardFreeMem(pAC); } + +#else + if (CHIP_ID_YUKON_2(pAC)) { + SkY2FreeResources(pAC); + } else { + BoardFreeMem(pAC); } - +#endif + } + } /* FreeResources */ -#if 0 +#if 0 /* uboot */ MODULE_AUTHOR("Mirko Lindner "); MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(Speed_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(Speed_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(DupCap_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -/* not used, just there because every driver should have them: */ -MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); -MODULE_PARM(debug, "i"); #endif - #ifdef LINK_SPEED_A -static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED_A; +static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED; #else static char *Speed_A[SK_MAX_CARD_PARAM] = {"", }; #endif #ifdef LINK_SPEED_B -static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED_B; +static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED; #else static char *Speed_B[SK_MAX_CARD_PARAM] = {"", }; #endif @@ -973,6 +1620,12 @@ static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B; static char *Role_B[SK_MAX_CARD_PARAM] = {"", }; #endif +#ifdef CON_TYPE +static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE; +#else +static char *ConType[SK_MAX_CARD_PARAM] = {"", }; +#endif + #ifdef PREF_PORT static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT; #else @@ -985,42 +1638,16 @@ static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE; static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; #endif +static int IntsPerSec[SK_MAX_CARD_PARAM]; +static char *Moderation[SK_MAX_CARD_PARAM]; +static char *ModerationMask[SK_MAX_CARD_PARAM]; + +static char *LowLatency[SK_MAX_CARD_PARAM]; + #if 0 -static int debug = 0; /* not used */ -static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ - - /***************************************************************************** * - * skge_init_module - module initialization function - * - * Description: - * Very simple, only call skge_probe and return approriate result. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __init skge_init_module(void) -{ - int cards; - SkGeRootDev = NULL; - - /* just to avoid warnings ... */ - debug = 0; - options[0] = 0; - - cards = skge_probe(); - if (cards == 0) { - printk("sk98lin: No adapter found.\n"); - } - return cards ? 0 : -ENODEV; -} /* skge_init_module */ - - -/***************************************************************************** - * - * skge_cleanup_module - module unload function + * sk98lin_remove_device - device deinit function * * Description: * Disable adapter if it is still running, free resources, @@ -1028,73 +1655,84 @@ static int __init skge_init_module(void) * * Returns: N/A */ -static void __exit skge_cleanup_module(void) + +static void sk98lin_remove_device(struct pci_dev *pdev) { DEV_NET *pNet; SK_AC *pAC; struct SK_NET_DEVICE *next; unsigned long Flags; -SK_EVPARA EvPara; +struct net_device *dev = pci_get_drvdata(pdev); - while (SkGeRootDev) { - pNet = (DEV_NET*) SkGeRootDev->priv; - pAC = pNet->pAC; - next = pAC->Next; - netif_stop_queue(SkGeRootDev); - SkGeYellowLED(pAC, pAC->IoBase, 0); + /* Device not available. Return. */ + if (!dev) + return; - if(pAC->BoardLevel == 2) { - /* board is still alive */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - SkGeDeInit(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->BoardLevel = 0; - /* We do NOT check here, if IRQ was pending, of course*/ - } + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + next = pAC->Next; - if(pAC->BoardLevel == 1) { - /* board is still alive */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = 0; - } + netif_stop_queue(dev); + SkGeYellowLED(pAC, pAC->IoBase, 0); - if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ - unregister_netdev(pAC->dev[1]); - kfree(pAC->dev[1]); - } + if(pAC->BoardLevel == SK_INIT_RUN) { + /* board is still alive */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, + 0, -1, SK_FALSE); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, + 1, -1, SK_TRUE); - FreeResources(SkGeRootDev); - - SkGeRootDev->get_stats = NULL; - /* - * otherwise unregister_netdev calls get_stats with - * invalid IO ... :-( - */ - unregister_netdev(SkGeRootDev); - kfree(SkGeRootDev); - kfree(pAC); - SkGeRootDev = next; + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + SkGeDeInit(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + pAC->BoardLevel = SK_INIT_DATA; + /* We do NOT check here, if IRQ was pending, of course*/ } - /* clear proc-dir */ - remove_proc_entry(pSkRootDir->name, proc_net); + if(pAC->BoardLevel == SK_INIT_IO) { + /* board is still alive */ + SkGeDeInit(pAC, pAC->IoBase); + pAC->BoardLevel = SK_INIT_DATA; + } -} /* skge_cleanup_module */ + if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ + unregister_netdev(pAC->dev[1]); + free_netdev(pAC->dev[1]); + } -module_init(skge_init_module); -module_exit(skge_cleanup_module); + FreeResources(dev); + +#ifdef CONFIG_PROC_FS + /* Remove the sk98lin procfs device entries */ + if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ + remove_proc_entry(pAC->dev[1]->name, pSkRootDir); + } + remove_proc_entry(pNet->InitialDevName, pSkRootDir); #endif + dev->get_stats = NULL; + /* + * otherwise unregister_netdev calls get_stats with + * invalid IO ... :-( + */ + unregister_netdev(dev); + free_netdev(dev); + kfree(pAC); + sk98lin_max_boards_found--; + +#ifdef CONFIG_PROC_FS + /* Remove all Proc entries if last device */ + if (sk98lin_max_boards_found == 0) { + /* clear proc-dir */ + remove_proc_entry(pSkRootDir->name, proc_net); + } +#endif + +} +#endif /***************************************************************************** * @@ -1115,7 +1753,7 @@ short i; unsigned long Flags; char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */ char *VerStr = VER_STRING; -#if 0 +#if 0 /* uboot */ int Ret; /* return code of request_irq */ #endif SK_BOOL DualNet; @@ -1134,121 +1772,173 @@ SK_BOOL DualNet; spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock); spin_lock_init(&pAC->RxPort[i].RxDesRingLock); } + + spin_lock_init(&pAC->InitLock); /* Init lock */ spin_lock_init(&pAC->SlowPathLock); + spin_lock_init(&pAC->TxQueueLock); /* for Yukon2 chipsets */ + spin_lock_init(&pAC->SetPutIndexLock); /* for Yukon2 chipsets */ /* level 0 init common modules here */ - + spin_lock_irqsave(&pAC->SlowPathLock, Flags); /* Does a RESET on board ...*/ - if (SkGeInit(pAC, pAC->IoBase, 0) != 0) { + if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { printk("HWInit (0) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); return(-EAGAIN); } - SkI2cInit( pAC, pAC->IoBase, 0); - SkEventInit(pAC, pAC->IoBase, 0); - SkPnmiInit( pAC, pAC->IoBase, 0); - SkAddrInit( pAC, pAC->IoBase, 0); - SkRlmtInit( pAC, pAC->IoBase, 0); - SkTimerInit(pAC, pAC->IoBase, 0); + SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA); + SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA); +#ifdef SK_PNMI_SUPPORT + SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA); +#endif + SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA); + SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA); + SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA); - pAC->BoardLevel = 0; - pAC->RxBufSize = ETH_BUF_SIZE; + pAC->BoardLevel = SK_INIT_DATA; + pAC->RxPort[0].RxBufSize = ETH_BUF_SIZE; + pAC->RxPort[1].RxBufSize = ETH_BUF_SIZE; SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString); SK_PNMI_SET_DRIVER_VER(pAC, VerStr); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - /* level 1 init common modules here (HW init) */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { - printk("HWInit (1) failed.\n"); + if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { + printk("sk98lin: HWInit (1) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); return(-EAGAIN); } - SkI2cInit( pAC, pAC->IoBase, 1); - SkEventInit(pAC, pAC->IoBase, 1); - SkPnmiInit( pAC, pAC->IoBase, 1); - SkAddrInit( pAC, pAC->IoBase, 1); - SkRlmtInit( pAC, pAC->IoBase, 1); - SkTimerInit(pAC, pAC->IoBase, 1); + SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); + SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); +#ifdef SK_PNMI_SUPPORT + SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO); +#endif + SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO); + SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO); + SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO); +#ifdef Y2_RECOVERY + /* mark entries invalid */ + pAC->LastPort = 3; + pAC->LastOpc = 0xFF; +#endif + + /* Set chipset type support */ + if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) || + (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) || + (pAC->GIni.GIChipId == CHIP_ID_YUKON_LP)) { + pAC->ChipsetType = 1; /* Yukon chipset (descriptor logic) */ + } else if (CHIP_ID_YUKON_2(pAC)) { + pAC->ChipsetType = 2; /* Yukon2 chipset (list logic) */ + } else { + pAC->ChipsetType = 0; /* Genesis chipset (descriptor logic) */ + } + + /* wake on lan support */ + pAC->WolInfo.SupportedWolOptions = 0; +#if defined (ETHTOOL_GWOL) && defined (ETHTOOL_SWOL) + if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) { + pAC->WolInfo.SupportedWolOptions = WAKE_MAGIC; + if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { + if (pAC->GIni.GIChipRev == 0) { + pAC->WolInfo.SupportedWolOptions = 0; + } + } + } +#endif + pAC->WolInfo.ConfiguredWolOptions = pAC->WolInfo.SupportedWolOptions; GetConfiguration(pAC); if (pAC->RlmtNets == 2) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; + pAC->GIni.GP[0].PPortUsage = SK_MUL_LINK; + pAC->GIni.GP[1].PPortUsage = SK_MUL_LINK; } - pAC->BoardLevel = 1; + pAC->BoardLevel = SK_INIT_IO; spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); -#if 0 - if (pAC->GIni.GIMacsFound == 2) { - Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); - } else if (pAC->GIni.GIMacsFound == 1) { - Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, - pAC->Name, dev); - } else { - printk(KERN_WARNING "%s: Illegal number of ports: %d\n", - dev->name, pAC->GIni.GIMacsFound); - return -EAGAIN; + if (!CHIP_ID_YUKON_2(pAC)) { +#ifdef CONFIG_SK98LIN_NAPI + dev->poll = &SkGePoll; + dev->weight = 64; +#endif +#if 0 /* uboot */ + if (pAC->GIni.GIMacsFound == 2) { + Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, dev->name, dev); + } else if (pAC->GIni.GIMacsFound == 1) { + Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, dev->name, dev); + } else { + printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", + pAC->GIni.GIMacsFound); + return -EAGAIN; + } + } + else { + Ret = request_irq(dev->irq, SkY2Isr, SA_SHIRQ, dev->name, dev); } if (Ret) { - printk(KERN_WARNING "%s: Requested IRQ %d is busy.\n", - dev->name, dev->irq); + printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", + dev->irq); return -EAGAIN; } #endif - pAC->AllocFlag |= SK_ALLOC_IRQ; - - /* Alloc memory for this board (Mem for RxD/TxD) : */ - if(!BoardAllocMem(pAC)) { - printk("No memory for descriptor rings.\n"); - return(-EAGAIN); } + + pAC->AllocFlag |= SK_ALLOC_IRQ; + + /* + ** Alloc descriptor/LETable memory for this board (both RxD/TxD) + */ + if (CHIP_ID_YUKON_2(pAC)) { + if (!SkY2AllocateResources(pAC)) { + printk("No memory for Yukon2 settings\n"); + return(-EAGAIN); + } + } else { + if(!BoardAllocMem(pAC)) { + printk("No memory for descriptor rings.\n"); + return(-EAGAIN); + } + } + +#ifdef SK_USE_CSUM SkCsSetReceiveFlags(pAC, SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP, &pAC->CsOfs1, &pAC->CsOfs2, 0); pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1; +#endif + /* + ** Function BoardInitMem() for Yukon dependent settings... + */ BoardInitMem(pAC); -#if 0 - SetQueueSizes(pAC); -#else /* tschilling: New common function with minimum size check. */ DualNet = SK_FALSE; if (pAC->RlmtNets == 2) { DualNet = SK_TRUE; } - + if (SkGeInitAssignRamToQueues( pAC, pAC->ActivePort, DualNet)) { +#if 0 /* Marvell - uboot */ BoardFreeMem(pAC); - printk("SkGeInitAssignRamToQueues failed.\n"); +#else + if (CHIP_ID_YUKON_2(pAC)) { + SkY2FreeResources(pAC); + } else { + BoardFreeMem(pAC); + } +#endif + + + + printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); return(-EAGAIN); } -#endif - - /* Print adapter specific string from vpd */ - ProductStr(pAC); -#ifdef SK98_INFO - printk("%s: %s\n", dev->name, pAC->DeviceStr); - - /* Print configuration settings */ - printk(" PrefPort:%c RlmtMode:%s\n", - 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, - (pAC->RlmtMode==0) ? "Check Link State" : - ((pAC->RlmtMode==1) ? "Check Link State" : - ((pAC->RlmtMode==3) ? "Check Local Port" : - ((pAC->RlmtMode==7) ? "Check Segmentation" : - ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); -#endif - - SkGeYellowLED(pAC, pAC->IoBase, 1); /* * Register the device here @@ -1282,7 +1972,7 @@ size_t AllocLength; /* length of complete descriptor area */ int i; /* loop counter */ unsigned long BusAddr; - + /* rings plus one for alignment (do not cross 4 GB boundary) */ /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */ #if (BITS_PER_LONG == 32) @@ -1313,7 +2003,7 @@ unsigned long BusAddr; pAC->TxPort[i][0].VTxDescrRing = BusAddr; pDescrMem += TX_RING_SIZE; BusAddr += TX_RING_SIZE; - + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n", i, (unsigned long) pDescrMem, @@ -1323,7 +2013,7 @@ unsigned long BusAddr; pDescrMem += RX_RING_SIZE; BusAddr += RX_RING_SIZE; } /* for */ - + return (SK_TRUE); } /* BoardAllocMem */ @@ -1345,16 +2035,20 @@ size_t AllocLength; /* length of complete descriptor area */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("BoardFreeMem\n")); + + if (pAC->pDescrMem) { + #if (BITS_PER_LONG == 32) - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; + AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; #else - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound - + RX_RING_SIZE + 8; + AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + + RX_RING_SIZE + 8; #endif - pci_free_consistent(pAC->PciDev, AllocLength, + pci_free_consistent(pAC->PciDev, AllocLength, pAC->pDescrMem, pAC->pDescrMemDMA); - pAC->pDescrMem = NULL; + pAC->pDescrMem = NULL; + } } /* BoardFreeMem */ @@ -1363,7 +2057,7 @@ size_t AllocLength; /* length of complete descriptor area */ * BoardInitMem - initiate the descriptor rings * * Description: - * This function sets the descriptor rings up in memory. + * This function sets the descriptor rings or LETables up in memory. * The adapter is initialized with the descriptor start addresses. * * Returns: N/A @@ -1378,34 +2072,37 @@ int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("BoardInitMem\n")); - RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize; - TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize; - - for (i=0; iGIni.GIMacsFound; i++) { - SetupRing( - pAC, - pAC->TxPort[i][0].pTxDescrRing, - pAC->TxPort[i][0].VTxDescrRing, - (RXD**)&pAC->TxPort[i][0].pTxdRingHead, - (RXD**)&pAC->TxPort[i][0].pTxdRingTail, - (RXD**)&pAC->TxPort[i][0].pTxdRingPrev, - &pAC->TxPort[i][0].TxdRingFree, - SK_TRUE); - SetupRing( - pAC, - pAC->RxPort[i].pRxDescrRing, - pAC->RxPort[i].VRxDescrRing, - &pAC->RxPort[i].pRxdRingHead, - &pAC->RxPort[i].pRxdRingTail, - &pAC->RxPort[i].pRxdRingPrev, - &pAC->RxPort[i].RxdRingFree, - SK_FALSE); + if (!pAC->GIni.GIYukon2) { + RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; + pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize; + TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; + pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize; + + for (i=0; iGIni.GIMacsFound; i++) { + SetupRing( + pAC, + pAC->TxPort[i][0].pTxDescrRing, + pAC->TxPort[i][0].VTxDescrRing, + (RXD**)&pAC->TxPort[i][0].pTxdRingHead, + (RXD**)&pAC->TxPort[i][0].pTxdRingTail, + (RXD**)&pAC->TxPort[i][0].pTxdRingPrev, + &pAC->TxPort[i][0].TxdRingFree, + &pAC->TxPort[i][0].TxdRingPrevFree, + SK_TRUE); + SetupRing( + pAC, + pAC->RxPort[i].pRxDescrRing, + pAC->RxPort[i].VRxDescrRing, + &pAC->RxPort[i].pRxdRingHead, + &pAC->RxPort[i].pRxdRingTail, + &pAC->RxPort[i].pRxdRingPrev, + &pAC->RxPort[i].RxdRingFree, + &pAC->RxPort[i].RxdRingFree, + SK_FALSE); + } } } /* BoardInitMem */ - /***************************************************************************** * * SetupRing - create one descriptor ring @@ -1425,6 +2122,7 @@ RXD **ppRingHead, /* address where the head should be written */ RXD **ppRingTail, /* address where the tail should be written */ RXD **ppRingPrev, /* address where the tail should be written */ int *pRingFree, /* address where the # of free descr. goes */ +int *pRingPrevFree, /* address where the # of free descr. goes */ SK_BOOL IsTx) /* flag: is this a tx ring */ { int i; /* loop counter */ @@ -1444,11 +2142,11 @@ uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ DESCR_ALIGN; DescrNum = RX_RING_SIZE / DescrSize; } - + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("Descriptor size: %d Descriptor Number: %d\n", DescrSize,DescrNum)); - + pDescr = (RXD*) pMemArea; pPrevDescr = NULL; pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); @@ -1467,11 +2165,12 @@ uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ } pPrevDescr->pNextRxd = (RXD*) pMemArea; pPrevDescr->VNextRxd = VMemArea; - pDescr = (RXD*) pMemArea; - *ppRingHead = (RXD*) pMemArea; - *ppRingTail = *ppRingHead; - *ppRingPrev = pPrevDescr; - *pRingFree = DescrNum; + pDescr = (RXD*) pMemArea; + *ppRingHead = (RXD*) pMemArea; + *ppRingTail = *ppRingHead; + *ppRingPrev = pPrevDescr; + *pRingFree = DescrNum; + *pRingPrevFree = DescrNum; } /* SetupRing */ @@ -1495,24 +2194,22 @@ int PortIndex) /* index of the port for which to re-init */ ("PortReInitBmu ")); /* set address of first descriptor of ring in BMU */ - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ - TX_Q_CUR_DESCR_LOW, + SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L, (uint32_t)(((caddr_t) (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) & 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ - TX_Q_DESCR_HIGH, + SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H, (uint32_t)(((caddr_t) (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CUR_DESCR_LOW, + SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L, (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - pAC->RxPort[PortIndex].pRxDescrRing + pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_DESCR_HIGH, + SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H, (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - pAC->RxPort[PortIndex].pRxDescrRing + pAC->RxPort[PortIndex].VRxDescrRing) >> 32)); @@ -1531,8 +2228,8 @@ int PortIndex) /* index of the port for which to re-init */ * Returns: N/A * */ -#if 0 -static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) +#if 0 /* uboot */ +static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) #else void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) #endif @@ -1540,98 +2237,111 @@ void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; DEV_NET *pNet; SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ +SK_U32 IntSrc; /* interrupts source register contents */ pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; - + /* * Check and process if its our interrupt */ SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { + if ((IntSrc == 0) && (!pNet->NetConsoleMode)) { return; } +#ifdef CONFIG_SK98LIN_NAPI + if (netif_rx_schedule_prep(dev)) { + pAC->GIni.GIValIrqMask &= ~(NAPI_DRV_IRQS); + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + __netif_rx_schedule(dev); + } + +#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ + if (IntSrc & IS_XA1_F) { + CLEAR_TX_IRQ(0, TX_PRIO_LOW); + } + if (IntSrc & IS_XA2_F) { + CLEAR_TX_IRQ(1, TX_PRIO_LOW); + } +#endif + + +#else while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { #if 0 /* software irq currently not used */ - if (IntSrc & IRQ_SW) { + if (IntSrc & IS_IRQ_SW) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("Software IRQ\n")); } #endif - if (IntSrc & IRQ_EOF_RX1) { + if (IntSrc & IS_R1_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF RX1 IRQ\n")); ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); + CLEAR_AND_START_RX(0); SK_PNMI_CNT_RX_INTR(pAC, 0); } - if (IntSrc & IRQ_EOF_RX2) { + if (IntSrc & IS_R2_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF RX2 IRQ\n")); ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); + CLEAR_AND_START_RX(1); SK_PNMI_CNT_RX_INTR(pAC, 1); } #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) { + if (IntSrc & IS_XA1_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF AS TX1 IRQ\n")); + CLEAR_TX_IRQ(0, TX_PRIO_LOW); SK_PNMI_CNT_TX_INTR(pAC, 0); spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); } - if (IntSrc & IRQ_EOF_AS_TX2) { + if (IntSrc & IS_XA2_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF AS TX2 IRQ\n")); + CLEAR_TX_IRQ(1, TX_PRIO_LOW); SK_PNMI_CNT_TX_INTR(pAC, 1); spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]); spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); } #if 0 /* only if sync. queues used */ - if (IntSrc & IRQ_EOF_SY_TX1) { + if (IntSrc & IS_XS1_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF SY TX1 IRQ\n")); + CLEAR_TX_IRQ(0, TX_PRIO_HIGH); SK_PNMI_CNT_TX_INTR(pAC, 1); spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); } - if (IntSrc & IRQ_EOF_SY_TX2) { + if (IntSrc & IS_XS2_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF SY TX2 IRQ\n")); + CLEAR_TX_IRQ(1, TX_PRIO_HIGH); SK_PNMI_CNT_TX_INTR(pAC, 1); spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH); spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 1, TX_PRIO_HIGH); } #endif #endif - /* do all IO at once */ - if (IntSrc & IRQ_EOF_RX1) - ClearAndStartRx(pAC, 0); - if (IntSrc & IRQ_EOF_RX2) - ClearAndStartRx(pAC, 1); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); - if (IntSrc & IRQ_EOF_AS_TX2) - ClearTxIrq(pAC, 1, TX_PRIO_LOW); -#endif SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); } /* while (IntSrc & IRQ_MASK != 0) */ +#endif + IntSrc &= pAC->GIni.GIValIrqMask; if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("SPECIAL IRQ DP-Cards => %x\n", IntSrc)); @@ -1643,14 +2353,12 @@ SK_U32 IntSrc; /* interrupts source register contents */ SkEventDispatcher(pAC, pAC->IoBase); spin_unlock(&pAC->SlowPathLock); } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - */ +#ifndef CONFIG_SK98LIN_NAPI + /* Handle interrupts */ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); +#endif if (pAC->CheckQueue) { pAC->CheckQueue = SK_FALSE; @@ -1659,11 +2367,10 @@ SK_U32 IntSrc; /* interrupts source register contents */ spin_unlock(&pAC->SlowPathLock); } - /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - return; + return; } /* SkGeIsr */ @@ -1680,102 +2387,112 @@ SK_U32 IntSrc; /* interrupts source register contents */ * Returns: N/A * */ -#if 0 -static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) +#if 0 /* uboot */ +static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) #else -void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) +SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) #endif { struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; DEV_NET *pNet; SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ +SK_U32 IntSrc; /* interrupts source register contents */ pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; - + /* * Check and process if its our interrupt */ SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { + if ((IntSrc == 0) && (!pNet->NetConsoleMode)) { return; } + +#ifdef CONFIG_SK98LIN_NAPI + if (netif_rx_schedule_prep(dev)) { + CLEAR_AND_START_RX(0); + CLEAR_TX_IRQ(0, TX_PRIO_LOW); + pAC->GIni.GIValIrqMask &= ~(NAPI_DRV_IRQS); + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + __netif_rx_schedule(dev); + } +#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ + if (IntSrc & IS_XA1_F) { + CLEAR_TX_IRQ(0, TX_PRIO_LOW); + } +#endif +#else while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { #if 0 /* software irq currently not used */ - if (IntSrc & IRQ_SW) { + if (IntSrc & IS_IRQ_SW) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("Software IRQ\n")); } #endif - if (IntSrc & IRQ_EOF_RX1) { + if (IntSrc & IS_R1_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF RX1 IRQ\n")); ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); + CLEAR_AND_START_RX(0); SK_PNMI_CNT_RX_INTR(pAC, 0); } #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) { + if (IntSrc & IS_XA1_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF AS TX1 IRQ\n")); + CLEAR_TX_IRQ(0, TX_PRIO_LOW); SK_PNMI_CNT_TX_INTR(pAC, 0); spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); } #if 0 /* only if sync. queues used */ - if (IntSrc & IRQ_EOF_SY_TX1) { + if (IntSrc & IS_XS1_F) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF SY TX1 IRQ\n")); + CLEAR_TX_IRQ(0, TX_PRIO_HIGH); SK_PNMI_CNT_TX_INTR(pAC, 0); spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); } #endif #endif - /* do all IO at once */ - if (IntSrc & IRQ_EOF_RX1) - ClearAndStartRx(pAC, 0); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IRQ_EOF_AS_TX1) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); -#endif SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); } /* while (IntSrc & IRQ_MASK != 0) */ - +#endif + + IntSrc &= pAC->GIni.GIValIrqMask; if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("SPECIAL IRQ SP-Cards => %x\n", IntSrc)); pAC->CheckQueue = SK_FALSE; spin_lock(&pAC->SlowPathLock); if (IntSrc & SPECIAL_IRQS) + SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); SkEventDispatcher(pAC, pAC->IoBase); spin_unlock(&pAC->SlowPathLock); } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - */ + +#ifndef CONFIG_SK98LIN_NAPI ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); +#endif /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - return; + return; } /* SkGeIsrOnePort */ - /**************************************************************************** * * SkGeOpen - handle start of initialized adapter @@ -1792,101 +2509,142 @@ SK_U32 IntSrc; /* interrupts source register contents */ * 0 on success * != 0 on error */ -#if 0 +#if 0 /* uboot */ static int SkGeOpen( #else int SkGeOpen( #endif -struct SK_NET_DEVICE *dev) +struct SK_NET_DEVICE *dev) /* the device that is to be opened */ { - DEV_NET *pNet; - SK_AC *pAC; - unsigned long Flags; /* for spin lock */ - int i; - SK_EVPARA EvPara; /* an event parameter union */ - - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + unsigned long Flags; /* for the spin locks */ + unsigned long InitFlags; /* for the spin locks */ + int CurrMac; /* loop ctr for ports */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); + spin_lock_irqsave(&pAC->InitLock, InitFlags); +#if 0 /* uboot */ - if (pAC->BoardLevel == 0) { + if (pAC->DiagModeActive == DIAG_ACTIVE) { + if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { + return (-1); /* still in use by diag; deny actions */ + } + } + + if (!try_module_get(THIS_MODULE)) { + return (-1); /* increase of usage count not possible */ + } + + /* Set blink mode */ + if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab )) + pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE; +#endif + + + + if (pAC->BoardLevel == SK_INIT_DATA) { /* level 1 init common modules here */ - if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { + if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name); return (-1); } - SkI2cInit (pAC, pAC->IoBase, 1); - SkEventInit (pAC, pAC->IoBase, 1); - SkPnmiInit (pAC, pAC->IoBase, 1); - SkAddrInit (pAC, pAC->IoBase, 1); - SkRlmtInit (pAC, pAC->IoBase, 1); - SkTimerInit (pAC, pAC->IoBase, 1); - pAC->BoardLevel = 1; + SkI2cInit (pAC, pAC->IoBase, SK_INIT_IO); + SkEventInit (pAC, pAC->IoBase, SK_INIT_IO); + +#ifdef SK_PNMI_SUPPORT + SkPnmiInit (pAC, pAC->IoBase, SK_INIT_IO); +#endif + + SkAddrInit (pAC, pAC->IoBase, SK_INIT_IO); + SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO); + SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO); + pAC->BoardLevel = SK_INIT_IO; +#ifdef Y2_RECOVERY + /* mark entries invalid */ + pAC->LastPort = 3; + pAC->LastOpc = 0xFF; +#endif } - if (pAC->BoardLevel != 2) { + if (pAC->BoardLevel != SK_INIT_RUN) { /* tschilling: Level 2 init modules here, check return value. */ - if (SkGeInit(pAC, pAC->IoBase, 2) != 0) { + if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) { printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name); return (-1); } - SkI2cInit (pAC, pAC->IoBase, 2); - SkEventInit (pAC, pAC->IoBase, 2); - SkPnmiInit (pAC, pAC->IoBase, 2); - SkAddrInit (pAC, pAC->IoBase, 2); - SkRlmtInit (pAC, pAC->IoBase, 2); - SkTimerInit (pAC, pAC->IoBase, 2); - pAC->BoardLevel = 2; - } + SkI2cInit (pAC, pAC->IoBase, SK_INIT_RUN); + SkEventInit (pAC, pAC->IoBase, SK_INIT_RUN); - for (i=0; iGIni.GIMacsFound; i++) { - /* Enable transmit descriptor polling. */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - } - SkGeYellowLED(pAC, pAC->IoBase, 1); - -#ifdef USE_INT_MOD -/* moderate only TX complete interrupts (these are not time critical) */ -#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2) - { - unsigned long ModBase; - ModBase = 53125000 / INTS_PER_SEC; - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); - SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); - } +#ifdef SK_PNMI_SUPPORT + SkPnmiInit (pAC, pAC->IoBase, SK_INIT_RUN); #endif - /* enable Interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); - SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); + SkAddrInit (pAC, pAC->IoBase, SK_INIT_RUN); + SkRlmtInit (pAC, pAC->IoBase, SK_INIT_RUN); + SkTimerInit (pAC, pAC->IoBase, SK_INIT_RUN); + pAC->BoardLevel = SK_INIT_RUN; + } + + for (CurrMac=0; CurrMacGIni.GIMacsFound; CurrMac++) { + if (!CHIP_ID_YUKON_2(pAC)) { + /* Enable transmit descriptor polling. */ + SkGePollTxD(pAC, pAC->IoBase, CurrMac, SK_TRUE); + FillRxRing(pAC, &pAC->RxPort[CurrMac]); + SkMacRxTxEnable(pAC, pAC->IoBase, pNet->PortNr); + } + } + + SkGeYellowLED(pAC, pAC->IoBase, 1); + SkDimEnableModerationIfNeeded(pAC); + + if (!CHIP_ID_YUKON_2(pAC)) { + /* + ** Has been setup already at SkGeInit(SK_INIT_IO), + ** but additional masking added for Genesis & Yukon + ** chipsets -> modify it... + */ + pAC->GIni.GIValIrqMask &= IRQ_MASK; +#ifndef USE_TX_COMPLETE + pAC->GIni.GIValIrqMask &= ~(TX_COMPL_IRQS); +#endif + } spin_lock_irqsave(&pAC->SlowPathLock, Flags); if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) { - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, - EvPara); - EvPara.Para32[0] = pAC->RlmtMode; - EvPara.Para32[1] = 0; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, - EvPara); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, + pAC->RlmtNets, -1, SK_FALSE); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, + pAC->RlmtMode, 0, SK_FALSE); } - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, + pNet->NetNr, -1, SK_TRUE); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->MaxPorts++; - pNet->Up = 1; +#ifdef Y2_RECOVERY + pNet->TimerExpired = SK_FALSE; + pNet->InRecover = SK_FALSE; + pNet->NetConsoleMode = SK_FALSE; - MOD_INC_USE_COUNT; + /* Initialize the kernel timer */ +#if 0 // u-boot + init_timer(&pNet->KernelTimer); + pNet->KernelTimer.function = SkGeHandleKernelTimer; + pNet->KernelTimer.data = (unsigned long) pNet; + pNet->KernelTimer.expires = jiffies + (HZ/4); /* initially 250ms */ + add_timer(&pNet->KernelTimer); +#endif +#endif + + /* enable Interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); + + pAC->MaxPorts++; + spin_unlock_irqrestore(&pAC->InitLock, InitFlags); SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeOpen suceeded\n")); @@ -1906,33 +2664,62 @@ struct SK_NET_DEVICE *dev) * 0 - on success * error code - on error */ -#if 0 +#if 0 /* uboot */ static int SkGeClose( #else int SkGeClose( #endif -struct SK_NET_DEVICE *dev) +struct SK_NET_DEVICE *dev) /* the device that is to be closed */ { - DEV_NET *pNet; - SK_AC *pAC; + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + DEV_NET *newPtrNet; + unsigned long Flags; /* for the spin locks */ + unsigned long InitFlags; /* for the spin locks */ + int CurrMac; /* loop ctr for the current MAC */ + int PortIdx; +#ifdef CONFIG_SK98LIN_NAPI + int WorkToDo = 1; /* min(*budget, dev->quota); */ + int WorkDone = 0; +#endif + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, + ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); + spin_lock_irqsave(&pAC->InitLock, InitFlags); - unsigned long Flags; /* for spin lock */ - int i; - int PortIdx; - SK_EVPARA EvPara; +#ifdef Y2_RECOVERY + pNet->InRecover = SK_TRUE; +#if 0 /* uboot */ + del_timer(&pNet->KernelTimer); +#endif +#endif + + if (pAC->DiagModeActive == DIAG_ACTIVE) { + if (pAC->DiagFlowCtrl == SK_FALSE) { + MOD_DEC_USE_COUNT; + /* + ** notify that the interface which has been closed + ** by operator interaction must not be started up + ** again when the DIAG has finished. + */ + newPtrNet = (DEV_NET *) pAC->dev[0]->priv; + if (newPtrNet == pNet) { + pAC->WasIfUp[0] = SK_FALSE; + } else { + pAC->WasIfUp[1] = SK_FALSE; + } + return 0; /* return to system everything is fine... */ + } else { + pAC->DiagFlowCtrl = SK_FALSE; + } + } netif_stop_queue(dev); - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; if (pAC->RlmtNets == 1) PortIdx = pAC->ActivePort; else PortIdx = pNet->NetNr; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); - /* * Clear multicast table, promiscuous mode .... */ @@ -1944,53 +2731,116 @@ struct SK_NET_DEVICE *dev) spin_lock_irqsave(&pAC->SlowPathLock, Flags); /* disable interrupts */ SK_OUT32(pAC->IoBase, B0_IMSK, 0); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, + pNet->NetNr, -1, SK_TRUE); SK_OUT32(pAC->IoBase, B0_IMSK, 0); /* stop the hardware */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = 0; + + + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 1)) { + /* RLMT check link state mode */ + for (CurrMac=0; CurrMacGIni.GIMacsFound; CurrMac++) { + if (CHIP_ID_YUKON_2(pAC)) + SkY2PortStop( pAC, + pAC->IoBase, + CurrMac, + SK_STOP_ALL, + SK_HARD_RST); + else + SkGeStopPort( pAC, + pAC->IoBase, + CurrMac, + SK_STOP_ALL, + SK_HARD_RST); + } /* for */ + } else { + /* Single link or single port */ + if (CHIP_ID_YUKON_2(pAC)) + SkY2PortStop( pAC, + pAC->IoBase, + PortIdx, + SK_STOP_ALL, + SK_HARD_RST); + else + SkGeStopPort( pAC, + pAC->IoBase, + PortIdx, + SK_STOP_ALL, + SK_HARD_RST); + } spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); } else { - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, + pNet->NetNr, -1, SK_FALSE); + SkLocalEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET, + pNet->NetNr, -1, SK_TRUE); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - + /* Stop port */ spin_lock_irqsave(&pAC->TxPort[pNet->PortNr] [TX_PRIO_LOW].TxDesRingLock, Flags); - SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, - SK_STOP_ALL, SK_HARD_RST); + if (CHIP_ID_YUKON_2(pAC)) { + SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr, + SK_STOP_ALL, SK_HARD_RST); + } + else { + SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, + SK_STOP_ALL, SK_HARD_RST); + } spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr] [TX_PRIO_LOW].TxDesRingLock, Flags); } if (pAC->RlmtNets == 1) { /* clear all descriptor rings */ - for (i=0; iGIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]); + for (CurrMac=0; CurrMacGIni.GIMacsFound; CurrMac++) { + if (!CHIP_ID_YUKON_2(pAC)) { +#ifdef CONFIG_SK98LIN_NAPI + WorkToDo = 1; + ReceiveIrq(pAC,&pAC->RxPort[CurrMac], + SK_TRUE,&WorkDone,WorkToDo); +#else + ReceiveIrq(pAC,&pAC->RxPort[CurrMac],SK_TRUE); +#endif + ClearRxRing(pAC, &pAC->RxPort[CurrMac]); + ClearTxRing(pAC, &pAC->TxPort[CurrMac][TX_PRIO_LOW]); + } else { + SkY2FreeRxBuffers(pAC, pAC->IoBase, CurrMac); + SkY2FreeTxBuffers(pAC, pAC->IoBase, CurrMac); + } } } else { /* clear port descriptor rings */ - ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); - ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]); + if (!CHIP_ID_YUKON_2(pAC)) { +#ifdef CONFIG_SK98LIN_NAPI + WorkToDo = 1; + ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE, &WorkDone, WorkToDo); +#else + ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); +#endif + ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); + ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]); + } + else { + SkY2FreeRxBuffers(pAC, pAC->IoBase, pNet->PortNr); + SkY2FreeTxBuffers(pAC, pAC->IoBase, pNet->PortNr); + } } SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeClose: done ")); + SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); + SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), + sizeof(SK_PNMI_STRUCT_DATA)); + pAC->MaxPorts--; - pNet->Up = 0; - MOD_DEC_USE_COUNT; + +#ifdef Y2_RECOVERY + pNet->InRecover = SK_FALSE; +#endif + spin_unlock_irqrestore(&pAC->InitLock, InitFlags); return (0); } /* SkGeClose */ @@ -2024,14 +2874,13 @@ int Rc; /* return code of XmitFrame */ pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; -#if 0 +#if 0 /* uboot */ if ((!skb_shinfo(skb)->nr_frags) || #else - if (1 || + if(1 || #endif (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) { /* Don't activate scatter-gather and hardware checksum */ - if (pAC->RlmtNets == 2) Rc = XmitFrame( pAC, @@ -2043,7 +2892,7 @@ int Rc; /* return code of XmitFrame */ &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb); } else { -#if 0 +#if 0 /* uboot */ /* scatter-gather and hardware TCP checksumming anabled*/ if (pAC->RlmtNets == 2) Rc = XmitFrameSG( @@ -2059,9 +2908,11 @@ int Rc; /* return code of XmitFrame */ } /* Transmitter out of resources? */ +#ifdef USE_TX_COMPLETE if (Rc <= 0) { netif_stop_queue(dev); } +#endif /* If not taken, give buffer ownership back to the * queueing layer. @@ -2069,12 +2920,112 @@ int Rc; /* return code of XmitFrame */ if (Rc < 0) return (1); -#if 0 +#if 0 /* uboot */ dev->trans_start = jiffies; #endif return (0); } /* SkGeXmit */ +#ifdef CONFIG_SK98LIN_NAPI +/***************************************************************************** + * + * SkGePoll - NAPI Rx polling callback for GEnesis and Yukon chipsets + * + * Description: + * Called by the Linux system in case NAPI polling is activated + * + * Returns: + * The number of work data still to be handled + */ +static int SkGePoll(struct net_device *dev, int *budget) +{ + SK_AC *pAC = ((DEV_NET*)(dev->priv))->pAC; /* pointer to adapter context */ + int WorkToDo = min(*budget, dev->quota); + int WorkDone = 0; + unsigned long Flags; + + + if (pAC->dev[0] != pAC->dev[1]) { + spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); + FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]); + spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); + + ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE, &WorkDone, WorkToDo); + CLEAR_AND_START_RX(1); + } + spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); + FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); + spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); + + ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE, &WorkDone, WorkToDo); + CLEAR_AND_START_RX(0); + + *budget -= WorkDone; + dev->quota -= WorkDone; + + if(WorkDone < WorkToDo) { + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + netif_rx_complete(dev); + pAC->GIni.GIValIrqMask |= (NAPI_DRV_IRQS); +#ifndef USE_TX_COMPLETE + pAC->GIni.GIValIrqMask &= ~(TX_COMPL_IRQS); +#endif + /* enable interrupts again */ + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + } + return (WorkDone >= WorkToDo); +} /* SkGePoll */ +#endif + +/* uboot */ +unsigned long xchg(volatile int * m, unsigned long val) +{ + unsigned int retval; + retval = *m; + *m = val; + return retval; +} + + +#ifdef SK_POLL_CONTROLLER +/***************************************************************************** + * + * SkGeNetPoll - Polling "interrupt" + * + * Description: + * Polling 'interrupt' - used by things like netconsole and netdump + * to send skbs without having to re-enable interrupts. + * It's not called while the interrupt routine is executing. + */ +static void SkGeNetPoll( +struct SK_NET_DEVICE *dev) +{ +DEV_NET *pNet; +SK_AC *pAC; + + pNet = (DEV_NET*) dev->priv; + pAC = pNet->pAC; + pNet->NetConsoleMode = SK_TRUE; + + /* Prevent any reconfiguration while handling + the 'interrupt' */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + + if (!CHIP_ID_YUKON_2(pAC)) { + /* Handle the GENESIS Isr */ + if (pAC->GIni.GIMacsFound == 2) + SkGeIsr(dev->irq, dev, NULL); + else + SkGeIsrOnePort(dev->irq, dev, NULL); + } else { + /* Handle the Yukon2 Isr */ + SkY2Isr(dev->irq, dev, NULL); + } + +} +#endif + /***************************************************************************** * @@ -2099,24 +3050,35 @@ int Rc; /* return code of XmitFrame */ * < 0 - on failure: other problems ( -> return failure to upper layers) */ static int XmitFrame( -SK_AC *pAC, /* pointer to adapter context */ +SK_AC *pAC, /* pointer to adapter context */ TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ +struct sk_buff *pMessage) /* pointer to send-message */ { -TXD *pTxd; /* the rxd to fill */ -unsigned long Flags; -SK_U64 PhysAddr; -int BytesSend; + TXD *pTxd; /* the rxd to fill */ + TXD *pOldTxd; + unsigned long Flags; + SK_U64 PhysAddr; +#if 0 /* uboot */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("X")); + int Protocol; + int IpHeaderLength; +#endif + int BytesSend = pMessage->len; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X")); spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); #ifndef USE_TX_COMPLETE - FreeTxDescriptors(pAC, pTxPort); + if ((pTxPort->TxdRingPrevFree - pTxPort->TxdRingFree) > 6) { + FreeTxDescriptors(pAC, pTxPort); + pTxPort->TxdRingPrevFree = pTxPort->TxdRingFree; + } #endif if (pTxPort->TxdRingFree == 0) { - /* no enough free descriptors in ring at the moment */ + /* + ** not enough free descriptors in ring at the moment. + ** Maybe free'ing some old one help? + */ FreeTxDescriptors(pAC, pTxPort); if (pTxPort->TxdRingFree == 0) { spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); @@ -2124,63 +3086,118 @@ int BytesSend; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("XmitFrame failed\n")); - /* this message can not be sent now */ - /* Because tbusy seems to be set, the message should not be freed here */ - /* It will be used by the scheduler of the ethernet handler */ + /* + ** the desired message can not be sent + ** Because tbusy seems to be set, the message + ** should not be freed here. It will be used + ** by the scheduler of the ethernet handler + */ return (-1); } } - /* advance head counter behind descriptor needed for this frame */ + +#if 0 /* uboot*/ + /* + ** If the passed socket buffer is of smaller MTU-size than 60, + ** copy everything into new buffer and fill all bytes between + ** the original packet end and the new packet end of 60 with 0x00. + ** This is to resolve faulty padding by the HW with 0xaa bytes. + */ + if (BytesSend < C_LEN_ETHERNET_MINSIZE) { + if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) { + spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); + return 0; + } + pMessage->len = C_LEN_ETHERNET_MINSIZE; + } +#endif + + /* + ** advance head counter behind descriptor needed for this frame, + ** so that needed descriptor is reserved from that on. The next + ** action will be to add the passed buffer to the TX-descriptor + */ pTxd = pTxPort->pTxdRingHead; pTxPort->pTxdRingHead = pTxd->pNextTxd; pTxPort->TxdRingFree--; - /* the needed descriptor is reserved now */ - - /* - * everything allocated ok, so add buffer to descriptor - */ #ifdef SK_DUMP_TX DumpMsg(pMessage, "XmitFrame"); #endif - /* set up descriptor and CONTROL dword */ -#if 0 + /* + ** First step is to map the data to be sent via the adapter onto + ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4 + ** and 2.6 need to use pci_map_page() for that mapping. + */ +#if 0 /* uboot */ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMessage->data), - ((unsigned long) pMessage->data & - ~PAGE_MASK), - pMessage->len, - PCI_DMA_TODEVICE); + virt_to_page(pMessage->data), + ((unsigned long) pMessage->data & ~PAGE_MASK), + pMessage->len, + PCI_DMA_TODEVICE); #else - PhysAddr = (SK_U64) pci_phys_to_mem(pAC->PciDev, (u32) pMessage->data); + PhysAddr = (SK_U64)(SK_U32)pMessage->data; #endif - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF | - TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE | + pTxd->pMBuf = pMessage; + +#if 0 /* uboot */ + if (pMessage->ip_summed == CHECKSUM_HW) { + Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); + if ((Protocol == C_PROTO_ID_UDP) && + (pAC->GIni.GIChipRev == 0) && + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + pTxd->TBControl = BMU_TCP_CHECK; + } else { + pTxd->TBControl = BMU_UDP_CHECK; + } + + IpHeaderLength = (SK_U8)pMessage->data[C_OFFSET_IPHEADER]; + IpHeaderLength = (IpHeaderLength & 0xf) * 4; + pTxd->TcpSumOfs = 0; /* PH-Checksum already calculated */ + pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength + + (Protocol == C_PROTO_ID_UDP ? + C_OFFSET_UDPHEADER_UDPCS : + C_OFFSET_TCPHEADER_TCPCS); + pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength; + + pTxd->TBControl |= BMU_OWN | BMU_STF | + BMU_SW | BMU_EOF | #ifdef USE_TX_COMPLETE - TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len; -#else - TX_CTRL_EOF | pMessage->len; + BMU_IRQ_EOF | #endif - - if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { - /* previous descriptor already done, so give tx start cmd */ - /* StartTx(pAC, pTxPort->HwAddr); */ - SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); + pMessage->len; + } else +#endif + { + pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | + BMU_SW | BMU_EOF | +#ifdef USE_TX_COMPLETE + BMU_IRQ_EOF | +#endif + pMessage->len; } - pTxPort->pTxdRingPrev = pTxd; + /* + ** If previous descriptor already done, give TX start cmd + */ + /* uboot */ + pOldTxd = (TXD *)xchg((int *)&pTxPort->pTxdRingPrev, (unsigned int)pTxd); + if ((pOldTxd->TBControl & BMU_OWN) == 0) { + SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START); + } - BytesSend = pMessage->len; + /* + ** after releasing the lock, the skb may immediately be free'd + */ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - /* after releasing the lock, the skb may be immidiately freed */ - if (pTxPort->TxdRingFree != 0) + if (pTxPort->TxdRingFree != 0) { return (BytesSend); - else + } else { return (0); + } } /* XmitFrame */ @@ -2199,23 +3216,23 @@ int BytesSend; * the ring is full ( -> set tbusy) * < 0 - on failure: other problems ( -> return failure to upper layers) */ -#if 0 +#if 0 /* uboot */ static int XmitFrameSG( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ +SK_AC *pAC, /* pointer to adapter context */ +TX_PORT *pTxPort, /* pointer to struct of port to send to */ +struct sk_buff *pMessage) /* pointer to send-message */ { - int i; - int BytesSend; - int hlength; - int protocol; - skb_frag_t *sk_frag; - TXD *pTxd; - TXD *pTxdFst; - TXD *pTxdLst; - SK_U64 PhysAddr; - unsigned long Flags; + TXD *pTxd; + TXD *pTxdFst; + TXD *pTxdLst; + int CurrFrag; + int BytesSend; + int IpHeaderLength; + int Protocol; + skb_frag_t *sk_frag; + SK_U64 PhysAddr; + unsigned long Flags; spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); #ifndef USE_TX_COMPLETE @@ -2234,114 +3251,123 @@ struct sk_buff *pMessage) /* pointer to send-message */ } } - - pTxd = pTxPort->pTxdRingHead; - pTxdFst = pTxd; - pTxdLst = pTxd; + pTxd = pTxPort->pTxdRingHead; + pTxdFst = pTxd; + pTxdLst = pTxd; BytesSend = 0; - protocol = 0; + Protocol = 0; - /* map first fragment (header) */ + /* + ** Map the first fragment (header) into the DMA-space + */ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, virt_to_page(pMessage->data), ((unsigned long) pMessage->data & ~PAGE_MASK), skb_headlen(pMessage), PCI_DMA_TODEVICE); - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - /* HW checksum? */ + /* + ** Does the HW need to evaluate checksum for TCP or UDP packets? + */ if (pMessage->ip_summed == CHECKSUM_HW) { - pTxd->TBControl = TX_CTRL_STF | - TX_CTRL_ST_FWD | - skb_headlen(pMessage); + pTxd->TBControl = BMU_STF | BMU_STFWD | skb_headlen(pMessage); + /* + ** We have to use the opcode for tcp here, because the + ** opcode for udp is not working in the hardware yet + ** (Revision 2.0) + */ + Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); + if ((Protocol == C_PROTO_ID_UDP) && + (pAC->GIni.GIChipRev == 0) && + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + pTxd->TBControl |= BMU_TCP_CHECK; + } else { + pTxd->TBControl |= BMU_UDP_CHECK; + } - /* We have to use the opcode for tcp here because the opcode for - udp is not working in the hardware yet (revision 2.0)*/ - protocol = ((SK_U8)pMessage->data[23] & 0xf); - if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) - pTxd->TBControl |= BMU_UDP_CHECK; - else - pTxd->TBControl |= BMU_TCP_CHECK ; - - hlength = ((SK_U8)pMessage->data[14] & 0xf) * 4; + IpHeaderLength = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4; pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */ - pTxd->TcpSumSt = 14+hlength+16; - pTxd->TcpSumWr = 14+hlength; - + pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength + + (Protocol == C_PROTO_ID_UDP ? + C_OFFSET_UDPHEADER_UDPCS : + C_OFFSET_TCPHEADER_TCPCS); + pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength; } else { - pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | - TX_CTRL_SOFTWARE | - TX_CTRL_STF | - skb_headlen(pMessage); + pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF | + skb_headlen(pMessage); } pTxd = pTxd->pNextTxd; pTxPort->TxdRingFree--; BytesSend += skb_headlen(pMessage); - - /* Map SG fragments */ - for (i = 0; i < skb_shinfo(pMessage)->nr_frags; i++) { - sk_frag = &skb_shinfo(pMessage)->frags[i]; - - /* we already have the proper value in entry */ + /* + ** Browse over all SG fragments and map each of them into the DMA space + */ + for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) { + sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag]; + /* + ** we already have the proper value in entry + */ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, sk_frag->page, sk_frag->page_offset, sk_frag->size, PCI_DMA_TODEVICE); - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - - /* HW checksum */ + pTxd->pMBuf = pMessage; + + /* + ** Does the HW need to evaluate checksum for TCP or UDP packets? + */ if (pMessage->ip_summed == CHECKSUM_HW) { - pTxd->TBControl = TX_CTRL_OWN_BMU | - TX_CTRL_SOFTWARE | - TX_CTRL_ST_FWD; - - /* We have to use the opcode for tcp here because the opcode for - udp is not working in the hardware yet (revision 2.0)*/ - if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) - pTxd->TBControl |= BMU_UDP_CHECK ; - else - pTxd->TBControl |= BMU_TCP_CHECK ; - + pTxd->TBControl = BMU_OWN | BMU_SW | BMU_STFWD; + /* + ** We have to use the opcode for tcp here because the + ** opcode for udp is not working in the hardware yet + ** (revision 2.0) + */ + if ((Protocol == C_PROTO_ID_UDP) && + (pAC->GIni.GIChipRev == 0) && + (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { + pTxd->TBControl |= BMU_TCP_CHECK; + } else { + pTxd->TBControl |= BMU_UDP_CHECK; + } } else { - pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | - TX_CTRL_SOFTWARE | - TX_CTRL_OWN_BMU; + pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN; } - /* Last fragment */ - if( (i+1) == skb_shinfo(pMessage)->nr_frags ) { + /* + ** Do we have the last fragment? + */ + if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) { #ifdef USE_TX_COMPLETE - pTxd->TBControl |= TX_CTRL_EOF | - TX_CTRL_EOF_IRQ | - sk_frag->size; + pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF | sk_frag->size; #else - pTxd->TBControl |= TX_CTRL_EOF | - sk_frag->size; + pTxd->TBControl |= BMU_EOF | sk_frag->size; #endif - pTxdFst->TBControl |= TX_CTRL_OWN_BMU | - TX_CTRL_SOFTWARE; + pTxdFst->TBControl |= BMU_OWN | BMU_SW; } else { pTxd->TBControl |= sk_frag->size; } pTxdLst = pTxd; - pTxd = pTxd->pNextTxd; + pTxd = pTxd->pNextTxd; pTxPort->TxdRingFree--; BytesSend += sk_frag->size; } - if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { - /* previous descriptor already done, so give tx start cmd */ - /* StartTx(pAC, pTxPort->HwAddr); */ - SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); + /* + ** If previous descriptor already done, give TX start cmd + */ + if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) { + SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START); } pTxPort->pTxdRingPrev = pTxdLst; @@ -2349,29 +3375,14 @@ struct sk_buff *pMessage) /* pointer to send-message */ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - if (pTxPort->TxdRingFree > 0) + if (pTxPort->TxdRingFree > 0) { return (BytesSend); - else + } else { return (0); -} -#endif - - -void dump_frag( SK_U8 *data, int length) -{ - int i; - - printk("Length: %d\n", length); - for( i=0; i < length; i++ ) { - printk(" %02x", (SK_U8)*(data + i) ); - if( !((i+1) % 20) ) - printk("\n"); } - printk("\n\n"); - } - +#endif /***************************************************************************** * * FreeTxDescriptors - release descriptors from the descriptor ring @@ -2400,44 +3411,48 @@ SK_U32 Control; /* TBControl field of descriptor */ SK_U64 PhysAddr; /* address of DMA mapping */ pNewTail = pTxPort->pTxdRingTail; - pTxd = pNewTail; + pTxd = pNewTail; /* - * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame - * or TX_CTRL_OWN_BMU bit set in any frame - */ + ** loop forever; exits if BMU_SW bit not set in start frame + ** or BMU_OWN bit set in any frame + */ while (1) { Control = pTxd->TBControl; - if ((Control & TX_CTRL_SOFTWARE) == 0) { + if ((Control & BMU_SW) == 0) { /* - * software controllable bit is set in first - * fragment when given to BMU. Not set means that - * this fragment was never sent or is already - * freed ( -> ring completely free now). - */ + ** software controllable bit is set in first + ** fragment when given to BMU. Not set means that + ** this fragment was never sent or is already + ** freed ( -> ring completely free now). + */ pTxPort->pTxdRingTail = pTxd; netif_wake_queue(pAC->dev[pTxPort->PortIndex]); return; } - if (Control & TX_CTRL_OWN_BMU) { + if (Control & BMU_OWN) { pTxPort->pTxdRingTail = pTxd; if (pTxPort->TxdRingFree > 0) { netif_wake_queue(pAC->dev[pTxPort->PortIndex]); } return; } - - /* release the DMA mapping */ + + /* + ** release the DMA mapping, because until not unmapped + ** this buffer is considered being under control of the + ** adapter card! + */ PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32; PhysAddr |= (SK_U64) pTxd->VDataLow; pci_unmap_page(pAC->PciDev, PhysAddr, pTxd->pMBuf->len, PCI_DMA_TODEVICE); - if (Control & TX_CTRL_EOF) + if (Control & BMU_EOF) DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */ pTxPort->TxdRingFree++; - pTxd->TBControl &= ~TX_CTRL_SOFTWARE; + pTxd->TBControl &= ~BMU_SW; pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */ } /* while(forever) */ } /* FreeTxDescriptors */ @@ -2455,7 +3470,7 @@ SK_U64 PhysAddr; /* address of DMA mapping */ * Description of rx ring structure: * head - points to the descriptor which will be used next by the BMU * tail - points to the next descriptor to give to the BMU - * + * * Returns: N/A */ static void FillRxRing( @@ -2495,7 +3510,7 @@ RXD *pRxd; /* the rxd to fill */ SK_U16 Length; /* data fragment length */ SK_U64 PhysAddr; /* physical address of a rx buffer */ - pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC); + pMsgBlock = alloc_skb(pRxPort->RxBufSize, GFP_ATOMIC); if (pMsgBlock == NULL) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, @@ -2509,22 +3524,26 @@ SK_U64 PhysAddr; /* physical address of a rx buffer */ pRxd = pRxPort->pRxdRingTail; pRxPort->pRxdRingTail = pRxd->pNextRxd; pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; -#if 0 + Length = pRxPort->RxBufSize; +#if 0 /* uboot */ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, virt_to_page(pMsgBlock->data), ((unsigned long) pMsgBlock->data & ~PAGE_MASK), - pAC->RxBufSize - 2, + pRxPort->RxBufSize - 2, PCI_DMA_FROMDEVICE); + #else - PhysAddr = (SK_U64) pci_phys_to_mem(pAC->PciDev, (u32)pMsgBlock->data); + PhysAddr = (SK_U64)(SK_U32)pMsgBlock->data; #endif - pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); + pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pRxd->pMBuf = pMsgBlock; - pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF | - RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length; + pRxd->pMBuf = pMsgBlock; + pRxd->RBControl = BMU_OWN | + BMU_STF | + BMU_IRQ_EOF | + BMU_TCP_CHECK | + Length; return (SK_TRUE); } /* FillRxDescriptor */ @@ -2554,16 +3573,19 @@ SK_U16 Length; /* data fragment length */ pRxd = pRxPort->pRxdRingTail; pRxPort->pRxdRingTail = pRxd->pNextRxd; pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; - pRxd->VDataLow = PhysLow; + Length = pRxPort->RxBufSize; + + pRxd->VDataLow = PhysLow; pRxd->VDataHigh = PhysHigh; - pRxd->pMBuf = pMsg; - pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF | - RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length; + pRxd->pMBuf = pMsg; + pRxd->RBControl = BMU_OWN | + BMU_STF | + BMU_IRQ_EOF | + BMU_TCP_CHECK | + Length; return; } /* ReQueueRxBuffer */ - /***************************************************************************** * * ReceiveIrq - handle a receive IRQ @@ -2575,42 +3597,50 @@ SK_U16 Length; /* data fragment length */ * * Returns: N/A */ -#if 0 +#if 0 /* uboot */ static void ReceiveIrq( #else void ReceiveIrq( #endif - SK_AC *pAC, /* pointer to adapter context */ - RX_PORT *pRxPort, /* pointer to receive port struct */ - SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */ -{ -RXD *pRxd; /* pointer to receive descriptors */ -SK_U32 Control; /* control field of descriptor */ -struct sk_buff *pMsg; /* pointer to message holding frame */ -struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */ -int FrameLength; /* total length of received frame */ -SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */ -SK_EVPARA EvPara; /* an event parameter union */ -unsigned long Flags; /* for spin lock */ -int PortIndex = pRxPort->PortIndex; -unsigned int Offset; -unsigned int NumBytes; -unsigned int ForRlmt; -SK_BOOL IsBc; -SK_BOOL IsMc; -SK_BOOL IsBadFrame; /* Bad frame */ - -SK_U32 FrameStat; -unsigned short Csum1; -unsigned short Csum2; -unsigned short Type; -#if 0 -int Result; +#ifdef CONFIG_SK98LIN_NAPI +SK_AC *pAC, /* pointer to adapter context */ +RX_PORT *pRxPort, /* pointer to receive port struct */ +SK_BOOL SlowPathLock, /* indicates if SlowPathLock is needed */ +int *WorkDone, +int WorkToDo) +#else +SK_AC *pAC, /* pointer to adapter context */ +RX_PORT *pRxPort, /* pointer to receive port struct */ +SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */ #endif -SK_U64 PhysAddr; +{ + RXD *pRxd; /* pointer to receive descriptors */ + struct sk_buff *pMsg; /* pointer to message holding frame */ + struct sk_buff *pNewMsg; /* pointer to new message for frame copy */ + SK_MBUF *pRlmtMbuf; /* ptr to buffer for giving frame to RLMT */ + SK_EVPARA EvPara; /* an event parameter union */ + SK_U32 Control; /* control field of descriptor */ + unsigned long Flags; /* for spin lock handling */ + int PortIndex = pRxPort->PortIndex; + int FrameLength; /* total length of received frame */ + int IpFrameLength; /* IP length of the received frame */ + unsigned int Offset; + unsigned int NumBytes; + unsigned int RlmtNotifier; + SK_BOOL IsBc; /* we received a broadcast packet */ + SK_BOOL IsMc; /* we received a multicast packet */ + SK_BOOL IsBadFrame; /* the frame received is bad! */ + SK_U32 FrameStat; + unsigned short Csum1; + unsigned short Csum2; + unsigned short Type; +#if 0 /* uboot */ + int Result; +#endif + SK_U64 PhysAddr; -rx_start: - /* do forever; exit if RX_CTRL_OWN_BMU found */ +rx_start: + /* do forever; exit if BMU_OWN found */ for ( pRxd = pRxPort->pRxdRingHead ; pRxPort->RxdRingFree < pAC->RxDescrPerRing ; pRxd = pRxd->pNextRxd, @@ -2628,9 +3658,16 @@ rx_start: */ Control = pRxd->RBControl; + +#ifdef CONFIG_SK98LIN_NAPI + if (*WorkDone >= WorkToDo) { + break; + } + (*WorkDone)++; +#endif /* check if this descriptor is ready */ - if ((Control & RX_CTRL_OWN_BMU) != 0) { + if ((Control & BMU_OWN) != 0) { /* this descriptor is not yet ready */ /* This is the usual end of the loop */ /* We don't need to start the ring again */ @@ -2639,14 +3676,13 @@ rx_start: } /* get length of frame and check it */ - FrameLength = Control & RX_CTRL_LEN_MASK; - if (FrameLength > pAC->RxBufSize) { + FrameLength = Control & BMU_BBC; + if (FrameLength > pRxPort->RxBufSize) { goto rx_failed; } /* check for STF and EOF */ - if ((Control & (RX_CTRL_STF | RX_CTRL_EOF)) != - (RX_CTRL_STF | RX_CTRL_EOF)) { + if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) { goto rx_failed; } @@ -2656,8 +3692,8 @@ rx_start: FrameStat = pRxd->FrameStat; /* check for frame length mismatch */ -#define XMR_FS_LEN_SHIFT 18 -#define GMR_FS_LEN_SHIFT 16 +#define XMR_FS_LEN_SHIFT 18 +#define GMR_FS_LEN_SHIFT 16 if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, @@ -2667,8 +3703,7 @@ rx_start: (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); goto rx_failed; } - } - else { + } else { if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, @@ -2700,8 +3735,7 @@ rx_start: pRxPort->RxdRingFree)); /* DumpMsg(pMsg, "Rx"); */ - if ((Control & RX_CTRL_STAT_VALID) != RX_CTRL_STAT_VALID || - (IsBadFrame)) { + if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) { #if 0 (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) { #endif @@ -2737,7 +3771,6 @@ rx_start: skb_put(pNewMsg, FrameLength); PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_dma_sync_single(pAC->PciDev, (dma_addr_t) PhysAddr, FrameLength, @@ -2746,111 +3779,100 @@ rx_start: FrameLength, 0); ReQueueRxBuffer(pAC, pRxPort, pMsg, pRxd->VDataHigh, pRxd->VDataLow); + pMsg = pNewMsg; - } - else { + } else { /* * if large frame, or SKB allocation failed, pass * the SKB directly to the networking */ - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; PhysAddr |= (SK_U64) pRxd->VDataLow; /* release the DMA mapping */ pci_unmap_single(pAC->PciDev, PhysAddr, - pAC->RxBufSize - 2, + pRxPort->RxBufSize - 2, PCI_DMA_FROMDEVICE); - - /* set length in message */ - skb_put(pMsg, FrameLength); - /* hardware checksum */ - Type = ntohs(*((short*)&pMsg->data[12])); - if (Type == 0x800) { - Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff); - Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff); -#if 0 - if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) && - (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) || - (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - Result = SkCsGetReceiveInfo(pAC, - &pMsg->data[14], - Csum1, Csum2, pRxPort->PortIndex); - if (Result == - SKCS_STATUS_IP_FRAGMENT || - Result == - SKCS_STATUS_IP_CSUM_OK || - Result == - SKCS_STATUS_TCP_CSUM_OK || - Result == - SKCS_STATUS_UDP_CSUM_OK) { - pMsg->ip_summed = - CHECKSUM_UNNECESSARY; - } else { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: CRC error. Frame dropped!\n")); - goto rx_failed; - } - }/* checksumControl calculation valid */ + skb_put(pMsg, FrameLength); /* set message len */ +#if 0 /* uboot */ + pMsg->ip_summed = CHECKSUM_NONE; /* initial default */ #endif - } /* IP frame */ + + if (pRxPort->UseRxCsum) { + Type = ntohs(*((short*)&pMsg->data[12])); + if (Type == 0x800) { + IpFrameLength = (int) ntohs((unsigned short) + ((unsigned short *) pMsg->data)[8]); + if ((FrameLength - IpFrameLength) == 0xe) { + Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff); + Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff); +#if 0 /* uboot */ + if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) && + (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) || + (pAC->ChipsetType)) { + Result = SkCsGetReceiveInfo(pAC, &pMsg->data[14], + Csum1, Csum2, PortIndex); + if ((Result == SKCS_STATUS_IP_FRAGMENT) || + (Result == SKCS_STATUS_IP_CSUM_OK) || + (Result == SKCS_STATUS_TCP_CSUM_OK) || + (Result == SKCS_STATUS_UDP_CSUM_OK)) { + pMsg->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR) || + (Result == SKCS_STATUS_UDP_CSUM_ERROR) || + (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) || + (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) || + (Result == SKCS_STATUS_IP_CSUM_ERROR)) { + /* HW Checksum error */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS, + ("skge: CRC error. Frame dropped!\n")); + goto rx_failed; + } else { + pMsg->ip_summed = CHECKSUM_NONE; + } + }/* checksumControl calculation valid */ +#endif + } /* Frame length check */ + } /* IP frame */ + } /* pRxPort->UseRxCsum */ } /* frame > SK_COPY_TRESHOLD */ - + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); - ForRlmt = SK_RLMT_RX_PROTOCOL; -#if 0 - IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC; -#endif + RlmtNotifier = SK_RLMT_RX_PROTOCOL; SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength, - IsBc, &Offset, &NumBytes); + IsBc, &Offset, &NumBytes); if (NumBytes != 0) { -#if 0 - IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC; -#endif - SK_RLMT_LOOKAHEAD(pAC, PortIndex, - &pMsg->data[Offset], - IsBc, IsMc, &ForRlmt); + SK_RLMT_LOOKAHEAD(pAC,PortIndex,&pMsg->data[Offset], + IsBc,IsMc,&RlmtNotifier); } - if (ForRlmt == SK_RLMT_RX_PROTOCOL) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W")); + if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W")); /* send up only frames from active port */ - if ((PortIndex == pAC->ActivePort) || - (pAC->RlmtNets == 2)) { - /* frame for upper layer */ + if ((PortIndex == pAC->ActivePort)||(pAC->RlmtNets == 2)) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U")); #ifdef xDEBUG DumpMsg(pMsg, "Rx"); #endif - SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, - FrameLength, pRxPort->PortIndex); - -#if 0 - pMsg->dev = pAC->dev[pRxPort->PortIndex]; - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); - netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; +#if 0 /* uboot */ + SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,FrameLength,PortIndex); + pMsg->dev = pAC->dev[PortIndex]; + pMsg->protocol = eth_type_trans(pMsg,pAC->dev[PortIndex]); + netif_rx(pMsg); /* frame for upper layer */ + pAC->dev[PortIndex]->last_rx = jiffies; #else - NetReceive(pMsg->data, pMsg->len); - dev_kfree_skb_any(pMsg); + NetReceive(pMsg->data, pMsg->len); + dev_kfree_skb_any(pMsg); #endif - } - else { - /* drop frame */ + } else { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("D")); - DEV_KFREE_SKB(pMsg); + SK_DBGCAT_DRV_RX_PROGRESS,("D")); + DEV_KFREE_SKB(pMsg); /* drop frame */ } - - } /* if not for rlmt */ - else { - /* packet for rlmt */ + } else { /* packet for RLMT stack */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, ("R")); + SK_DBGCAT_DRV_RX_PROGRESS,("R")); pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC, pAC->IoBase, FrameLength); if (pRlmtMbuf != NULL) { @@ -2878,37 +3900,26 @@ rx_start: } SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("Q")); + SK_DBGCAT_DRV_RX_PROGRESS,("Q")); } -#if 0 - if ((pAC->dev[pRxPort->PortIndex]->flags & - (IFF_PROMISC | IFF_ALLMULTI)) != 0 || - (ForRlmt & SK_RLMT_RX_PROTOCOL) == - SK_RLMT_RX_PROTOCOL) { - pMsg->dev = pAC->dev[pRxPort->PortIndex]; - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); +#if 0 /* uboot */ + if ((pAC->dev[PortIndex]->flags & (IFF_PROMISC | IFF_ALLMULTI)) || + (RlmtNotifier & SK_RLMT_RX_PROTOCOL)) { + pMsg->dev = pAC->dev[PortIndex]; + pMsg->protocol = eth_type_trans(pMsg,pAC->dev[PortIndex]); netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; - } + pAC->dev[PortIndex]->last_rx = jiffies; #else if (0) { - } #endif - else { + } else { DEV_KFREE_SKB(pMsg); } - - } /* if packet for rlmt */ + } /* if packet for RLMT stack */ } /* for ... scanning the RXD ring */ /* RXD ring is empty -> fill and restart */ FillRxRing(pAC, pRxPort); - /* do not start if called from Close */ - if (pAC->BoardLevel > 0) { - ClearAndStartRx(pAC, PortIndex); - } return; rx_failed: @@ -2922,7 +3933,7 @@ rx_failed: PhysAddr |= (SK_U64) pRxd->VDataLow; pci_unmap_page(pAC->PciDev, PhysAddr, - pAC->RxBufSize - 2, + pRxPort->RxBufSize - 2, PCI_DMA_FROMDEVICE); DEV_KFREE_SKB_IRQ(pRxd->pMBuf); pRxd->pMBuf = NULL; @@ -2932,47 +3943,6 @@ rx_failed: } /* ReceiveIrq */ - -/***************************************************************************** - * - * ClearAndStartRx - give a start receive command to BMU, clear IRQ - * - * Description: - * This function sends a start command and a clear interrupt - * command for one receive queue to the BMU. - * - * Returns: N/A - * none - */ -static void ClearAndStartRx( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex) /* index of the receive port (XMAC) */ -{ - SK_OUT8(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CTRL, - RX_Q_CTRL_START | RX_Q_CTRL_CLR_I_EOF); -} /* ClearAndStartRx */ - - -/***************************************************************************** - * - * ClearTxIrq - give a clear transmit IRQ command to BMU - * - * Description: - * This function sends a clear tx IRQ command for one - * transmit queue to the BMU. - * - * Returns: N/A - */ -static void ClearTxIrq( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex, /* index of the transmit port (XMAC) */ -int Prio) /* priority or normal queue */ -{ - SK_OUT8(pAC->IoBase, TxQueueAddr[PortIndex][Prio]+TX_Q_CTRL, - TX_Q_CTRL_CLR_I_EOF); -} /* ClearTxIrq */ - - /***************************************************************************** * * ClearRxRing - remove all buffers from the receive ring @@ -3003,12 +3973,12 @@ SK_U64 PhysAddr; PhysAddr |= (SK_U64) pRxd->VDataLow; pci_unmap_page(pAC->PciDev, PhysAddr, - pAC->RxBufSize - 2, + pRxPort->RxBufSize - 2, PCI_DMA_FROMDEVICE); DEV_KFREE_SKB(pRxd->pMBuf); pRxd->pMBuf = NULL; } - pRxd->RBControl &= RX_CTRL_OWN_BMU; + pRxd->RBControl &= BMU_OWN; pRxd = pRxd->pNextRxd; pRxPort->RxdRingFree++; } while (pRxd != pRxPort->pRxdRingTail); @@ -3016,7 +3986,6 @@ SK_U64 PhysAddr; spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); } /* ClearRxRing */ - /***************************************************************************** * * ClearTxRing - remove all buffers from the transmit ring @@ -3041,108 +4010,14 @@ unsigned long Flags; spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); pTxd = pTxPort->pTxdRingHead; for (i=0; iTxDescrPerRing; i++) { - pTxd->TBControl &= ~TX_CTRL_OWN_BMU; + pTxd->TBControl &= ~BMU_OWN; pTxd = pTxd->pNextTxd; } FreeTxDescriptors(pAC, pTxPort); spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); } /* ClearTxRing */ - -#if 0 -/***************************************************************************** - * - * SetQueueSizes - configure the sizes of rx and tx queues - * - * Description: - * This function assigns the sizes for active and passive port - * to the appropriate HWinit structure variables. - * The passive port(s) get standard values, all remaining RAM - * is given to the active port. - * The queue sizes are in kbyte and must be multiple of 8. - * The limits for the number of buffers filled into the rx rings - * is also set in this routine. - * - * Returns: - * none - */ -static void SetQueueSizes( -SK_AC *pAC) /* pointer to the adapter context */ -{ -int StandbyRam; /* adapter RAM used for a standby port */ -int RemainingRam; /* adapter RAM available for the active port */ -int RxRam; /* RAM used for the active port receive queue */ -int i; /* loop counter */ - -if (pAC->RlmtNets == 1) { - StandbyRam = SK_RLMT_STANDBY_QRXSIZE + SK_RLMT_STANDBY_QXASIZE + - SK_RLMT_STANDBY_QXSSIZE; - RemainingRam = pAC->GIni.GIRamSize - - (pAC->GIni.GIMacsFound-1) * StandbyRam; - for (i=0; iGIni.GIMacsFound; i++) { - pAC->GIni.GP[i].PRxQSize = SK_RLMT_STANDBY_QRXSIZE; - pAC->GIni.GP[i].PXSQSize = SK_RLMT_STANDBY_QXSSIZE; - pAC->GIni.GP[i].PXAQSize = SK_RLMT_STANDBY_QXASIZE; - } - RxRam = (RemainingRam * 8 / 10) & ~7; - pAC->GIni.GP[pAC->ActivePort].PRxQSize = RxRam; - pAC->GIni.GP[pAC->ActivePort].PXSQSize = 0; - pAC->GIni.GP[pAC->ActivePort].PXAQSize = - (RemainingRam - RxRam) & ~7; - pAC->RxQueueSize = RxRam; - pAC->TxSQueueSize = 0; - pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("queue sizes settings - rx:%d txA:%d txS:%d\n", - pAC->RxQueueSize,pAC->TxAQueueSize, pAC->TxSQueueSize)); -} else { - RemainingRam = pAC->GIni.GIRamSize/pAC->GIni.GIMacsFound; - RxRam = (RemainingRam * 8 / 10) & ~7; - for (i=0; iGIni.GIMacsFound; i++) { - pAC->GIni.GP[i].PRxQSize = RxRam; - pAC->GIni.GP[i].PXSQSize = 0; - pAC->GIni.GP[i].PXAQSize = (RemainingRam - RxRam) & ~7; - } - - pAC->RxQueueSize = RxRam; - pAC->TxSQueueSize = 0; - pAC->TxAQueueSize = (RemainingRam - RxRam) & ~7; -} - for (i=0; iRxPort[i].RxFillLimit = pAC->RxDescrPerRing; - } - - if (pAC->RlmtNets == 2) { - for (i=0; iGIni.GIMacsFound; i++) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100; - } - } else { - for (i=0; iGIni.GIMacsFound; i++) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 100; - } - /* - * Do not set the Limit to 0, because this could cause - * wrap around with ReQueue'ed buffers (a buffer could - * be requeued in the same position, made accessable to - * the hardware, and the hardware could change its - * contents! - */ - pAC->RxPort[pAC->ActivePort].RxFillLimit = 1; - } - -#ifdef DEBUG - for (i=0; iGIni.GIMacsFound; i++) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("i: %d, RxQSize: %d, PXSQsize: %d, PXAQSize: %d\n", - i, - pAC->GIni.GP[i].PRxQSize, - pAC->GIni.GP[i].PXSQSize, - pAC->GIni.GP[i].PXAQSize)); - } -#endif -} /* SetQueueSizes */ - - +#if 0 /* uboot */ /***************************************************************************** * * SkGeSetMacAddr - Set the hardware MAC address @@ -3159,31 +4034,32 @@ static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p) DEV_NET *pNet = (DEV_NET*) dev->priv; SK_AC *pAC = pNet->pAC; +int Ret; struct sockaddr *addr = p; unsigned long Flags; - + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeSetMacAddr starts now...\n")); - if(netif_running(dev)) - return -EBUSY; memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - + spin_lock_irqsave(&pAC->SlowPathLock, Flags); if (pAC->RlmtNets == 2) - SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr, + Ret = SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr, (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); else - SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort, + Ret = SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort, (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); - - + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + + if (Ret != SK_ADDR_OVERRIDE_SUCCESS) + return -EBUSY; + return 0; } /* SkGeSetMacAddr */ -#endif /***************************************************************************** @@ -3200,7 +4076,6 @@ unsigned long Flags; * 0, if everything is ok * !=0, on error */ -#if 0 static void SkGeSetRxMode(struct SK_NET_DEVICE *dev) { @@ -3240,7 +4115,7 @@ unsigned long Flags; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("Number of MC entries: %d ", dev->mc_count)); - + pMcList = dev->mc_list; for (i=0; imc_count; i++, pMcList = pMcList->next) { SkAddrMcAdd(pAC, pAC->IoBase, PortIdx, @@ -3257,11 +4132,50 @@ unsigned long Flags; SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx); } spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - + return; } /* SkGeSetRxMode */ +/***************************************************************************** + * + * SkSetMtuBufferSize - set the MTU buffer to another value + * + * Description: + * This function sets the new buffers and is called whenever the MTU + * size is changed + * + * Returns: + * N/A + */ + +static void SkSetMtuBufferSize( +SK_AC *pAC, /* pointer to adapter context */ +int PortNr, /* Port number */ +int Mtu) /* pointer to tx prt struct */ +{ + pAC->RxPort[PortNr].RxBufSize = Mtu + 32; + + /* RxBufSize must be a multiple of 8 */ + while (pAC->RxPort[PortNr].RxBufSize % 8) { + pAC->RxPort[PortNr].RxBufSize = + pAC->RxPort[PortNr].RxBufSize + 1; + } + + if (Mtu > 1500) { + pAC->GIni.GP[PortNr].PPortUsage = SK_JUMBO_LINK; + } else { + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { + pAC->GIni.GP[PortNr].PPortUsage = SK_MUL_LINK; + } else { + pAC->GIni.GP[PortNr].PPortUsage = SK_RED_LINK; + } + } + + return; +} + + /***************************************************************************** * * SkGeChangeMtu - set the MTU to another value @@ -3277,212 +4191,107 @@ unsigned long Flags; */ static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu) { -DEV_NET *pNet; -DEV_NET *pOtherNet; -SK_AC *pAC; -unsigned long Flags; -int i; -SK_EVPARA EvPara; +DEV_NET *pNet; +SK_AC *pAC; +unsigned long Flags; +#ifdef CONFIG_SK98LIN_NAPI +int WorkToDo = 1; // min(*budget, dev->quota); +int WorkDone = 0; +#endif SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeChangeMtu starts now...\n")); pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; + pAC = pNet->pAC; + /* MTU size outside the spec */ if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) { return -EINVAL; } - if(pAC->BoardLevel != 2) { + /* MTU > 1500 on yukon ulra not allowed */ + if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) + && (NewMtu > 1500)){ return -EINVAL; } - pNet->Mtu = NewMtu; - pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv; - if ((pOtherNet->Mtu > 1500) && (NewMtu <= 1500) && (pOtherNet->Up==1)) { - return(0); + /* Diag access active */ + if (pAC->DiagModeActive == DIAG_ACTIVE) { + if (pAC->DiagFlowCtrl == SK_FALSE) { + return -1; /* still in use, deny any actions of MTU */ + } else { + pAC->DiagFlowCtrl = SK_FALSE; + } } - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - - pAC->RxBufSize = NewMtu + 32; dev->mtu = NewMtu; + SkSetMtuBufferSize(pAC, pNet->PortNr, NewMtu); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("New MTU: %d\n", NewMtu)); + if(!netif_running(dev)) { + /* Preset MTU size if device not ready/running */ + return 0; + } - /* prevent reconfiguration while changing the MTU */ - - /* disable interrupts */ + /* Prevent any reconfiguration while changing the MTU + by disabling any interrupts */ SK_OUT32(pAC->IoBase, B0_IMSK, 0); spin_lock_irqsave(&pAC->SlowPathLock, Flags); - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - /* Stop both ports */ - EvPara.Para32[0] = 0; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + /* Notify RLMT that the port has to be stopped */ + netif_stop_queue(dev); + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, + pNet->PortNr, -1, SK_TRUE); + spin_lock(&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW].TxDesRingLock); + + + /* Change RxFillLimit to 1 */ + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { + pAC->RxPort[pNet->PortNr].RxFillLimit = 1; } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + pAC->RxPort[1 - pNet->PortNr].RxFillLimit = 1; + pAC->RxPort[pNet->PortNr].RxFillLimit = pAC->RxDescrPerRing - + (pAC->RxDescrPerRing / 4); } - SkEventDispatcher(pAC, pAC->IoBase); - - for (i=0; iGIni.GIMacsFound; i++) { - spin_lock_irqsave( - &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags); - netif_stop_queue(pAC->dev[i]); - - } - - /* - * adjust number of rx buffers allocated - */ - if (NewMtu > 1500) { - /* use less rx buffers */ - for (i=0; iGIni.GIMacsFound; i++) { - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 100; - } else { - if (i == pAC->ActivePort) - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 100; - else - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 10; - } - } - } - else { - /* use normal amount of rx buffers */ - for (i=0; iGIni.GIMacsFound; i++) { - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = 1; - } else { - if (i == pAC->ActivePort) - pAC->RxPort[i].RxFillLimit = 1; - else - pAC->RxPort[i].RxFillLimit = - pAC->RxDescrPerRing - 100; - } - } - } - - SkGeDeInit(pAC, pAC->IoBase); - - /* - * enable/disable hardware support for long frames - */ - if (NewMtu > 1500) { -/* pAC->JumboActivated = SK_TRUE; /#* is never set back !!! */ - pAC->GIni.GIPortUsage = SK_JUMBO_LINK; - } - else { - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; - } else { - pAC->GIni.GIPortUsage = SK_RED_LINK; - } - } - - SkGeInit( pAC, pAC->IoBase, 1); - SkI2cInit( pAC, pAC->IoBase, 1); - SkEventInit(pAC, pAC->IoBase, 1); - SkPnmiInit( pAC, pAC->IoBase, 1); - SkAddrInit( pAC, pAC->IoBase, 1); - SkRlmtInit( pAC, pAC->IoBase, 1); - SkTimerInit(pAC, pAC->IoBase, 1); - - /* - * tschilling: - * Speed and others are set back to default in level 1 init! - */ - GetConfiguration(pAC); - - SkGeInit( pAC, pAC->IoBase, 2); - SkI2cInit( pAC, pAC->IoBase, 2); - SkEventInit(pAC, pAC->IoBase, 2); - SkPnmiInit( pAC, pAC->IoBase, 2); - SkAddrInit( pAC, pAC->IoBase, 2); - SkRlmtInit( pAC, pAC->IoBase, 2); - SkTimerInit(pAC, pAC->IoBase, 2); - - /* - * clear and reinit the rx rings here - */ - for (i=0; iGIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - FillRxRing(pAC, &pAC->RxPort[i]); - - /* Enable transmit descriptor polling. */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - }; - - SkGeYellowLED(pAC, pAC->IoBase, 1); - -#ifdef USE_INT_MOD - { - unsigned long ModBase; - ModBase = 53125000 / INTS_PER_SEC; - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); - SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); - } + /* clear and reinit the rx rings here, because of new MTU size */ + if (CHIP_ID_YUKON_2(pAC)) { + SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr, SK_STOP_ALL, SK_SOFT_RST); + SkY2AllocateRxBuffers(pAC, pAC->IoBase, pNet->PortNr); + SkY2PortStart(pAC, pAC->IoBase, pNet->PortNr); + } else { +// SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, SK_STOP_ALL, SK_SOFT_RST); +#ifdef CONFIG_SK98LIN_NAPI + WorkToDo = 1; + ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE, &WorkDone, WorkToDo); +#else + ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); #endif + ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); + FillRxRing(pAC, &pAC->RxPort[pNet->PortNr]); + + /* Enable transmit descriptor polling */ + SkGePollTxD(pAC, pAC->IoBase, pNet->PortNr, SK_TRUE); + FillRxRing(pAC, &pAC->RxPort[pNet->PortNr]); + } netif_start_queue(pAC->dev[pNet->PortNr]); - for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) { - spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); - } - /* enable Interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); + spin_unlock(&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW].TxDesRingLock); + + + /* Notify RLMT about the changing and restarting one (or more) ports */ + SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, + pNet->PortNr, -1, SK_TRUE); + + /* Enable Interrupts again */ + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - - /* Found more than one port */ - if ((pAC->GIni.GIMacsFound == 2 ) && - (pAC->RlmtNets == 2)) { - /* Start both ports */ - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, - EvPara); - - - EvPara.Para32[1] = -1; - EvPara.Para32[0] = pNet->PortNr; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - - if (pOtherNet->Up) { - EvPara.Para32[0] = pOtherNet->PortNr; - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_START, EvPara); - } - } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - } - - SkEventDispatcher(pAC, pAC->IoBase); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return 0; -} /* SkGeChangeMtu */ + +} /***************************************************************************** @@ -3498,66 +4307,67 @@ SK_EVPARA EvPara; */ static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev) { -DEV_NET *pNet = (DEV_NET*) dev->priv; -SK_AC *pAC = pNet->pAC; -SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */ -SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */ -SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */ -unsigned int Size; /* size of pnmi struct */ -unsigned long Flags; /* for spin lock */ + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + unsigned long LateCollisions, ExcessiveCollisions, RxTooLong; + unsigned long Flags; /* for spin lock */ + SK_U32 MaxNumOidEntries, Oid, Len; + char Buf[8]; + struct { + SK_U32 Oid; + unsigned long *pVar; + } Vars[] = { + { OID_SKGE_STAT_TX_LATE_COL, &LateCollisions }, + { OID_SKGE_STAT_TX_EXCESS_COL, &ExcessiveCollisions }, + { OID_SKGE_STAT_RX_TOO_LONG, &RxTooLong }, + { OID_SKGE_STAT_RX, &pAC->stats.rx_packets }, + { OID_SKGE_STAT_TX, &pAC->stats.tx_packets }, + { OID_SKGE_STAT_RX_OCTETS, &pAC->stats.rx_bytes }, + { OID_SKGE_STAT_TX_OCTETS, &pAC->stats.tx_bytes }, + { OID_SKGE_RX_NO_BUF_CTS, &pAC->stats.rx_dropped }, + { OID_SKGE_TX_NO_BUF_CTS, &pAC->stats.tx_dropped }, + { OID_SKGE_STAT_RX_MULTICAST, &pAC->stats.multicast }, + { OID_SKGE_STAT_RX_RUNT, &pAC->stats.rx_length_errors }, + { OID_SKGE_STAT_RX_FCS, &pAC->stats.rx_crc_errors }, + { OID_SKGE_STAT_RX_FRAMING, &pAC->stats.rx_frame_errors }, + { OID_SKGE_STAT_RX_OVERFLOW, &pAC->stats.rx_over_errors }, + { OID_SKGE_STAT_RX_MISSED, &pAC->stats.rx_missed_errors }, + { OID_SKGE_STAT_TX_CARRIER, &pAC->stats.tx_carrier_errors }, + { OID_SKGE_STAT_TX_UNDERRUN, &pAC->stats.tx_fifo_errors }, + }; + + if ((pAC->DiagModeActive == DIAG_NOTACTIVE) && + (pAC->BoardLevel == SK_INIT_RUN)) { + memset(&pAC->stats, 0x00, sizeof(pAC->stats)); /* clean first */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeStats starts now...\n")); - pPnmiStruct = &pAC->PnmiStruct; - memset(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA)); - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - Size = SK_PNMI_STRUCT_SIZE; - SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pPnmiStat = &pPnmiStruct->Stat[0]; - pPnmiConf = &pPnmiStruct->Conf[0]; + MaxNumOidEntries = sizeof(Vars) / sizeof(Vars[0]); + for (Oid = 0; Oid < MaxNumOidEntries; Oid++) { + if (SkPnmiGetVar(pAC,pAC->IoBase, Vars[Oid].Oid, + &Buf, &Len, 1, pNet->NetNr) != SK_PNMI_ERR_OK) { + memset(Buf, 0x00, sizeof(Buf)); + } + *Vars[Oid].pVar = (unsigned long) (*((SK_U64 *) Buf)); + } + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF; - pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF; - pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts; - pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts; + pAC->stats.collisions = LateCollisions + ExcessiveCollisions; + pAC->stats.tx_errors = pAC->stats.tx_carrier_errors + + pAC->stats.tx_fifo_errors; + pAC->stats.rx_errors = pAC->stats.rx_length_errors + + pAC->stats.rx_crc_errors + + pAC->stats.rx_frame_errors + + pAC->stats.rx_over_errors + + pAC->stats.rx_missed_errors; - if (pNet->Mtu <= 1500) { - pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF; - } else { - pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF); + if (dev->mtu > 1500) { + pAC->stats.rx_errors = pAC->stats.rx_errors - RxTooLong; + } } - - if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12) - pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts; - - pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF; - pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF; - pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF; - pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - - /* detailed rx_errors: */ - pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF; - pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF; - pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF; - pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF; - - /* detailed tx_errors */ - pAC->stats.tx_aborted_errors = (SK_U32) 0; - pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF; - pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_window_errors = (SK_U32) 0; - return(&pAC->stats); } /* SkGeStats */ - /***************************************************************************** * * SkGeIoctl - IO-control function @@ -3571,30 +4381,37 @@ unsigned long Flags; /* for spin lock */ * 0, if everything is ok * !=0, on error */ -static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd) +static int SkGeIoctl( +struct SK_NET_DEVICE *dev, /* the device the IOCTL is to be performed on */ +struct ifreq *rq, /* additional request structure containing data */ +int cmd) /* requested IOCTL command number */ { -DEV_NET *pNet; -SK_AC *pAC; - -SK_GE_IOCTL Ioctl; -unsigned int Err = 0; -int Size; + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + struct pci_dev *pdev = NULL; + void *pMemBuf; + SK_GE_IOCTL Ioctl; + unsigned long Flags; /* for spin lock */ + unsigned int Err = 0; + unsigned int Length = 0; + int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32); + int Size = 0; + int Ret = 0; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeIoctl starts now...\n")); - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { return -EFAULT; } switch(cmd) { - case SK_IOCTL_SETMIB: - case SK_IOCTL_PRESETMIB: + case SIOCETHTOOL: + return SkEthIoctl(dev, rq); + case SK_IOCTL_SETMIB: /* FALL THRU */ + case SK_IOCTL_PRESETMIB: /* FALL THRU (if capable!) */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - case SK_IOCTL_GETMIB: + case SK_IOCTL_GETMIB: if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData, Ioctl.LenPnmiStruct)? Ioctl.Len : sizeof(pAC->PnmiStruct))) { @@ -3610,10 +4427,80 @@ int Size; return -EFAULT; } break; + case SK_IOCTL_GEN: + if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) { + Length = Ioctl.Len; + } else { + Length = sizeof(pAC->PnmiStruct) + HeaderLength; + } + if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { + return -ENOMEM; + } + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { + Err = -EFAULT; + goto fault_gen; + } + if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) { + Err = -EFAULT; + goto fault_gen; + } + if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { + Err = -EFAULT; + goto fault_gen; + } + Ioctl.Len = Length; + if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { + Err = -EFAULT; + goto fault_gen; + } +fault_gen: + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + kfree(pMemBuf); /* cleanup everything */ + break; + case SK_IOCTL_DIAG: + if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) { + Length = Ioctl.Len; + } else { + Length = sizeof(pAC->PnmiStruct) + HeaderLength; + } + if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { + return -ENOMEM; + } + if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { + Err = -EFAULT; + goto fault_diag; + } + pdev = pAC->PciDev; + Length = 3 * sizeof(SK_U32); /* Error, Bus and Device */ + /* + ** While coding this new IOCTL interface, only a few lines of code + ** are to to be added. Therefore no dedicated function has been + ** added. If more functionality is added, a separate function + ** should be used... + */ + * ((SK_U32 *)pMemBuf) = 0; + * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number; + * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev)); + if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { + Err = -EFAULT; + goto fault_diag; + } + Ioctl.Len = Length; + if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { + Err = -EFAULT; + goto fault_diag; + } +fault_diag: + kfree(pMemBuf); /* cleanup everything */ + break; default: Err = -EOPNOTSUPP; } + return(Err); + } /* SkGeIoctl */ @@ -3639,12 +4526,12 @@ DEV_NET *pNet, /* pointer to the adapter context */ unsigned int Size, /* length of ioctl data */ int mode) /* flag for set/preset */ { -unsigned long Flags; /* for spin lock */ -SK_AC *pAC; + SK_AC *pAC = pNet->pAC; + unsigned long Flags; /* for spin lock */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeIocMib starts now...\n")); - pAC = pNet->pAC; + /* access MIB */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); switch(mode) { @@ -3670,7 +4557,6 @@ SK_AC *pAC; } /* SkGeIocMib */ #endif - /***************************************************************************** * * GetConfiguration - read configuration information @@ -3686,12 +4572,20 @@ static void GetConfiguration( SK_AC *pAC) /* pointer to the adapter context structure */ { SK_I32 Port; /* preferred port */ -int LinkSpeed; /* Link speed */ -int AutoNeg; /* auto negotiation off (0) or on (1) */ -int DuplexCap; /* duplex capabilities (0=both, 1=full, 2=half */ -int MSMode; /* master / slave mode selection */ SK_BOOL AutoSet; SK_BOOL DupSet; +int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */ +int AutoNeg = 1; /* autoneg off (0) or on (1) */ +int DuplexCap = 0; /* 0=both,1=full,2=half */ +int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */ +int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */ +int IrqModMaskOffset = 6; /* all ints moderated=default */ + +SK_BOOL IsConTypeDefined = SK_TRUE; +SK_BOOL IsLinkSpeedDefined = SK_TRUE; +SK_BOOL IsFlowCtrlDefined = SK_TRUE; +SK_BOOL IsRoleDefined = SK_TRUE; +SK_BOOL IsModeDefined = SK_TRUE; /* * The two parameters AutoNeg. and DuplexCap. map to one configuration * parameter. The mapping is described by this table: @@ -3705,399 +4599,732 @@ SK_BOOL DupSet; * Sense | AutoSense | AutoSense | AutoSense | */ int Capabilities[3][3] = - { { -1, SK_LMODE_FULL, SK_LMODE_HALF}, - {SK_LMODE_AUTOBOTH, SK_LMODE_AUTOFULL, SK_LMODE_AUTOHALF}, + { { -1, SK_LMODE_FULL , SK_LMODE_HALF }, + {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF }, {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} }; +SK_U32 IrqModMask[7][2] = + { { IRQ_MASK_RX_ONLY , Y2_DRIVER_IRQS }, + { IRQ_MASK_TX_ONLY , Y2_DRIVER_IRQS }, + { IRQ_MASK_SP_ONLY , Y2_SPECIAL_IRQS }, + { IRQ_MASK_SP_RX , Y2_IRQ_MASK }, + { IRQ_MASK_TX_RX , Y2_DRIVER_IRQS }, + { IRQ_MASK_SP_TX , Y2_IRQ_MASK }, + { IRQ_MASK_RX_TX_SP, Y2_IRQ_MASK } }; + #define DC_BOTH 0 #define DC_FULL 1 #define DC_HALF 2 #define AN_OFF 0 #define AN_ON 1 #define AN_SENS 2 +#define M_CurrPort pAC->GIni.GP[Port] - /* settings for port A */ - /* settings link speed */ - LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */ + + /* + ** Set the default values first for both ports! + */ + for (Port = 0; Port < SK_MAX_MACS; Port++) { + M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH]; + M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; + M_CurrPort.PMSMode = SK_MS_MODE_AUTO; + M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO; + } + + /* + ** Check merged parameter ConType. If it has not been used, + ** verify any other parameter (e.g. AutoNeg) and use default values. + ** + ** Stating both ConType and other lowlevel link parameters is also + ** possible. If this is the case, the passed ConType-parameter is + ** overwritten by the lowlevel link parameter. + ** + ** The following settings are used for a merged ConType-parameter: + ** + ** ConType DupCap AutoNeg FlowCtrl Role Speed + ** ------- ------ ------- -------- ---------- ----- + ** Auto Both On SymOrRem Auto Auto + ** 1000FD Full Off None 1000 + ** 100FD Full Off None 100 + ** 100HD Half Off None 100 + ** 10FD Full Off None 10 + ** 10HD Half Off None 10 + ** + ** This ConType parameter is used for all ports of the adapter! + */ + if ( (ConType != NULL) && + (pAC->Index < SK_MAX_CARD_PARAM) && + (ConType[pAC->Index] != NULL) ) { + + /* Check chipset family */ + if ((!pAC->ChipsetType) && + (strcmp(ConType[pAC->Index],"Auto")!=0) && + (strcmp(ConType[pAC->Index],"")!=0)) { + /* Set the speed parameter back */ + printk("sk98lin: Illegal value \"%s\" " + "for ConType." + " Using Auto.\n", + ConType[pAC->Index]); + + sprintf(ConType[pAC->Index], "Auto"); + } + + if ((pAC->GIni.GICopperType != SK_TRUE) && + (strcmp(ConType[pAC->Index],"1000FD") != 0)) { + /* Set the speed parameter back */ + printk("sk98lin: Illegal value \"%s\" " + "for ConType." + " Using Auto.\n", + ConType[pAC->Index]); + + sprintf(ConType[pAC->Index], "Auto"); + } + + if (strcmp(ConType[pAC->Index],"")==0) { + IsConTypeDefined = SK_FALSE; /* No ConType defined */ + } else if (strcmp(ConType[pAC->Index],"Auto")==0) { + for (Port = 0; Port < SK_MAX_MACS; Port++) { + M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH]; + M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; + M_CurrPort.PMSMode = SK_MS_MODE_AUTO; + M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO; + } + } else if (strcmp(ConType[pAC->Index],"1000FD")==0) { + for (Port = 0; Port < SK_MAX_MACS; Port++) { + M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL]; + M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; + M_CurrPort.PMSMode = SK_MS_MODE_AUTO; + M_CurrPort.PLinkSpeed = SK_LSPEED_1000MBPS; + } + } else if (strcmp(ConType[pAC->Index],"100FD")==0) { + for (Port = 0; Port < SK_MAX_MACS; Port++) { + M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL]; + M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; + M_CurrPort.PMSMode = SK_MS_MODE_AUTO; + M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS; + } + } else if (strcmp(ConType[pAC->Index],"100HD")==0) { + for (Port = 0; Port < SK_MAX_MACS; Port++) { + M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF]; + M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; + M_CurrPort.PMSMode = SK_MS_MODE_AUTO; + M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS; + } + } else if (strcmp(ConType[pAC->Index],"10FD")==0) { + for (Port = 0; Port < SK_MAX_MACS; Port++) { + M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL]; + M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; + M_CurrPort.PMSMode = SK_MS_MODE_AUTO; + M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS; + } + } else if (strcmp(ConType[pAC->Index],"10HD")==0) { + for (Port = 0; Port < SK_MAX_MACS; Port++) { + M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF]; + M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; + M_CurrPort.PMSMode = SK_MS_MODE_AUTO; + M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS; + } + } else { + printk("sk98lin: Illegal value \"%s\" for ConType\n", + ConType[pAC->Index]); + IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */ + } + } else { + IsConTypeDefined = SK_FALSE; /* No ConType defined */ + } + + /* + ** Parse any parameter settings for port A: + ** a) any LinkSpeed stated? + */ if (Speed_A != NULL && pAC->IndexIndex] != NULL) { if (strcmp(Speed_A[pAC->Index],"")==0) { - LinkSpeed = SK_LSPEED_AUTO; + IsLinkSpeedDefined = SK_FALSE; + } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) { + LinkSpeed = SK_LSPEED_AUTO; + } else if (strcmp(Speed_A[pAC->Index],"10")==0) { + LinkSpeed = SK_LSPEED_10MBPS; + } else if (strcmp(Speed_A[pAC->Index],"100")==0) { + LinkSpeed = SK_LSPEED_100MBPS; + } else if (strcmp(Speed_A[pAC->Index],"1000")==0) { +#if 0 /* uboot */ + if ((pAC->PciDev->vendor == 0x11ab ) && + (pAC->PciDev->device == 0x4350)) { + LinkSpeed = SK_LSPEED_100MBPS; + printk("sk98lin: Illegal value \"%s\" for Speed_A.\n" + "Gigabit speed not possible with this chip revision!", + Speed_A[pAC->Index]); + } else +#endif + { + LinkSpeed = SK_LSPEED_1000MBPS; + } + } else { + printk("sk98lin: Illegal value \"%s\" for Speed_A\n", + Speed_A[pAC->Index]); + IsLinkSpeedDefined = SK_FALSE; } - else if (strcmp(Speed_A[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } - else if (strcmp(Speed_A[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } - else if (strcmp(Speed_A[pAC->Index],"100")==0) { + } else { +#if 0 /* uboot */ + if ((pAC->PciDev->vendor == 0x11ab ) && + (pAC->PciDev->device == 0x4350)) { + /* Gigabit speed not supported + * Swith to speed 100 + */ LinkSpeed = SK_LSPEED_100MBPS; + } else +#endif + { + IsLinkSpeedDefined = SK_FALSE; } - else if (strcmp(Speed_A[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } - else printk("%s: Illegal value for Speed_A\n", - pAC->dev[0]->name); } - /* Check speed parameter */ - /* Only copper type adapter and GE V2 cards */ - if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) || - (pAC->GIni.GICopperType != SK_TRUE)) && + /* + ** Check speed parameter: + ** Only copper type adapter and GE V2 cards + */ + if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && ((LinkSpeed != SK_LSPEED_AUTO) && (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("%s: Illegal value for Speed_A. " + printk("sk98lin: Illegal value for Speed_A. " "Not a copper card or GE V2 card\n Using " - "speed 1000\n", pAC->dev[0]->name); + "speed 1000\n"); LinkSpeed = SK_LSPEED_1000MBPS; } - pAC->GIni.GP[0].PLinkSpeed = LinkSpeed; + + /* + ** Decide whether to set new config value if somethig valid has + ** been received. + */ + if (IsLinkSpeedDefined) { + pAC->GIni.GP[0].PLinkSpeed = LinkSpeed; + } - /* Autonegotiation */ + /* + ** b) Any Autonegotiation and DuplexCapabilities set? + ** Please note that both belong together... + */ AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */ AutoSet = SK_FALSE; if (AutoNeg_A != NULL && pAC->IndexIndex] != NULL) { AutoSet = SK_TRUE; if (strcmp(AutoNeg_A[pAC->Index],"")==0) { - AutoSet = SK_FALSE; + AutoSet = SK_FALSE; + } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) { + AutoNeg = AN_ON; + } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) { + AutoNeg = AN_OFF; + } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) { + AutoNeg = AN_SENS; + } else { + printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n", + AutoNeg_A[pAC->Index]); } - else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } - else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } - else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } - else printk("%s: Illegal value for AutoNeg_A\n", - pAC->dev[0]->name); } DuplexCap = DC_BOTH; - DupSet = SK_FALSE; + DupSet = SK_FALSE; if (DupCap_A != NULL && pAC->IndexIndex] != NULL) { DupSet = SK_TRUE; if (strcmp(DupCap_A[pAC->Index],"")==0) { - DupSet = SK_FALSE; + DupSet = SK_FALSE; + } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) { + DuplexCap = DC_BOTH; + } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) { + DuplexCap = DC_FULL; + } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) { + DuplexCap = DC_HALF; + } else { + printk("sk98lin: Illegal value \"%s\" for DupCap_A\n", + DupCap_A[pAC->Index]); } - else if (strcmp(DupCap_A[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } - else if (strcmp(DupCap_A[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } - else if (strcmp(DupCap_A[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } - else printk("%s: Illegal value for DupCap_A\n", - pAC->dev[0]->name); } - /* check for illegal combinations */ - if (AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("%s, Port A: DuplexCapabilities" - " ignored using Sense mode\n", pAC->dev[0]->name); + /* + ** Check for illegal combinations + */ + if ((LinkSpeed == SK_LSPEED_1000MBPS) && + ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || + (DuplexCap == SK_LMODE_STAT_HALF)) && + (pAC->ChipsetType)) { + printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" + " Using Full Duplex.\n"); + DuplexCap = DC_FULL; } + + if ( AutoSet && AutoNeg==AN_SENS && DupSet) { + printk("sk98lin, Port A: DuplexCapabilities" + " ignored using Sense mode\n"); + } + if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("%s, Port A: Illegal combination" + printk("sk98lin: Port A: Illegal combination" " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n", pAC->dev[0]->name); - + "Full Duplex\n"); DuplexCap = DC_FULL; } + if (AutoSet && AutoNeg==AN_OFF && !DupSet) { DuplexCap = DC_FULL; } - + if (!AutoSet && DupSet) { - printk("%s, Port A: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n", - pAC->dev[0]->name); AutoNeg = AN_ON; } - - /* set the desired mode */ - pAC->GIni.GP[0].PLinkModeConf = - Capabilities[AutoNeg][DuplexCap]; - - pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; + + /* + ** set the desired mode + */ + if (AutoSet || DupSet) { + pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap]; + } + + /* + ** c) Any Flowcontrol-parameter set? + */ if (FlowCtrl_A != NULL && pAC->IndexIndex] != NULL) { if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) { + IsFlowCtrlDefined = SK_FALSE; + } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) { + FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; + } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) { + FlowCtrl = SK_FLOW_MODE_SYMMETRIC; + } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) { + FlowCtrl = SK_FLOW_MODE_LOC_SEND; + } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) { + FlowCtrl = SK_FLOW_MODE_NONE; + } else { + printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n", + FlowCtrl_A[pAC->Index]); + IsFlowCtrlDefined = SK_FALSE; } - else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_SYM_OR_REM; - } - else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_SYMMETRIC; - } - else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_LOC_SEND; - } - else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) { - pAC->GIni.GP[0].PFlowCtrlMode = - SK_FLOW_MODE_NONE; - } - else printk("Illegal value for FlowCtrl_A\n"); - } - if (AutoNeg==AN_OFF && pAC->GIni.GP[0].PFlowCtrlMode!= - SK_FLOW_MODE_NONE) { - printk("%s, Port A: FlowControl" - " impossible without AutoNegotiation," - " disabled\n", pAC->dev[0]->name); - pAC->GIni.GP[0].PFlowCtrlMode = SK_FLOW_MODE_NONE; + } else { + IsFlowCtrlDefined = SK_FALSE; } - MSMode = SK_MS_MODE_AUTO; /* default: do auto select */ + if (IsFlowCtrlDefined) { + if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { + printk("sk98lin: Port A: FlowControl" + " impossible without AutoNegotiation," + " disabled\n"); + FlowCtrl = SK_FLOW_MODE_NONE; + } + pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl; + } + + /* + ** d) What is with the RoleParameter? + */ if (Role_A != NULL && pAC->IndexIndex] != NULL) { if (strcmp(Role_A[pAC->Index],"")==0) { + IsRoleDefined = SK_FALSE; + } else if (strcmp(Role_A[pAC->Index],"Auto")==0) { + MSMode = SK_MS_MODE_AUTO; + } else if (strcmp(Role_A[pAC->Index],"Master")==0) { + MSMode = SK_MS_MODE_MASTER; + } else if (strcmp(Role_A[pAC->Index],"Slave")==0) { + MSMode = SK_MS_MODE_SLAVE; + } else { + printk("sk98lin: Illegal value \"%s\" for Role_A\n", + Role_A[pAC->Index]); + IsRoleDefined = SK_FALSE; } - else if (strcmp(Role_A[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } - else if (strcmp(Role_A[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } - else if (strcmp(Role_A[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } - else printk("%s: Illegal value for Role_A\n", - pAC->dev[0]->name); + } else { + IsRoleDefined = SK_FALSE; } - pAC->GIni.GP[0].PMSMode = MSMode; + if (IsRoleDefined == SK_TRUE) { + pAC->GIni.GP[0].PMSMode = MSMode; + } + + + + /* + ** Parse any parameter settings for port B: + ** a) any LinkSpeed stated? + */ + IsConTypeDefined = SK_TRUE; + IsLinkSpeedDefined = SK_TRUE; + IsFlowCtrlDefined = SK_TRUE; + IsModeDefined = SK_TRUE; - /* settings for port B */ - /* settings link speed */ - LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */ if (Speed_B != NULL && pAC->IndexIndex] != NULL) { if (strcmp(Speed_B[pAC->Index],"")==0) { - LinkSpeed = SK_LSPEED_AUTO; + IsLinkSpeedDefined = SK_FALSE; + } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) { + LinkSpeed = SK_LSPEED_AUTO; + } else if (strcmp(Speed_B[pAC->Index],"10")==0) { + LinkSpeed = SK_LSPEED_10MBPS; + } else if (strcmp(Speed_B[pAC->Index],"100")==0) { + LinkSpeed = SK_LSPEED_100MBPS; + } else if (strcmp(Speed_B[pAC->Index],"1000")==0) { + LinkSpeed = SK_LSPEED_1000MBPS; + } else { + printk("sk98lin: Illegal value \"%s\" for Speed_B\n", + Speed_B[pAC->Index]); + IsLinkSpeedDefined = SK_FALSE; } - else if (strcmp(Speed_B[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } - else if (strcmp(Speed_B[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } - else if (strcmp(Speed_B[pAC->Index],"100")==0) { - LinkSpeed = SK_LSPEED_100MBPS; - } - else if (strcmp(Speed_B[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } - else printk("%s: Illegal value for Speed_B\n", - pAC->dev[1]->name); + } else { + IsLinkSpeedDefined = SK_FALSE; } - /* Check speed parameter */ - /* Only copper type adapter and GE V2 cards */ - if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) || - (pAC->GIni.GICopperType != SK_TRUE)) && + /* + ** Check speed parameter: + ** Only copper type adapter and GE V2 cards + */ + if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && ((LinkSpeed != SK_LSPEED_AUTO) && (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("%s: Illegal value for Speed_B. " + printk("sk98lin: Illegal value for Speed_B. " "Not a copper card or GE V2 card\n Using " - "speed 1000\n", pAC->dev[1]->name); + "speed 1000\n"); LinkSpeed = SK_LSPEED_1000MBPS; } - pAC->GIni.GP[1].PLinkSpeed = LinkSpeed; - /* Auto negotiation */ + /* + ** Decide whether to set new config value if somethig valid has + ** been received. + */ + if (IsLinkSpeedDefined) { + pAC->GIni.GP[1].PLinkSpeed = LinkSpeed; + } + + /* + ** b) Any Autonegotiation and DuplexCapabilities set? + ** Please note that both belong together... + */ AutoNeg = AN_SENS; /* default: do auto Sense */ AutoSet = SK_FALSE; if (AutoNeg_B != NULL && pAC->IndexIndex] != NULL) { AutoSet = SK_TRUE; if (strcmp(AutoNeg_B[pAC->Index],"")==0) { - AutoSet = SK_FALSE; + AutoSet = SK_FALSE; + } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) { + AutoNeg = AN_ON; + } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) { + AutoNeg = AN_OFF; + } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) { + AutoNeg = AN_SENS; + } else { + printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n", + AutoNeg_B[pAC->Index]); } - else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } - else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } - else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } - else printk("Illegal value for AutoNeg_B\n"); } DuplexCap = DC_BOTH; - DupSet = SK_FALSE; + DupSet = SK_FALSE; if (DupCap_B != NULL && pAC->IndexIndex] != NULL) { DupSet = SK_TRUE; if (strcmp(DupCap_B[pAC->Index],"")==0) { - DupSet = SK_FALSE; + DupSet = SK_FALSE; + } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) { + DuplexCap = DC_BOTH; + } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) { + DuplexCap = DC_FULL; + } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) { + DuplexCap = DC_HALF; + } else { + printk("sk98lin: Illegal value \"%s\" for DupCap_B\n", + DupCap_B[pAC->Index]); } - else if (strcmp(DupCap_B[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } - else if (strcmp(DupCap_B[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } - else if (strcmp(DupCap_B[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } - else printk("Illegal value for DupCap_B\n"); } - /* check for illegal combinations */ + + /* + ** Check for illegal combinations + */ + if ((LinkSpeed == SK_LSPEED_1000MBPS) && + ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || + (DuplexCap == SK_LMODE_STAT_HALF)) && + (pAC->ChipsetType)) { + printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" + " Using Full Duplex.\n"); + DuplexCap = DC_FULL; + } + if (AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("%s, Port B: DuplexCapabilities" - " ignored using Sense mode\n", pAC->dev[1]->name); + printk("sk98lin, Port B: DuplexCapabilities" + " ignored using Sense mode\n"); } - if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("%s, Port B: Illegal combination" - " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n", pAC->dev[1]->name); + if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ + printk("sk98lin: Port B: Illegal combination" + " of values AutoNeg. and DuplexCap.\n Using " + "Full Duplex\n"); DuplexCap = DC_FULL; } + if (AutoSet && AutoNeg==AN_OFF && !DupSet) { DuplexCap = DC_FULL; } - + if (!AutoSet && DupSet) { - printk("%s, Port B: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n", - pAC->dev[1]->name); AutoNeg = AN_ON; } - /* set the desired mode */ - pAC->GIni.GP[1].PLinkModeConf = - Capabilities[AutoNeg][DuplexCap]; + /* + ** set the desired mode + */ + if (AutoSet || DupSet) { + pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap]; + } - pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; + /* + ** c) Any FlowCtrl parameter set? + */ if (FlowCtrl_B != NULL && pAC->IndexIndex] != NULL) { if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) { + IsFlowCtrlDefined = SK_FALSE; + } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) { + FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; + } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) { + FlowCtrl = SK_FLOW_MODE_SYMMETRIC; + } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) { + FlowCtrl = SK_FLOW_MODE_LOC_SEND; + } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) { + FlowCtrl = SK_FLOW_MODE_NONE; + } else { + printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n", + FlowCtrl_B[pAC->Index]); + IsFlowCtrlDefined = SK_FALSE; } - else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_SYM_OR_REM; - } - else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_SYMMETRIC; - } - else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_LOC_SEND; - } - else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) { - pAC->GIni.GP[1].PFlowCtrlMode = - SK_FLOW_MODE_NONE; - } - else printk("Illegal value for FlowCtrl_B\n"); - } - if (AutoNeg==AN_OFF && pAC->GIni.GP[1].PFlowCtrlMode!= - SK_FLOW_MODE_NONE) { - printk("%s, Port B: FlowControl" - " impossible without AutoNegotiation," - " disabled\n", pAC->dev[1]->name); - pAC->GIni.GP[1].PFlowCtrlMode = SK_FLOW_MODE_NONE; + } else { + IsFlowCtrlDefined = SK_FALSE; } - MSMode = SK_MS_MODE_AUTO; /* default: do auto select */ + if (IsFlowCtrlDefined) { + if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { + printk("sk98lin: Port B: FlowControl" + " impossible without AutoNegotiation," + " disabled\n"); + FlowCtrl = SK_FLOW_MODE_NONE; + } + pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl; + } + + /* + ** d) What is the RoleParameter? + */ if (Role_B != NULL && pAC->IndexIndex] != NULL) { if (strcmp(Role_B[pAC->Index],"")==0) { + IsRoleDefined = SK_FALSE; + } else if (strcmp(Role_B[pAC->Index],"Auto")==0) { + MSMode = SK_MS_MODE_AUTO; + } else if (strcmp(Role_B[pAC->Index],"Master")==0) { + MSMode = SK_MS_MODE_MASTER; + } else if (strcmp(Role_B[pAC->Index],"Slave")==0) { + MSMode = SK_MS_MODE_SLAVE; + } else { + printk("sk98lin: Illegal value \"%s\" for Role_B\n", + Role_B[pAC->Index]); + IsRoleDefined = SK_FALSE; } - else if (strcmp(Role_B[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } - else if (strcmp(Role_B[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } - else if (strcmp(Role_B[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } - else printk("%s: Illegal value for Role_B\n", - pAC->dev[1]->name); + } else { + IsRoleDefined = SK_FALSE; } - pAC->GIni.GP[1].PMSMode = MSMode; - - /* settings for both ports */ + if (IsRoleDefined) { + pAC->GIni.GP[1].PMSMode = MSMode; + } + + /* + ** Evaluate settings for both ports + */ pAC->ActivePort = 0; if (PrefPort != NULL && pAC->IndexIndex] != NULL) { if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */ - pAC->ActivePort = 0; + pAC->ActivePort = 0; pAC->Rlmt.Net[0].Preference = -1; /* auto */ - pAC->Rlmt.Net[0].PrefPort = 0; - } - else if (strcmp(PrefPort[pAC->Index],"A") == 0) { + pAC->Rlmt.Net[0].PrefPort = 0; + } else if (strcmp(PrefPort[pAC->Index],"A") == 0) { /* - * do not set ActivePort here, thus a port - * switch is issued after net up. - */ - Port = 0; + ** do not set ActivePort here, thus a port + ** switch is issued after net up. + */ + Port = 0; pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; - } - else if (strcmp(PrefPort[pAC->Index],"B") == 0) { + pAC->Rlmt.Net[0].PrefPort = Port; + } else if (strcmp(PrefPort[pAC->Index],"B") == 0) { /* - * do not set ActivePort here, thus a port - * switch is issued after net up. - */ - Port = 1; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; + ** do not set ActivePort here, thus a port + ** switch is issued after net up. + */ + if (pAC->GIni.GIMacsFound == 1) { + printk("sk98lin: Illegal value \"B\" for PrefPort.\n" + " Port B not available on single port adapters.\n"); + + pAC->ActivePort = 0; + pAC->Rlmt.Net[0].Preference = -1; /* auto */ + pAC->Rlmt.Net[0].PrefPort = 0; + } else { + Port = 1; + pAC->Rlmt.Net[0].Preference = Port; + pAC->Rlmt.Net[0].PrefPort = Port; + } + } else { + printk("sk98lin: Illegal value \"%s\" for PrefPort\n", + PrefPort[pAC->Index]); } - else printk("%s: Illegal value for PrefPort\n", - pAC->dev[0]->name); } pAC->RlmtNets = 1; + pAC->RlmtMode = 0; if (RlmtMode != NULL && pAC->IndexIndex] != NULL) { if (strcmp(RlmtMode[pAC->Index], "") == 0) { - pAC->RlmtMode = 0; - } - else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK; - } - else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK; - } - else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK | - SK_RLMT_CHECK_SEG; - } - else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) && - (pAC->GIni.GIMacsFound == 2)) { + if (pAC->GIni.GIMacsFound == 2) { pAC->RlmtMode = SK_RLMT_CHECK_LINK; pAC->RlmtNets = 2; - } - else { - printk("%s: Illegal value for" - " RlmtMode, using default\n", pAC->dev[0]->name); + } + } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK; + } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK | + SK_RLMT_CHECK_LOC_LINK; + } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK | + SK_RLMT_CHECK_LOC_LINK | + SK_RLMT_CHECK_SEG; + } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) && + (pAC->GIni.GIMacsFound == 2)) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK; + pAC->RlmtNets = 2; + } else { + printk("sk98lin: Illegal value \"%s\" for" + " RlmtMode, using default\n", + RlmtMode[pAC->Index]); pAC->RlmtMode = 0; } + } else { + if (pAC->GIni.GIMacsFound == 2) { + pAC->RlmtMode = SK_RLMT_CHECK_LINK; + pAC->RlmtNets = 2; + } } - else { - pAC->RlmtMode = 0; + +#ifdef SK_YUKON2 + /* + ** use dualnet config per default + * + pAC->RlmtMode = SK_RLMT_CHECK_LINK; + pAC->RlmtNets = 2; + */ +#endif + + + /* + ** Check the LowLatance parameters + */ + pAC->LowLatency = SK_FALSE; + if (LowLatency[pAC->Index] != NULL) { + if (strcmp(LowLatency[pAC->Index], "On") == 0) { + pAC->LowLatency = SK_TRUE; + } } + + + /* + ** Check the interrupt moderation parameters + */ + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; + if (Moderation[pAC->Index] != NULL) { + if (strcmp(Moderation[pAC->Index], "") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; + } else if (strcmp(Moderation[pAC->Index], "Static") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC; + } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC; + } else if (strcmp(Moderation[pAC->Index], "None") == 0) { + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; + } else { + printk("sk98lin: Illegal value \"%s\" for Moderation.\n" + " Disable interrupt moderation.\n", + Moderation[pAC->Index]); + } + } else { +/* Set interrupt moderation if wished */ +#ifdef CONFIG_SK98LIN_STATINT + pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC; +#endif + } + + if (ModerationMask[pAC->Index] != NULL) { + if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) { + IrqModMaskOffset = 0; + } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) { + IrqModMaskOffset = 1; + } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) { + IrqModMaskOffset = 2; + } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) { + IrqModMaskOffset = 3; + } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) { + IrqModMaskOffset = 3; + } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) { + IrqModMaskOffset = 4; + } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) { + IrqModMaskOffset = 4; + } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) { + IrqModMaskOffset = 5; + } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) { + IrqModMaskOffset = 5; + } else { /* some rubbish stated */ + // IrqModMaskOffset = 6; ->has been initialized + // already at the begin of this function... + } + } + if (!CHIP_ID_YUKON_2(pAC)) { + pAC->DynIrqModInfo.MaskIrqModeration = IrqModMask[IrqModMaskOffset][0]; + } else { + pAC->DynIrqModInfo.MaskIrqModeration = IrqModMask[IrqModMaskOffset][1]; + } + + if (!CHIP_ID_YUKON_2(pAC)) { + pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; + } else { + pAC->DynIrqModInfo.MaxModIntsPerSec = C_Y2_INTS_PER_SEC_DEFAULT; + } + if (IntsPerSec[pAC->Index] != 0) { + if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || + (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) { + printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n" + " Using default value of %i.\n", + IntsPerSec[pAC->Index], + C_INT_MOD_IPS_LOWER_RANGE, + C_INT_MOD_IPS_UPPER_RANGE, + pAC->DynIrqModInfo.MaxModIntsPerSec); + } else { + pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index]; + } + } + + /* + ** Evaluate upper and lower moderation threshold + */ + pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit = + pAC->DynIrqModInfo.MaxModIntsPerSec + + (pAC->DynIrqModInfo.MaxModIntsPerSec / 5); + + pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit = + pAC->DynIrqModInfo.MaxModIntsPerSec - + (pAC->DynIrqModInfo.MaxModIntsPerSec / 5); + + pAC->DynIrqModInfo.DynIrqModSampleInterval = + SK_DRV_MODERATION_TIMER_LENGTH; + } /* GetConfiguration */ - +#if 0 /* uboot */ /***************************************************************************** * * ProductStr - return a adapter identification string from vpd @@ -4108,28 +5335,23 @@ int Capabilities[3][3] = * * Returns: N/A */ -static void ProductStr( -SK_AC *pAC /* pointer to adapter context */ -) +static void ProductStr(SK_AC *pAC) { -int StrLen = 80; /* length of the string, defined in SK_AC */ -char Keyword[] = VPD_NAME; /* vpd productname identifier */ -int ReturnCode; /* return code from vpd_read */ -unsigned long Flags; + char Default[] = "Generic Marvell Yukon chipset Ethernet device"; + char Key[] = VPD_NAME; /* VPD productname key */ + int StrLen = 80; /* stringlen */ + unsigned long Flags; spin_lock_irqsave(&pAC->SlowPathLock, Flags); - ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr, - &StrLen); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - if (ReturnCode != 0) { - /* there was an error reading the vpd data */ + if (VpdRead(pAC, pAC->IoBase, Key, pAC->DeviceStr, &StrLen)) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, ("Error reading VPD data: %d\n", ReturnCode)); - pAC->DeviceStr[0] = '\0'; + strcpy(pAC->DeviceStr, Default); } + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); } /* ProductStr */ - +#endif /****************************************************************************/ /* functions for common modules *********************************************/ /****************************************************************************/ @@ -4217,10 +5439,14 @@ SK_MBUF *pNextMbuf; */ SK_U64 SkOsGetTime(SK_AC *pAC) { -#if 0 - return jiffies; +#if 0 /* uboot */ + SK_U64 PrivateJiffies; + + SkOsGetTimeCurrent(pAC, &PrivateJiffies); + + return PrivateJiffies; #else - return get_timer(0); + return (get_timer(0)/(CFG_TCLK/1000)); #endif } /* SkOsGetTime */ @@ -4372,34 +5598,30 @@ SK_U8 Val) /* pointer to store the read value */ * Returns: * 0 if everything ok * < 0 on error - * + * */ int SkDrvEvent( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* io-context */ -SK_U32 Event, /* event-id */ -SK_EVPARA Param) /* event-parameter */ +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* IO control context */ +SK_U32 Event, /* event-id */ +SK_EVPARA Param) /* event-parameter */ { -SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */ -struct sk_buff *pMsg; /* pointer to a message block */ -int FromPort; /* the port from which we switch away */ -int ToPort; /* the port we switch to */ -SK_EVPARA NewPara; /* parameter for further events */ -#if 0 -int Stat; + SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */ + struct sk_buff *pMsg; /* pointer to a message block */ + SK_BOOL DualNet; + SK_U32 Reason; + unsigned long Flags; + unsigned long InitFlags; + int FromPort; /* the port from which we switch away */ + int ToPort; /* the port we switch to */ + int Stat; + DEV_NET *pNet = NULL; +#ifdef CONFIG_SK98LIN_NAPI + int WorkToDo = 1; /* min(*budget, dev->quota); */ + int WorkDone = 0; #endif -unsigned long Flags; -SK_BOOL DualNet; switch (Event) { - case SK_DRV_ADAP_FAIL: - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("ADAPTER FAIL EVENT\n")); - printk("%s: Adapter failed.\n", pAC->dev[0]->name); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - /* cgoos */ - break; case SK_DRV_PORT_FAIL: FromPort = Param.Para32[0]; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, @@ -4409,193 +5631,308 @@ SK_BOOL DualNet; } else { printk("%s: Port B failed.\n", pAC->dev[1]->name); } - /* cgoos */ break; - case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */ - /* action list 4 */ + case SK_DRV_PORT_RESET: FromPort = Param.Para32[0]; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, ("PORT RESET EVENT, Port: %d ", FromPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); + SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET, + FromPort, SK_FALSE); spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); -#if 0 + if (CHIP_ID_YUKON_2(pAC)) { + SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); + } else { + SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); + } +#if 0 /* uboot */ pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING; #endif spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - - /* clear rx ring from received frames */ - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); - - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); + + if (!CHIP_ID_YUKON_2(pAC)) { +#ifdef CONFIG_SK98LIN_NAPI + WorkToDo = 1; + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo); +#else + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); +#endif + ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); + } spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - /* tschilling: Handling of return value inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort)) { - if (FromPort == 0) { - printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name); - } else { - printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name); +#ifdef USE_TIST_FOR_RESET + if (pAC->GIni.GIYukon2) { +#ifdef Y2_RECOVERY + /* for Yukon II we want to have tist enabled all the time */ + if (!SK_ADAPTER_WAITING_FOR_TIST(pAC)) { + Y2_ENABLE_TIST(pAC->IoBase); } +#else + /* make sure that we do not accept any status LEs from now on */ + if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) { +#endif + /* port already waiting for tist */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Port %c is now waiting for specific Tist\n", + 'A' + FromPort)); + SK_SET_WAIT_BIT_FOR_PORT( + pAC, + SK_PSTATE_WAITING_FOR_SPECIFIC_TIST, + FromPort); + /* get current timestamp */ + Y2_GET_TIST_LOW_VAL(pAC->IoBase, &pAC->MinTistLo); + pAC->MinTistHi = pAC->GIni.GITimeStampCnt; +#ifndef Y2_RECOVERY + } else { + /* nobody is waiting yet */ + SK_SET_WAIT_BIT_FOR_PORT( + pAC, + SK_PSTATE_WAITING_FOR_ANY_TIST, + FromPort); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Port %c is now waiting for any Tist (0x%X)\n", + 'A' + FromPort, pAC->AdapterResetState)); + /* start tist */ + Y2_ENABLE_TIST(pAC-IoBase); + } +#endif + } +#endif + +#ifdef Y2_LE_CHECK + /* mark entries invalid */ + pAC->LastPort = 3; + pAC->LastOpc = 0xFF; +#endif + if (CHIP_ID_YUKON_2(pAC)) { + SkY2PortStart(pAC, IoC, FromPort); + } else { + /* tschilling: Handling of return value inserted. */ + if (SkGeInitPort(pAC, IoC, FromPort)) { + if (FromPort == 0) { + printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name); + } else { + printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name); + } + } + SkAddrMcUpdate(pAC,IoC, FromPort); + PortReInitBmu(pAC, FromPort); + SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); + CLEAR_AND_START_RX(FromPort); } - SkAddrMcUpdate(pAC,IoC, FromPort); - PortReInitBmu(pAC, FromPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); break; - case SK_DRV_NET_UP: /* SK_U32 PortIdx */ - /* action list 5 */ + case SK_DRV_NET_UP: + spin_lock_irqsave(&pAC->InitLock, InitFlags); FromPort = Param.Para32[0]; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("NET UP EVENT, Port: %d ", Param.Para32[0])); -#ifdef SK98_INFO - printk("%s: network connection up using" - " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]); + ("NET UP EVENT, Port: %d ", FromPort)); + SkAddrMcUpdate(pAC,IoC, FromPort); /* Mac update */ + if (DoPrintInterfaceChange) { + printk("%s: network connection up using port %c\n", + pAC->dev[FromPort]->name, 'A'+FromPort); - /* tschilling: Values changed according to LinkSpeedUsed. */ - Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed; - if (Stat == SK_LSPEED_STAT_10MBPS) { - printk(" speed: 10\n"); - } else if (Stat == SK_LSPEED_STAT_100MBPS) { - printk(" speed: 100\n"); - } else if (Stat == SK_LSPEED_STAT_1000MBPS) { - printk(" speed: 1000\n"); - } else { - printk(" speed: unknown\n"); - } - - Stat = pAC->GIni.GP[FromPort].PLinkModeStatus; - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_AUTOFULL) { - printk(" autonegotiation: yes\n"); - } - else { - printk(" autonegotiation: no\n"); - } - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_HALF) { - printk(" duplex mode: half\n"); - } - else { - printk(" duplex mode: full\n"); - } - Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus; - if (Stat == SK_FLOW_STAT_REM_SEND ) { - printk(" flowctrl: remote send\n"); - } - else if (Stat == SK_FLOW_STAT_LOC_SEND ){ - printk(" flowctrl: local send\n"); - } - else if (Stat == SK_FLOW_STAT_SYMMETRIC ){ - printk(" flowctrl: symmetric\n"); - } - else { - printk(" flowctrl: none\n"); - } - - /* tschilling: Check against CopperType now. */ - if ((pAC->GIni.GICopperType == SK_TRUE) && - (pAC->GIni.GP[FromPort].PLinkSpeedUsed == - SK_LSPEED_STAT_1000MBPS)) { - Stat = pAC->GIni.GP[FromPort].PMSStatus; - if (Stat == SK_MS_STAT_MASTER ) { - printk(" role: master\n"); + /* tschilling: Values changed according to LinkSpeedUsed. */ + Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed; + if (Stat == SK_LSPEED_STAT_10MBPS) { + printk(" speed: 10\n"); + } else if (Stat == SK_LSPEED_STAT_100MBPS) { + printk(" speed: 100\n"); + } else if (Stat == SK_LSPEED_STAT_1000MBPS) { + printk(" speed: 1000\n"); + } else { + printk(" speed: unknown\n"); } - else if (Stat == SK_MS_STAT_SLAVE ) { - printk(" role: slave\n"); - } - else { - printk(" role: ???\n"); - } - } -#ifdef SK_ZEROCOPY - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) - printk(" scatter-gather: enabled\n"); - else - printk(" scatter-gather: disabled\n"); + Stat = pAC->GIni.GP[FromPort].PLinkModeStatus; + if ((Stat == SK_LMODE_STAT_AUTOHALF) || + (Stat == SK_LMODE_STAT_AUTOFULL)) { + printk(" autonegotiation: yes\n"); + } else { + printk(" autonegotiation: no\n"); + } -#else - printk(" scatter-gather: disabled\n"); + if ((Stat == SK_LMODE_STAT_AUTOHALF) || + (Stat == SK_LMODE_STAT_HALF)) { + printk(" duplex mode: half\n"); + } else { + printk(" duplex mode: full\n"); + } + + Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus; + if (Stat == SK_FLOW_STAT_REM_SEND ) { + printk(" flowctrl: remote send\n"); + } else if (Stat == SK_FLOW_STAT_LOC_SEND ) { + printk(" flowctrl: local send\n"); + } else if (Stat == SK_FLOW_STAT_SYMMETRIC ) { + printk(" flowctrl: symmetric\n"); + } else { + printk(" flowctrl: none\n"); + } + + /* tschilling: Check against CopperType now. */ + if ((pAC->GIni.GICopperType == SK_TRUE) && + (pAC->GIni.GP[FromPort].PLinkSpeedUsed == + SK_LSPEED_STAT_1000MBPS)) { + Stat = pAC->GIni.GP[FromPort].PMSStatus; + if (Stat == SK_MS_STAT_MASTER ) { + printk(" role: master\n"); + } else if (Stat == SK_MS_STAT_SLAVE ) { + printk(" role: slave\n"); + } else { + printk(" role: ???\n"); + } + } + + /* Display interrupt moderation informations */ + if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) { + printk(" irq moderation: static (%d ints/sec)\n", + pAC->DynIrqModInfo.MaxModIntsPerSec); + } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) { + printk(" irq moderation: dynamic (%d ints/sec)\n", + pAC->DynIrqModInfo.MaxModIntsPerSec); + } else { + printk(" irq moderation: disabled\n"); + } + +#ifdef NETIF_F_TSO + if (CHIP_ID_YUKON_2(pAC)) { + if (pAC->dev[FromPort]->features & NETIF_F_TSO) { + printk(" tcp offload: enabled\n"); + } else { + printk(" tcp offload: disabled\n"); + } + } #endif -#endif /* SK98_INFO */ - if ((Param.Para32[0] != pAC->ActivePort) && - (pAC->RlmtNets == 1)) { - NewPara.Para32[0] = pAC->ActivePort; - NewPara.Para32[1] = Param.Para32[0]; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN, - NewPara); +#if 0 /* uboot */ + if (pAC->dev[FromPort]->features & NETIF_F_SG) { + printk(" scatter-gather: enabled\n"); + } else { + printk(" scatter-gather: disabled\n"); + } + + if (pAC->dev[FromPort]->features & NETIF_F_IP_CSUM) { + printk(" tx-checksum: enabled\n"); + } else { + printk(" tx-checksum: disabled\n"); + } + + if (pAC->RxPort[FromPort].UseRxCsum) { + printk(" rx-checksum: enabled\n"); + } else { + printk(" rx-checksum: disabled\n"); + } +#ifdef CONFIG_SK98LIN_NAPI + printk(" rx-polling: enabled\n"); +#endif +#endif + if (pAC->LowLatency) { + printk(" low latency: enabled\n"); + } + } else { + DoPrintInterfaceChange = SK_TRUE; + } + + if ((FromPort != pAC->ActivePort)&&(pAC->RlmtNets == 1)) { + SkLocalEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN, + pAC->ActivePort, FromPort, SK_FALSE); } /* Inform the world that link protocol is up. */ -#if 0 - pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING; + netif_wake_queue(pAC->dev[FromPort]); +#if 0 //u-boot + netif_carrier_on(pAC->dev[FromPort]); + pAC->dev[FromPort]->flags |= IFF_RUNNING; #endif - + spin_unlock_irqrestore(&pAC->InitLock, InitFlags); break; - case SK_DRV_NET_DOWN: /* SK_U32 Reason */ - /* action list 7 */ + case SK_DRV_NET_DOWN: + Reason = Param.Para32[0]; + FromPort = Param.Para32[1]; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, ("NET DOWN EVENT ")); -#ifdef SK98_INFO - printk("%s: network connection down\n", pAC->dev[Param.Para32[1]]->name); + +#if 0 //u-boot + /* Stop queue and carrier */ + netif_stop_queue(pAC->dev[FromPort]); + netif_carrier_off(pAC->dev[FromPort]); #endif -#if 0 - pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING; + + /* Print link change */ + if (DoPrintInterfaceChange) { +#if 0 /* uboot */ + if (pAC->dev[FromPort]->flags & IFF_RUNNING) { + printk("%s: network connection down\n", + pAC->dev[FromPort]->name); + } +#endif + } else { + DoPrintInterfaceChange = SK_TRUE; + } +#if 0 /* uboot */ + pAC->dev[FromPort]->flags &= ~IFF_RUNNING; #endif break; - case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT SWITCH HARD ")); - case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - /* action list 6 */ - printk("%s: switching to port %c\n", pAC->dev[0]->name, - 'A'+Param.Para32[1]); - case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ + case SK_DRV_SWITCH_HARD: /* FALL THRU */ + case SK_DRV_SWITCH_SOFT: /* FALL THRU */ + case SK_DRV_SWITCH_INTERN: FromPort = Param.Para32[0]; - ToPort = Param.Para32[1]; + ToPort = Param.Para32[1]; + printk("%s: switching from port %c to port %c\n", + pAC->dev[0]->name, 'A'+FromPort, 'A'+ToPort); SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ", FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - NewPara.Para64 = ToPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); + SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET, + FromPort, SK_FALSE); + SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET, + ToPort, SK_FALSE); spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); - SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); + if (CHIP_ID_YUKON_2(pAC)) { + SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); + SkY2PortStop(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); + } + else { + SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); + SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); + } + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */ - ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */ + + if (!CHIP_ID_YUKON_2(pAC)) { +#ifdef CONFIG_SK98LIN_NAPI + WorkToDo = 1; + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo); + ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE, &WorkDone, WorkToDo); +#else + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */ + ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */ +#endif + ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); + ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]); + } - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); - ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]); spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); pAC->ActivePort = ToPort; + #if 0 SetQueueSizes(pAC); #else @@ -4604,13 +5941,12 @@ SK_BOOL DualNet; if (pAC->RlmtNets == 2) { DualNet = SK_TRUE; } - + if (SkGeInitAssignRamToQueues( pAC, pAC->ActivePort, DualNet)) { - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4618,40 +5954,215 @@ SK_BOOL DualNet; break; } #endif - /* tschilling: Handling of return values inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort) || - SkGeInitPort(pAC, IoC, ToPort)) { - printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name); + if (!CHIP_ID_YUKON_2(pAC)) { + /* tschilling: Handling of return values inserted. */ + if (SkGeInitPort(pAC, IoC, FromPort) || + SkGeInitPort(pAC, IoC, ToPort)) { + printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name); + } } - if (Event == SK_DRV_SWITCH_SOFT) { - SkMacRxTxEnable(pAC, IoC, FromPort); + if (!CHIP_ID_YUKON_2(pAC)) { + if (Event == SK_DRV_SWITCH_SOFT) { + SkMacRxTxEnable(pAC, IoC, FromPort); + } + SkMacRxTxEnable(pAC, IoC, ToPort); } - SkMacRxTxEnable(pAC, IoC, ToPort); + SkAddrSwap(pAC, IoC, FromPort, ToPort); SkAddrMcUpdate(pAC, IoC, FromPort); SkAddrMcUpdate(pAC, IoC, ToPort); - PortReInitBmu(pAC, FromPort); - PortReInitBmu(pAC, ToPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); - ClearAndStartRx(pAC, ToPort); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + +#ifdef USE_TIST_FOR_RESET + if (pAC->GIni.GIYukon2) { + /* make sure that we do not accept any status LEs from now on */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("both Ports now waiting for specific Tist\n")); + SK_SET_WAIT_BIT_FOR_PORT( + pAC, + SK_PSTATE_WAITING_FOR_ANY_TIST, + 0); + SK_SET_WAIT_BIT_FOR_PORT( + pAC, + SK_PSTATE_WAITING_FOR_ANY_TIST, + 1); + + /* start tist */ + Y2_ENABLE_TIST(pAC->IoBase); + } +#endif + if (!CHIP_ID_YUKON_2(pAC)) { + PortReInitBmu(pAC, FromPort); + PortReInitBmu(pAC, ToPort); + SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); + SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); + CLEAR_AND_START_RX(FromPort); + CLEAR_AND_START_RX(ToPort); + } else { + SkY2PortStart(pAC, IoC, FromPort); + SkY2PortStart(pAC, IoC, ToPort); +#ifdef SK_YUKON2 + /* in yukon-II always port 0 has to be started first */ + // SkY2PortStart(pAC, IoC, 0); + // SkY2PortStart(pAC, IoC, 1); +#endif + } + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); break; case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("RLS ")); + SK_DBG_MSG(NULL,SK_DBGMOD_DRV,SK_DBGCAT_DRV_EVENT,("RLS ")); pRlmtMbuf = (SK_MBUF*) Param.pParaPtr; pMsg = (struct sk_buff*) pRlmtMbuf->pOs; skb_put(pMsg, pRlmtMbuf->Length); - if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW], - pMsg) < 0) + if (!CHIP_ID_YUKON_2(pAC)) { + if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW], + pMsg) < 0) { + DEV_KFREE_SKB_ANY(pMsg); + } + } else { + if (SkY2RlmtSend(pAC, pRlmtMbuf->PortIdx, pMsg) < 0) { + DEV_KFREE_SKB_ANY(pMsg); + } + } + break; + case SK_DRV_TIMER: + if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) { + /* check what IRQs are to be moderated */ + SkDimStartModerationTimer(pAC); + SkDimModerate(pAC); + } else { + printk("Expiration of unknown timer\n"); + } + break; + case SK_DRV_ADAP_FAIL: +#if (!defined (Y2_RECOVERY) && !defined (Y2_LE_CHECK)) + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("ADAPTER FAIL EVENT\n")); + printk("%s: Adapter failed.\n", pAC->dev[0]->name); + SK_OUT32(pAC->IoBase, B0_IMSK, 0); /* disable interrupts */ + break; +#endif - DEV_KFREE_SKB_ANY(pMsg); +#if (defined (Y2_RECOVERY) || defined (Y2_LE_CHECK)) + case SK_DRV_RECOVER: + spin_lock_irqsave(&pAC->InitLock, InitFlags); + pNet = (DEV_NET *) pAC->dev[Param.Para32[0]]->priv; + + /* Recover already in progress */ + if (pNet->InRecover) { + break; + } + + netif_stop_queue(pAC->dev[Param.Para32[0]]); /* stop device if running */ + pNet->InRecover = SK_TRUE; + + FromPort = Param.Para32[0]; + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, + ("PORT RESET EVENT, Port: %d ", FromPort)); + + /* Disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + SK_OUT32(pAC->IoBase, B0_HWE_IMSK, 0); + + SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET, + FromPort, SK_FALSE); + spin_lock_irqsave( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + if (CHIP_ID_YUKON_2(pAC)) { + SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); + } else { + SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); + } +#if 0 //u-boot + pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING; +#endif + spin_unlock_irqrestore( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + + if (!CHIP_ID_YUKON_2(pAC)) { +#ifdef CONFIG_SK98LIN_NAPI + WorkToDo = 1; + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo); +#else + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); +#endif + ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); + } + spin_lock_irqsave( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + +#ifdef USE_TIST_FOR_RESET + if (pAC->GIni.GIYukon2) { +#if 0 + /* make sure that we do not accept any status LEs from now on */ + Y2_ENABLE_TIST(pAC->IoBase); + + /* get current timestamp */ + Y2_GET_TIST_LOW_VAL(pAC->IoBase, &pAC->MinTistLo); + pAC->MinTistHi = pAC->GIni.GITimeStampCnt; + + SK_SET_WAIT_BIT_FOR_PORT( + pAC, + SK_PSTATE_WAITING_FOR_SPECIFIC_TIST, + FromPort); +#endif + SK_SET_WAIT_BIT_FOR_PORT( + pAC, + SK_PSTATE_WAITING_FOR_ANY_TIST, + FromPort); + + /* start tist */ + Y2_ENABLE_TIST(pAC->IoBase); + } +#endif + + /* Restart Receive BMU on Yukon-2 */ + if (HW_FEATURE(pAC, HWF_WA_DEV_4167)) { + SkYuk2RestartRxBmu(pAC, IoC, FromPort); + } + +#ifdef Y2_LE_CHECK + /* mark entries invalid */ + pAC->LastPort = 3; + pAC->LastOpc = 0xFF; +#endif + +#endif + /* Restart ports but do not initialize PHY. */ + if (CHIP_ID_YUKON_2(pAC)) { + SkY2PortStart(pAC, IoC, FromPort); + } else { + /* tschilling: Handling of return value inserted. */ + if (SkGeInitPort(pAC, IoC, FromPort)) { + if (FromPort == 0) { + printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name); + } else { + printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name); + } + } + SkAddrMcUpdate(pAC,IoC, FromPort); + PortReInitBmu(pAC, FromPort); + SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); + CLEAR_AND_START_RX(FromPort); + } + spin_unlock_irqrestore( + &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, + Flags); + + /* Map any waiting RX buffers to HW */ + FillReceiveTableYukon2(pAC, pAC->IoBase, FromPort); + + pNet->InRecover = SK_FALSE; + /* enable Interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); + netif_wake_queue(pAC->dev[FromPort]); + spin_unlock_irqrestore(&pAC->InitLock, InitFlags); break; default: break; @@ -4663,6 +6174,103 @@ SK_BOOL DualNet; } /* SkDrvEvent */ +/****************************************************************************** + * + * SkLocalEventQueue() - add event to queue + * + * Description: + * This function adds an event to the event queue and run the + * SkEventDispatcher. At least Init Level 1 is required to queue events, + * but will be scheduled add Init Level 2. + * + * returns: + * nothing + */ +void SkLocalEventQueue( +SK_AC *pAC, /* Adapters context */ +SK_U32 Class, /* Event Class */ +SK_U32 Event, /* Event to be queued */ +SK_U32 Param1, /* Event parameter 1 */ +SK_U32 Param2, /* Event parameter 2 */ +SK_BOOL Dispatcher) /* Dispatcher flag: + * TRUE == Call SkEventDispatcher + * FALSE == Don't execute SkEventDispatcher + */ +{ + SK_EVPARA EvPara; + EvPara.Para32[0] = Param1; + EvPara.Para32[1] = Param2; + + + if (Class == SKGE_PNMI) { + #ifdef SK_PNMI_SUPPORT + SkPnmiEvent( pAC, + pAC->IoBase, + Event, + EvPara); + #endif + } else { + SkEventQueue( pAC, + Class, + Event, + EvPara); + } + + /* Run the dispatcher */ + if (Dispatcher) { + SkEventDispatcher(pAC, pAC->IoBase); + } + +} + +/****************************************************************************** + * + * SkLocalEventQueue64() - add event to queue (64bit version) + * + * Description: + * This function adds an event to the event queue and run the + * SkEventDispatcher. At least Init Level 1 is required to queue events, + * but will be scheduled add Init Level 2. + * + * returns: + * nothing + */ +void SkLocalEventQueue64( +SK_AC *pAC, /* Adapters context */ +SK_U32 Class, /* Event Class */ +SK_U32 Event, /* Event to be queued */ +SK_U64 Param, /* Event parameter */ +SK_BOOL Dispatcher) /* Dispatcher flag: + * TRUE == Call SkEventDispatcher + * FALSE == Don't execute SkEventDispatcher + */ +{ + SK_EVPARA EvPara; + EvPara.Para64 = Param; + + + if (Class == SKGE_PNMI) { + #ifdef SK_PNMI_SUPPORT + SkPnmiEvent( pAC, + pAC->IoBase, + Event, + EvPara); + #endif + } else { + SkEventQueue( pAC, + Class, + Event, + EvPara); + } + + /* Run the dispatcher */ + if (Dispatcher) { + SkEventDispatcher(pAC, pAC->IoBase); + } + +} + + /***************************************************************************** * * SkErrorLog - log errors @@ -4673,7 +6281,7 @@ SK_BOOL DualNet; * Returns: * 0 if everything ok * < 0 on error - * + * */ void SkErrorLog( SK_AC *pAC, @@ -4712,12 +6320,258 @@ char ClassStr[80]; } /* SkErrorLog */ +/***************************************************************************** + * + * SkDrvEnterDiagMode - handles DIAG attach request + * + * Description: + * Notify the kernel to NOT access the card any longer due to DIAG + * Deinitialize the Card + * + * Returns: + * int + */ +int SkDrvEnterDiagMode( +SK_AC *pAc) /* pointer to adapter context */ +{ + SK_AC *pAC = NULL; + DEV_NET *pNet = NULL; + + pNet = (DEV_NET *) pAc->dev[0]->priv; + pAC = pNet->pAC; + + SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), + sizeof(SK_PNMI_STRUCT_DATA)); + + pAC->DiagModeActive = DIAG_ACTIVE; + if (pAC->BoardLevel > SK_INIT_DATA) { + if (netif_running(pAC->dev[0])) { + pAC->WasIfUp[0] = SK_TRUE; + pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + } else { + pAC->WasIfUp[0] = SK_FALSE; + } + + if (pNet != (DEV_NET *) pAc->dev[1]->priv) { + pNet = (DEV_NET *) pAc->dev[1]->priv; + if (netif_running(pAC->dev[1])) { + pAC->WasIfUp[1] = SK_TRUE; + pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 1); /* do SkGeClose */ + } else { + pAC->WasIfUp[1] = SK_FALSE; + } + } + pAC->BoardLevel = SK_INIT_DATA; + } + return(0); +} + +#ifdef DSK_DIAG_SUPPORT +/***************************************************************************** + * + * SkDrvLeaveDiagMode - handles DIAG detach request + * + * Description: + * Notify the kernel to may access the card again after use by DIAG + * Initialize the Card + * + * Returns: + * int + */ +int SkDrvLeaveDiagMode( +SK_AC *pAc) /* pointer to adapter control context */ +{ + SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), + sizeof(SK_PNMI_STRUCT_DATA)); + pAc->DiagModeActive = DIAG_NOTACTIVE; + #ifdef SK_DIAG_SUPPORT + + pAc->Pnmi.DiagAttached = SK_DIAG_IDLE; + #endif //SK_DIAG_SUPPORT + + if (pAc->WasIfUp[0] == SK_TRUE) { + pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAc, 0); /* first device */ + } + if (pAc->WasIfUp[1] == SK_TRUE) { + pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAc, 1); /* second device */ + } + return(0); +} +#endif /* DSK_DIAG_SUPPORT */ + +#if 0 /* uboot */ +/***************************************************************************** + * + * ParseDeviceNbrFromSlotName - Evaluate PCI device number + * + * Description: + * This function parses the PCI slot name information string and will + * retrieve the devcie number out of it. The slot_name maintianed by + * linux is in the form of '02:0a.0', whereas the first two characters + * represent the bus number in hex (in the sample above this is + * pci bus 0x02) and the next two characters the device number (0x0a). + * + * Returns: + * SK_U32: The device number from the PCI slot name + */ + +static SK_U32 ParseDeviceNbrFromSlotName( +const char *SlotName) /* pointer to pci slot name eg. '02:0a.0' */ +{ + char *CurrCharPos = (char *) SlotName; + int FirstNibble = -1; + int SecondNibble = -1; + SK_U32 Result = 0; + + while (*CurrCharPos != '\0') { + if (*CurrCharPos == ':') { + while (*CurrCharPos != '.') { + CurrCharPos++; + if ( (*CurrCharPos >= '0') && + (*CurrCharPos <= '9')) { + if (FirstNibble == -1) { + /* dec. value for '0' */ + FirstNibble = *CurrCharPos - 48; + } else { + SecondNibble = *CurrCharPos - 48; + } + } else if ( (*CurrCharPos >= 'a') && + (*CurrCharPos <= 'f') ) { + if (FirstNibble == -1) { + FirstNibble = *CurrCharPos - 87; + } else { + SecondNibble = *CurrCharPos - 87; + } + } else { + Result = 0; + } + } + + Result = FirstNibble; + Result = Result << 4; /* first nibble is higher one */ + Result = Result | SecondNibble; + } + CurrCharPos++; /* next character */ + } + return (Result); +} +#endif +/**************************************************************************** + * + * SkDrvDeInitAdapter - deinitialize adapter (this function is only + * called if Diag attaches to that card) + * + * Description: + * Close initialized adapter. + * + * Returns: + * 0 - on success + * error code - on error + */ +static int SkDrvDeInitAdapter( +SK_AC *pAC, /* pointer to adapter context */ +int devNbr) /* what device is to be handled */ +{ + struct SK_NET_DEVICE *dev; + + dev = pAC->dev[devNbr]; + + /* + ** Function SkGeClose() uses MOD_DEC_USE_COUNT (2.2/2.4) + ** or module_put() (2.6) to decrease the number of users for + ** a device, but if a device is to be put under control of + ** the DIAG, that count is OK already and does not need to + ** be adapted! Hence the opposite MOD_INC_USE_COUNT or + ** try_module_get() needs to be used again to correct that. + */ + MOD_INC_USE_COUNT; + + if (SkGeClose(dev) != 0) { + MOD_DEC_USE_COUNT; + return (-1); + } + return (0); + +} /* SkDrvDeInitAdapter() */ + +#if 0 /* uboot*/ +/**************************************************************************** + * + * SkDrvInitAdapter - Initialize adapter (this function is only + * called if Diag deattaches from that card) + * + * Description: + * Close initialized adapter. + * + * Returns: + * 0 - on success + * error code - on error + */ +static int SkDrvInitAdapter( +SK_AC *pAC, /* pointer to adapter context */ +int devNbr) /* what device is to be handled */ +{ + struct SK_NET_DEVICE *dev; + + dev = pAC->dev[devNbr]; + + if (SkGeOpen(dev) != 0) { + return (-1); + } else { + /* + ** Function SkGeOpen() uses MOD_INC_USE_COUNT (2.2/2.4) + ** or try_module_get() (2.6) to increase the number of + ** users for a device, but if a device was just under + ** control of the DIAG, that count is OK already and + ** does not need to be adapted! Hence the opposite + ** MOD_DEC_USE_COUNT or module_put() needs to be used + ** again to correct that. + */ + module_put(THIS_MODULE); + } + + /* + ** Use correct MTU size and indicate to kernel TX queue can be started + */ +#if 0 /* uboot */ + if (SkGeChangeMtu(dev, dev->mtu) != 0) { + return (-1); + } +#endif + return (0); + +} /* SkDrvInitAdapter */ + +#endif +#if 0 /* uboot */ +static int __init sk98lin_init(void) +{ + return pci_module_init(&sk98lin_driver); +} + +static void __exit sk98lin_cleanup(void) +{ + pci_unregister_driver(&sk98lin_driver); +} + +module_init(sk98lin_init); +module_exit(sk98lin_cleanup); + +#endif + #ifdef DEBUG /****************************************************************************/ /* "debug only" section *****************************************************/ /****************************************************************************/ - /***************************************************************************** * * DumpMsg - print a frame @@ -4726,11 +6580,13 @@ char ClassStr[80]; * This function prints frames to the system logfile/to the console. * * Returns: N/A - * + * */ -static void DumpMsg(struct sk_buff *skb, char *str) +static void DumpMsg( +struct sk_buff *skb, /* linux' socket buffer */ +char *str) /* additional msg string */ { - int msglen; + int msglen = (skb->len > 64) ? 64 : skb->len; if (skb == NULL) { printk("DumpMsg(): NULL-Message\n"); @@ -4741,19 +6597,16 @@ static void DumpMsg(struct sk_buff *skb, char *str) printk("DumpMsg(): Message empty\n"); return; } - - msglen = skb->len; - if (msglen > 64) - msglen = 64; - - printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len); - +#if 0 /* uboot */ + printk("DumpMsg: PhysPage: %p\n", + page_address(virt_to_page(skb->data))); +#endif + printk("--- Begin of message from %s , len %d (from %d) ----\n", + str, msglen, skb->len); DumpData((char *)skb->data, msglen); - printk("------- End of message ---------\n"); } /* DumpMsg */ - /***************************************************************************** * * DumpData - print a data area @@ -4763,25 +6616,24 @@ static void DumpMsg(struct sk_buff *skb, char *str) * console. * * Returns: N/A - * + * */ -static void DumpData(char *p, int size) +static void DumpData( +char *p, /* pointer to area containing the data */ +int size) /* the size of that data area in bytes */ { -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; + register int i; + int haddr = 0, addr = 0; + char hex_buffer[180] = { '\0' }; + char asc_buffer[180] = { '\0' }; + char HEXCHAR[] = "0123456789ABCDEF"; - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; for (i=0; i < size; ) { - if (*p >= '0' && *p <='z') + if (*p >= '0' && *p <='z') { asc_buffer[addr] = *p; - else + } else { asc_buffer[addr] = '.'; + } addr++; asc_buffer[addr] = 0; hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4]; @@ -4807,27 +6659,24 @@ char HEXCHAR[] = "0123456789ABCDEF"; * DumpLong - print a data area as long values * * Description: - * This function prints a area of data to the system logfile/to the + * This function prints a long variable to the system logfile/to the * console. * * Returns: N/A - * + * */ -static void DumpLong(char *pc, int size) +static void DumpLong( +char *pc, /* location of the variable to print */ +int size) /* how large is the variable? */ { -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; -long *p; -int l; + register int i; + int haddr = 0, addr = 0; + char hex_buffer[180] = { '\0' }; + char asc_buffer[180] = { '\0' }; + char HEXCHAR[] = "0123456789ABCDEF"; + long *p = (long*) pc; + int l; - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; - p = (long*) pc; for (i=0; i < size; ) { l = (long) *p; hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf]; @@ -4861,4 +6710,11 @@ int l; #endif -#endif /* CONFIG_SK98 */ +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ + +#endif + diff --git a/drivers/sk98lin/skgehwt.c b/drivers/sk98lin/skgehwt.c index f8681a8..2589bdb 100644 --- a/drivers/sk98lin/skgehwt.c +++ b/drivers/sk98lin/skgehwt.c @@ -1,17 +1,17 @@ /****************************************************************************** * * Name: skgehwt.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.13 $ - * Date: $Date: 1999/11/22 13:31:12 $ - * Purpose: Hardware Timer. + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Hardware Timer * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2004 Marvell. * * 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 @@ -22,76 +22,24 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skgehwt.c,v $ - * Revision 1.13 1999/11/22 13:31:12 cgoos - * Changed license header to GPL. - * - * Revision 1.12 1998/10/15 15:11:34 gklug - * fix: ID_sccs to SysKonnectFileId - * - * Revision 1.11 1998/10/08 15:27:51 gklug - * chg: correction factor is host clock dependent - * - * Revision 1.10 1998/09/15 14:18:31 cgoos - * Changed more BOOLEANs to SK_xxx - * - * Revision 1.9 1998/09/15 14:16:06 cgoos - * Changed line 107: FALSE to SK_FALSE - * - * Revision 1.8 1998/08/24 13:04:44 gklug - * fix: typo - * - * Revision 1.7 1998/08/19 09:50:49 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.6 1998/08/17 09:59:02 gklug - * fix: typos - * - * Revision 1.5 1998/08/14 07:09:10 gklug - * fix: chg pAc -> pAC - * - * Revision 1.4 1998/08/10 14:14:52 gklug - * rmv: unneccessary SK_ADDR macro - * - * Revision 1.3 1998/08/07 12:53:44 gklug - * fix: first compiled version - * - * Revision 1.2 1998/08/07 09:19:29 gklug - * adapt functions to the C coding conventions - * rmv unneccessary functions. - * - * Revision 1.1 1998/08/05 11:28:36 gklug - * first version: adapted from SMT/FDDI - * - * - * - * - ******************************************************************************/ - - #include - + #ifdef CONFIG_SK98 /* - Event queue and dispatcher -*/ + * Event queue and dispatcher + */ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/skgehwt.c,v 1.13 1999/11/22 13:31:12 cgoos Exp $" ; + "@(#) $Id: skgehwt.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ #ifdef __C2MAN__ /* - Hardware Timer function queue management. - - General Description: - + * Hardware Timer function queue management. */ intro() {} @@ -100,10 +48,10 @@ intro() /* * Prototypes of local functions. */ -#define SK_HWT_MAX (65000) +#define SK_HWT_MAX 65000UL * 160 /* ca. 10 sec. */ /* correction factor */ -#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100) +#define SK_HWT_FAC (10 * (SK_U32)pAC->GIni.GIHstClkFact / 16) /* * Initialize hardware timer. @@ -116,9 +64,9 @@ SK_IOC Ioc) /* IoContext */ { pAC->Hwt.TStart = 0 ; pAC->Hwt.TStop = 0 ; - pAC->Hwt.TActive = SK_FALSE ; + pAC->Hwt.TActive = SK_FALSE; - SkHwtStop(pAC,Ioc) ; + SkHwtStop(pAC, Ioc); } /* @@ -129,30 +77,23 @@ SK_IOC Ioc) /* IoContext */ void SkHwtStart( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ -SK_U32 Time) /* Time in units of 16us to load the timer with. */ +SK_U32 Time) /* Time in usec to load the timer */ { - SK_U32 Cnt ; - if (Time > SK_HWT_MAX) - Time = SK_HWT_MAX ; + Time = SK_HWT_MAX; - pAC->Hwt.TStart = Time ; - pAC->Hwt.TStop = 0L ; + pAC->Hwt.TStart = Time; + pAC->Hwt.TStop = 0L; - Cnt = Time ; - - /* - * if time < 16 us - * time = 16 us - */ - if (!Cnt) { - Cnt++ ; + if (!Time) { + Time = 1L; } - SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC) ; - SK_OUT16(Ioc, B2_TI_CRTL, TIM_START) ; /* Start timer. */ + SK_OUT32(Ioc, B2_TI_INI, Time * SK_HWT_FAC); - pAC->Hwt.TActive = SK_TRUE ; + SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer */ + + pAC->Hwt.TActive = SK_TRUE; } /* @@ -163,13 +104,13 @@ void SkHwtStop( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - SK_OUT16(Ioc, B2_TI_CRTL, TIM_STOP) ; - SK_OUT16(Ioc, B2_TI_CRTL, TIM_CLR_IRQ) ; + SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP); - pAC->Hwt.TActive = SK_FALSE ; + SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ); + + pAC->Hwt.TActive = SK_FALSE; } - /* * Stop hardware timer and read time elapsed since last start. * @@ -181,26 +122,34 @@ SK_U32 SkHwtRead( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - SK_U32 TRead ; - SK_U32 IStatus ; + SK_U32 TRead; + SK_U32 IStatus; + SK_U32 TimerInt; + + TimerInt = CHIP_ID_YUKON_2(pAC) ? Y2_IS_TIMINT : IS_TIMINT; if (pAC->Hwt.TActive) { - SkHwtStop(pAC,Ioc) ; + + SkHwtStop(pAC, Ioc); SK_IN32(Ioc, B2_TI_VAL, &TRead); TRead /= SK_HWT_FAC; SK_IN32(Ioc, B0_ISRC, &IStatus); - /* Check if timer expired (or wraparound). */ - if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) { - SkHwtStop(pAC,Ioc) ; - pAC->Hwt.TStop = pAC->Hwt.TStart ; - } else { - pAC->Hwt.TStop = pAC->Hwt.TStart - TRead ; + /* Check if timer expired (or wrapped around) */ + if ((TRead > pAC->Hwt.TStart) || ((IStatus & TimerInt) != 0)) { + + SkHwtStop(pAC, Ioc); + + pAC->Hwt.TStop = pAC->Hwt.TStart; + } + else { + + pAC->Hwt.TStop = pAC->Hwt.TStart - TRead; } } - return (pAC->Hwt.TStop) ; + return(pAC->Hwt.TStop); } /* @@ -210,11 +159,13 @@ void SkHwtIsr( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - SkHwtStop(pAC,Ioc); + SkHwtStop(pAC, Ioc); + pAC->Hwt.TStop = pAC->Hwt.TStart; - SkTimerDone(pAC,Ioc) ; + + SkTimerDone(pAC, Ioc); } -#endif /* CONFIG_SK98 */ - /* End of file */ + +#endif diff --git a/drivers/sk98lin/skgeinit.c b/drivers/sk98lin/skgeinit.c index a18dc0a..764c6bb 100644 --- a/drivers/sk98lin/skgeinit.c +++ b/drivers/sk98lin/skgeinit.c @@ -1,398 +1,29 @@ /****************************************************************************** * * Name: skgeinit.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.85 $ - * Date: $Date: 2003/02/05 15:30:33 $ - * Purpose: Contains functions to initialize the GE HW + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Contains functions to initialize the adapter * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2006 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skgeinit.c,v $ - * Revision 1.85 2003/02/05 15:30:33 rschmidt - * Corrected setting of GIHstClkFact (Host Clock Factor) and - * GIPollTimerVal (Descr. Poll Timer Init Value) for YUKON. - * Editorial changes. - * - * Revision 1.84 2003/01/28 09:57:25 rschmidt - * Added detection of YUKON-Lite Rev. A0 (stored in GIYukonLite). - * Disabled Rx GMAC FIFO Flush for YUKON-Lite Rev. A0. - * Added support for CLK_RUN (YUKON-Lite). - * Added additional check of PME from D3cold for setting GIVauxAvail. - * Editorial changes. - * - * Revision 1.83 2002/12/17 16:15:41 rschmidt - * Added default setting of PhyType (Copper) for YUKON. - * Added define around check for HW self test results. - * Editorial changes. - * - * Revision 1.82 2002/12/05 13:40:21 rschmidt - * Added setting of Rx GMAC FIFO Flush Mask register. - * Corrected PhyType with new define SK_PHY_MARV_FIBER when - * YUKON Fiber board was found. - * Editorial changes. - * - * Revision 1.81 2002/11/15 12:48:35 rschmidt - * Replaced message SKERR_HWI_E018 with SKERR_HWI_E024 for Rx queue error - * in SkGeStopPort(). - * Added init for pAC->GIni.GIGenesis with SK_FALSE in YUKON-branch. - * Editorial changes. - * - * Revision 1.80 2002/11/12 17:28:30 rschmidt - * Initialized GIPciSlot64 and GIPciClock66 in SkGeInit1(). - * Reduced PCI FIFO watermarks for 32bit/33MHz bus in SkGeInitBmu(). - * Editorial changes. - * - * Revision 1.79 2002/10/21 09:31:02 mkarl - * Changed SkGeInitAssignRamToQueues(), removed call to - * SkGeInitAssignRamToQueues in SkGeInit1 and fixed compiler warning in - * SkGeInit1. - * - * Revision 1.78 2002/10/16 15:55:07 mkarl - * Fixed a bug in SkGeInitAssignRamToQueues. - * - * Revision 1.77 2002/10/14 15:07:22 rschmidt - * Corrected timeout handling for Rx queue in SkGeStopPort() (#10748) - * Editorial changes. - * - * Revision 1.76 2002/10/11 09:24:38 mkarl - * Added check for HW self test results. - * - * Revision 1.75 2002/10/09 16:56:44 mkarl - * Now call SkGeInitAssignRamToQueues() in Init Level 1 in order to assign - * the adapter memory to the queues. This default assignment is not suitable - * for dual net mode. - * - * Revision 1.74 2002/09/12 08:45:06 rwahl - * Set defaults for PMSCap, PLinkSpeed & PLinkSpeedCap dependent on PHY. - * - * Revision 1.73 2002/08/16 15:19:45 rschmidt - * Corrected check for Tx queues in SkGeCheckQSize(). - * Added init for new entry GIGenesis and GICopperType - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. - * Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros. - * - * Revision 1.72 2002/08/12 13:38:55 rschmidt - * Added check if VAUX is available (stored in GIVauxAvail) - * Initialized PLinkSpeedCap in Port struct with SK_LSPEED_CAP_1000MBPS - * Editorial changes. - * - * Revision 1.71 2002/08/08 16:32:58 rschmidt - * Added check for Tx queues in SkGeCheckQSize(). - * Added start of Time Stamp Timer (YUKON) in SkGeInit2(). - * Editorial changes. - * - * Revision 1.70 2002/07/23 16:04:26 rschmidt - * Added init for GIWolOffs (HW-Bug in YUKON 1st rev.) - * Minor changes - * - * Revision 1.69 2002/07/17 17:07:08 rwahl - * - SkGeInit1(): fixed PHY type debug output; corrected init of GIFunc - * table & GIMacType. - * - Editorial changes. - * - * Revision 1.68 2002/07/15 18:38:31 rwahl - * Added initialization for MAC type dependent function table. - * - * Revision 1.67 2002/07/15 15:45:39 rschmidt - * Added Tx Store & Forward for YUKON (GMAC Tx FIFO is only 1 kB) - * Replaced SK_PHY_MARV by SK_PHY_MARV_COPPER - * Editorial changes - * - * Revision 1.66 2002/06/10 09:35:08 rschmidt - * Replaced C++ comments (//) - * Editorial changes - * - * Revision 1.65 2002/06/05 08:33:37 rschmidt - * Changed GIRamSize and Reset sequence for YUKON. - * SkMacInit() replaced by SkXmInitMac() resp. SkGmInitMac() - * - * Revision 1.64 2002/04/25 13:03:20 rschmidt - * Changes for handling YUKON. - * Removed reference to xmac_ii.h (not necessary). - * Moved all defines into header file. - * Replaced all SkXm...() functions with SkMac...() to handle also - * YUKON's GMAC. - * Added handling for GMAC FIFO in SkGeInitMacFifo(), SkGeStopPort(). - * Removed 'goto'-directive from SkGeCfgSync(), SkGeCheckQSize(). - * Replaced all XMAC-access macros by functions: SkMacRxTxDisable(), - * SkMacFlushTxFifo(). - * Optimized timeout handling in SkGeStopPort(). - * Initialized PLinkSpeed in Port struct with SK_LSPEED_AUTO. - * Release of GMAC Link Control reset in SkGeInit1(). - * Initialized GIChipId and GIChipRev in GE Init structure. - * Added GIRamSize and PhyType values for YUKON. - * Removed use of PRxCmd to setup XMAC. - * Moved setting of XM_RX_DIS_CEXT to SkXmInitMac(). - * Use of SkGeXmitLED() only for GENESIS. - * Changes for V-CPU support. - * Editorial changes. - * - * Revision 1.63 2001/04/05 11:02:09 rassmann - * Stop Port check of the STOP bit did not take 2/18 sec as wanted. - * - * Revision 1.62 2001/02/07 07:54:21 rassmann - * Corrected copyright. - * - * Revision 1.61 2001/01/31 15:31:40 gklug - * fix: problem with autosensing an SR8800 switch - * - * Revision 1.60 2000/10/18 12:22:21 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.59 2000/10/10 11:22:06 gklug - * add: in manual half duplex mode ignore carrier extension errors - * - * Revision 1.58 2000/10/02 14:10:27 rassmann - * Reading BCOM PHY after releasing reset until it returns a valid value. - * - * Revision 1.57 2000/08/03 14:55:28 rassmann - * Waiting for I2C to be ready before de-initializing adapter - * (prevents sensors from hanging up). - * - * Revision 1.56 2000/07/27 12:16:48 gklug - * fix: Stop Port check of the STOP bit does now take 2/18 sec as wanted - * - * Revision 1.55 1999/11/22 13:32:26 cgoos - * Changed license header to GPL. - * - * Revision 1.54 1999/10/26 07:32:54 malthoff - * Initialize PHWLinkUp with SK_FALSE. Required for Diagnostics. - * - * Revision 1.53 1999/08/12 19:13:50 malthoff - * Fix for 1000BT. Do not owerwrite XM_MMU_CMD when - * disabling receiver and transmitter. Other bits - * may be lost. - * - * Revision 1.52 1999/07/01 09:29:54 gklug - * fix: DoInitRamQueue needs pAC - * - * Revision 1.51 1999/07/01 08:42:21 gklug - * chg: use Store & forward for RAM buffer when Jumbos are used - * - * Revision 1.50 1999/05/27 13:19:38 cgoos - * Added Tx PCI watermark initialization. - * Removed Tx RAM queue Store & Forward setting. - * - * Revision 1.49 1999/05/20 14:32:45 malthoff - * SkGeLinkLED() is completly removed now. - * - * Revision 1.48 1999/05/19 07:28:24 cgoos - * SkGeLinkLED no more available for drivers. - * Changes for 1000Base-T. - * - * Revision 1.47 1999/04/08 13:57:45 gklug - * add: Init of new port struct fiels PLinkResCt - * chg: StopPort Timer check - * - * Revision 1.46 1999/03/25 07:42:15 malthoff - * SkGeStopPort(): Add workaround for cache incoherency. - * Create error log entry, disable port, and - * exit loop if it does not terminate. - * Add XM_RX_LENERR_OK to the default value for the - * XMAC receive command register. - * - * Revision 1.45 1999/03/12 16:24:47 malthoff - * Remove PPollRxD and PPollTxD. - * Add check for GIPollTimerVal. - * - * Revision 1.44 1999/03/12 13:40:23 malthoff - * Fix: SkGeXmitLED(), SK_LED_TST mode does not work. - * Add: Jumbo frame support. - * Chg: Resolution of parameter IntTime in SkGeCfgSync(). - * - * Revision 1.43 1999/02/09 10:29:46 malthoff - * Bugfix: The previous modification again also for the second location. - * - * Revision 1.42 1999/02/09 09:35:16 malthoff - * Bugfix: The bits '66 MHz Capable' and 'NEWCAP are reset while - * clearing the error bits in the PCI status register. - * - * Revision 1.41 1999/01/18 13:07:02 malthoff - * Bugfix: Do not use CFG cycles after during Init- or Runtime, because - * they may not be available after Boottime. - * - * Revision 1.40 1999/01/11 12:40:49 malthoff - * Bug fix: PCI_STATUS: clearing error bits sets the UDF bit. - * - * Revision 1.39 1998/12/11 15:17:33 gklug - * chg: Init LipaAutoNeg with Unknown - * - * Revision 1.38 1998/12/10 11:02:57 malthoff - * Disable Error Log Message when calling SkGeInit(level 2) - * more than once. - * - * Revision 1.37 1998/12/07 12:18:25 gklug - * add: refinement of autosense mode: take into account the autoneg cap of LiPa - * - * Revision 1.36 1998/12/07 07:10:39 gklug - * fix: init values of LinkBroken/ Capabilities for management - * - * Revision 1.35 1998/12/02 10:56:20 gklug - * fix: do NOT init LoinkSync Counter. - * - * Revision 1.34 1998/12/01 10:53:21 gklug - * add: init of additional Counters for workaround - * - * Revision 1.33 1998/12/01 10:00:49 gklug - * add: init PIsave var in Port struct - * - * Revision 1.32 1998/11/26 14:50:40 gklug - * chg: Default is autosensing with AUTOFULL mode - * - * Revision 1.31 1998/11/25 15:36:16 gklug - * fix: do NOT stop LED Timer when port should be stopped - * - * Revision 1.30 1998/11/24 13:15:28 gklug - * add: Init PCkeckPar struct member - * - * Revision 1.29 1998/11/18 13:19:27 malthoff - * Disable packet arbiter timeouts on receive side. - * Use maximum timeout value for packet arbiter - * transmit timeouts. - * Add TestStopBit() function to handle stop RX/TX - * problem with active descriptor poll timers. - * Bug Fix: Descriptor Poll Timer not started, because - * GIPollTimerVal was initialized with 0. - * - * Revision 1.28 1998/11/13 14:24:26 malthoff - * Bug Fix: SkGeStopPort() may hang if a Packet Arbiter Timout - * is pending or occurs while waiting for TX_STOP and RX_STOP. - * The PA timeout is cleared now while waiting for TX- or RX_STOP. - * - * Revision 1.27 1998/11/02 11:04:36 malthoff - * fix the last fix - * - * Revision 1.26 1998/11/02 10:37:03 malthoff - * Fix: SkGePollTxD() enables always the synchronounous poll timer. - * - * Revision 1.25 1998/10/28 07:12:43 cgoos - * Fixed "LED_STOP" in SkGeLnkSyncCnt, "== SK_INIT_IO" in SkGeInit. - * Removed: Reset of RAM Interface in SkGeStopPort. - * - * Revision 1.24 1998/10/27 08:13:12 malthoff - * Remove temporary code. - * - * Revision 1.23 1998/10/26 07:45:03 malthoff - * Add Address Calculation Workaround: If the EPROM byte - * Id is 3, the address offset is 512 kB. - * Initialize default values for PLinkMode and PFlowCtrlMode. - * - * Revision 1.22 1998/10/22 09:46:47 gklug - * fix SysKonnectFileId typo - * - * Revision 1.21 1998/10/20 12:11:56 malthoff - * Don't dendy the Queue config if the size of the unused - * Rx qeueu is zero. - * - * Revision 1.20 1998/10/19 07:27:58 malthoff - * SkGeInitRamIface() is public to be called by diagnostics. - * - * Revision 1.19 1998/10/16 13:33:45 malthoff - * Fix: enabling descriptor polling is not allowed until - * the descriptor addresses are set. Descriptor polling - * must be handled by the driver. - * - * Revision 1.18 1998/10/16 10:58:27 malthoff - * Remove temp. code for Diag prototype. - * Remove lint warning for dummy reads. - * Call SkGeLoadLnkSyncCnt() during SkGeInitPort(). - * - * Revision 1.17 1998/10/14 09:16:06 malthoff - * Change parameter LimCount and programming of - * the limit counter in SkGeCfgSync(). - * - * Revision 1.16 1998/10/13 09:21:16 malthoff - * Don't set XM_RX_SELF_RX in RxCmd Reg, because it's - * like a Loopback Mode in half duplex. - * - * Revision 1.15 1998/10/09 06:47:40 malthoff - * SkGeInitMacArb(): set recovery counters init value - * to zero although this counters are not uesd. - * Bug fix in Rx Upper/Lower Pause Threshold calculation. - * Add XM_RX_SELF_RX to RxCmd. - * - * Revision 1.14 1998/10/06 15:15:53 malthoff - * Make sure no pending IRQ is cleared in SkGeLoadLnkSyncCnt(). - * - * Revision 1.13 1998/10/06 14:09:36 malthoff - * Add SkGeLoadLnkSyncCnt(). Modify - * the 'port stopped' condition according - * to the current problem report. - * - * Revision 1.12 1998/10/05 08:17:21 malthoff - * Add functions: SkGePollRxD(), SkGePollTxD(), - * DoCalcAddr(), SkGeCheckQSize(), - * DoInitRamQueue(), and SkGeCfgSync(). - * Add coding for SkGeInitMacArb(), SkGeInitPktArb(), - * SkGeInitMacFifo(), SkGeInitRamBufs(), - * SkGeInitRamIface(), and SkGeInitBmu(). - * - * Revision 1.11 1998/09/29 08:26:29 malthoff - * bug fix: SkGeInit0() 'i' should be increment. - * - * Revision 1.10 1998/09/28 13:19:01 malthoff - * Coding time: Save the done work. - * Modify SkGeLinkLED(), add SkGeXmitLED(), - * define SkGeCheckQSize(), SkGeInitMacArb(), - * SkGeInitPktArb(), SkGeInitMacFifo(), - * SkGeInitRamBufs(), SkGeInitRamIface(), - * and SkGeInitBmu(). Do coding for SkGeStopPort(), - * SkGeInit1(), SkGeInit2(), and SkGeInit3(). - * Do coding for SkGeDinit() and SkGeInitPort(). - * - * Revision 1.9 1998/09/16 14:29:05 malthoff - * Some minor changes. - * - * Revision 1.8 1998/09/11 05:29:14 gklug - * add: init state of a port - * - * Revision 1.7 1998/09/04 09:26:25 malthoff - * Short temporary modification. - * - * Revision 1.6 1998/09/04 08:27:59 malthoff - * Remark the do-while in StopPort() because it never ends - * without a GE adapter. - * - * Revision 1.5 1998/09/03 14:05:45 malthoff - * Change comment for SkGeInitPort(). Do not - * repair the queue sizes if invalid. - * - * Revision 1.4 1998/09/03 10:03:19 malthoff - * Implement the new interface according to the - * reviewed interface specification. - * - * Revision 1.3 1998/08/19 09:11:25 gklug - * fix: struct are removed from c-source (see CCC) - * - * Revision 1.2 1998/07/28 12:33:58 malthoff - * Add 'IoC' parameter in function declaration and SK IO macros. - * - * Revision 1.1 1998/07/23 09:48:57 malthoff - * Creation. First dummy 'C' file. - * SkGeInit(Level 0) is card_start for GE. - * SkGeDeInit() is card_stop for GE. - * - * - ******************************************************************************/ - +/*#define DEBUG*/ #include #ifdef CONFIG_SK98 @@ -404,18 +35,125 @@ /* local variables ************************************************************/ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "@(#)$Id: skgeinit.c,v 1.85 2003/02/05 15:30:33 rschmidt Exp $ (C) SK "; + "@(#) $Id: skgeinit.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif struct s_QOffTab { int RxQOff; /* Receive Queue Address Offset */ int XsQOff; /* Sync Tx Queue Address Offset */ int XaQOff; /* Async Tx Queue Address Offset */ }; + static struct s_QOffTab QOffTab[] = { {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2} }; +struct s_Config { + char ScanString[8]; + SK_U32 Value; +}; + +static struct s_Config OemConfig = { + {'O','E','M','_','C','o','n','f'}, +#ifdef SK_OEM_CONFIG + OEM_CONFIG_VALUE, +#else + 0, +#endif +}; + +#ifndef SK_SLIM +/****************************************************************************** + * + * SkGePortVlan() - Enable / Disable VLAN support + * + * Description: + * Enable or disable the VLAN support of the selected port. + * The new configuration is *not* saved over any SkGeStopPort() and + * SkGeInitPort() calls. + * Currently this function is only supported on Yukon-2/EC adapters. + * + * Returns: + * nothing + */ +void SkGePortVlan( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port number */ +SK_BOOL Enable) /* Flag */ +{ + SK_U32 RxCtrl; + SK_U32 TxCtrl; + + if (CHIP_ID_YUKON_2(pAC)) { + if (Enable) { + RxCtrl = RX_VLAN_STRIP_ON; + TxCtrl = TX_VLAN_TAG_ON; + } + else { + RxCtrl = RX_VLAN_STRIP_OFF; + TxCtrl = TX_VLAN_TAG_OFF; + } + + SK_OUT32(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), RxCtrl); + SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TxCtrl); + } +} /* SkGePortVlan */ + + +/****************************************************************************** + * + * SkGeRxRss() - Enable / Disable RSS Hash Calculation + * + * Description: + * Enable or disable the RSS hash calculation of the selected port. + * The new configuration is *not* saved over any SkGeStopPort() and + * SkGeInitPort() calls. + * Currently this function is only supported on Yukon-2/EC adapters. + * + * Returns: + * nothing + */ +void SkGeRxRss( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port number */ +SK_BOOL Enable) /* Flag */ +{ + if (CHIP_ID_YUKON_2(pAC)) { + SK_OUT32(IoC, Q_ADDR(pAC->GIni.GP[Port].PRxQOff, Q_CSR), + Enable ? BMU_ENA_RX_RSS_HASH : BMU_DIS_RX_RSS_HASH); + } +} /* SkGeRxRss */ + + +/****************************************************************************** + * + * SkGeRxCsum() - Enable / Disable Receive Checksum + * + * Description: + * Enable or disable the checksum of the selected port. + * The new configuration is *not* saved over any SkGeStopPort() and + * SkGeInitPort() calls. + * Currently this function is only supported on Yukon-2/EC adapters. + * + * Returns: + * nothing + */ +void SkGeRxCsum( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port number */ +SK_BOOL Enable) /* Flag */ +{ + if (CHIP_ID_YUKON_2(pAC)) { + SK_OUT32(IoC, Q_ADDR(pAC->GIni.GP[Port].PRxQOff, Q_CSR), + Enable ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + } +} /* SkGeRxCsum */ +#endif /* !SK_SLIM */ /****************************************************************************** * @@ -431,8 +169,8 @@ static struct s_QOffTab QOffTab[] = { * nothing */ void SkGePollRxD( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL PollRxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ { @@ -440,8 +178,8 @@ SK_BOOL PollRxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ pPrt = &pAC->GIni.GP[Port]; - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (PollRxD) ? - CSR_ENA_POL : CSR_DIS_POL); + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (SK_U32)((PollRxD) ? + CSR_ENA_POL : CSR_DIS_POL)); } /* SkGePollRxD */ @@ -459,8 +197,8 @@ SK_BOOL PollRxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ * nothing */ void SkGePollTxD( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ { @@ -469,7 +207,7 @@ SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ pPrt = &pAC->GIni.GP[Port]; - DWord = (PollTxD) ? CSR_ENA_POL : CSR_DIS_POL; + DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL); if (pPrt->PXSQSize != 0) { SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord); @@ -480,7 +218,7 @@ SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ } } /* SkGePollTxD */ - +#ifndef SK_SLIM /****************************************************************************** * * SkGeYellowLED() - Switch the yellow LED on or off. @@ -495,21 +233,32 @@ SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ * nothing */ void SkGeYellowLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int State) /* yellow LED state, 0 = OFF, 0 != ON */ { - if (State == 0) { - /* Switch yellow LED OFF */ - SK_OUT8(IoC, B0_LED, LED_STAT_OFF); + int LedReg; + + if (CHIP_ID_YUKON_2(pAC)) { + /* different mapping on Yukon-2 */ + LedReg = B0_CTST + 1; } else { - /* Switch yellow LED ON */ - SK_OUT8(IoC, B0_LED, LED_STAT_ON); + LedReg = B0_LED; + } + + if (State == 0) { + /* Switch state LED OFF */ + SK_OUT8(IoC, LedReg, LED_STAT_OFF); + } + else { + /* Switch state LED ON */ + SK_OUT8(IoC, LedReg, LED_STAT_ON); } } /* SkGeYellowLED */ +#endif /* !SK_SLIM */ - +#if (!defined(SK_SLIM) || defined(GENESIS)) /****************************************************************************** * * SkGeXmitLED() - Modify the Operational Mode of a transmission LED. @@ -528,8 +277,8 @@ int State) /* yellow LED state, 0 = OFF, 0 != ON */ * nothing */ void SkGeXmitLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Led, /* offset to the LED Init Value register */ int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */ { @@ -554,17 +303,17 @@ int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */ */ SK_OUT32(IoC, Led + XMIT_LED_CNT, 0); SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF); - break; } /* - * 1000BT: The Transmit LED is driven by the PHY. + * 1000BT: the Transmit LED is driven by the PHY. * But the default LED configuration is used for * Level One and Broadcom PHYs. - * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.) - * (In this case it has to be added here. But we will see. XXX) + * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set. + * In this case it has to be added here.) */ } /* SkGeXmitLED */ +#endif /* !SK_SLIM || GENESIS */ /****************************************************************************** @@ -585,12 +334,12 @@ int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */ * 1: configuration error */ static int DoCalcAddr( -SK_AC *pAC, /* adapter context */ -SK_GEPORT *pPrt, /* port index */ -int QuSize, /* size of the queue to configure in kB */ -SK_U32 *StartVal, /* start value for address calculation */ -SK_U32 *QuStartAddr, /* start addr to calculate */ -SK_U32 *QuEndAddr) /* end address to calculate */ +SK_AC *pAC, /* Adapter Context */ +SK_GEPORT SK_FAR *pPrt, /* port index */ +int QuSize, /* size of the queue to configure in kB */ +SK_U32 SK_FAR *StartVal, /* start value for address calculation */ +SK_U32 SK_FAR *QuStartAddr,/* start addr to calculate */ +SK_U32 SK_FAR *QuEndAddr) /* end address to calculate */ { SK_U32 EndVal; SK_U32 NextStart; @@ -620,6 +369,29 @@ SK_U32 *QuEndAddr) /* end address to calculate */ return(Rtv); } /* DoCalcAddr */ +/****************************************************************************** + * + * SkGeRoundQueueSize() - Round the given queue size to the adpaters QZ units + * + * Description: + * This function rounds the given queue size in kBs to adapter specific + * queue size units (Genesis and Yukon: 8 kB, Yukon-2/EC: 1 kB). + * + * Returns: + * the rounded queue size in kB + */ +static int SkGeRoundQueueSize( +SK_AC *pAC, /* Adapter Context */ +int QueueSizeKB) /* Queue size in kB */ +{ + int QueueSizeSteps; + + QueueSizeSteps = (CHIP_ID_YUKON_2(pAC)) ? QZ_STEP_Y2 : QZ_STEP; + + return((QueueSizeKB + QueueSizeSteps - 1) & ~(QueueSizeSteps - 1)); +} /* SkGeRoundQueueSize */ + + /****************************************************************************** * * SkGeInitAssignRamToQueues() - allocate default queue sizes @@ -627,7 +399,7 @@ SK_U32 *QuEndAddr) /* end address to calculate */ * Description: * This function assigns the memory to the different queues and ports. * When DualNet is set to SK_TRUE all ports get the same amount of memory. - * Otherwise the first port gets most of the memory and all the + * Otherwise the first port gets most of the memory and all the * other ports just the required minimum. * This function can only be called when pAC->GIni.GIRamSize and * pAC->GIni.GIMacsFound have been initialized, usually this happens @@ -640,103 +412,146 @@ SK_U32 *QuEndAddr) /* end address to calculate */ */ int SkGeInitAssignRamToQueues( -SK_AC *pAC, /* Adapter context */ +SK_AC *pAC, /* Adapter Context */ int ActivePort, /* Active Port in RLMT mode */ -SK_BOOL DualNet) /* adapter context */ +SK_BOOL DualNet) /* Dual Net active */ { int i; int UsedKilobytes; /* memory already assigned */ int ActivePortKilobytes; /* memory available for active port */ - SK_GEPORT *pGePort; - - UsedKilobytes = 0; + int MinQueueSize; /* min. memory for queues */ + int TotalRamSize; /* total memory for queues */ + SK_BOOL DualPortYukon2; + SK_GEPORT *pPrt; if (ActivePort >= pAC->GIni.GIMacsFound) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n", ActivePort)); return(1); } - if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) + - ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) { + + DualPortYukon2 = (CHIP_ID_YUKON_2(pAC) && pAC->GIni.GIMacsFound == 2); + + TotalRamSize = pAC->GIni.GIRamSize; + + if (DualPortYukon2) { + TotalRamSize *= 2; + } + + MinQueueSize = SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE; + + if (MinQueueSize > pAC->GIni.GIRamSize) { + MinQueueSize = pAC->GIni.GIRamSize; + } + + if ((pAC->GIni.GIMacsFound * MinQueueSize + + RAM_QUOTA_SYNC * SK_MIN_TXQ_SIZE) > TotalRamSize) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n", - pAC->GIni.GIRamSize)); + TotalRamSize)); return(2); } - if (DualNet) { /* every port gets the same amount of memory */ - ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound; + ActivePortKilobytes = TotalRamSize / pAC->GIni.GIMacsFound; + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - pGePort = &pAC->GIni.GP[i]; + pPrt = &pAC->GIni.GP[i]; + if (DualPortYukon2) { + ActivePortKilobytes = pAC->GIni.GIRamSize; + } /* take away the minimum memory for active queues */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); + ActivePortKilobytes -= MinQueueSize; /* receive queue gets the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB(( - ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100)) + pPrt->PRxQSize = SkGeRoundQueueSize(pAC, + (int)((long)ActivePortKilobytes * RAM_QUOTA_RX) / 100) + SK_MIN_RXQ_SIZE; - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); + ActivePortKilobytes -= (pPrt->PRxQSize - SK_MIN_RXQ_SIZE); /* synchronous transmit queue */ - pGePort->PXSQSize = 0; + pPrt->PXSQSize = 0; /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes + - SK_MIN_TXQ_SIZE); + pPrt->PXAQSize = SkGeRoundQueueSize(pAC, + ActivePortKilobytes + SK_MIN_TXQ_SIZE); } } - else { - /* Rlmt Mode or single link adapter */ + else { /* RLMT Mode or single link adapter */ - /* Set standby queue size defaults for all standby ports */ + UsedKilobytes = 0; + + /* set standby queue size defaults for all standby ports */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { if (i != ActivePort) { - pGePort = &pAC->GIni.GP[i]; + pPrt = &pAC->GIni.GP[i]; - pGePort->PRxQSize = SK_MIN_RXQ_SIZE; - pGePort->PXAQSize = SK_MIN_TXQ_SIZE; - pGePort->PXSQSize = 0; + if (DualPortYukon2) { + pPrt->PRxQSize = SkGeRoundQueueSize(pAC, + (int)((long)(pAC->GIni.GIRamSize - MinQueueSize) * + RAM_QUOTA_RX) / 100) + SK_MIN_RXQ_SIZE; + + pPrt->PXAQSize = pAC->GIni.GIRamSize - pPrt->PRxQSize; + } + else { + pPrt->PRxQSize = SK_MIN_RXQ_SIZE; + pPrt->PXAQSize = SK_MIN_TXQ_SIZE; + } + pPrt->PXSQSize = 0; /* Count used RAM */ - UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize; + UsedKilobytes += pPrt->PRxQSize + pPrt->PXAQSize; } } /* what's left? */ - ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes; + ActivePortKilobytes = TotalRamSize - UsedKilobytes; /* assign it to the active port */ /* first take away the minimum memory */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); - pGePort = &pAC->GIni.GP[ActivePort]; + ActivePortKilobytes -= MinQueueSize; + pPrt = &pAC->GIni.GP[ActivePort]; - /* receive queue get's the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes * - (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE; + /* receive queue gets 80% of the rest */ + pPrt->PRxQSize = SkGeRoundQueueSize(pAC, + (int)((long)ActivePortKilobytes * RAM_QUOTA_RX) / 100); - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); + ActivePortKilobytes -= pPrt->PRxQSize; + + /* add the minimum memory for Rx queue */ + pPrt->PRxQSize += MinQueueSize/2; /* synchronous transmit queue */ - pGePort->PXSQSize = 0; + pPrt->PXSQSize = 0; - /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) + - SK_MIN_TXQ_SIZE; + /* asynchronous transmit queue gets 20% of the rest */ + pPrt->PXAQSize = SkGeRoundQueueSize(pAC, ActivePortKilobytes) + + /* add the minimum memory for Tx queue */ + MinQueueSize/2; } -#ifdef VCPU - VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n", - pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize); -#endif /* VCPU */ + +#ifdef DEBUG + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + pPrt = &pAC->GIni.GP[i]; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Port %d: RxQSize=%u, TxAQSize=%u, TxSQSize=%u\n", + i, pPrt->PRxQSize, pPrt->PXAQSize, pPrt->PXSQSize)); + } +#endif /* DEBUG */ return(0); } /* SkGeInitAssignRamToQueues */ + /****************************************************************************** * * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration @@ -747,12 +562,12 @@ SK_BOOL DualNet) /* adapter context */ * used ports. * This requirements must be fullfilled to have a valid configuration: * - The size of all queues must not exceed GIRamSize. - * - The queue sizes must be specified in units of 8 kB. + * - The queue sizes must be specified in units of 8 kB (Genesis & Yukon). * - The size of Rx queues of available ports must not be - * smaller than 16 kB. + * smaller than 16 kB (Genesis & Yukon) resp. 10 kB (Yukon-2). * - The size of at least one Tx queue (synch. or asynch.) - * of available ports must not be smaller than 16 kB - * when Jumbo Frames are used. + * of available ports must not be smaller than 16 kB (Genesis & Yukon), + * resp. 10 kB (Yukon-2) when Jumbo Frames are used. * - The RAM start and end addresses must not be changed * for ports which are already initialized. * Furthermore SkGeCheckQSize() defines the Start and End Addresses @@ -763,30 +578,41 @@ SK_BOOL DualNet) /* adapter context */ * 1: Queue Size Configuration invalid */ static int SkGeCheckQSize( -SK_AC *pAC, /* adapter context */ +SK_AC *pAC, /* Adapter Context */ int Port) /* port index */ { SK_GEPORT *pPrt; - int UsedMem; /* total memory used (max. found ports) */ int i; int Rtv; int Rtv2; SK_U32 StartAddr; +#ifndef SK_SLIM + int UsedMem; /* total memory used (max. found ports) */ +#endif + + Rtv = 0; + +#ifndef SK_SLIM UsedMem = 0; - Rtv = 0; + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { pPrt = &pAC->GIni.GP[i]; - if ((pPrt->PRxQSize & QZ_UNITS) != 0 || - (pPrt->PXSQSize & QZ_UNITS) != 0 || - (pPrt->PXAQSize & QZ_UNITS) != 0) { + if (CHIP_ID_YUKON_2(pAC)) { + UsedMem = 0; + } + else if (((pPrt->PRxQSize & QZ_UNITS) != 0 || + (pPrt->PXSQSize & QZ_UNITS) != 0 || + (pPrt->PXAQSize & QZ_UNITS) != 0)) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); return(1); } - if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) { +#ifndef SK_DIAG + if (i == Port && pAC->GIni.GIRamSize > SK_MIN_RXQ_SIZE && + pPrt->PRxQSize < SK_MIN_RXQ_SIZE) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG); return(1); } @@ -796,26 +622,34 @@ int Port) /* port index */ * if Jumbo Frames are used, this size has to be >= 16 kB. */ if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) || - (pAC->GIni.GIPortUsage == SK_JUMBO_LINK && - ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) || + (pPrt->PPortUsage == SK_JUMBO_LINK && + ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) || (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG); return(1); } +#endif /* !SK_DIAG */ UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize; + + if (UsedMem > pAC->GIni.GIRamSize) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); + return(1); + } } - if (UsedMem > pAC->GIni.GIRamSize) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); - return(1); - } +#endif /* !SK_SLIM */ /* Now start address calculation */ StartAddr = pAC->GIni.GIRamOffs; for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + pPrt = &pAC->GIni.GP[i]; + if (CHIP_ID_YUKON_2(pAC)) { + StartAddr = 0; + } + /* Calculate/Check values for the receive queue */ Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr, &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd); @@ -841,6 +675,7 @@ int Port) /* port index */ } /* SkGeCheckQSize */ +#ifdef GENESIS /****************************************************************************** * * SkGeInitMacArb() - Initialize the MAC Arbiter @@ -854,8 +689,8 @@ int Port) /* port index */ * nothing */ static void SkGeInitMacArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { /* release local reset */ SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR); @@ -894,8 +729,8 @@ SK_IOC IoC) /* IO context */ * nothing */ static void SkGeInitPktArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { /* release local reset */ SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR); @@ -911,7 +746,8 @@ SK_IOC IoC) /* IO context */ * NOTE: the packet arbiter timeout interrupt is needed for * half duplex hangup workaround */ - if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) { + if (pAC->GIni.GP[MAC_1].PPortUsage != SK_JUMBO_LINK && + pAC->GIni.GP[MAC_2].PPortUsage != SK_JUMBO_LINK) { if (pAC->GIni.GIMacsFound == 1) { SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1); } @@ -920,6 +756,7 @@ SK_IOC IoC) /* IO context */ } } } /* SkGeInitPktArb */ +#endif /* GENESIS */ /****************************************************************************** @@ -933,14 +770,11 @@ SK_IOC IoC) /* IO context */ * nothing */ static void SkGeInitMacFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_U16 Word; -#ifdef VCPU - SK_U32 DWord; -#endif /* VCPU */ /* * For each FIFO: * - release local reset @@ -949,55 +783,106 @@ int Port) /* Port Index (MAC_1 + n) */ * - enable the FIFO */ - Word = GMF_RX_CTRL_DEF; - +#ifdef GENESIS if (pAC->GIni.GIGenesis) { - /* Configure Rx MAC FIFO */ + /* configure Rx MAC FIFO */ SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR); SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF); SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD); - /* Configure Tx MAC FIFO */ + /* configure Tx MAC FIFO */ SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR); SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD); - /* Enable frame flushing if jumbo frames used */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + /* enable frame flushing if jumbo frames used */ + if (pAC->GIni.GP[Port].PPortUsage == SK_JUMBO_LINK) { SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH); } } - else { - /* set Rx GMAC FIFO Flush Mask */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK); +#endif /* GENESIS */ - if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) { +#ifdef YUKON + if (pAC->GIni.GIYukon) { + + Word = (SK_U16)GMF_RX_CTRL_DEF; + + /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */ + if (pAC->GIni.GIYukonLite /* && pAC->GIni.GIChipId == CHIP_ID_YUKON */) { Word &= ~GMF_RX_F_FL_ON; } - /* Configure Rx MAC FIFO */ + /* configure Rx GMAC FIFO */ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word); - /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); + Word = RX_FF_FL_DEF_MSK; - /* Configure Tx MAC FIFO */ +#ifndef SK_DIAG + if (HW_FEATURE(pAC, HWF_WA_DEV_4115)) { + /* + * Flushing must be enabled (needed for ASF see dev. #4.29), + * but the flushing mask should be disabled (see dev. #4.115) + */ + Word = 0; + } +#endif /* !SK_DIAG */ + + /* set Rx GMAC FIFO Flush Mask (after clearing reset) */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), Word); + + /* default: 0x0a -> 56 bytes on Yukon-1 and 64 bytes on Yukon-2 */ + Word = (SK_U16)RX_GMF_FL_THR_DEF; + + if (CHIP_ID_YUKON_2(pAC)) { + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC && + pAC->GIni.GIAsfEnabled) { + /* WA for dev. #4.30 (reduce to 0x08 -> 48 bytes) */ + Word -= 2; + } + } + else { + /* + * because Pause Packet Truncation in GMAC is not working + * we have to increase the Flush Threshold to 64 bytes + * in order to flush pause packets in Rx FIFO on Yukon-1 + */ + Word++; + } + + /* set Rx GMAC FIFO Flush Threshold (after clearing reset) */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), Word); + + /* configure Tx GMAC FIFO */ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF); -#ifdef VCPU - SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord); - SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord); -#endif /* VCPU */ + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) { + /* set Rx Pause Threshold */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_LP_THR), (SK_U16)SK_ECU_LLPP); + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_UP_THR), (SK_U16)SK_ECU_ULPP); - /* set Tx GMAC FIFO Almost Empty Threshold */ -/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */ + if (pAC->GIni.GP[Port].PPortUsage == SK_JUMBO_LINK) { + /* set Tx GMAC FIFO Almost Empty Threshold */ + SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_AE_THR), + (SK_U16)SK_ECU_AE_THR); + /* disable Store & Forward mode for TX */ + SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_STFW_DIS); + } +#ifdef TEST_ONLY + else { + /* enable Store & Forward mode for TX */ + SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_STFW_ENA); + } +#endif /* TEST_ONLY */ + } } +#endif /* YUKON */ + } /* SkGeInitMacFifo */ - +#ifdef SK_LNK_SYNC_CNT /****************************************************************************** * * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting @@ -1018,8 +903,8 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkGeLoadLnkSyncCnt( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_U32 CntVal) /* Counter value */ { @@ -1029,7 +914,7 @@ SK_U32 CntVal) /* Counter value */ SK_BOOL IrqPend; /* stop counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP); + SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_STOP); /* * ASIC problem: @@ -1042,6 +927,7 @@ SK_U32 CntVal) /* Counter value */ IrqPend = SK_FALSE; SK_IN32(IoC, B0_ISRC, &ISrc); SK_IN32(IoC, B0_IMSK, &OrgIMsk); + if (Port == MAC_1) { NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1; if ((ISrc & IS_LNK_SYNC_M1) != 0) { @@ -1054,6 +940,7 @@ SK_U32 CntVal) /* Counter value */ IrqPend = SK_TRUE; } } + if (!IrqPend) { SK_OUT32(IoC, B0_IMSK, NewIMsk); } @@ -1062,16 +949,19 @@ SK_U32 CntVal) /* Counter value */ SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal); /* start counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START); + SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_START); if (!IrqPend) { - /* clear the unexpected IRQ, and restore the interrupt mask */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ); + /* clear the unexpected IRQ */ + SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_CLR_IRQ); + + /* restore the interrupt mask */ SK_OUT32(IoC, B0_IMSK, OrgIMsk); } } /* SkGeLoadLnkSyncCnt*/ +#endif /* SK_LNK_SYNC_CNT */ - +#if defined(SK_DIAG) || defined(SK_CFG_SYNC) /****************************************************************************** * * SkGeCfgSync() - Configure synchronous bandwidth for this port. @@ -1101,8 +991,8 @@ SK_U32 CntVal) /* Counter value */ * synchronous queue is configured */ int SkGeCfgSync( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_U32 IntTime, /* Interval Timer Value in units of 8ns */ SK_U32 LimCount, /* Number of bytes to transfer during IntTime */ @@ -1160,6 +1050,7 @@ int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */ return(0); } /* SkGeCfgSync */ +#endif /* SK_DIAG || SK_CFG_SYNC*/ /****************************************************************************** @@ -1173,10 +1064,10 @@ int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */ * Returns: * nothing */ -static void DoInitRamQueue( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int QuIoOffs, /* Queue IO Address Offset */ +void DoInitRamQueue( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int QuIoOffs, /* Queue I/O Address Offset */ SK_U32 QuStartAddr, /* Queue Start Address */ SK_U32 QuEndAddr, /* Queue End Address */ int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ @@ -1209,8 +1100,7 @@ int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ /* continue with SK_RX_BRAM_Q */ case SK_RX_BRAM_Q: - /* write threshold for Rx Queue */ - + /* write threshold for Rx Queue (Pause packets) */ SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal); SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal); @@ -1224,8 +1114,9 @@ int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ * or YUKON is used ((GMAC Tx FIFO is only 1 kB) * we NEED Store & Forward of the RAM buffer. */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK || - !pAC->GIni.GIGenesis) { + if (pAC->GIni.GP[MAC_1].PPortUsage == SK_JUMBO_LINK || + pAC->GIni.GP[MAC_2].PPortUsage == SK_JUMBO_LINK || + pAC->GIni.GIYukon) { /* enable Store & Forward Mode for the Tx Side */ SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD); } @@ -1253,8 +1144,8 @@ int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ * nothing */ static void SkGeInitRamBufs( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; @@ -1262,8 +1153,8 @@ int Port) /* Port Index (MAC_1 + n) */ pPrt = &pAC->GIni.GP[Port]; - if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) { - RxQType = SK_RX_SRAM_Q; /* small Rx Queue */ + if (pPrt->PRxQSize <= SK_MIN_RXQ_SIZE) { + RxQType = SK_RX_SRAM_Q; /* small Rx Queue */ } else { RxQType = SK_RX_BRAM_Q; /* big Rx Queue */ @@ -1295,26 +1186,37 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkGeInitRamIface( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { - /* release local reset */ - SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR); + int i; + int RamBuffers; - /* configure timeout values */ - SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53); + if (CHIP_ID_YUKON_2(pAC)) { + RamBuffers = pAC->GIni.GIMacsFound; + } + else { + RamBuffers = 1; + } + for (i = 0; i < RamBuffers; i++) { + /* release local reset */ + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_CTRL), (SK_U8)RI_RST_CLR); + + /* configure timeout values */ + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53); + SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53); + } } /* SkGeInitRamIface */ @@ -1329,41 +1231,91 @@ SK_IOC IoC) /* IO context */ * nothing */ static void SkGeInitBmu( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; - SK_U32 RxWm; - SK_U32 TxWm; + SK_U16 RxWm; + SK_U16 TxWm; pPrt = &pAC->GIni.GP[Port]; RxWm = SK_BMU_RX_WM; TxWm = SK_BMU_TX_WM; - if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) { - /* for better performance */ - RxWm /= 2; - TxWm /= 2; + if (CHIP_ID_YUKON_2(pAC)) { + + if (pAC->GIni.GIPciBus == SK_PEX_BUS) { + /* for better performance set it to 128 */ + RxWm = SK_BMU_RX_WM_PEX; + } + + /* Rx Queue: Release all local resets and set the watermark */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_OPER_INIT); + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_FIFO_OP_ON); + + SK_OUT16(IoC, Q_ADDR(pPrt->PRxQOff, Q_WM), RxWm); + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U && + pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A1) { + /* MAC Rx RAM Read is controlled by hardware */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), F_M_RX_RAM_DIS); + } + + /* + * Tx Queue: Release all local resets if the queue is used ! + * set watermark + */ + if (pPrt->PXSQSize != 0 && HW_SYNC_TX_SUPPORTED(pAC)) { + /* Yukon-EC doesn't have a synchronous Tx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_OPER_INIT); + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_FIFO_OP_ON); + + SK_OUT16(IoC, Q_ADDR(pPrt->PXsQOff, Q_WM), TxWm); + } + + if (pPrt->PXAQSize != 0) { + + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_OPER_INIT); + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_FIFO_OP_ON); + + SK_OUT16(IoC, Q_ADDR(pPrt->PXaQOff, Q_WM), TxWm); + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U && + pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A0) { + /* fix for Yukon-EC Ultra: set BMU FIFO level */ + SK_OUT16(IoC, Q_ADDR(pPrt->PXaQOff, Q_AL), SK_ECU_TXFF_LEV); + } + } } + else { + if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) { + /* for better performance */ + RxWm /= 2; + TxWm /= 2; + } - /* Rx Queue: Release all local resets and set the watermark */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm); + /* Rx Queue: Release all local resets and set the watermark */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm); - /* - * Tx Queue: Release all local resets if the queue is used ! - * set watermark - */ - if (pPrt->PXSQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm); - } + /* + * Tx Queue: Release all local resets if the queue is used ! + * set watermark + */ + if (pPrt->PXSQSize != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm); + } - if (pPrt->PXAQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm); + if (pPrt->PXAQSize != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET); + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm); + } } /* * Do NOT enable the descriptor poll timers here, because @@ -1387,20 +1339,29 @@ int Port) /* Port Index (MAC_1 + n) */ */ static SK_U32 TestStopBit( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int QuIoOffs) /* Queue IO Address Offset */ +SK_IOC IoC, /* I/O Context */ +int QuIoOffs) /* Queue I/O Address Offset */ { SK_U32 QuCsr; /* CSR contents */ SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); - if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) { - /* Stop Descriptor overridden by start command */ - SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP); + if (CHIP_ID_YUKON_2(pAC)) { + if ((QuCsr & (BMU_STOP | BMU_IDLE)) == 0) { + /* Stop Descriptor overridden by start command */ + SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), BMU_STOP); - SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); + SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); + } } + else { + if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) { + /* Stop Descriptor overridden by start command */ + SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP); + SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); + } + } return(QuCsr); } /* TestStopBit */ @@ -1424,13 +1385,13 @@ int QuIoOffs) /* Queue IO Address Offset */ * has to be stopped once before. * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX * - * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive. - * SK_HARD_RST Resets the MAC and the PHY. + * RstMode = SK_SOFT_RST Resets the MAC, the PHY is still alive. + * SK_HARD_RST Resets the MAC and the PHY. * * Example: * 1) A Link Down event was signaled for a port. Therefore the activity * of this port should be stopped and a hardware reset should be issued - * to enable the workaround of XMAC errata #2. But the received frames + * to enable the workaround of XMAC Errata #2. But the received frames * should not be discarded. * ... * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST); @@ -1484,56 +1445,82 @@ int QuIoOffs) /* Queue IO Address Offset */ * SWITCH_PORT. */ void SkGeStopPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -int Port, /* port to stop (MAC_1 + n) */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port to stop (MAC_1 + n) */ int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */ int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ { -#ifndef SK_DIAG - SK_EVPARA Para; -#endif /* !SK_DIAG */ SK_GEPORT *pPrt; - SK_U32 DWord; + SK_U32 RxCsr; SK_U32 XsCsr; SK_U32 XaCsr; SK_U64 ToutStart; + SK_U32 CsrStart; + SK_U32 CsrStop; + SK_U32 CsrIdle; + SK_U32 CsrTest; + SK_U8 rsl; /* FIFO read shadow level */ + SK_U8 rl; /* FIFO read level */ int i; int ToutCnt; pPrt = &pAC->GIni.GP[Port]; + /* set the proper values of Q_CSR register layout depending on the chip */ + if (CHIP_ID_YUKON_2(pAC)) { + CsrStart = BMU_START; + CsrStop = BMU_STOP; + CsrIdle = BMU_IDLE; + CsrTest = BMU_IDLE; + } + else { + CsrStart = CSR_START; + CsrStop = CSR_STOP; + CsrIdle = CSR_SV_IDLE; + CsrTest = CSR_SV_IDLE | CSR_STOP; + } + if ((Dir & SK_STOP_TX) != 0) { - /* disable receiver and transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); + + if (!pAC->GIni.GIAsfEnabled) { + /* disable receiver and transmitter */ + SkMacRxTxDisable(pAC, IoC, Port); + } /* stop both transmit queues */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CsrStop); + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CsrStop); /* * If the BMU is in the reset state CSR_STOP will terminate * immediately. */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP); ToutStart = SkOsGetTime(pAC); ToutCnt = 0; do { - /* - * Clear packet arbiter timeout to make sure - * this loop will terminate. - */ - SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_TX1 : - PA_CLR_TO_TX2); +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + /* clear Tx packet arbiter timeout IRQ */ + SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ? + PA_CLR_TO_TX1 : PA_CLR_TO_TX2)); + /* + * If the transfer stucks at the XMAC the STOP command will not + * terminate if we don't flush the XMAC's transmit FIFO ! + */ + SkMacFlushTxFifo(pAC, IoC, Port); + } +#endif /* GENESIS */ - /* - * If the transfer stucks at the MAC the STOP command will not - * terminate if we don't flush the XMAC's transmit FIFO ! - */ - SkMacFlushTxFifo(pAC, IoC, Port); - - XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff); + if (HW_SYNC_TX_SUPPORTED(pAC)) { + XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); + } + else { + XsCsr = XaCsr; + } + if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) { /* * Timeout of 1/18 second reached. @@ -1541,49 +1528,80 @@ int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ */ ToutCnt++; if (ToutCnt > 1) { - /* Might be a problem when the driver event handler - * calls StopPort again. XXX. + /* + * If BMU stop doesn't terminate, we assume that + * we have a stable state and can reset the BMU, + * the Prefetch Unit, and RAM buffer now. */ - - /* Fatal Error, Loop aborted */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018, - SKERR_HWI_E018MSG); -#ifndef SK_DIAG - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); -#endif /* !SK_DIAG */ - return; + break; /* ===> leave do/while loop here */ } /* - * Cache incoherency workaround: Assume a start command + * Cache incoherency workaround: assume a start command * has been lost while sending the frame. */ ToutStart = SkOsGetTime(pAC); - if ((XsCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START); + if ((XsCsr & CsrStop) != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CsrStart); } - if ((XaCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START); + + if ((XaCsr & CsrStop) != 0) { + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CsrStart); + } + + /* + * After the previous operations the X(s|a)Csr does no + * longer contain the proper values + */ + XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff); + + if (HW_SYNC_TX_SUPPORTED(pAC)) { + XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); + } + else { + XsCsr = XaCsr; } } - /* * Because of the ASIC problem report entry from 21.08.1998 it is * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set. + * (valid for GENESIS only) */ - } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE || - (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); + } while (((XsCsr & CsrTest) != CsrIdle || + (XaCsr & CsrTest) != CsrIdle)); - /* Reset the MAC depending on the RstMode */ - if (RstMode == SK_SOFT_RST) { - SkMacSoftRst(pAC, IoC, Port); + if (pAC->GIni.GIAsfEnabled) { + + pPrt->PState = (RstMode == SK_SOFT_RST) ? SK_PRT_STOP : + SK_PRT_RESET; } else { - SkMacHardRst(pAC, IoC, Port); + /* Reset the MAC depending on the RstMode */ + if (RstMode == SK_SOFT_RST) { + + SkMacSoftRst(pAC, IoC, Port); + } + else { +#ifdef SK_DIAG + if (HW_FEATURE(pAC, HWF_WA_DEV_472) && Port == MAC_1 && + pAC->GIni.GP[MAC_2].PState == SK_PRT_RUN) { + + pAC->GIni.GP[MAC_1].PState = SK_PRT_RESET; + + /* set GPHY Control reset */ + SK_OUT8(IoC, MR_ADDR(MAC_1, GPHY_CTRL), (SK_U8)GPC_RST_SET); + } + else { + + SkMacHardRst(pAC, IoC, Port); + } +#else /* !SK_DIAG */ + SkMacHardRst(pAC, IoC, Port); +#endif /* !SK_DIAG */ + } } - /* Disable Force Sync bit and Enable Alloc bit */ + /* disable Force Sync bit and Enable Alloc bit */ SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); @@ -1592,17 +1610,35 @@ int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L); /* Perform a local reset of the port's Tx path */ + if (CHIP_ID_YUKON_2(pAC)) { + /* Reset the PCI FIFO of the async Tx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), + BMU_RST_SET | BMU_FIFO_RST); + + /* Reset the PCI FIFO of the sync Tx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), + BMU_RST_SET | BMU_FIFO_RST); + + /* Reset the Tx prefetch units */ + SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PXaQOff, PREF_UNIT_CTRL_REG), + PREF_UNIT_RST_SET); + SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PXsQOff, PREF_UNIT_CTRL_REG), + PREF_UNIT_RST_SET); + } + else { + /* Reset the PCI FIFO of the async Tx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET); + /* Reset the PCI FIFO of the sync Tx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET); + } - /* Reset the PCI FIFO of the async Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET); - /* Reset the PCI FIFO of the sync Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET); /* Reset the RAM Buffer async Tx queue */ SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET); /* Reset the RAM Buffer sync Tx queue */ SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET); /* Reset Tx MAC FIFO */ +#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* Note: MFF_RST_SET does NOT reset the XMAC ! */ SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET); @@ -1611,56 +1647,106 @@ int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ /* Link LED is switched off by the RLMT and the Diag itself */ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS); } - else { - /* Reset TX MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + /* do the reset only if ASF is not enabled */ + if (!pAC->GIni.GIAsfEnabled) { + /* Reset Tx MAC FIFO */ + SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); + } + + /* set Pause Off */ + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_PAUSE_OFF); } +#endif /* YUKON */ } if ((Dir & SK_STOP_RX) != 0) { - /* - * The RX Stop Command will not terminate if no buffers - * are queued in the RxD ring. But it will always reach - * the Idle state. Therefore we can use this feature to - * stop the transfer of received packets. - */ - /* stop the port's receive queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP); - i = 100; - do { + if (CHIP_ID_YUKON_2(pAC)) { /* - * Clear packet arbiter timeout to make sure - * this loop will terminate + * The RX Stop command will not work for Yukon-2 if the BMU does not + * reach the end of packet and since we can't make sure that we have + * incoming data, we must reset the BMU while it is not during a DMA + * transfer. Since it is possible that the RX path is still active, + * the RX RAM buffer will be stopped first, so any possible incoming + * data will not trigger a DMA. After the RAM buffer is stopped, the + * BMU is polled until any DMA in progress is ended and only then it + * will be reset. */ - SK_OUT16(IoC, B3_PA_CTRL, (Port == MAC_1) ? PA_CLR_TO_RX1 : - PA_CLR_TO_RX2); - DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff); + /* disable the RAM Buffer receive queue */ + SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_DIS_OP_MD); - /* timeout if i==0 (bug fix for #10748) */ - if (--i == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024, - SKERR_HWI_E024MSG); - break; + i = 0xffff; + while (--i) { + SK_IN8(IoC, RB_ADDR(pPrt->PRxQOff, Q_RX_RSL), &rsl); + SK_IN8(IoC, RB_ADDR(pPrt->PRxQOff, Q_RX_RL), &rl); + + if (rsl == rl) { + break; + } } + /* - * because of the ASIC problem report entry from 21.08.98 - * it is required to wait until CSR_STOP is reset and - * CSR_SV_IDLE is set. + * If the Rx side is blocked, the above loop cannot terminate. + * But, if there was any traffic it should be terminated, now. + * However, stop the Rx BMU and the Prefetch Unit ! */ - } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), + BMU_RST_SET | BMU_FIFO_RST); + /* reset the Rx prefetch unit */ + SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PRxQOff, PREF_UNIT_CTRL_REG), + PREF_UNIT_RST_SET); + } + else { + /* + * The RX Stop Command will not terminate if no buffers + * are queued in the RxD ring. But it will always reach + * the Idle state. Therefore we can use this feature to + * stop the transfer of received packets. + */ + /* stop the port's receive queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CsrStop); - /* The path data transfer activity is fully stopped now */ + i = 100; + do { +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + /* clear Rx packet arbiter timeout IRQ */ + SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ? + PA_CLR_TO_RX1 : PA_CLR_TO_RX2)); + } +#endif /* GENESIS */ - /* Perform a local reset of the port's Rx path */ + RxCsr = TestStopBit(pAC, IoC, pPrt->PRxQOff); + + /* timeout if i==0 (bug fix for #10748) */ + if (--i == 0) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024, + SKERR_HWI_E024MSG); + break; + } + /* + * Because of the ASIC problem report entry from 21.08.1998 it is + * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set. + * (valid for GENESIS only) + */ + } while ((RxCsr & CsrTest) != CsrIdle); + /* The path data transfer activity is fully stopped now */ + + /* Perform a local reset of the port's Rx path */ + /* Reset the PCI FIFO of the Rx queue */ + SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET); + } - /* Reset the PCI FIFO of the Rx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET); /* Reset the RAM Buffer receive queue */ SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET); /* Reset Rx MAC FIFO */ +#ifdef GENESIS if (pAC->GIni.GIGenesis) { SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET); @@ -1668,10 +1754,27 @@ int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ /* switch Rx LED off, stop the LED counter */ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon && !pAC->GIni.GIAsfEnabled) { /* Reset Rx MAC FIFO */ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); } + +#ifndef NDIS_MINIPORT_DRIVER /* temp. ifndef, remove after PM module rework*/ + /* WA for Dev. #4.169 */ + if ((pAC->GIni.GIChipId == CHIP_ID_YUKON || + pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) && + RstMode == SK_HARD_RST) { + /* set Link Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_SET); + + /* clear Link Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_CLR); + } +#endif /* !NDIS_MINIPORT */ +#endif /* YUKON */ } } /* SkGeStopPort */ @@ -1687,8 +1790,8 @@ int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ * nothing */ static void SkGeInit0( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { int i; SK_GEPORT *pPrt; @@ -1697,6 +1800,7 @@ SK_IOC IoC) /* IO context */ pPrt = &pAC->GIni.GP[i]; pPrt->PState = SK_PRT_RESET; + pPrt->PPortUsage = SK_RED_LINK; pPrt->PRxQOff = QOffTab[i].RxQOff; pPrt->PXsQOff = QOffTab[i].XsQOff; pPrt->PXaQOff = QOffTab[i].XaQOff; @@ -1708,32 +1812,47 @@ SK_IOC IoC) /* IO context */ pPrt->PPrevRx = 0; pPrt->PPrevFcs = 0; pPrt->PRxLim = SK_DEF_RX_WA_LIM; - pPrt->PLinkMode = SK_LMODE_AUTOFULL; - pPrt->PLinkSpeedCap = SK_LSPEED_CAP_1000MBPS; - pPrt->PLinkSpeed = SK_LSPEED_1000MBPS; - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_UNKNOWN; - pPrt->PLinkModeConf = SK_LMODE_AUTOSENSE; - pPrt->PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - pPrt->PLinkBroken = SK_TRUE; /* See WA code */ - pPrt->PLinkCap = (SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL | - SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL); - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlCap = SK_FLOW_MODE_SYM_OR_REM; - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; + pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS; + pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN; + pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE; + pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM; + pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL | + SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL); + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; + pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM; + pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; pPrt->PMSCap = 0; - pPrt->PMSMode = SK_MS_MODE_AUTO; - pPrt->PMSStatus = SK_MS_STAT_UNSET; + pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO; + pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET; + pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN; pPrt->PAutoNegFail = SK_FALSE; - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; pPrt->PHWLinkUp = SK_FALSE; + pPrt->PLinkBroken = SK_TRUE; /* See WA code */ + pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE; + pPrt->PMacColThres = TX_COL_DEF; + pPrt->PMacJamLen = TX_JAM_LEN_DEF; + pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF; + pPrt->PMacJamIpgData = TX_IPG_JAM_DEF; + pPrt->PMacBackOffLim = TX_BOF_LIM_DEF; + pPrt->PMacDataBlind = DATA_BLIND_DEF; + pPrt->PMacIpgData = IPG_DATA_DEF; + pPrt->PMacLimit4 = SK_FALSE; } - pAC->GIni.GIPortUsage = SK_RED_LINK; + pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value; + pAC->GIni.GIChipCap = 0; + + for (i = 0; i < 4; i++) { + pAC->GIni.HwF.Features[i]= 0x00000000; + pAC->GIni.HwF.OnMask[i] = 0x00000000; + pAC->GIni.HwF.OffMask[i] = 0x00000000; + } } /* SkGeInit0*/ #ifdef SK_PCI_RESET - /****************************************************************************** * * SkGePciReset() - Reset PCI interface @@ -1749,8 +1868,8 @@ SK_IOC IoC) /* IO context */ * 1: Power state could not be changed to 3. */ static int SkGePciReset( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { int i; SK_U16 PmCtlSts; @@ -1792,7 +1911,20 @@ SK_IOC IoC) /* IO context */ SkPciReadCfgWord(pAC, PCI_COMMAND, &PciCmd); SkPciReadCfgByte(pAC, PCI_CACHE_LSZ, &Cls); SkPciReadCfgDWord(pAC, PCI_BASE_1ST, &Bp1); - SkPciReadCfgDWord(pAC, PCI_BASE_2ND, &Bp2); + + /* + * Compute the location in PCI config space of BAR2 + * relativ to the location of BAR1 + */ + if ((Bp1 & PCI_MEM_TYP_MSK) == PCI_MEM64BIT) { + /* BAR1 is 64 bits wide */ + i = 8; + } + else { + i = 4; + } + + SkPciReadCfgDWord(pAC, PCI_BASE_1ST + i, &Bp2); SkPciReadCfgByte(pAC, PCI_LAT_TIM, &Lat); if (PciCmd != 0 || Cls != 0 || (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1 || @@ -1807,9 +1939,116 @@ SK_IOC IoC) /* IO context */ return(0); } /* SkGePciReset */ - #endif /* SK_PCI_RESET */ + +#ifndef SK_SLIM +/****************************************************************************** + * + * SkGeSetUpSupFeatures() - Collect Feature List for HW_FEATURE Macro + * + * Description: + * This function collects the available features and required + * deviation services of the Adapter and provides these + * information in the GIHwF struct. This information is used as + * default value and may be overritten by the driver using the + * SET_HW_FEATURE_MASK() macro in its Init0 phase. + * + * Notice: + * Using the On and Off mask: Never switch on the same bit in both + * masks simultaneously. However, if doing the Off mask will win. + * + * Returns: + * nothing + */ +static void SkGeSetUpSupFeatures( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + int i; + SK_U16 Word; + + switch (pAC->GIni.GIChipId) { + case CHIP_ID_YUKON_EC: + if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_A1) { + /* A0/A1 */ + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_42 | HWF_WA_DEV_46 | HWF_WA_DEV_43_418 | + HWF_WA_DEV_420 | HWF_WA_DEV_423 | + HWF_WA_DEV_424 | HWF_WA_DEV_425 | HWF_WA_DEV_427 | + HWF_WA_DEV_428 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 | + HWF_WA_DEV_4152| HWF_WA_DEV_4167; + } + else { + /* A2/A3 */ + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_424 | HWF_WA_DEV_425 | HWF_WA_DEV_427 | + HWF_WA_DEV_428 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 | + HWF_WA_DEV_4152| HWF_WA_DEV_4167; + } + break; + case CHIP_ID_YUKON_FE: + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_427 | HWF_WA_DEV_4109 | + HWF_WA_DEV_4152| HWF_WA_DEV_4167; + break; + case CHIP_ID_YUKON_XL: + switch (pAC->GIni.GIChipRev) { + case CHIP_REV_YU_XL_A0: /* still needed for Diag */ + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_427 | HWF_WA_DEV_463 | HWF_WA_DEV_472 | + HWF_WA_DEV_479 | HWF_WA_DEV_483 | HWF_WA_DEV_4115 | + HWF_WA_DEV_4152| HWF_WA_DEV_4167; + break; + + case CHIP_REV_YU_XL_A1: + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 | + HWF_WA_DEV_4115| HWF_WA_DEV_4152| HWF_WA_DEV_4167; + break; + + case CHIP_REV_YU_XL_A2: + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 | + HWF_WA_DEV_4115 | HWF_WA_DEV_4167; + break; + + case CHIP_REV_YU_XL_A3: + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 | + HWF_WA_DEV_4115; + break; + } + break; + case CHIP_ID_YUKON_EC_U: + if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A0) { + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109; + } + else if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A1) { + pAC->GIni.HwF.Features[HW_DEV_LIST] = + HWF_WA_DEV_427 | HWF_WA_DEV_4109 | HWF_WA_DEV_4185; + + /* check for Rev. A1 */ + SK_IN16(IoC, Q_ADDR(Q_XA1, Q_WM), &Word); + + if (Word == 0) { + pAC->GIni.HwF.Features[HW_DEV_LIST] |= + HWF_WA_DEV_4185CS | HWF_WA_DEV_4200; + } + } + break; + } + + for (i = 0; i < 4; i++) { + pAC->GIni.HwF.Features[i] = + (pAC->GIni.HwF.Features[i] | pAC->GIni.HwF.OnMask[i]) & + ~pAC->GIni.HwF.OffMask[i]; + } +} /* SkGeSetUpSupFeatures */ +#endif /* !SK_SLIM */ + + /****************************************************************************** * * SkGeInit1() - Level 1 Initialization @@ -1832,75 +2071,253 @@ SK_IOC IoC) /* IO context */ * 6: HW self test failed */ static int SkGeInit1( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { SK_U8 Byte; SK_U16 Word; - SK_U16 CtrlStat; - SK_U32 FlashAddr; + SK_U32 CtrlStat; + SK_U32 VauxAvail; + SK_U32 DWord; + SK_U32 Our1; + SK_U32 PowerDownBit; + SK_BOOL FiberType; + SK_GEPORT *pPrt; int RetVal; - int i; + int i, j; RetVal = 0; - /* save CLK_RUN bits (YUKON-Lite) */ - SK_IN16(IoC, B0_CTST, &CtrlStat); + /* save CLK_RUN & ASF_ENABLE bits (YUKON-Lite, YUKON-EC) */ + SK_IN32(IoC, B0_CTST, &CtrlStat); #ifdef SK_PCI_RESET (void)SkGePciReset(pAC, IoC); #endif /* SK_PCI_RESET */ - /* do the SW-reset */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); - /* release the SW-reset */ + /* Important: SW-reset has to be cleared here, to ensure + * the CHIP_ID can be read IO-mapped based, too - + * remember the RAP register can only be written if + * SW-reset is cleared. + */ SK_OUT8(IoC, B0_CTST, CS_RST_CLR); + /* read Chip Identification Number */ + SK_IN8(IoC, B2_CHIP_ID, &Byte); + pAC->GIni.GIChipId = Byte; + + pAC->GIni.GIAsfEnabled = SK_FALSE; + + /* ASF support only for Yukon-2 */ + if ((pAC->GIni.GIChipId >= CHIP_ID_YUKON_XL) && + (pAC->GIni.GIChipId <= CHIP_ID_YUKON_EC)) { +#ifdef SK_ASF + if ((CtrlStat & Y2_ASF_ENABLE) != 0) { + /* do the SW-reset only if ASF is not enabled */ + pAC->GIni.GIAsfEnabled = SK_TRUE; + } +#else /* !SK_ASF */ + + SK_IN8(IoC, B28_Y2_ASF_STAT_CMD, &Byte); + + pAC->GIni.GIAsfRunning = Byte & Y2_ASF_RUNNING; + + /* put ASF system in reset state */ + SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)Y2_ASF_RESET); + + /* disable ASF Unit */ + SK_OUT16(IoC, B0_CTST, Y2_ASF_DISABLE); +#endif /* !SK_ASF */ + } + + if (!pAC->GIni.GIAsfEnabled) { + /* Yukon-2: required for Diag and Power Management */ + /* set the SW-reset */ + SK_OUT8(IoC, B0_CTST, CS_RST_SET); + + /* release the SW-reset */ + SK_OUT8(IoC, B0_CTST, CS_RST_CLR); + } + + /* enable Config Write */ + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + /* reset all error bits in the PCI STATUS register */ /* * Note: PCI Cfg cycles cannot be used, because they are not * available on some platforms after 'boot time'. */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); + SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), Word | (SK_U16)PCI_ERRBITS); /* release Master Reset */ SK_OUT8(IoC, B0_CTST, CS_MRST_CLR); #ifdef CLK_RUN CtrlStat |= CS_CLK_RUN_ENA; -#endif /* CLK_RUN */ /* restore CLK_RUN bits */ - SK_OUT16(IoC, B0_CTST, CtrlStat & - (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)); + SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat & + (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA))); +#endif /* CLK_RUN */ - /* read Chip Identification Number */ - SK_IN8(IoC, B2_CHIP_ID, &Byte); - pAC->GIni.GIChipId = Byte; + if ((pAC->GIni.GIChipId >= CHIP_ID_YUKON_XL) && + (pAC->GIni.GIChipId <= CHIP_ID_YUKON_FE)) { - /* read number of MACs */ - SK_IN8(IoC, B2_MAC_CFG, &Byte); - pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2; + pAC->GIni.GIYukon2 = SK_TRUE; + pAC->GIni.GIValIrqMask = Y2_IS_ALL_MSK; + pAC->GIni.GIValHwIrqMask = Y2_HWE_ALL_MSK; + + VauxAvail = Y2_VAUX_AVAIL; + + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_STATUS), &DWord); + + if ((DWord & PCI_OS_PCI_X) != 0) { +#ifndef SK_SLIM + /* this is a PCI / PCI-X bus */ + if ((DWord & PCI_OS_PCIX) != 0) { + /* this is a PCI-X bus */ + pAC->GIni.GIPciBus = SK_PCIX_BUS; + + /* PCI-X is always 64-bit wide */ + pAC->GIni.GIPciSlot64 = SK_TRUE; + + pAC->GIni.GIPciMode = (SK_U8)(PCI_OS_SPEED(DWord)); + } + else { + /* this is a conventional PCI bus */ + pAC->GIni.GIPciBus = SK_PCI_BUS; + + SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_2), &Word); + + /* check if 64-bit width is used */ + pAC->GIni.GIPciSlot64 = (SK_BOOL) + (((DWord & PCI_OS_PCI64B) != 0) && + ((Word & PCI_USEDATA64) != 0)); + + /* check if 66 MHz PCI Clock is active */ + pAC->GIni.GIPciClock66 = (SK_BOOL)((DWord & PCI_OS_PCI66M) != 0); + } +#endif /* !SK_SLIM */ + } + else { + /* this is a PEX bus */ + pAC->GIni.GIPciBus = SK_PEX_BUS; + + /* clear any PEX errors */ + SK_OUT32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), 0xffffffffUL); + + SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord); + + if ((DWord & PEX_RX_OV) != 0) { + /* Dev #4.205 occured */ + pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP; + pAC->GIni.GIValIrqMask &= ~Y2_IS_HW_ERR; + } + + SK_IN16(IoC, PCI_C(pAC, PEX_LNK_STAT), &Word); + + pAC->GIni.GIPexWidth = (SK_U8)((Word & PEX_LS_LINK_WI_MSK) >> 4); + } + /* + * Yukon-2 chips family has a different way of providing + * the number of MACs available + */ + pAC->GIni.GIMacsFound = 1; + + /* get HW Resources */ + SK_IN8(IoC, B2_Y2_HW_RES, &Byte); + + if (CHIP_ID_YUKON_2(pAC)) { + /* + * OEM config value is overwritten and should not + * be used for Yukon-2 + */ + pAC->GIni.GILedBlinkCtrl |= SK_ACT_LED_BLINK; + +#ifndef SK_SLIM + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) { + /* LED Configuration is stored in GPIO */ + SK_IN8(IoC, B2_GP_IO, &Byte); + + if (CFG_LED_MODE(Byte) == CFG_LED_LINK_MUX_P60) { + + pAC->GIni.GILedBlinkCtrl |= SK_LED_LINK_MUX_P60; + } + } +#endif /* !SK_SLIM */ + + if (CFG_LED_MODE(Byte) == CFG_LED_DUAL_ACT_LNK) { + + pAC->GIni.GILedBlinkCtrl |= SK_DUAL_LED_ACT_LNK; + } + } + + /* save HW Resources / Application Information */ + pAC->GIni.GIHwResInfo = Byte; + + if ((Byte & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { + + SK_IN8(IoC, B2_Y2_CLK_GATE, &Byte); + + if (!(Byte & Y2_STATUS_LNK2_INAC)) { + /* Link 2 activ */ + pAC->GIni.GIMacsFound++; + } + } + +#ifdef VCPU + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) { + /* temporary WA for reported number of links */ + pAC->GIni.GIMacsFound = 2; + } +#endif /* VCPU */ + + /* read Chip Revision */ + SK_IN8(IoC, B2_MAC_CFG, &Byte); + + pAC->GIni.GIChipCap = Byte & 0x0f; + } + else { + pAC->GIni.GIYukon2 = SK_FALSE; + pAC->GIni.GIValIrqMask = IS_ALL_MSK; + pAC->GIni.GIValHwIrqMask = 0; /* not activated */ + + VauxAvail = CS_VAUX_AVAIL; + + /* read number of MACs and Chip Revision */ + SK_IN8(IoC, B2_MAC_CFG, &Byte); + + pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2; + } /* get Chip Revision Number */ pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4); - /* get diff. PCI parameters */ - SK_IN16(IoC, B0_CTST, &CtrlStat); +#ifndef SK_DIAG + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL && + pAC->GIni.GIChipRev == CHIP_REV_YU_XL_A0) { + /* Yukon-2 Chip Rev. A0 */ + return(6); + } +#endif /* !SK_DIAG */ /* read the adapters RAM size */ SK_IN8(IoC, B2_E_0, &Byte); + pAC->GIni.GIGenesis = SK_FALSE; + pAC->GIni.GIYukon = SK_FALSE; + pAC->GIni.GIYukonLite = SK_FALSE; + pAC->GIni.GIVauxAvail = SK_FALSE; + +#ifdef GENESIS if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { pAC->GIni.GIGenesis = SK_TRUE; - if (Byte == 3) { + if (Byte == (SK_U8)3) { /* special case: 4 x 64k x 36, offset = 0x80000 */ pAC->GIni.GIRamSize = 1024; pAC->GIni.GIRamOffs = (SK_U32)512 * 1024; @@ -1909,161 +2326,385 @@ SK_IOC IoC) /* IO context */ pAC->GIni.GIRamSize = (int)Byte * 512; pAC->GIni.GIRamOffs = 0; } - /* all GE adapters work with 53.125 MHz host clock */ + /* all GENESIS adapters work with 53.125 MHz host clock */ pAC->GIni.GIHstClkFact = SK_FACT_53; /* set Descr. Poll Timer Init Value to 250 ms */ pAC->GIni.GIPollTimerVal = SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100; } - else { - pAC->GIni.GIGenesis = SK_FALSE; +#endif /* GENESIS */ -#ifndef VCPU - pAC->GIni.GIRamSize = (Byte == 0) ? 128 : (int)Byte * 4; -#else - pAC->GIni.GIRamSize = 128; -#endif +#ifdef YUKON + if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) { + + pAC->GIni.GIYukon = SK_TRUE; + + pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4; + +#ifndef SK_SLIM pAC->GIni.GIRamOffs = 0; - /* WA for chip Rev. A */ - pAC->GIni.GIWolOffs = (pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0; + /* WA for Yukon chip Rev. A */ + pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON && + pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0; /* get PM Capabilities of PCI config space */ - SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word); + SK_IN16(IoC, PCI_C(pAC, PCI_PM_CAP_REG), &Word); /* check if VAUX is available */ - if (((CtrlStat & CS_VAUX_AVAIL) != 0) && + if (((CtrlStat & VauxAvail) != 0) && /* check also if PME from D3cold is set */ ((Word & PCI_PME_D3C_SUP) != 0)) { /* set entry in GE init struct */ pAC->GIni.GIVauxAvail = SK_TRUE; } +#endif /* !SK_SLIM */ - /* save Flash-Address Register */ - SK_IN32(IoC, B2_FAR, &FlashAddr); + if (!CHIP_ID_YUKON_2(pAC)) { - /* test Flash-Address Register */ - SK_OUT8(IoC, B2_FAR + 3, 0xff); - SK_IN8(IoC, B2_FAR + 3, &Byte); + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) { + /* this is Rev. A1 */ + pAC->GIni.GIYukonLite = SK_TRUE; + } +#ifndef SK_SLIM + else { + /* save Flash-Address Register */ + SK_IN32(IoC, B2_FAR, &DWord); - pAC->GIni.GIYukonLite = (SK_BOOL)(Byte != 0); + /* test Flash-Address Register */ + SK_OUT8(IoC, B2_FAR + 3, 0xff); + SK_IN8(IoC, B2_FAR + 3, &Byte); - /* restore Flash-Address Register */ - SK_OUT32(IoC, B2_FAR, FlashAddr); + if (Byte != 0) { + /* this is Rev. A0 */ + pAC->GIni.GIYukonLite = SK_TRUE; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - /* set GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET); - - /* clear GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR); + /* restore Flash-Address Register */ + SK_OUT32(IoC, B2_FAR, DWord); + } + } +#endif /* !SK_SLIM */ } - /* all YU chips work with 78.125 MHz host clock */ - pAC->GIni.GIHstClkFact = SK_FACT_78; + else { + /* Check for CLS = 0 (dev. #4.55) */ + if (pAC->GIni.GIPciBus != SK_PEX_BUS) { + /* PCI and PCI-X */ + SK_IN8(IoC, PCI_C(pAC, PCI_CACHE_LSZ), &Byte); - pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */ + if (Byte == 0) { + /* set CLS to 2 if configured to 0 */ + SK_OUT8(IoC, PCI_C(pAC, PCI_CACHE_LSZ), 2); + } + + if (pAC->GIni.GIPciBus == SK_PCIX_BUS) { + /* set Cache Line Size opt. */ + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord); + DWord |= PCI_CLS_OPT; + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord); + } + } + } + + /* switch power to VCC (WA for VAUX problem) */ + SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA | + PC_VAUX_OFF | PC_VCC_ON)); + + Byte = 0; + + if (CHIP_ID_YUKON_2(pAC)) { + switch (pAC->GIni.GIChipId) { + /* PEX adapters work with different host clock */ + case CHIP_ID_YUKON_EC: + case CHIP_ID_YUKON_EC_U: + /* Yukon-EC works with 125 MHz host clock */ + pAC->GIni.GIHstClkFact = SK_FACT_125; + break; + case CHIP_ID_YUKON_FE: + /* Yukon-FE works with 100 MHz host clock */ + pAC->GIni.GIHstClkFact = SK_FACT_100; + break; + case CHIP_ID_YUKON_XL: + /* all Yukon-2 adapters work with 156 MHz host clock */ + pAC->GIni.GIHstClkFact = 2 * SK_FACT_78; + + if (pAC->GIni.GIChipRev > CHIP_REV_YU_XL_A1) { + /* enable bits are inverted */ + Byte = (SK_U8)(Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | + Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | + Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); + } + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E006, + SKERR_HWI_E006MSG); + } + + pAC->GIni.GIPollTimerVal = + SK_DPOLL_DEF_Y2 * (SK_U32)pAC->GIni.GIHstClkFact / 100; + + /* set power down bit */ + PowerDownBit = PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD; + + /* disable Core Clock Division, set Clock Select to 0 (Yukon-2) */ + SK_OUT32(IoC, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); + + /* enable MAC/PHY, PCI and Core Clock for both Links */ + SK_OUT8(IoC, B2_Y2_CLK_GATE, Byte); + } + else { + /* YUKON adapters work with 78 MHz host clock */ + pAC->GIni.GIHstClkFact = SK_FACT_78; + + pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */ + + /* read the Interrupt source */ + SK_IN32(IoC, B0_ISRC, &DWord); + + if ((DWord & IS_HW_ERR) != 0) { + /* read the HW Error Interrupt source */ + SK_IN32(IoC, B0_HWE_ISRC, &DWord); + + if ((DWord & IS_IRQ_SENSOR) != 0) { + /* disable HW Error IRQ */ + pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; + } + } + /* set power down bit */ + PowerDownBit = PCI_PHY_COMA; + } + + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Our1); + + Our1 &= ~PowerDownBit; + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL && + pAC->GIni.GIChipRev > CHIP_REV_YU_XL_A1) { + /* deassert Low Power for 1st PHY */ + Our1 |= PCI_Y2_PHY1_COMA; + + if (pAC->GIni.GIMacsFound > 1) { + /* deassert Low Power for 2nd PHY */ + Our1 |= PCI_Y2_PHY2_COMA; + } + } + else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) { + /* enable HW WOL */ + SK_OUT16(IoC, B0_CTST, (SK_U16)Y2_HW_WOL_ON); + + /* enable all clocks */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_3), 0); + + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord); + + DWord &= P_ASPM_CONTROL_MSK; + /* set all bits to 0 except bits 15..12 */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord); + + /* set to default value */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), 0); + } + + /* release PHY from PowerDown/COMA Mode */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), Our1); + + if (!pAC->GIni.GIAsfEnabled) { + + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + /* set Link Control reset */ + SK_OUT8(IoC, MR_ADDR(i, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_SET); + + /* clear Link Control reset */ + SK_OUT8(IoC, MR_ADDR(i, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_CLR); + } + } + } +#endif /* YUKON */ + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + +#ifndef SK_SLIM + if (!CHIP_ID_YUKON_2(pAC)) { + /* this is a conventional PCI bus */ + pAC->GIni.GIPciBus = SK_PCI_BUS; + + /* check if 64-bit PCI Slot is present */ + pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0); + + /* check if 66 MHz PCI Clock is active */ + pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0); } - /* check if 64-bit PCI Slot is present */ - pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0); - - /* check if 66 MHz PCI Clock is active */ - pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0); - /* read PCI HW Revision Id. */ - SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte); + SK_IN8(IoC, PCI_C(pAC, PCI_REV_ID), &Byte); pAC->GIni.GIPciHwRev = Byte; + /* read connector type */ + SK_IN8(IoC, B2_CONN_TYP, &pAC->GIni.GIConTyp); +#endif /* !SK_SLIM */ + /* read the PMD type */ SK_IN8(IoC, B2_PMD_TYP, &Byte); - pAC->GIni.GICopperType = (SK_U8)(Byte == 'T'); - /* read the PHY type */ + pAC->GIni.GIPmdTyp = Byte; + + FiberType = (Byte == 'L' || Byte == 'S' || Byte == 'P'); + + pAC->GIni.GICopperType = (SK_BOOL)(Byte == 'T' || Byte == '1' || + (pAC->GIni.GIYukon2 && !FiberType)); + + /* read the PHY type (Yukon and Genesis) */ SK_IN8(IoC, B2_E_1, &Byte); Byte &= 0x0f; /* the PHY type is stored in the lower nibble */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + pPrt = &pAC->GIni.GP[i]; + + /* get the MAC addresses */ + for (j = 0; j < 3; j++) { + SK_IN16(IoC, B2_MAC_1 + i * 8 + j * 2, &pPrt->PMacAddr[j]); + } + +#ifdef GENESIS if (pAC->GIni.GIGenesis) { switch (Byte) { case SK_PHY_XMAC: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC; + pPrt->PhyAddr = PHY_ADDR_XMAC; break; case SK_PHY_BCOM: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM; - pAC->GIni.GP[i].PMSCap = - SK_MS_CAP_AUTO | SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE; + pPrt->PhyAddr = PHY_ADDR_BCOM; + pPrt->PMSCap = (SK_U8)(SK_MS_CAP_AUTO | + SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE); break; #ifdef OTHER_PHY case SK_PHY_LONE: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE; + pPrt->PhyAddr = PHY_ADDR_LONE; break; case SK_PHY_NAT: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT; + pPrt->PhyAddr = PHY_ADDR_NAT; break; #endif /* OTHER_PHY */ default: /* ERROR: unexpected PHY type detected */ RetVal = 5; - break; } } - else { - if (Byte == 0) { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + + if (((Byte < (SK_U8)SK_PHY_MARV_COPPER) || pAC->GIni.GIYukon2) && + !FiberType) { /* if this field is not initialized */ - Byte = SK_PHY_MARV_COPPER; + Byte = (SK_U8)SK_PHY_MARV_COPPER; + pAC->GIni.GICopperType = SK_TRUE; } - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV; + + pPrt->PhyAddr = PHY_ADDR_MARV; if (pAC->GIni.GICopperType) { - pAC->GIni.GP[i].PLinkSpeedCap = SK_LSPEED_CAP_AUTO | - SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS | - SK_LSPEED_CAP_1000MBPS; - pAC->GIni.GP[i].PLinkSpeed = SK_LSPEED_AUTO; - pAC->GIni.GP[i].PMSCap = - SK_MS_CAP_AUTO | SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE; + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE || + (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC && + pAC->GIni.GIChipCap == 2)) { + + pPrt->PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_100MBPS | + SK_LSPEED_CAP_10MBPS); + + pAC->GIni.GIRamSize = 4; + } + else { + pPrt->PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_1000MBPS | + SK_LSPEED_CAP_100MBPS | SK_LSPEED_CAP_10MBPS | + SK_LSPEED_CAP_AUTO); + } + + pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_AUTO; + + pPrt->PMSCap = (SK_U8)(SK_MS_CAP_AUTO | + SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE); } else { - Byte = SK_PHY_MARV_FIBER; + Byte = (SK_U8)SK_PHY_MARV_FIBER; } } - pAC->GIni.GP[i].PhyType = Byte; + /* clear TWSI IRQ */ + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); + +#endif /* YUKON */ + + pPrt->PhyType = (int)Byte; SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("PHY type: %d PHY addr: %04x\n", Byte, - pAC->GIni.GP[i].PhyAddr)); + ("PHY type: %d PHY addr: %04x\n", + Byte, pPrt->PhyAddr)); } - /* get Mac Type & set function pointers dependent on */ + /* get MAC Type & set function pointers dependent on */ +#ifdef GENESIS if (pAC->GIni.GIGenesis) { + pAC->GIni.GIMacType = SK_MAC_XMAC; pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats; pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic; pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter; pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus; +#ifdef SK_DIAG + pAC->GIni.GIFunc.pFnMacPhyRead = SkXmPhyRead; + pAC->GIni.GIFunc.pFnMacPhyWrite = SkXmPhyWrite; +#else /* SK_DIAG */ + pAC->GIni.GIFunc.pSkGeSirqIsr = SkGeYuSirqIsr; +#endif /* !SK_DIAG */ } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + +#ifndef SK_SLIM pAC->GIni.GIMacType = SK_MAC_GMAC; pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats; pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic; pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter; pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus; +#endif /* !SK_SLIM */ + +#ifdef SK_DIAG + pAC->GIni.GIFunc.pFnMacPhyRead = SkGmPhyRead; + pAC->GIni.GIFunc.pFnMacPhyWrite = SkGmPhyWrite; +#else /* SK_DIAG */ + if (CHIP_ID_YUKON_2(pAC)) { + pAC->GIni.GIFunc.pSkGeSirqIsr = SkYuk2SirqIsr; + } + else { + pAC->GIni.GIFunc.pSkGeSirqIsr = SkGeYuSirqIsr; + } +#endif /* !SK_DIAG */ #ifdef SPECIAL_HANDLING if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { /* check HW self test result */ SK_IN8(IoC, B2_E_3, &Byte); - if ((Byte & B2_E3_RES_MASK) != 0) { + if (Byte & B2_E3_RES_MASK) { RetVal = 6; } } #endif } +#endif /* YUKON */ + +#ifndef SK_SLIM + + SkGeSetUpSupFeatures(pAC, IoC); + +#endif /* !SK_SLIM */ + return(RetVal); } /* SkGeInit1 */ @@ -2084,10 +2725,18 @@ SK_IOC IoC) /* IO context */ * nothing */ static void SkGeInit2( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { +#ifdef YUKON + SK_U16 Word; +#if (!defined(SK_SLIM) && !defined(SK_DIAG)) + SK_EVPARA Para; +#endif /* !SK_SLIM && !SK_DIAG */ +#endif /* YUKON */ +#ifdef GENESIS SK_U32 DWord; +#endif /* GENESIS */ int i; /* start the Descriptor Poll Timer */ @@ -2101,6 +2750,7 @@ SK_IOC IoC) /* IO context */ SK_OUT8(IoC, B28_DPT_CTRL, DPT_START); } +#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* start the Blink Source Counter */ DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; @@ -2116,10 +2766,14 @@ SK_IOC IoC) /* IO context */ SkGeInitPktArb(pAC, IoC); } - else { +#endif /* GENESIS */ + +#ifdef xSK_DIAG + if (pAC->GIni.GIYukon) { /* start Time Stamp Timer */ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START); } +#endif /* SK_DIAG */ /* enable the Tx Arbiters */ for (i = 0; i < pAC->GIni.GIMacsFound; i++) { @@ -2129,8 +2783,62 @@ SK_IOC IoC) /* IO context */ /* enable the RAM Interface Arbiter */ SkGeInitRamIface(pAC, IoC); +#ifdef YUKON + if (CHIP_ID_YUKON_2(pAC)) { + + if (pAC->GIni.GIPciBus == SK_PEX_BUS) { + + SK_IN16(IoC, PCI_C(pAC, PEX_DEV_CTRL), &Word); + + /* change Max. Read Request Size to 2048 bytes */ + Word &= ~PEX_DC_MAX_RRS_MSK; + Word |= PEX_DC_MAX_RD_RQ_SIZE(4); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + + SK_OUT16(IoC, PCI_C(pAC, PEX_DEV_CTRL), Word); + +#ifdef REPLAY_TIMER + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) { + /* PEX Ack Reply Timeout to 40 us */ + SK_OUT16(IoC, PCI_C(pAC, PEX_ACK_RPLY_TOX1), 0x2710); + } +#endif + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + +#if (!defined(SK_SLIM) && !defined(SK_DIAG)) + SK_IN16(IoC, PCI_C(pAC, PEX_LNK_CAP), &Word); + + Word = (Word & PEX_CAP_MAX_WI_MSK) >> 4; + + /* compare PEX Negotiated Link Width against max. capabil */ + if (pAC->GIni.GIPexWidth != (SK_U8)Word) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("PEX negotiated Link width is: %d, exp.: %d\n", + pAC->GIni.GIPexWidth, Word)); + +#ifndef NDIS_MINIPORT_DRIVER + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E026, + SKERR_HWI_E026MSG); +#endif + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PEX_LINK_WIDTH, Para); + } +#endif /* !SK_SLIM && !SK_DIAG */ + } + + /* + * Writing the HW Error Mask Reg. will not generate an IRQ + * as long as the B0_IMSK is not set by the driver. + */ + SK_OUT32(IoC, B0_HWE_IMSK, pAC->GIni.GIValHwIrqMask); + } +#endif /* YUKON */ } /* SkGeInit2 */ + /****************************************************************************** * * SkGeInit() - Initialize the GE Adapter with the specified level. @@ -2152,7 +2860,7 @@ SK_IOC IoC) /* IO context */ * if Number of MACs > SK_MAX_MACS * * After returning from Level 0 the adapter - * may be accessed with IO operations. + * may be accessed with I/O operations. * * Level 2: start the Blink Source Counter * @@ -2161,14 +2869,14 @@ SK_IOC IoC) /* IO context */ * 1: Number of MACs exceeds SK_MAX_MACS (after level 1) * 2: Adapter not present or not accessible * 3: Illegal initialization level - * 4: Initialization Level 1 Call missing + * 4: Initialization level 1 call missing * 5: Unexpected PHY type detected * 6: HW self test failed */ int SkGeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Level) /* initialization level */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Level) /* Initialization Level */ { int RetVal; /* return value */ SK_U32 DWord; @@ -2192,20 +2900,22 @@ int Level) /* initialization level */ } /* check if the adapter seems to be accessible */ - SK_OUT32(IoC, B2_IRQM_INI, 0x11335577L); + SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL); SK_IN32(IoC, B2_IRQM_INI, &DWord); SK_OUT32(IoC, B2_IRQM_INI, 0L); - if (DWord != 0x11335577L) { + if (DWord != SK_TEST_VAL) { RetVal = 2; break; } +#ifdef DEBUG /* check if the number of GIMacsFound matches SK_MAX_MACS */ if (pAC->GIni.GIMacsFound > SK_MAX_MACS) { RetVal = 1; break; } +#endif /* DEBUG */ /* Level 1 successfully passed */ pAC->GIni.GILevel = SK_INIT_IO; @@ -2220,6 +2930,7 @@ int Level) /* initialization level */ RetVal = 4; break; } + SkGeInit2(pAC, IoC); /* Level 2 successfully passed */ @@ -2248,39 +2959,83 @@ int Level) /* initialization level */ * nothing */ void SkGeDeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ { int i; SK_U16 Word; -#ifndef VCPU +#ifdef SK_PHY_LP_MODE_DEEP_SLEEP + SK_U16 PmCtlSts; +#endif + +#if (!defined(SK_SLIM) && !defined(VCPU)) /* ensure I2C is ready */ SkI2cWaitIrq(pAC, IoC); #endif - /* stop all current transfer activity */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - if (pAC->GIni.GP[i].PState != SK_PRT_STOP && - pAC->GIni.GP[i].PState != SK_PRT_RESET) { +#ifdef SK_PHY_LP_MODE_DEEP_SLEEP + /* + * for power saving purposes within mobile environments + * we set the PHY to coma mode. + */ +#ifdef XXX + if (pAC->GIni.GIVauxAvail) { + /* switch power to VAUX */ + SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA | + PC_VAUX_ON | PC_VCC_OFF)); + } +#endif /* XXX */ - SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST); + if (CHIP_ID_YUKON_2(pAC) && /* pAC->GIni.GIMacsFound == 1 && */ + !pAC->GIni.GIAsfEnabled +#ifdef XXX + || (pAC->GIni.GIYukonLite && pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) +#endif /* XXX */ + ) { + + /* flag for SkGmEnterLowPowerMode() that the call was from here */ + pAC->GIni.GILevel = SK_INIT_IO; + + /* for all ports switch PHY to coma mode */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + (void)SkGmEnterLowPowerMode(pAC, IoC, i, PHY_PM_DEEP_SLEEP); + } + } +#else /* !SK_PHY_LP_MODE_DEEP_SLEEP */ + + if (!pAC->GIni.GIAsfEnabled) { + /* stop all current transfer activity */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + if (pAC->GIni.GP[i].PState != SK_PRT_STOP && + pAC->GIni.GP[i].PState != SK_PRT_RESET) { + + SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST); + } } } - /* Reset all bits in the PCI STATUS register */ + /* reset all bits in the PCI STATUS register */ /* * Note: PCI Cfg cycles cannot be used, because they are not * available on some platforms after 'boot time'. */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); + SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word); SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); + + SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), Word | (SK_U16)PCI_ERRBITS); + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - /* do the reset, all LEDs are switched off now */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); + if (!pAC->GIni.GIAsfEnabled) { + /* set the SW-reset */ + SK_OUT8(IoC, B0_CTST, CS_RST_SET); + } +#endif /* !SK_PHY_LP_MODE_DEEP_SLEEP */ + + pAC->GIni.GILevel = SK_INIT_DATA; } /* SkGeDeInit */ @@ -2313,8 +3068,8 @@ SK_IOC IoC) /* IO context */ * 2: The port has to be stopped before it can be initialized again. */ int SkGeInitPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port to configure */ { SK_GEPORT *pPrt; @@ -2326,17 +3081,18 @@ int Port) /* Port to configure */ return(1); } - if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) { + if (pPrt->PState >= SK_PRT_INIT) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG); return(2); } /* configuration ok, initialize the Port now */ +#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* initialize Rx, Tx and Link LED */ /* - * If 1000BT Phy needs LED initialization than swap + * If 1000BT PHY needs LED initialization than swap * LED and XMAC initialization order */ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); @@ -2345,10 +3101,14 @@ int Port) /* Port to configure */ SkXmInitMac(pAC, IoC, Port); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { SkGmInitMac(pAC, IoC, Port); } +#endif /* YUKON */ /* do NOT initialize the Link Sync Counter */ @@ -2369,4 +3129,214 @@ int Port) /* Port to configure */ return(0); } /* SkGeInitPort */ -#endif /* CONFIG_SK98 */ + +#if (defined(YUK2) && !defined(SK_SLIM)) +/****************************************************************************** + * + * SkGeRamWrite() - Writes One quadword to RAM + * + * Returns: + * 0 + */ +static void SkGeRamWrite( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Addr, /* Address to be written to (in quadwords) */ +SK_U32 LowDword, /* Lower Dword to be written */ +SK_U32 HighDword, /* Upper Dword to be written */ +int Port) /* Select RAM buffer (Yukon-2 has 2 RAM buffers) */ +{ + SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_ADDR), Addr); + + /* Write Access is initiated by writing the upper Dword */ + SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_DATA_LO), LowDword); + SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_DATA_HI), HighDword); +} + +/****************************************************************************** + * + * SkYuk2RestartRxBmu() - Restart Receive BMU on Yukon-2 + * + * return: + * 0 o.k. + * 1 timeout + */ +int SkYuk2RestartRxBmu( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U16 Word; + SK_U16 MacCtrl; + SK_U16 RxCtrl; + SK_U16 FlushMask; + SK_U16 FlushTrsh; + SK_U32 RamAdr; + SK_U32 StartTime; + SK_U32 CurrTime; + SK_U32 Delta; + SK_U32 TimeOut; + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + int Rtv; + SK_U16 WordBuffer[4]; /* Buffer to handle MAC address */ + + Rtv = 0; + + pPrt = &pAC->GIni.GP[Port]; + +/* + 1. save Rx MAC FIFO Flush Mask and Rx MAC FIFO Flush Threshold + 2. save GMAC Rx Control Register + 3. re-initialize MAC Rx FIFO, Rx RAM Buffer Queue, PCI Rx FIFO, + Rx BMU and Rx Prefetch Unit of the link. + 4. set Rx MAC FIFO Flush Mask to 0xffff + set Rx MAC FIFO Flush Threshold to a high value, e.g. 0x20 + 5. set GMAC to loopback mode and switch GMAC back to Rx/Tx enable + 6. clear Rx/Tx Frame Complete IRQ in Rx/T MAC FIFO Control Register + 7. send one packet with a size of 64bytes (size below flush threshold) + from TXA RAM Buffer Queue to set the rx_sop flop: + - set TxAQ Write Pointer to (packet size in qwords + 2) + - set TxAQ Level to (packet size in qwords + 2) + - write Internal Status Word 1 and 2 to TxAQ RAM Buffer Queue QWord 0,1 + according to figure 61 on page 330 of Yukon-2 Spec. + - write MAC header with Destination Address = own MAC address to + TxAQ RAM Buffer Queue QWords 2 and 3 + - set TxAQ Packet Counter to 1 -> packet is transmitted immediately + 8. poll GMAC IRQ Source Register for IRQ Rx/Tx Frame Complete + 9. restore GMAC Rx Control Register +10. restore Rx MAC FIFO Flush Mask and Rx MAC FIFO Flush Threshold +11. set GMAC back to GMII mode +*/ + + /* save Rx GMAC FIFO Flush Mask */ + SK_IN16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), &FlushMask); + + /* save Rx GMAC FIFO Flush Threshold */ + SK_IN16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), &FlushTrsh); + + /* save GMAC Rx Control Register */ + GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl); + + /* configure the GMAC FIFOs */ + SkGeInitMacFifo(pAC, IoC, Port); + + SkGeInitRamBufs(pAC, IoC, Port); + + SkGeInitBmu(pAC, IoC, Port); + + /* configure Rx GMAC FIFO */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), GMF_RX_CTRL_DEF); + + /* set Rx GMAC FIFO Flush Mask */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), 0xffff); + + /* set Rx GMAC FIFO Flush Threshold */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), 0x20); + + /* set to promiscuous mode */ + Word = RxCtrl & ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); + + /* set GMAC Rx Control Register */ + GM_OUT16(IoC, Port, GM_RX_CTRL, Word); + + /* get General Purpose Control */ + GM_IN16(IoC, Port, GM_GP_CTRL, &MacCtrl); + + /* enable MAC Loopback Mode*/ + GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl | GM_GPCR_LOOP_ENA); + + /* enable MAC Loopback Mode and Rx/Tx */ + GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl | GM_GPCR_LOOP_ENA | + GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); + + /* clear GMAC IRQ Rx Frame Complete */ + SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FC); + + /* clear GMAC IRQ Tx Frame Complete */ + SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FC); + + /* send one packet with a size of 64bytes from RAM buffer*/ + + RamAdr = pPrt->PXaQRamStart / 8; + + SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_WP), RamAdr + 10); + + SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_LEV), 10); + + /* write 1st status quad word (packet end address in RAM, packet length */ + SkGeRamWrite(pAC, IoC, RamAdr, (RamAdr + 9) << 16, 64, Port); + + /* write 2nd status quad word */ + SkGeRamWrite(pAC, IoC, RamAdr + 1, 0, 0, Port); + + WordBuffer[0] = pPrt->PMacAddr[0]; + WordBuffer[1] = pPrt->PMacAddr[1]; + WordBuffer[2] = pPrt->PMacAddr[2]; + WordBuffer[3] = pPrt->PMacAddr[0]; + + /* write DA to MAC header */ + SkGeRamWrite(pAC, IoC, RamAdr + 2, *(SK_U32 *)&WordBuffer[0], + *(SK_U32 *)&WordBuffer[2], Port); + + WordBuffer[0] = pPrt->PMacAddr[1]; + WordBuffer[1] = pPrt->PMacAddr[2]; + WordBuffer[2] = 0x3200; /* len / type field (big endian) */ + WordBuffer[3] = 0x00; + + SkGeRamWrite(pAC, IoC, RamAdr + 3, *(SK_U32 *)&WordBuffer[0], + *(SK_U32 *)&WordBuffer[2], Port); + + SkGeRamWrite(pAC, IoC, RamAdr + 4, 0x4c56524d, /* "MRVL" */ + 0x00464d2d, Port); /* "-MF" */ + + SkGeRamWrite(pAC, IoC, RamAdr + 5, 0x00000000, 0x00000000, Port); + SkGeRamWrite(pAC, IoC, RamAdr + 6, 0x00000000, 0x00000000, Port); + SkGeRamWrite(pAC, IoC, RamAdr + 7, 0x00000000, 0x00000000, Port); + SkGeRamWrite(pAC, IoC, RamAdr + 8, 0x00000000, 0x00000000, Port); + SkGeRamWrite(pAC, IoC, RamAdr + 9, 0x00000000, 0x00000000, Port); + + SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_PC), 1); + + SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime); + + /* set timeout to 10 ms */ + TimeOut = HW_MS_TO_TICKS(pAC, 10); + + do { + SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime); + + if (CurrTime >= StartTime) { + Delta = CurrTime - StartTime; + } + else { + Delta = CurrTime + ~StartTime + 1; + } + + if (Delta > TimeOut) { + Rtv = 1; + break; + } + + /* read the GMAC Interrupt source register */ + SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &Word); + + } while ((Word & (GM_IS_TX_COMPL | GM_IS_RX_COMPL)) != + (GM_IS_TX_COMPL | GM_IS_RX_COMPL)); + + /* disable MAC Loopback Mode and Rx/Tx */ + GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl); + + /* restore GMAC Rx Control Register */ + GM_OUT16(IoC, Port, GM_RX_CTRL, RxCtrl); + + /* restore Rx GMAC FIFO Flush Mask */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), FlushMask); + + /* restore Rx GMAC FIFO Flush Threshold */ + SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), FlushTrsh); + + return(Rtv); + +} /* SkYuk2RestartRxBmu */ +#endif /* YUK2 && !SK_SLIM */ +#endif diff --git a/drivers/sk98lin/skgemib.c b/drivers/sk98lin/skgemib.c index 4a9e9e6..d2ddc0f 100644 --- a/drivers/sk98lin/skgemib.c +++ b/drivers/sk98lin/skgemib.c @@ -2,15 +2,17 @@ * * Name: skgemib.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.7 $ - * Date: $Date: 2002/12/16 09:04:34 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Private Network Management Interface Management Database * ****************************************************************************/ /****************************************************************************** * - * (C)Copyright 2002 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,40 +20,11 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ - -/***************************************************************************** - * - * History: - * - * $Log: skgemib.c,v $ - * Revision 1.7 2002/12/16 09:04:34 tschilli - * Code for VCT handling added. - * - * Revision 1.6 2002/08/09 15:40:21 rwahl - * Editorial change (renamed ConfSpeedCap). - * - * Revision 1.5 2002/08/09 11:05:34 rwahl - * Added oid handling for link speed cap. - * - * Revision 1.4 2002/08/09 09:40:27 rwahl - * Added support for NDIS OID_PNP_xxx. - * - * Revision 1.3 2002/07/17 19:39:54 rwahl - * Added handler for OID_SKGE_SPEED_MODE & OID_SKGE_SPEED_STATUS. - * - * Revision 1.2 2002/05/22 08:59:00 rwahl - * - static functions only for release build. - * - Source file must be included. - * - * Revision 1.1 2002/05/22 08:12:42 rwahl - * Initial version. - * - ****************************************************************************/ - #include - + #ifdef CONFIG_SK98 /* @@ -104,7 +77,19 @@ PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex); -#endif +#endif /* SK_POWER_MGMT */ + +#ifdef SK_DIAG_SUPPORT +PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +#endif /* SK_DIAG_SUPPORT */ + +#ifdef SK_ASF +PNMI_STATIC int Asf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, + char *pBuf, unsigned int *pLen, SK_U32 Instance, + unsigned int TableIndex, SK_U32 NetIndex); +#endif /* SK_ASF */ /* defines *******************************************************************/ @@ -270,6 +255,190 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { 0, SK_PNMI_RW, PowerManagement, 0}, #endif /* SK_POWER_MGMT */ +#ifdef SK_DIAG_SUPPORT + {OID_SKGE_DIAG_MODE, + 0, + 0, + 0, + SK_PNMI_RW, DiagActions, 0}, +#endif /* SK_DIAG_SUPPORT */ +#ifdef SK_ASF + {OID_SKGE_ASF, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_STORE_CONFIG, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_ENA, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_RETRANS, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_RETRANS_INT, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_HB_ENA, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_HB_INT, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_WD_ENA, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_WD_TIME, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_IP_SOURCE, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_MAC_SOURCE, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_IP_DEST, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_MAC_DEST, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_COMMUNITY_NAME, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_RSP_ENA, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_RETRANS_COUNT_MIN, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_RETRANS_COUNT_MAX, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_RETRANS_INT_MIN, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_RETRANS_INT_MAX, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_HB_INT_MIN, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_HB_INT_MAX, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_WD_TIME_MIN, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_WD_TIME_MAX, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_HB_CAP, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_WD_TIMER_RES, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_GUID, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_KEY_OP, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_KEY_ADM, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_KEY_GEN, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_CAP, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_PAR_1, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_OVERALL_OID, + 0, + 0, + 0, + SK_PNMI_RW, Asf, 0}, + {OID_SKGE_ASF_FWVER_OID, + 0, + 0, + 0, + SK_PNMI_RO, Asf, 0}, + {OID_SKGE_ASF_ACPI_OID, + 0, + 0, + 0, + SK_PNMI_RO, Asf, 0}, + {OID_SKGE_ASF_SMBUS_OID, + 0, + 0, + 0, + SK_PNMI_RO, Asf, 0}, +#endif /* SK_ASF */ {OID_SKGE_MDB_VERSION, 1, 0, @@ -320,7 +489,7 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { sizeof(SK_PNMI_VPD), SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction), SK_PNMI_RW, Vpd, 0}, - {OID_SKGE_PORT_NUMBER, + {OID_SKGE_PORT_NUMBER, 1, 0, SK_PNMI_MAI_OFF(PortNumber), @@ -340,6 +509,16 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { 0, SK_PNMI_MAI_OFF(DriverVersion), SK_PNMI_RO, General, 0}, + {OID_SKGE_DRIVER_RELDATE, + 1, + 0, + SK_PNMI_MAI_OFF(DriverReleaseDate), + SK_PNMI_RO, General, 0}, + {OID_SKGE_DRIVER_FILENAME, + 1, + 0, + SK_PNMI_MAI_OFF(DriverFileName), + SK_PNMI_RO, General, 0}, {OID_SKGE_HW_DESCR, 1, 0, @@ -355,6 +534,21 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { 0, SK_PNMI_MAI_OFF(Chipset), SK_PNMI_RO, General, 0}, + {OID_SKGE_CHIPID, + 1, + 0, + SK_PNMI_MAI_OFF(ChipId), + SK_PNMI_RO, General, 0}, + {OID_SKGE_RAMSIZE, + 1, + 0, + SK_PNMI_MAI_OFF(RamSize), + SK_PNMI_RO, General, 0}, + {OID_SKGE_VAUXAVAIL, + 1, + 0, + SK_PNMI_MAI_OFF(VauxAvail), + SK_PNMI_RO, General, 0}, {OID_SKGE_ACTION, 1, 0, @@ -860,6 +1054,18 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { sizeof(SK_PNMI_CONF), SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector), SK_PNMI_RO, MacPrivateConf, 0}, + {OID_SKGE_PHY_TYPE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType), + SK_PNMI_RO, MacPrivateConf, 0}, +#ifdef SK_PHY_LP_MODE + {OID_SKGE_PHY_LP_MODE, + SK_PNMI_MAC_ENTRIES, + sizeof(SK_PNMI_CONF), + SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyMode), + SK_PNMI_RW, MacPrivateConf, 0}, +#endif {OID_SKGE_LINK_CAP, SK_PNMI_MAC_ENTRIES, sizeof(SK_PNMI_CONF), @@ -1055,6 +1261,15 @@ PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { 0, 0, SK_PNMI_RO, Vct, 0}, + {OID_SKGE_VCT_CAPABILITIES, + 0, + 0, + 0, + SK_PNMI_RO, Vct, 0}, + {OID_SKGE_BOARDLEVEL, + 0, + 0, + 0, + SK_PNMI_RO, General, 0}, }; - -#endif /* CONFIG_SK98 */ +#endif diff --git a/drivers/sk98lin/skgepnmi.c b/drivers/sk98lin/skgepnmi.c index b5d32b0..cde2ced 100644 --- a/drivers/sk98lin/skgepnmi.c +++ b/drivers/sk98lin/skgepnmi.c @@ -1,16 +1,18 @@ /***************************************************************************** * * Name: skgepnmi.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.102 $ - * Date: $Date: 2002/12/16 14:03:24 $ + * Project: Gigabit Ethernet Adapters, PNMI-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Private Network Management Interface * ****************************************************************************/ /****************************************************************************** * + * LICENSE: * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,427 +20,17 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ - -/***************************************************************************** - * - * History: - * - * $Log: skgepnmi.c,v $ - * Revision 1.102 2002/12/16 14:03:24 tschilli - * VCT code in Vct() changed. - * - * Revision 1.101 2002/12/16 09:04:10 tschilli - * Code for VCT handling added. - * - * Revision 1.100 2002/09/26 14:28:13 tschilli - * For XMAC the values in the SK_PNMI_PORT Port struct are copied to - * the new SK_PNMI_PORT BufPort struct during a MacUpdate() call. - * These values are used when GetPhysStatVal() is called. With this - * mechanism you get the best results when software corrections for - * counters are needed. Example: RX_LONGFRAMES. - * - * Revision 1.99 2002/09/17 12:31:19 tschilli - * OID_SKGE_TX_HW_ERROR_CTS, OID_SKGE_OUT_ERROR_CTS, OID_GEN_XMIT_ERROR: - * Double count of SK_PNMI_HTX_EXCESS_COL in function General() removed. - * OID_PNP_CAPABILITIES: sizeof(SK_PM_WAKE_UP_CAPABILITIES) changed to - * sizeof(SK_PNP_CAPABILITIES) in function PowerManagement(). - * - * Revision 1.98 2002/09/10 09:00:03 rwahl - * Adapted boolean definitions according sktypes. - * - * Revision 1.97 2002/09/05 15:07:03 rwahl - * Editorial changes. - * - * Revision 1.96 2002/09/05 11:04:14 rwahl - * - Rx/Tx packets statistics of virtual port were zero on link down (#10750) - * - For GMAC the overflow IRQ for Rx longframe counter was not counted. - * - Incorrect calculation for oids OID_SKGE_RX_HW_ERROR_CTS, - * OID_SKGE_IN_ERRORS_CTS, OID_GEN_RCV_ERROR. - * - Moved correction for OID_SKGE_STAT_RX_TOO_LONG to GetPhysStatVal(). - * - Editorial changes. - * - * Revision 1.95 2002/09/04 08:53:37 rwahl - * - Incorrect statistics for Rx_too_long counter with jumbo frame (#10751) - * - StatRxFrameTooLong & StatRxPMaccErr counters were not reset. - * - Fixed compiler warning for debug msg arg types. - * - * Revision 1.94 2002/08/09 15:42:14 rwahl - * - Fixed StatAddr table for GMAC. - * - VirtualConf(): returned indeterminated status for speed oids if no - * active port. - * - * Revision 1.93 2002/08/09 11:04:59 rwahl - * Added handler for link speed caps. - * - * Revision 1.92 2002/08/09 09:43:03 rwahl - * - Added handler for NDIS OID_PNP_xxx ids. - * - * Revision 1.91 2002/07/17 19:53:03 rwahl - * - Added StatOvrflwBit table for XMAC & GMAC. - * - Extended StatAddr table for GMAC. Added check of number of counters - * in enumeration and size of StatAddr table on init level. - * - Added use of GIFunc table. - * - ChipSet is not static anymore, - * - Extended SIRQ event handler for both mac types. - * - Fixed rx short counter bug (#10620) - * - Added handler for oids SKGE_SPEED_MODE & SKGE_SPEED_STATUS. - * - Extendet GetPhysStatVal() for GMAC. - * - Editorial changes. - * - * Revision 1.90 2002/05/22 08:56:25 rwahl - * - Moved OID table to separate source file. - * - Fix: TX_DEFFERAL counter incremented in full-duplex mode. - * - Use string definitions for error msgs. - * - * Revision 1.89 2001/09/18 10:01:30 mkunz - * some OID's fixed for dualnetmode - * - * Revision 1.88 2001/08/02 07:58:08 rwahl - * - Fixed NetIndex to csum module at ResetCounter(). - * - * Revision 1.87 2001/04/06 13:35:09 mkunz - * -Bugs fixed in handling of OID_SKGE_MTU and the VPD OID's - * - * Revision 1.86 2001/03/09 09:18:03 mkunz - * Changes in SK_DBG_MSG - * - * Revision 1.85 2001/03/08 09:37:31 mkunz - * Bugfix in ResetCounter for Pnmi.Port structure - * - * Revision 1.84 2001/03/06 09:04:55 mkunz - * Made some changes in instance calculation - * - * Revision 1.83 2001/02/15 09:15:32 mkunz - * Necessary changes for dual net mode added - * - * Revision 1.82 2001/02/07 08:24:19 mkunz - * -Made changes in handling of OID_SKGE_MTU - * - * Revision 1.81 2001/02/06 09:58:00 mkunz - * -Vpd bug fixed - * -OID_SKGE_MTU added - * -pnmi support for dual net mode. Interface function and macros extended - * - * Revision 1.80 2001/01/22 13:41:35 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.79 2000/12/05 14:57:40 cgoos - * SetStruct failed before first Link Up (link mode of virtual - * port "INDETERMINATED"). - * - * Revision 1.78 2000/09/12 10:44:58 cgoos - * Fixed SK_PNMI_STORE_U32 calls with typecasted argument. - * - * Revision 1.77 2000/09/07 08:10:19 rwahl - * - Modified algorithm for 64bit NDIS statistic counters; - * returns 64bit or 32bit value depending on passed buffer - * size. Indicate capability for 64bit NDIS counter, if passed - * buffer size is zero. OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR, - * and OID_GEN_RCV_NO_BUFFER handled as 64bit counter, too. - * - corrected OID_SKGE_RLMT_PORT_PREFERRED. - * - * Revision 1.76 2000/08/03 15:23:39 rwahl - * - Correction for FrameTooLong counter has to be moved to OID handling - * routines (instead of statistic counter routine). - * - Fix in XMAC Reset Event handling: Only offset counter for hardware - * statistic registers are updated. - * - * Revision 1.75 2000/08/01 16:46:05 rwahl - * - Added StatRxLongFrames counter and correction of FrameTooLong counter. - * - Added directive to control width (default = 32bit) of NDIS statistic - * counters (SK_NDIS_64BIT_CTR). - * - * Revision 1.74 2000/07/04 11:41:53 rwahl - * - Added volition connector type. - * - * Revision 1.73 2000/03/15 16:33:10 rwahl - * Fixed bug 10510; wrong reset of virtual port statistic counters. - * - * Revision 1.72 1999/12/06 16:15:53 rwahl - * Fixed problem of instance range for current and factory MAC address. - * - * Revision 1.71 1999/12/06 10:14:20 rwahl - * Fixed bug 10476; set operation for PHY_OPERATION_MODE. - * - * Revision 1.70 1999/11/22 13:33:34 cgoos - * Changed license header to GPL. - * - * Revision 1.69 1999/10/18 11:42:15 rwahl - * Added typecasts for checking event dependent param (debug only). - * - * Revision 1.68 1999/10/06 09:35:59 cgoos - * Added state check to PHY_READ call (hanged if called during startup). - * - * Revision 1.67 1999/09/22 09:53:20 rwahl - * - Read Broadcom register for updating fcs error counter (1000Base-T). - * - * Revision 1.66 1999/08/26 13:47:56 rwahl - * Added SK_DRIVER_SENDEVENT when queueing RLMT_CHANGE_THRES trap. - * - * Revision 1.65 1999/07/26 07:49:35 cgoos - * Added two typecasts to avoid compiler warnings. - * - * Revision 1.64 1999/05/20 09:24:12 cgoos - * Changes for 1000Base-T (sensors, Master/Slave). - * - * Revision 1.63 1999/04/13 15:11:58 mhaveman - * Moved include of rlmt.h to header skgepnmi.h because some macros - * are needed there. - * - * Revision 1.62 1999/04/13 15:08:07 mhaveman - * Replaced again SK_RLMT_CHECK_LINK with SK_PNMI_RLMT_MODE_CHK_LINK - * to grant unified interface by only using the PNMI header file. - * SK_PNMI_RLMT_MODE_CHK_LINK is defined the same as SK_RLMT_CHECK_LINK. - * - * Revision 1.61 1999/04/13 15:02:48 mhaveman - * Changes caused by review: - * -Changed some comments - * -Removed redundant check for OID_SKGE_PHYS_FAC_ADDR - * -Optimized PRESET check. - * -Meaning of error SK_ADDR_DUPLICATE_ADDRESS changed. Set of same - * address will now not cause this error. Removed corresponding check. - * - * Revision 1.60 1999/03/23 10:41:23 mhaveman - * Added comments. - * - * Revision 1.59 1999/02/19 08:01:28 mhaveman - * Fixed bug 10372 that after counter reset all ports were displayed - * as inactive. - * - * Revision 1.58 1999/02/16 18:04:47 mhaveman - * Fixed problem of twisted OIDs SENSOR_WAR_TIME and SENSOR_ERR_TIME. - * - * Revision 1.56 1999/01/27 12:29:11 mhaveman - * SkTimerStart was called with time value in milli seconds but needs - * micro seconds. - * - * Revision 1.55 1999/01/25 15:00:38 mhaveman - * Added support to allow multiple ports to be active. If this feature in - * future will be used, the Management Data Base variables PORT_ACTIVE - * and PORT_PREFERED should be moved to the port specific part of RLMT. - * Currently they return the values of the first active physical port - * found. A set to the virtual port will actually change all active - * physical ports. A get returns the melted values of all active physical - * ports. If the port values differ a return value INDETERMINATED will - * be returned. This effects especially the CONF group. - * - * Revision 1.54 1999/01/19 10:10:22 mhaveman - * -Fixed bug 10354: Counter values of virtual port were wrong after port - * switches - * -Added check if a switch to the same port is notified. - * - * Revision 1.53 1999/01/07 09:25:21 mhaveman - * Forgot to initialize a variable. - * - * Revision 1.52 1999/01/05 10:34:33 mhaveman - * Fixed little error in RlmtChangeEstimate calculation. - * - * Revision 1.51 1999/01/05 09:59:07 mhaveman - * -Moved timer start to init level 2 - * -Redesigned port switch average calculation to avoid 64bit - * arithmetic. - * - * Revision 1.50 1998/12/10 15:13:59 mhaveman - * -Fixed: PHYS_CUR_ADDR returned wrong addresses - * -Fixed: RLMT_PORT_PREFERED and RLMT_CHANGE_THRES preset returned - * always BAD_VALUE. - * -Fixed: TRAP buffer seemed to sometimes suddenly empty - * - * Revision 1.49 1998/12/09 16:17:07 mhaveman - * Fixed: Couldnot delete VPD keys on UNIX. - * - * Revision 1.48 1998/12/09 14:11:10 mhaveman - * -Add: Debugmessage for XMAC_RESET supressed to minimize output. - * -Fixed: RlmtChangeThreshold will now be initialized. - * -Fixed: VPD_ENTRIES_LIST extended value with unnecessary space char. - * -Fixed: On VPD key creation an invalid key name could be created - * (e.g. A5) - * -Some minor changes in comments and code. - * - * Revision 1.47 1998/12/08 16:00:31 mhaveman - * -Fixed: For RLMT_PORT_ACTIVE will now be returned a 0 if no port - * is active. - * -Fixed: For the RLMT statistics group only the last value was - * returned and the rest of the buffer was filled with 0xff - * -Fixed: Mysteriously the preset on RLMT_MODE still returned - * BAD_VALUE. - * Revision 1.46 1998/12/08 10:04:56 mhaveman - * -Fixed: Preset on RLMT_MODE returned always BAD_VALUE error. - * -Fixed: Alignment error in GetStruct - * -Fixed: If for Get/Preset/SetStruct the buffer size is equal or - * larger than SK_PNMI_MIN_STRUCT_SIZE the return value is stored - * to the buffer. In this case the caller should always return - * ok to its upper routines. Only if the buffer size is less - * than SK_PNMI_MIN_STRUCT_SIZE and the return value is unequal - * to 0, an error should be returned by the caller. - * -Fixed: Wrong number of instances with RLMT statistic. - * -Fixed: Return now SK_LMODE_STAT_UNKNOWN if the LinkModeStatus is 0. - * - * Revision 1.45 1998/12/03 17:17:24 mhaveman - * -Removed for VPD create action the buffer size limitation to 4 bytes. - * -Pass now physical/active physical port to ADDR for CUR_ADDR set - * - * Revision 1.44 1998/12/03 15:14:35 mhaveman - * Another change to Vpd instance evaluation. - * - * Revision 1.43 1998/12/03 14:18:10 mhaveman - * -Fixed problem in PnmiSetStruct. It was impossible to set any value. - * -Removed VPD key evaluation for VPD_FREE_BYTES and VPD_ACTION. - * - * Revision 1.42 1998/12/03 11:31:47 mhaveman - * Inserted cast to satisfy lint. - * - * Revision 1.41 1998/12/03 11:28:16 mhaveman - * Removed SK_PNMI_CHECKPTR - * - * Revision 1.40 1998/12/03 11:19:07 mhaveman - * Fixed problems - * -A set to virtual port will now be ignored. A set with broadcast - * address to any port will be ignored. - * -GetStruct function made VPD instance calculation wrong. - * -Prefered port returned -1 instead of 0. - * - * Revision 1.39 1998/11/26 15:30:29 mhaveman - * Added sense mode to link mode. - * - * Revision 1.38 1998/11/23 15:34:00 mhaveman - * -Fixed bug for RX counters. On an RX overflow interrupt the high - * words of all RX counters were incremented. - * -SET operations on FLOWCTRL_MODE and LINK_MODE accept now the - * value 0, which has no effect. It is usefull for multiple instance - * SETs. - * - * Revision 1.37 1998/11/20 08:02:04 mhaveman - * -Fixed: Ports were compared with MAX_SENSORS - * -Fixed: Crash in GetTrapEntry with MEMSET macro - * -Fixed: Conversions between physical, logical port index and instance - * - * Revision 1.36 1998/11/16 07:48:53 mhaveman - * Casted SK_DRIVER_SENDEVENT with (void) to eleminate compiler warnings - * on Solaris. - * - * Revision 1.35 1998/11/16 07:45:34 mhaveman - * SkAddrOverride now returns value and will be checked. - * - * Revision 1.34 1998/11/10 13:40:37 mhaveman - * Needed to change interface, because NT driver needs a return value - * of needed buffer space on TOO_SHORT errors. Therefore all - * SkPnmiGet/Preset/Set functions now have a pointer to the length - * parameter, where the needed space on error is returned. - * - * Revision 1.33 1998/11/03 13:52:46 mhaveman - * Made file lint conform. - * - * Revision 1.32 1998/11/03 13:19:07 mhaveman - * The events SK_HWEV_SET_LMODE and SK_HWEV_SET_FLOWMODE pass now in - * Para32[0] the physical MAC index and in Para32[1] the new mode. - * - * Revision 1.31 1998/11/03 12:30:40 gklug - * fix: compiler warning memset - * - * Revision 1.30 1998/11/03 12:04:46 mhaveman - * Fixed problem in SENSOR_VALUE, which wrote beyond the buffer end - * Fixed alignment problem with CHIPSET. - * - * Revision 1.29 1998/11/02 11:23:54 mhaveman - * Corrected SK_ERROR_LOG to SK_ERR_LOG. Sorry. - * - * Revision 1.28 1998/11/02 10:47:16 mhaveman - * Added syslog messages for internal errors. - * - * Revision 1.27 1998/10/30 15:48:06 mhaveman - * Fixed problems after simulation of SK_PNMI_EVT_CHG_EST_TIMER and - * RlmtChangeThreshold calculation. - * - * Revision 1.26 1998/10/29 15:36:55 mhaveman - * -Fixed bug in trap buffer handling. - * -OID_SKGE_DRIVER_DESCR, OID_SKGE_DRIVER_VERSION, OID_SKGE_HW_DESCR, - * OID_SKGE_HW_VERSION, OID_SKGE_VPD_ENTRIES_LIST, OID_SKGE_VPD_KEY, - * OID_SKGE_VPD_VALUE, and OID_SKGE_SENSOR_DESCR return values with - * a leading octet before each string storing the string length. - * -Perform a RlmtUpdate during SK_PNMI_EVT_XMAC_RESET to minimize - * RlmtUpdate calls in GetStatVal. - * -Inserted SK_PNMI_CHECKFLAGS macro increase readability. - * - * Revision 1.25 1998/10/29 08:50:36 mhaveman - * Fixed problems after second event simulation. - * - * Revision 1.24 1998/10/28 08:44:37 mhaveman - * -Fixed alignment problem - * -Fixed problems during event simulation - * -Fixed sequence of error return code (INSTANCE -> ACCESS -> SHORT) - * -Changed type of parameter Instance back to SK_U32 because of VPD - * -Updated new VPD function calls - * - * Revision 1.23 1998/10/23 10:16:37 mhaveman - * Fixed bugs after buffer test simulation. - * - * Revision 1.22 1998/10/21 13:23:52 mhaveman - * -Call syntax of SkOsGetTime() changed to SkOsGetTime(pAc). - * -Changed calculation of hundrets of seconds. - * - * Revision 1.20 1998/10/20 07:30:45 mhaveman - * Made type changes to unsigned integer where possible. - * - * Revision 1.19 1998/10/19 10:51:30 mhaveman - * -Made Bug fixes after simulation run - * -Renamed RlmtMAC... to RlmtPort... - * -Marked workarounds with Errata comments - * - * Revision 1.18 1998/10/14 07:50:08 mhaveman - * -For OID_SKGE_LINK_STATUS the link down detection has moved from RLMT - * to HWACCESS. - * -Provided all MEMCPY/MEMSET macros with (char *) pointers, because - * Solaris throwed warnings when mapping to bcopy/bset. - * - * Revision 1.17 1998/10/13 07:42:01 mhaveman - * -Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA - * -Removed old cvs history entries - * -Renamed MacNumber to PortNumber - * - * Revision 1.16 1998/10/07 10:52:49 mhaveman - * -Inserted handling of some OID_GEN_ Ids for windows - * -Fixed problem with 803.2 statistic. - * - * Revision 1.15 1998/10/01 09:16:29 mhaveman - * Added Debug messages for function call and UpdateFlag tracing. - * - * Revision 1.14 1998/09/30 13:39:09 mhaveman - * -Reduced namings of 'MAC' by replacing them with 'PORT'. - * -Completed counting of OID_SKGE_RX_HW_ERROR_CTS, - * OID_SKGE_TX_HW_ERROR_CTS, - * OID_SKGE_IN_ERRORS_CTS, and OID_SKGE_OUT_ERROR_CTS. - * -SET check for RlmtMode - * - * Revision 1.13 1998/09/28 13:13:08 mhaveman - * Hide strcmp, strlen, and strncpy behind macros SK_STRCMP, SK_STRLEN, - * and SK_STRNCPY. (Same reasons as for mem.. and MEM..) - * - * Revision 1.12 1998/09/16 08:18:36 cgoos - * Fix: XM_INxx and XM_OUTxx called with different parameter order: - * sometimes IoC,Mac,... sometimes Mac,IoC,... Now always first variant. - * Fix: inserted "Pnmi." into some pAC->pDriverDescription / Version. - * Change: memset, memcpy to makros SK_MEMSET, SK_MEMCPY - * - * Revision 1.11 1998/09/04 17:01:45 mhaveman - * Added SyncCounter as macro and OID_SKGE_.._NO_DESCR_CTS to - * OID_SKGE_RX_NO_BUF_CTS. - * - * Revision 1.10 1998/09/04 14:35:35 mhaveman - * Added macro counters, that are counted by driver. - * - ****************************************************************************/ - - #include - + #ifdef CONFIG_SK98 +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "@(#) $Id: skgepnmi.c,v 1.102 2002/12/16 14:03:24 tschilli Exp $" - " (C) SysKonnect."; + "@(#) $Id: skgepnmi.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif #include "h/skdrv1st.h" #include "h/sktypes.h" @@ -450,12 +42,14 @@ static const char SysKonnectFileId[] = #include "h/skcsum.h" #include "h/skvpd.h" #include "h/skgehw.h" +#include "h/sky2le.h" #include "h/skgeinit.h" #include "h/skdrv2nd.h" #include "h/skgepnm2.h" #ifdef SK_POWER_MGMT #include "h/skgepmgt.h" -#endif +#endif /* SK_POWER_MGMT */ + /* defines *******************************************************************/ #ifndef DEBUG @@ -464,25 +58,6 @@ static const char SysKonnectFileId[] = #define PNMI_STATIC #endif /* DEBUG */ -/* - * Public Function prototypes - */ -int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level); -int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param); - - /* * Private Function prototypes */ @@ -519,9 +94,8 @@ PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC); PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf); -PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf, - unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex); PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32); +PNMI_STATIC void VctGetResults(SK_AC *, SK_IOC, SK_U32); /* * Table to correlate OID with handler function and index to @@ -698,7 +272,7 @@ PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] /* SK_PNMI_HRX_FRAMING */ {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}}, /* SK_PNMI_HRX_UNDERSIZE */ - {{0, SK_FALSE},{GM_RXF_SHT, SK_TRUE}}, + {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}}, /* SK_PNMI_HRX_OVERFLOW */ {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}}, /* SK_PNMI_HRX_JABBER */ @@ -763,18 +337,13 @@ PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] * Always 0 */ int SkPnmiInit( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Level) /* Initialization level */ +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Level) /* Initialization level */ { unsigned int PortMax; /* Number of ports */ unsigned int PortIndex; /* Current port index in loop */ - SK_U16 Val16; /* Multiple purpose 16 bit variable */ - SK_U8 Val8; /* Mulitple purpose 8 bit variable */ - SK_EVPARA EventParam; /* Event struct for timer event */ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - + SK_EVPARA EventParam; /* Event struct for timer event */ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiInit: Called, level=%d\n", Level)); @@ -783,30 +352,35 @@ int Level) /* Initialization level */ case SK_INIT_DATA: SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi)); + pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN; pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES; + for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) { pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE; pAC->Pnmi.DualNetActiveFlag = SK_FALSE; + + /* Initialize DSP variables for Vct() to 0xff => Never written! */ + pAC->GIni.GP[PortIndex].PCableLen = 0xff; + pAC->Pnmi.VctBackup[PortIndex].CableLen = 0xff; } #ifdef SK_PNMI_CHECK if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) { - + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG); SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, ("CounterOffset struct size (%d) differs from" "SK_PNMI_MAX_IDX (%d)\n", SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX)); - BRK; } if (SK_PNMI_MAX_IDX != (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) { - + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG); SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, @@ -815,15 +389,13 @@ int Level) /* Initialization level */ (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)), SK_PNMI_MAX_IDX)); - BRK; } #endif /* SK_PNMI_CHECK */ break; case SK_INIT_IO: - /* - * Reset MAC counters - */ + + /* Reset MAC counters. */ PortMax = pAC->GIni.GIMacsFound; for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { @@ -831,42 +403,27 @@ int Level) /* Initialization level */ pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex); } - /* Initialize DSP variables for Vct() to 0xff => Never written! */ - for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { - pPrt = &pAC->GIni.GP[PortIndex]; - pPrt->PCableLen =0xff; - pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex]; - pVctBackupData->PCableLen = 0xff; - } + /* Get PCI bus speed. */ + if (pAC->GIni.GIPciClock66) { - /* - * Get pci bus speed - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_CLOCK) == 0) { - - pAC->Pnmi.PciBusSpeed = 33; - } - else { pAC->Pnmi.PciBusSpeed = 66; } - - /* - * Get pci bus width - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_SLOT_SZ) == 0) { - - pAC->Pnmi.PciBusWidth = 32; - } else { + pAC->Pnmi.PciBusSpeed = 33; + } + + /* Get PCI bus width. */ + if (pAC->GIni.GIPciSlot64) { + pAC->Pnmi.PciBusWidth = 64; } + else { + pAC->Pnmi.PciBusWidth = 32; + } - /* - * Get chipset - */ + /* Get chipset. */ switch (pAC->GIni.GIChipId) { + case CHIP_ID_GENESIS: pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC; break; @@ -875,57 +432,51 @@ int Level) /* Initialization level */ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON; break; + case CHIP_ID_YUKON_LITE: + pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LITE; + break; + + case CHIP_ID_YUKON_LP: + pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LP; + break; + + case CHIP_ID_YUKON_XL: + pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_XL; + break; + + case CHIP_ID_YUKON_EC: + pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_EC; + break; + + case CHIP_ID_YUKON_FE: + pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_FE; + break; + default: break; } - /* - * Get PMD and DeviceType - */ - SK_IN8(IoC, B2_PMD_TYP, &Val8); - switch (Val8) { + /* Get PMD and Device Type. */ + switch (pAC->GIni.GIPmdTyp) { + case 'S': pAC->Pnmi.PMD = 3; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020002; - } - else { - pAC->Pnmi.DeviceType = 0x00020001; - } + pAC->Pnmi.DeviceType = 0x00020001; break; case 'L': pAC->Pnmi.PMD = 2; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020004; - } - else { - pAC->Pnmi.DeviceType = 0x00020003; - } + pAC->Pnmi.DeviceType = 0x00020003; break; case 'C': pAC->Pnmi.PMD = 4; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020006; - } - else { - pAC->Pnmi.DeviceType = 0x00020005; - } + pAC->Pnmi.DeviceType = 0x00020005; break; case 'T': pAC->Pnmi.PMD = 5; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020008; - } - else { - pAC->Pnmi.DeviceType = 0x00020007; - } + pAC->Pnmi.DeviceType = 0x00020007; break; default : @@ -934,11 +485,14 @@ int Level) /* Initialization level */ break; } - /* - * Get connector - */ - SK_IN8(IoC, B2_CONN_TYP, &Val8); - switch (Val8) { + if (pAC->GIni.GIMacsFound > 1) { + + pAC->Pnmi.DeviceType++; + } + + /* Get connector type. */ + switch (pAC->GIni.GIConTyp) { + case 'C': pAC->Pnmi.Connector = 2; break; @@ -966,17 +520,17 @@ int Level) /* Initialization level */ break; case SK_INIT_RUN: - /* - * Start timer for RLMT change counter - */ - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); + + /* Start timer for RLMT change counter. */ + SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, + SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, EventParam); break; default: - break; /* Nothing todo */ + break; /* Nothing to do. */ } return (0); @@ -998,17 +552,17 @@ int Level) /* Initialization level */ * the data. * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ int SkPnmiGetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which to mgmt data will be retrieved */ +void *pBuf, /* Buffer to which the management data will be copied */ unsigned int *pLen, /* On call: buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", @@ -1026,8 +580,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * Calls a general sub-function for all this stuff. The preset does * the same as a set, but returns just before finally setting the * new value. This is usefull to check if a set might be successfull. - * If as instance a -1 is passed, an array of values is supposed and - * all instance of the OID will be set. + * If the instance -1 is passed, an array of values is supposed and + * all instances of the OID will be set. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. @@ -1040,23 +594,22 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ int SkPnmiPreSetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer which stores the mgmt data to be set */ -unsigned int *pLen, /* Total length of mgmt data */ +void *pBuf, /* Buffer to which the management data will be copied */ +unsigned int *pLen, /* Total length of management data */ SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", Id, *pLen, Instance, NetIndex)); - return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen, Instance, NetIndex)); } @@ -1069,8 +622,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * Calls a general sub-function for all this stuff. The preset does * the same as a set, but returns just before finally setting the * new value. This is usefull to check if a set might be successfull. - * If as instance a -1 is passed, an array of values is supposed and - * all instance of the OID will be set. + * If the instance -1 is passed, an array of values is supposed and + * all instances of the OID will be set. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. @@ -1083,17 +636,17 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ int SkPnmiSetVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer which stores the mgmt data to be set */ -unsigned int *pLen, /* Total length of mgmt data */ +void *pBuf, /* Buffer to which the management data will be copied */ +unsigned int *pLen, /* Total length of management data */ SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", @@ -1125,9 +678,9 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ int SkPnmiGetStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which will store the retrieved data */ +void *pBuf, /* Buffer to which the management data will be copied. */ unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int TableIndex; @@ -1138,7 +691,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ unsigned int TmpLen; char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n", *pLen, NetIndex)); @@ -1147,22 +699,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1)); } *pLen = SK_PNMI_STRUCT_SIZE; return (SK_PNMI_ERR_TOO_SHORT); } - /* - * Check NetIndex - */ + /* Check NetIndex. */ if (NetIndex >= pAC->Rlmt.NumNets) { return (SK_PNMI_ERR_UNKNOWN_NET); } - /* Update statistic */ + /* Update statistics. */ SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call"); if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) != @@ -1187,35 +736,37 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (Ret); } - /* - * Increment semaphores to indicate that an update was - * already done - */ + /* Increment semaphores to indicate that an update was already done. */ pAC->Pnmi.MacUpdatedFlag ++; pAC->Pnmi.RlmtUpdatedFlag ++; pAC->Pnmi.SirqUpdatedFlag ++; - /* Get vpd keys for instance calculation */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen); - if (Ret != SK_PNMI_ERR_OK) { + /* + * Get VPD keys for instance calculation. + * Please read comment in Vpd(). + */ + if (pAC->Pnmi.VpdKeyReadError == SK_FALSE) { + Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen); + if (Ret != SK_PNMI_ERR_OK) { - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; + pAC->Pnmi.MacUpdatedFlag --; + pAC->Pnmi.RlmtUpdatedFlag --; + pAC->Pnmi.SirqUpdatedFlag --; - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_GENERAL); + SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); + SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); + *pLen = SK_PNMI_MIN_STRUCT_SIZE; + return (SK_PNMI_ERR_GENERAL); + } } - /* Retrieve values */ + /* Retrieve values. */ SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE); + for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { InstanceNo = IdTable[TableIndex].InstanceNo; - for (InstanceCnt = 1; InstanceCnt <= InstanceNo; - InstanceCnt ++) { + for (InstanceCnt = 1; InstanceCnt <= InstanceNo; InstanceCnt ++) { DstOffset = IdTable[TableIndex].Offset + (InstanceCnt - 1) * @@ -1250,7 +801,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ */ if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { - break; + break; } if (Ret != SK_PNMI_ERR_OK) { @@ -1305,14 +856,14 @@ SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ void *pBuf, /* Buffer which contains the data to be set */ unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n", *pLen, NetIndex)); return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf, - pLen, NetIndex)); + pLen, NetIndex)); } /***************************************************************************** @@ -1343,14 +894,14 @@ SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ void *pBuf, /* Buffer which contains the data to be set */ unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n", *pLen, NetIndex)); return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf, - pLen, NetIndex)); + pLen, NetIndex)); } /***************************************************************************** @@ -1396,9 +947,9 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * is now an active port. PNMI will now * add the statistic data of this port to * the virtual port. - * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first Parameter + * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter * contains the number of nets. 1 means single net, 2 means - * dual net. The second Parameter is -1 + * dual net. The second parameter is -1 * * Returns: * Always 0 @@ -1410,9 +961,8 @@ SK_U32 Event, /* Event-Id */ SK_EVPARA Param) /* Event dependent parameter */ { unsigned int PhysPortIndex; - unsigned int MaxNetNumber; + unsigned int MaxNetNumber; int CounterIndex; - int Ret; SK_U16 MacStatus; SK_U64 OverflowStatus; SK_U64 Mask; @@ -1426,12 +976,7 @@ SK_EVPARA Param) /* Event dependent parameter */ SK_U64 Delta; SK_PNMI_ESTIMATE *pEst; SK_U32 NetIndex; - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; SK_U32 RetCode; - int i; - SK_U32 CableLength; - #ifdef DEBUG if (Event != SK_PNMI_EVT_XMAC_RESET) { @@ -1440,11 +985,11 @@ SK_EVPARA Param) /* Event dependent parameter */ ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n", (unsigned int)Event, (unsigned int)Param.Para64)); } -#endif +#endif /* DEBUG */ SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call"); MacType = pAC->GIni.GIMacType; - + switch (Event) { case SK_PNMI_EVT_SIRQ_OVERFLOW: @@ -1459,14 +1004,12 @@ SK_EVPARA Param) /* Event dependent parameter */ PhysPortIndex)); return (0); } -#endif +#endif /* DEBUG */ OverflowStatus = 0; - /* - * Check which source caused an overflow interrupt. - */ - if ((pAC->GIni.GIFunc.pFnMacOverflow( - pAC, IoC, PhysPortIndex, MacStatus, &OverflowStatus) != 0) || + /* Check which source caused an overflow interrupt. */ + if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex, + MacStatus, &OverflowStatus) != 0) || (OverflowStatus == 0)) { SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); @@ -1482,7 +1025,6 @@ SK_EVPARA Param) /* Event dependent parameter */ Mask = (SK_U64)1 << CounterIndex; if ((OverflowStatus & Mask) == 0) { - continue; } @@ -1490,20 +1032,20 @@ SK_EVPARA Param) /* Event dependent parameter */ case SK_PNMI_HTX_UTILUNDER: case SK_PNMI_HTX_UTILOVER: - XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, - &Register); - Register |= XM_TX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, - Register); + if (MacType == SK_MAC_XMAC) { + XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register); + Register |= XM_TX_SAM_LINE; + XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register); + } break; case SK_PNMI_HRX_UTILUNDER: case SK_PNMI_HRX_UTILOVER: - XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, - &Register); - Register |= XM_RX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, - Register); + if (MacType == SK_MAC_XMAC) { + XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register); + Register |= XM_RX_SAM_LINE; + XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register); + } break; case SK_PNMI_HTX_OCTETHIGH: @@ -1513,10 +1055,8 @@ SK_EVPARA Param) /* Event dependent parameter */ case SK_PNMI_HRX_OCTETLOW: case SK_PNMI_HRX_IRLENGTH: case SK_PNMI_HRX_RESERVED: - - /* - * the following counters aren't be handled (id > 63) - */ + + /* The following counters aren't be handled (id > 63). */ case SK_PNMI_HTX_SYNC: case SK_PNMI_HTX_SYNC_OCTET: break; @@ -1544,7 +1084,8 @@ SK_EVPARA Param) /* Event dependent parameter */ (unsigned int)Param.Para64)); return (0); } -#endif +#endif /* DEBUG */ + /* * Store a trap message in the trap buffer and generate * an event for user space applications with the @@ -1560,11 +1101,12 @@ SK_EVPARA Param) /* Event dependent parameter */ if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR:SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n", + ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n", (unsigned int)Param.Para64)); return (0); } -#endif +#endif /* DEBUG */ + /* * Store a trap message in the trap buffer and generate * an event for user space applications with the @@ -1584,7 +1126,8 @@ SK_EVPARA Param) /* Event dependent parameter */ (unsigned int)Param.Para64)); return (0); } -#endif +#endif /* DEBUG */ + /* * Store a trap message in the trap buffer and generate * an event for user space applications with the @@ -1594,17 +1137,18 @@ SK_EVPARA Param) /* Event dependent parameter */ (unsigned int)Param.Para64); (void)SK_DRIVER_SENDEVENT(pAC, IoC); break; - + case SK_PNMI_EVT_SEN_ERR_UPP: #ifdef DEBUG if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n", + ("PNMI: ERR: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n", (unsigned int)Param.Para64)); return (0); } -#endif +#endif /* DEBUG */ + /* * Store a trap message in the trap buffer and generate * an event for user space applications with the @@ -1618,16 +1162,14 @@ SK_EVPARA Param) /* Event dependent parameter */ case SK_PNMI_EVT_CHG_EST_TIMER: /* * Calculate port switch average on a per hour basis - * Time interval for check : 28125 ms + * Time interval for check : 28125 ms (SK_PNMI_EVT_TIMER_CHECK) * Number of values for average : 8 * * Be careful in changing these values, on change check * - typedef of SK_PNMI_ESTIMATE (Size of EstValue * array one less than value number) - * - Timer initilization SkTimerStart() in SkPnmiInit - * - Delta value below must be multiplicated with - * power of 2 - * + * - Timer initialization SkTimerStart() in SkPnmiInit + * - Delta value below must be multiplicated with power of 2 */ pEst = &pAC->Pnmi.RlmtChangeEstimate; CounterIndex = pEst->EstValueIndex + 1; @@ -1650,7 +1192,7 @@ SK_EVPARA Param) /* Event dependent parameter */ Delta = NewestValue - OldestValue; } else { - /* Overflow situation */ + /* Overflow situation. */ Delta = (SK_U64)(0 - OldestValue) + NewestValue; } @@ -1675,9 +1217,10 @@ SK_EVPARA Param) /* Event dependent parameter */ (void)SK_DRIVER_SENDEVENT(pAC, IoC); } - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); + SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, + SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, EventParam); break; @@ -1697,13 +1240,14 @@ SK_EVPARA Param) /* Event dependent parameter */ return (0); } -#endif +#endif /* DEBUG */ /* - * Set all counters and timestamps to zero + * Set all counters and timestamps to zero. + * The according NetIndex is required as a + * parameter of the event. */ - ResetCounter(pAC, IoC, NetIndex); /* the according NetIndex is required - as a Parameter of the Event */ + ResetCounter(pAC, IoC, NetIndex); break; case SK_PNMI_EVT_XMAC_RESET: @@ -1720,37 +1264,32 @@ SK_EVPARA Param) /* Event dependent parameter */ (unsigned int)Param.Para64)); return (0); } -#endif +#endif /* DEBUG */ + PhysPortIndex = (unsigned int)Param.Para64; - /* - * Update XMAC statistic to get fresh values - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { + /* Update XMAC statistic to get fresh values. */ + if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != + SK_PNMI_ERR_OK) { SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); return (0); } - /* - * Increment semaphore to indicate that an update was - * already done - */ + + /* Increment semaphore to indicate that an update was already done. */ pAC->Pnmi.MacUpdatedFlag ++; for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; CounterIndex ++) { if (!StatAddr[CounterIndex][MacType].GetOffset) { - continue; } - pAC->Pnmi.Port[PhysPortIndex]. - CounterOffset[CounterIndex] = GetPhysStatVal( - pAC, IoC, PhysPortIndex, CounterIndex); - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] = 0; + pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] = + GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); + + pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0; } pAC->Pnmi.MacUpdatedFlag --; @@ -1763,11 +1302,12 @@ SK_EVPARA Param) /* Event dependent parameter */ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); + " wrong, PhysPortIndex=%d\n", PhysPortIndex)); return (0); } -#endif +#endif /* DEBUG */ + /* * Store a trap message in the trap buffer and generate an event for * user space applications with the SK_DRIVER_SENDEVENT macro. @@ -1775,21 +1315,21 @@ SK_EVPARA Param) /* Event dependent parameter */ QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex); (void)SK_DRIVER_SENDEVENT(pAC, IoC); - /* Bugfix for XMAC errata (#10620)*/ - if (pAC->GIni.GIMacType == SK_MAC_XMAC){ - - /* Add incremental difference to offset (#10620)*/ + /* Bugfix for XMAC errata (#10620). */ + if (MacType == SK_MAC_XMAC) { + /* Add incremental difference to offset (#10620). */ (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, XM_RXE_SHT_ERR, &Val32); - + Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); + pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] += Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark; } - + /* Tell VctStatus() that a link was up meanwhile. */ - pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK; + pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK; break; case SK_PNMI_EVT_RLMT_PORT_DOWN: @@ -1800,11 +1340,12 @@ SK_EVPARA Param) /* Event dependent parameter */ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); + " wrong, PhysPortIndex=%d\n", PhysPortIndex)); return (0); } -#endif +#endif /* DEBUG */ + /* * Store a trap message in the trap buffer and generate an event for * user space applications with the SK_DRIVER_SENDEVENT macro. @@ -1812,11 +1353,12 @@ SK_EVPARA Param) /* Event dependent parameter */ QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex); (void)SK_DRIVER_SENDEVENT(pAC, IoC); - /* Bugfix #10620 - get zero level for incremental difference */ - if ((pAC->GIni.GIMacType == SK_MAC_XMAC)) { + /* Bugfix #10620 - get zero level for incremental difference. */ + if (MacType == SK_MAC_XMAC) { (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, XM_RXE_SHT_ERR, &Val32); + pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); @@ -1841,18 +1383,15 @@ SK_EVPARA Param) /* Event dependent parameter */ ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n", NetIndex)); } -#endif - /* - * For now, ignore event if NetIndex != 0. - */ +#endif /* DEBUG */ + + /* For now, ignore event if NetIndex != 0. */ if (Param.Para32[1] != 0) { return (0); } - /* - * Nothing to do if port is already inactive - */ + /* Nothing to do if port is already inactive. */ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { return (0); @@ -1883,7 +1422,6 @@ SK_EVPARA Param) /* Event dependent parameter */ CounterIndex ++) { if (!StatAddr[CounterIndex][MacType].GetOffset) { - continue; } @@ -1892,9 +1430,7 @@ SK_EVPARA Param) /* Event dependent parameter */ pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value; } - /* - * Set port to inactive - */ + /* Set port to inactive. */ pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE; pAC->Pnmi.MacUpdatedFlag --; @@ -1918,26 +1454,21 @@ SK_EVPARA Param) /* Event dependent parameter */ ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n", NetIndex)); } -#endif - /* - * For now, ignore event if NetIndex != 0. - */ +#endif /* DEBUG */ + + /* For now, ignore event if NetIndex != 0. */ if (Param.Para32[1] != 0) { return (0); } - /* - * Nothing to do if port is already active - */ + /* Nothing to do if port is already inactive. */ if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { return (0); } - /* - * Statistic maintenance - */ + /* Statistic maintenance. */ pAC->Pnmi.RlmtChangeCts ++; pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); @@ -1971,7 +1502,6 @@ SK_EVPARA Param) /* Event dependent parameter */ CounterIndex ++) { if (!StatAddr[CounterIndex][MacType].GetOffset) { - continue; } @@ -1980,18 +1510,14 @@ SK_EVPARA Param) /* Event dependent parameter */ pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value; } - /* - * Set port to active - */ + /* Set port to active. */ pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE; pAC->Pnmi.MacUpdatedFlag --; break; case SK_PNMI_EVT_RLMT_SEGMENTATION: - /* - * Para.Para32[0] contains the NetIndex. - */ + /* Para.Para32[0] contains the NetIndex. */ /* * Store a trap message in the trap buffer and generate an event for @@ -2006,65 +1532,56 @@ SK_EVPARA Param) /* Event dependent parameter */ * Param.Para32[0] contains the number of Nets. * Param.Para32[1] is reserved, contains -1. */ - /* - * Check number of nets - */ + /* Check number of nets. */ MaxNetNumber = pAC->GIni.GIMacsFound; - if (((unsigned int)Param.Para32[0] < 1) - || ((unsigned int)Param.Para32[0] > MaxNetNumber)) { + + if (((unsigned int)Param.Para32[0] < 1) || + ((unsigned int)Param.Para32[0] > MaxNetNumber)) { + return (SK_PNMI_ERR_UNKNOWN_NET); } - if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_FALSE; - } - else { /* dual net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_TRUE; - } - break; + if ((unsigned int)Param.Para32[0] == 1) { /* SingleNet mode. */ + pAC->Pnmi.DualNetActiveFlag = SK_FALSE; + } + else { /* DualNet mode. */ + pAC->Pnmi.DualNetActiveFlag = SK_TRUE; + } + break; case SK_PNMI_EVT_VCT_RESET: - PhysPortIndex = Param.Para32[0]; - pPrt = &pAC->GIni.GP[PhysPortIndex]; - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 2) { - /* - * VCT test is still running. - * Start VCT timer counter again. - */ - SK_MEMSET((char *) &Param, 0, sizeof(Param)); - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); - break; - } - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairLen[i] > 35) { - CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); + PhysPortIndex = Param.Para32[0]; + + if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { + + RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); + + if (RetCode == 2) { + /* + * VCT test is still running. + * Start VCT timer counter again. + */ + SK_MEMSET((char *)&Param, 0, sizeof(Param)); + + Param.Para32[0] = PhysPortIndex; + Param.Para32[1] = -1; + + SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex], + SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); + + break; } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; + + VctGetResults(pAC, IoC, PhysPortIndex); + + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = -1; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, EventParam); + + /* SkEventDispatcher(pAC, IoC); */ } - - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param); - SkEventDispatcher(pAC, IoC); - } - - break; + + break; default: break; @@ -2092,33 +1609,30 @@ SK_EVPARA Param) /* Event dependent parameter */ * SkGePnmiPreSetVar, or SkGePnmiSetVar. * * Returns: - * SK_PNMI_ERR_XXX. For details have a look to the description of the + * SK_PNMI_ERR_XXX. For details have a look at the description of the * calling functions. * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist */ PNMI_STATIC int PnmiVar( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer which stores the mgmt data to be set */ -unsigned int *pLen, /* Total length of mgmt data */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* Total length of pBuf management data */ SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int TableIndex; int Ret; - if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_OID); } - - /* - * Check NetIndex - */ + + /* Check NetIndex. */ if (NetIndex >= pAC->Rlmt.NumNets) { return (SK_PNMI_ERR_UNKNOWN_NET); } @@ -2154,10 +1668,10 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ PNMI_STATIC int PnmiStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Set action to be performed */ -char *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +int Action, /* PRESET/SET action to be performed */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* Length of pBuf management data buffer */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int TableIndex; @@ -2168,28 +1682,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_U32 Instance; SK_U32 Id; - - /* Check if the passed buffer has the right size */ + /* Check if the passed buffer has the right size. */ if (*pLen < SK_PNMI_STRUCT_SIZE) { - /* Check if we can return the error within the buffer */ + /* Check if we can return the error within the buffer. */ if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1)); } *pLen = SK_PNMI_STRUCT_SIZE; return (SK_PNMI_ERR_TOO_SHORT); } - - /* - * Check NetIndex - */ + + /* Check NetIndex. */ if (NetIndex >= pAC->Rlmt.NumNets) { return (SK_PNMI_ERR_UNKNOWN_NET); } - + SK_PNMI_CHECKFLAGS("PnmiStruct: On call"); /* @@ -2213,12 +1723,11 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ pAC->Pnmi.RlmtUpdatedFlag ++; pAC->Pnmi.SirqUpdatedFlag ++; - /* Preset/Set values */ + /* PRESET/SET values. */ for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { if ((IdTable[TableIndex].Access != SK_PNMI_RW) && (IdTable[TableIndex].Access != SK_PNMI_WO)) { - continue; } @@ -2229,8 +1738,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ InstanceCnt ++) { DstOffset = IdTable[TableIndex].Offset + - (InstanceCnt - 1) * - IdTable[TableIndex].StructSize; + (InstanceCnt - 1) * IdTable[TableIndex].StructSize; /* * Because VPD multiple instance variables are @@ -2240,9 +1748,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ */ Instance = (SK_U32)InstanceCnt; - /* - * Evaluate needed buffer length - */ + /* Evaluate needed buffer length. */ Len = 0; Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET, IdTable[TableIndex].Id, @@ -2258,8 +1764,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ pAC->Pnmi.SirqUpdatedFlag --; SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, - SK_PNMI_ERR_GENERAL, DstOffset); + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_GENERAL, DstOffset); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (SK_PNMI_ERR_GENERAL); } @@ -2281,7 +1786,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } - /* Call the OID handler function */ + /* Call the OID handler function. */ Ret = IdTable[TableIndex].Func(pAC, IoC, Action, IdTable[TableIndex].Id, pBuf + DstOffset, &Len, Instance, TableIndex, NetIndex); @@ -2292,8 +1797,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ pAC->Pnmi.SirqUpdatedFlag --; SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, - DstOffset); + SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, DstOffset); *pLen = SK_PNMI_MIN_STRUCT_SIZE; return (SK_PNMI_ERR_BAD_VALUE); } @@ -2327,7 +1831,7 @@ SK_U32 Id) /* Object identifier to be searched */ if (IdTable[i].Id == Id) { - return i; + return (i); } } @@ -2352,32 +1856,29 @@ SK_U32 Id) /* Object identifier to be searched */ * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int OidStruct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { if (Id != OID_SKGE_ALL_DATA) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, - SK_PNMI_ERR003MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, SK_PNMI_ERR003MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } - /* - * Check instance. We only handle single instance variables - */ + /* Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; @@ -2419,27 +1920,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Perform( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; SK_U32 ActionOp; - - /* - * Check instance. We only handle single instance variables - */ + /* Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; @@ -2452,10 +1950,10 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_TOO_SHORT); } - /* Check if a get should be performed */ + /* Check if a GET should be performed. */ if (Action == SK_PNMI_GET) { - /* A get is easy. We always return the same value */ + /* A GET is easy. We always return the same value. */ ActionOp = (SK_U32)SK_PNMI_ACT_IDLE; SK_PNMI_STORE_U32(pBuf, ActionOp); *pLen = sizeof(SK_U32); @@ -2463,13 +1961,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_OK); } - /* Continue with PRESET/SET action */ + /* Continue with PRESET/SET action. */ if (*pLen > sizeof(SK_U32)) { return (SK_PNMI_ERR_BAD_VALUE); } - /* Check if the command is a known one */ + /* Check if the command is a known one. */ SK_PNMI_READ_U32(pBuf, ActionOp); if (*pLen > sizeof(SK_U32) || (ActionOp != SK_PNMI_ACT_IDLE && @@ -2481,7 +1979,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_BAD_VALUE); } - /* A preset ends here */ + /* A PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); @@ -2490,19 +1988,15 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ switch (ActionOp) { case SK_PNMI_ACT_IDLE: - /* Nothing to do */ + /* Nothing to do. */ break; case SK_PNMI_ACT_RESET: - /* - * Perform a driver reset or something that comes near - * to this. - */ + /* Perform a driver reset or something that comes near to this. */ Ret = SK_DRIVER_RESET(pAC, IoC); if (Ret != 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, - SK_PNMI_ERR005MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, SK_PNMI_ERR005MSG); return (SK_PNMI_ERR_GENERAL); } @@ -2519,13 +2013,12 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case SK_PNMI_ACT_RESETCNT: - /* Set all counters and timestamps to zero */ + /* Set all counters and timestamps to zero. */ ResetCounter(pAC, IoC, NetIndex); break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, - SK_PNMI_ERR006MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, SK_PNMI_ERR006MSG); return (SK_PNMI_ERR_GENERAL); } @@ -2550,46 +2043,40 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Mac8023Stat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; SK_U64 StatVal; SK_U32 StatVal32; SK_BOOL Is64BitReq = SK_FALSE; - /* - * Only the active Mac is returned - */ + /* Only the active MAC is returned. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } - /* - * Check action type - */ + /* Check action type. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - /* - * Check length - */ + /* Check length. */ switch (Id) { case OID_802_3_PERMANENT_ADDRESS: @@ -2610,14 +2097,12 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ #else /* SK_NDIS_64BIT_CTR */ - /* - * for compatibility, at least 32bit are required for oid - */ + /* For compatibility, at least 32 bits are required for OID. */ if (*pLen < sizeof(SK_U32)) { /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ + * Indicate handling for 64 bit values, + * if insufficient space is provided. + */ *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } @@ -2633,16 +2118,14 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * to indicate that an update was already done. */ Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if ( Ret != SK_PNMI_ERR_OK) { + if (Ret != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); } pAC->Pnmi.MacUpdatedFlag ++; - /* - * Get value (MAC Index 0 identifies the virtual MAC) - */ + /* Get value (MAC index 0 identifies the virtual MAC). */ switch (Id) { case OID_802_3_PERMANENT_ADDRESS: @@ -2658,9 +2141,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ default: StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex); - /* - * by default 32bit values are evaluated - */ + /* By default 32 bit values are evaluated. */ if (!Is64BitReq) { StatVal32 = (SK_U32)StatVal; SK_PNMI_STORE_U32(pBuf, StatVal32); @@ -2683,7 +2164,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX * * Description: - * Retrieves the XMAC statistic data. + * Retrieves the MAC statistic data. * * Returns: * SK_PNMI_ERR_OK The request was successfully performed. @@ -2692,42 +2173,41 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int MacPrivateStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int LogPortMax; unsigned int LogPortIndex; unsigned int PhysPortMax; unsigned int Limit; unsigned int Offset; + int MacType; int Ret; SK_U64 StatVal; - - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ + /* Calculate instance if wished. MAC index 0 is the virtual MAC. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); + + MacType = pAC->GIni.GIMacType; - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ LogPortMax--; } - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ + if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */ + /* Check instance range. */ if ((Instance < 1) || (Instance > LogPortMax)) { *pLen = 0; @@ -2737,25 +2217,20 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Limit = LogPortIndex + 1; } - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ + else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */ LogPortIndex = 0; Limit = LogPortMax; } - - /* - * Check action - */ + /* Check action. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - /* - * Check length - */ + /* Check length. */ if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) { *pLen = (Limit - LogPortIndex) * sizeof(SK_U64); @@ -2763,7 +2238,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } /* - * Update XMAC statistic and increment semaphore to indicate that + * Update MAC statistic and increment semaphore to indicate that * an update was already done. */ Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); @@ -2774,9 +2249,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } pAC->Pnmi.MacUpdatedFlag ++; - /* - * Get value - */ + /* Get value. */ Offset = 0; for (; LogPortIndex < Limit; LogPortIndex ++) { @@ -2791,51 +2264,44 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_GENERAL); */ case OID_SKGE_STAT_RX: - case OID_SKGE_STAT_TX: - switch (pAC->GIni.GIMacType) { - case SK_MAC_XMAC: + if (MacType == SK_MAC_GMAC) { + StatVal = + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_BROADCAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_MULTICAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_UNICAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HRX_UNDERSIZE, NetIndex); + } + else { StatVal = GetStatVal(pAC, IoC, LogPortIndex, IdTable[TableIndex].Param, NetIndex); - break; - - case SK_MAC_GMAC: - if (Id == OID_SKGE_STAT_TX) { - - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_UNICAST, NetIndex); - } - else { - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNDERSIZE, NetIndex); - } - break; - - default: - StatVal = 0; - break; } + break; - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); + case OID_SKGE_STAT_TX: + if (MacType == SK_MAC_GMAC) { + StatVal = + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HTX_BROADCAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HTX_MULTICAST, NetIndex) + + GetStatVal(pAC, IoC, LogPortIndex, + SK_PNMI_HTX_UNICAST, NetIndex); + } + else { + StatVal = GetStatVal(pAC, IoC, LogPortIndex, + IdTable[TableIndex].Param, NetIndex); + } break; default: StatVal = GetStatVal(pAC, IoC, LogPortIndex, IdTable[TableIndex].Param, NetIndex); - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - break; } + SK_PNMI_STORE_U64(pBuf + Offset, StatVal); Offset += sizeof(SK_U64); } @@ -2867,19 +2333,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Addr( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int LogPortMax; @@ -2889,19 +2355,16 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ unsigned int Limit; unsigned int Offset = 0; - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ + /* Calculate instance if wished. MAC index 0 is the virtual MAC. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ LogPortMax--; } - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ + if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */ + /* Check instance range. */ if ((Instance < 1) || (Instance > LogPortMax)) { *pLen = 0; @@ -2910,30 +2373,23 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); Limit = LogPortIndex + 1; } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ + else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */ LogPortIndex = 0; Limit = LogPortMax; } - /* - * Perform Action - */ + /* Perform action. */ if (Action == SK_PNMI_GET) { - /* - * Check length - */ + /* Check length. */ if (*pLen < (Limit - LogPortIndex) * 6) { *pLen = (Limit - LogPortIndex) * 6; return (SK_PNMI_ERR_TOO_SHORT); } - /* - * Get value - */ + /* Get value. */ for (; LogPortIndex < Limit; LogPortIndex ++) { switch (Id) { @@ -2957,8 +2413,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ &pAC->Addr.Net[NetIndex].PermanentMacAddress); } else { - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); CopyMac(pBuf + Offset, &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress); @@ -2967,8 +2422,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, - SK_PNMI_ERR008MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, SK_PNMI_ERR008MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -2979,8 +2433,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } else { /* - * The logical MAC address may not be changed only - * the physical ones + * The logical MAC address may not be changed, + * only the physical ones. */ if (Id == OID_SKGE_PHYS_FAC_ADDR) { @@ -2988,21 +2442,16 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_READ_ONLY); } - /* - * Only the current address may be changed - */ + /* Only the current address may be changed. */ if (Id != OID_SKGE_PHYS_CUR_ADDR) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, - SK_PNMI_ERR009MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, SK_PNMI_ERR009MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } - /* - * Check length - */ + /* Check length. */ if (*pLen < (Limit - LogPortIndex) * 6) { *pLen = (Limit - LogPortIndex) * 6; @@ -3014,32 +2463,26 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_BAD_VALUE); } - /* - * Check Action - */ + /* Check action. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; return (SK_PNMI_ERR_OK); } - /* - * Set OID_SKGE_MAC_CUR_ADDR - */ + /* Set OID_SKGE_MAC_CUR_ADDR. */ for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) { /* * A set to virtual port and set of broadcast - * address will be ignored + * address will be ignored. */ if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset, "\xff\xff\xff\xff\xff\xff", 6) == 0) { - continue; } - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, - LogPortIndex); + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); Ret = SkAddrOverride(pAC, IoC, PhysPortIndex, (SK_MAC_ADDR *)(pBuf + Offset), @@ -3073,29 +2516,26 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int CsumStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int Index; unsigned int Limit; unsigned int Offset = 0; SK_U64 StatVal; - - /* - * Calculate instance if wished - */ + /* Calculate instance if wished. */ if (Instance != (SK_U32)(-1)) { if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) { @@ -3111,27 +2551,21 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Limit = SKCS_NUM_PROTOCOLS; } - /* - * Check action - */ + /* Check action. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - /* - * Check length - */ + /* Check length. */ if (*pLen < (Limit - Index) * sizeof(SK_U64)) { *pLen = (Limit - Index) * sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } - /* - * Get value - */ + /* Get value. */ for (; Index < Limit; Index ++) { switch (Id) { @@ -3157,8 +2591,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, - SK_PNMI_ERR010MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, SK_PNMI_ERR010MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -3168,9 +2601,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Offset += sizeof(SK_U64); } - /* - * Store used buffer space - */ + /* Store used buffer space. */ *pLen = Offset; return (SK_PNMI_ERR_OK); @@ -3191,19 +2622,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int SensorStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int i; unsigned int Index; @@ -3213,10 +2644,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_U32 Val32; SK_U64 Val64; - - /* - * Calculate instance if wished - */ + /* Calculate instance if wished. */ if ((Instance != (SK_U32)(-1))) { if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) { @@ -3233,18 +2661,14 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Limit = (unsigned int) pAC->I2c.MaxSens; } - /* - * Check action - */ + /* Check action. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - /* - * Check length - */ + /* Check length. */ switch (Id) { case OID_SKGE_SENSOR_VALUE: @@ -3303,38 +2727,33 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, - SK_PNMI_ERR012MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, SK_PNMI_ERR012MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } - /* - * Get value - */ + /* Get value. */ for (Offset = 0; Index < Limit; Index ++) { switch (Id) { case OID_SKGE_SENSOR_INDEX: *(pBuf + Offset) = (char)Index; - Offset += sizeof(char); + Offset ++; break; case OID_SKGE_SENSOR_DESCR: Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc); - SK_MEMCPY(pBuf + Offset + 1, - pAC->I2c.SenTable[Index].SenDesc, Len); + SK_MEMCPY(pBuf + Offset + 1, pAC->I2c.SenTable[Index].SenDesc, Len); *(pBuf + Offset) = (char)Len; Offset += Len + 1; break; case OID_SKGE_SENSOR_TYPE: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenType; - Offset += sizeof(char); + *(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenType; + Offset ++; break; case OID_SKGE_SENSOR_VALUE: @@ -3371,9 +2790,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_SENSOR_STATUS: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenErrFlag; - Offset += sizeof(char); + *(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenErrFlag; + Offset ++; break; case OID_SKGE_SENSOR_WAR_CTS: @@ -3410,9 +2828,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } - /* - * Store used buffer space - */ + /* Store used buffer space. */ *pLen = Offset; return (SK_PNMI_ERR_OK); @@ -3438,19 +2854,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Vpd( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { SK_VPD_STATUS *pVpdStatus; unsigned int BufLen; @@ -3467,10 +2883,30 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_U32 Val32; /* - * Get array of all currently stored VPD keys - */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), - &KeyNo); + * VpdKeyReadError will be set in GetVpdKeyArr() if an error occurs. + * Due to the fact that some drivers use SkPnmiGetStruct() to retrieve + * all statistical data, an error in GetVpdKeyArr() will generate a PNMI + * error and terminate SkPnmiGetStruct() without filling in statistical + * data into the PNMI struct. In this case the driver will get no values + * for statistical purposes (netstat, ifconfig etc.). GetVpdKeyArr() is + * the first function to be called in SkPnmiGetStruct(), so any error + * will terminate SkPnmiGetStruct() immediately. Hence, VpdKeyReadError will + * be set during the first call to GetVpdKeyArr() to make successful calls + * to SkPnmiGetStruct() possible. But there is another point to consider: + * When filling in the statistical data into the PNMI struct, the VPD + * handler Vpd() will also be called. If GetVpdKeyArr() in Vpd() would + * return with SK_PNMI_ERR_GENERAL, SkPnmiGetStruct() would fail again. + * For this reason VpdKeyReadError is checked here and, if set, Vpd() + * will return without doing anything and the return value SK_PNMI_ERR_OK. + * Therefore SkPnmiGetStruct() is able to continue and fill in all other + * statistical data. + */ + if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) { + return (SK_PNMI_ERR_OK); + } + + /* Get array of all currently stored VPD keys. */ + Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo); if (Ret != SK_PNMI_ERR_OK) { *pLen = 0; return (Ret); @@ -3514,46 +2950,44 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } - /* - * Get value, if a query should be performed - */ + /* Get value, if a query should be performed. */ if (Action == SK_PNMI_GET) { switch (Id) { case OID_SKGE_VPD_FREE_BYTES: - /* Check length of buffer */ + /* Check length of buffer. */ if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } - /* Get number of free bytes */ + /* Get number of free bytes. */ pVpdStatus = VpdStat(pAC, IoC); if (pVpdStatus == NULL) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017, - SK_PNMI_ERR017MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR017MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018, - SK_PNMI_ERR018MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR018MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } - + Val32 = (SK_U32)pVpdStatus->vpd_free_rw; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_VPD_ENTRIES_LIST: - /* Check length */ + /* Check length. */ for (Len = 0, Index = 0; Index < KeyNo; Index ++) { Len += SK_STRLEN(KeyArr[Index]) + 1; @@ -3564,7 +2998,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_TOO_SHORT); } - /* Get value */ + /* Get value. */ *(pBuf) = (char)Len - 1; for (Offset = 1, Index = 0; Index < KeyNo; Index ++) { @@ -3583,7 +3017,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_VPD_ENTRIES_NUMBER: - /* Check length */ + /* Check length. */ if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); @@ -3596,7 +3030,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_VPD_KEY: - /* Check buffer length, if it is large enough */ + /* Check buffer length, if it is large enough. */ for (Len = 0, Index = FirstIndex; Index < LastIndex; Index ++) { @@ -3612,32 +3046,28 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * Get the key to an intermediate buffer, because * we have to prepend a length byte. */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { + for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { Len = SK_STRLEN(KeyArr[Index]); *(pBuf + Offset) = (char)Len; - SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], - Len); + SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], Len); Offset += Len + 1; } *pLen = Offset; break; case OID_SKGE_VPD_VALUE: - /* Check the buffer length if it is large enough */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { + /* Check the buffer length if it is large enough. */ + for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { BufLen = 256; if (VpdRead(pAC, IoC, KeyArr[Index], Buf, (int *)&BufLen) > 0 || BufLen >= SK_PNMI_VPD_DATALEN) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR021, - SK_PNMI_ERR021MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR021MSG)); return (SK_PNMI_ERR_GENERAL); } @@ -3653,17 +3083,15 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * Get the value to an intermediate buffer, because * we have to prepend a length byte. */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { + for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { BufLen = 256; if (VpdRead(pAC, IoC, KeyArr[Index], Buf, (int *)&BufLen) > 0 || BufLen >= SK_PNMI_VPD_DATALEN) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR022, - SK_PNMI_ERR022MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR022MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -3683,8 +3111,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_TOO_SHORT); } - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { + for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) { if (VpdMayWrite(KeyArr[Index])) { @@ -3710,15 +3137,15 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023, - SK_PNMI_ERR023MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR023MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } else { - /* The only OID which can be set is VPD_ACTION */ + /* The only OID which can be set is VPD_ACTION. */ if (Id != OID_SKGE_VPD_ACTION) { if (Id == OID_SKGE_VPD_FREE_BYTES || @@ -3732,8 +3159,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_READ_ONLY); } - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024, - SK_PNMI_ERR024MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR024MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -3749,14 +3176,11 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_TOO_SHORT); } - /* - * The first byte contains the VPD action type we should - * perform. - */ + /* The first byte contains the VPD action type we should perform. */ switch (*pBuf) { case SK_PNMI_VPD_IGNORE: - /* Nothing to do */ + /* Nothing to do. */ break; case SK_PNMI_VPD_CREATE: @@ -3788,13 +3212,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_MEMCPY(Buf, pBuf + 4, Offset); Buf[Offset] = 0; - /* A preset ends here */ + /* A PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } - /* Write the new entry or modify an existing one */ + /* Write the new entry or modify an existing one .*/ Ret = VpdWrite(pAC, IoC, KeyStr, Buf); if (Ret == SK_PNMI_VPD_NOWRITE ) { @@ -3803,8 +3227,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } else if (Ret != SK_PNMI_VPD_OK) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025, - SK_PNMI_ERR025MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR025MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -3817,8 +3241,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Ret = VpdUpdate(pAC, IoC); if (Ret != SK_PNMI_VPD_OK) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026, - SK_PNMI_ERR026MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR026MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -3826,7 +3250,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case SK_PNMI_VPD_DELETE: - /* Check if the buffer size is plausible */ + /* Check if the buffer size is plausible. */ if (*pLen < 3) { *pLen = 3; @@ -3841,7 +3265,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ KeyStr[1] = pBuf[2]; KeyStr[2] = 0; - /* Find the passed key in the array */ + /* Find the passed key in the array. */ for (Index = 0; Index < KeyNo; Index ++) { if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { @@ -3849,6 +3273,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; } } + /* * If we cannot find the key it is wrong, so we * return an appropriate error value. @@ -3864,12 +3289,12 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_OK); } - /* Ok, you wanted it and you will get it */ + /* Ok, you wanted it and you will get it. */ Ret = VpdDelete(pAC, IoC, KeyStr); if (Ret != SK_PNMI_VPD_OK) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027, - SK_PNMI_ERR027MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR027MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -3882,8 +3307,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Ret = VpdUpdate(pAC, IoC); if (Ret != SK_PNMI_VPD_OK) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028, - SK_PNMI_ERR028MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR028MSG)); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -3913,19 +3338,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int General( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ +char *pBuf, /* Buffer used for the management data transfer */ unsigned int *pLen, /* On call: buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int Index; @@ -3937,34 +3362,30 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_U32 Val32; SK_U64 Val64; SK_U64 Val64RxHwErrs = 0; + SK_U64 Val64RxRunt = 0; + SK_U64 Val64RxFcs = 0; SK_U64 Val64TxHwErrs = 0; SK_BOOL Is64BitReq = SK_FALSE; char Buf[256]; int MacType; - /* - * Check instance. We only handle single instance variables - */ + /* Check instance. We only handle single instance variables. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } - /* - * Check action. We only allow get requests. - */ + /* Check action. We only allow get requests. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - + MacType = pAC->GIni.GIMacType; - - /* - * Check length for the various supported OIDs - */ + + /* Check length for the various supported OIDs. */ switch (Id) { case OID_GEN_XMIT_ERROR: @@ -3978,14 +3399,12 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ #else /* SK_NDIS_64BIT_CTR */ - /* - * for compatibility, at least 32bit are required for oid - */ + /* For compatibility, at least 32bit are required for OID. */ if (*pLen < sizeof(SK_U32)) { /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ + * Indicate handling for 64bit values, + * if insufficient space is provided. + */ *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } @@ -4001,6 +3420,9 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ case OID_GEN_TRANSMIT_QUEUE_LENGTH: case OID_SKGE_TRAP_NUMBER: case OID_SKGE_MDB_VERSION: + case OID_SKGE_BOARDLEVEL: + case OID_SKGE_CHIPID: + case OID_SKGE_RAMSIZE: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); @@ -4021,6 +3443,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ case OID_SKGE_BUS_WIDTH: case OID_SKGE_SENSOR_NUMBER: case OID_SKGE_CHKSM_NUMBER: + case OID_SKGE_VAUXAVAIL: if (*pLen < sizeof(SK_U8)) { *pLen = sizeof(SK_U8); @@ -4052,11 +3475,11 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - /* Checked later */ + /* Checked later. */ break; } - /* Update statistic */ + /* Update statistics. */ if (Id == OID_SKGE_RX_HW_ERROR_CTS || Id == OID_SKGE_TX_HW_ERROR_CTS || Id == OID_SKGE_IN_ERRORS_CTS || @@ -4064,7 +3487,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Id == OID_GEN_XMIT_ERROR || Id == OID_GEN_RCV_ERROR) { - /* Force the XMAC to update its statistic counters and + /* + * Force the XMAC to update its statistic counters and * Increment semaphore to indicate that an update was * already done. */ @@ -4089,33 +3513,46 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Val64RxHwErrs = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex)+ + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex)+ + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); - break; + + + /* + * In some cases the runt and fcs counters are incremented when collisions + * occur. We have to correct those counters here. + */ + Val64RxRunt = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex); + Val64RxFcs = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex); + + if (Val64RxRunt > Val64RxFcs) { + Val64RxRunt -= Val64RxFcs; + Val64RxHwErrs += Val64RxRunt; + } + else { + Val64RxFcs -= Val64RxRunt; + Val64RxHwErrs += Val64RxFcs; + } + break; case OID_SKGE_TX_HW_ERROR_CTS: case OID_SKGE_OUT_ERROR_CTS: case OID_GEN_XMIT_ERROR: Val64TxHwErrs = GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex)+ - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex)+ + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) + + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) + GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex); break; } } - /* - * Retrieve value - */ + /* Retrieve value. */ switch (Id) { case OID_SKGE_SUPPORTED_LIST: @@ -4125,15 +3562,21 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ *pLen = Len; return (SK_PNMI_ERR_TOO_SHORT); } - for (Offset = 0, Index = 0; Offset < Len; - Offset += sizeof(SK_U32), Index ++) { + for (Offset = 0, Index = 0; Offset < Len; Index ++) { Val32 = (SK_U32)IdTable[Index].Id; SK_PNMI_STORE_U32(pBuf + Offset, Val32); + Offset += sizeof(SK_U32); } *pLen = Len; break; + case OID_SKGE_BOARDLEVEL: + Val32 = (SK_U32)pAC->GIni.GILevel; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + case OID_SKGE_PORT_NUMBER: Val32 = (SK_U32)pAC->GIni.GIMacsFound; SK_PNMI_STORE_U32(pBuf, Val32); @@ -4149,8 +3592,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ case OID_SKGE_DRIVER_DESCR: if (pAC->Pnmi.pDriverDescription == NULL) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, - SK_PNMI_ERR007MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, SK_PNMI_ERR007MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4159,8 +3601,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1; if (Len > SK_PNMI_STRINGLEN1) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, - SK_PNMI_ERR029MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, SK_PNMI_ERR029MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4179,8 +3620,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ case OID_SKGE_DRIVER_VERSION: if (pAC->Pnmi.pDriverVersion == NULL) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR030MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, SK_PNMI_ERR030MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4189,8 +3629,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1; if (Len > SK_PNMI_STRINGLEN1) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR031MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, SK_PNMI_ERR031MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4206,18 +3645,78 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ *pLen = Len; break; + case OID_SKGE_DRIVER_RELDATE: + if (pAC->Pnmi.pDriverReleaseDate == NULL) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR053, SK_PNMI_ERR053MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1; + if (Len > SK_PNMI_STRINGLEN1) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR054, SK_PNMI_ERR054MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + *pBuf = (char)(Len - 1); + SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1); + *pLen = Len; + break; + + case OID_SKGE_DRIVER_FILENAME: + if (pAC->Pnmi.pDriverFileName == NULL) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR055, SK_PNMI_ERR055MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1; + if (Len > SK_PNMI_STRINGLEN1) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR056, SK_PNMI_ERR056MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + + if (*pLen < Len) { + + *pLen = Len; + return (SK_PNMI_ERR_TOO_SHORT); + } + *pBuf = (char)(Len - 1); + SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1); + *pLen = Len; + break; + case OID_SKGE_HW_DESCR: /* * The hardware description is located in the VPD. This * query may move to the initialisation routine. But * the VPD data is cached and therefore a call here * will not make much difference. + * Please read comment in Vpd(). */ + if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) { + return (SK_PNMI_ERR_OK); + } + Len = 256; if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, - SK_PNMI_ERR032MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, SK_PNMI_ERR032MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4225,8 +3724,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Len ++; if (Len > SK_PNMI_STRINGLEN1) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, - SK_PNMI_ERR033MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, SK_PNMI_ERR033MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4242,7 +3740,6 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_HW_VERSION: - /* Oh, I love to do some string manipulation */ if (*pLen < 5) { *pLen = 5; @@ -4251,9 +3748,9 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Val8 = (SK_U8)pAC->GIni.GIPciHwRev; pBuf[0] = 4; pBuf[1] = 'v'; - pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F)); + pBuf[2] = (char)('0' | ((Val8 >> 4) & 0x0f)); pBuf[3] = '.'; - pBuf[4] = (char)(0x30 | (Val8 & 0x0F)); + pBuf[4] = (char)('0' | (Val8 & 0x0f)); *pLen = 5; break; @@ -4263,6 +3760,23 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ *pLen = sizeof(SK_U16); break; + case OID_SKGE_CHIPID: + Val32 = pAC->GIni.GIChipId; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_RAMSIZE: + Val32 = pAC->GIni.GIRamSize; + SK_PNMI_STORE_U32(pBuf, Val32); + *pLen = sizeof(SK_U32); + break; + + case OID_SKGE_VAUXAVAIL: + *pBuf = (char)pAC->GIni.GIVauxAvail; + *pLen = sizeof(char); + break; + case OID_SKGE_BUS_TYPE: *pBuf = (char)SK_PNMI_BUS_PCI; *pLen = sizeof(char); @@ -4313,35 +3827,35 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_RLMT_MONITOR_NUMBER: -/* XXX Not yet implemented by RLMT therefore we return zero elements */ + /* Not yet implemented by RLMT, therefore we return zero elements. */ Val32 = 0; SK_PNMI_STORE_U32(pBuf, Val32); *pLen = sizeof(SK_U32); break; case OID_SKGE_TX_SW_QUEUE_LEN: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + pAC->Pnmi.BufPort[1].TxSwQueueLen; - } + } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxSwQueueLen + pAC->Pnmi.Port[1].TxSwQueueLen; - } + } } SK_PNMI_STORE_U64(pBuf, Val64); *pLen = sizeof(SK_U64); @@ -4349,24 +3863,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ case OID_SKGE_TX_SW_QUEUE_MAX: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + pAC->Pnmi.BufPort[1].TxSwQueueMax; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxSwQueueMax + pAC->Pnmi.Port[1].TxSwQueueMax; @@ -4377,24 +3891,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_TX_RETRY: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + pAC->Pnmi.BufPort[1].TxRetryCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxRetryCts + pAC->Pnmi.Port[1].TxRetryCts; @@ -4405,24 +3919,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_RX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + pAC->Pnmi.BufPort[1].RxIntrCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxIntrCts + pAC->Pnmi.Port[1].RxIntrCts; @@ -4433,24 +3947,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_TX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + pAC->Pnmi.BufPort[1].TxIntrCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxIntrCts + pAC->Pnmi.Port[1].TxIntrCts; @@ -4461,24 +3975,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_RX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + pAC->Pnmi.BufPort[1].RxNoBufCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxNoBufCts + pAC->Pnmi.Port[1].RxNoBufCts; @@ -4489,24 +4003,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_TX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + pAC->Pnmi.BufPort[1].TxNoBufCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxNoBufCts + pAC->Pnmi.Port[1].TxNoBufCts; @@ -4517,24 +4031,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_TX_USED_DESCR_NO: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + pAC->Pnmi.BufPort[1].TxUsedDescrNo; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo + pAC->Pnmi.Port[1].TxUsedDescrNo; @@ -4545,24 +4059,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_RX_DELIVERED_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + pAC->Pnmi.BufPort[1].RxDeliveredCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxDeliveredCts + pAC->Pnmi.Port[1].RxDeliveredCts; @@ -4573,24 +4087,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_RX_OCTETS_DELIV_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts + pAC->Pnmi.Port[1].RxOctetsDeliveredCts; @@ -4611,13 +4125,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_IN_ERRORS_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[0].RxNoBufCts + @@ -4625,11 +4139,11 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = Val64RxHwErrs + pAC->Pnmi.Port[0].RxNoBufCts + @@ -4641,13 +4155,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_OUT_ERROR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[0].TxNoBufCts + @@ -4655,11 +4169,11 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = Val64TxHwErrs + pAC->Pnmi.Port[0].TxNoBufCts + @@ -4671,24 +4185,24 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_ERR_RECOVERY_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + pAC->Pnmi.BufPort[1].ErrRecoveryCts; } } else { - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; } - /* Single net mode */ + /* SingleNet mode. */ else { Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts + pAC->Pnmi.Port[1].ErrRecoveryCts; @@ -4712,7 +4226,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_GEN_RCV_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; } @@ -4721,7 +4235,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } /* - * by default 32bit values are evaluated + * By default 32bit values are evaluated. */ if (!Is64BitReq) { Val32 = (SK_U32)Val64; @@ -4735,7 +4249,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_GEN_XMIT_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; } @@ -4744,7 +4258,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } /* - * by default 32bit values are evaluated + * By default 32bit values are evaluated. */ if (!Is64BitReq) { Val32 = (SK_U32)Val64; @@ -4758,16 +4272,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_GEN_RCV_NO_BUFFER: - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ if (MacType == SK_MAC_XMAC) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; + Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex); + } else { - Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; + Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts + + GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex); } /* - * by default 32bit values are evaluated + * By default 32bit values are evaluated. */ if (!Is64BitReq) { Val32 = (SK_U32)Val64; @@ -4787,8 +4304,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, - SK_PNMI_ERR034MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, SK_PNMI_ERR034MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4824,19 +4340,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Rlmt( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { int Ret; unsigned int PhysPortIndex; @@ -4845,25 +4361,17 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_U32 Val32; SK_U64 Val64; - - /* - * Check instance. Only single instance OIDs are allowed here. - */ + /* Check instance. Only single instance OIDs are allowed here. */ if (Instance != (SK_U32)(-1) && Instance != 1) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } - /* - * Perform the requested action - */ + /* Perform the requested action. */ if (Action == SK_PNMI_GET) { - /* - * Check if the buffer length is large enough. - */ - + /* Check if the buffer length is large enough. */ switch (Id) { case OID_SKGE_RLMT_MODE: @@ -4896,8 +4404,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, - SK_PNMI_ERR035MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, SK_PNMI_ERR035MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -4916,9 +4423,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } pAC->Pnmi.RlmtUpdatedFlag ++; - /* - * Retrieve Value - */ + /* Retrieve value. */ switch (Id) { case OID_SKGE_RLMT_MODE: @@ -4996,17 +4501,17 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ pAC->Pnmi.RlmtUpdatedFlag --; } else { - /* Perform a preset or set */ + /* Perform a PRESET or SET. */ switch (Id) { case OID_SKGE_RLMT_MODE: - /* Check if the buffer length is plausible */ + /* Check if the buffer length is plausible. */ if (*pLen < sizeof(char)) { *pLen = sizeof(char); return (SK_PNMI_ERR_TOO_SHORT); } - /* Check if the value range is correct */ + /* Check if the value range is correct. */ if (*pLen != sizeof(char) || (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 || *(SK_U8 *)pBuf > 15) { @@ -5014,21 +4519,21 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } - /* The preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; return (SK_PNMI_ERR_OK); } - /* Send an event to RLMT to change the mode */ + /* Send an event to RLMT to change the mode. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + EventParam.Para32[0] |= (SK_U32)(*pBuf); EventParam.Para32[1] = 0; if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, EventParam) > 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, - SK_PNMI_ERR037MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, SK_PNMI_ERR037MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -5036,20 +4541,25 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_RLMT_PORT_PREFERRED: - /* Check if the buffer length is plausible */ + /* PRESET/SET action makes no sense in Dual Net mode. */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { + break; + } + + /* Check if the buffer length is plausible. */ if (*pLen < sizeof(char)) { *pLen = sizeof(char); return (SK_PNMI_ERR_TOO_SHORT); } - /* Check if the value range is correct */ + /* Check if the value range is correct. */ if (*pLen != sizeof(char) || *(SK_U8 *)pBuf > (SK_U8)pAC->GIni.GIMacsFound) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } - /* The preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; @@ -5062,13 +4572,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * make the decision which is the preferred port. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); + EventParam.Para32[0] = (SK_U32)(*pBuf) - 1; EventParam.Para32[1] = NetIndex; if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, EventParam) > 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, - SK_PNMI_ERR038MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, SK_PNMI_ERR038MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -5076,22 +4586,20 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_SKGE_RLMT_CHANGE_THRES: - /* Check if the buffer length is plausible */ + /* Check if the buffer length is plausible. */ if (*pLen < sizeof(SK_U64)) { *pLen = sizeof(SK_U64); return (SK_PNMI_ERR_TOO_SHORT); } - /* - * There are not many restrictions to the - * value range. - */ + + /* There are not many restrictions to the value range. */ if (*pLen != sizeof(SK_U64)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } - /* A preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { *pLen = 0; @@ -5106,7 +4614,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - /* The other OIDs are not be able for set */ + /* The other OIDs are not be able for set. */ *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } @@ -5129,19 +4637,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int RlmtStat( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int PhysPortMax; unsigned int PhysPortIndex; @@ -5151,54 +4659,49 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_U32 Val32; SK_U64 Val64; - /* - * Calculate the port indexes from the instance - */ + + /* Calculate the port indexes from the instance. */ PhysPortMax = pAC->GIni.GIMacsFound; if ((Instance != (SK_U32)(-1))) { - /* Check instance range */ + /* Check instance range. */ if ((Instance < 1) || (Instance > PhysPortMax)) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } - /* Single net mode */ + /* SingleNet mode. */ PhysPortIndex = Instance - 1; - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; } - /* Both net modes */ + /* Both net modes. */ Limit = PhysPortIndex + 1; } else { - /* Single net mode */ + /* SingleNet mode. */ PhysPortIndex = 0; Limit = PhysPortMax; - /* Dual net mode */ + /* DualNet mode. */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; Limit = PhysPortIndex + 1; } } - /* - * Currently only get requests are allowed. - */ + /* Currently only GET requests are allowed. */ if (Action != SK_PNMI_GET) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - /* - * Check if the buffer length is large enough. - */ + /* Check if the buffer length is large enough. */ switch (Id) { case OID_SKGE_RLMT_PORT_INDEX: @@ -5222,8 +4725,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, - SK_PNMI_ERR039MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, SK_PNMI_ERR039MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -5241,9 +4743,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } pAC->Pnmi.RlmtUpdatedFlag ++; - /* - * Get value - */ + /* Get value. */ Offset = 0; for (; PhysPortIndex < Limit; PhysPortIndex ++) { @@ -5331,19 +4831,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int MacPrivateConf( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int PhysPortMax; unsigned int PhysPortIndex; @@ -5352,24 +4852,25 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ unsigned int Limit; unsigned int Offset; char Val8; - int Ret; + char *pBufPtr; + int Ret; SK_EVPARA EventParam; SK_U32 Val32; +#ifdef SK_PHY_LP_MODE + SK_U8 CurrentPhyPowerState; +#endif /* SK_PHY_LP_MODE */ - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ + /* Calculate instance if wished. MAC index 0 is the virtual MAC. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ LogPortMax--; } - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ + if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */ + /* Check instance range. */ if ((Instance < 1) || (Instance > LogPortMax)) { *pLen = 0; @@ -5379,20 +4880,16 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Limit = LogPortIndex + 1; } - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ + else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */ LogPortIndex = 0; Limit = LogPortMax; } - /* - * Perform action - */ + /* Perform action. */ if (Action == SK_PNMI_GET) { - /* - * Check length - */ + /* Check length. */ switch (Id) { case OID_SKGE_PMD: @@ -5410,25 +4907,27 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ case OID_SKGE_SPEED_CAP: case OID_SKGE_SPEED_MODE: case OID_SKGE_SPEED_STATUS: +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: +#endif if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { - *pLen = (Limit - LogPortIndex) * - sizeof(SK_U8); + *pLen = (Limit - LogPortIndex) * sizeof(SK_U8); return (SK_PNMI_ERR_TOO_SHORT); } break; - case OID_SKGE_MTU: - if (*pLen < sizeof(SK_U32)) { + case OID_SKGE_MTU: + case OID_SKGE_PHY_TYPE: + if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) { - *pLen = sizeof(SK_U32); + *pLen = (Limit - LogPortIndex) * sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } break; default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, - SK_PNMI_ERR041MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, SK_PNMI_ERR041MSG); *pLen = 0; return (SK_PNMI_ERR_GENERAL); } @@ -5444,349 +4943,336 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } pAC->Pnmi.SirqUpdatedFlag ++; - /* - * Get value - */ + /* Get value. */ Offset = 0; for (; LogPortIndex < Limit; LogPortIndex ++) { + pBufPtr = pBuf + Offset; + switch (Id) { case OID_SKGE_PMD: - *(pBuf + Offset) = pAC->Pnmi.PMD; - Offset += sizeof(char); + *pBufPtr = pAC->Pnmi.PMD; + Offset ++; break; case OID_SKGE_CONNECTOR: - *(pBuf + Offset) = pAC->Pnmi.Connector; - Offset += sizeof(char); + *pBufPtr = pAC->Pnmi.Connector; + Offset ++; break; - case OID_SKGE_LINK_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + case OID_SKGE_PHY_TYPE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { + continue; + } + /* Get value for physical port. */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + Val32 = pAC->GIni.GP[PhysPortIndex].PhyType; + } + else { /* DualNet mode. */ + + Val32 = pAC->GIni.GP[NetIndex].PhyType; + } + SK_PNMI_STORE_U32(pBufPtr, Val32); + Offset += sizeof(SK_U32); + break; - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ + if (LogPortIndex == 0) { + continue; + } + /* Get value for physical port. */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + *pBufPtr = (SK_U8)pAC->GIni.GP[PhysPortIndex].PPhyPowerState; + } + else { /* DualNet mode. */ + + *pBufPtr = (SK_U8)pAC->GIni.GP[NetIndex].PPhyPowerState; + } + Offset += sizeof(SK_U8); + break; +#endif + + case OID_SKGE_LINK_CAP: + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ + if (LogPortIndex == 0) { + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical ports */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkCap; + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap; } - Offset += sizeof(char); } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkCap; - Offset += sizeof(char); + else { /* DualNet mode. */ + + *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap; } + Offset ++; break; case OID_SKGE_LINK_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical ports */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkModeConf; + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; } - Offset += sizeof(char); } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkModeConf; - Offset += sizeof(char); + else { /* DualNet mode. */ + + *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf; } + Offset ++; break; case OID_SKGE_LINK_MODE_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical port */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - *(pBuf + Offset) = - CalculateLinkModeStatus(pAC, - IoC, PhysPortIndex); + *pBufPtr = + CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); } - Offset += sizeof(char); } - else { /* DualNetMode */ - *(pBuf + Offset) = CalculateLinkModeStatus(pAC, IoC, NetIndex); - Offset += sizeof(char); + else { /* DualNet mode. */ + + *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex); } + Offset ++; break; case OID_SKGE_LINK_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical ports */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = - CalculateLinkStatus(pAC, - IoC, PhysPortIndex); + + *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex); } - Offset += sizeof(char); } - else { /* DualNetMode */ + else { /* DualNet mode. */ - *(pBuf + Offset) = CalculateLinkStatus(pAC, IoC, NetIndex); - Offset += sizeof(char); + *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex); } + Offset ++; break; case OID_SKGE_FLOWCTRL_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical ports */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PFlowCtrlCap; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; } - Offset += sizeof(char); } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlCap; - Offset += sizeof(char); + else { /* DualNet mode. */ + + *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap; } + Offset ++; break; case OID_SKGE_FLOWCTRL_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical port */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PFlowCtrlMode; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; } - Offset += sizeof(char); } - else { /* DualNetMode */ + else { /* DualNet mode. */ - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlMode; - Offset += sizeof(char); + *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode; } + Offset ++; break; case OID_SKGE_FLOWCTRL_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical port */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PFlowCtrlStatus; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; } - Offset += sizeof(char); } - else { /* DualNetMode */ + else { /* DualNet mode. */ - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; - Offset += sizeof(char); + *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; } + Offset ++; break; case OID_SKGE_PHY_OPERATION_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet Mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical ports */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PMSCap; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap; } - Offset += sizeof(char); } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSCap; - Offset += sizeof(char); + else { /* DualNet mode. */ + + *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap; } + Offset ++; break; case OID_SKGE_PHY_OPERATION_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical port */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PMSMode; + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode; } - Offset += sizeof(char); } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSMode; - Offset += sizeof(char); + else { /* DualNet mode. */ + + *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode; } + Offset ++; break; case OID_SKGE_PHY_OPERATION_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical port */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PMSStatus; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus; } - Offset += sizeof(char); } else { - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSStatus; - Offset += sizeof(char); + + *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus; } + Offset ++; break; case OID_SKGE_SPEED_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + - Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical ports */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkSpeedCap; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap; } - Offset += sizeof(char); } - else { /* DualNetMode */ - - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedCap; - Offset += sizeof(char); + else { /* DualNet mode. */ + + *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap; } + Offset ++; break; case OID_SKGE_SPEED_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical port */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkSpeed; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; } - Offset += sizeof(char); } - else { /* DualNetMode */ + else { /* DualNet mode. */ - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeed; - Offset += sizeof(char); + *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed; } + Offset ++; break; case OID_SKGE_SPEED_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ if (LogPortIndex == 0) { - - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBuf + Offset); + /* Get value for virtual port. */ + VirtualConf(pAC, IoC, Id, pBufPtr); } else { - /* Get value for physical port */ + /* Get value for physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( pAC, LogPortIndex); - - *(pBuf + Offset) = pAC->GIni.GP[ - PhysPortIndex].PLinkSpeedUsed; + + *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; } - Offset += sizeof(char); } - else { /* DualNetMode */ + else { /* DualNet mode. */ - *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; - Offset += sizeof(char); + *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; } + Offset ++; break; - + case OID_SKGE_MTU: Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex); - SK_PNMI_STORE_U32(pBuf + Offset, Val32); + SK_PNMI_STORE_U32(pBufPtr, Val32); Offset += sizeof(SK_U32); break; @@ -5826,38 +5312,41 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } break; - case OID_SKGE_MTU: - if (*pLen < sizeof(SK_U32)) { +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: + if (*pLen < Limit - LogPortIndex) { - *pLen = sizeof(SK_U32); + *pLen = Limit - LogPortIndex; return (SK_PNMI_ERR_TOO_SHORT); } - if (*pLen != sizeof(SK_U32)) { + break; +#endif /* SK_PHY_LP_MODE */ - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); + case OID_SKGE_MTU: + if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) { + + *pLen = (Limit - LogPortIndex) * sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); } break; - + default: *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - /* - * Perform preset or set - */ + /* Perform PRESET or SET. */ Offset = 0; for (; LogPortIndex < Limit; LogPortIndex ++) { + Val8 = *(pBuf + Offset); + switch (Id) { case OID_SKGE_LINK_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); + /* Check the value range. */ if (Val8 == 0) { - - Offset += sizeof(char); + Offset++; break; } if (Val8 < SK_LMODE_HALF || @@ -5868,51 +5357,68 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_BAD_VALUE); } - /* The preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } - if (LogPortIndex == 0) { + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ + if (LogPortIndex == 0) { + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with the new link mode to SIRQ. + */ + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new link mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; + if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + continue; + } + + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_LMODE, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR043, + SK_PNMI_ERR043MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + } /* for */ + } + else { + /* + * Send an event with the new link mode to + * the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_LMODE, + if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, EventParam) > 0) { - + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR043, SK_PNMI_ERR043MSG); - + *pLen = 0; return (SK_PNMI_ERR_GENERAL); } } } - else { + else { /* DualNet mode. */ + /* * Send an event with the new link mode to * the SIRQ module. */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); + EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, EventParam) > 0) { @@ -5925,15 +5431,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_GENERAL); } } - Offset += sizeof(char); + Offset++; break; case OID_SKGE_FLOWCTRL_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); + /* Check the value range. */ if (Val8 == 0) { - - Offset += sizeof(char); + Offset++; break; } if (Val8 < SK_FLOW_MODE_NONE || @@ -5944,30 +5448,48 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_BAD_VALUE); } - /* The preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } - if (LogPortIndex == 0) { + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ + if (LogPortIndex == 0) { + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with the new flow control mode to SIRQ. + */ + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { + if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + continue; + } - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_FLOWMODE, + EventParam) > 0) { - continue; + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR044, + SK_PNMI_ERR044MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } } - - EventParam.Para32[0] = PhysPortIndex; + } + else { + /* + * Send an event with the new flow control + * mode to the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE, @@ -5982,17 +5504,16 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } } - else { + else { /* DualNet mode. */ + /* - * Send an event with the new flow control - * mode to the SIRQ module. + * Send an event with the new link mode to + * the SIRQ module. */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); + EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_FLOWMODE, EventParam) - > 0) { + if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE, + EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR044, @@ -6002,15 +5523,14 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_GENERAL); } } - Offset += sizeof(char); + Offset++; break; case OID_SKGE_PHY_OPERATION_MODE : - /* Check the value range */ - Val8 = *(pBuf + Offset); + /* Check the value range. */ if (Val8 == 0) { - /* mode of this port remains unchanged */ - Offset += sizeof(char); + /* Mode of this port remains unchanged. */ + Offset++; break; } if (Val8 < SK_MS_MODE_AUTO || @@ -6021,34 +5541,51 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_BAD_VALUE); } - /* The preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } - if (LogPortIndex == 0) { + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ + if (LogPortIndex == 0) { + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with new master/slave (role) mode to SIRQ. + */ + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with new master/slave (role) mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { + if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + continue; + } - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_ROLE, + EventParam) > 0) { - continue; + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR042, + SK_PNMI_ERR042MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } } - - EventParam.Para32[0] = PhysPortIndex; + } + else { + /* + * Send an event with the new master/slave + * (role) mode to the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, - EventParam) > 0) { + SK_HWEV_SET_ROLE, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042, @@ -6059,16 +5596,16 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } } - else { + else { /* DualNet mode. */ + /* - * Send an event with the new master/slave - * (role) mode to the SIRQ module. + * Send an event with the new link mode to + * the SIRQ module. */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); + EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, EventParam) > 0) { + if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE, + EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042, @@ -6078,16 +5615,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_GENERAL); } } - - Offset += sizeof(char); + Offset++; break; case OID_SKGE_SPEED_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); + /* Check the value range. */ if (Val8 == 0) { - - Offset += sizeof(char); + Offset++; break; } if (Val8 < (SK_LSPEED_AUTO) || @@ -6098,29 +5632,49 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_BAD_VALUE); } - /* The preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } - if (LogPortIndex == 0) { + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ + if (LogPortIndex == 0) { - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { + /* + * The virtual port consists of all currently + * active ports. Find them and send an event + * with the new flow control mode to SIRQ. + */ + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; + PhysPortIndex ++) { - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { + continue; + } - continue; + EventParam.Para32[0] = PhysPortIndex; + EventParam.Para32[1] = (SK_U32)Val8; + if (SkGeSirqEvent(pAC, IoC, + SK_HWEV_SET_SPEED, + EventParam) > 0) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, + SK_PNMI_ERR045, + SK_PNMI_ERR045MSG); + + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } } - - EventParam.Para32[0] = PhysPortIndex; + } + else { + /* + * Send an event with the new flow control + * mode to the SIRQ module. + */ + EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( + pAC, LogPortIndex); EventParam.Para32[1] = (SK_U32)Val8; if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED, @@ -6135,16 +5689,15 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ } } } - else { + else { /* DualNet mode. */ + /* - * Send an event with the new flow control - * mode to the SIRQ module. + * Send an event with the new link mode to + * the SIRQ module. */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); + EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_SPEED, + if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED, EventParam) > 0) { SK_ERR_LOG(pAC, SK_ERRCL_SW, @@ -6155,23 +5708,25 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (SK_PNMI_ERR_GENERAL); } } - Offset += sizeof(char); + Offset++; break; - case OID_SKGE_MTU : - /* Check the value range */ - Val32 = *(SK_U32*)(pBuf + Offset); + case OID_SKGE_MTU: + /* Check the value range. */ + SK_PNMI_READ_U32((pBuf + Offset), Val32); + if (Val32 == 0) { - /* mtu of this port remains unchanged */ + /* MTU of this port remains unchanged. */ Offset += sizeof(SK_U32); break; } + if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } - /* The preset ends here */ + /* The PRESET ends here. */ if (Action == SK_PNMI_PRESET) { return (SK_PNMI_ERR_OK); } @@ -6183,9 +5738,72 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Offset += sizeof(SK_U32); break; +#ifdef SK_PHY_LP_MODE + case OID_SKGE_PHY_LP_MODE: + /* The PRESET ends here. */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */ + if (LogPortIndex == 0) { + Offset = 0; + continue; + } + } + /* Set value for physical port. */ + PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + CurrentPhyPowerState = pAC->GIni.GP[PhysPortIndex].PPhyPowerState; + + switch (Val8) { + case PHY_PM_OPERATIONAL_MODE: + /* If LowPowerMode is active, we can leave it. */ + if (CurrentPhyPowerState) { + + Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex); + + if ((CurrentPhyPowerState == PHY_PM_DEEP_SLEEP) || + (CurrentPhyPowerState == PHY_PM_IEEE_POWER_DOWN)) { + + SkDrvInitAdapter(pAC); + } + break; + } + else { + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + case PHY_PM_DEEP_SLEEP: + case PHY_PM_IEEE_POWER_DOWN: + /* If no LowPowerMode is active, we can enter it. */ + if (!CurrentPhyPowerState) { + SkDrvDeInitAdapter(pAC); + } + + case PHY_PM_ENERGY_DETECT: + case PHY_PM_ENERGY_DETECT_PLUS: + /* If no LowPowerMode is active, we can enter it. */ + if (!CurrentPhyPowerState) { + + Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf); + break; + } + else { + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); + } + default: + *pLen = 0; + return (SK_PNMI_ERR_BAD_VALUE); + } + Offset++; + break; +#endif /* SK_PHY_LP_MODE */ + default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("MacPrivateConf: Unknown OID should be handled before set")); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, + ("MacPrivateConf: Unknown OID should be handled before set")); *pLen = 0; return (SK_PNMI_ERR_GENERAL); @@ -6213,32 +5831,29 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * value range. * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter. */ PNMI_STATIC int Monitor( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ { unsigned int Index; unsigned int Limit; unsigned int Offset; unsigned int Entries; - - - /* - * Calculate instance if wished. - */ -/* XXX Not yet implemented. Return always an empty table. */ + + /* Not implemented yet. Return always an empty table. */ Entries = 0; + /* Calculate instance if wished. */ if ((Instance != (SK_U32)(-1))) { if ((Instance < 1) || (Instance > Entries)) { @@ -6255,12 +5870,10 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ Limit = Entries; } - /* - * Get/Set value - */ + /* GET/SET value. */ if (Action == SK_PNMI_GET) { - for (Offset=0; Index < Limit; Index ++) { + for (Offset = 0; Index < Limit; Index ++) { switch (Id) { @@ -6282,32 +5895,29 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ *pLen = Offset; } else { - /* Only MONITOR_ADMIN can be set */ + /* Only MONITOR_ADMIN can be set. */ if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) { *pLen = 0; return (SK_PNMI_ERR_READ_ONLY); } - /* Check if the length is plausible */ + /* Check if the length is plausible. */ if (*pLen < (Limit - Index)) { return (SK_PNMI_ERR_TOO_SHORT); } - /* Okay, we have a wide value range */ + /* Okay, we have a wide value range. */ if (*pLen != (Limit - Index)) { *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } -/* - for (Offset=0; Index < Limit; Index ++) { - } -*/ -/* - * XXX Not yet implemented. Return always BAD_VALUE, because the table - * is empty. - */ + + /* + * Not yet implemented. Return always BAD_VALUE, + * because the table is empty. + */ *pLen = 0; return (SK_PNMI_ERR_BAD_VALUE); } @@ -6335,24 +5945,25 @@ PNMI_STATIC void VirtualConf( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf) /* Buffer to which to mgmt data will be retrieved */ +char *pBuf) /* Buffer used for the management data transfer */ { unsigned int PhysPortMax; unsigned int PhysPortIndex; SK_U8 Val8; + SK_U32 Val32; SK_BOOL PortActiveFlag; - + SK_GEPORT *pPrt; *pBuf = 0; PortActiveFlag = SK_FALSE; PhysPortMax = pAC->GIni.GIMacsFound; + + for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { + pPrt = &pAC->GIni.GP[PhysPortIndex]; - /* Check if the physical port is active */ + /* Check if the physical port is active. */ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - continue; } @@ -6360,6 +5971,15 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ switch (Id) { + case OID_SKGE_PHY_TYPE: + /* Check if it is the first active port. */ + if (*pBuf == 0) { + Val32 = pPrt->PhyType; + SK_PNMI_STORE_U32(pBuf, Val32); + continue; + } + break; + case OID_SKGE_LINK_CAP: /* @@ -6368,34 +5988,32 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ * From a curious point of view the virtual port * is capable of all found capabilities. */ - *pBuf |= pAC->GIni.GP[PhysPortIndex].PLinkCap; + *pBuf |= pPrt->PLinkCap; break; case OID_SKGE_LINK_MODE: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; + *pBuf = pPrt->PLinkModeConf; continue; } /* - * If we find an active port with a different link - * mode than the first one we return a value that - * indicates that the link mode is indeterminated. + * If we find an active port with a different link mode + * than the first one we return indeterminated. */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkModeConf - ) { + if (*pBuf != pPrt->PLinkModeConf) { *pBuf = SK_LMODE_INDETERMINATED; } break; case OID_SKGE_LINK_MODE_STATUS: - /* Get the link mode of the physical port */ + /* Get the link mode of the physical port. */ Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = Val8; @@ -6403,10 +6021,8 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ } /* - * If we find an active port with a different link - * mode status than the first one we return a value - * that indicates that the link mode status is - * indeterminated. + * If we find an active port with a different link mode status + * than the first one we return indeterminated. */ if (*pBuf != Val8) { @@ -6415,10 +6031,10 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ break; case OID_SKGE_LINK_STATUS: - /* Get the link status of the physical port */ + /* Get the link status of the physical port. */ Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex); - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { *pBuf = Val8; @@ -6426,10 +6042,8 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ } /* - * If we find an active port with a different link - * status than the first one, we return a value - * that indicates that the link status is - * indeterminated. + * If we find an active port with a different link status + * than the first one we return indeterminated. */ if (*pBuf != Val8) { @@ -6438,10 +6052,10 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ break; case OID_SKGE_FLOWCTRL_CAP: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; + *pBuf = pPrt->PFlowCtrlCap; continue; } @@ -6449,53 +6063,50 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ * From a curious point of view the virtual port * is capable of all found capabilities. */ - *pBuf |= pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; + *pBuf |= pPrt->PFlowCtrlCap; break; case OID_SKGE_FLOWCTRL_MODE: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; + *pBuf = pPrt->PFlowCtrlMode; continue; } /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. + * If we find an active port with a different flow-control mode + * than the first one we return indeterminated. */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode) { + if (*pBuf != pPrt->PFlowCtrlMode) { *pBuf = SK_FLOW_MODE_INDETERMINATED; } break; case OID_SKGE_FLOWCTRL_STATUS: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; + *pBuf = pPrt->PFlowCtrlStatus; continue; } /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. + * If we find an active port with a different flow-control status + * than the first one we return indeterminated. */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus) { + if (*pBuf != pPrt->PFlowCtrlStatus) { *pBuf = SK_FLOW_STAT_INDETERMINATED; } break; - + case OID_SKGE_PHY_OPERATION_CAP: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PMSCap; + *pBuf = pPrt->PMSCap; continue; } @@ -6503,82 +6114,76 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ * From a curious point of view the virtual port * is capable of all found capabilities. */ - *pBuf |= pAC->GIni.GP[PhysPortIndex].PMSCap; + *pBuf |= pPrt->PMSCap; break; case OID_SKGE_PHY_OPERATION_MODE: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PMSMode; + *pBuf = pPrt->PMSMode; continue; } /* - * If we find an active port with a different master/ - * slave mode than the first one, we return a value - * that indicates that the mode is indeterminated. + * If we find an active port with a different master/slave mode + * than the first one we return indeterminated. */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSMode) { + if (*pBuf != pPrt->PMSMode) { *pBuf = SK_MS_MODE_INDETERMINATED; } break; case OID_SKGE_PHY_OPERATION_STATUS: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PMSStatus; + *pBuf = pPrt->PMSStatus; continue; } /* - * If we find an active port with a different master/ - * slave status than the first one, we return a - * value that indicates that the status is - * indeterminated. + * If we find an active port with a different master/slave status + * than the first one we return indeterminated. */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSStatus) { + if (*pBuf != pPrt->PMSStatus) { *pBuf = SK_MS_STAT_INDETERMINATED; } break; - + case OID_SKGE_SPEED_MODE: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; + *pBuf = pPrt->PLinkSpeed; continue; } /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. + * If we find an active port with a different link speed + * than the first one we return indeterminated. */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeed) { + if (*pBuf != pPrt->PLinkSpeed) { *pBuf = SK_LSPEED_INDETERMINATED; } break; - + case OID_SKGE_SPEED_STATUS: - /* Check if it is the first active port */ + /* Check if it is the first active port. */ if (*pBuf == 0) { - *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; + *pBuf = pPrt->PLinkSpeedUsed; continue; } /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. + * If we find an active port with a different link speed used + * than the first one we return indeterminated. */ - if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed) { + if (*pBuf != pPrt->PLinkSpeedUsed) { *pBuf = SK_LSPEED_STAT_INDETERMINATED; } @@ -6586,9 +6191,7 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ } } - /* - * If no port is active return an indeterminated answer - */ + /* If no port is active return an indeterminated answer. */ if (!PortActiveFlag) { switch (Id) { @@ -6617,7 +6220,7 @@ char *pBuf) /* Buffer to which to mgmt data will be retrieved */ case OID_SKGE_FLOWCTRL_STATUS: *pBuf = SK_FLOW_STAT_INDETERMINATED; break; - + case OID_SKGE_PHY_OPERATION_CAP: *pBuf = SK_MS_CAP_INDETERMINATED; break; @@ -6666,7 +6269,6 @@ unsigned int PhysPortIndex) /* Physical port index */ { SK_U8 Result; - if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) { Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN; @@ -6706,17 +6308,15 @@ unsigned int PhysPortIndex) /* Physical port index */ { SK_U8 Result; - - /* Get the current mode, which can be full or half duplex */ + /* Get the current mode, which can be full or half duplex. */ Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus; - /* Check if no valid mode could be found (link is down) */ + /* Check if no valid mode could be found (link is down). */ if (Result < SK_LMODE_STAT_HALF) { Result = SK_LMODE_STAT_UNKNOWN; } else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) { - /* * Auto-negotiation was used to bring up the link. Change * the already found duplex status that it indicates @@ -6761,22 +6361,22 @@ unsigned int *pKeyNo) /* Number of keys */ int Index; int Ret; - SK_MEMSET(pKeyArr, 0, KeyArrLen); - /* - * Get VPD key list - */ - Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen, + /* Get VPD key list. */ + Ret = VpdKeys(pAC, IoC, BufKeys, (int *)&BufKeysLen, (int *)pKeyNo); + if (Ret > 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014, - SK_PNMI_ERR014MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR014MSG)); + /* Please read comment in Vpd(). */ + pAC->Pnmi.VpdKeyReadError = SK_TRUE; return (SK_PNMI_ERR_GENERAL); } - /* If no keys are available return now */ + /* If no keys are available return now. */ if (*pKeyNo == 0 || BufKeysLen == 0) { return (SK_PNMI_ERR_OK); @@ -6784,12 +6384,12 @@ unsigned int *pKeyNo) /* Number of keys */ /* * If the key list is too long for us trunc it and give a * errorlog notification. This case should not happen because - * the maximum number of keys is limited due to RAM limitations + * the maximum number of keys is limited due to RAM limitations. */ if (*pKeyNo > SK_PNMI_VPD_ENTRIES) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015, - SK_PNMI_ERR015MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR015MSG)); *pKeyNo = SK_PNMI_VPD_ENTRIES; } @@ -6802,14 +6402,14 @@ unsigned int *pKeyNo) /* Number of keys */ Offset ++) { if (BufKeys[Offset] != 0) { - continue; } if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016, - SK_PNMI_ERR016MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, + (SK_PNMI_ERR016MSG)); + return (SK_PNMI_ERR_GENERAL); } @@ -6820,7 +6420,7 @@ unsigned int *pKeyNo) /* Number of keys */ StartOffset = Offset + 1; } - /* Last key not zero terminated? Get it anyway */ + /* Last key not zero terminated? Get it anyway. */ if (StartOffset < Offset) { SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, @@ -6849,19 +6449,18 @@ SK_IOC IoC) /* IO context handle */ { SK_EVPARA EventParam; - /* Was the module already updated during the current PNMI call? */ if (pAC->Pnmi.SirqUpdatedFlag > 0) { return (SK_PNMI_ERR_OK); } - /* Send an synchronuous update event to the module */ + /* Send an synchronuous update event to the module. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) { + + if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam)) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, - SK_PNMI_ERR047MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, SK_PNMI_ERR047MSG); return (SK_PNMI_ERR_GENERAL); } @@ -6889,21 +6488,19 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ { SK_EVPARA EventParam; - /* Was the module already updated during the current PNMI call? */ if (pAC->Pnmi.RlmtUpdatedFlag > 0) { return (SK_PNMI_ERR_OK); } - /* Send an synchronuous update event to the module */ + /* Send an synchronuous update event to the module. */ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)-1; if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, - SK_PNMI_ERR048MSG); + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, SK_PNMI_ERR048MSG); return (SK_PNMI_ERR_GENERAL); } @@ -6917,8 +6514,8 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * * Description: * The XMAC holds its statistic internally. To obtain the current - * values we send a command so that the statistic data will - * be written to apredefined memory area on the adapter. + * values we must send a command so that the statistic data will + * be written to a predefined memory area on the adapter. * * Returns: * SK_PNMI_ERR_OK Task successfully performed. @@ -6941,20 +6538,20 @@ unsigned int LastMac) /* Index of the last Mac to be updated */ return (SK_PNMI_ERR_OK); } - /* Send an update command to all MACs specified */ + /* Send an update command to all MACs specified. */ for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) { /* - * 2002-09-13 pweber: Freeze the current sw counters. + * 2002-09-13 pweber: Freeze the current SW counters. * (That should be done as close as * possible to the update of the - * hw counters) + * HW counters). */ if (pAC->GIni.GIMacType == SK_MAC_XMAC) { pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex]; } - - /* 2002-09-13 pweber: Update the hw counter */ + + /* 2002-09-13 pweber: Update the HW counter. */ if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) { return (SK_PNMI_ERR_GENERAL); @@ -6992,34 +6589,35 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ SK_U64 Val = 0; - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ + if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */ PhysPortIndex = NetIndex; + Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); } - else { /* Single Net mode */ + else { /* SingleNet mode. */ if (LogPortIndex == 0) { PhysPortMax = pAC->GIni.GIMacsFound; - /* Add counter of all active ports */ + /* Add counter of all active ports. */ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) { if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, - StatIndex); + Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); } } - /* Correct value because of port switches */ + /* Correct value because of port switches. */ Val += pAC->Pnmi.VirtualCounterOffset[StatIndex]; } else { - /* Get counter value of physical port */ + /* Get counter value of physical port. */ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); + Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); } } @@ -7053,33 +6651,68 @@ unsigned int StatIndex) /* Index to statistic value */ SK_U32 HighVal = 0; SK_U16 Word; int MacType; - + unsigned int HelpIndex; + SK_GEPORT *pPrt; + SK_PNMI_PORT *pPnmiPrt; SK_GEMACFUNC *pFnMac; - + + pPrt = &pAC->GIni.GP[PhysPortIndex]; + MacType = pAC->GIni.GIMacType; - - /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ - if (pAC->GIni.GIMacType == SK_MAC_XMAC) { + + /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */ + if (MacType == SK_MAC_XMAC) { pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex]; } else { pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex]; } - + pFnMac = &pAC->GIni.GIFunc; switch (StatIndex) { case SK_PNMI_HTX: - case SK_PNMI_HRX: - /* Not supported by GMAC */ if (MacType == SK_MAC_GMAC) { - return (Val); + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg, + &LowVal); + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg, + &HighVal); + LowVal += HighVal; + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg, + &HighVal); + LowVal += HighVal; + } + else { + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); + } + HighVal = pPnmiPrt->CounterHigh[StatIndex]; + break; + + case SK_PNMI_HRX: + if (MacType == SK_MAC_GMAC) { + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg, + &LowVal); + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg, + &HighVal); + LowVal += HighVal; + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg, + &HighVal); + LowVal += HighVal; + } + else { + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, + StatAddr[StatIndex][MacType].Reg, + &LowVal); } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; @@ -7096,7 +6729,7 @@ unsigned int StatIndex) /* Index to statistic value */ case SK_PNMI_HTX_BURST: case SK_PNMI_HTX_EXCESS_DEF: case SK_PNMI_HTX_CARRIER: - /* Not supported by GMAC */ + /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { return (Val); } @@ -7108,22 +6741,24 @@ unsigned int StatIndex) /* Index to statistic value */ break; case SK_PNMI_HTX_MACC: - /* GMAC only supports PAUSE MAC control frames */ + /* GMAC only supports PAUSE MAC control frames. */ if (MacType == SK_MAC_GMAC) { - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, SK_PNMI_HTX_PMACC); - - return (Val); + HelpIndex = SK_PNMI_HTX_PMACC; } - + else { + HelpIndex = StatIndex; + } + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); + StatAddr[HelpIndex][MacType].Reg, + &LowVal); + HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; case SK_PNMI_HTX_COL: case SK_PNMI_HRX_UNDERSIZE: - /* Not supported by XMAC */ + /* Not supported by XMAC. */ if (MacType == SK_MAC_XMAC) { return (Val); } @@ -7134,21 +6769,20 @@ unsigned int StatIndex) /* Index to statistic value */ HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; - case SK_PNMI_HTX_DEFFERAL: - /* Not supported by GMAC */ + /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { return (Val); } - + /* * XMAC counts frames with deferred transmission * even in full-duplex mode. * * In full-duplex mode the counter remains constant! */ - if ((pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || - (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_FULL)) { + if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || + (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) { LowVal = 0; HighVal = 0; @@ -7156,14 +6790,14 @@ unsigned int StatIndex) /* Index to statistic value */ else { /* Otherwise get contents of hardware register. */ (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_DEFFERAL][MacType].Reg, + StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; } break; case SK_PNMI_HRX_BADOCTET: - /* Not supported by XMAC */ + /* Not supported by XMAC. */ if (MacType == SK_MAC_XMAC) { return (Val); } @@ -7173,7 +6807,7 @@ unsigned int StatIndex) /* Index to statistic value */ &HighVal); (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex + 1][MacType].Reg, - &LowVal); + &LowVal); break; case SK_PNMI_HTX_OCTETLOW: @@ -7182,32 +6816,30 @@ unsigned int StatIndex) /* Index to statistic value */ return (Val); case SK_PNMI_HRX_LONGFRAMES: - /* For XMAC the SW counter is managed by PNMI */ + /* For XMAC the SW counter is managed by PNMI. */ if (MacType == SK_MAC_XMAC) { return (pPnmiPrt->StatRxLongFrameCts); } - + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; - + case SK_PNMI_HRX_TOO_LONG: (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, + StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; - + Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - switch (MacType) { - case SK_MAC_GMAC: - /* For GMAC the SW counter is additionally managed by PNMI */ + if (MacType == SK_MAC_GMAC) { + /* For GMAC the SW counter is additionally managed by PNMI. */ Val += pPnmiPrt->StatRxFrameTooLongCts; - break; - - case SK_MAC_XMAC: + } + else { /* * Frames longer than IEEE 802.3 frame max size are counted * by XMAC in frame_too_long counter even reception of long @@ -7215,31 +6847,26 @@ unsigned int StatIndex) /* Index to statistic value */ * So correct the value by subtracting RxLongFrame counter. */ Val -= pPnmiPrt->StatRxLongFrameCts; - break; - - default: - break; } LowVal = (SK_U32)Val; HighVal = (SK_U32)(Val >> 32); break; - + case SK_PNMI_HRX_SHORTS: - /* Not supported by GMAC */ + /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { /* GM_RXE_FRAG?? */ return (Val); } - + /* - * XMAC counts short frame errors even if link down (#10620) - * - * If link-down the counter remains constant + * XMAC counts short frame errors even if link down (#10620). + * If the link is down, the counter remains constant. */ - if (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { + if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { - /* Otherwise get incremental difference */ + /* Otherwise get incremental difference. */ (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); @@ -7262,9 +6889,8 @@ unsigned int StatIndex) /* Index to statistic value */ case SK_PNMI_HRX_IRLENGTH: case SK_PNMI_HRX_SYMBOL: case SK_PNMI_HRX_CEXT: - /* Not supported by GMAC */ + /* Not supported by GMAC. */ if (MacType == SK_MAC_GMAC) { - /* GM_RXE_FRAG?? */ return (Val); } @@ -7275,24 +6901,24 @@ unsigned int StatIndex) /* Index to statistic value */ break; case SK_PNMI_HRX_PMACC_ERR: - /* For GMAC the SW counter is managed by PNMI */ + /* For GMAC the SW counter is managed by PNMI. */ if (MacType == SK_MAC_GMAC) { return (pPnmiPrt->StatRxPMaccErr); } - + (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, StatAddr[StatIndex][MacType].Reg, &LowVal); HighVal = pPnmiPrt->CounterHigh[StatIndex]; break; - /* SW counter managed by PNMI */ + /* SW counter managed by PNMI. */ case SK_PNMI_HTX_SYNC: LowVal = (SK_U32)pPnmiPrt->StatSyncCts; HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32); break; - /* SW counter managed by PNMI */ + /* SW counter managed by PNMI. */ case SK_PNMI_HTX_SYNC_OCTET: LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts; HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32); @@ -7300,19 +6926,19 @@ unsigned int StatIndex) /* Index to statistic value */ case SK_PNMI_HRX_FCS: /* - * Broadcom filters fcs errors and counts it in - * Receive Error Counter register + * Broadcom filters FCS errors and counts them in + * Receive Error Counter register. */ - if (pAC->GIni.GP[PhysPortIndex].PhyType == SK_PHY_BCOM) { - /* do not read while not initialized (PHY_READ hangs!)*/ - if (pAC->GIni.GP[PhysPortIndex].PState) { - PHY_READ(IoC, &pAC->GIni.GP[PhysPortIndex], - PhysPortIndex, PHY_BCOM_RE_CTR, - &Word); - + if (pPrt->PhyType == SK_PHY_BCOM) { +#ifdef GENESIS + /* Do not read while not initialized (PHY_READ hangs!). */ + if (pPrt->PState != SK_PRT_RESET) { + SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word); + LowVal = Word; } HighVal = pPnmiPrt->CounterHigh[StatIndex]; +#endif /* GENESIS */ } else { (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, @@ -7332,7 +6958,7 @@ unsigned int StatIndex) /* Index to statistic value */ Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - /* Correct value because of possible XMAC reset. XMAC Errata #2 */ + /* Correct value because of possible XMAC reset (XMAC Errata #2). */ Val += pPnmiPrt->CounterOffset[StatIndex]; return (Val); @@ -7357,30 +6983,29 @@ SK_U32 NetIndex) unsigned int PhysPortIndex; SK_EVPARA EventParam; - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - /* Notify sensor module */ + /* Notify sensor module. */ SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam); - /* Notify RLMT module */ + /* Notify RLMT module. */ EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)-1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam); EventParam.Para32[1] = 0; - /* Notify SIRQ module */ + /* Notify SIRQ module. */ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam); - /* Notify CSUM module */ + /* Notify CSUM module. */ #ifdef SK_USE_CSUM EventParam.Para32[0] = NetIndex; EventParam.Para32[1] = (SK_U32)-1; SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS, EventParam); -#endif - - /* Clear XMAC statistic */ +#endif /* SK_USE_CSUM */ + + /* Clear XMAC statistics. */ for (PhysPortIndex = 0; PhysPortIndex < (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) { @@ -7407,13 +7032,13 @@ SK_U32 NetIndex) PhysPortIndex].StatRxPMaccErr)); } - /* - * Clear local statistics - */ + /* Clear local statistics. */ SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0, sizeof(pAC->Pnmi.VirtualCounterOffset)); + pAC->Pnmi.RlmtChangeCts = 0; pAC->Pnmi.RlmtChangeTime = 0; + SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0, sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue)); pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0; @@ -7450,23 +7075,21 @@ SK_AC *pAC, /* Pointer to adapter context */ SK_U32 TrapId, /* SNMP ID of the trap */ unsigned int Size) /* Space needed for trap entry */ { - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int BufFree = pAC->Pnmi.TrapBufFree; - unsigned int Beg = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; + unsigned int BufPad = pAC->Pnmi.TrapBufPad; + unsigned int BufFree = pAC->Pnmi.TrapBufFree; + unsigned int Beg = pAC->Pnmi.TrapQueueBeg; + unsigned int End = pAC->Pnmi.TrapQueueEnd; char *pBuf = &pAC->Pnmi.TrapBuf[0]; int Wrap; - unsigned int NeededSpace; - unsigned int EntrySize; + unsigned int NeededSpace; + unsigned int EntrySize; SK_U32 Val32; SK_U64 Val64; - - /* Last byte of entry will get a copy of the entry length */ + /* Last byte of entry will get a copy of the entry length. */ Size ++; - /* - * Calculate needed buffer space */ + /* Calculate needed buffer space. */ if (Beg >= Size) { NeededSpace = Size; @@ -7481,7 +7104,7 @@ unsigned int Size) /* Space needed for trap entry */ * Check if enough buffer space is provided. Otherwise * free some entries. Leave one byte space between begin * and end of buffer to make it possible to detect whether - * the buffer is full or empty + * the buffer is full or empty. */ while (BufFree < NeededSpace + 1) { @@ -7495,11 +7118,11 @@ unsigned int Size) /* Space needed for trap entry */ End -= EntrySize; #ifdef DEBUG SK_MEMSET(pBuf + End, (char)(-1), EntrySize); -#endif +#endif /* DEBUG */ if (End == BufPad) { #ifdef DEBUG SK_MEMSET(pBuf, (char)(-1), End); -#endif +#endif /* DEBUG */ BufFree += End; End = 0; BufPad = 0; @@ -7520,13 +7143,13 @@ unsigned int Size) /* Space needed for trap entry */ } BufFree -= NeededSpace; - /* Save the current offsets */ + /* Save the current offsets. */ pAC->Pnmi.TrapQueueBeg = Beg; pAC->Pnmi.TrapQueueEnd = End; pAC->Pnmi.TrapBufPad = BufPad; pAC->Pnmi.TrapBufFree = BufFree; - /* Initialize the trap entry */ + /* Initialize the trap entry. */ *(pBuf + Beg + Size - 1) = (char)Size; *(pBuf + Beg) = (char)Size; Val32 = (pAC->Pnmi.TrapUnique) ++; @@ -7561,7 +7184,6 @@ char *pDstBuf) /* Buffer to which the queued traps will be copied */ unsigned int Len; unsigned int DstOff = 0; - while (Trap != End) { Len = (unsigned int)*(pBuf + Trap); @@ -7606,7 +7228,6 @@ unsigned int *pEntries) /* Returns number of trapes stored in queue */ unsigned int Entries = 0; unsigned int TotalLen = 0; - while (Trap != End) { Len = (unsigned int)*(pBuf + Trap); @@ -7663,21 +7284,21 @@ unsigned int SensorIndex) /* Index of sensor which caused the trap */ unsigned int DescrLen; SK_U32 Val32; - - /* Get trap buffer entry */ + /* Get trap buffer entry. */ DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc); + pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen); Offset = SK_PNMI_TRAP_SIMPLE_LEN; - /* Store additionally sensor trap related data */ + /* Store additionally sensor trap related data. */ Val32 = OID_SKGE_SENSOR_INDEX; SK_PNMI_STORE_U32(pBuf + Offset, Val32); *(pBuf + Offset + 4) = 4; Val32 = (SK_U32)SensorIndex; SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); Offset += 9; - + Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR; SK_PNMI_STORE_U32(pBuf + Offset, Val32); *(pBuf + Offset + 4) = (char)DescrLen; @@ -7715,7 +7336,6 @@ unsigned int ActiveMac) /* Index (0..n) of the currently active port */ char *pBuf; SK_U32 Val32; - pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT, SK_PNMI_TRAP_RLMT_CHANGE_LEN); @@ -7743,7 +7363,6 @@ unsigned int PortIndex) /* Index of the port, which changed its state */ char *pBuf; SK_U32 Val32; - pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN); Val32 = OID_SKGE_RLMT_PORT_INDEX; @@ -7763,19 +7382,17 @@ unsigned int PortIndex) /* Index of the port, which changed its state */ * Nothing */ PNMI_STATIC void CopyMac( -char *pDst, /* Pointer to destination buffer */ +char *pDst, /* Pointer to destination buffer */ SK_MAC_ADDR *pMac) /* Pointer of Source */ { int i; - for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) { *(pDst + i) = pMac->a[i]; } } - #ifdef SK_POWER_MGMT /***************************************************************************** * @@ -7806,60 +7423,64 @@ SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ { - + + int i; + unsigned int HwPortIndex; + SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { + /* Check instance. We only handle single instance variables. */ + if ((Instance != (SK_U32)(-1))) { *pLen = 0; return (SK_PNMI_ERR_UNKNOWN_INST); } - /* - * Perform action - */ + /* Get hardware port index */ + HwPortIndex = NetIndex; + + /* Check length. */ + switch (Id) { + + case OID_PNP_CAPABILITIES: + if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { + + *pLen = sizeof(SK_PNP_CAPABILITIES); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_PNP_SET_POWER: + case OID_PNP_QUERY_POWER: + if (*pLen < sizeof(SK_DEVICE_POWER_STATE)) + { + *pLen = sizeof(SK_DEVICE_POWER_STATE); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_PNP_ADD_WAKE_UP_PATTERN: + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { + + *pLen = sizeof(SK_PM_PACKET_PATTERN); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + + case OID_PNP_ENABLE_WAKE_UP: + if (*pLen < sizeof(SK_U32)) { + + *pLen = sizeof(SK_U32); + return (SK_PNMI_ERR_TOO_SHORT); + } + break; + } + + /* Perform action. */ if (Action == SK_PNMI_GET) { - /* - * Check length - */ - switch (Id) { - - case OID_PNP_CAPABILITIES: - if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { - - *pLen = sizeof(SK_PNP_CAPABILITIES); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_QUERY_POWER: - case OID_PNP_ENABLE_WAKE_UP: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_SET_POWER: - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, - SK_PNMI_ERR040MSG); - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Get value - */ + /* Get value. */ switch (Id) { case OID_PNP_CAPABILITIES: @@ -7867,27 +7488,31 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ break; case OID_PNP_QUERY_POWER: - /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests - the miniport to indicate whether it can transition its NIC - to the low-power state. - A miniport driver must always return NDIS_STATUS_SUCCESS - to a query of OID_PNP_QUERY_POWER. */ - RetCode = SK_PNMI_ERR_OK; + /* + * The Windows DDK describes: An OID_PNP_QUERY_POWER requests + * the miniport to indicate whether it can transition its NIC + * to the low-power state. + * A miniport driver must always return NDIS_STATUS_SUCCESS + * to a query of OID_PNP_QUERY_POWER. + */ + *pLen = sizeof(SK_DEVICE_POWER_STATE); + RetCode = SK_PNMI_ERR_OK; break; - /* NDIS handles these OIDs as write-only. + /* + * NDIS handles these OIDs as write-only. * So in case of get action the buffer with written length = 0 - * is returned + * is returned. */ case OID_PNP_SET_POWER: case OID_PNP_ADD_WAKE_UP_PATTERN: case OID_PNP_REMOVE_WAKE_UP_PATTERN: - *pLen = 0; - RetCode = SK_PNMI_ERR_OK; + *pLen = 0; + RetCode = SK_PNMI_ERR_NOT_SUPPORTED; break; case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen); + RetCode = SkPowerGetEnableWakeUp(pAC, IoC, HwPortIndex, pBuf, pLen); break; default: @@ -7897,78 +7522,256 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ return (RetCode); } + + /* Perform PRESET or SET. */ + + /* The POWER module does not support PRESET action. */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + /* */ + i= HwPortIndex; - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ switch (Id) { case OID_PNP_SET_POWER: + /* Dual net mode? */ + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + if (RetCode = SkPowerSetPower(pAC, IoC, i, pBuf, pLen)) { + break; + } + } + break; + + case OID_PNP_ADD_WAKE_UP_PATTERN: + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + if (RetCode = SkPowerAddWakeUpPattern(pAC, IoC, i, pBuf, pLen)) { + break; + } + } + break; + + case OID_PNP_REMOVE_WAKE_UP_PATTERN: + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + if (RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, i, pBuf, pLen)) { + break; + } + } + break; + case OID_PNP_ENABLE_WAKE_UP: + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + if (RetCode = SkPowerSetEnableWakeUp(pAC, IoC, i, pBuf, pLen)) { + break; + } + } + break; + + default: + RetCode = SK_PNMI_ERR_READ_ONLY; + } + + return (RetCode); +} +#endif /* SK_POWER_MGMT */ + +#ifdef SK_DIAG_SUPPORT +/***************************************************************************** + * + * DiagActions - OID handler function of Diagnostic driver + * + * Description: + * The code is simple. No description necessary. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ + +PNMI_STATIC int DiagActions( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* GET/PRESET/SET action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ +{ + SK_U32 DiagStatus; + SK_U32 RetCode = SK_PNMI_ERR_GENERAL; + + /* Check instance. We only handle single instance variables. */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + /* Check length. */ + switch (Id) { + + case OID_SKGE_DIAG_MODE: if (*pLen < sizeof(SK_U32)) { *pLen = sizeof(SK_U32); return (SK_PNMI_ERR_TOO_SHORT); } - if (*pLen != sizeof(SK_U32)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Perform preset or set - */ - - /* POWER module does not support PRESET action */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - switch (Id) { - case OID_PNP_SET_POWER: - RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen); break; default: - RetCode = SK_PNMI_ERR_GENERAL; + SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG); + *pLen = 0; + return (SK_PNMI_ERR_GENERAL); } + /* Perform action. */ + if (Action == SK_PNMI_GET) { + + /* Get value. */ + switch (Id) { + + case OID_SKGE_DIAG_MODE: + DiagStatus = pAC->Pnmi.DiagAttached; + SK_PNMI_STORE_U32(pBuf, DiagStatus); + *pLen = sizeof(SK_U32); + RetCode = SK_PNMI_ERR_OK; + break; + + default: + *pLen = 0; + RetCode = SK_PNMI_ERR_GENERAL; + break; + } + return (RetCode); + } + + /* From here SET or PRESET value. */ + + /* PRESET value is not supported. */ + if (Action == SK_PNMI_PRESET) { + + return (SK_PNMI_ERR_OK); + } + + /* SET value. */ + switch (Id) { + case OID_SKGE_DIAG_MODE: + + /* Handle the SET. */ + switch (*pBuf) { + + /* Attach the DIAG to this adapter. */ + case SK_DIAG_ATTACHED: + /* Check if we come from running. */ + if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { + + RetCode = SkDrvLeaveDiagMode(pAC); + + } + else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) { + + RetCode = SK_PNMI_ERR_OK; + } + + else { + + RetCode = SK_PNMI_ERR_GENERAL; + + } + + if (RetCode == SK_PNMI_ERR_OK) { + + pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED; + } + break; + + /* Enter the DIAG mode in the driver. */ + case SK_DIAG_RUNNING: + RetCode = SK_PNMI_ERR_OK; + + /* + * If DiagAttached is set, we can tell the driver + * to enter the DIAG mode. + */ + if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { + /* If DiagMode is not active, we can enter it. */ + if (!pAC->DiagModeActive) { + + RetCode = SkDrvEnterDiagMode(pAC); + } + else { + + RetCode = SK_PNMI_ERR_GENERAL; + } + } + else { + + RetCode = SK_PNMI_ERR_GENERAL; + } + + if (RetCode == SK_PNMI_ERR_OK) { + + pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING; + } + break; + + case SK_DIAG_IDLE: + /* Check if we come from running. */ + if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { + + RetCode = SkDrvLeaveDiagMode(pAC); + + } + else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { + + RetCode = SK_PNMI_ERR_OK; + } + + else { + + RetCode = SK_PNMI_ERR_GENERAL; + + } + + if (RetCode == SK_PNMI_ERR_OK) { + + pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; + } + break; + + default: + RetCode = SK_PNMI_ERR_BAD_VALUE; + break; + } + break; + + default: + RetCode = SK_PNMI_ERR_GENERAL; + } + + if (RetCode == SK_PNMI_ERR_OK) { + *pLen = sizeof(SK_U32); + } + else { + + *pLen = 0; + } return (RetCode); } -#endif /* SK_POWER_MGMT */ - +#endif /* SK_DIAG_SUPPORT */ /***************************************************************************** * - * Vct - OID handler function of OIDs + * Vct - OID handler function of OIDs for Virtual Cable Tester (VCT) * * Description: * The code is simple. No description necessary. @@ -7980,7 +7783,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ * the correct data (e.g. a 32bit value is * needed, but a 16 bit value was passed). * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port + * exist (e.g. port instance 3 on a two port * adapter). * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed. * @@ -7989,10 +7792,10 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ PNMI_STATIC int Vct( SK_AC *pAC, /* Pointer to adapter context */ SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ +int Action, /* GET/PRESET/SET action */ SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which the mgmt data will be copied */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */ unsigned int TableIndex, /* Index to the Id table */ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ @@ -8004,15 +7807,13 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ SK_U32 PhysPortIndex; SK_U32 Limit; SK_U32 Offset; - SK_BOOL Link; - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - int i; + SK_U32 RetCode; + int i; SK_EVPARA Para; - SK_U32 CableLength; - /* - * Calculate the port indexes from the instance. - */ + RetCode = SK_PNMI_ERR_GENERAL; + + /* Calculate the port indexes from the instance. */ PhysPortMax = pAC->GIni.GIMacsFound; LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); @@ -8022,55 +7823,43 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ } if ((Instance != (SK_U32) (-1))) { - /* Check instance range. */ - if ((Instance < 2) || (Instance > LogPortMax)) { - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - + /* + * Get one instance of that OID, so check the instance range: + * There is no virtual port with an Instance == 1, so we get + * the values from one physical port only. + */ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { PhysPortIndex = NetIndex; } else { + if ((Instance < 2) || (Instance > LogPortMax)) { + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } PhysPortIndex = Instance - 2; } Limit = PhysPortIndex + 1; } - else { /* - * Instance == (SK_U32) (-1), get all Instances of that OID. - * - * Not implemented yet. May be used in future releases. + else { + /* + * Instance == (SK_U32) (-1), so get all instances of that OID. + * There is no virtual port with an Instance == 1, so we get + * the values from all physical ports. */ PhysPortIndex = 0; Limit = PhysPortMax; } - pPrt = &pAC->GIni.GP[PhysPortIndex]; - if (pPrt->PHWLinkUp) { - Link = SK_TRUE; - } - else { - Link = SK_FALSE; - } - - /* - * Check MAC type. - */ - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { + /* Check MAC type. */ + if ((Id != OID_SKGE_VCT_CAPABILITIES) && + (pAC->GIni.GP[PhysPortIndex].PhyType != SK_PHY_MARV_COPPER)) { *pLen = 0; - return (SK_PNMI_ERR_GENERAL); + return (SK_PNMI_ERR_NOT_SUPPORTED); } - /* Initialize backup data pointer. */ - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - /* - * Check action type. - */ + /* Check action type. */ if (Action == SK_PNMI_GET) { - /* - * Check length. - */ + /* Check length. */ switch (Id) { case OID_SKGE_VCT_GET: @@ -8081,6 +7870,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ break; case OID_SKGE_VCT_STATUS: + case OID_SKGE_VCT_CAPABILITIES: if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) { *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8); return (SK_PNMI_ERR_TOO_SHORT); @@ -8090,63 +7880,53 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ default: *pLen = 0; return (SK_PNMI_ERR_GENERAL); - } + } - /* - * Get value. - */ + /* Get value. */ Offset = 0; for (; PhysPortIndex < Limit; PhysPortIndex++) { + + pPrt = &pAC->GIni.GP[PhysPortIndex]; + switch (Id) { case OID_SKGE_VCT_GET: - if ((Link == SK_FALSE) && + if (!pPrt->PHWLinkUp && (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 0) { - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { - pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; - } - } - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { - CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); - } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; - } + RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); + + if (RetCode == 0) { + + /* VCT test is finished, so save the data. */ + VctGetResults(pAC, IoC, PhysPortIndex); Para.Para32[0] = PhysPortIndex; Para.Para32[1] = -1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - SkEventDispatcher(pAC, IoC); - } - else { - ; /* VCT test is running. */ + + /* SkEventDispatcher(pAC, IoC); */ } } + /* Initialize backup data pointer. */ + pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; + /* Get all results. */ CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); + + Offset++; *(pBuf + Offset) = pPrt->PCableLen; - Offset += sizeof(SK_U8); + Offset++; for (i = 0; i < 4; i++) { - SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]); + + SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->MdiPairLen[i]); Offset += sizeof(SK_U32); } for (i = 0; i < 4; i++) { - *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i]; - Offset += sizeof(SK_U8); + + *(pBuf + Offset) = pVctBackupData->MdiPairSts[i]; + Offset++; } RetCode = SK_PNMI_ERR_OK; @@ -8154,7 +7934,20 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ case OID_SKGE_VCT_STATUS: CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); + + Offset++; + RetCode = SK_PNMI_ERR_OK; + break; + + case OID_SKGE_VCT_CAPABILITIES: + if (pPrt->PhyType != SK_PHY_MARV_COPPER) { + *(pBuf + Offset) = SK_PNMI_VCT_NOT_SUPPORTED; + } + else { + *(pBuf + Offset) = SK_PNMI_VCT_SUPPORTED; + } + Offset++; + RetCode = SK_PNMI_ERR_OK; break; @@ -8173,9 +7966,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ * buffer length is plausible. */ - /* - * Check length. - */ + /* Check length. */ switch (Id) { case OID_SKGE_VCT_SET: if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { @@ -8189,36 +7980,39 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ return (SK_PNMI_ERR_GENERAL); } - /* - * Perform preset or set. - */ + /* Perform PRESET or SET. */ /* VCT does not support PRESET action. */ if (Action == SK_PNMI_PRESET) { + return (SK_PNMI_ERR_OK); } Offset = 0; for (; PhysPortIndex < Limit; PhysPortIndex++) { + + pPrt = &pAC->GIni.GP[PhysPortIndex]; + switch (Id) { case OID_SKGE_VCT_SET: /* Start VCT test. */ - if (Link == SK_FALSE) { + if (!pPrt->PHWLinkUp) { SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST); RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE); + if (RetCode == 0) { /* RetCode: 0 => Start! */ pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK; + pAC->Pnmi.VctStatus[PhysPortIndex] &= + ~(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_LINK); - /* - * Start VCT timer counter. - */ - SK_MEMSET((char *) &Para, 0, sizeof(Para)); + /* Start VCT timer counter. */ + SK_MEMSET((char *)&Para, 0, sizeof(Para)); Para.Para32[0] = PhysPortIndex; Para.Para32[1] = -1; - SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); + + SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex], + SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); + SK_PNMI_STORE_U32((pBuf + Offset), RetCode); RetCode = SK_PNMI_ERR_OK; } @@ -8246,6 +8040,65 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ } /* Vct */ +PNMI_STATIC void VctGetResults( +SK_AC *pAC, +SK_IOC IoC, +SK_U32 Port) +{ + SK_GEPORT *pPrt; + int i; + SK_U8 PairLen; + SK_U8 PairSts; + SK_U32 MinLength; + SK_U32 CableLength; + + pPrt = &pAC->GIni.GP[Port]; + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { + MinLength = 25; + } + else { + MinLength = 35; + } + + /* Copy results for later use to PNMI struct. */ + for (i = 0; i < 4; i++) { + + PairLen = pPrt->PMdiPairLen[i]; + + if (((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) == 0) && (i > 1)) { + PairSts = SK_PNMI_VCT_NOT_PRESENT; + } + else { + PairSts = pPrt->PMdiPairSts[i]; + } + + if ((PairSts == SK_PNMI_VCT_NORMAL_CABLE) && + (PairLen > 28) && (PairLen < 0xff)) { + + PairSts = SK_PNMI_VCT_IMPEDANCE_MISMATCH; + } + + /* Ignore values <= MinLength, the linear factor is 4/5. */ + if ((PairLen > MinLength) && (PairLen < 0xff)) { + + CableLength = 1000UL * (PairLen - MinLength) * 4 / 5; + } + else { + /* No cable or short cable. */ + CableLength = 0; + } + + pAC->Pnmi.VctBackup[Port].MdiPairLen[i] = CableLength; + pAC->Pnmi.VctBackup[Port].MdiPairSts[i] = PairSts; + } + + pAC->Pnmi.VctStatus[Port] &= ~SK_PNMI_VCT_PENDING; + pAC->Pnmi.VctStatus[Port] |= (SK_PNMI_VCT_NEW_VCT_DATA | + SK_PNMI_VCT_TEST_DONE); + +} /* GetVctResults */ + PNMI_STATIC void CheckVctStatus( SK_AC *pAC, SK_IOC IoC, @@ -8255,19 +8108,21 @@ SK_U32 PhysPortIndex) { SK_GEPORT *pPrt; SK_PNMI_VCT *pVctData; + SK_U8 VctStatus; SK_U32 RetCode; - SK_U8 LinkSpeedUsed; pPrt = &pAC->GIni.GP[PhysPortIndex]; pVctData = (SK_PNMI_VCT *) (pBuf + Offset); pVctData->VctStatus = SK_PNMI_VCT_NONE; + VctStatus = pAC->Pnmi.VctStatus[PhysPortIndex]; + if (!pPrt->PHWLinkUp) { /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { - if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) { + if (VctStatus & SK_PNMI_VCT_TEST_DONE) { + if (VctStatus & SK_PNMI_VCT_LINK) { pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; } else { @@ -8277,11 +8132,12 @@ SK_U32 PhysPortIndex) /* Check VCT test status. */ RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE); + if (RetCode == 2) { /* VCT test is running. */ pVctData->VctStatus |= SK_PNMI_VCT_RUNNING; } else { /* VCT data was copied to pAC here. Check PENDING state. */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { + if (VctStatus & SK_PNMI_VCT_PENDING) { pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; } } @@ -8291,20 +8147,185 @@ SK_U32 PhysPortIndex) } } else { - /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { + if (VctStatus & SK_PNMI_VCT_TEST_DONE) { pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA; pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; } /* DSP only valid in 100/1000 modes. */ - LinkSpeedUsed = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; - if (LinkSpeedUsed != SK_LSPEED_STAT_10MBPS) { + if (pPrt->PLinkSpeedUsed != SK_LSPEED_STAT_10MBPS) { pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA; } } } /* CheckVctStatus */ -#endif /* CONFIG_SK98 */ + +/***************************************************************************** + * + * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed + * PNMI function depending on the subcommand and + * returns all data belonging to the complete database + * or OID request. + * + * Description: + * Looks up the requested subcommand, calls the corresponding handler + * function and passes all required parameters to it. + * The function is called by the driver. It is needed to handle the new + * generic PNMI IOCTL. This IOCTL is given to the driver and contains both + * the OID and a subcommand to decide what kind of request has to be done. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed + * SK_PNMI_ERR_GENERAL A general severe internal error occured + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take + * the data. + * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ +int SkPnmiGenIoctl( +SK_AC *pAC, /* Pointer to adapter context struct */ +SK_IOC IoC, /* I/O context */ +void *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* Length of buffer */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ +{ +SK_I32 Mode; /* Store value of subcommand. */ +SK_U32 Oid; /* Store value of OID. */ +int ReturnCode; /* Store return value to show status of PNMI action. */ +int HeaderLength; /* Length of desired action plus OID. */ + + ReturnCode = SK_PNMI_ERR_GENERAL; + + SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32)); + SK_MEMCPY(&Oid, (char *)pBuf + sizeof(SK_I32), sizeof(SK_U32)); + HeaderLength = sizeof(SK_I32) + sizeof(SK_U32); + *pLen = *pLen - HeaderLength; + SK_MEMCPY((char *)pBuf + sizeof(SK_I32), (char *)pBuf + HeaderLength, *pLen); + + switch(Mode) { + case SK_GET_SINGLE_VAR: + ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, + (char *)pBuf + sizeof(SK_I32), pLen, + ((SK_U32) (-1)), NetIndex); + SK_PNMI_STORE_U32(pBuf, ReturnCode); + *pLen = *pLen + sizeof(SK_I32); + break; + case SK_PRESET_SINGLE_VAR: + ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, + (char *)pBuf + sizeof(SK_I32), pLen, + ((SK_U32) (-1)), NetIndex); + SK_PNMI_STORE_U32(pBuf, ReturnCode); + *pLen = *pLen + sizeof(SK_I32); + break; + case SK_SET_SINGLE_VAR: + ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, + (char *)pBuf + sizeof(SK_I32), pLen, + ((SK_U32) (-1)), NetIndex); + SK_PNMI_STORE_U32(pBuf, ReturnCode); + *pLen = *pLen + sizeof(SK_I32); + break; + case SK_GET_FULL_MIB: + ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex); + break; + case SK_PRESET_FULL_MIB: + ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex); + break; + case SK_SET_FULL_MIB: + ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex); + break; + default: + break; + } + + return (ReturnCode); + +} /* SkGeIocGen */ + +#ifdef SK_ASF +/***************************************************************************** + * + * Asf + * + * Description: + * The code is simple. No description necessary. + * + * Returns: + * SK_PNMI_ERR_OK The request was successfully performed. + * SK_PNMI_ERR_GENERAL A general severe internal error occured. + * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain + * the correct data (e.g. a 32bit value is + * needed, but a 16 bit value was passed). + * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't + * exist (e.g. port instance 3 on a two port + * adapter. + */ + +PNMI_STATIC int Asf( +SK_AC *pAC, /* Pointer to adapter context */ +SK_IOC IoC, /* IO context handle */ +int Action, /* GET/PRESET/SET action */ +SK_U32 Id, /* Object ID that is to be processed */ +char *pBuf, /* Buffer used for the management data transfer */ +unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ +SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ +unsigned int TableIndex, /* Index to the Id table */ +SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ +{ + SK_U32 RetCode = SK_PNMI_ERR_GENERAL; + + /* + * Check instance. We only handle single instance variables. + */ + if (Instance != (SK_U32)(-1) && Instance != 1) { + + *pLen = 0; + return (SK_PNMI_ERR_UNKNOWN_INST); + } + + /* Perform action. */ + /* GET value. */ + if (Action == SK_PNMI_GET) { + switch (Id) { + case OID_SKGE_ASF: + RetCode = SkAsfGet(pAC, IoC, (SK_U8 *) pBuf, pLen); + break; + default: + RetCode = SkAsfGetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen ); + break; + } + + return (RetCode); + } + + /* PRESET value. */ + if (Action == SK_PNMI_PRESET) { + switch (Id) { + case OID_SKGE_ASF: + RetCode = SkAsfPreSet(pAC, IoC, (SK_U8 *) pBuf, pLen); + break; + default: + RetCode = SkAsfPreSetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen ); + break; + } + } + + /* SET value. */ + if (Action == SK_PNMI_SET) { + switch (Id) { + case OID_SKGE_ASF: + RetCode = SkAsfSet(pAC, IoC, (SK_U8 *) pBuf, pLen); + break; + default: + RetCode = SkAsfSetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen ); + break; + } + } + return (RetCode); +} +#endif /* SK_ASF */ + +#endif diff --git a/drivers/sk98lin/skgesirq.c b/drivers/sk98lin/skgesirq.c index e5a4f7e..047f5e2 100644 --- a/drivers/sk98lin/skgesirq.c +++ b/drivers/sk98lin/skgesirq.c @@ -1,346 +1,28 @@ /****************************************************************************** * * Name: skgesirq.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.83 $ - * Date: $Date: 2003/02/05 15:10:59 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Special IRQ module * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2006 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skgesirq.c,v $ - * Revision 1.83 2003/02/05 15:10:59 rschmidt - * Fixed setting of PLinkSpeedUsed in SkHWLinkUp() when - * auto-negotiation is disabled. - * Editorial changes. - * - * Revision 1.82 2003/01/29 13:34:33 rschmidt - * Added some typecasts to avoid compiler warnings. - * - * Revision 1.81 2002/12/05 10:49:51 rschmidt - * Fixed missing Link Down Event for fiber (Bug Id #10768) - * Added reading of cable length when link is up - * Removed testing of unused error bits in PHY ISR - * Editorial changes. - * - * Revision 1.80 2002/11/12 17:15:21 rschmidt - * Replaced SkPnmiGetVar() by ...MacStatistic() in SkMacParity(). - * Editorial changes. - * - * Revision 1.79 2002/10/14 15:14:51 rschmidt - * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in - * SkMacParity() depending on GIChipRev (HW-Bug #8). - * Added error messages for GPHY Auto-Negotiation Error and - * FIFO Overflow/Underrun in SkPhyIsrGmac(). - * Editorial changes. - * - * Revision 1.78 2002/10/10 15:54:29 mkarl - * changes for PLinkSpeedUsed - * - * Revision 1.77 2002/09/12 08:58:51 rwahl - * Retrieve counters needed for XMAC errata workarounds directly because - * PNMI returns corrected counter values (e.g. #10620). - * - * Revision 1.76 2002/08/16 15:21:54 rschmidt - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. - * Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros. - * Editorial changes. - * - * Revision 1.75 2002/08/12 13:50:47 rschmidt - * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in - * SkMacParity() by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE (HW-Bug #8). - * Added clearing of IS_IRQ_TIST_OV and IS_IRQ_SENSOR in SkGeHwErr(). - * Corrected handling of Link Up and Auto-Negotiation Over for GPHY. - * in SkGePortCheckUpGmac(). - * Editorial changes. - * - * Revision 1.74 2002/08/08 16:17:04 rschmidt - * Added PhyType check for SK_HWEV_SET_ROLE event (copper only) - * Changed Link Up check reading PHY Specific Status (YUKON) - * Editorial changes - * - * Revision 1.73 2002/07/15 18:36:53 rwahl - * Editorial changes. - * - * Revision 1.72 2002/07/15 15:46:26 rschmidt - * Added new event: SK_HWEV_SET_SPEED - * Editorial changes - * - * Revision 1.71 2002/06/10 09:34:19 rschmidt - * Editorial changes - * - * Revision 1.70 2002/06/05 08:29:18 rschmidt - * SkXmRxTxEnable() replaced by SkMacRxTxEnable(). - * Editorial changes. - * - * Revision 1.69 2002/04/25 13:03:49 rschmidt - * Changes for handling YUKON. - * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types. - * Replaced all XMAC-access macros by functions: SkMacRxTxDisable(), - * SkMacIrqDisable(). - * Added handling for GMAC FIFO in SkMacParity(). - * Replaced all SkXm...() functions with SkMac...() to handle also - * YUKON's GMAC. - * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced - * by functions SkXmPhyRead(), SkXmPhyWrite(). - * Disabling all PHY interrupts moved to SkMacIrqDisable(). - * Added handling for GPHY IRQ in SkGeSirqIsr(). - * Removed status parameter from MAC IRQ handler SkMacIrq(). - * Added SkGePortCheckUpGmac(), SkPhyIsrGmac() for GMAC. - * Editorial changes - * - * Revision 1.68 2002/02/26 15:24:53 rwahl - * Fix: no link with manual configuration (#10673). The previous fix for - * #10639 was removed. So for RLMT mode = CLS the RLMT may switch to - * misconfigured port. It should not occur for the other RLMT modes. - * - * Revision 1.67 2001/11/20 09:19:58 rwahl - * Reworked bugfix #10639 (no dependency to RLMT mode). - * - * Revision 1.66 2001/10/26 07:52:53 afischer - * Port switching bug in `check local link` mode - * - * Revision 1.65 2001/02/23 13:41:51 gklug - * fix: PHYS2INST should be used correctly for Dual Net operation - * chg: do no longer work with older PNMI - * - * Revision 1.64 2001/02/15 11:27:04 rassmann - * Working with RLMT v1 if SK_MAX_NETS undefined. - * - * Revision 1.63 2001/02/06 10:44:23 mkunz - * - NetIndex added to interface functions of pnmi V4 with dual net support - * - * Revision 1.62 2001/01/31 15:31:41 gklug - * fix: problem with autosensing an SR8800 switch - * - * Revision 1.61 2000/11/09 11:30:09 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.60 2000/10/18 12:37:48 cgoos - * Reinserted the comment for version 1.56. - * - * Revision 1.59 2000/10/18 12:22:20 cgoos - * Added workaround for half duplex hangup. - * - * Revision 1.58 2000/09/28 13:06:04 gklug - * fix: BCom may NOT be touched if XMAC is in RESET state - * - * Revision 1.57 2000/09/08 12:38:39 cgoos - * Added forgotten variable declaration. - * - * Revision 1.56 2000/09/08 08:12:13 cgoos - * Changed handling of parity errors in SkGeHwErr (correct reset of error). - * - * Revision 1.55 2000/06/19 08:36:25 cgoos - * Changed comment. - * - * Revision 1.54 2000/05/22 08:45:57 malthoff - * Fix: #10523 is valid for all BCom PHYs. - * - * Revision 1.53 2000/05/19 10:20:30 cgoos - * Removed Solaris debug output code. - * - * Revision 1.52 2000/05/19 10:19:37 cgoos - * Added PHY state check in HWLinkDown. - * Move PHY interrupt code to IS_EXT_REG case in SkGeSirqIsr. - * - * Revision 1.51 2000/05/18 05:56:20 cgoos - * Fixed typo. - * - * Revision 1.50 2000/05/17 12:49:49 malthoff - * Fixes BCom link bugs (#10523). - * - * Revision 1.49 1999/12/17 11:02:50 gklug - * fix: read PHY_STAT of Broadcom chip more often to assure good status - * - * Revision 1.48 1999/12/06 10:01:17 cgoos - * Added SET function for Role. - * - * Revision 1.47 1999/11/22 13:34:24 cgoos - * Changed license header to GPL. - * - * Revision 1.46 1999/09/16 10:30:07 cgoos - * Removed debugging output statement from Linux. - * - * Revision 1.45 1999/09/16 07:32:55 cgoos - * Fixed dual-port copperfield bug (PHY_READ from resetted port). - * Removed some unused variables. - * - * Revision 1.44 1999/08/03 15:25:04 cgoos - * Removed workaround for disabled interrupts in half duplex mode. - * - * Revision 1.43 1999/08/03 14:27:58 cgoos - * Removed SENSE mode code from SkGePortCheckUpBcom. - * - * Revision 1.42 1999/07/26 09:16:54 cgoos - * Added some typecasts to avoid compiler warnings. - * - * Revision 1.41 1999/05/19 07:28:59 cgoos - * Changes for 1000Base-T. - * - * Revision 1.40 1999/04/08 13:59:39 gklug - * fix: problem with 3Com switches endless RESTARTs - * - * Revision 1.39 1999/03/08 10:10:52 gklug - * fix: AutoSensing did switch to next mode even if LiPa indicated offline - * - * Revision 1.38 1999/03/08 09:49:03 gklug - * fix: Bug using pAC instead of IoC, causing AIX problems - * fix: change compare for Linux compiler bug workaround - * - * Revision 1.37 1999/01/28 14:51:33 gklug - * fix: monitor for autosensing and extra RESETS the RX on wire counters - * - * Revision 1.36 1999/01/22 09:19:55 gklug - * fix: Init DupMode and InitPauseMd are now called in RxTxEnable - * - * Revision 1.35 1998/12/11 15:22:59 gklug - * chg: autosensing: check for receive if manual mode was guessed - * chg: simplified workaround for XMAC errata - * chg: wait additional 100 ms before link goes up. - * chg: autoneg timeout to 600 ms - * chg: restart autoneg even if configured to autonegotiation - * - * Revision 1.34 1998/12/10 10:33:14 gklug - * add: more debug messages - * fix: do a new InitPhy if link went down (AutoSensing problem) - * chg: Check for zero shorts if link is NOT up - * chg: reset Port if link goes down - * chg: wait additional 100 ms when link comes up to check shorts - * fix: dummy read extended autoneg status to prevent link going down immediately - * - * Revision 1.33 1998/12/07 12:18:29 gklug - * add: refinement of autosense mode: take into account the autoneg cap of LiPa - * - * Revision 1.32 1998/12/07 07:11:21 gklug - * fix: compiler warning - * - * Revision 1.31 1998/12/02 09:29:05 gklug - * fix: WA XMAC Errata: FCSCt check was not correct. - * fix: WA XMAC Errata: Prec Counter were NOT updated in case of short checks. - * fix: Clear Stat : now clears the Prev counters of all known Ports - * - * Revision 1.30 1998/12/01 10:54:15 gklug - * dd: workaround for XMAC errata changed. Check RX count and CRC err Count, too. - * - * Revision 1.29 1998/12/01 10:01:53 gklug - * fix: if MAC IRQ occurs during port down, this will be handled correctly - * - * Revision 1.28 1998/11/26 16:22:11 gklug - * fix: bug in autosense if manual modes are used - * - * Revision 1.27 1998/11/26 15:50:06 gklug - * fix: PNMI needs to set PLinkModeConf - * - * Revision 1.26 1998/11/26 14:51:58 gklug - * add: AutoSensing functionalty - * - * Revision 1.25 1998/11/26 07:34:37 gklug - * fix: Init PrevShorts when restarting port due to Link connection - * - * Revision 1.24 1998/11/25 10:57:32 gklug - * fix: remove unreferenced local vars - * - * Revision 1.23 1998/11/25 08:26:40 gklug - * fix: don't do a RESET on a starting or stopping port - * - * Revision 1.22 1998/11/24 13:29:44 gklug - * add: Workaround for MAC parity errata - * - * Revision 1.21 1998/11/18 15:31:06 gklug - * fix: lint bugs - * - * Revision 1.20 1998/11/18 12:58:54 gklug - * fix: use PNMI query instead of hardware access - * - * Revision 1.19 1998/11/18 12:54:55 gklug - * chg: add new workaround for XMAC Errata - * add: short event counter monitoring on active link too - * - * Revision 1.18 1998/11/13 14:27:41 malthoff - * Bug Fix: Packet Arbiter Timeout was not cleared correctly - * for timeout on TX1 and TX2. - * - * Revision 1.17 1998/11/04 07:01:59 cgoos - * Moved HW link poll sequence. - * Added call to SkXmRxTxEnable. - * - * Revision 1.16 1998/11/03 13:46:03 gklug - * add: functionality of SET_LMODE and SET_FLOW_MODE - * fix: send RLMT LinkDown event when Port stop is given with LinkUp - * - * Revision 1.15 1998/11/03 12:56:47 gklug - * fix: Needs more events - * - * Revision 1.14 1998/10/30 07:36:35 gklug - * rmv: unnecessary code - * - * Revision 1.13 1998/10/29 15:21:57 gklug - * add: Poll link feature for activating HW link - * fix: Deactivate HWLink when Port STOP is given - * - * Revision 1.12 1998/10/28 07:38:57 cgoos - * Checking link status at begin of SkHWLinkUp. - * - * Revision 1.11 1998/10/22 09:46:50 gklug - * fix SysKonnectFileId typo - * - * Revision 1.10 1998/10/14 13:57:47 gklug - * add: Port start/stop event - * - * Revision 1.9 1998/10/14 05:48:29 cgoos - * Added definition for Para. - * - * Revision 1.8 1998/10/14 05:40:09 gklug - * add: Hardware Linkup signal used - * - * Revision 1.7 1998/10/09 06:50:20 malthoff - * Remove ID_sccs by SysKonnectFileId. - * - * Revision 1.6 1998/10/08 09:11:49 gklug - * add: clear IRQ commands - * - * Revision 1.5 1998/10/02 14:27:35 cgoos - * Fixed some typos and wrong event names. - * - * Revision 1.4 1998/10/02 06:24:17 gklug - * add: HW error function - * fix: OUT macros - * - * Revision 1.3 1998/10/01 07:03:00 gklug - * add: ISR for the usual interrupt source register - * - * Revision 1.2 1998/09/03 13:50:33 gklug - * add: function prototypes - * - * Revision 1.1 1998/08/27 11:50:21 gklug - * initial revision - * - * - * - ******************************************************************************/ - -#include - -#ifdef CONFIG_SK98 - /* * Special Interrupt handler * @@ -357,34 +39,48 @@ * right after this ISR. * * The Interrupt source register of the adapter is NOT read by this module. - * SO if the drivers implementor needs a while loop around the + * SO if the drivers implementor needs a while loop around the * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for * each loop entered. * * However, the MAC Interrupt status registers are read in a while loop. * */ - -static const char SysKonnectFileId[] = - "$Id: skgesirq.c,v 1.83 2003/02/05 15:10:59 rschmidt Exp $" ; +#include + +#ifdef CONFIG_SK98 #include "h/skdrv1st.h" /* Driver Specific Definitions */ +#ifndef SK_SLIM #include "h/skgepnmi.h" /* PNMI Definitions */ #include "h/skrlmt.h" /* RLMT Definitions */ +#endif #include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */ +/* local variables ************************************************************/ + +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) +static const char SysKonnectFileId[] = + "@(#) $Id: skgesirq.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif + /* local function prototypes */ -static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int); -static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int); -static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int); +#ifdef GENESIS +static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL); +static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL); static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16); +#endif /* GENESIS */ +#ifdef YUKON +static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL); static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16); +#endif /* YUKON */ #ifdef OTHER_PHY -static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int); -static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int); +static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL); +static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL); static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16); #endif /* OTHER_PHY */ +#ifdef GENESIS /* * array of Rx counter from XMAC which are checked * in AutoSense mode to check whether a link is not able to auto-negotiate. @@ -396,7 +92,8 @@ static const SK_U16 SkGeRxRegs[]= { XM_RXF_511B, XM_RXF_1023B, XM_RXF_MAX_SZ -} ; +}; +#endif /* GENESIS */ #ifdef __C2MAN__ /* @@ -409,11 +106,6 @@ intro() {} #endif -/* Define return codes of SkGePortCheckUp and CheckShort */ -#define SK_HW_PS_NONE 0 /* No action needed */ -#define SK_HW_PS_RESTART 1 /* Restart needed */ -#define SK_HW_PS_LINK 2 /* Link Up actions needed */ - /****************************************************************************** * * SkHWInitDefSense() - Default Autosensing mode initialization @@ -423,8 +115,8 @@ intro() * Returns: N/A */ static void SkHWInitDefSense( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; /* GIni Port struct pointer */ @@ -433,7 +125,7 @@ int Port) /* Port Index (MAC_1 + n) */ pPrt->PAutoNegTimeOut = 0; - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { + if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { pPrt->PLinkMode = pPrt->PLinkModeConf; return; } @@ -442,12 +134,13 @@ int Port) /* Port Index (MAC_1 + n) */ ("AutoSensing: First mode %d on Port %d\n", (int)SK_LMODE_AUTOFULL, Port)); - pPrt->PLinkMode = SK_LMODE_AUTOFULL; + pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; return; } /* SkHWInitDefSense */ +#ifdef GENESIS /****************************************************************************** * * SkHWSenseGetNext() - Get Next Autosensing Mode @@ -457,9 +150,9 @@ int Port) /* Port Index (MAC_1 + n) */ * Note: * */ -SK_U8 SkHWSenseGetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +static SK_U8 SkHWSenseGetNext( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; /* GIni Port struct pointer */ @@ -468,18 +161,18 @@ int Port) /* Port Index (MAC_1 + n) */ pPrt->PAutoNegTimeOut = 0; - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { + if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { /* Leave all as configured */ return(pPrt->PLinkModeConf); } - if (pPrt->PLinkMode == SK_LMODE_AUTOFULL) { + if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) { /* Return next mode AUTOBOTH */ - return(SK_LMODE_AUTOBOTH); + return((SK_U8)SK_LMODE_AUTOBOTH); } /* Return default autofull */ - return(SK_LMODE_AUTOFULL); + return((SK_U8)SK_LMODE_AUTOFULL); } /* SkHWSenseGetNext */ @@ -491,9 +184,9 @@ int Port) /* Port Index (MAC_1 + n) */ * * Returns: N/A */ -void SkHWSenseSetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +static void SkHWSenseSetNext( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ int Port, /* Port Index (MAC_1 + n) */ SK_U8 NewMode) /* New Mode to be written in sense mode */ { @@ -503,7 +196,7 @@ SK_U8 NewMode) /* New Mode to be written in sense mode */ pPrt->PAutoNegTimeOut = 0; - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { + if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { return; } @@ -515,6 +208,7 @@ SK_U8 NewMode) /* New Mode to be written in sense mode */ return; } /* SkHWSenseSetNext */ +#endif /* GENESIS */ /****************************************************************************** @@ -526,8 +220,8 @@ SK_U8 NewMode) /* New Mode to be written in sense mode */ * Returns: N/A */ void SkHWLinkDown( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; /* GIni Port struct pointer */ @@ -547,18 +241,20 @@ int Port) /* Port Index (MAC_1 + n) */ return; } - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("Link down Port %d\n", Port)); /* Set Link to DOWN */ pPrt->PHWLinkUp = SK_FALSE; +#ifndef SK_SLIM /* Reset Port stati */ - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_INDETERMINATED; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; + pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED; +#endif /* !SK_SLIM */ - /* Re-init Phy especially when the AutoSense default is set now */ + /* Re-init PHY especially when the AutoSense default is set now */ SkMacInitPhy(pAC, IoC, Port, SK_FALSE); /* GP0: used for workaround of Rev. C Errata 2 */ @@ -578,8 +274,8 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: N/A */ void SkHWLinkUp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; /* GIni Port struct pointer */ @@ -592,12 +288,14 @@ int Port) /* Port Index (MAC_1 + n) */ } pPrt->PHWLinkUp = SK_TRUE; - pPrt->PAutoNegFail = SK_FALSE; - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; - if (pPrt->PLinkMode != SK_LMODE_AUTOHALF && - pPrt->PLinkMode != SK_LMODE_AUTOFULL && - pPrt->PLinkMode != SK_LMODE_AUTOBOTH) { +#ifndef SK_SLIM + pPrt->PAutoNegFail = SK_FALSE; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; + + if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF && + pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL && + pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) { /* Link is up and no Auto-negotiation should be done */ /* Link speed should be the configured one */ @@ -605,30 +303,32 @@ int Port) /* Port Index (MAC_1 + n) */ case SK_LSPEED_AUTO: /* default is 1000 Mbps */ case SK_LSPEED_1000MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + pPrt->PLinkSpeedUsed = (SK_U8) + ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) ? + SK_LSPEED_STAT_1000MBPS : SK_LSPEED_STAT_100MBPS; break; case SK_LSPEED_100MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; break; case SK_LSPEED_10MBPS: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; break; } /* Set Link Mode Status */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL; - } - else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_HALF; - } + pPrt->PLinkModeStatus = (SK_U8) + ((pPrt->PLinkMode == (SK_U8)SK_LMODE_FULL) ? + SK_LMODE_STAT_FULL : SK_LMODE_STAT_HALF); /* No flow control without auto-negotiation */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; +#endif /* !SK_SLIM */ /* enable Rx/Tx */ - SkMacRxTxEnable(pAC, IoC, Port); + (void)SkMacRxTxEnable(pAC, IoC, Port); +#ifndef SK_SLIM } +#endif /* !SK_SLIM */ } /* SkHWLinkUp */ @@ -641,27 +341,37 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: N/A */ static void SkMacParity( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index of the port failed */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ +int Port) /* Port Index (MAC_1 + n) */ { SK_EVPARA Para; SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 TxMax; /* TxMax Counter */ + SK_U32 TxMax; /* Tx Max Size Counter */ + + TxMax = 0; pPrt = &pAC->GIni.GP[Port]; /* Clear IRQ Tx Parity Error */ +#ifdef GENESIS if (pAC->GIni.GIGenesis) { + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), - (SK_U8)((pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); + (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON && + pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); } +#endif /* YUKON */ if (pPrt->PCheckPar) { + if (Port == MAC_1) { SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); } @@ -670,6 +380,7 @@ int Port) /* Port Index of the port failed */ } Para.Para64 = Port; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = Port; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); @@ -677,15 +388,21 @@ int Port) /* Port Index of the port failed */ } /* Check whether frames with a size of 1k were sent */ +#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* Snap statistic counters */ (void)SkXmUpdateStats(pAC, IoC, Port); (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); } +#endif /* YUKON */ if (TxMax > 0) { /* From now on check the parity */ @@ -696,15 +413,15 @@ int Port) /* Port Index of the port failed */ /****************************************************************************** * - * SkGeHwErr() - Hardware Error service routine + * SkGeYuHwErr() - Hardware Error service routine (Genesis and Yukon) * * Description: handles all HW Error interrupts * * Returns: N/A */ -static void SkGeHwErr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +static void SkGeYuHwErr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ SK_U32 HwStatus) /* Interrupt status word */ { SK_EVPARA Para; @@ -720,17 +437,19 @@ SK_U32 HwStatus) /* Interrupt status word */ } /* Reset all bits in the PCI STATUS register */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); + SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word); SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS); + SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } +#ifdef GENESIS if (pAC->GIni.GIGenesis) { + if ((HwStatus & IS_NO_STAT_M1) != 0) { /* Ignore it */ /* This situation is also indicated in the descriptor */ @@ -755,28 +474,42 @@ SK_U32 HwStatus) /* Interrupt status word */ SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); } } - else { /* YUKON */ +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { /* This is necessary only for Rx timing measurements */ if ((HwStatus & IS_IRQ_TIST_OV) != 0) { + /* increment Time Stamp Timer counter (high) */ + pAC->GIni.GITimeStampCnt++; + /* Clear Time Stamp Timer IRQ */ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); } if ((HwStatus & IS_IRQ_SENSOR) != 0) { - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); + /* no sensors on 32-bit Yukon */ + if (pAC->GIni.GIYukon32Bit) { + /* disable HW Error IRQ */ + pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; + } } } +#endif /* YUKON */ if ((HwStatus & IS_RAM_RD_PAR) != 0) { + SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); } if ((HwStatus & IS_RAM_WR_PAR) != 0) { + SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); Para.Para64 = 0; SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); @@ -797,6 +530,7 @@ SK_U32 HwStatus) /* Interrupt status word */ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); Para.Para64 = MAC_1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } @@ -808,39 +542,297 @@ SK_U32 HwStatus) /* Interrupt status word */ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); Para.Para64 = MAC_2; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + Para.Para32[0] = MAC_2; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } -} /* SkGeHwErr */ +} /* SkGeYuHwErr */ +#ifdef YUK2 +/****************************************************************************** + * + * SkYuk2HwPortErr() - Service HW Errors for specified port (Yukon-2 only) + * + * Description: handles the HW Error interrupts for a specific port. + * + * Returns: N/A + */ +static void SkYuk2HwPortErr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 HwStatus, /* Interrupt status word */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_EVPARA Para; + int Queue; + + if (Port == MAC_2) { + HwStatus >>= 8; + } + + if ((HwStatus & Y2_HWE_L1_MASK) == 0) { + return; + } + + if ((HwStatus & Y2_IS_PAR_RD1) != 0) { + /* Clear IRQ */ + SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_RD_PERR); + + if (Port == MAC_1) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E028, SKERR_SIRQ_E028MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E030, SKERR_SIRQ_E030MSG); + } + } + + if ((HwStatus & Y2_IS_PAR_WR1) != 0) { + /* Clear IRQ */ + SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_WR_PERR); + + if (Port == MAC_1) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E029, SKERR_SIRQ_E029MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E031, SKERR_SIRQ_E031MSG); + } + } + + if ((HwStatus & Y2_IS_PAR_MAC1) != 0) { + /* Clear IRQ */ + SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), GMF_CLI_TX_PE); + + if (Port == MAC_1) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); + } + } + + if ((HwStatus & Y2_IS_PAR_RX1) != 0) { + if (Port == MAC_1) { + Queue = Q_R1; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); + } + else { + Queue = Q_R2; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); + } + /* Clear IRQ */ + SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_PAR); + } + + if ((HwStatus & Y2_IS_TCP_TXS1) != 0) { + if (Port == MAC_1) { + Queue = Q_XS1; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E033, SKERR_SIRQ_E033MSG); + } + else { + Queue = Q_XS2; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E035, SKERR_SIRQ_E035MSG); + } + /* Clear IRQ */ + SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP); + } + + if ((HwStatus & Y2_IS_TCP_TXA1) != 0) { + if (Port == MAC_1) { + Queue = Q_XA1; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E032, SKERR_SIRQ_E032MSG); + } + else { + Queue = Q_XA2; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E034, SKERR_SIRQ_E034MSG); + } + /* Clear IRQ */ + SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP); + } + + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + + Para.Para32[0] = Port; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + +} /* SkYuk2HwPortErr */ /****************************************************************************** * - * SkGeSirqIsr() - Special Interrupt Service Routine + * SkYuk2HwErr() - Hardware Error service routine (Yukon-2 only) + * + * Description: handles all HW Error interrupts + * + * Returns: N/A + */ +static void SkYuk2HwErr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 HwStatus) /* Interrupt status word */ +{ + SK_EVPARA Para; + SK_U16 Word; + SK_U32 DWord; + SK_U32 TlpHead[4]; + int i; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("HW-Error Status: 0x%08lX\n", HwStatus)); + + /* This is necessary only for Rx timing measurements */ + if ((HwStatus & Y2_IS_TIST_OV) != 0) { + /* increment Time Stamp Timer counter (high) */ + pAC->GIni.GITimeStampCnt++; + + /* Clear Time Stamp Timer IRQ */ + SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); + } + + /* Evaluate Y2_IS_PCI_NEXP before Y2_IS_MST_ERR or Y2_IS_IRQ_STAT */ + if ((HwStatus & Y2_IS_PCI_NEXP) != 0) { + /* + * This error is also mapped either to Master Abort (Y2_IS_MST_ERR) + * or Target Abort (Y2_IS_IRQ_STAT) bit and can only be cleared there. + * Therefore handle this event just by printing an error log entry. + */ + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E027, SKERR_SIRQ_E027MSG); + } + + if ((HwStatus & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) != 0) { + /* PCI Errors occured */ + if ((HwStatus & Y2_IS_IRQ_STAT) != 0) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); + } + + /* Reset all bits in the PCI STATUS register */ + SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); + } + + /* check for PCI-Express Uncorrectable Error */ + if ((HwStatus & Y2_IS_PCI_EXP) != 0) { + /* + * On PCI-Express bus bridges are called root complexes (RC). + * PCI-Express errors are recognized by the root complex too, + * which requests the system to handle the problem. After error + * occurence it may be that no access to the adapter may be performed + * any longer. + */ + + /* Get uncorrectable error status */ + SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("PEX Uncorr.Error Status: 0x%08lX\n", DWord)); + + if (DWord != PEX_UNSUP_REQ) { + /* ignore Unsupported Request Errors */ + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E026, SKERR_SIRQ_E026MSG); + } + + if ((DWord & (PEX_FATAL_ERRORS | PEX_POIS_TLP)) != 0) { + /* + * Stop only, if the uncorrectable error is fatal or + * Poisoned TLP occured + */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Header Log:")); + + for (i = 0; i < 4; i++) { + /* get TLP Header from Log Registers */ + SK_IN32(IoC, PCI_C(pAC, PEX_HEADER_LOG + i*4), &TlpHead[i]); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + (" 0x%08lX", TlpHead[i])); + } + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("\n")); + + /* check for vendor defined broadcast message */ + if (TlpHead[0] == 0x73004001 && (SK_U8)TlpHead[1] == 0x7f) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Vendor defined broadcast message\n")); + } + else { + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); + + pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP; + /* Rewrite HW IRQ mask */ + SK_OUT32(IoC, B0_HWE_IMSK, pAC->GIni.GIValHwIrqMask); + } + } + + /* clear any PEX errors */ + SK_OUT32(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + SK_OUT32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), 0xffffffffUL); + SK_OUT32(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord); + + if ((DWord & PEX_RX_OV) != 0) { + /* Dev #4.205 occured */ + pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP; + pAC->GIni.GIValIrqMask &= ~Y2_IS_HW_ERR; + } + } + + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + + SkYuk2HwPortErr(pAC, IoC, HwStatus, i); + } + +} /* SkYuk2HwErr */ +#endif /* YUK2 */ + +/****************************************************************************** + * + * SkGeSirqIsr() - Wrapper for Special Interrupt Service Routine + * + * Description: calls the preselected special ISR (slow path) + * + * Returns: N/A + */ +void SkGeSirqIsr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O context */ +SK_U32 Istatus) /* Interrupt status word */ +{ + pAC->GIni.GIFunc.pSkGeSirqIsr(pAC, IoC, Istatus); +} + +/****************************************************************************** + * + * SkGeYuSirqIsr() - Special Interrupt Service Routine * * Description: handles all non data transfer specific interrupts (slow path) * * Returns: N/A */ -void SkGeSirqIsr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +void SkGeYuSirqIsr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ SK_U32 Istatus) /* Interrupt status word */ { SK_EVPARA Para; SK_U32 RegVal32; /* Read register value */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ - unsigned Len; - SK_U64 Octets; - SK_U16 PhyInt; - SK_U16 PhyIMsk; + SK_U16 PhyInt; int i; - if ((Istatus & IS_HW_ERR) != 0) { + if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) { /* read the HW Error Interrupt source */ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); - SkGeHwErr(pAC, IoC, RegVal32); + SkGeYuHwErr(pAC, IoC, RegVal32); } /* @@ -855,7 +847,7 @@ SK_U32 Istatus) /* Interrupt status word */ } if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) && - pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { + pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { /* MAC 2 was not initialized but Packet timeout occured */ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, SKERR_SIRQ_E005MSG); @@ -877,69 +869,86 @@ SK_U32 Istatus) /* Interrupt status word */ if ((Istatus & IS_PA_TO_TX1) != 0) { - pPrt = &pAC->GIni.GP[0]; + pPrt = &pAC->GIni.GP[MAC_1]; /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); - /* - * workaround: if in half duplex mode, check for Tx hangup. - * Read number of TX'ed bytes, wait for 10 ms, then compare - * the number with current value. If nothing changed, we assume - * that Tx is hanging and do a FIFO flush (see event routine). - */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { /* - * many more pack. arb. timeouts may come in between, - * we ignore those + * workaround: if in half duplex mode, check for Tx hangup. + * Read number of TX'ed bytes, wait for 10 ms, then compare + * the number with current value. If nothing changed, we assume + * that Tx is hanging and do a FIFO flush (see event routine). */ - pPrt->HalfDupTimerActive = SK_TRUE; + if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && + !pPrt->HalfDupTimerActive) { + /* + * many more pack. arb. timeouts may come in between, + * we ignore those + */ + pPrt->HalfDupTimerActive = SK_TRUE; - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 0), - pAC->Rlmt.Port[0].Net->NetNumber); + /* Snap statistic counters */ + (void)SkXmUpdateStats(pAC, IoC, 0); - pPrt->LastOctets = Octets; + (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32); - Para.Para32[0] = 0; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); + pPrt->LastOctets = (SK_U64)RegVal32 << 32; + + (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32); + + pPrt->LastOctets += RegVal32; + + Para.Para32[0] = 0; + SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, + SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); + } } +#endif /* GENESIS */ } if ((Istatus & IS_PA_TO_TX2) != 0) { - pPrt = &pAC->GIni.GP[1]; + pPrt = &pAC->GIni.GP[MAC_2]; /* May be a normal situation in a server with a slow network */ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); - /* workaround: see above */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { - pPrt->HalfDupTimerActive = SK_TRUE; +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + /* workaround: see above */ + if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && + !pPrt->HalfDupTimerActive) { + pPrt->HalfDupTimerActive = SK_TRUE; - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 1), - pAC->Rlmt.Port[1].Net->NetNumber); + /* Snap statistic counters */ + (void)SkXmUpdateStats(pAC, IoC, 1); - pPrt->LastOctets = Octets; + (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32); - Para.Para32[0] = 1; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); + pPrt->LastOctets = (SK_U64)RegVal32 << 32; + + (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32); + + pPrt->LastOctets += RegVal32; + + Para.Para32[0] = 1; + SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, + SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); + } } +#endif /* GENESIS */ } /* Check interrupts of the particular queues */ if ((Istatus & IS_R1_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, SKERR_SIRQ_E006MSG); Para.Para64 = MAC_1; @@ -951,6 +960,7 @@ SK_U32 Istatus) /* Interrupt status word */ if ((Istatus & IS_R2_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, SKERR_SIRQ_E007MSG); Para.Para64 = MAC_2; @@ -962,6 +972,7 @@ SK_U32 Istatus) /* Interrupt status word */ if ((Istatus & IS_XS1_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, SKERR_SIRQ_E008MSG); Para.Para64 = MAC_1; @@ -973,8 +984,10 @@ SK_U32 Istatus) /* Interrupt status word */ if ((Istatus & IS_XA1_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, SKERR_SIRQ_E009MSG); + Para.Para64 = MAC_1; SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); Para.Para32[0] = MAC_1; @@ -984,6 +997,7 @@ SK_U32 Istatus) /* Interrupt status word */ if ((Istatus & IS_XS2_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, SKERR_SIRQ_E010MSG); Para.Para64 = MAC_2; @@ -995,6 +1009,7 @@ SK_U32 Istatus) /* Interrupt status word */ if ((Istatus & IS_XA2_C) != 0) { /* Clear IRQ */ SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, SKERR_SIRQ_E011MSG); Para.Para64 = MAC_2; @@ -1014,59 +1029,66 @@ SK_U32 Istatus) /* Interrupt status word */ continue; } - switch (pPrt->PhyType) { +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { - case SK_PHY_XMAC: - break; + switch (pPrt->PhyType) { - case SK_PHY_BCOM: - SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); - SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_MASK, &PhyIMsk); + case SK_PHY_XMAC: + break; - if ((PhyInt & ~PhyIMsk) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Bcom Int: 0x%04X Mask: 0x%04X\n", - i, PhyInt, PhyIMsk)); - SkPhyIsrBcom(pAC, IoC, i, PhyInt); + case SK_PHY_BCOM: + SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); + + if ((PhyInt & ~PHY_B_DEF_MSK) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Port %d PHY Int: 0x%04X\n", i, PhyInt)); + SkPhyIsrBcom(pAC, IoC, i, PhyInt); + } + break; +#ifdef OTHER_PHY + case SK_PHY_LONE: + SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); + + if ((PhyInt & PHY_L_DEF_MSK) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Port %d PHY Int: 0x%04X\n", i, PhyInt)); + SkPhyIsrLone(pAC, IoC, i, PhyInt); + } + break; +#endif /* OTHER_PHY */ } - break; + } +#endif /* GENESIS */ - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: +#ifdef YUKON + if (pAC->GIni.GIYukon) { + /* Read PHY Interrupt Status */ SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); - SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_MASK, &PhyIMsk); - if ((PhyInt & PhyIMsk) != 0) { + if ((PhyInt & PHY_M_DEF_MSK) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Marv Int: 0x%04X Mask: 0x%04X\n", - i, PhyInt, PhyIMsk)); + ("Port %d PHY Int: 0x%04X\n", i, PhyInt)); SkPhyIsrGmac(pAC, IoC, i, PhyInt); } - break; - -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); - SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_ENAB, &PhyIMsk); - - if ((PhyInt & PhyIMsk) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Lone Int: %x Mask: %x\n", - i, PhyInt, PhyIMsk)); - SkPhyIsrLone(pAC, IoC, i, PhyInt); - } - break; - case SK_PHY_NAT: - /* todo: National */ - break; -#endif /* OTHER_PHY */ } +#endif /* YUKON */ } } - /* I2C Ready interrupt */ + /* TWSI Ready interrupt */ if ((Istatus & IS_I2C_READY) != 0) { +#ifdef SK_SLIM + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); +#else SkI2cIsr(pAC, IoC); +#endif + } + + /* SW forced interrupt */ + if ((Istatus & IS_IRQ_SW) != 0) { + /* clear the software IRQ */ + SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); } if ((Istatus & IS_LNK_SYNC_M1) != 0) { @@ -1075,7 +1097,7 @@ SK_U32 Istatus) /* Interrupt status word */ * us only a link going down. */ /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); + SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LNK_CLR_IRQ); } /* Check MAC after link sync counter */ @@ -1090,7 +1112,7 @@ SK_U32 Istatus) /* Interrupt status word */ * us only a link going down. */ /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); + SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LNK_CLR_IRQ); } /* Check MAC after link sync counter */ @@ -1101,11 +1123,211 @@ SK_U32 Istatus) /* Interrupt status word */ /* Timer interrupt (served last) */ if ((Istatus & IS_TIMINT) != 0) { + /* check for HW Errors */ + if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { + /* read the HW Error Interrupt source */ + SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); + + SkGeYuHwErr(pAC, IoC, RegVal32); + } + SkHwtIsr(pAC, IoC); } -} /* SkGeSirqIsr */ + +} /* SkGeYuSirqIsr */ + +#ifdef YUK2 +/****************************************************************************** + * + * SkYuk2PortSirq() - Service HW Errors for specified port (Yukon-2 only) + * + * Description: handles the HW Error interrupts for a specific port. + * + * Returns: N/A + */ +static void SkYuk2PortSirq( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 IStatus, /* Interrupt status word */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_EVPARA Para; + int Queue; + SK_U16 PhyInt; + + if (Port == MAC_2) { + IStatus >>= 8; + } + + /* Interrupt from PHY */ + if ((IStatus & Y2_IS_IRQ_PHY1) != 0) { + /* Read PHY Interrupt Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyInt); + + if ((PhyInt & PHY_M_DEF_MSK) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Port %d PHY Int: 0x%04X\n", Port, PhyInt)); + SkPhyIsrGmac(pAC, IoC, Port, PhyInt); + } + } + + /* Interrupt from MAC */ + if ((IStatus & Y2_IS_IRQ_MAC1) != 0) { + SkMacIrq(pAC, IoC, Port); + } + + if ((IStatus & (Y2_IS_CHK_RX1 | Y2_IS_CHK_TXS1 | Y2_IS_CHK_TXA1)) != 0) { + if ((IStatus & Y2_IS_CHK_RX1) != 0) { + if (Port == MAC_1) { + Queue = Q_R1; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E006, + SKERR_SIRQ_E006MSG); + } + else { + Queue = Q_R2; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E007, + SKERR_SIRQ_E007MSG); + } + /* Clear IRQ */ + SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK); + } + + if ((IStatus & Y2_IS_CHK_TXS1) != 0) { + if (Port == MAC_1) { + Queue = Q_XS1; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E008, + SKERR_SIRQ_E008MSG); + } + else { + Queue = Q_XS2; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E010, + SKERR_SIRQ_E010MSG); + } + /* Clear IRQ */ + SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK); + } + + if ((IStatus & Y2_IS_CHK_TXA1) != 0) { + if (Port == MAC_1) { + Queue = Q_XA1; + + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E009, + SKERR_SIRQ_E009MSG); + + } + else { + Queue = Q_XA2; + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E011, + SKERR_SIRQ_E011MSG); + } + /* Clear IRQ */ + SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK); + } + + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); + + Para.Para32[0] = Port; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } +} /* SkYuk2PortSirq */ +#endif /* YUK2 */ + +/****************************************************************************** + * + * SkYuk2SirqIsr() - Special Interrupt Service Routine (Yukon-2 only) + * + * Description: handles all non data transfer specific interrupts (slow path) + * + * Returns: N/A + */ +void SkYuk2SirqIsr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Istatus) /* Interrupt status word */ +{ +#ifdef YUK2 + SK_EVPARA Para; + SK_U32 RegVal32; /* Read register value */ + SK_U8 Value; + + /* HW Error indicated ? */ + if (((Istatus & Y2_IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) { + /* read the HW Error Interrupt source */ + SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); + + SkYuk2HwErr(pAC, IoC, RegVal32); + } + + /* Interrupt from ASF Subsystem */ + if ((Istatus & Y2_IS_ASF) != 0) { + /* clear IRQ */ + /* later on clearing should be done in ASF ISR handler */ + SK_IN8(IoC, B28_Y2_ASF_STAT_CMD, &Value); + Value |= Y2_ASF_CLR_HSTI; + SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, Value); + /* Call IRQ handler in ASF Module */ + /* TBD */ + } + + /* Check IRQ from polling unit */ + if ((Istatus & Y2_IS_POLL_CHK) != 0) { + /* Clear IRQ */ + SK_OUT32(IoC, POLL_CTRL, PC_CLR_IRQ_CHK); + + SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E036, + SKERR_SIRQ_E036MSG); + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); + } + + /* TWSI Ready interrupt */ + if ((Istatus & Y2_IS_TWSI_RDY) != 0) { +#ifdef SK_SLIM + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); +#else + SkI2cIsr(pAC, IoC); +#endif + } + + /* SW forced interrupt */ + if ((Istatus & Y2_IS_IRQ_SW) != 0) { + /* clear the software IRQ */ + SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); + } + + if ((Istatus & Y2_IS_L1_MASK) != 0) { + SkYuk2PortSirq(pAC, IoC, Istatus, MAC_1); + } + + if ((Istatus & Y2_IS_L2_MASK) != 0) { + SkYuk2PortSirq(pAC, IoC, Istatus, MAC_2); + } + + /* Timer interrupt (served last) */ + if ((Istatus & Y2_IS_TIMINT) != 0) { + + if (((Istatus & Y2_IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { + /* read the HW Error Interrupt source */ + SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); + + /* otherwise we would generate error log entries periodically */ + RegVal32 &= pAC->GIni.GIValHwIrqMask; + if (RegVal32 != 0) { + SkYuk2HwErr(pAC, IoC, RegVal32); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Timer Int: 0x%08lX\n", Istatus)); + SkHwtIsr(pAC, IoC); + } +#endif /* YUK2 */ + +} /* SkYuk2SirqIsr */ +#ifdef GENESIS /****************************************************************************** * * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 @@ -1114,10 +1336,10 @@ SK_U32 Istatus) /* Interrupt status word */ * 0 o.k. nothing needed * 1 Restart needed on this port */ -static int SkGePortCheckShorts( +static int SkGePortCheckShorts( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ +SK_IOC IoC, /* I/O Context */ +int Port) /* Port Index (MAC_1 + n) */ { SK_U32 Shorts; /* Short Event Counter */ SK_U32 CheckShorts; /* Check value for Short Event Counter */ @@ -1139,13 +1361,15 @@ int Port) /* Which port should be checked */ (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); /* - * Read Rx counter (packets seen on the network and not necessarily + * Read Rx counters (packets seen on the network and not necessarily * really received. */ RxCts = 0; for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) { + (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); + RxCts += (SK_U64)RxTmp; } @@ -1163,10 +1387,10 @@ int Port) /* Which port should be checked */ (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && - (pPrt->PLinkMode == SK_LMODE_HALF || - pPrt->PLinkMode == SK_LMODE_FULL)) { + if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_UNKNOWN && + (pPrt->PLinkMode == (SK_U8)SK_LMODE_HALF || + pPrt->PLinkMode == (SK_U8)SK_LMODE_FULL)) { /* * This is autosensing and we are in the fallback * manual full/half duplex mode. @@ -1179,12 +1403,12 @@ int Port) /* Which port should be checked */ return(SK_HW_PS_RESTART); } else { - pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; + pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_MANUAL; } } if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || - (!(FcsErrCts - pPrt->PPrevFcs))) { + (!(FcsErrCts - pPrt->PPrevFcs))) { /* * Note: The compare with zero above has to be done the way shown, * otherwise the Linux driver will have a problem. @@ -1215,6 +1439,7 @@ int Port) /* Which port should be checked */ return(Rtv); } /* SkGePortCheckShorts */ +#endif /* GENESIS */ /****************************************************************************** @@ -1226,30 +1451,57 @@ int Port) /* Which port should be checked */ * 1 Restart needed on this port * 2 Link came up */ -static int SkGePortCheckUp( +static int SkGePortCheckUp( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ +SK_IOC IoC, /* I/O Context */ +int Port) /* Port Index (MAC_1 + n) */ { - switch (pAC->GIni.GP[Port].PhyType) { - case SK_PHY_XMAC: - return(SkGePortCheckUpXmac(pAC, IoC, Port)); - case SK_PHY_BCOM: - return(SkGePortCheckUpBcom(pAC, IoC, Port)); - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: - return(SkGePortCheckUpGmac(pAC, IoC, Port)); + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ + int Rtv; /* Return value */ + + Rtv = SK_HW_PS_NONE; + + pPrt = &pAC->GIni.GP[Port]; + + AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF && + pPrt->PLinkMode != SK_LMODE_FULL; + +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + + switch (pPrt->PhyType) { + + case SK_PHY_XMAC: + Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg); + break; + case SK_PHY_BCOM: + Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg); + break; #ifdef OTHER_PHY - case SK_PHY_LONE: - return(SkGePortCheckUpLone(pAC, IoC, Port)); - case SK_PHY_NAT: - return(SkGePortCheckUpNat(pAC, IoC, Port)); + case SK_PHY_LONE: + Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg); + break; + case SK_PHY_NAT: + Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg); + break; #endif /* OTHER_PHY */ + } } - return(SK_HW_PS_NONE); +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + + Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg); + } +#endif /* YUKON */ + + return(Rtv); } /* SkGePortCheckUp */ +#ifdef GENESIS /****************************************************************************** * * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 @@ -1261,8 +1513,9 @@ int Port) /* Which port should be checked */ */ static int SkGePortCheckUpXmac( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ { SK_U32 Shorts; /* Short Event Counter */ SK_GEPORT *pPrt; /* GIni Port struct pointer */ @@ -1273,7 +1526,6 @@ int Port) /* Which port should be checked */ SK_U16 LpAb; /* Link Partner Ability */ SK_U16 ResAb; /* Resolved Ability */ SK_U16 ExtStat; /* Extended Status Register */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ SK_U8 NextMode; /* Next AutoSensing Mode */ pPrt = &pAC->GIni.GP[Port]; @@ -1291,13 +1543,6 @@ int Port) /* Which port should be checked */ pPrt->PIsave = 0; /* Now wait for each port's link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - if (pPrt->PLinkBroken) { /* Link was broken */ XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); @@ -1326,7 +1571,7 @@ int Port) /* Which port should be checked */ * Link Restart Workaround: * it may be possible that the other Link side * restarts its link as well an we detect - * another LinkBroken. To prevent this + * another PLinkBroken. To prevent this * happening we check for a maximum number * of consecutive restart. If those happens, * we do NOT restart the active link and @@ -1374,7 +1619,7 @@ int Port) /* Which port should be checked */ if ((Isrc & XM_IS_INP_ASS) != 0) { pPrt->PLinkBroken = SK_TRUE; /* Re-Init Link partner Autoneg flag */ - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; + pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN; SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link broken Port %d\n", Port)); @@ -1387,6 +1632,7 @@ int Port) /* Which port should be checked */ } else { SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); + if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { return(SK_HW_PS_RESTART); } @@ -1418,20 +1664,26 @@ int Port) /* Which port should be checked */ } if (AutoNeg) { + /* Auto-Negotiation Done ? */ if ((IsrcSum & XM_IS_AND) != 0) { + SkHWLinkUp(pAC, IoC, Port); + Done = SkMacAutoNegDone(pAC, IoC, Port); + if (Done != SK_AND_OK) { /* Get PHY parameters, for debugging only */ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb); SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", - Port, LpAb, ResAb)); + Port, LpAb, ResAb)); /* Try next possible mode */ NextMode = SkHWSenseGetNext(pAC, IoC, Port); + SkHWLinkDown(pAC, IoC, Port); + if (Done == SK_AND_DUP_CAP) { /* GoTo next mode */ SkHWSenseSetNext(pAC, IoC, Port, NextMode); @@ -1444,43 +1696,41 @@ int Port) /* Which port should be checked */ * (clear Page Received bit if set) */ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); + return(SK_HW_PS_LINK); } /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { + if (pPrt->PAutoNegTimeOut++ >= SK_AND_MAX_TO) { /* Increase the Timeout counter */ pPrt->PAutoNegTOCt++; /* Timeout occured */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { + if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg != (SK_U8)SK_LIPA_AUTO) { /* Set Link manually up */ SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Set manual full duplex Port %d\n", Port)); } - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_AUTO && + if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO && pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { /* * This is rather complicated. * we need to check here whether the LIPA_AUTO * we saw before is false alert. We saw at one - * switch ( SR8800) that on boot time it sends + * switch (SR8800) that on boot time it sends * just one auto-neg packet and does no further * auto-negotiation. * Solution: we restart the autosensing after * a few timeouts. */ pPrt->PAutoNegTOCt = 0; - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; + pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN; SkHWInitDefSense(pAC, IoC, Port); } @@ -1491,8 +1741,8 @@ int Port) /* Which port should be checked */ else { /* Link is up and we don't need more */ #ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("ERROR: Lipa auto detected on port %d\n", Port)); } #endif /* DEBUG */ @@ -1501,8 +1751,8 @@ int Port) /* Which port should be checked */ SkHWLinkUp(pAC, IoC, Port); /* - * Link sync (GP) and so assume a good connection. But if not received - * a bunch of frames received in a time slot (maybe broken tx cable) + * Link sync (GP) and so assume a good connection. But if no + * bunch of frames received in a time slot (maybe broken Tx cable) * the port is restart. */ return(SK_HW_PS_LINK); @@ -1522,95 +1772,27 @@ int Port) /* Which port should be checked */ * 2 Link came up */ static int SkGePortCheckUpBcom( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ { SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Done; SK_U16 Isrc; /* Interrupt source register */ - SK_U16 PhyStat; /* Phy Status Register */ + SK_U16 PhyStat; /* PHY Status Register */ SK_U16 ResAb; /* Master/Slave resolution */ SK_U16 Ctrl; /* Broadcom control flags */ #ifdef DEBUG SK_U16 LpAb; SK_U16 ExtStat; #endif /* DEBUG */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ pPrt = &pAC->GIni.GP[Port]; /* Check for No HCD Link events (#10523) */ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); -#ifdef xDEBUG - if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) == - (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { - - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1 - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { /* * Workaround BCom Errata: @@ -1623,14 +1805,6 @@ int Port) /* Which port should be checked */ (SK_U16)(Ctrl & ~PHY_CT_LOOP)); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("No HCD Link event, Port %d\n", Port)); -#ifdef xDEBUG - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "No HCD link event, port %d.", - (void *)Port, - (void *)NULL); -#endif /* DEBUG */ } /* Not obsolete: link status bit is latched to 0 and autoclearing! */ @@ -1640,80 +1814,6 @@ int Port) /* Which port should be checked */ return(SK_HW_PS_NONE); } -#ifdef xDEBUG - { - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1a - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - Stat1 = Stat1 << 16 | PhyStat; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); - Stat2 = Stat2 << 16 | ResAb; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - - /* Now wait for each port's link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - /* * Here we usually can check whether the link is in sync and * auto-negotiation is done. @@ -1724,14 +1824,15 @@ int Port) /* Which port should be checked */ SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); + ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); if ((ResAb & PHY_B_1000S_MSF) != 0) { /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("Master/Slave Fault, ResAb: 0x%04X\n", ResAb)); + pPrt->PAutoNegFail = SK_TRUE; pPrt->PMSStatus = SK_MS_STAT_FAULT; @@ -1746,158 +1847,7 @@ int Port) /* Which port should be checked */ SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); - - if (AutoNeg) { - if ((PhyStat & PHY_ST_AN_OVER) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { -#ifdef DEBUG - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", - Port, LpAb, ExtStat)); -#endif /* DEBUG */ - return(SK_HW_PS_RESTART); - } - else { -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp2 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - return(SK_HW_PS_LINK); - } - } - } - else { /* !AutoNeg */ - /* Link is up and we don't need more. */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp3 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpBcom */ - - -/****************************************************************************** - * - * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpGmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source */ - SK_U16 PhyStat; /* Phy Status */ - SK_U16 PhySpecStat;/* Phy Specific Status */ - SK_U16 ResAb; /* Master/Slave resolution */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Read PHY Interrupt Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &Isrc); - - if ((Isrc & PHY_M_IS_AN_COMPL) != 0) { - /* TBD */ - } - - if ((Isrc & PHY_M_IS_DOWNSH_DET) != 0) { - /* TBD */ - } - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - /* Now wait for each port's link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat)); - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); - - if ((ResAb & PHY_B_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - - return(SK_HW_PS_RESTART); - } - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg: %d, PhySpecStat: 0x%04x\n", AutoNeg, PhySpecStat)); - - if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { - return(SK_HW_PS_NONE); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; - - pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); + ("Port %d, ResAb: 0x%04X\n", Port, ResAb)); if (AutoNeg) { /* Auto-Negotiation Over ? */ @@ -1908,23 +1858,211 @@ int Port) /* Which port should be checked */ Done = SkMacAutoNegDone(pAC, IoC, Port); if (Done != SK_AND_OK) { +#ifdef DEBUG + /* Get PHY parameters, for debugging only */ + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", + Port, LpAb, ExtStat)); +#endif /* DEBUG */ return(SK_HW_PS_RESTART); } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - return(SK_HW_PS_LINK); + else { + return(SK_HW_PS_LINK); + } } } else { /* !AutoNeg */ /* Link is up and we don't need more */ #ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("ERROR: Lipa auto detected on port %d\n", Port)); } #endif /* DEBUG */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, + ("Link sync(GP), Port %d\n", Port)); + SkHWLinkUp(pAC, IoC, Port); + + return(SK_HW_PS_LINK); + } + + return(SK_HW_PS_NONE); +} /* SkGePortCheckUpBcom */ +#endif /* GENESIS */ + + +#ifdef YUKON +/****************************************************************************** + * + * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY + * + * return: + * 0 o.k. nothing needed + * 1 Restart needed on this port + * 2 Link came up + */ +static int SkGePortCheckUpGmac( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ +{ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + int Done; + SK_U16 PhyStat; /* PHY Status */ + SK_U16 PhySpecStat;/* PHY Specific Status */ + SK_U16 ResAb; /* Master/Slave resolution */ +#ifndef SK_SLIM + SK_EVPARA Para; +#endif /* !SK_SLIM */ +#ifdef DEBUG + SK_U16 Word; /* I/O helper */ +#endif /* DEBUG */ + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PHWLinkUp) { + return(SK_HW_PS_NONE); + } + + /* Read PHY Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); + + SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); + + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); + + if ((ResAb & PHY_B_1000S_MSF) != 0) { + /* Error */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("Master/Slave Fault, ResAb: 0x%04X\n", ResAb)); + + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PMSStatus = SK_MS_STAT_FAULT; + + return(SK_HW_PS_RESTART); + } + } + + /* Read PHY Specific Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat)); + +#if (defined(DEBUG) && !defined(SK_SLIM)) + /* Read PHY Auto-Negotiation Expansion */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word); + + if (pAC->GIni.GICopperType && (Word & PHY_ANE_LP_CAP) == 0) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Link Partner not Auto-Neg. able, AN Exp.: 0x%04X\n", Word)); + } + + if ((Word & PHY_ANE_RX_PG) != 0 || + (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) { + /* Read PHY Next Page Link Partner */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Page received, NextPage: 0x%04X\n", Word)); + } +#endif /* DEBUG && !SK_SLIM */ + + if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { + /* Link down */ + return(SK_HW_PS_NONE); + } + +#ifdef XXX + SK_U16 PhyInt; + /* Read PHY Interrupt Status */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyInt); + + /* cross check that the link is really up */ + if ((PhyInt & PHY_M_IS_LST_CHANGE) == 0) { + /* Link Status unchanged */ + return(SK_HW_PS_NONE); + } +#endif /* XXX */ + +#ifndef SK_SLIM + if (pAC->GIni.GICopperType) { + + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { + + if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0) { + /* Downshift detected */ + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Downshift detected, PhySpecStat: 0x%04X\n", PhySpecStat)); + + SK_ERR_LOG(pAC, SK_ERRCL_CONFIG, SKERR_SIRQ_E025, + SKERR_SIRQ_E025MSG); + } + + pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? + SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; + } + + if ((PhySpecStat & PHY_M_PS_MDI_X_STAT) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("MDI Xover detected, PhyStat: 0x%04X\n", PhySpecStat)); + } + + /* on PHY 88E1112 & 88E1145 cable length is in Reg. 26, Page 5 */ + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL || + pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) { + /* select page 5 to access VCT DSP distance register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5); + + /* get VCT DSP distance */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL_2, &PhySpecStat); + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); + + pPrt->PCableLen = (SK_U8)(PhySpecStat & PHY_M_EC2_FO_AM_MSK); + } + else { + pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); + } + } +#endif /* !SK_SLIM */ + + if (AutoNeg) { + /* Auto-Negotiation Complete ? */ + if ((PhyStat & PHY_ST_AN_OVER) != 0) { + + SkHWLinkUp(pAC, IoC, Port); + + Done = SkMacAutoNegDone(pAC, IoC, Port); + + if (Done != SK_AND_OK) { + return(SK_HW_PS_RESTART); + } + + return(SK_HW_PS_LINK); + } + } + else { /* !AutoNeg */ +#if (defined(DEBUG) && !defined(SK_SLIM)) + if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("ERROR: Lipa auto detected on port %d\n", Port)); + } +#endif /* DEBUG && !SK_SLIM */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link sync, Port %d\n", Port)); SkHWLinkUp(pAC, IoC, Port); @@ -1935,6 +2073,8 @@ int Port) /* Which port should be checked */ return(SK_HW_PS_NONE); } /* SkGePortCheckUpGmac */ +#endif /* YUKON */ + #ifdef OTHER_PHY /****************************************************************************** @@ -1948,17 +2088,17 @@ int Port) /* Which port should be checked */ */ static int SkGePortCheckUpLone( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ { SK_GEPORT *pPrt; /* GIni Port struct pointer */ int Done; SK_U16 Isrc; /* Interrupt source register */ SK_U16 LpAb; /* Link Partner Ability */ SK_U16 ExtStat; /* Extended Status Register */ - SK_U16 PhyStat; /* Phy Status Register */ + SK_U16 PhyStat; /* PHY Status Register */ SK_U16 StatSum; - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ SK_U8 NextMode; /* Next AutoSensing Mode */ pPrt = &pAC->GIni.GP[Port]; @@ -1970,14 +2110,6 @@ int Port) /* Which port should be checked */ StatSum = pPrt->PIsave; pPrt->PIsave = 0; - /* Now wait for each ports link */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - /* * here we usually can check whether the link is in sync and * auto-negotiation is done. @@ -2000,20 +2132,26 @@ int Port) /* Which port should be checked */ } if (AutoNeg) { + /* Auto-Negotiation Over ? */ if ((StatSum & PHY_ST_AN_OVER) != 0) { + SkHWLinkUp(pAC, IoC, Port); + Done = SkMacAutoNegDone(pAC, IoC, Port); + if (Done != SK_AND_OK) { /* Get PHY parameters, for debugging only */ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", Port, LpAb, ExtStat)); /* Try next possible mode */ NextMode = SkHWSenseGetNext(pAC, IoC, Port); + SkHWLinkDown(pAC, IoC, Port); + if (Done == SK_AND_DUP_CAP) { /* GoTo next mode */ SkHWSenseSetNext(pAC, IoC, Port, NextMode); @@ -2028,20 +2166,17 @@ int Port) /* Which port should be checked */ * extra link down/ups */ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); return(SK_HW_PS_LINK); } } /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { + if (pPrt->PAutoNegTimeOut++ >= SK_AND_MAX_TO) { /* Timeout occured */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { + if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE && + pPrt->PLipaAutoNeg != (SK_U8)SK_LIPA_AUTO) { /* Set Link manually up */ SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, @@ -2055,8 +2190,8 @@ int Port) /* Which port should be checked */ else { /* Link is up and we don't need more */ #ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("ERROR: Lipa auto detected on port %d\n", Port)); } #endif /* DEBUG */ @@ -2069,7 +2204,9 @@ int Port) /* Which port should be checked */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Link sync(GP), Port %d\n", Port)); + SkHWLinkUp(pAC, IoC, Port); + return(SK_HW_PS_LINK); } @@ -2088,8 +2225,9 @@ int Port) /* Which port should be checked */ */ static int SkGePortCheckUpNat( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ { /* todo: National */ return(SK_HW_PS_NONE); @@ -2107,32 +2245,39 @@ int Port) /* Which port should be checked */ */ int SkGeSirqEvent( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ +SK_IOC IoC, /* I/O Context */ SK_U32 Event, /* Module specific Event */ SK_EVPARA Para) /* Event specific Parameter */ { - SK_U64 Octets; SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 Port; - SK_U32 Time; - unsigned Len; + int Port; + SK_U32 Val32; int PortStat; +#ifndef SK_SLIM SK_U8 Val8; +#endif +#ifdef GENESIS + SK_U64 Octets; +#endif /* GENESIS */ - Port = Para.Para32[0]; + Port = (int)Para.Para32[0]; pPrt = &pAC->GIni.GP[Port]; switch (Event) { case SK_HWEV_WATIM: - /* Check whether port came up */ - PortStat = SkGePortCheckUp(pAC, IoC, Port); + if (pPrt->PState == SK_PRT_RESET) { + + PortStat = SK_HW_PS_NONE; + } + else { + /* Check whether port came up */ + PortStat = SkGePortCheckUp(pAC, IoC, Port); + } switch (PortStat) { case SK_HW_PS_RESTART: if (pPrt->PHWLinkUp) { - /* - * Set Link to down. - */ + /* Set Link to down */ SkHWLinkDown(pAC, IoC, Port); /* @@ -2150,24 +2295,29 @@ SK_EVPARA Para) /* Event specific Parameter */ /* Signal to RLMT */ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); break; - } /* Start again the check Timer */ if (pPrt->PHWLinkUp) { - Time = SK_WA_ACT_TIME; + + Val32 = SK_WA_ACT_TIME; } else { - Time = SK_WA_INA_TIME; - } + Val32 = SK_WA_INA_TIME; - /* Todo: still needed for non-XMAC PHYs??? */ + if (pAC->GIni.GIYukon) { + Val32 *= 5; + } + } /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Time, + SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32, SKGE_HWAC, SK_HWEV_WATIM, Para); + break; case SK_HWEV_PORT_START: + +#ifndef SK_SLIM if (pPrt->PHWLinkUp) { /* * Signal directly to RLMT to ensure correct @@ -2175,6 +2325,7 @@ SK_EVPARA Para) /* Event specific Parameter */ */ SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); } +#endif /* !SK_SLIM */ SkHWLinkDown(pAC, IoC, Port); @@ -2184,9 +2335,11 @@ SK_EVPARA Para) /* Event specific Parameter */ /* Start workaround Errata #2 timer */ SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, SKGE_HWAC, SK_HWEV_WATIM, Para); + break; case SK_HWEV_PORT_STOP: +#ifndef SK_SLIM if (pPrt->PHWLinkUp) { /* * Signal directly to RLMT to ensure correct @@ -2194,6 +2347,7 @@ SK_EVPARA Para) /* Event specific Parameter */ */ SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); } +#endif /* !SK_SLIM */ /* Stop Workaround Timer */ SkTimerStop(pAC, IoC, &pPrt->PWaTimer); @@ -2201,13 +2355,14 @@ SK_EVPARA Para) /* Event specific Parameter */ SkHWLinkDown(pAC, IoC, Port); break; +#ifndef SK_SLIM case SK_HWEV_UPDATE_STAT: /* We do NOT need to update any statistics */ break; case SK_HWEV_CLEAR_STAT: /* We do NOT need to clear any statistics */ - for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) { + for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) { pPrt->PPrevRx = 0; pPrt->PPrevFcs = 0; pPrt->PPrevShorts = 0; @@ -2245,7 +2400,7 @@ SK_EVPARA Para) /* Event specific Parameter */ } Val8 = (SK_U8)Para.Para32[1]; if (pPrt->PMSMode != Val8) { - /* Set New link mode */ + /* Set New Role (Master/Slave) mode */ pPrt->PMSMode = Val8; /* Restart Port */ @@ -2268,27 +2423,38 @@ SK_EVPARA Para) /* Event specific Parameter */ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); } break; +#endif /* !SK_SLIM */ +#ifdef GENESIS case SK_HWEV_HALFDUP_CHK: - /* - * half duplex hangup workaround. - * See packet arbiter timeout interrupt for description - */ - pPrt->HalfDupTimerActive = SK_FALSE; - if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { + if (pAC->GIni.GIGenesis) { + /* + * half duplex hangup workaround. + * See packet arbiter timeout interrupt for description + */ + pPrt->HalfDupTimerActive = SK_FALSE; + if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || + pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { - Len = sizeof(SK_U64); - SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, - &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), - pAC->Rlmt.Port[Port].Net->NetNumber); + /* Snap statistic counters */ + (void)SkXmUpdateStats(pAC, IoC, Port); - if (pPrt->LastOctets == Octets) { - /* Tx hanging, a FIFO flush restarts it */ - SkMacFlushTxFifo(pAC, IoC, Port); + (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32); + + Octets = (SK_U64)Val32 << 32; + + (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32); + + Octets += Val32; + + if (pPrt->LastOctets == Octets) { + /* Tx hanging, a FIFO flush restarts it */ + SkMacFlushTxFifo(pAC, IoC, Port); + } } } break; +#endif /* GENESIS */ default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); @@ -2299,6 +2465,7 @@ SK_EVPARA Para) /* Event specific Parameter */ } /* SkGeSirqEvent */ +#ifdef GENESIS /****************************************************************************** * * SkPhyIsrBcom() - PHY interrupt service routine @@ -2309,8 +2476,8 @@ SK_EVPARA Para) /* Event specific Parameter */ */ static void SkPhyIsrBcom( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ SK_U16 IStatus) /* Interrupt Status */ { SK_GEPORT *pPrt; /* GIni Port struct pointer */ @@ -2320,15 +2487,15 @@ SK_U16 IStatus) /* Interrupt Status */ if ((IStatus & PHY_B_IS_PSE) != 0) { /* Incorrectable pair swap error */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E022, + SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022, SKERR_SIRQ_E022MSG); } if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { - Para.Para32[0] = (SK_U32)Port; SkHWLinkDown(pAC, IoC, Port); + Para.Para32[0] = (SK_U32)Port; /* Signal to RLMT */ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); @@ -2338,8 +2505,10 @@ SK_U16 IStatus) /* Interrupt Status */ } } /* SkPhyIsrBcom */ +#endif /* GENESIS */ +#ifdef YUKON /****************************************************************************** * * SkPhyIsrGmac() - PHY interrupt service routine @@ -2350,38 +2519,85 @@ SK_U16 IStatus) /* Interrupt Status */ */ static void SkPhyIsrGmac( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ SK_U16 IStatus) /* Interrupt Status */ { - SK_GEPORT *pPrt; /* GIni Port struct pointer */ + SK_GEPORT *pPrt; /* GIni Port struct pointer */ SK_EVPARA Para; +#ifdef XXX + SK_U16 Word; +#endif /* XXX */ pPrt = &pAC->GIni.GP[Port]; - if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Port %d PHY IRQ, PhyIsrc: 0x%04X\n", Port, IStatus)); + + if ((IStatus & PHY_M_IS_LST_CHANGE) != 0) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Link Status changed\n")); + Para.Para32[0] = (SK_U32)Port; - SkHWLinkDown(pAC, IoC, Port); + if (pPrt->PHWLinkUp) { - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + SkHWLinkDown(pAC, IoC, Port); + +#ifdef XXX + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg.Adv: 0x%04X\n", Word)); + + /* Set Auto-negotiation advertisement */ + if (pAC->GIni.GIChipId != CHIP_ID_YUKON_FE && + pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) { + /* restore Asymmetric Pause bit */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, + (SK_U16)(Word | PHY_M_AN_ASP)); + } +#endif /* XXX */ + + /* Signal to RLMT */ + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); + } + else { + if ((IStatus & PHY_M_IS_AN_COMPL) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Auto-Negotiation completed\n")); + } + + if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Link Speed changed\n")); + } + + SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_WATIM, Para); + } } if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { - /* Auto-Negotiation Error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); - } - - if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) { - /* TBD */ + /* the copper PHY makes 1 retry */ + if (pAC->GIni.GICopperType) { + /* not logged as error, it might be the first attempt */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Auto-Negotiation Error\n")); + } + else { + /* Auto-Negotiation Error */ + SK_ERR_LOG(pAC, SK_ERRCL_CONFIG, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); + } } if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { /* FIFO Overflow/Underrun Error */ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); } + } /* SkPhyIsrGmac */ +#endif /* YUKON */ #ifdef OTHER_PHY @@ -2395,23 +2611,24 @@ SK_U16 IStatus) /* Interrupt Status */ */ static void SkPhyIsrLone( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ SK_U16 IStatus) /* Interrupt Status */ { SK_EVPARA Para; if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { + SkHWLinkDown(pAC, IoC, Port); - /* Signal to RLMT */ Para.Para32[0] = (SK_U32)Port; + /* Signal to RLMT */ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); } } /* SkPhyIsrLone */ #endif /* OTHER_PHY */ -#endif /* CONFIG_SK98 */ - /* End of File */ + +#endif diff --git a/drivers/sk98lin/ski2c.c b/drivers/sk98lin/ski2c.c index 2ab635a..8c7b6cb 100644 --- a/drivers/sk98lin/ski2c.c +++ b/drivers/sk98lin/ski2c.c @@ -2,8 +2,8 @@ * * Name: ski2c.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.57 $ - * Date: $Date: 2003/01/28 09:17:38 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Functions to access Voltage and Temperature Sensor * ******************************************************************************/ @@ -26,6 +26,15 @@ * History: * * $Log: ski2c.c,v $ + * Revision 1.1.1.1 2008-12-15 11:39:21 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:11 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:16 wokes + * marvell 88f6281 u-boot + * * Revision 1.57 2003/01/28 09:17:38 rschmidt * Fixed handling for sensors on YUKON Fiber. * Editorial changes. @@ -236,7 +245,7 @@ * I2C Protocol */ static const char SysKonnectFileId[] = - "$Id: ski2c.c,v 1.57 2003/01/28 09:17:38 rschmidt Exp $"; + "$Id: ski2c.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $"; #include "h/skdrv1st.h" /* Driver Specific Definitions */ #include "h/lm80.h" diff --git a/drivers/sk98lin/sklm80.c b/drivers/sk98lin/sklm80.c index 687572b..8a3a901 100644 --- a/drivers/sk98lin/sklm80.c +++ b/drivers/sk98lin/sklm80.c @@ -1,16 +1,18 @@ /****************************************************************************** * * Name: sklm80.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.20 $ - * Date: $Date: 2002/08/13 09:16:27 $ - * Purpose: Funktions to access Voltage and Temperature Sensor (LM80) + * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Functions to access Voltage and Temperature Sensor (LM80) * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2002 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,95 +20,20 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. + * /LICENSE * ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: sklm80.c,v $ - * Revision 1.20 2002/08/13 09:16:27 rschmidt - * Changed return value for SkLm80ReadSensor() back to 'int' - * Editorial changes - * - * Revision 1.19 2002/08/06 09:43:31 jschmalz - * Extensions and changes for Yukon - * - * Revision 1.18 2002/08/02 12:26:57 rschmidt - * Editorial changes - * - * Revision 1.17 1999/11/22 13:35:51 cgoos - * Changed license header to GPL. - * - * Revision 1.16 1999/05/27 14:05:47 malthoff - * Fans: Set SenVal to 0 if the fan value is 0 or 0xff. Both values - * are outside the limits (0: div zero error, 0xff: value not in - * range, assume 0). - * - * Revision 1.15 1999/05/27 13:38:51 malthoff - * Pervent from Division by zero errors. - * - * Revision 1.14 1999/05/20 09:20:01 cgoos - * Changes for 1000Base-T (Fan sensors). - * - * Revision 1.13 1998/10/22 09:48:14 gklug - * fix: SysKonnectFileId typo - * - * Revision 1.12 1998/10/09 06:12:06 malthoff - * Remove ID_sccs by SysKonnectFileId. - * - * Revision 1.11 1998/09/04 08:33:48 malthoff - * bug fix: SenState = SK_SEN_IDLE when - * leaving SK_SEN_VALEXT state - * - * Revision 1.10 1998/08/20 12:02:10 gklug - * fix: compiler warnings type mismatch - * - * Revision 1.9 1998/08/20 11:37:38 gklug - * chg: change Ioc to IoC - * - * Revision 1.8 1998/08/19 12:20:58 gklug - * fix: remove struct from C files (see CCC) - * - * Revision 1.7 1998/08/17 07:04:57 malthoff - * Take SkLm80RcvReg() function from ski2c.c. - * Add IoC parameter to BREAK_OR_WAIT() macro. - * - * Revision 1.6 1998/08/14 07:11:28 malthoff - * remove pAc with pAC. - * - * Revision 1.5 1998/08/14 06:46:55 gklug - * fix: temperature can get negative - * - * Revision 1.4 1998/08/13 08:27:04 gklug - * add: temperature reading now o.k. - * fix: pSen declaration, SK_ERR_LOG call, ADDR macro - * - * Revision 1.3 1998/08/13 07:28:21 gklug - * fix: pSen was wrong initialized - * add: correct conversion for voltage readings - * - * Revision 1.2 1998/08/11 07:52:14 gklug - * add: Lm80 read sensor function - * - * Revision 1.1 1998/07/17 09:57:12 gklug - * initial version - * - * - * - ******************************************************************************/ - - #include - + #ifdef CONFIG_SK98 /* LM80 functions */ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Id: sklm80.c,v 1.20 2002/08/13 09:16:27 rschmidt Exp $" ; + "@(#) $Id: sklm80.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell. "; +#endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ #include "h/lm80.h" @@ -158,9 +85,9 @@ int Reg) /* register to read */ } Val = Val * SK_LM80_TEMP_LSB; SkI2cStop(IoC); - + TempExt = (int)SkLm80RcvReg(IoC, LM80_ADDR, LM80_TEMP_CTRL); - + if (Val > 0) { Val += ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); } @@ -175,7 +102,7 @@ int Reg) /* register to read */ case LM80_VT3_IN: Val = (int)SkI2cRcvByte(IoC, 1) * SK_LM80_VT_LSB; break; - + default: Val = (int)SkI2cRcvByte(IoC, 1); break; @@ -189,12 +116,12 @@ int Reg) /* register to read */ /* * read a sensors value (LM80 specific) * - * This function reads a sensors value from the I2C sensor chip LM80. + * This function reads a sensors value from the TWSI sensor chip LM80. * The sensor is defined by its index into the sensors database in the struct * pAC points to. * * Returns 1 if the read is completed - * 0 if the read must be continued (I2C Bus still allocated) + * 0 if the read must be continued (TWSI Bus still allocated) */ int SkLm80ReadSensor( SK_AC *pAC, /* Adapter Context */ @@ -206,15 +133,15 @@ SK_SENSOR *pSen) /* Sensor to be read */ switch (pSen->SenState) { case SK_SEN_IDLE: /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, pSen->SenReg, 0); + SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0); pSen->SenState = SK_SEN_VALUE ; BREAK_OR_WAIT(pAC, IoC, I2C_READ); - + case SK_SEN_VALUE: /* Read value from data register */ SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); - + Value &= 0xff; /* only least significant byte is valid */ /* Do NOT check the Value against the thresholds */ @@ -254,11 +181,11 @@ SK_SENSOR *pSen) /* Sensor to be read */ (pSen->SenValue % SK_LM80_TEMP_LSB); /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, LM80_TEMP_CTRL, 0); + SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0); pSen->SenState = SK_SEN_VALEXT ; BREAK_OR_WAIT(pAC, IoC, I2C_READ); - + case SK_SEN_VALEXT: /* Read value from data register */ SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); @@ -279,7 +206,7 @@ SK_SENSOR *pSen) /* Sensor to be read */ pSen->SenState = SK_SEN_IDLE ; return(1); - + default: SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG); return(1); @@ -289,4 +216,4 @@ SK_SENSOR *pSen) /* Sensor to be read */ return(0); } -#endif /* CONFIG_SK98 */ +#endif diff --git a/drivers/sk98lin/skproc.c b/drivers/sk98lin/skproc.c index 4e34073..727e535 100644 --- a/drivers/sk98lin/skproc.c +++ b/drivers/sk98lin/skproc.c @@ -1,139 +1,104 @@ /****************************************************************************** * - * Name: skproc.c + * Name: skproc.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2003/02/25 14:16:37 $ - * Purpose: Funktions to display statictic data + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Functions to display statictic data * ******************************************************************************/ - + /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. + * + * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet + * Server Adapters. + * + * Author: Ralph Roesler (rroesler@syskonnect.de) + * Mirko Lindner (mlindner@syskonnect.de) + * + * Address all question to: linux@syskonnect.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * Created 22-Nov-2000 - * Author: Mirko Lindner (mlindner@syskonnect.de) - * * The information in this file is provided "AS IS" without warranty. * - ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skproc.c,v $ - * Revision 1.4 2003/02/25 14:16:37 mlindner - * Fix: Copyright statement - * - * Revision 1.3 2002/10/02 12:59:51 mlindner - * Add: Support for Yukon - * Add: Speed check and setup - * Add: Merge source for kernel 2.2.x and 2.4.x - * Add: Read sensor names directly from VPD - * Fix: Volt values - * - * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner - * Fix: Editorial changes - * - * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner - * Fix: Return value of proc_read - * - * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner - * New ProcFs entries - * - * Revision 1.2.2.4 2001/09/05 12:16:02 mlindner - * Add: New ProcFs entries - * Fix: Counter Errors (Jumbo == to long errors) - * Fix: Kernel error compilation - * Fix: too short counters - * - * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner - * Add: More error messages - * - * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner - * fix: ProcFS owner protection - * - * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner - * chg: 2.4 requirements for procfs - * - * Revision 1.1 2001/01/22 14:15:31 mlindner - * added ProcFs functionality - * Dual Net functionality integrated - * Rlmt networks added - * - * - ******************************************************************************/ - + *****************************************************************************/ #include - + #ifdef CONFIG_SK98 +#if 0 /* uboot */ #include +#endif #include "h/skdrv1st.h" #include "h/skdrv2nd.h" -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIALX 32 /* 0x */ -#define LARGE 64 +#include "h/skversion.h" -extern SK_AC *pACList; -extern struct net_device *SkGeRootDev; +extern struct SK_NET_DEVICE *SkGeRootDev; -extern char * SkNumber( - char * str, - long long num, - int base, - int size, - int precision, - int type); +/****************************************************************************** + * + * Local Function Prototypes and Local Variables + * + *****************************************************************************/ +static int sk_proc_print(void *writePtr, char *format, ...); +static void sk_gen_browse(void *buffer); +static int len; + +static int sk_seq_show(struct seq_file *seq, void *v); +static int sk_proc_open(struct inode *inode, struct file *file); +struct file_operations sk_proc_fops = { + .owner = THIS_MODULE, + .open = sk_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +struct net_device *currDev = NULL; /***************************************************************************** * - * proc_read - print "summaries" entry + * sk_gen_browse -generic print "summaries" entry * * Description: - * This function fills the proc entry with statistic data about - * the ethernet device. - * - * - * Returns: buffer with statistic data - * + * This function fills the proc entry with statistic data about + * the ethernet device. + * + * Returns: N/A + * */ -int proc_read(char *buffer, -char **buffer_location, -off_t offset, -int buffer_length, -int *eof, -void *data) +static void sk_gen_browse( +void *buffer) /* buffer where the statistics will be stored in */ { - int len = 0; - int t; - int i; - DEV_NET *pNet; - SK_AC *pAC; - char test_buf[100]; - char sens_msg[50]; - unsigned long Flags; - unsigned int Size; - struct SK_NET_DEVICE *next; - struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev; - + struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev; + struct SK_NET_DEVICE *next; + SK_BOOL DisableStatistic = 0; SK_PNMI_STRUCT_DATA *pPnmiStruct; SK_PNMI_STAT *pPnmiStat; - struct proc_dir_entry *file = (struct proc_dir_entry*) data; + unsigned long Flags; + unsigned int Size; + DEV_NET *pNet; + SK_AC *pAC; + char sens_msg[50]; + int card_type; + int MaxSecurityCount = 0; + int t; + int i; while (SkgeProcDev) { + MaxSecurityCount++; + if (MaxSecurityCount > 100) { + printk("Max limit for sk_proc_read security counter!\n"); + return; + } pNet = (DEV_NET*) SkgeProcDev->priv; pAC = pNet->pAC; next = pAC->Next; @@ -146,370 +111,373 @@ void *data) spin_lock_irqsave(&pAC->SlowPathLock, Flags); Size = SK_PNMI_STRUCT_SIZE; - SkPnmiGetStruct(pAC, pAC->IoBase, - pPnmiStruct, &Size, t-1); + DisableStatistic = 0; + if (pAC->BoardLevel == SK_INIT_DATA) { + SK_MEMCPY(&(pAC->PnmiStruct), &(pAC->PnmiBackup), sizeof(SK_PNMI_STRUCT_DATA)); + if (pAC->DiagModeActive == DIAG_NOTACTIVE) { + pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; + } + } else { + SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1); + } spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + if (strcmp(pAC->dev[t-1]->name, currDev->name) == 0) { + if (!pAC->GIni.GIYukon32Bit) + card_type = 64; + else + card_type = 32; - if (strcmp(pAC->dev[t-1]->name, file->name) == 0) { pPnmiStat = &pPnmiStruct->Stat[0]; - len = sprintf(buffer, + len = sk_proc_print(buffer, "\nDetailed statistic for device %s\n", pAC->dev[t-1]->name); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "=======================================\n"); - + /* Board statistics */ - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "\nBoard statistics\n\n"); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, + "Card name %s\n", + pAC->DeviceStr); + len += sk_proc_print(buffer, + "Vendor/Device ID %x/%x\n", + pAC->PciDev->vendor, + pAC->PciDev->device); + len += sk_proc_print(buffer, + "Card type (Bit) %d\n", + card_type); + + len += sk_proc_print(buffer, "Active Port %c\n", 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. Net[t-1].PrefPort]->PortNumber); - len += sprintf(buffer + len, + len += sk_proc_print(buffer, "Preferred Port %c\n", 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. Net[t-1].PrefPort]->PortNumber); - len += sprintf(buffer + len, - "Bus speed (MHz) %d\n", - pPnmiStruct->BusSpeed); + if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) { + len += sk_proc_print(buffer, + "Interrupt Moderation static (%d ints/sec)\n", + pAC->DynIrqModInfo.MaxModIntsPerSec); + } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) { + len += sk_proc_print(buffer, + "Interrupt Moderation dynamic (%d ints/sec)\n", + pAC->DynIrqModInfo.MaxModIntsPerSec); + } else { + len += sk_proc_print(buffer, + "Interrupt Moderation disabled\n"); + } - len += sprintf(buffer + len, - "Bus width (Bit) %d\n", - pPnmiStruct->BusWidth); - len += sprintf(buffer + len, + if (pAC->GIni.GIPciBus == SK_PEX_BUS) { + len += sk_proc_print(buffer, + "Bus type PCI-Express\n"); + len += sk_proc_print(buffer, + "Bus width (Lanes) %d\n", + pAC->GIni.GIPexWidth); + } else { + if (pAC->GIni.GIPciBus == SK_PCIX_BUS) { + len += sk_proc_print(buffer, + "Bus type PCI-X\n"); + if (pAC->GIni.GIPciMode == PCI_OS_SPD_X133) { + len += sk_proc_print(buffer, + "Bus speed (MHz) 133\n"); + } else if (pAC->GIni.GIPciMode == PCI_OS_SPD_X100) { + len += sk_proc_print(buffer, + "Bus speed (MHz) 100\n"); + } else if (pAC->GIni.GIPciMode == PCI_OS_SPD_X66) { + len += sk_proc_print(buffer, + "Bus speed (MHz) 66\n"); + } else { + len += sk_proc_print(buffer, + "Bus speed (MHz) 33\n"); + } + } else { + len += sk_proc_print(buffer, + "Bus type PCI\n"); + len += sk_proc_print(buffer, + "Bus speed (MHz) %d\n", + pPnmiStruct->BusSpeed); + } + len += sk_proc_print(buffer, + "Bus width (Bit) %d\n", + pPnmiStruct->BusWidth); + } + + len += sk_proc_print(buffer, + "Driver version %s (%s)\n", + VER_STRING, PATCHLEVEL); + len += sk_proc_print(buffer, + "Driver release date %s\n", + pAC->Pnmi.pDriverReleaseDate); + len += sk_proc_print(buffer, "Hardware revision v%d.%d\n", (pAC->GIni.GIPciHwRev >> 4) & 0x0F, pAC->GIni.GIPciHwRev & 0x0F); + if (!netif_running(pAC->dev[t-1])) { + len += sk_proc_print(buffer, + "\n Device %s is down.\n" + " Therefore no statistics are available.\n" + " After bringing the device up (ifconfig)" + " statistics will\n" + " be displayed.\n", + pAC->dev[t-1]->name); + DisableStatistic = 1; + } + + /* Display only if statistic info available */ /* Print sensor informations */ - for (i=0; i < pAC->I2c.MaxSens; i ++) { - /* Check type */ - switch (pAC->I2c.SenTable[i].SenType) { - case 1: - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (C)"); - len += sprintf(buffer + len, - "%-25s %d.%02d\n", - sens_msg, - pAC->I2c.SenTable[i].SenValue / 10, - pAC->I2c.SenTable[i].SenValue % 10); + if (!DisableStatistic) { + for (i=0; i < pAC->I2c.MaxSens; i ++) { + /* Check type */ + switch (pAC->I2c.SenTable[i].SenType) { + case 1: + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (C)"); + len += sk_proc_print(buffer, + "%-25s %d.%02d\n", + sens_msg, + pAC->I2c.SenTable[i].SenValue / 10, + pAC->I2c.SenTable[i].SenValue % + 10); - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (F)"); - len += sprintf(buffer + len, - "%-25s %d.%02d\n", - sens_msg, - ((((pAC->I2c.SenTable[i].SenValue) - *10)*9)/5 + 3200)/100, - ((((pAC->I2c.SenTable[i].SenValue) - *10)*9)/5 + 3200) % 10); - break; - case 2: - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (V)"); - len += sprintf(buffer + len, - "%-25s %d.%03d\n", - sens_msg, - pAC->I2c.SenTable[i].SenValue / 1000, - pAC->I2c.SenTable[i].SenValue % 1000); - break; - case 3: - strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); - strcat(sens_msg, " (rpm)"); - len += sprintf(buffer + len, - "%-25s %d\n", - sens_msg, - pAC->I2c.SenTable[i].SenValue); - break; - default: - break; + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (F)"); + len += sk_proc_print(buffer, + "%-25s %d.%02d\n", + sens_msg, + ((((pAC->I2c.SenTable[i].SenValue) + *10)*9)/5 + 3200)/100, + ((((pAC->I2c.SenTable[i].SenValue) + *10)*9)/5 + 3200) % 10); + break; + case 2: + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (V)"); + len += sk_proc_print(buffer, + "%-25s %d.%03d\n", + sens_msg, + pAC->I2c.SenTable[i].SenValue / 1000, + pAC->I2c.SenTable[i].SenValue % 1000); + break; + case 3: + strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); + strcat(sens_msg, " (rpm)"); + len += sk_proc_print(buffer, + "%-25s %d\n", + sens_msg, + pAC->I2c.SenTable[i].SenValue); + break; + default: + break; + } } - } + + /*Receive statistics */ + len += sk_proc_print(buffer, + "\nReceive statistics\n\n"); - /*Receive statistics */ - len += sprintf(buffer + len, - "\nReceive statistics\n\n"); - - len += sprintf(buffer + len, - "Received bytes %s\n", - SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Received packets %s\n", - SkNumber(test_buf, pPnmiStat->StatRxOkCts, - 10,0,-1,0)); + len += sk_proc_print(buffer, + "Received bytes %Lu\n", + (unsigned long long) pPnmiStat->StatRxOctetsOkCts); + len += sk_proc_print(buffer, + "Received packets %Lu\n", + (unsigned long long) pPnmiStat->StatRxOkCts); #if 0 - if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && - pAC->HWRevision < 12) { - pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxShortsCts; - pPnmiStat->StatRxShortsCts = 0; - } + if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && + pAC->HWRevision < 12) { + pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - + pPnmiStat->StatRxShortsCts; + pPnmiStat->StatRxShortsCts = 0; + } #endif - if (pNet->Mtu > 1500) - pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxTooLongCts; + if (pAC->dev[t-1]->mtu > 1500) + pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - + pPnmiStat->StatRxTooLongCts; - len += sprintf(buffer + len, - "Receive errors %s\n", - SkNumber(test_buf, pPnmiStruct->InErrorsCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Receive drops %s\n", - SkNumber(test_buf, pPnmiStruct->RxNoBufCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Received multicast %s\n", - SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Receive error types\n"); - len += sprintf(buffer + len, - " length %s\n", - SkNumber(test_buf, pPnmiStat->StatRxRuntCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " buffer overflow %s\n", - SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " bad crc %s\n", - SkNumber(test_buf, pPnmiStat->StatRxFcsCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " framing %s\n", - SkNumber(test_buf, pPnmiStat->StatRxFramingCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " missed frames %s\n", - SkNumber(test_buf, pPnmiStat->StatRxMissedCts, - 10, 0, -1, 0)); + len += sk_proc_print(buffer, + "Receive errors %Lu\n", + (unsigned long long) pPnmiStruct->InErrorsCts); + len += sk_proc_print(buffer, + "Receive dropped %Lu\n", + (unsigned long long) pPnmiStruct->RxNoBufCts); + len += sk_proc_print(buffer, + "Received multicast %Lu\n", + (unsigned long long) pPnmiStat->StatRxMulticastOkCts); +#ifdef ADVANCED_STATISTIC_OUTPUT + len += sk_proc_print(buffer, + "Receive error types\n"); + len += sk_proc_print(buffer, + " length %Lu\n", + (unsigned long long) pPnmiStat->StatRxRuntCts); + len += sk_proc_print(buffer, + " buffer overflow %Lu\n", + (unsigned long long) pPnmiStat->StatRxFifoOverflowCts); + len += sk_proc_print(buffer, + " bad crc %Lu\n", + (unsigned long long) pPnmiStat->StatRxFcsCts); + len += sk_proc_print(buffer, + " framing %Lu\n", + (unsigned long long) pPnmiStat->StatRxFramingCts); + len += sk_proc_print(buffer, + " missed frames %Lu\n", + (unsigned long long) pPnmiStat->StatRxMissedCts); - if (pNet->Mtu > 1500) - pPnmiStat->StatRxTooLongCts = 0; + if (pAC->dev[t-1]->mtu > 1500) + pPnmiStat->StatRxTooLongCts = 0; - len += sprintf(buffer + len, - " too long %s\n", - SkNumber(test_buf, pPnmiStat->StatRxTooLongCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " carrier extension %s\n", - SkNumber(test_buf, pPnmiStat->StatRxCextCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " too short %s\n", - SkNumber(test_buf, pPnmiStat->StatRxShortsCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " symbol %s\n", - SkNumber(test_buf, pPnmiStat->StatRxSymbolCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " LLC MAC size %s\n", - SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " carrier event %s\n", - SkNumber(test_buf, pPnmiStat->StatRxCarrierCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " jabber %s\n", - SkNumber(test_buf, pPnmiStat->StatRxJabberCts, - 10, 0, -1, 0)); + len += sk_proc_print(buffer, + " too long %Lu\n", + (unsigned long long) pPnmiStat->StatRxTooLongCts); + len += sk_proc_print(buffer, + " carrier extension %Lu\n", + (unsigned long long) pPnmiStat->StatRxCextCts); + len += sk_proc_print(buffer, + " too short %Lu\n", + (unsigned long long) pPnmiStat->StatRxShortsCts); + len += sk_proc_print(buffer, + " symbol %Lu\n", + (unsigned long long) pPnmiStat->StatRxSymbolCts); + len += sk_proc_print(buffer, + " LLC MAC size %Lu\n", + (unsigned long long) pPnmiStat->StatRxIRLengthCts); + len += sk_proc_print(buffer, + " carrier event %Lu\n", + (unsigned long long) pPnmiStat->StatRxCarrierCts); + len += sk_proc_print(buffer, + " jabber %Lu\n", + (unsigned long long) pPnmiStat->StatRxJabberCts); +#endif - - /*Transmit statistics */ - len += sprintf(buffer + len, - "\nTransmit statistics\n\n"); - - len += sprintf(buffer + len, - "Transmited bytes %s\n", - SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmited packets %s\n", - SkNumber(test_buf, pPnmiStat->StatTxOkCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit errors %s\n", - SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit dropped %s\n", - SkNumber(test_buf, pPnmiStruct->TxNoBufCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit collisions %s\n", - SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts, - 10,0,-1,0)); - len += sprintf(buffer + len, - "Transmit errors types\n"); - len += sprintf(buffer + len, - " excessive collision %ld\n", - pAC->stats.tx_aborted_errors); - len += sprintf(buffer + len, - " carrier %s\n", - SkNumber(test_buf, pPnmiStat->StatTxCarrierCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " fifo underrun %s\n", - SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " heartbeat %s\n", - SkNumber(test_buf, pPnmiStat->StatTxCarrierCts, - 10, 0, -1, 0)); - len += sprintf(buffer + len, - " window %ld\n", - pAC->stats.tx_window_errors); - - } + /*Transmit statistics */ + len += sk_proc_print(buffer, + "\nTransmit statistics\n\n"); + + len += sk_proc_print(buffer, + "Transmitted bytes %Lu\n", + (unsigned long long) pPnmiStat->StatTxOctetsOkCts); + len += sk_proc_print(buffer, + "Transmitted packets %Lu\n", + (unsigned long long) pPnmiStat->StatTxOkCts); + len += sk_proc_print(buffer, + "Transmit errors %Lu\n", + (unsigned long long) pPnmiStat->StatTxSingleCollisionCts); + len += sk_proc_print(buffer, + "Transmit dropped %Lu\n", + (unsigned long long) pPnmiStruct->TxNoBufCts); + len += sk_proc_print(buffer, + "Transmit collisions %Lu\n", + (unsigned long long) pPnmiStat->StatTxSingleCollisionCts); +#ifdef ADVANCED_STATISTIC_OUTPUT + len += sk_proc_print(buffer, + "Transmit error types\n"); + len += sk_proc_print(buffer, + " excessive collision %ld\n", + pAC->stats.tx_aborted_errors); + len += sk_proc_print(buffer, + " carrier %Lu\n", + (unsigned long long) pPnmiStat->StatTxCarrierCts); + len += sk_proc_print(buffer, + " fifo underrun %Lu\n", + (unsigned long long) pPnmiStat->StatTxFifoUnderrunCts); + len += sk_proc_print(buffer, + " heartbeat %Lu\n", + (unsigned long long) pPnmiStat->StatTxCarrierCts); + len += sk_proc_print(buffer, + " window %ld\n", + pAC->stats.tx_window_errors); +#endif + } /* if (!DisableStatistic) */ + + } /* if (strcmp(pACname, currDeviceName) == 0) */ } SkgeProcDev = next; } - if (offset >= len) { - *eof = 1; - return 0; - } - - *buffer_location = buffer + offset; - if (buffer_length >= len - offset) { - *eof = 1; - } - return (min_t(int, buffer_length, len - offset)); } - /***************************************************************************** * - * SkDoDiv - convert 64bit number + * sk_proc_print - generic line print * * Description: - * This function "converts" a long long number. - * + * This function fills the proc entry with statistic data about the + * ethernet device. + * * Returns: - * remainder of division - */ -static long SkDoDiv (long long Dividend, int Divisor, long long *pErg) -{ - long Rest; - long long Ergebnis; - long Akku; + * the number of bytes written + * + */ +static int sk_proc_print( +void *writePtr, /* the buffer pointer */ +char *format, /* the format of the string */ +...) /* variable list of arguments */ +{ +#define MAX_LEN_SINGLE_LINE 256 + char str[MAX_LEN_SINGLE_LINE]; + va_list a_start; + int lenght = 0; + struct seq_file *seq = (struct seq_file *) writePtr; - Akku = Dividend >> 32; + SK_MEMSET(str, 0, MAX_LEN_SINGLE_LINE); - Ergebnis = ((long long) (Akku / Divisor)) << 32; - Rest = Akku % Divisor ; + va_start(a_start, format); + vsprintf(str, format, a_start); + va_end(a_start); - Akku = Rest << 16; - Akku |= ((Dividend & 0xFFFF0000) >> 16); + lenght = strlen(str); - - Ergebnis += ((long long) (Akku / Divisor)) << 16; - Rest = Akku % Divisor ; - - Akku = Rest << 16; - Akku |= (Dividend & 0xFFFF); - - Ergebnis += (Akku / Divisor); - Rest = Akku % Divisor ; - - *pErg = Ergebnis; - return (Rest); + seq_printf(seq, str); + return lenght; } +/***************************************************************************** + * + * sk_seq_show - show proc information of a particular adapter + * + * Description: + * This function fills the proc entry with statistic data about the + * ethernet device. It invokes the generic sk_gen_browse() to print + * out all items one per one. + * + * Returns: + * the number of bytes written + * + */ +static int sk_seq_show( +struct seq_file *seq, /* the sequence pointer */ +void *v) /* additional pointer */ +{ + void *castedBuffer = (void *) seq; + currDev = seq->private; + sk_gen_browse(castedBuffer); + return 0; +} -#if 0 -#define do_div(n,base) ({ \ -long long __res; \ -__res = ((unsigned long long) n) % (unsigned) base; \ -n = ((unsigned long long) n) / (unsigned) base; \ -__res; }) +/***************************************************************************** + * + * sk_proc_open - register the show function when proc is open'ed + * + * Description: + * This function is called whenever a sk98lin proc file is queried. + * + * Returns: + * the return value of single_open() + * + */ +static int sk_proc_open( +struct inode *inode, /* the inode of the file */ +struct file *file) /* the file pointer itself */ +{ + return single_open(file, sk_seq_show, PDE(inode)->data); +} + +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ #endif - - -/***************************************************************************** - * - * SkNumber - Print results - * - * Description: - * This function converts a long long number into a string. - * - * Returns: - * number as string - */ -char * SkNumber(char * str, long long num, int base, int size, int precision - ,int type) -{ - char c,sign,tmp[66], *strorg = str; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; - - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (num < 0) { - sign = '-'; - num = -num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIALX) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[SkDoDiv(num,base, &num)]; - - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIALX) { - if (base==8) - *str++ = '0'; - else if (base==16) { - *str++ = '0'; - *str++ = digits[33]; - } - } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - - str[0] = '\0'; - - return strorg; -} - -#endif /* CONFIG_SK98 */ diff --git a/drivers/sk98lin/skqueue.c b/drivers/sk98lin/skqueue.c index c49baed..28277a9 100644 --- a/drivers/sk98lin/skqueue.c +++ b/drivers/sk98lin/skqueue.c @@ -1,17 +1,17 @@ /****************************************************************************** * * Name: skqueue.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.18 $ - * Date: $Date: 2002/05/07 14:11:11 $ + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Management of an event queue. * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -22,80 +22,17 @@ * ******************************************************************************/ -/****************************************************************************** - * - * History: - * - * $Log: skqueue.c,v $ - * Revision 1.18 2002/05/07 14:11:11 rwahl - * Fixed Watcom Precompiler error. - * - * Revision 1.17 2002/03/25 10:06:41 mkunz - * SkIgnoreEvent deleted - * - * Revision 1.16 2002/03/15 10:51:59 mkunz - * Added event classes for link aggregation - * - * Revision 1.15 1999/11/22 13:36:29 cgoos - * Changed license header to GPL. - * - * Revision 1.14 1998/10/15 15:11:35 gklug - * fix: ID_sccs to SysKonnectFileId - * - * Revision 1.13 1998/09/08 08:47:52 gklug - * add: init level handling - * - * Revision 1.12 1998/09/08 07:43:20 gklug - * fix: Sirq Event function name - * - * Revision 1.11 1998/09/08 05:54:34 gklug - * chg: define SK_CSUM is replaced by SK_USE_CSUM - * - * Revision 1.10 1998/09/03 14:14:49 gklug - * add: CSUM and HWAC Eventclass and function. - * - * Revision 1.9 1998/08/19 09:50:50 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.8 1998/08/17 13:43:11 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.7 1998/08/14 07:09:11 gklug - * fix: chg pAc -> pAC - * - * Revision 1.6 1998/08/11 12:13:14 gklug - * add: return code feature of Event service routines - * add: correct Error log calls - * - * Revision 1.5 1998/08/07 12:53:45 gklug - * fix: first compiled version - * - * Revision 1.4 1998/08/07 09:20:48 gklug - * adapt functions to C coding conventions. - * - * Revision 1.3 1998/08/05 11:29:32 gklug - * rmv: Timer event entry. Timer will queue event directly - * - * Revision 1.2 1998/07/31 11:22:40 gklug - * Initial version - * - * Revision 1.1 1998/07/30 15:14:01 gklug - * Initial version. Adapted from SMT - * - * - * - ******************************************************************************/ - - #include - + #ifdef CONFIG_SK98 /* - Event queue and dispatcher -*/ + * Event queue and dispatcher + */ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/skqueue.c,v 1.18 2002/05/07 14:11:11 rwahl Exp $" ; + "@(#) $Id: skqueue.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ #include "h/skqueue.h" /* Queue Definitions */ @@ -114,27 +51,42 @@ intro() #define PRINTF(a,b,c) -/* - * init event queue management +/****************************************************************************** * - * Must be called during init level 0. + * SkEventInit() - init event queue management + * + * Description: + * This function initializes event queue management. + * It must be called during init level 0. + * + * Returns: + * nothing */ void SkEventInit( SK_AC *pAC, /* Adapter context */ SK_IOC Ioc, /* IO context */ -int Level) /* Init level */ +int Level) /* Init level */ { switch (Level) { case SK_INIT_DATA: - pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue ; + pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue; break; default: break; } } -/* - * add event to queue +/****************************************************************************** + * + * SkEventQueue() - add event to queue + * + * Description: + * This function adds an event to the event queue. + * At least Init Level 1 is required to queue events, + * but will be scheduled add Init Level 2. + * + * returns: + * nothing */ void SkEventQueue( SK_AC *pAC, /* Adapters context */ @@ -142,101 +94,154 @@ SK_U32 Class, /* Event Class */ SK_U32 Event, /* Event to be queued */ SK_EVPARA Para) /* Event parameter */ { - pAC->Event.EvPut->Class = Class ; - pAC->Event.EvPut->Event = Event ; - pAC->Event.EvPut->Para = Para ; - if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pAC->Event.EvPut = pAC->Event.EvQueue ; - if (pAC->Event.EvPut == pAC->Event.EvGet) { - SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG) ; + if (pAC->GIni.GILevel == SK_INIT_DATA) { + SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E003, SKERR_Q_E003MSG); + } + else { + pAC->Event.EvPut->Class = Class; + pAC->Event.EvPut->Event = Event; + pAC->Event.EvPut->Para = Para; + + if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT]) + pAC->Event.EvPut = pAC->Event.EvQueue; + + if (pAC->Event.EvPut == pAC->Event.EvGet) { + SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG); + } } } -/* - * event dispatcher - * while event queue is not empty - * get event from queue - * send command to state machine - * end - * return error reported by individual Event function - * 0 if no error occured. +/****************************************************************************** + * + * SkEventDispatcher() - Event Dispatcher + * + * Description: + * The event dispatcher performs the following operations: + * o while event queue is not empty + * - get event from queue + * - send event to state machine + * end + * + * CAUTION: + * The event functions MUST report an error if performing a reinitialization + * of the event queue, e.g. performing level Init 0..2 while in dispatcher + * call! + * ANY OTHER return value delays scheduling the other events in the + * queue. In this case the event blocks the queue until + * the error condition is cleared! + * + * Returns: + * The return value error reported by individual event function */ int SkEventDispatcher( SK_AC *pAC, /* Adapters Context */ SK_IOC Ioc) /* Io context */ { - SK_EVENTELEM *pEv ; /* pointer into queue */ - SK_U32 Class ; - int Rtv ; + SK_EVENTELEM *pEv; /* pointer into queue */ + SK_U32 Class; + int Rtv; - pEv = pAC->Event.EvGet ; - PRINTF("dispatch get %x put %x\n",pEv,pAC->Event.ev_put) ; + if (pAC->GIni.GILevel != SK_INIT_RUN) { + SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E005, SKERR_Q_E005MSG); + } + + pEv = pAC->Event.EvGet; + + PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put); + while (pEv != pAC->Event.EvPut) { - PRINTF("dispatch Class %d Event %d\n",pEv->Class,pEv->Event) ; - switch(Class = pEv->Class) { + PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event); + + switch (Class = pEv->Class) { #ifndef SK_USE_LAC_EV - case SKGE_RLMT : /* RLMT Event */ - Rtv = SkRlmtEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_I2C : /* I2C Event */ - Rtv = SkI2cEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; - case SKGE_PNMI : - Rtv = SkPnmiEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; -#endif /* SK_USE_LAC_EV */ - case SKGE_DRV : /* Driver Event */ - Rtv = SkDrvEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; +#ifndef SK_SLIM + case SKGE_RLMT: /* RLMT Event */ + Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; + case SKGE_I2C: /* I2C Event */ + Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; + +#ifdef SK_PNMI_SUPPORT + case SKGE_PNMI: /* PNMI Event */ + Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; +#endif /* SK_PNMI_SUPPORT */ + +#endif /* not SK_SLIM */ +#endif /* not SK_USE_LAC_EV */ + case SKGE_DRV: /* Driver Event */ + Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #ifndef SK_USE_SW_TIMER - case SKGE_HWAC : - Rtv = SkGeSirqEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + case SKGE_HWAC: + Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #else /* !SK_USE_SW_TIMER */ - case SKGE_SWT : - Rtv = SkSwtEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + case SKGE_SWT : + Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #endif /* !SK_USE_SW_TIMER */ #ifdef SK_USE_LAC_EV case SKGE_LACP : - Rtv = SkLacpEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; case SKGE_RSF : - Rtv = SkRsfEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; case SKGE_MARKER : - Rtv = SkMarkerEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; case SKGE_FD : - Rtv = SkFdEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #endif /* SK_USE_LAC_EV */ +#ifdef SK_ASF + case SKGE_ASF : + Rtv = SkAsfEvent(pAC,Ioc,pEv->Event,pEv->Para); + break ; +#endif #ifdef SK_USE_CSUM case SKGE_CSUM : - Rtv = SkCsEvent(pAC,Ioc,pEv->Event,pEv->Para); - break ; + Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para); + break; #endif /* SK_USE_CSUM */ default : - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, - SKERR_Q_E002MSG) ; + #if 0 // u-boot + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG); + #endif Rtv = 0; } if (Rtv != 0) { - return(Rtv) ; + /* + * Special Case: See CAUTION statement above. + * We assume the event queue is reset. + */ + if (pAC->Event.EvGet != pAC->Event.EvQueue && + pAC->Event.EvGet != pEv) { + /* + * Create an error log entry if the + * event queue isn't reset. + * In this case it may be blocked. + */ + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E004, SKERR_Q_E004MSG); + } + + return(Rtv); } if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pEv = pAC->Event.EvQueue ; + pEv = pAC->Event.EvQueue; /* Renew get: it is used in queue_events to detect overruns */ pAC->Event.EvGet = pEv; } - return(0) ; + return(0); } -#endif /* CONFIG_SK98 */ - /* End of file */ + +#endif diff --git a/drivers/sk98lin/skrlmt.c b/drivers/sk98lin/skrlmt.c index f8a3b41..3b9cc5d 100644 --- a/drivers/sk98lin/skrlmt.c +++ b/drivers/sk98lin/skrlmt.c @@ -2,15 +2,17 @@ * * Name: skrlmt.c * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.68 $ - * Date: $Date: 2003/01/31 15:26:56 $ + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Manage links on SK-NET Adapters, esp. redundant ones. * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2001 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2003 Marvell. * * 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 @@ -18,250 +20,7 @@ * (at your option) any later version. * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skrlmt.c,v $ - * Revision 1.68 2003/01/31 15:26:56 rschmidt - * Added init for local variables in RlmtInit(). - * - * Revision 1.67 2003/01/31 14:12:41 mkunz - * single port adapter runs now with two identical MAC addresses - * - * Revision 1.66 2002/09/23 15:14:19 rwahl - * - Reset broadcast timestamp on link down. - * - Editorial corrections. - * - * Revision 1.65 2002/07/22 14:29:48 rwahl - * - Removed BRK statement from debug check. - * - * Revision 1.64 2001/11/28 19:36:14 rwahl - * - RLMT Packets sent to an invalid MAC address in CLP/CLPSS mode - * (#10650). - * - Reworked fix for port switching in CLS mode (#10639) - * (no dependency to RLMT module). - * - Enabled dbg output for entry/exit of event functions. - * - Editorial changes. - * - * Revision 1.63 2001/10/26 07:53:18 afischer - * Port switching bug in `check local link` mode - * - * Revision 1.62 2001/07/03 12:16:30 mkunz - * New Flag ChgBcPrio (Change priority of last broadcast received) - * - * Revision 1.61 2001/03/14 12:52:08 rassmann - * Fixed reporting of active port up/down to PNMI. - * - * Revision 1.60 2001/02/21 16:02:25 gklug - * fix: when RLMT starts set Active Port for PNMI - * - * Revision 1.59 2001/02/16 14:38:19 rassmann - * Initializing some pointers earlier in the init phase. - * Rx Mbufs are freed if the net which they belong to is stopped. - * - * Revision 1.58 2001/02/14 14:06:31 rassmann - * Editorial changes. - * - * Revision 1.57 2001/02/05 14:25:26 rassmann - * Prepared RLMT for transparent operation. - * - * Revision 1.56 2001/01/30 10:29:09 rassmann - * Not checking switching befor RlmtStart. - * Editorial changes. - * - * Revision 1.55 2001/01/22 13:41:38 rassmann - * Supporting two nets on dual-port adapters. - * - * Revision 1.54 2000/11/30 13:25:07 rassmann - * Setting SK_TICK_INCR to 1 by default. - * - * Revision 1.53 2000/11/30 10:48:07 cgoos - * Changed definition of SK_RLMT_BC_DELTA. - * - * Revision 1.52 2000/11/27 12:50:03 rassmann - * Checking ports after receiving broadcasts. - * - * Revision 1.51 2000/11/17 08:58:00 rassmann - * Moved CheckSwitch from SK_RLMT_PACKET_RECEIVED to SK_RLMT_TIM event. - * - * Revision 1.50 2000/11/09 12:24:34 rassmann - * Indicating that segmentation check is not running anymore after - * SkRlmtCheckSeg(). - * Restarting segmentation timer after segmentation log. - * Editorial changes. - * - * Revision 1.49 1999/11/22 13:38:02 cgoos - * Changed license header to GPL. - * Added initialization to some variables to avoid compiler warnings. - * - * Revision 1.48 1999/10/04 14:01:17 rassmann - * Corrected reaction to reception of BPDU frames (#10441). - * - * Revision 1.47 1999/07/20 12:53:36 rassmann - * Fixed documentation errors for lookahead macros. - * - * Revision 1.46 1999/05/28 13:29:16 rassmann - * Replaced C++-style comment. - * - * Revision 1.45 1999/05/28 13:28:08 rassmann - * Corrected syntax error (xxx). - * - * Revision 1.44 1999/05/28 11:15:54 rassmann - * Changed behaviour to reflect Design Spec v1.2. - * Controlling Link LED(s). - * Introduced RLMT Packet Version field in RLMT Packet. - * Newstyle lookahead macros (checking meta-information before looking at - * the packet). - * - * Revision 1.43 1999/01/28 13:12:43 rassmann - * Corrected Lookahead (bug introduced in previous Rev.). - * - * Revision 1.42 1999/01/28 12:50:41 rassmann - * Not using broadcast time stamps in CheckLinkState mode. - * - * Revision 1.41 1999/01/27 14:13:02 rassmann - * Monitoring broadcast traffic. - * Switching more reliably and not too early if switch is - * configured for spanning tree. - * - * Revision 1.40 1999/01/22 13:17:30 rassmann - * Informing PNMI of NET_UP. - * Clearing RLMT multicast addresses before setting them for the first time. - * Reporting segmentation earlier, setting a "quiet time" - * after a report. - * - * Revision 1.39 1998/12/10 15:29:53 rassmann - * Corrected SuspectStatus in SkRlmtBuildCheckChain(). - * Corrected CHECK_SEG mode. - * - * Revision 1.38 1998/12/08 13:11:23 rassmann - * Stopping SegTimer at RlmtStop. - * - * Revision 1.37 1998/12/07 16:51:42 rassmann - * Corrected comments. - * - * Revision 1.36 1998/12/04 10:58:56 rassmann - * Setting next pointer to NULL when receiving. - * - * Revision 1.35 1998/12/03 16:12:42 rassmann - * Ignoring/correcting illegal PrefPort values. - * - * Revision 1.34 1998/12/01 11:45:35 rassmann - * Code cleanup. - * - * Revision 1.33 1998/12/01 10:29:32 rassmann - * Starting standby ports before getting the net up. - * Checking if a port is started when the link comes up. - * - * Revision 1.32 1998/11/30 16:19:50 rassmann - * New default for PortNoRx. - * - * Revision 1.31 1998/11/27 19:17:13 rassmann - * Corrected handling of LINK_DOWN coming shortly after LINK_UP. - * - * Revision 1.30 1998/11/24 12:37:31 rassmann - * Implemented segmentation check. - * - * Revision 1.29 1998/11/18 13:04:32 rassmann - * Secured PortUpTimer event. - * Waiting longer before starting standby port(s). - * - * Revision 1.28 1998/11/17 13:43:04 rassmann - * Handling (logical) tx failure. - * Sending packet on logical address after PORT_SWITCH. - * - * Revision 1.27 1998/11/13 17:09:50 rassmann - * Secured some events against being called in wrong state. - * - * Revision 1.26 1998/11/13 16:56:54 rassmann - * Added macro version of SkRlmtLookaheadPacket. - * - * Revision 1.25 1998/11/06 18:06:04 rassmann - * Corrected timing when RLMT checks fail. - * Clearing tx counter earlier in periodical checks. - * - * Revision 1.24 1998/11/05 10:37:27 rassmann - * Checking destination address in Lookahead. - * - * Revision 1.23 1998/11/03 13:53:49 rassmann - * RLMT should switch now (at least in mode 3). - * - * Revision 1.22 1998/10/29 14:34:49 rassmann - * Clearing SK_RLMT struct at startup. - * Initializing PortsUp during SK_RLMT_START. - * - * Revision 1.21 1998/10/28 11:30:17 rassmann - * Default mode is now SK_RLMT_CHECK_LOC_LINK. - * - * Revision 1.20 1998/10/26 16:02:03 rassmann - * Ignoring LINK_DOWN for links that are down. - * - * Revision 1.19 1998/10/22 15:54:01 rassmann - * Corrected EtherLen. - * Starting Link Check when second port comes up. - * - * Revision 1.18 1998/10/22 11:39:50 rassmann - * Corrected signed/unsigned mismatches. - * Corrected receive list handling and address recognition. - * - * Revision 1.17 1998/10/19 17:01:20 rassmann - * More detailed checking of received packets. - * - * Revision 1.16 1998/10/15 15:16:34 rassmann - * Finished Spanning Tree checking. - * Checked with lint. - * - * Revision 1.15 1998/09/24 19:16:07 rassmann - * Code cleanup. - * Introduced Timer for PORT_DOWN due to no RX. - * - * Revision 1.14 1998/09/18 20:27:14 rassmann - * Added address override. - * - * Revision 1.13 1998/09/16 11:31:48 rassmann - * Including skdrv1st.h again. :( - * - * Revision 1.12 1998/09/16 11:09:50 rassmann - * Syntax corrections. - * - * Revision 1.11 1998/09/15 12:32:03 rassmann - * Syntax correction. - * - * Revision 1.10 1998/09/15 11:28:49 rassmann - * Syntax corrections. - * - * Revision 1.9 1998/09/14 17:07:37 rassmann - * Added code for port checking via LAN. - * Changed Mbuf definition. - * - * Revision 1.8 1998/09/07 11:14:14 rassmann - * Syntax corrections. - * - * Revision 1.7 1998/09/07 09:06:07 rassmann - * Syntax corrections. - * - * Revision 1.6 1998/09/04 19:41:33 rassmann - * Syntax corrections. - * Started entering code for checking local links. - * - * Revision 1.5 1998/09/04 12:14:27 rassmann - * Interface cleanup. - * - * Revision 1.4 1998/09/02 16:55:28 rassmann - * Updated to reflect new DRV/HWAC/RLMT interface. - * - * Revision 1.3 1998/08/27 14:29:03 rassmann - * Code cleanup. - * - * Revision 1.2 1998/08/27 14:26:24 rassmann - * Updated interface. - * - * Revision 1.1 1998/08/21 08:26:49 rassmann - * First public version. + * /LICENSE * ******************************************************************************/ @@ -279,20 +38,18 @@ * "skdrv2nd.h" * ******************************************************************************/ - #include - + #ifdef CONFIG_SK98 #ifndef lint static const char SysKonnectFileId[] = - "@(#) $Id: skrlmt.c,v 1.68 2003/01/31 15:26:56 rschmidt Exp $ (C) SysKonnect."; + "@(#) $Id: skrlmt.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; #endif /* !defined(lint) */ #define __SKRLMT_C #ifdef __cplusplus -#error C++ is not yet supported. extern "C" { #endif /* cplusplus */ @@ -598,7 +355,7 @@ int Level) /* Initialization Level */ SK_BOOL PhysicalAMacAddressSet; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT Init level %d.\n", Level)) + ("RLMT Init level %d.\n", Level)); switch (Level) { case SK_INIT_DATA: /* Initialize data structures. */ @@ -638,7 +395,7 @@ int Level) /* Initialization Level */ case SK_INIT_IO: /* GIMacsFound first available here. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound)) + ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound)); pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; @@ -668,7 +425,7 @@ int Level) /* Initialization Level */ } (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY); - + /* Add RLMT MC address. */ (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT); @@ -680,34 +437,34 @@ int Level) /* Initialization Level */ (void)SkAddrMcUpdate(pAC, IoC, i); } - VirtualMacAddressSet = SK_FALSE; + VirtualMacAddressSet = SK_FALSE; /* Read virtual MAC address from Control Register File. */ for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); - VirtualMacAddressSet |= VirtualMacAddress.a[j]; + + SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); + VirtualMacAddressSet |= VirtualMacAddress.a[j]; } - - PhysicalAMacAddressSet = SK_FALSE; + + PhysicalAMacAddressSet = SK_FALSE; /* Read physical MAC address for MAC A from Control Register File. */ for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); - PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; + + SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); + PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; } - /* check if the two mac addresses contain reasonable values */ - if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { + /* check if the two mac addresses contain reasonable values */ + if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { - pAC->Rlmt.RlmtOff = SK_TRUE; - } + pAC->Rlmt.RlmtOff = SK_TRUE; + } - /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD - and the RLMT_LOOKAHEAD macros */ - else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { + /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD + and the RLMT_LOOKAHEAD macros */ + else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { - pAC->Rlmt.RlmtOff = SK_TRUE; - } + pAC->Rlmt.RlmtOff = SK_TRUE; + } else { pAC->Rlmt.RlmtOff = SK_FALSE; } @@ -751,16 +508,16 @@ SK_U32 NetIdx) /* Net Number */ FirstMacUp = NULL; PrevMacUp = NULL; - + if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) { pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; } return; /* Done. */ } - + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtBuildCheckChain.\n")) + ("SkRlmtBuildCheckChain.\n")); NumMacsUp = 0; @@ -806,7 +563,7 @@ SK_U32 NetIdx) /* Net Number */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("Port %d checks %d other ports: %2X.\n", i, pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked, - pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])) + pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])); } #endif /* DEBUG */ @@ -843,7 +600,7 @@ SK_MAC_ADDR *DestAddr) /* Destination address */ #ifdef DEBUG SK_U8 CheckSrc = 0; SK_U8 CheckDest = 0; - + for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { CheckSrc |= SrcAddr->a[i]; CheckDest |= DestAddr->a[i]; @@ -852,7 +609,7 @@ SK_MAC_ADDR *DestAddr) /* Destination address */ if ((CheckSrc == 0) || (CheckDest == 0)) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, ("SkRlmtBuildPacket: Invalid %s%saddr.\n", - (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))) + (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))); } #endif @@ -878,7 +635,7 @@ SK_MAC_ADDR *DestAddr) /* Destination address */ for (i = 0; i < 4; i++) { pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i]; } - + SK_U16_TO_NETWORK_ORDER( SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]); @@ -1044,7 +801,7 @@ SK_U32 PortNumber) /* Sending port */ SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX, - ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)) + ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)); } } return; @@ -1083,7 +840,7 @@ SK_U32 PortNumber) /* Port to check */ * Bring it up. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Received on PortDown.\n")) + ("SkRlmtPacketReceive: Received on PortDown.\n")); pRPort->PortState = SK_RLMT_PS_GOING_UP; pRPort->GuTimeStamp = SkOsGetTime(pAC); @@ -1097,7 +854,7 @@ SK_U32 PortNumber) /* Port to check */ } /* PortDown && !SuspectTx */ else if (pRPort->CheckingState & SK_RLMT_PCS_RX) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Stop bringing port down.\n")) + ("SkRlmtPacketReceive: Stop bringing port down.\n")); SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); pRPort->CheckingState &= ~SK_RLMT_PCS_RX; /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ @@ -1144,7 +901,7 @@ SK_MBUF *pMb) /* Received packet */ pRPort = &pAC->Rlmt.Port[PortNumber]; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)) + ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)); pRPacket = (SK_RLMT_PACKET*)pMb->pData; pSPacket = (SK_SPTREE_PACKET*)pRPacket; @@ -1156,7 +913,7 @@ SK_MBUF *pMb) /* Received packet */ if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) { SkRlmtPortReceives(pAC, IoC, PortNumber); } - + /* Check destination address. */ if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) && @@ -1165,7 +922,7 @@ SK_MBUF *pMb) /* Received packet */ /* Not sent to current MAC or registered MC address => Trash it. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Not for me.\n")) + ("SkRlmtPacketReceive: Not for me.\n")); SkDrvFreeRlmtMbuf(pAC, IoC, pMb); return; @@ -1203,7 +960,7 @@ SK_MBUF *pMb) /* Received packet */ pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Duplicate MAC Address.\n")) + ("SkRlmtPacketReceive: Duplicate MAC Address.\n")); /* Error Log entry. */ SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG); @@ -1211,7 +968,7 @@ SK_MBUF *pMb) /* Received packet */ else { /* Simply trash it. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Sent by me.\n")) + ("SkRlmtPacketReceive: Sent by me.\n")); } SkDrvFreeRlmtMbuf(pAC, IoC, pMb); @@ -1255,7 +1012,7 @@ SK_MBUF *pMb) /* Received packet */ #endif /* 0 */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Announce.\n")) + ("SkRlmtPacketReceive: Announce.\n")); SkDrvFreeRlmtMbuf(pAC, IoC, pMb); break; @@ -1263,7 +1020,7 @@ SK_MBUF *pMb) /* Received packet */ case SK_PACKET_ALIVE: if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Reply.\n")) + ("SkRlmtPacketReceive: Alive Reply.\n")); if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) || SK_ADDR_EQUAL( @@ -1294,7 +1051,7 @@ SK_MBUF *pMb) /* Received packet */ } else { /* Alive Request Packet. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Request.\n")) + ("SkRlmtPacketReceive: Alive Request.\n")); pRPort->RxHelloCts++; @@ -1313,7 +1070,7 @@ SK_MBUF *pMb) /* Received packet */ case SK_PACKET_CHECK_TX: SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Check your tx line.\n")) + ("SkRlmtPacketReceive: Check your tx line.\n")); /* A port checking us requests us to check our tx line. */ pRPort->CheckingState |= SK_RLMT_PCS_TX; @@ -1336,7 +1093,7 @@ SK_MBUF *pMb) /* Received packet */ case SK_PACKET_ADDR_CHANGED: SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Address Change.\n")) + ("SkRlmtPacketReceive: Address Change.\n")); /* Build the check chain. */ SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); @@ -1345,7 +1102,7 @@ SK_MBUF *pMb) /* Received packet */ default: SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown RLMT packet.\n")) + ("SkRlmtPacketReceive: Unknown RLMT packet.\n")); /* RA;:;: ??? */ SkDrvFreeRlmtMbuf(pAC, IoC, pMb); @@ -1355,7 +1112,7 @@ SK_MBUF *pMb) /* Received packet */ pSPacket->Ctrl == SK_RLMT_SPT_CTRL && (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: BPDU Packet.\n")) + ("SkRlmtPacketReceive: BPDU Packet.\n")); /* Spanning Tree packet. */ pRPort->RxSpHelloCts++; @@ -1387,7 +1144,7 @@ SK_MBUF *pMb) /* Received packet */ pRPort->Root.Id[0], pRPort->Root.Id[1], pRPort->Root.Id[2], pRPort->Root.Id[3], pRPort->Root.Id[4], pRPort->Root.Id[5], - pRPort->Root.Id[6], pRPort->Root.Id[7])) + pRPort->Root.Id[6], pRPort->Root.Id[7])); } SkDrvFreeRlmtMbuf(pAC, IoC, pMb); @@ -1398,7 +1155,7 @@ SK_MBUF *pMb) /* Received packet */ } else { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown Packet Type.\n")) + ("SkRlmtPacketReceive: Unknown Packet Type.\n")); /* Unknown packet. */ SkDrvFreeRlmtMbuf(pAC, IoC, pMb); @@ -1480,7 +1237,7 @@ SK_U32 PortNumber) /* Port to check */ if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n", - PortNumber, pRPort->PacketsPerTimeSlot)) + PortNumber, pRPort->PacketsPerTimeSlot)); /* * Check segmentation if there was no receive at least twice @@ -1497,7 +1254,7 @@ SK_U32 PortNumber) /* Port to check */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n", - pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)) + pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)); if (pRPort->PortState != SK_RLMT_PS_DOWN) { NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue); @@ -1543,8 +1300,8 @@ SK_U32 PortNumber) /* Port to check */ ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n", PortNumber, pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, - pRPort->PacketsPerTimeSlot)) - + pRPort->PacketsPerTimeSlot)); + SkRlmtPortReceives(pAC, IoC, PortNumber); if (pAC->Rlmt.CheckSwitch) { SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); @@ -1584,16 +1341,16 @@ SK_U32 *pSelect) /* New active port */ BcTimeStamp = 0; /* Not totally necessary, but feeling better. */ PortFound = SK_FALSE; - + /* Select port with the latest TimeStamp. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n", i, - pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, + pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32), - *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))) + *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))); if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) { if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) { @@ -1606,7 +1363,7 @@ SK_U32 *pSelect) /* New active port */ if (PortFound) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received the last broadcast.\n", *pSelect)) + ("Port %d received the last broadcast.\n", *pSelect)); /* Look if another port's time stamp is similar. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { @@ -1619,9 +1376,9 @@ SK_U32 *pSelect) /* New active port */ pAC->Rlmt.Port[i].BcTimeStamp + SK_RLMT_BC_DELTA > BcTimeStamp)) { PortFound = SK_FALSE; - + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received a broadcast at a similar time.\n", i)) + ("Port %d received a broadcast at a similar time.\n", i)); break; } } @@ -1633,7 +1390,7 @@ SK_U32 *pSelect) /* New active port */ ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially " "latest broadcast (%u).\n", *pSelect, - BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)) + BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)); } #endif /* DEBUG */ @@ -1682,7 +1439,7 @@ SK_U32 *pSelect) /* New active port */ PortFound = SK_TRUE; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n", - *pSelect)) + *pSelect)); break; } } @@ -1731,7 +1488,7 @@ SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ } PortFound = SK_TRUE; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)) + ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)); break; } } @@ -1792,7 +1549,7 @@ SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)) + ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)); return (SK_TRUE); } /* SkRlmtSelectGoingUp */ @@ -1838,7 +1595,7 @@ SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ } PortFound = SK_TRUE; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)) + ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)); break; } } @@ -1928,16 +1685,19 @@ SK_U32 NetIdx) /* Net index */ Para.Para32[1] = NetIdx; SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); - if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, - pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, - SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. - CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { - /* - * Send announce packet to RLMT multicast address to force - * switches to learn the new location of the logical MAC address. - */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + if (pAC->Rlmt.NumNets == 1) { + if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && + (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, + pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, + SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. + CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { + + /* + * Send announce packet to RLMT multicast address to force + * switches to learn the new location of the logical MAC address. + */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); + } } } else { @@ -1974,7 +1734,7 @@ SK_U32 NetIdx) /* Net index */ /* check of ChgBcPrio flag added */ if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && (!pAC->Rlmt.Net[0].ChgBcPrio)) { - + if (!PortFound) { PortFound = SkRlmtSelectBcRx( pAC, IoC, Active, PrefPort, &Para.Para32[1]); @@ -2036,7 +1796,7 @@ SK_U32 NetIdx) /* Net index */ if (Para.Para32[1] != Active) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])) + ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])); pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1]; Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. Port[Para.Para32[0]]->PortNumber; @@ -2116,7 +1876,7 @@ SK_U32 NetIdx) /* Net number */ pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1], pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3], pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5], - pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])) + pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])); if (!pNet->RootIdSet) { pNet->Root = pNet->Port[i]->Root; @@ -2130,7 +1890,7 @@ SK_U32 NetIdx) /* Net number */ break; } } - + if (!Equal) { SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG); Para.Para32[0] = NetIdx; @@ -2211,13 +1971,13 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ SK_U32 i; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0])); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n")) + ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n")); return; } @@ -2238,7 +1998,7 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n")) + ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n")); } /* SkRlmtEvtPortStartTim */ @@ -2266,21 +2026,21 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ SK_EVPARA Para2; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0])); pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; if (!pRPort->PortStarted) { SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) + ("SK_RLMT_LINK_UP Event EMPTY.\n")); return; } if (!pRPort->LinkDown) { /* RA;:;: Any better solution? */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) + ("SK_RLMT_LINK_UP Event EMPTY.\n")); return; } @@ -2332,14 +2092,17 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2); /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */ - if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 && - (Para2.pParaPtr = - SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, - &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) - ) != NULL) { - /* Send "new" packet to RLMT multicast address. */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); + if (pAC->Rlmt.NumNets == 1) { + if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 && + (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 && + (Para2.pParaPtr = + SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, + &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) + ) != NULL) { + + /* Send "new" packet to RLMT multicast address. */ + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); + } } if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) { @@ -2358,7 +2121,7 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event END.\n")) + ("SK_RLMT_LINK_UP Event END.\n")); } /* SkRlmtEvtLinkUp */ @@ -2384,20 +2147,20 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ SK_RLMT_PORT *pRPort; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0])); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event EMPTY.\n")) + ("SK_RLMT_PORTUP_TIM Event EMPTY.\n")); return; } pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0])) + ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0])); return; } @@ -2412,7 +2175,7 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event END.\n")) + ("SK_RLMT_PORTUP_TIM Event END.\n")); } /* SkRlmtEvtPortUpTim */ @@ -2440,13 +2203,13 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n", - Para.Para32[0], Event)) + Para.Para32[0], Event)); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event EMPTY.\n")) + ("SK_RLMT_PORTDOWN* Event EMPTY.\n")); return; } @@ -2454,10 +2217,10 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM && !(pRPort->CheckingState & SK_RLMT_PCS_TX))) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event)) + ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event)); return; } - + /* Stop port's timers. */ SkTimerStop(pAC, IoC, &pRPort->UpTimer); SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); @@ -2491,7 +2254,7 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event)) + ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event)); } /* SkRlmtEvtPortDownX */ @@ -2518,7 +2281,7 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0])); if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { pRPort->Net->LinksUp--; @@ -2537,7 +2300,7 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Event END.\n")) + ("SK_RLMT_LINK_DOWN Event END.\n")); } /* SkRlmtEvtLinkDown */ @@ -2566,13 +2329,13 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ SK_MAC_ADDR *pNewMacAddr; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0])); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event EMPTY.\n")) + ("SK_RLMT_PORT_ADDR Event EMPTY.\n")); return; } @@ -2596,7 +2359,7 @@ SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event END.\n")) + ("SK_RLMT_PORT_ADDR Event END.\n")); } /* SkRlmtEvtPortAddr */ @@ -2624,35 +2387,35 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ SK_U32 PortNumber; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0])); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) + ("SK_RLMT_START Event EMPTY.\n")); return; } if (Para.Para32[0] >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) + ("Bad NetNumber %d.\n", Para.Para32[0])); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) + ("SK_RLMT_START Event EMPTY.\n")); return; } if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) + ("SK_RLMT_START Event EMPTY.\n")); return; } if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets should have been started.\n")) + ("All nets should have been started.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) + ("SK_RLMT_START Event EMPTY.\n")); return; } @@ -2686,7 +2449,7 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ pAC->Rlmt.NetsStarted++; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event END.\n")) + ("SK_RLMT_START Event END.\n")); } /* SkRlmtEvtStart */ @@ -2714,35 +2477,35 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ SK_U32 i; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0])); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) + ("SK_RLMT_STOP Event EMPTY.\n")); return; } if (Para.Para32[0] >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) + ("Bad NetNumber %d.\n", Para.Para32[0])); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) + ("SK_RLMT_STOP Event EMPTY.\n")); return; } if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) + ("SK_RLMT_STOP Event EMPTY.\n")); return; } if (pAC->Rlmt.NetsStarted == 0) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets are stopped.\n")) + ("All nets are stopped.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) + ("SK_RLMT_STOP Event EMPTY.\n")); return; } @@ -2777,7 +2540,7 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ pAC->Rlmt.NetsStarted--; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event END.\n")) + ("SK_RLMT_STOP Event END.\n")); } /* SkRlmtEvtStop */ @@ -2807,13 +2570,13 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ SK_U32 i; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event BEGIN.\n")) + ("SK_RLMT_TIM Event BEGIN.\n")); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event EMPTY.\n")) + ("SK_RLMT_TIM Event EMPTY.\n")); return; } @@ -2885,7 +2648,7 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event END.\n")) + ("SK_RLMT_TIM Event END.\n")); } /* SkRlmtEvtTim */ @@ -2913,13 +2676,13 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ #endif /* DEBUG */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event BEGIN.\n")) + ("SK_RLMT_SEG_TIM Event BEGIN.\n")); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event EMPTY.\n")) + ("SK_RLMT_SEG_TIM Event EMPTY.\n")); return; } @@ -2943,15 +2706,15 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ InAddr8[3], InAddr8[4], InAddr8[5], pAPort->Exact[k].a[0], pAPort->Exact[k].a[1], pAPort->Exact[k].a[2], pAPort->Exact[k].a[3], - pAPort->Exact[k].a[4], pAPort->Exact[k].a[5])) + pAPort->Exact[k].a[4], pAPort->Exact[k].a[5])); } } #endif /* xDEBUG */ - + SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event END.\n")) + ("SK_RLMT_SEG_TIM Event END.\n")); } /* SkRlmtEvtSegTim */ @@ -2978,20 +2741,20 @@ SK_EVPARA Para) /* SK_MBUF *pMb */ SK_MBUF *pNextMb; SK_U32 NetNumber; - + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n")) + ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n")); /* Should we ignore frames during port switching? */ #ifdef DEBUG pMb = Para.pParaPtr; if (pMb == NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n")) + SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n")); } else if (pMb->pNext != NULL) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("More than one mbuf or pMb->pNext not set.\n")) + ("More than one mbuf or pMb->pNext not set.\n")); } #endif /* DEBUG */ @@ -3009,7 +2772,7 @@ SK_EVPARA Para) /* SK_MBUF *pMb */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event END.\n")) + ("SK_RLMT_PACKET_RECEIVED Event END.\n")); } /* SkRlmtEvtPacketRx */ @@ -3036,21 +2799,21 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ SK_RLMT_PORT *pRPort; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event BEGIN.\n")) + ("SK_RLMT_STATS_CLEAR Event BEGIN.\n")); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) + ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")); return; } if (Para.Para32[0] >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) + ("Bad NetNumber %d.\n", Para.Para32[0])); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) + ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")); return; } @@ -3065,7 +2828,7 @@ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event END.\n")) + ("SK_RLMT_STATS_CLEAR Event END.\n")); } /* SkRlmtEvtStatsClear */ @@ -3089,28 +2852,28 @@ SK_IOC IoC, /* I/O Context */ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event BEGIN.\n")) + ("SK_RLMT_STATS_UPDATE Event BEGIN.\n")); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) + ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")); return; } if (Para.Para32[0] >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) + ("Bad NetNumber %d.\n", Para.Para32[0])); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) + ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")); return; } /* Update statistics - currently always up-to-date. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event END.\n")) + ("SK_RLMT_STATS_UPDATE Event END.\n")); } /* SkRlmtEvtStatsUpdate */ @@ -3134,13 +2897,13 @@ SK_IOC IoC, /* I/O Context */ SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0])) + ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0])); if (Para.Para32[1] >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) + ("Bad NetNumber %d.\n", Para.Para32[1])); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) + ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")); return; } @@ -3153,7 +2916,7 @@ SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) + ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")); return; } @@ -3167,7 +2930,7 @@ SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event END.\n")) + ("SK_RLMT_PREFPORT_CHANGE Event END.\n")); } /* SkRlmtEvtPrefportChange */ @@ -3193,37 +2956,37 @@ SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ int i; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event BEGIN.\n")) + ("SK_RLMT_SET_NETS Event BEGIN.\n")); if (Para.Para32[1] != (SK_U32)-1) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) + ("Bad Parameter.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) + ("SK_RLMT_SET_NETS Event EMPTY.\n")); return; } if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS || Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad number of nets: %d.\n", Para.Para32[0])) + ("Bad number of nets: %d.\n", Para.Para32[0])); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) + ("SK_RLMT_SET_NETS Event EMPTY.\n")); return; } if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) + ("SK_RLMT_SET_NETS Event EMPTY.\n")); return; } /* Entering and leaving dual mode only allowed while nets are stopped. */ if (pAC->Rlmt.NetsStarted > 0) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Changing dual mode only allowed while all nets are stopped.\n")) + ("Changing dual mode only allowed while all nets are stopped.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) + ("SK_RLMT_SET_NETS Event EMPTY.\n")); return; } @@ -3254,14 +3017,15 @@ SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to one net with two ports.\n")) + ("RLMT: Changed to one net with two ports.\n")); } else if (Para.Para32[0] == 2) { + pAC->Rlmt.RlmtOff = SK_TRUE; pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1]; pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1; pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts; - + pAC->Rlmt.NumNets = Para.Para32[0]; for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; @@ -3283,19 +3047,19 @@ SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to two nets with one port each.\n")) + ("RLMT: Changed to two nets with one port each.\n")); } else { /* Not implemented for more than two nets. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SetNets not implemented for more than two nets.\n")) + ("SetNets not implemented for more than two nets.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) + ("SK_RLMT_SET_NETS Event EMPTY.\n")); return; } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event END.\n")) + ("SK_RLMT_SET_NETS Event END.\n")); } /* SkRlmtSetNets */ @@ -3323,13 +3087,13 @@ SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ SK_U32 PrevRlmtMode; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event BEGIN.\n")) + ("SK_RLMT_MODE_CHANGE Event BEGIN.\n")); if (Para.Para32[1] >= pAC->Rlmt.NumNets) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) + ("Bad NetNumber %d.\n", Para.Para32[1])); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) + ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")); return; } @@ -3339,9 +3103,9 @@ SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ Para.Para32[0] != SK_RLMT_MODE_CLS) { pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Forced RLMT mode to CLS on single port net.\n")) + ("Forced RLMT mode to CLS on single port net.\n")); SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) + ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")); return; } @@ -3407,7 +3171,7 @@ SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ } /* SK_RLMT_CHECK_SEG bit changed. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event END.\n")) + ("SK_RLMT_MODE_CHANGE Event END.\n")); } /* SkRlmtEvtModeChange */ @@ -3432,7 +3196,7 @@ SK_U32 Event, /* Event code */ SK_EVPARA Para) /* Event-specific parameter */ { switch (Event) { - + /* ----- PORT events ----- */ case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */ @@ -3493,7 +3257,7 @@ SK_EVPARA Para) /* Event-specific parameter */ default: /* Create error log entry. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Unknown RLMT Event %d.\n", Event)) + ("Unknown RLMT Event %d.\n", Event)); SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG); break; } /* switch() */ @@ -3505,4 +3269,4 @@ SK_EVPARA Para) /* Event-specific parameter */ } #endif /* __cplusplus */ -#endif /* CONFIG_SK98 */ +#endif diff --git a/drivers/sk98lin/sktimer.c b/drivers/sk98lin/sktimer.c index 37cd4c9..fa4fc6d 100644 --- a/drivers/sk98lin/sktimer.c +++ b/drivers/sk98lin/sktimer.c @@ -1,17 +1,17 @@ /****************************************************************************** * * Name: sktimer.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.12 $ - * Date: $Date: 1999/11/22 13:38:51 $ + * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: High level timer functions. * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998,1999 SysKonnect, - * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2004 Marvell. * * 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 @@ -21,66 +21,17 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: sktimer.c,v $ - * Revision 1.12 1999/11/22 13:38:51 cgoos - * Changed license header to GPL. - * - * Revision 1.11 1998/12/17 13:24:13 gklug - * fix: restart problem: do NOT destroy timer queue if init 1 is done - * - * Revision 1.10 1998/10/15 15:11:36 gklug - * fix: ID_sccs to SysKonnectFileId - * - * Revision 1.9 1998/09/15 15:15:04 cgoos - * Changed TRUE/FALSE to SK_TRUE/SK_FALSE - * - * Revision 1.8 1998/09/08 08:47:55 gklug - * add: init level handling - * - * Revision 1.7 1998/08/19 09:50:53 gklug - * fix: remove struct keyword from c-code (see CCC) add typedefs - * - * Revision 1.6 1998/08/17 13:43:13 gklug - * chg: Parameter will be union of 64bit para, 2 times SK_U32 or SK_PTR - * - * Revision 1.5 1998/08/14 07:09:14 gklug - * fix: chg pAc -> pAC - * - * Revision 1.4 1998/08/07 12:53:46 gklug - * fix: first compiled version - * - * Revision 1.3 1998/08/07 09:31:53 gklug - * fix: delta spelling - * - * Revision 1.2 1998/08/07 09:31:02 gklug - * adapt functions to new c coding conventions - * rmv: "fast" handling - * chg: inserting of new timer in queue. - * chg: event queue generation when timer runs out - * - * Revision 1.1 1998/08/05 11:27:55 gklug - * first version: adapted from SMT - * - * - * - * - ******************************************************************************/ - - #include - + #ifdef CONFIG_SK98 /* - Event queue and dispatcher -*/ + * Event queue and dispatcher + */ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) static const char SysKonnectFileId[] = - "$Header: /usr56/projects/ge/schedule/sktimer.c,v 1.12 1999/11/22 13:38:51 cgoos Exp $" ; + "@(#) $Id: sktimer.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif #include "h/skdrv1st.h" /* Driver Specific Definitions */ #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ @@ -109,14 +60,14 @@ static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart); void SkTimerInit( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ -int Level) /* Init Level */ +int Level) /* Init Level */ { switch (Level) { case SK_INIT_DATA: - pAC->Tim.StQueue = 0 ; + pAC->Tim.StQueue = 0; break; case SK_INIT_IO: - SkHwtInit(pAC,Ioc) ; + SkHwtInit(pAC, Ioc); SkTimerDone(pAC, Ioc); break; default: @@ -133,31 +84,32 @@ SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ SK_TIMER *pTimer) /* Timer Pointer to be started */ { - SK_TIMER **ppTimPrev ; - SK_TIMER *pTm ; + SK_TIMER **ppTimPrev; + SK_TIMER *pTm; + + /* remove timer from queue */ + pTimer->TmActive = SK_FALSE; - /* - * remove timer from queue - */ - pTimer->TmActive = SK_FALSE ; if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) { - SkHwtStop(pAC,Ioc) ; + SkHwtStop(pAC, Ioc); } - for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; + + for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); ppTimPrev = &pTm->TmNext ) { + if (pTm == pTimer) { /* * Timer found in queue - * - dequeue it and + * - dequeue it * - correct delta of the next timer */ - *ppTimPrev = pTm->TmNext ; + *ppTimPrev = pTm->TmNext; if (pTm->TmNext) { /* correct delta of next timer in queue */ - pTm->TmNext->TmDelta += pTm->TmDelta ; + pTm->TmNext->TmDelta += pTm->TmDelta; } - return ; + return; } } } @@ -169,70 +121,60 @@ void SkTimerStart( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ SK_TIMER *pTimer, /* Timer Pointer to be started */ -SK_U32 Time, /* Time value */ +SK_U32 Time, /* Time Value (in microsec.) */ SK_U32 Class, /* Event Class for this timer */ SK_U32 Event, /* Event Value for this timer */ SK_EVPARA Para) /* Event Parameter for this timer */ { - SK_TIMER **ppTimPrev ; - SK_TIMER *pTm ; - SK_U32 Delta ; + SK_TIMER **ppTimPrev; + SK_TIMER *pTm; + SK_U32 Delta; - Time /= 16 ; /* input is uS, clock ticks are 16uS */ - if (!Time) - Time = 1 ; + SkTimerStop(pAC, Ioc, pTimer); - SkTimerStop(pAC,Ioc,pTimer) ; - - pTimer->TmClass = Class ; - pTimer->TmEvent = Event ; - pTimer->TmPara = Para ; - pTimer->TmActive = SK_TRUE ; + pTimer->TmClass = Class; + pTimer->TmEvent = Event; + pTimer->TmPara = Para; + pTimer->TmActive = SK_TRUE; if (!pAC->Tim.StQueue) { - /* First Timer to be started */ - pAC->Tim.StQueue = pTimer ; - pTimer->TmNext = 0 ; - pTimer->TmDelta = Time ; - SkHwtStart(pAC,Ioc,Time) ; - return ; + /* first Timer to be started */ + pAC->Tim.StQueue = pTimer; + pTimer->TmNext = 0; + pTimer->TmDelta = Time; + + SkHwtStart(pAC, Ioc, Time); + + return; } - /* - * timer correction - */ - timer_done(pAC,Ioc,0) ; + /* timer correction */ + timer_done(pAC, Ioc, 0); - /* - * find position in queue - */ - Delta = 0 ; - for (ppTimPrev = &pAC->Tim.StQueue ; (pTm = *ppTimPrev) ; + /* find position in queue */ + Delta = 0; + for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); ppTimPrev = &pTm->TmNext ) { + if (Delta + pTm->TmDelta > Time) { - /* Position found */ - /* Here the timer needs to be inserted. */ - break ; + /* the timer needs to be inserted here */ + break; } - Delta += pTm->TmDelta ; + Delta += pTm->TmDelta; } /* insert in queue */ - *ppTimPrev = pTimer ; - pTimer->TmNext = pTm ; - pTimer->TmDelta = Time - Delta ; + *ppTimPrev = pTimer; + pTimer->TmNext = pTm; + pTimer->TmDelta = Time - Delta; if (pTm) { - /* There is a next timer - * -> correct its Delta value. - */ - pTm->TmDelta -= pTimer->TmDelta ; + /* there is a next timer: correct its Delta value */ + pTm->TmDelta -= pTimer->TmDelta; } - /* - * start new with first - */ - SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; + /* restart with first */ + SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); } @@ -240,58 +182,59 @@ void SkTimerDone( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc) /* IoContext */ { - timer_done(pAC,Ioc,1) ; + timer_done(pAC, Ioc, 1); } static void timer_done( SK_AC *pAC, /* Adapters context */ SK_IOC Ioc, /* IoContext */ -int Restart) /* Do we need to restart the Hardware timer ? */ +int Restart) /* Do we need to restart the Hardware timer ? */ { - SK_U32 Delta ; - SK_TIMER *pTm ; - SK_TIMER *pTComp ; /* Timer completed now now */ - SK_TIMER **ppLast ; /* Next field of Last timer to be deq */ - int Done = 0 ; + SK_U32 Delta; + SK_TIMER *pTm; + SK_TIMER *pTComp; /* Timer completed now now */ + SK_TIMER **ppLast; /* Next field of Last timer to be deq */ + int Done = 0; - Delta = SkHwtRead(pAC,Ioc) ; - ppLast = &pAC->Tim.StQueue ; - pTm = pAC->Tim.StQueue ; + Delta = SkHwtRead(pAC, Ioc); + + ppLast = &pAC->Tim.StQueue; + pTm = pAC->Tim.StQueue; while (pTm && !Done) { if (Delta >= pTm->TmDelta) { /* Timer ran out */ - pTm->TmActive = SK_FALSE ; - Delta -= pTm->TmDelta ; - ppLast = &pTm->TmNext ; - pTm = pTm->TmNext ; - } else { + pTm->TmActive = SK_FALSE; + Delta -= pTm->TmDelta; + ppLast = &pTm->TmNext; + pTm = pTm->TmNext; + } + else { /* We found the first timer that did not run out */ - pTm->TmDelta -= Delta ; - Delta = 0 ; - Done = 1 ; + pTm->TmDelta -= Delta; + Delta = 0; + Done = 1; } } - *ppLast = 0 ; + *ppLast = 0; /* * pTm points to the first Timer that did not run out. * StQueue points to the first Timer that run out. */ - for ( pTComp = pAC->Tim.StQueue ; pTComp ; pTComp = pTComp->TmNext) { - SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, - pTComp->TmPara) ; + for (pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) { + SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara); } /* Set head of timer queue to the first timer that did not run out */ - pAC->Tim.StQueue = pTm ; + pAC->Tim.StQueue = pTm; if (Restart && pAC->Tim.StQueue) { /* Restart HW timer */ - SkHwtStart(pAC,Ioc,pAC->Tim.StQueue->TmDelta) ; + SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); } } -#endif /* CONFIG_SK98 */ - /* End of file */ + +#endif diff --git a/drivers/sk98lin/sktwsi.c b/drivers/sk98lin/sktwsi.c new file mode 100644 index 0000000..bbe95ec --- /dev/null +++ b/drivers/sk98lin/sktwsi.c @@ -0,0 +1,1365 @@ +/****************************************************************************** + * + * Name: sktwsi.c + * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Functions to access Voltage and Temperature Sensor + * + ******************************************************************************/ + +/****************************************************************************** + * + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2005 Marvell. + * + * 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. + * The information in this file is provided "AS IS" without warranty. + * /LICENSE + * + ******************************************************************************/ +#include + +#ifdef CONFIG_SK98 + +/* + * TWSI Protocol + */ +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) +static const char SysKonnectFileId[] = + "@(#) $Id: sktwsi.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif + +#include "h/skdrv1st.h" /* Driver Specific Definitions */ +#include "h/lm80.h" +#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ + +#ifdef __C2MAN__ +/* + TWSI protocol implementation. + + General Description: + + The TWSI protocol is used for the temperature sensors and for + the serial EEPROM which hold the configuration. + + This file covers functions that allow to read write and do + some bulk requests a specified TWSI address. + + The Genesis has 2 TWSI buses. One for the EEPROM which holds + the VPD Data and one for temperature and voltage sensor. + The following picture shows the TWSI buses, TWSI devices and + their control registers. + + Note: The VPD functions are in skvpd.c +. +. PCI Config TWSI Bus for VPD Data: +. +. +------------+ +. | VPD EEPROM | +. +------------+ +. | +. | <-- TWSI +. | +. +-----------+-----------+ +. | | +. +-----------------+ +-----------------+ +. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG | +. +-----------------+ +-----------------+ +. +. +. TWSI Bus for LM80 sensor: +. +. +-----------------+ +. | Temperature and | +. | Voltage Sensor | +. | LM80 | +. +-----------------+ +. | +. | +. TWSI --> | +. | +. +----+ +. +-------------->| OR |<--+ +. | +----+ | +. +------+------+ | +. | | | +. +--------+ +--------+ +----------+ +. | B2_I2C | | B2_I2C | | B2_I2C | +. | _CTRL | | _DATA | | _SW | +. +--------+ +--------+ +----------+ +. + The TWSI bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL + and B2_I2C_DATA registers. + For driver software it is recommended to use the TWSI control and + data register, because TWSI bus timing is done by the ASIC and + an interrupt may be received when the TWSI request is completed. + + Clock Rate Timing: MIN MAX generated by + VPD EEPROM: 50 kHz 100 kHz HW + LM80 over TWSI Ctrl/Data reg. 50 kHz 100 kHz HW + LM80 over B2_I2C_SW register 0 400 kHz SW + + Note: The clock generated by the hardware is dependend on the + PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD + clock is 50 kHz. + */ +intro() +{} +#endif + +#ifdef SK_DIAG +/* + * TWSI Fast Mode timing values used by the LM80. + * If new devices are added to the TWSI bus the timing values have to be checked. + */ +#ifndef I2C_SLOW_TIMING +#define T_CLK_LOW 1300L /* clock low time in ns */ +#define T_CLK_HIGH 600L /* clock high time in ns */ +#define T_DATA_IN_SETUP 100L /* data in Set-up Time */ +#define T_START_HOLD 600L /* start condition hold time */ +#define T_START_SETUP 600L /* start condition Set-up time */ +#define T_STOP_SETUP 600L /* stop condition Set-up time */ +#define T_BUS_IDLE 1300L /* time the bus must free after Tx */ +#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */ +#else /* I2C_SLOW_TIMING */ +/* TWSI Standard Mode Timing */ +#define T_CLK_LOW 4700L /* clock low time in ns */ +#define T_CLK_HIGH 4000L /* clock high time in ns */ +#define T_DATA_IN_SETUP 250L /* data in Set-up Time */ +#define T_START_HOLD 4000L /* start condition hold time */ +#define T_START_SETUP 4700L /* start condition Set-up time */ +#define T_STOP_SETUP 4000L /* stop condition Set-up time */ +#define T_BUS_IDLE 4700L /* time the bus must free after Tx */ +#endif /* !I2C_SLOW_TIMING */ + +#define NS2BCLK(x) (((x)*125)/10000) + +/* + * TWSI Wire Operations + * + * About I2C_CLK_LOW(): + * + * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting + * clock to low, to prevent the ASIC and the TWSI data client from driving the + * serial data line simultaneously (ASIC: last bit of a byte = '1', TWSI client + * send an 'ACK'). See also Concentrator Bugreport No. 10192. + */ +#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA) +#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA) +#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR) +#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA) +#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK) +#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR) +#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK) + +#define NS2CLKT(x) ((x*125L)/10000) + +/*--------------- TWSI Interface Register Functions --------------- */ + +/* + * sending one bit + */ +void SkI2cSndBit( +SK_IOC IoC, /* I/O Context */ +SK_U8 Bit) /* Bit to send */ +{ + I2C_DATA_OUT(IoC); + if (Bit) { + I2C_DATA_HIGH(IoC); + } + else { + I2C_DATA_LOW(IoC); + } + SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP)); + I2C_CLK_HIGH(IoC); + SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); + I2C_CLK_LOW(IoC); +} /* SkI2cSndBit*/ + + +/* + * Signal a start to the TWSI Bus. + * + * A start is signaled when data goes to low in a high clock cycle. + * + * Ends with Clock Low. + * + * Status: not tested + */ +void SkI2cStart( +SK_IOC IoC) /* I/O Context */ +{ + /* Init data and Clock to output lines */ + /* Set Data high */ + I2C_DATA_OUT(IoC); + I2C_DATA_HIGH(IoC); + /* Set Clock high */ + I2C_CLK_HIGH(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP)); + + /* Set Data Low */ + I2C_DATA_LOW(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD)); + + /* Clock low without Data to Input */ + I2C_START_COND(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW)); +} /* SkI2cStart */ + + +void SkI2cStop( +SK_IOC IoC) /* I/O Context */ +{ + /* Init data and Clock to output lines */ + /* Set Data low */ + I2C_DATA_OUT(IoC); + I2C_DATA_LOW(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); + + /* Set Clock high */ + I2C_CLK_HIGH(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP)); + + /* + * Set Data High: Do it by setting the Data Line to Input. + * Because of a pull up resistor the Data Line + * floods to high. + */ + I2C_DATA_IN(IoC); + + /* + * When TWSI activity is stopped + * o DATA should be set to input and + * o CLOCK should be set to high! + */ + SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE)); +} /* SkI2cStop */ + + +/* + * Receive just one bit via the TWSI bus. + * + * Note: Clock must be set to LOW before calling this function. + * + * Returns The received bit. + */ +int SkI2cRcvBit( +SK_IOC IoC) /* I/O Context */ +{ + int Bit; + SK_U8 I2cSwCtrl; + + /* Init data as input line */ + I2C_DATA_IN(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); + + I2C_CLK_HIGH(IoC); + + SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); + + SK_I2C_GET_SW(IoC, &I2cSwCtrl); + + Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0; + + I2C_CLK_LOW(IoC); + SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT)); + + return(Bit); +} /* SkI2cRcvBit */ + + +/* + * Receive an ACK. + * + * returns 0 If acknowledged + * 1 in case of an error + */ +int SkI2cRcvAck( +SK_IOC IoC) /* I/O Context */ +{ + /* + * Received bit must be zero. + */ + return(SkI2cRcvBit(IoC) != 0); +} /* SkI2cRcvAck */ + + +/* + * Send an NACK. + */ +void SkI2cSndNAck( +SK_IOC IoC) /* I/O Context */ +{ + /* + * Received bit must be zero. + */ + SkI2cSndBit(IoC, 1); +} /* SkI2cSndNAck */ + + +/* + * Send an ACK. + */ +void SkI2cSndAck( +SK_IOC IoC) /* I/O Context */ +{ + /* + * Received bit must be zero. + */ + SkI2cSndBit(IoC, 0); +} /* SkI2cSndAck */ + + +/* + * Send one byte to the TWSI device and wait for ACK. + * + * Return acknowleged status. + */ +int SkI2cSndByte( +SK_IOC IoC, /* I/O Context */ +int Byte) /* byte to send */ +{ + int i; + + for (i = 0; i < 8; i++) { + if (Byte & (1<<(7-i))) { + SkI2cSndBit(IoC, 1); + } + else { + SkI2cSndBit(IoC, 0); + } + } + + return(SkI2cRcvAck(IoC)); +} /* SkI2cSndByte */ + + +/* + * Receive one byte and ack it. + * + * Return byte. + */ +int SkI2cRcvByte( +SK_IOC IoC, /* I/O Context */ +int Last) /* Last Byte Flag */ +{ + int i; + int Byte = 0; + + for (i = 0; i < 8; i++) { + Byte <<= 1; + Byte |= SkI2cRcvBit(IoC); + } + + if (Last) { + SkI2cSndNAck(IoC); + } + else { + SkI2cSndAck(IoC); + } + + return(Byte); +} /* SkI2cRcvByte */ + + +/* + * Start dialog and send device address + * + * Return 0 if acknowleged, 1 in case of an error + */ +int SkI2cSndDev( +SK_IOC IoC, /* I/O Context */ +int Addr, /* Device Address */ +int Rw) /* Read / Write Flag */ +{ + SkI2cStart(IoC); + Rw = ~Rw; + Rw &= I2C_WRITE; + return(SkI2cSndByte(IoC, (Addr << 1) | Rw)); +} /* SkI2cSndDev */ + +#endif /* SK_DIAG */ + +/*----------------- TWSI CTRL Register Functions ----------*/ + +/* + * waits for a completion of a TWSI transfer + * + * returns 0: success, transfer completes + * 1: error, transfer does not complete, TWSI transfer + * killed, wait loop terminated. + */ +int SkI2cWait( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */ +{ + SK_U64 StartTime; + SK_U64 CurrentTime; + SK_U32 I2cCtrl; + + StartTime = SkOsGetTime(pAC); + + do { + CurrentTime = SkOsGetTime(pAC); + + if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) { + + SK_I2C_STOP(IoC); +#ifndef SK_DIAG + if (pAC->I2c.InitLevel > SK_INIT_DATA) { + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG); + } +#endif /* !SK_DIAG */ + return(1); + } + + SK_I2C_GET_CTL(IoC, &I2cCtrl); + +#ifdef xYUKON_DBG + printf("StartTime=%lu, CurrentTime=%lu\n", + StartTime, CurrentTime); + if (kbhit()) { + return(1); + } +#endif /* YUKON_DBG */ + + } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31); + + return(0); +} /* SkI2cWait */ + + +/* + * waits for a completion of a TWSI transfer + * + * Returns + * Nothing + */ +void SkI2cWaitIrq( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + SK_SENSOR *pSen; + SK_U64 StartTime; + SK_U32 IrqSrc; + SK_U32 IsTwsiReadyBit; + + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + + if (pSen->SenState == SK_SEN_IDLE) { + return; + } + + IsTwsiReadyBit = CHIP_ID_YUKON_2(pAC) ? Y2_IS_TWSI_RDY : IS_I2C_READY; + + StartTime = SkOsGetTime(pAC); + + do { + if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) { + + SK_I2C_STOP(IoC); +#ifndef SK_DIAG + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG); +#endif /* !SK_DIAG */ + return; + } + + SK_IN32(IoC, B0_ISRC, &IrqSrc); + + } while ((IrqSrc & IsTwsiReadyBit) == 0); + + pSen->SenState = SK_SEN_IDLE; + return; +} /* SkI2cWaitIrq */ + +/* + * writes a single byte or 4 bytes into the TWSI device + * + * returns 0: success + * 1: error + */ +int SkI2cWrite( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 I2cData, /* TWSI Data to write */ +int I2cDev, /* TWSI Device Address */ +int I2cDevSize, /* TWSI Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ +int I2cReg, /* TWSI Device Register Address */ +int I2cBurst) /* TWSI Burst Flag */ +{ + SK_OUT32(IoC, B2_I2C_DATA, I2cData); + + SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst); + + return(SkI2cWait(pAC, IoC, I2C_WRITE)); +} /* SkI2cWrite*/ + + +#ifdef SK_DIAG +/* + * reads a single byte or 4 bytes from the TWSI device + * + * returns the word read + */ +SK_U32 SkI2cRead( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int I2cDev, /* TWSI Device Address */ +int I2cDevSize, /* TWSI Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ +int I2cReg, /* TWSI Device Register Address */ +int I2cBurst) /* TWSI Burst Flag */ +{ + SK_U32 Data; + + SK_OUT32(IoC, B2_I2C_DATA, 0); + + SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst); + + if (SkI2cWait(pAC, IoC, I2C_READ) != 0) { + w_print("%s\n", SKERR_I2C_E002MSG); + } + + SK_IN32(IoC, B2_I2C_DATA, &Data); + + return(Data); +} /* SkI2cRead */ +#endif /* SK_DIAG */ + + +/* + * read a sensor's value + * + * This function reads a sensor's value from the TWSI sensor chip. The sensor + * is defined by its index into the sensors database in the struct pAC points + * to. + * Returns + * 1 if the read is completed + * 0 if the read must be continued (TWSI Bus still allocated) + */ +int SkI2cReadSensor( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_SENSOR *pSen) /* Sensor to be read */ +{ + if (pSen->SenRead != NULL) { + return((*pSen->SenRead)(pAC, IoC, pSen)); + } + + return(0); /* no success */ +} /* SkI2cReadSensor */ + +/* + * Do the Init state 0 initialization + */ +static int SkI2cInit0( +SK_AC *pAC) /* Adapter Context */ +{ + int i; + SK_SENSOR *pSen; + + /* Begin with first sensor */ + pAC->I2c.CurrSens = 0; + + /* Begin with timeout control for state machine */ + pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; + + /* Set sensor number to zero */ + pAC->I2c.MaxSens = 0; + +#ifndef SK_DIAG + /* Initialize Number of Dummy Reads */ + pAC->I2c.DummyReads = SK_MAX_SENSORS; +#endif /* !SK_DIAG */ + + for (i = 0; i < SK_MAX_SENSORS; i++) { + pSen = &pAC->I2c.SenTable[i]; + + pSen->SenDesc = "unknown"; + pSen->SenType = SK_SEN_UNKNOWN; + pSen->SenThreErrHigh = 0; + pSen->SenThreErrLow = 0; + pSen->SenThreWarnHigh = 0; + pSen->SenThreWarnLow = 0; + pSen->SenReg = LM80_FAN2_IN; + pSen->SenInit = SK_SEN_DYN_INIT_NONE; + pSen->SenValue = 0; + pSen->SenErrFlag = SK_SEN_ERR_NOT_PRESENT; + pSen->SenErrCts = 0; + pSen->SenBegErrTS = 0; + pSen->SenState = SK_SEN_IDLE; + pSen->SenRead = NULL; + pSen->SenDev = 0; + } + + /* Now we are "INIT data"ed */ + pAC->I2c.InitLevel = SK_INIT_DATA; + return(0); +} /* SkI2cInit0*/ + + +/* + * Do the init state 1 initialization + * + * initialize the following register of the LM80: + * Configuration register: + * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT + * + * Interrupt Mask Register 1: + * - all interrupts are Disabled (0xff) + * + * Interrupt Mask Register 2: + * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter. + * + * Fan Divisor/RST_OUT register: + * - Divisors set to 1 (bits 00), all others 0s. + * + * OS# Configuration/Temperature resolution Register: + * - all 0s + * + */ +static int SkI2cInit1( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + int i; + SK_U8 I2cSwCtrl; + SK_GEPORT *pPrt; /* GIni Port struct pointer */ + SK_SENSOR *pSen; + + if (pAC->I2c.InitLevel != SK_INIT_DATA) { + /* Re-init not needed in TWSI module */ + return(0); + } + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC || + pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { + /* No sensors on Yukon-EC and Yukon-FE */ + return(0); + } + + /* Set the Direction of TWSI-Data Pin to IN */ + SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA); + + /* Check for 32-Bit Yukon with Low at TWSI-Data Pin */ + SK_I2C_GET_SW(IoC, &I2cSwCtrl); + + if ((I2cSwCtrl & I2C_DATA) == 0) { + /* this is a 32-Bit board */ + pAC->GIni.GIYukon32Bit = SK_TRUE; + return(0); + } + + /* Check for 64 Bit Yukon without sensors */ + if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) { + return(0); + } + + (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0); + + (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0); + + (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0); + + (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0); + + (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV, + LM80_CFG, 0); + + /* + * MaxSens has to be updated here, because PhyType is not + * set when performing Init Level 0 + */ + pAC->I2c.MaxSens = 5; + + pPrt = &pAC->GIni.GP[0]; + + if (pAC->GIni.GIGenesis) { + if (pPrt->PhyType == SK_PHY_BCOM) { + if (pAC->GIni.GIMacsFound == 1) { + pAC->I2c.MaxSens += 1; + } + else { + pAC->I2c.MaxSens += 3; + } + } + } + else { + pAC->I2c.MaxSens += 3; + } + + for (i = 0; i < pAC->I2c.MaxSens; i++) { + pSen = &pAC->I2c.SenTable[i]; + switch (i) { + case 0: + pSen->SenDesc = "Temperature"; + pSen->SenType = SK_SEN_TEMP; + pSen->SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_TEMP_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_TEMP_LOW_ERR; + pSen->SenReg = LM80_TEMP_IN; + break; + case 1: + pSen->SenDesc = "Voltage PCI"; + pSen->SenType = SK_SEN_VOLT; + pSen->SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN; + if (pAC->GIni.GIPciBus != SK_PEX_BUS) { + pSen->SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR; + } + else { + pSen->SenThreWarnLow = 0; + pSen->SenThreErrLow = 0; + } + pSen->SenReg = LM80_VT0_IN; + break; + case 2: + pSen->SenDesc = "Voltage PCI-IO"; + pSen->SenType = SK_SEN_VOLT; + pSen->SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN; + if (pAC->GIni.GIPciBus != SK_PEX_BUS) { + pSen->SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR; + } + else { + pSen->SenThreWarnLow = 0; + pSen->SenThreErrLow = 0; + } + pSen->SenReg = LM80_VT1_IN; + pSen->SenInit = SK_SEN_DYN_INIT_PCI_IO; + break; + case 3: + if (pAC->GIni.GIGenesis) { + pSen->SenDesc = "Voltage ASIC"; + } + else { + pSen->SenDesc = "Voltage VMAIN"; + } + pSen->SenType = SK_SEN_VOLT; + pSen->SenThreErrHigh = SK_SEN_VDD_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_VDD_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_VDD_LOW_ERR; + pSen->SenReg = LM80_VT2_IN; + break; + case 4: + if (pAC->GIni.GIGenesis) { + if (pPrt->PhyType == SK_PHY_BCOM) { + pSen->SenDesc = "Voltage PHY A PLL"; + pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; + } + else { + pSen->SenDesc = "Voltage PMA"; + pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; + } + } + else { + pSen->SenDesc = "Voltage VAUX"; + pSen->SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN; + if (pAC->GIni.GIVauxAvail) { + pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; + } + else { + pSen->SenThreErrLow = 0; + pSen->SenThreWarnLow = 0; + } + } + pSen->SenType = SK_SEN_VOLT; + pSen->SenReg = LM80_VT3_IN; + break; + case 5: + if (CHIP_ID_YUKON_2(pAC)) { + if (pAC->GIni.GIChipRev == CHIP_REV_YU_XL_A0) { + pSen->SenDesc = "Voltage Core 1V3"; + pSen->SenThreErrHigh = SK_SEN_CORE_1V3_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_CORE_1V3_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_CORE_1V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_CORE_1V3_LOW_ERR; + } + else { + pSen->SenDesc = "Voltage Core 1V2"; + pSen->SenThreErrHigh = SK_SEN_CORE_1V2_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_CORE_1V2_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_CORE_1V2_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_CORE_1V2_LOW_ERR; + } + } + else { + if (pAC->GIni.GIGenesis) { + pSen->SenDesc = "Voltage PHY 2V5"; + pSen->SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; + } + else { + pSen->SenDesc = "Voltage Core 1V5"; + pSen->SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR; + } + } + pSen->SenType = SK_SEN_VOLT; + pSen->SenReg = LM80_VT4_IN; + break; + case 6: + if (CHIP_ID_YUKON_2(pAC)) { + pSen->SenDesc = "Voltage PHY 1V5"; + pSen->SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; + if (pAC->GIni.GIPciBus == SK_PEX_BUS) { + pSen->SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR; + } + else { + pSen->SenThreWarnLow = 0; + pSen->SenThreErrLow = 0; + } + } + else { + if (pAC->GIni.GIGenesis) { + pSen->SenDesc = "Voltage PHY B PLL"; + } + else { + pSen->SenDesc = "Voltage PHY 3V3"; + } + pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; + } + pSen->SenType = SK_SEN_VOLT; + pSen->SenReg = LM80_VT5_IN; + break; + case 7: + if (pAC->GIni.GIGenesis) { + pSen->SenDesc = "Speed Fan"; + pSen->SenType = SK_SEN_FAN; + pSen->SenThreErrHigh = SK_SEN_FAN_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_FAN_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_FAN_LOW_ERR; + pSen->SenReg = LM80_FAN2_IN; + } + else { + pSen->SenDesc = "Voltage PHY 2V5"; + pSen->SenType = SK_SEN_VOLT; + pSen->SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; + pSen->SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; + pSen->SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; + pSen->SenReg = LM80_VT6_IN; + } + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW, + SKERR_I2C_E001, SKERR_I2C_E001MSG); + break; + } + + pSen->SenValue = 0; + pSen->SenErrFlag = SK_SEN_ERR_OK; + pSen->SenErrCts = 0; + pSen->SenBegErrTS = 0; + pSen->SenState = SK_SEN_IDLE; + if (pSen->SenThreWarnLow != 0) { + pSen->SenRead = SkLm80ReadSensor; + } + pSen->SenDev = LM80_ADDR; + } + +#ifndef SK_DIAG + pAC->I2c.DummyReads = pAC->I2c.MaxSens; +#endif /* !SK_DIAG */ + + /* Clear TWSI IRQ */ + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); + + /* Now we are I/O initialized */ + pAC->I2c.InitLevel = SK_INIT_IO; + return(0); +} /* SkI2cInit1 */ + + +/* + * Init level 2: Start first sensor read. + */ +static int SkI2cInit2( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + int ReadComplete; + SK_SENSOR *pSen; + + if (pAC->I2c.InitLevel != SK_INIT_IO) { + /* ReInit not needed in TWSI module */ + /* Init0 and Init2 not permitted */ + return(0); + } + + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + + ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); + + if (ReadComplete) { + SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG); + } + + /* Now we are correctly initialized */ + pAC->I2c.InitLevel = SK_INIT_RUN; + + return(0); +} /* SkI2cInit2*/ + + +/* + * Initialize TWSI devices + * + * Get the first voltage value and discard it. + * Go into temperature read mode. A default pointer is not set. + * + * The things to be done depend on the init level in the parameter list: + * Level 0: + * Initialize only the data structures. Do NOT access hardware. + * Level 1: + * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts. + * Level 2: + * Everything is possible. Interrupts may be used from now on. + * + * return: + * 0 = success + * other = error. + */ +int SkI2cInit( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */ +int Level) /* Init Level */ +{ + + switch (Level) { + case SK_INIT_DATA: + return(SkI2cInit0(pAC)); + case SK_INIT_IO: + return(SkI2cInit1(pAC, IoC)); + case SK_INIT_RUN: + return(SkI2cInit2(pAC, IoC)); + default: + break; + } + + return(0); +} /* SkI2cInit */ + + +#ifndef SK_DIAG +/* + * Interrupt service function for the TWSI Interface + * + * Clears the Interrupt source + * + * Reads the register and check it for sending a trap. + * + * Starts the timer if necessary. + */ +void SkI2cIsr( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC) /* I/O Context */ +{ + SK_EVPARA Para; + + /* Clear TWSI IRQ */ + SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); + + Para.Para64 = 0; + SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para); +} /* SkI2cIsr */ + + +/* + * Check this sensors Value against the threshold and send events. + */ +static void SkI2cCheckSensor( +SK_AC *pAC, /* Adapter Context */ +SK_SENSOR *pSen) +{ + SK_EVPARA ParaLocal; + SK_BOOL TooHigh; /* Is sensor too high? */ + SK_BOOL TooLow; /* Is sensor too low? */ + SK_U64 CurrTime; /* Current Time */ + SK_BOOL DoTrapSend; /* We need to send a trap */ + SK_BOOL DoErrLog; /* We need to log the error */ + SK_BOOL IsError; /* Error occured */ + + /* Check Dummy Reads first */ + if (pAC->I2c.DummyReads > 0) { + pAC->I2c.DummyReads--; + return; + } + + /* Get the current time */ + CurrTime = SkOsGetTime(pAC); + + /* Set para to the most useful setting: The current sensor. */ + ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens; + + /* Check the Value against the thresholds. First: Error Thresholds */ + TooHigh = pSen->SenValue > pSen->SenThreErrHigh; + TooLow = pSen->SenValue < pSen->SenThreErrLow; + + IsError = SK_FALSE; + + if (TooHigh || TooLow) { + /* Error condition is satisfied */ + DoTrapSend = SK_TRUE; + DoErrLog = SK_TRUE; + + /* Now error condition is satisfied */ + IsError = SK_TRUE; + + if (pSen->SenErrFlag == SK_SEN_ERR_ERR) { + /* This state is the former one */ + + /* So check first whether we have to send a trap */ + if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > CurrTime) { + /* + * Do NOT send the Trap. The hold back time + * has to run out first. + */ + DoTrapSend = SK_FALSE; + } + + /* Check now whether we have to log an Error */ + if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > CurrTime) { + /* + * Do NOT log the error. The hold back time + * has to run out first. + */ + DoErrLog = SK_FALSE; + } + } + else { + /* We came from a different state -> Set Begin Time Stamp */ + pSen->SenBegErrTS = CurrTime; + pSen->SenErrFlag = SK_SEN_ERR_ERR; + } + + if (DoTrapSend) { + /* Set current Time */ + pSen->SenLastErrTrapTS = CurrTime; + pSen->SenErrCts++; + + /* Queue PNMI Event */ + SkEventQueue(pAC, SKGE_PNMI, TooHigh ? + SK_PNMI_EVT_SEN_ERR_UPP : SK_PNMI_EVT_SEN_ERR_LOW, + ParaLocal); + } + + if (DoErrLog) { + /* Set current Time */ + pSen->SenLastErrLogTS = CurrTime; + + if (pSen->SenType == SK_SEN_TEMP) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG); + } + else if (pSen->SenType == SK_SEN_VOLT) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG); + } + } + } + + /* Check the Value against the thresholds */ + /* 2nd: Warning thresholds */ + TooHigh = pSen->SenValue > pSen->SenThreWarnHigh; + TooLow = pSen->SenValue < pSen->SenThreWarnLow; + + if (!IsError && (TooHigh || TooLow)) { + /* Error condition is satisfied */ + DoTrapSend = SK_TRUE; + DoErrLog = SK_TRUE; + + if (pSen->SenErrFlag == SK_SEN_ERR_WARN) { + /* This state is the former one */ + + /* So check first whether we have to send a trap */ + if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) { + /* + * Do NOT send the Trap. The hold back time + * has to run out first. + */ + DoTrapSend = SK_FALSE; + } + + /* Check now whether we have to log an Error */ + if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) { + /* + * Do NOT log the error. The hold back time + * has to run out first. + */ + DoErrLog = SK_FALSE; + } + } + else { + /* We came from a different state -> Set Begin Time Stamp */ + pSen->SenBegWarnTS = CurrTime; + pSen->SenErrFlag = SK_SEN_ERR_WARN; + } + + if (DoTrapSend) { + /* Set current Time */ + pSen->SenLastWarnTrapTS = CurrTime; + pSen->SenWarnCts++; + + /* Queue PNMI Event */ + SkEventQueue(pAC, SKGE_PNMI, TooHigh ? + SK_PNMI_EVT_SEN_WAR_UPP : SK_PNMI_EVT_SEN_WAR_LOW, ParaLocal); + } + + if (DoErrLog) { + /* Set current Time */ + pSen->SenLastWarnLogTS = CurrTime; + + if (pSen->SenType == SK_SEN_TEMP) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG); + } + else if (pSen->SenType == SK_SEN_VOLT) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG); + } + else { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG); + } + } + } + + /* Check for NO error at all */ + if (!IsError && !TooHigh && !TooLow) { + /* Set o.k. Status if no error and no warning condition */ + pSen->SenErrFlag = SK_SEN_ERR_OK; + } + + /* End of check against the thresholds */ + + if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) { + /* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */ + pSen->SenInit = SK_SEN_DYN_INIT_NONE; + + if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) { + /* 5V PCI-IO Voltage */ + pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR; + } + else { + /* 3.3V PCI-IO Voltage */ + pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN; + pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR; + } + } + +#ifdef TEST_ONLY + /* Dynamic thresholds also for VAUX of LM80 sensor */ + if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) { + + pSen->SenInit = SK_SEN_DYN_INIT_NONE; + + /* 3.3V VAUX Voltage */ + if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) { + pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; + pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; + } + /* 0V VAUX Voltage */ + else { + pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR; + pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR; + } + } + + /* Check initialization state: the VIO Thresholds need adaption */ + if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && + pSen->SenValue > SK_SEN_WARNLOW2C && + pSen->SenValue < SK_SEN_WARNHIGH2) { + + pSen->SenThreErrLow = SK_SEN_ERRLOW2C; + pSen->SenThreWarnLow = SK_SEN_WARNLOW2C; + pSen->SenInit = SK_TRUE; + } + + if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && + pSen->SenValue > SK_SEN_WARNLOW2 && + pSen->SenValue < SK_SEN_WARNHIGH2C) { + + pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C; + pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C; + pSen->SenInit = SK_TRUE; + } +#endif + + if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) { + SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG); + } +} /* SkI2cCheckSensor */ + + +/* + * The only Event to be served is the timeout event + * + */ +int SkI2cEvent( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +SK_U32 Event, /* Module specific Event */ +SK_EVPARA Para) /* Event specific Parameter */ +{ + int ReadComplete; + SK_SENSOR *pSen; + SK_U32 Time; + SK_EVPARA ParaLocal; + int i; + + /* New case: no sensors */ + if (pAC->I2c.MaxSens == 0) { + return(0); + } + + switch (Event) { + case SK_I2CEV_IRQ: + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); + + if (ReadComplete) { + /* Check sensor against defined thresholds */ + SkI2cCheckSensor(pAC, pSen); + + /* Increment Current sensor and set appropriate Timeout */ + pAC->I2c.CurrSens++; + if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) { + pAC->I2c.CurrSens = 0; + Time = SK_I2C_TIM_LONG; + } + else { + Time = SK_I2C_TIM_SHORT; + } + + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + else { + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + break; + case SK_I2CEV_TIM: + if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) { + + ParaLocal.Para64 = (SK_U64)0; + SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer); + + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); + + if (ReadComplete) { + /* Check sensor against defined thresholds */ + SkI2cCheckSensor(pAC, pSen); + + /* Increment Current sensor and set appropriate Timeout */ + pAC->I2c.CurrSens++; + if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { + pAC->I2c.CurrSens = 0; + Time = SK_I2C_TIM_LONG; + } + else { + Time = SK_I2C_TIM_SHORT; + } + + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + } + else { + pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; + pSen->SenErrFlag = SK_SEN_ERR_FAULTY; + SK_I2C_STOP(IoC); + + /* Increment Current sensor and set appropriate Timeout */ + pAC->I2c.CurrSens++; + if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { + pAC->I2c.CurrSens = 0; + Time = SK_I2C_TIM_LONG; + } + else { + Time = SK_I2C_TIM_SHORT; + } + + /* Start Timer */ + ParaLocal.Para64 = (SK_U64)0; + + pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; + + SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, + SKGE_I2C, SK_I2CEV_TIM, ParaLocal); + } + break; + case SK_I2CEV_CLEAR: + for (i = 0; i < SK_MAX_SENSORS; i++) { + pSen = &pAC->I2c.SenTable[i]; + + pSen->SenErrFlag = SK_SEN_ERR_OK; + pSen->SenErrCts = 0; + pSen->SenWarnCts = 0; + pSen->SenBegErrTS = 0; + pSen->SenBegWarnTS = 0; + pSen->SenLastErrTrapTS = (SK_U64)0; + pSen->SenLastErrLogTS = (SK_U64)0; + pSen->SenLastWarnTrapTS = (SK_U64)0; + pSen->SenLastWarnLogTS = (SK_U64)0; + } + break; + default: + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG); + } + + return(0); +} /* SkI2cEvent*/ + +#endif /* !SK_DIAG */ + +#endif diff --git a/drivers/sk98lin/skvpd.c b/drivers/sk98lin/skvpd.c index 3b81e67..dd15bd9 100644 --- a/drivers/sk98lin/skvpd.c +++ b/drivers/sk98lin/skvpd.c @@ -1,174 +1,34 @@ /****************************************************************************** * * Name: skvpd.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.37 $ - * Date: $Date: 2003/01/13 10:42:45 $ - * Purpose: Shared software to read and write VPD data + * Project: Gigabit Ethernet Adapters, VPD-Module + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Shared software to read and write VPD * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2004 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skvpd.c,v $ - * Revision 1.37 2003/01/13 10:42:45 rschmidt - * Replaced check for PCI device Id from YUKON with GENESIS - * to set the VPD size in VpdInit() - * Editorial changes - * - * Revision 1.36 2002/11/14 15:16:56 gheinig - * Added const specifier to key and buf parameters for VpdPara, VpdRead - * and VpdWrite for Diag 7 GUI - * - * Revision 1.35 2002/10/21 14:31:59 gheinig - * Took out CVS web garbage at head of file - * - * Revision 1.34 2002/10/21 11:47:24 gheinig - * Reverted to version 1.32 due to unwanted commit - * - * Revision 1.32 2002/10/14 16:04:29 rschmidt - * Added saving of VPD ROM Size from PCI_OUR_REG_2 - * Avoid reading of PCI_OUR_REG_2 in VpdTransferBlock() - * Editorial changes - * - * Revision 1.31 2002/09/10 09:21:32 mkarl - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis - * - * Revision 1.30 2002/09/09 14:43:03 mkarl - * changes for diagnostics in order to read VPD data before the adapter - * has been initialized - * editorial changes - * - * Revision 1.29 2002/07/26 13:20:43 mkarl - * added Yukon support - * save size of VPD in pAC->vpd.vpd_size - * - * Revision 1.28 2002/04/02 15:31:47 afischer - * Bug fix in VpdWait() - * - * Revision 1.27 2000/08/10 11:29:06 rassmann - * Editorial changes. - * Preserving 32-bit alignment in structs for the adapter context. - * Removed unused function VpdWriteDword() (#if 0). - * Made VpdReadKeyword() available for SKDIAG only. - * - * Revision 1.26 2000/06/13 08:00:01 mkarl - * additional cast to avoid compile problems in 64 bit environment - * - * Revision 1.25 1999/11/22 13:39:32 cgoos - * Changed license header to GPL. - * - * Revision 1.24 1999/03/11 14:25:49 malthoff - * Replace __STDC__ with SK_KR_PROTO. - * - * Revision 1.23 1999/01/11 15:13:11 gklug - * fix: syntax error - * - * Revision 1.22 1998/10/30 06:41:15 gklug - * rmv: WARNING - * - * Revision 1.21 1998/10/29 07:15:14 gklug - * fix: Write Stream function needs verify. - * - * Revision 1.20 1998/10/28 18:05:08 gklug - * chg: no DEBUG in VpdMayWrite - * - * Revision 1.19 1998/10/28 15:56:11 gklug - * fix: Return len at end of ReadStream - * fix: Write even less than 4 bytes correctly - * - * Revision 1.18 1998/10/28 09:00:47 gklug - * fix: unreferenced local vars - * - * Revision 1.17 1998/10/28 08:25:45 gklug - * fix: WARNING - * - * Revision 1.16 1998/10/28 08:17:30 gklug - * fix: typo - * - * Revision 1.15 1998/10/28 07:50:32 gklug - * fix: typo - * - * Revision 1.14 1998/10/28 07:20:38 gklug - * chg: Interface functions to use IoC as parameter as well - * fix: VpdRead/WriteDWord now returns SK_U32 - * chg: VPD_IN/OUT names conform to SK_IN/OUT - * add: usage of VPD_IN/OUT8 macros - * add: VpdRead/Write Stream functions to r/w a stream of data - * fix: VpdTransferBlock swapped illegal - * add: VpdMayWrite - * - * Revision 1.13 1998/10/22 10:02:37 gklug - * fix: SysKonnectFileId typo - * - * Revision 1.12 1998/10/20 10:01:01 gklug - * fix: parameter to SkOsGetTime - * - * Revision 1.11 1998/10/15 12:51:48 malthoff - * Remove unrequired parameter p in vpd_setup_para(). - * - * Revision 1.10 1998/10/08 14:52:43 malthoff - * Remove CvsId by SysKonnectFileId. - * - * Revision 1.9 1998/09/16 07:33:52 malthoff - * replace memcmp() by SK_MEMCMP and - * memcpy() by SK_MEMCPY() to be - * independent from the 'C' Standard Library. - * - * Revision 1.8 1998/08/19 12:52:35 malthoff - * compiler fix: use SK_VPD_KEY instead of S_VPD. - * - * Revision 1.7 1998/08/19 08:14:01 gklug - * fix: remove struct keyword as much as possible from the C-code (see CCC) - * - * Revision 1.6 1998/08/18 13:03:58 gklug - * SkOsGetTime now returns SK_U64 - * - * Revision 1.5 1998/08/18 08:17:29 malthoff - * Ensure we issue a VPD read in vpd_read_dword(). - * Discard all VPD keywords other than Vx or Yx, where - * x is '0..9' or 'A..Z'. - * - * Revision 1.4 1998/07/03 14:52:19 malthoff - * Add category SK_DBGCAT_FATAL to some debug macros. - * bug fix: correct the keyword name check in vpd_write(). - * - * Revision 1.3 1998/06/26 11:16:53 malthoff - * Correct the modified File Identifier. - * - * Revision 1.2 1998/06/26 11:13:43 malthoff - * Modify the File Identifier. - * - * Revision 1.1 1998/06/19 14:11:08 malthoff - * Created, Tests with AIX were performed successfully - * - * - ******************************************************************************/ - #include - + #ifdef CONFIG_SK98 /* Please refer skvpd.txt for infomation how to include this module */ static const char SysKonnectFileId[] = - "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK"; + "@(#) $Id: skvpd.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; #include "h/skdrv1st.h" #include "h/sktypes.h" @@ -202,9 +62,10 @@ int event) /* event to wait for (VPD_READ / VPD_write) completion*/ SK_U64 start_time; SK_U16 state; - SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("VPD wait for %s\n", event?"Write":"Read")); start_time = SkOsGetTime(pAC); + do { if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) { @@ -229,12 +90,13 @@ int event) /* event to wait for (VPD_READ / VPD_write) completion*/ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("state = %x, event %x\n",state,event)); - } while((int)(state & PCI_VPD_FLAG) == event); + } while ((int)(state & PCI_VPD_FLAG) == event); return(0); } -#ifdef SKDIAG + +#ifdef SK_DIAG /* * Read the dword at address 'addr' from the VPD EEPROM. @@ -272,8 +134,7 @@ int addr) /* VPD address */ ("VPD read dword data = 0x%x\n",Rtv)); return(Rtv); } - -#endif /* SKDIAG */ +#endif /* SK_DIAG */ #if 0 @@ -294,7 +155,6 @@ int addr) /* VPD address */ . over all 3.8 ms 13.2 ms . - Returns 0: success 1: error, I2C transfer does not terminate 2: error, data verify error @@ -334,6 +194,7 @@ SK_U32 data) /* VPD data to write */ #endif /* 0 */ + /* * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from * or to the I2C EEPROM. @@ -358,7 +219,7 @@ int Len) /* number of bytes to read / to write */ pComp = (SK_U8 *) buf; for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { + if ((i % SZ_LONG) == 0) { /* * At the begin of each cycle read the Data Reg * So it is initialized even if only a few bytes @@ -376,14 +237,13 @@ int Len) /* number of bytes to read / to write */ } } - /* Write current Byte */ - VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - *(SK_U8*)buf); + /* Write current byte */ + VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i % SZ_LONG), *(SK_U8*)buf); - if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) { + if (((i % SZ_LONG) == 3) || (i == (Len - 1))) { /* New Address needs to be written to VPD_ADDR reg */ AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); + Addr += SZ_LONG; AdrReg |= VPD_WRITE; /* WRITE operation */ VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); @@ -393,7 +253,7 @@ int Len) /* number of bytes to read / to write */ if (Rtv != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("Write Timed Out\n")); - return(i - (i%sizeof(SK_U32))); + return(i - (i % SZ_LONG)); } /* @@ -408,10 +268,10 @@ int Len) /* number of bytes to read / to write */ if (Rtv != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("Verify Timed Out\n")); - return(i - (i%sizeof(SK_U32))); + return(i - (i % SZ_LONG)); } - for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) { + for (j = 0; j <= (int)(i % SZ_LONG); j++, pComp++) { VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data); @@ -419,7 +279,7 @@ int Len) /* number of bytes to read / to write */ /* Verify Error */ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("WriteStream Verify Error\n")); - return(i - (i%sizeof(SK_U32)) + j); + return(i - (i % SZ_LONG) + j); } } } @@ -447,10 +307,10 @@ int Len) /* number of bytes to read / to write */ int Rtv; for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { + if ((i % SZ_LONG) == 0) { /* New Address needs to be written to VPD_ADDR reg */ AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); + Addr += SZ_LONG; AdrReg &= ~VPD_WRITE; /* READ operation */ VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); @@ -461,13 +321,13 @@ int Len) /* number of bytes to read / to write */ return(i); } } - VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - (SK_U8 *)buf); + VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i % SZ_LONG), (SK_U8 *)buf); } return(Len); } + /* * Read ore writes 'len' bytes of VPD data, starting at 'addr' from * or to the I2C EEPROM. @@ -517,8 +377,8 @@ int dir) /* transfer direction may be VPD_READ or VPD_WRITE */ return(Rtv); } -#ifdef SKDIAG +#if defined (SK_DIAG) || defined (SK_ASF) /* * Read 'len' bytes of VPD data, starting at 'addr'. * @@ -534,6 +394,7 @@ int len) /* number of bytes to read */ return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)); } + /* * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'. * @@ -548,18 +409,27 @@ int len) /* number of bytes to write */ { return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)); } -#endif /* SKDIAG */ +#endif /* SK_DIAG */ -/* - * (re)initialize the VPD buffer + +/****************************************************************************** * - * Reads the VPD data from the EEPROM into the VPD buffer. - * Get the remaining read only and read / write space. + * VpdInit() - (re)initialize the VPD buffer * - * return 0: success - * 1: fatal VPD error + * Description: + * Reads the VPD data from the EEPROM into the VPD buffer. + * Get the remaining read only and read / write space. + * + * Note: + * This is a local function and should be used locally only. + * However, the ASF module needs to use this function also. + * Therfore it has been published. + * + * Returns: + * 0: success + * 1: fatal VPD error */ -static int VpdInit( +int VpdInit( SK_AC *pAC, /* Adapters context */ SK_IOC IoC) /* IO Context */ { @@ -570,7 +440,7 @@ SK_IOC IoC) /* IO Context */ SK_U16 dev_id; SK_U32 our_reg2; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. ")); + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit ... ")); VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id); @@ -611,6 +481,13 @@ SK_IOC IoC) /* IO Context */ pAC->vpd.vpd_size = vpd_size; + /* Asus K8V Se Deluxe bugfix. Correct VPD content */ + i = 62; + if (!SK_STRNCMP(pAC->vpd.vpd_buf + i, " 8vpd.vpd_buf[i + 2] = '8'; + } + /* find the end tag of the RO area */ if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, @@ -619,7 +496,7 @@ SK_IOC IoC) /* IO Context */ } if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) { - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + SK_DBG_MSG(pAC, SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Encoding Error: Invalid VPD struct size\n")); return(1); } @@ -663,6 +540,7 @@ SK_IOC IoC) /* IO Context */ return(0); } + /* * find the Keyword 'key' in the VPD buffer and fills the * parameter struct 'p' with it's values @@ -673,7 +551,7 @@ SK_IOC IoC) /* IO Context */ static SK_VPD_PARA *vpd_find_para( SK_AC *pAC, /* common data base */ const char *key, /* keyword to find (e.g. "MN") */ -SK_VPD_PARA *p) /* parameter description struct */ +SK_VPD_PARA *p) /* parameter description struct */ { char *v ; /* points to VPD buffer */ int max; /* Maximum Number of Iterations */ @@ -691,7 +569,7 @@ SK_VPD_PARA *p) /* parameter description struct */ return(0); } - if (strcmp(key, VPD_NAME) == 0) { + if (SK_STRCMP(key, VPD_NAME) == 0) { p->p_len = VPD_GET_RES_LEN(v); p->p_val = VPD_GET_VAL(v); SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, @@ -701,7 +579,7 @@ SK_VPD_PARA *p) /* parameter description struct */ v += 3 + VPD_GET_RES_LEN(v) + 3; for (;; ) { - if (SK_MEMCMP(key,v,2) == 0) { + if (SK_MEMCMP(key, v, 2) == 0) { p->p_len = VPD_GET_VPD_LEN(v); p->p_val = VPD_GET_VAL(v); SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, @@ -711,11 +589,11 @@ SK_VPD_PARA *p) /* parameter description struct */ /* exit when reaching the "RW" Tag or the maximum of itera. */ max--; - if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) { + if (SK_MEMCMP(VPD_RW, v, 2) == 0 || max == 0) { break; } - if (SK_MEMCMP(VPD_RV,v,2) == 0) { + if (SK_MEMCMP(VPD_RV, v, 2) == 0) { v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ } else { @@ -735,6 +613,7 @@ SK_VPD_PARA *p) /* parameter description struct */ return(0); } + /* * Move 'n' bytes. Begin with the last byte if 'n' is > 0, * Start with the last byte if n is < 0. @@ -769,6 +648,7 @@ int n) /* number of bytes the memory block has to be moved */ } } + /* * setup the VPD keyword 'key' at 'ip'. * @@ -785,10 +665,11 @@ char *ip) /* inseration point */ p = (SK_VPD_KEY *) ip; p->p_key[0] = key[0]; p->p_key[1] = key[1]; - p->p_len = (unsigned char) len; - SK_MEMCPY(&p->p_val,buf,len); + p->p_len = (unsigned char)len; + SK_MEMCPY(&p->p_val, buf, len); } + /* * Setup the VPD end tag "RV" / "RW". * Also correct the remaining space variables vpd_free_ro / vpd_free_rw. @@ -814,7 +695,7 @@ char *etp) /* end pointer input position */ if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) { /* something wrong here, encoding error */ - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, ("Encoding Error: invalid end tag\n")); return(1); } @@ -846,6 +727,7 @@ char *etp) /* end pointer input position */ return(0); } + /* * Insert a VPD keyword into the VPD buffer. * @@ -1007,18 +889,18 @@ int *elements) /* number of keywords returned */ } } - if ((signed)strlen(VPD_NAME) + 1 <= *len) { + if ((signed)SK_STRLEN(VPD_NAME) + 1 <= *len) { v = pAC->vpd.vpd_buf; - strcpy(buf,VPD_NAME); - n = strlen(VPD_NAME) + 1; + SK_STRCPY(buf, VPD_NAME); + n = SK_STRLEN(VPD_NAME) + 1; buf += n; *elements = 1; SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("'%c%c' ",v[0],v[1])); + ("'%c%c' ", v[0], v[1])); } else { *len = 0; - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR, + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("buffer overflow\n")); return(2); } @@ -1026,17 +908,17 @@ int *elements) /* number of keywords returned */ v += 3 + VPD_GET_RES_LEN(v) + 3; for (;; ) { /* exit when reaching the "RW" Tag */ - if (SK_MEMCMP(VPD_RW,v,2) == 0) { + if (SK_MEMCMP(VPD_RW, v, 2) == 0) { break; } - if (SK_MEMCMP(VPD_RV,v,2) == 0) { + if (SK_MEMCMP(VPD_RV, v, 2) == 0) { v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ continue; } if (n+3 <= *len) { - SK_MEMCPY(buf,v,2); + SK_MEMCPY(buf, v, 2); buf += 2; *buf++ = '\0'; n += 3; @@ -1123,13 +1005,14 @@ char *key) /* keyword to write (allowed values "Yx", "Vx") */ { if ((*key != 'Y' && *key != 'V') || key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { + (key[1] > '9' && key[1] < 'A') || SK_STRLEN(key) != 2) { return(SK_FALSE); } return(SK_TRUE); } + /* * Read the contents of the VPD EEPROM and copy it to the VPD * buffer if not already done. Insert/overwrite the keyword 'key' @@ -1158,7 +1041,7 @@ const char *buf) /* buffer where the keyword value can be read from */ if ((*key != 'Y' && *key != 'V') || key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { + (key[1] > '9' && key[1] < 'A') || SK_STRLEN(key) != 2) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("illegal key tag, keyword not written\n")); @@ -1174,13 +1057,13 @@ const char *buf) /* buffer where the keyword value can be read from */ } rtv = 0; - len = strlen(buf); + len = SK_STRLEN(buf); if (len > VPD_MAX_LEN) { /* cut it */ len = VPD_MAX_LEN; rtv = 2; SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN)); + ("keyword too long, cut after %d bytes\n", VPD_MAX_LEN)); } if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, @@ -1191,6 +1074,7 @@ const char *buf) /* buffer where the keyword value can be read from */ return(rtv); } + /* * Read the contents of the VPD EEPROM and copy it to the * VPD buffer if not already done. Remove the VPD keyword @@ -1214,7 +1098,7 @@ char *key) /* keyword to read (e.g. "MN") */ vpd_size = pAC->vpd.vpd_size; - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key)); + SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD delete key %s\n", key)); if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { if (VpdInit(pAC, IoC) != 0) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, @@ -1251,6 +1135,7 @@ char *key) /* keyword to read (e.g. "MN") */ return(0); } + /* * If the VPD buffer contains valid data write the VPD * read/write area back to the VPD EEPROM. @@ -1309,7 +1194,7 @@ char *msg) /* error log message */ } } - len = strlen(msg); + len = SK_STRLEN(msg); if (len > VPD_MAX_LEN) { /* cut it */ len = VPD_MAX_LEN; @@ -1326,4 +1211,4 @@ char *msg) /* error log message */ (void)VpdUpdate(pAC, IoC); } -#endif /* CONFIG_SK98 */ +#endif diff --git a/drivers/sk98lin/skxmac2.c b/drivers/sk98lin/skxmac2.c index e6b5a95..5552797 100644 --- a/drivers/sk98lin/skxmac2.c +++ b/drivers/sk98lin/skxmac2.c @@ -1,417 +1,30 @@ /****************************************************************************** * * Name: skxmac2.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.91 $ - * Date: $Date: 2003/02/05 15:09:34 $ + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ * Purpose: Contains functions to initialize the MACs and PHYs * ******************************************************************************/ /****************************************************************************** * - * (C)Copyright 1998-2003 SysKonnect GmbH. + * LICENSE: + * (C)Copyright 1998-2002 SysKonnect. + * (C)Copyright 2002-2006 Marvell. * * 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. - * * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * History: - * - * $Log: skxmac2.c,v $ - * Revision 1.91 2003/02/05 15:09:34 rschmidt - * Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv(). - * Disabled auto-update for speed, duplex and flow-control when - * auto-negotiation is not enabled (Bug Id #10766). - * Editorial changes. - * - * Revision 1.90 2003/01/29 13:35:19 rschmidt - * Increment Rx FIFO Overflow counter only in DEBUG-mode. - * Corrected define for blinking active LED. - * - * Revision 1.89 2003/01/28 16:37:45 rschmidt - * Changed init for blinking active LED - * - * Revision 1.88 2003/01/28 10:09:38 rschmidt - * Added debug outputs in SkGmInitMac(). - * Added customized init of LED registers in SkGmInitPhyMarv(), - * for blinking active LED (#ifdef ACT_LED_BLINK) and - * for normal duplex LED (#ifdef DUP_LED_NORMAL). - * Editorial changes. - * - * Revision 1.87 2002/12/10 14:39:05 rschmidt - * Improved initialization of GPHY in SkGmInitPhyMarv(). - * Editorial changes. - * - * Revision 1.86 2002/12/09 15:01:12 rschmidt - * Added setup of Ext. PHY Specific Ctrl Reg (downshift feature). - * - * Revision 1.85 2002/12/05 14:09:16 rschmidt - * Improved avoiding endless loop in SkGmPhyWrite(), SkGmPhyWrite(). - * Added additional advertising for 10Base-T when 100Base-T is selected. - * Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter. - * Editorial changes. - * - * Revision 1.84 2002/11/15 12:50:09 rschmidt - * Changed SkGmCableDiagStatus() when getting results. - * - * Revision 1.83 2002/11/13 10:28:29 rschmidt - * Added some typecasts to avoid compiler warnings. - * - * Revision 1.82 2002/11/13 09:20:46 rschmidt - * Replaced for(..) with do {} while (...) in SkXmUpdateStats(). - * Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic(). - * Added SkGmCableDiagStatus() for Virtual Cable Test (VCT). - * Editorial changes. - * - * Revision 1.81 2002/10/28 14:28:08 rschmidt - * Changed MAC address setup for GMAC in SkGmInitMac(). - * Optimized handling of counter overflow IRQ in SkGmOverflowStatus(). - * Editorial changes. - * - * Revision 1.80 2002/10/14 15:29:44 rschmidt - * Corrected disabling of all PHY IRQs. - * Added WA for deviation #16 (address used for pause packets). - * Set Pause Mode in SkMacRxTxEnable() only for Genesis. - * Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode. - * SkXmTimeStamp() replaced by SkMacTimeStamp(). - * Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq(). - * Editorial changes. - * - * Revision 1.79 2002/10/10 15:55:36 mkarl - * changes for PLinkSpeedUsed - * - * Revision 1.78 2002/09/12 09:39:51 rwahl - * Removed deactivate code for SIRQ overflow event separate for TX/RX. - * - * Revision 1.77 2002/09/09 12:26:37 mkarl - * added handling for Yukon to SkXmTimeStamp - * - * Revision 1.76 2002/08/21 16:41:16 rschmidt - * Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE. - * Added forced speed settings in SkGmInitPhyMarv(). - * Added settings of full/half duplex capabilities for YUKON Fiber. - * Editorial changes. - * - * Revision 1.75 2002/08/16 15:12:01 rschmidt - * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis. - * Added function SkMacHashing() for ADDR-Module. - * Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced - * with macros). - * Removed functions SkGmGetMuxConfig(). - * Added HWCFG_MODE init for YUKON Fiber. - * Changed initialization of GPHY in SkGmInitPhyMarv(). - * Changed check of parameter in SkXmMacStatistic(). - * Editorial changes. - * - * Revision 1.74 2002/08/12 14:00:17 rschmidt - * Replaced usage of Broadcom PHY Ids with defines. - * Corrected error messages in SkGmMacStatistic(). - * Made SkMacPromiscMode() public for ADDR-Modul. - * Editorial changes. - * - * Revision 1.73 2002/08/08 16:26:24 rschmidt - * Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac(). - * Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM. - * Editorial changes. - * - * Revision 1.72 2002/07/24 15:11:19 rschmidt - * Fixed wrong placement of parenthesis. - * Editorial changes. - * - * Revision 1.71 2002/07/23 16:05:18 rschmidt - * Added global functions for PHY: SkGePhyRead(), SkGePhyWrite(). - * Fixed Tx Counter Overflow IRQ (Bug ID #10730). - * Editorial changes. - * - * Revision 1.70 2002/07/18 14:27:27 rwahl - * Fixed syntax error. - * - * Revision 1.69 2002/07/17 17:08:47 rwahl - * Fixed check in SkXmMacStatistic(). - * - * Revision 1.68 2002/07/16 07:35:24 rwahl - * Removed check for cleared mib counter in SkGmResetCounter(). - * - * Revision 1.67 2002/07/15 18:35:56 rwahl - * Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(), - * SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(), - * SkXmOverflowStatus(), SkGmOverflowStatus(). - * Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both - * RX & TX. - * Changes to SkGmInitMac(): call to SkGmResetCounter(). - * Editorial changes. - * - * Revision 1.66 2002/07/15 15:59:30 rschmidt - * Added PHY Address in SkXmPhyRead(), SkXmPhyWrite(). - * Added MIB Clear Counter in SkGmInitMac(). - * Added Duplex and Flow-Control settings. - * Reset all Multicast filtering Hash reg. in SkGmInitMac(). - * Added new function: SkGmGetMuxConfig(). - * Editorial changes. - * - * Revision 1.65 2002/06/10 09:35:39 rschmidt - * Replaced C++ comments (//). - * Added #define VCPU around VCPUwaitTime. - * Editorial changes. - * - * Revision 1.64 2002/06/05 08:41:10 rschmidt - * Added function for XMAC2: SkXmTimeStamp(). - * Added function for YUKON: SkGmSetRxCmd(). - * Changed SkGmInitMac() resp. SkGmHardRst(). - * Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode). - * SkXmRxTxEnable() replaced by SkMacRxTxEnable(). - * Editorial changes. - * - * Revision 1.63 2002/04/25 13:04:44 rschmidt - * Changes for handling YUKON. - * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types. - * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced - * by functions SkXmPhyRead(), SkXmPhyWrite(); - * Removed use of PRxCmd to setup XMAC. - * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res. - * Added setting of XM_RX_DIS_CEXT in SkXmInitMac(). - * Removed status parameter from MAC IRQ handler SkMacIrq(), - * SkXmIrq() and SkGmIrq(). - * SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy(). - * Added SkMac...() functions to handle both XMAC and GMAC. - * Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(), - * SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(), - * SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite(). - * Changes for V-CPU support. - * Editorial changes. - * - * Revision 1.62 2001/08/06 09:50:14 rschmidt - * Workaround BCOM Errata #1 for the C5 type. - * Editorial changes. - * - * Revision 1.61 2001/02/09 15:40:59 rassmann - * Editorial changes. - * - * Revision 1.60 2001/02/07 15:02:01 cgoos - * Added workaround for Fujitsu switch link down. - * - * Revision 1.59 2001/01/10 09:38:06 cgoos - * Fixed Broadcom C0/A1 Id check for workaround. - * - * Revision 1.58 2000/11/29 11:30:38 cgoos - * Changed DEBUG sections with NW output to xDEBUG - * - * Revision 1.57 2000/11/27 12:40:40 rassmann - * Suppressing preamble after first access to BCom, not before (#10556). - * - * Revision 1.56 2000/11/09 12:32:48 rassmann - * Renamed variables. - * - * Revision 1.55 2000/11/09 11:30:10 rassmann - * WA: Waiting after releasing reset until BCom chip is accessible. - * - * Revision 1.54 2000/10/02 14:10:27 rassmann - * Reading BCOM PHY after releasing reset until it returns a valid value. - * - * Revision 1.53 2000/07/27 12:22:11 gklug - * fix: possible endless loop in XmHardRst. - * - * Revision 1.52 2000/05/22 08:48:31 malthoff - * Fix: #10523 errata valid for all BCOM PHYs. - * - * Revision 1.51 2000/05/17 12:52:18 malthoff - * Fixes BCom link errata (#10523). - * - * Revision 1.50 1999/11/22 13:40:14 cgoos - * Changed license header to GPL. - * - * Revision 1.49 1999/11/22 08:12:13 malthoff - * Add workaround for power consumption feature of BCom C0 chip. - * - * Revision 1.48 1999/11/16 08:39:01 malthoff - * Fix: MDIO preamble suppression is port dependent. - * - * Revision 1.47 1999/08/27 08:55:35 malthoff - * 1000BT: Optimizing MDIO transfer by oppressing MDIO preamble. - * - * Revision 1.46 1999/08/13 11:01:12 malthoff - * Fix for 1000BT: pFlowCtrlMode was not set correctly. - * - * Revision 1.45 1999/08/12 19:18:28 malthoff - * 1000BT Fixes: Do not owerwrite XM_MMU_CMD. - * Do not execute BCOM A1 workaround for B1 chips. - * Fix pause frame setting. - * Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL. - * - * Revision 1.44 1999/08/03 15:23:48 cgoos - * Fixed setting of PHY interrupt mask in half duplex mode. - * - * Revision 1.43 1999/08/03 15:22:17 cgoos - * Added some debug output. - * Disabled XMac GP0 interrupt for external PHYs. - * - * Revision 1.42 1999/08/02 08:39:23 malthoff - * BCOM PHY: TX LED: To get the mono flop behaviour it is required - * to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL. - * - * Revision 1.41 1999/07/30 06:54:31 malthoff - * Add temp. workarounds for the BCOM Phy revision A1. - * - * Revision 1.40 1999/06/01 07:43:26 cgoos - * Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to - * AUTOFULL/AUTOHALF. - * - * Revision 1.39 1999/05/19 07:29:51 cgoos - * Changes for 1000Base-T. - * - * Revision 1.38 1999/04/08 14:35:10 malthoff - * Add code for enabling signal detect. Enabling signal detect is disabled. - * - * Revision 1.37 1999/03/12 13:42:54 malthoff - * Add: Jumbo Frame Support. - * Add: Receive modes SK_LENERR_OK_ON/OFF and - * SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd(). - * - * Revision 1.36 1999/03/08 10:10:55 gklug - * fix: AutoSensing did switch to next mode even if LiPa indicated offline - * - * Revision 1.35 1999/02/22 15:16:41 malthoff - * Remove some compiler warnings. - * - * Revision 1.34 1999/01/22 09:19:59 gklug - * fix: Init DupMode and InitPauseMd are now called in RxTxEnable - * - * Revision 1.33 1998/12/11 15:19:11 gklug - * chg: lipa autoneg stati - * chg: debug messages - * chg: do NOT use spurious XmIrq - * - * Revision 1.32 1998/12/10 11:08:44 malthoff - * bug fix: pAC has been used for IOs in SkXmHardRst(). - * SkXmInitPhy() is also called for the Diag in SkXmInitMac(). - * - * Revision 1.31 1998/12/10 10:39:11 gklug - * fix: do 4 RESETS of the XMAC at the beginning - * fix: dummy read interrupt source register BEFORE initializing the Phy - * add: debug messages - * fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt - * - * Revision 1.30 1998/12/07 12:18:32 gklug - * add: refinement of autosense mode: take into account the autoneg cap of LiPa - * - * Revision 1.29 1998/12/07 07:12:29 gklug - * fix: if page is received the link is down. - * - * Revision 1.28 1998/12/01 10:12:47 gklug - * chg: if spurious IRQ from XMAC encountered, save it - * - * Revision 1.27 1998/11/26 07:33:38 gklug - * add: InitPhy call is now in XmInit function - * - * Revision 1.26 1998/11/18 13:38:24 malthoff - * 'Imsk' is also unused in SkXmAutoNegDone. - * - * Revision 1.25 1998/11/18 13:28:01 malthoff - * Remove unused variable 'Reg' in SkXmAutoNegDone(). - * - * Revision 1.24 1998/11/18 13:18:45 gklug - * add: workaround for xmac errata #1 - * add: detect Link Down also when Link partner requested config - * chg: XMIrq is only used when link is up - * - * Revision 1.23 1998/11/04 07:07:04 cgoos - * Added function SkXmRxTxEnable. - * - * Revision 1.22 1998/10/30 07:35:54 gklug - * fix: serve LinkDown interrupt when link is already down - * - * Revision 1.21 1998/10/29 15:32:03 gklug - * fix: Link Down signaling - * - * Revision 1.20 1998/10/29 11:17:27 gklug - * fix: AutoNegDone bug - * - * Revision 1.19 1998/10/29 10:14:43 malthoff - * Add endainesss comment for reading/writing MAC addresses. - * - * Revision 1.18 1998/10/28 07:48:55 cgoos - * Fix: ASS somtimes signaled although link is up. - * - * Revision 1.17 1998/10/26 07:55:39 malthoff - * Fix in SkXmInitPauseMd(): Pause Mode - * was disabled and not enabled. - * Fix in SkXmAutoNegDone(): Checking Mode bits - * always failed, becaues of some missing braces. - * - * Revision 1.16 1998/10/22 09:46:52 gklug - * fix SysKonnectFileId typo - * - * Revision 1.15 1998/10/21 05:51:37 gklug - * add: para DoLoop to InitPhy function for loopback set-up - * - * Revision 1.14 1998/10/16 10:59:23 malthoff - * Remove Lint warning for dummy reads. - * - * Revision 1.13 1998/10/15 14:01:20 malthoff - * Fix: SkXmAutoNegDone() is (int) but does not return a value. - * - * Revision 1.12 1998/10/14 14:45:04 malthoff - * Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by - * SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent - * from the Sirq module. - * - * Revision 1.11 1998/10/14 13:59:01 gklug - * add: InitPhy function - * - * Revision 1.10 1998/10/14 11:20:57 malthoff - * Make SkXmAutoNegDone() public, because it's - * used in diagnostics, too. - * The Link Up event to the RLMT is issued in SkXmIrq(). - * SkXmIrq() is not available in diagnostics. - * Use PHY_READ when reading PHY registers. - * - * Revision 1.9 1998/10/14 05:50:10 cgoos - * Added definition for Para. - * - * Revision 1.8 1998/10/14 05:41:28 gklug - * add: Xmac IRQ - * add: auto-negotiation done function - * - * Revision 1.7 1998/10/09 06:55:20 malthoff - * The configuration of the XMACs Tx Request Threshold - * depends from the drivers port usage now. The port - * usage is configured in GIPortUsage. - * - * Revision 1.6 1998/10/05 07:48:00 malthoff - * minor changes - * - * Revision 1.5 1998/10/01 07:03:54 gklug - * add: dummy function for XMAC ISR - * - * Revision 1.4 1998/09/30 12:37:44 malthoff - * Add SkXmSetRxCmd() and related code. - * - * Revision 1.3 1998/09/28 13:26:40 malthoff - * Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd() - * - * Revision 1.2 1998/09/16 14:34:21 malthoff - * Add SkXmClrExactAddr(), SkXmClrSrcCheck(), - * SkXmClrHashAddr(), SkXmFlushTxFifo(), - * SkXmFlushRxFifo(), and SkXmHardRst(). - * Finish Coding of SkXmSoftRst(). - * The sources may be compiled now. - * - * Revision 1.1 1998/09/04 10:05:56 malthoff - * Created. - * + * /LICENSE * ******************************************************************************/ #include - + #ifdef CONFIG_SK98 #include "h/skdrv1st.h" @@ -421,14 +34,18 @@ /* BCOM PHY magic pattern list */ typedef struct s_PhyHack { - int PhyReg; /* Phy register */ + int PhyReg; /* PHY register */ SK_U16 PhyVal; /* Value to write */ } BCOM_HACK; /* local variables ************************************************************/ -static const char SysKonnectFileId[] = - "@(#)$Id: skxmac2.c,v 1.91 2003/02/05 15:09:34 rschmidt Exp $ (C) SK "; +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) +static const char SysKonnectFileId[] = + "@(#) $Id: skxmac2.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif + +#ifdef GENESIS BCOM_HACK BcomRegA1Hack[] = { { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, @@ -440,14 +57,19 @@ BCOM_HACK BcomRegC0Hack[] = { { 0x15, 0x0A04 }, { 0x18, 0x0420 }, { 0, 0 } }; +#endif /* function prototypes ********************************************************/ +#ifdef GENESIS static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL); static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL); static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int); static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int); +#endif /* GENESIS */ +#ifdef YUKON +static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL); static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int); +#endif /* YUKON */ #ifdef OTHER_PHY static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL); static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL); @@ -456,6 +78,7 @@ static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int); #endif /* OTHER_PHY */ +#ifdef GENESIS /****************************************************************************** * * SkXmPhyRead() - Read from XMAC PHY register @@ -465,12 +88,12 @@ static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int); * Returns: * nothing */ -void SkXmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 *pVal) /* Pointer to Value */ +int SkXmPhyRead( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 SK_FAR *pVal) /* Pointer to Value */ { SK_U16 Mmu; SK_GEPORT *pPrt; @@ -492,6 +115,8 @@ SK_U16 *pVal) /* Pointer to Value */ /* get the PHY register's value */ XM_IN16(IoC, Port, XM_PHY_DATA, pVal); } + + return(0); } /* SkXmPhyRead */ @@ -504,7 +129,7 @@ SK_U16 *pVal) /* Pointer to Value */ * Returns: * nothing */ -void SkXmPhyWrite( +int SkXmPhyWrite( SK_AC *pAC, /* Adapter Context */ SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ @@ -535,9 +160,13 @@ SK_U16 Val) /* Value */ /* wait until 'Busy' is cleared */ } while ((Mmu & XM_MMU_PHY_BUSY) != 0); } + + return(0); } /* SkXmPhyWrite */ +#endif /* GENESIS */ +#ifdef YUKON /****************************************************************************** * * SkGmPhyRead() - Read from GPHY register @@ -545,62 +174,97 @@ SK_U16 Val) /* Value */ * Description: reads a 16-bit word from GPHY through MDIO * * Returns: - * nothing + * 0 o.k. + * 1 error during MDIO read + * 2 timeout */ -void SkGmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 *pVal) /* Pointer to Value */ +int SkGmPhyRead( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +int PhyReg, /* Register Address (Offset) */ +SK_U16 SK_FAR *pVal) /* Pointer to Value */ { + SK_U16 Word; SK_U16 Ctrl; SK_GEPORT *pPrt; -#ifdef VCPU - u_long SimCyle; - u_long SimLowTime; + SK_U32 StartTime; + SK_U32 CurrTime; + SK_U32 Delta; + SK_U32 TimeOut; + int Rtv; - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n", - PhyReg, SimCyle, SimLowTime); -#endif /* VCPU */ + Rtv = 0; + + *pVal = 0xffff; pPrt = &pAC->GIni.GP[Port]; /* set PHY-Register offset and 'Read' OpCode (= 1) */ - *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | + Word = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD); - GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); + GM_OUT16(IoC, Port, GM_SMI_CTRL, Word); /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - *pVal = 0; - return; + GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); + + if (Ctrl == 0xffff || (Ctrl & GM_SMI_CT_OP_RD) == 0) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("PHY read impossible on Port %d (Ctrl=0x%04x)\n", Port, Ctrl)); + + return(1); } - *pVal |= GM_SMI_CT_BUSY; + Word |= GM_SMI_CT_BUSY; - do { + SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime); + + /* set timeout to 10 ms */ + TimeOut = HW_MS_TO_TICKS(pAC, 10); + + do { /* wait until 'Busy' is cleared and 'ReadValid' is set */ #ifdef VCPU VCPUwaitTime(1000); #endif /* VCPU */ + SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime); + + if (CurrTime >= StartTime) { + Delta = CurrTime - StartTime; + } + else { + Delta = CurrTime + ~StartTime + 1; + } + + if (Delta > TimeOut) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("PHY read timeout on Port %d (Ctrl=0x%04x)\n", Port, Ctrl)); + Rtv = 2; + break; + } + GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - /* wait until 'ReadValid' is set */ - } while (Ctrl == *pVal); + /* Error on reading SMI Control Register */ + if (Ctrl == 0xffff) { + return(1); + } + + } while ((Ctrl ^ Word) != (GM_SMI_CT_RD_VAL | GM_SMI_CT_BUSY)); - /* get the PHY register's value */ GM_IN16(IoC, Port, GM_SMI_DATA, pVal); -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ + /* dummy read after GM_IN16() */ + SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("SkGmPhyRead Port:%d, Reg=%d, Val = 0x%04X\n", + Port, PhyReg, *pVal)); + + return(Rtv); } /* SkGmPhyRead */ @@ -611,9 +275,11 @@ SK_U16 *pVal) /* Pointer to Value */ * Description: writes a 16-bit word to GPHY through MDIO * * Returns: - * nothing + * 0 o.k. + * 1 error during MDIO read + * 2 timeout */ -void SkGmPhyWrite( +int SkGmPhyWrite( SK_AC *pAC, /* Adapter Context */ SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ @@ -622,56 +288,83 @@ SK_U16 Val) /* Value */ { SK_U16 Ctrl; SK_GEPORT *pPrt; -#ifdef VCPU - SK_U32 DWord; - u_long SimCyle; - u_long SimLowTime; + SK_U32 StartTime; + SK_U32 CurrTime; + SK_U32 Delta; + SK_U32 TimeOut; - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n", - PhyReg, Val, SimCyle, SimLowTime); -#endif /* VCPU */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("SkGmPhyWrite Port:%d, Reg=%d, Val = 0x%04X\n", + Port, PhyReg, Val)); pPrt = &pAC->GIni.GP[Port]; /* write the PHY register's value */ GM_OUT16(IoC, Port, GM_SMI_DATA, Val); - /* set PHY-Register offset and 'Write' OpCode (= 0) */ - Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg); - - GM_OUT16(IoC, Port, GM_SMI_CTRL, Val); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - +#ifdef DEBUG /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - return; + GM_IN16(IoC, Port, GM_SMI_DATA, &Ctrl); + + if (Ctrl != Val) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("PHY write impossible on Port %d (Val=0x%04x)\n", Port, Ctrl)); + + return(1); } +#endif /* DEBUG */ - Val |= GM_SMI_CT_BUSY; + /* set PHY-Register offset and 'Write' OpCode (= 0) */ + Ctrl = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | + GM_SMI_CT_REG_AD(PhyReg)); - do { + GM_OUT16(IoC, Port, GM_SMI_CTRL, Ctrl); + + SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime); + + /* set timeout to 10 ms */ + TimeOut = HW_MS_TO_TICKS(pAC, 10); + + do { /* wait until 'Busy' is cleared */ #ifdef VCPU - /* read Timer value */ - SK_IN32(IoC, B2_TI_VAL, &DWord); - VCPUwaitTime(1000); #endif /* VCPU */ + SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime); + + if (CurrTime >= StartTime) { + Delta = CurrTime - StartTime; + } + else { + Delta = CurrTime + ~StartTime + 1; + } + + if (Delta > TimeOut) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("PHY write timeout on Port %d (Ctrl=0x%04x)\n", Port, Ctrl)); + return(2); + } + GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - /* wait until 'Busy' is cleared */ - } while (Ctrl == Val); + /* Error on reading SMI Control Register */ + if (Ctrl == 0xffff) { + return(1); + } -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ + } while ((Ctrl & GM_SMI_CT_BUSY) != 0); + + /* dummy read after GM_IN16() */ + SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime); + + return(0); } /* SkGmPhyWrite */ +#endif /* YUKON */ +#ifdef SK_DIAG /****************************************************************************** * * SkGePhyRead() - Read from PHY register @@ -688,16 +381,8 @@ int Port, /* Port Index (MAC_1 + n) */ int PhyReg, /* Register Address (Offset) */ SK_U16 *pVal) /* Pointer to Value */ { - void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal); - if (pAC->GIni.GIGenesis) { - r_func = SkXmPhyRead; - } - else { - r_func = SkGmPhyRead; - } - - r_func(pAC, IoC, Port, PhyReg, pVal); + pAC->GIni.GIFunc.pFnMacPhyRead(pAC, IoC, Port, PhyReg, pVal); } /* SkGePhyRead */ @@ -717,17 +402,10 @@ int Port, /* Port Index (MAC_1 + n) */ int PhyReg, /* Register Address (Offset) */ SK_U16 Val) /* Value */ { - void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val); - if (pAC->GIni.GIGenesis) { - w_func = SkXmPhyWrite; - } - else { - w_func = SkGmPhyWrite; - } - - w_func(pAC, IoC, Port, PhyReg, Val); + pAC->GIni.GIFunc.pFnMacPhyWrite(pAC, IoC, Port, PhyReg, Val); } /* SkGePhyWrite */ +#endif /* SK_DIAG */ /****************************************************************************** @@ -735,21 +413,26 @@ SK_U16 Val) /* Value */ * SkMacPromiscMode() - Enable / Disable Promiscuous Mode * * Description: - * enables / disables promiscuous mode by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type + * enables / disables promiscuous mode by setting Mode Register (XMAC) or + * Receive Control Register (GMAC) dep. on board type * * Returns: * nothing */ void SkMacPromiscMode( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL Enable) /* Enable / Disable */ { +#ifdef YUKON SK_U16 RcReg; +#endif +#ifdef GENESIS SK_U32 MdReg; +#endif +#ifdef GENESIS if (pAC->GIni.GIGenesis) { XM_IN32(IoC, Port, XM_MODE, &MdReg); @@ -763,7 +446,10 @@ SK_BOOL Enable) /* Enable / Disable */ /* setup Mode Register */ XM_OUT32(IoC, Port, XM_MODE, MdReg); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); @@ -777,6 +463,8 @@ SK_BOOL Enable) /* Enable / Disable */ /* setup Receive Control Register */ GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); } +#endif /* YUKON */ + } /* SkMacPromiscMode*/ @@ -785,21 +473,26 @@ SK_BOOL Enable) /* Enable / Disable */ * SkMacHashing() - Enable / Disable Hashing * * Description: - * enables / disables hashing by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type + * enables / disables hashing by setting Mode Register (XMAC) or + * Receive Control Register (GMAC) dep. on board type * * Returns: * nothing */ void SkMacHashing( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL Enable) /* Enable / Disable */ { +#ifdef YUKON SK_U16 RcReg; +#endif +#ifdef GENESIS SK_U32 MdReg; +#endif +#ifdef GENESIS if (pAC->GIni.GIGenesis) { XM_IN32(IoC, Port, XM_MODE, &MdReg); @@ -813,7 +506,10 @@ SK_BOOL Enable) /* Enable / Disable */ /* setup Mode Register */ XM_OUT32(IoC, Port, XM_MODE, MdReg); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); @@ -827,6 +523,8 @@ SK_BOOL Enable) /* Enable / Disable */ /* setup Receive Control Register */ GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); } +#endif /* YUKON */ + } /* SkMacHashing*/ @@ -842,8 +540,8 @@ SK_BOOL Enable) /* Enable / Disable */ * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF * for inrange length error frames * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF + * for frames > 1514 bytes + * - enable Rx of own packets SK_SELF_RX_ON/OFF * * for incoming packets may be enabled/disabled by this function. * Additional modes may be added later. @@ -854,11 +552,11 @@ SK_BOOL Enable) /* Enable / Disable */ * nothing */ static void SkXmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ + SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ { SK_U16 OldRxCmd; SK_U16 RxCmd; @@ -927,8 +625,8 @@ int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, * The features * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF + * for frames > 1514 bytes + * - enable Rx of own packets SK_SELF_RX_ON/OFF * * for incoming packets may be enabled/disabled by this function. * Additional modes may be added later. @@ -939,20 +637,17 @@ int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, * nothing */ static void SkGmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ + SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ { - SK_U16 OldRxCmd; SK_U16 RxCmd; if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) { - GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd); - - RxCmd = OldRxCmd; + GM_IN16(IoC, Port, GM_RX_CTRL, &RxCmd); if ((Mode & SK_STRIP_FCS_ON) != 0) { RxCmd |= GM_RXCR_CRC_DIS; @@ -960,17 +655,13 @@ int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, else { RxCmd &= ~GM_RXCR_CRC_DIS; } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd); - } + /* Write the new mode to the Rx Control register */ + GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd); } if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) { - GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd); - - RxCmd = OldRxCmd; + GM_IN16(IoC, Port, GM_SERIAL_MODE, &RxCmd); if ((Mode & SK_BIG_PK_OK_ON) != 0) { RxCmd |= GM_SMOD_JUMBO_ENA; @@ -978,10 +669,8 @@ int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, else { RxCmd &= ~GM_SMOD_JUMBO_ENA; } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd); - } + /* Write the new mode to the Serial Mode register */ + GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd); } } /* SkGmSetRxCmd */ @@ -996,8 +685,8 @@ int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, * nothing */ void SkMacSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ int Mode) /* Rx Mode */ { @@ -1009,6 +698,7 @@ int Mode) /* Rx Mode */ SkGmSetRxCmd(pAC, IoC, Port, Mode); } + } /* SkMacSetRxCmd */ @@ -1022,8 +712,8 @@ int Mode) /* Rx Mode */ * nothing */ void SkMacCrcGener( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL Enable) /* Enable / Disable */ { @@ -1040,7 +730,7 @@ SK_BOOL Enable) /* Enable / Disable */ Word |= XM_TX_NO_CRC; } /* setup Tx Command Register */ - XM_OUT16(pAC, Port, XM_TX_CMD, Word); + XM_OUT16(IoC, Port, XM_TX_CMD, Word); } else { @@ -1055,11 +745,13 @@ SK_BOOL Enable) /* Enable / Disable */ /* setup Tx Control Register */ GM_OUT16(IoC, Port, GM_TX_CTRL, Word); } + } /* SkMacCrcGener*/ #endif /* SK_DIAG */ +#ifdef GENESIS /****************************************************************************** * * SkXmClrExactAddr() - Clear Exact Match Address Registers @@ -1073,14 +765,14 @@ SK_BOOL Enable) /* Enable / Disable */ * nothing */ void SkXmClrExactAddr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ int StartNum, /* Begin with this Address Register Index (0..15) */ int StopNum) /* Stop after finished with this Register Idx (0..15) */ { int i; - SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000}; + SK_U16 ZeroAddr[3] = {0, 0, 0}; if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 || StartNum > StopNum) { @@ -1090,9 +782,10 @@ int StopNum) /* Stop after finished with this Register Idx (0..15) */ } for (i = StartNum; i <= StopNum; i++) { - XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]); + XM_OUTADDR(IoC, Port, XM_EXM(i), ZeroAddr); } } /* SkXmClrExactAddr */ +#endif /* GENESIS */ /****************************************************************************** @@ -1106,10 +799,11 @@ int StopNum) /* Stop after finished with this Register Idx (0..15) */ * nothing */ void SkMacFlushTxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { +#ifdef GENESIS SK_U32 MdReg; if (pAC->GIni.GIGenesis) { @@ -1118,10 +812,15 @@ int Port) /* Port Index (MAC_1 + n) */ XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { /* no way to flush the FIFO we have to issue a reset */ /* TBD */ } +#endif /* YUKON */ + } /* SkMacFlushTxFifo */ @@ -1136,10 +835,11 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkMacFlushRxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { +#ifdef GENESIS SK_U32 MdReg; if (pAC->GIni.GIGenesis) { @@ -1148,13 +848,19 @@ int Port) /* Port Index (MAC_1 + n) */ XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { /* no way to flush the FIFO we have to issue a reset */ /* TBD */ } +#endif /* YUKON */ + } /* SkMacFlushRxFifo */ +#ifdef GENESIS /****************************************************************************** * * SkXmSoftRst() - Do a XMAC software reset @@ -1191,11 +897,11 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ static void SkXmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { - SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000}; + SK_U16 ZeroAddr[4] = {0, 0, 0, 0}; /* reset the statistics module */ XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT); @@ -1225,13 +931,13 @@ int Port) /* Port Index (MAC_1 + n) */ } /* clear the Hash Register */ - XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr); + XM_OUTHASH(IoC, Port, XM_HSM, ZeroAddr); /* clear the Exact Match Address registers */ SkXmClrExactAddr(pAC, IoC, Port, 0, 15); /* clear the Source Check Address registers */ - XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr); + XM_OUTHASH(IoC, Port, XM_SRC_CHK, ZeroAddr); } /* SkXmSoftRst */ @@ -1243,7 +949,7 @@ int Port) /* Port Index (MAC_1 + n) */ * Description: * The XMAC of the specified 'Port' and all connected devices * (PHY and SERDES) will receive a reset signal on its *Reset pins. - * External PHYs must be reset be clearing a bit in the GPIO register + * External PHYs must be reset by clearing a bit in the GPIO register * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns). * * ATTENTION: @@ -1254,8 +960,8 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ static void SkXmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_U32 Reg; @@ -1286,25 +992,66 @@ int Port) /* Port Index (MAC_1 + n) */ /* For external PHYs there must be special handling */ if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { - /* reset external PHY */ + SK_IN32(IoC, B2_GP_IO, &Reg); + if (Port == 0) { - Reg |= GP_DIR_0; /* set to output */ - Reg &= ~GP_IO_0; + Reg |= GP_DIR_0; /* set to output */ + Reg &= ~GP_IO_0; /* set PHY reset (active low) */ } else { - Reg |= GP_DIR_2; /* set to output */ - Reg &= ~GP_IO_2; + Reg |= GP_DIR_2; /* set to output */ + Reg &= ~GP_IO_2; /* set PHY reset (active low) */ } + /* reset external PHY */ SK_OUT32(IoC, B2_GP_IO, Reg); /* short delay */ SK_IN32(IoC, B2_GP_IO, &Reg); } - } /* SkXmHardRst */ +/****************************************************************************** + * + * SkXmClearRst() - Release the PHY & XMAC reset + * + * Description: + * + * Returns: + * nothing + */ +static void SkXmClearRst( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U32 DWord; + + /* clear HW reset */ + SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + + if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { + + SK_IN32(IoC, B2_GP_IO, &DWord); + + if (Port == 0) { + DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */ + } + else { + DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */ + } + /* Clear PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + + /* enable GMII interface */ + XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); + } +} /* SkXmClearRst */ +#endif /* GENESIS */ + + +#ifdef YUKON /****************************************************************************** * * SkGmSoftRst() - Do a GMAC software reset @@ -1317,17 +1064,17 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ static void SkGmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { - SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000}; - SK_U16 RxCtrl; + SK_U16 EmptyHash[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; + SK_U16 RxCtrl; /* reset the statistics module */ /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); + SK_OUT8(IoC, MR_ADDR(Port, GMAC_IRQ_MSK), 0); /* disable all PHY IRQs */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); @@ -1335,11 +1082,10 @@ int Port) /* Port Index (MAC_1 + n) */ /* clear the Hash Register */ GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash); - /* Enable Unicast and Multicast filtering */ + /* enable Unicast and Multicast filtering */ GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl); - GM_OUT16(IoC, Port, GM_RX_CTRL, - RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); + GM_OUT16(IoC, Port, GM_RX_CTRL, RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); } /* SkGmSoftRst */ @@ -1350,27 +1096,162 @@ int Port) /* Port Index (MAC_1 + n) */ * * Description: * - * ATTENTION: - * It is absolutely necessary to reset the SW_RST Bit first - * before calling this function. - * * Returns: * nothing */ static void SkGmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { + SK_U32 DWord; + + /* WA code for COMA mode */ + if (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { + + SK_IN32(IoC, B2_GP_IO, &DWord); + + DWord |= (GP_DIR_9 | GP_IO_9); + + /* set PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + } + /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); + SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET); /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_SET); } /* SkGmHardRst */ +/****************************************************************************** + * + * SkGmClearRst() - Release the GPHY & GMAC reset + * + * Description: + * + * Returns: + * nothing + */ +static void SkGmClearRst( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U32 DWord; +#ifdef SK_DIAG + SK_U16 PhyId0; + SK_U16 PhyId1; +#endif /* SK_DIAG */ + +#if defined(SK_DIAG) || defined(DEBUG) + SK_U16 Word; +#endif /* SK_DIAG || DEBUG */ + + /* WA code for COMA mode */ + if (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { + + SK_IN32(IoC, B2_GP_IO, &DWord); + + DWord |= GP_DIR_9; /* set to output */ + DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ + + /* clear PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + } + +#ifdef VCPU + /* set MAC Reset before PHY reset is set */ + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_SET); +#endif /* VCPU */ + + if (CHIP_ID_YUKON_2(pAC)) { + /* set GPHY Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET); + + /* release GPHY Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR); + +#ifdef DEBUG + /* additional check for PEX */ + SK_IN16(IoC, GPHY_CTRL, &Word); + + if (pAC->GIni.GIPciBus == SK_PEX_BUS && Word != GPC_RST_CLR) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("Error on PEX-bus after GPHY reset\n")); + } +#endif /* DEBUG */ + } + else { + /* set HWCFG_MODE */ + DWord = GPC_INT_POL | GPC_DIS_FC | GPC_DIS_SLEEP | + GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | + (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : + GPC_HWCFG_GMII_FIB); + + /* set GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); + + /* release GPHY Control reset */ + SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); + } + +#ifdef VCPU + /* wait for internal initialization of GPHY */ + VCPUprintf(0, "Waiting until PHY %d is ready to initialize\n", Port); + VCpuWait(10000); + + /* release GMAC reset */ + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR); + + /* wait for stable GMAC clock */ + VCpuWait(9000); +#endif /* VCPU */ + + /* clear GMAC Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR); + +#ifdef SK_DIAG + if (HW_FEATURE(pAC, HWF_WA_DEV_472) && Port == MAC_2) { + + /* clear GMAC 1 Control reset */ + SK_OUT8(IoC, MR_ADDR(MAC_1, GMAC_CTRL), (SK_U8)GMC_RST_CLR); + + do { + /* set GMAC 2 Control reset */ + SK_OUT8(IoC, MR_ADDR(MAC_2, GMAC_CTRL), (SK_U8)GMC_RST_SET); + + /* clear GMAC 2 Control reset */ + SK_OUT8(IoC, MR_ADDR(MAC_2, GMAC_CTRL), (SK_U8)GMC_RST_CLR); + + SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_ID0, &PhyId0); + + SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_ID1, &PhyId1); + + SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_INT_MASK, &Word); + + } while (Word != 0 || PhyId0 != PHY_MARV_ID0_VAL || + PhyId1 != PHY_MARV_ID1_Y2); + } +#endif /* SK_DIAG */ + +#ifdef VCPU + VCpuWait(2000); + + SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord); + + SK_IN32(IoC, B0_ISRC, &DWord); +#endif /* VCPU */ + +} /* SkGmClearRst */ +#endif /* YUKON */ + + /****************************************************************************** * * SkMacSoftRst() - Do a MAC software reset @@ -1381,32 +1262,33 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkMacSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - /* disable receiver and transmitter */ SkMacRxTxDisable(pAC, IoC, Port); +#ifdef GENESIS if (pAC->GIni.GIGenesis) { SkXmSoftRst(pAC, IoC, Port); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { SkGmSoftRst(pAC, IoC, Port); } +#endif /* YUKON */ /* flush the MAC's Rx and Tx FIFOs */ SkMacFlushTxFifo(pAC, IoC, Port); SkMacFlushRxFifo(pAC, IoC, Port); - pPrt->PState = SK_PRT_STOP; + pAC->GIni.GP[Port].PState = SK_PRT_STOP; } /* SkMacSoftRst */ @@ -1421,25 +1303,65 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkMacHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { +#ifdef GENESIS if (pAC->GIni.GIGenesis) { SkXmHardRst(pAC, IoC, Port); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { SkGmHardRst(pAC, IoC, Port); } +#endif /* YUKON */ + + pAC->GIni.GP[Port].PHWLinkUp = SK_FALSE; pAC->GIni.GP[Port].PState = SK_PRT_RESET; } /* SkMacHardRst */ +#ifndef SK_SLIM +/****************************************************************************** + * + * SkMacClearRst() - Clear the MAC reset + * + * Description: calls a clear MAC reset routine dep. on board type + * + * Returns: + * nothing + */ +void SkMacClearRst( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port) /* Port Index (MAC_1 + n) */ +{ +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + + SkXmClearRst(pAC, IoC, Port); + } +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + + SkGmClearRst(pAC, IoC, Port); + } +#endif /* YUKON */ + +} /* SkMacClearRst */ +#endif /* !SK_SLIM */ + +#ifdef GENESIS /****************************************************************************** * * SkXmInitMac() - Initialize the XMAC II @@ -1455,57 +1377,34 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkXmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; - SK_U32 Reg; int i; SK_U16 SWord; pPrt = &pAC->GIni.GP[Port]; if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ /* Verify that the reset bit is cleared */ SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); if ((SWord & MFF_SET_MAC_RST) != 0) { /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("SkXmInitMac: PState does not match HW state")); /* Correct it */ pPrt->PState = SK_PRT_RESET; } } if (pPrt->PState == SK_PRT_RESET) { - /* - * clear HW reset - * Note: The SW reset is self clearing, therefore there is - * nothing to do here. - */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - /* Ensure that XMAC reset release is done (errata from LReinbold?) */ - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); + SkXmClearRst(pAC, IoC, Port); - /* Clear PHY reset */ if (pPrt->PhyType != SK_PHY_XMAC) { - - SK_IN32(IoC, B2_GP_IO, &Reg); - - if (Port == 0) { - Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */ - } - else { - Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */ - } - SK_OUT32(IoC, B2_GP_IO, Reg); - - /* Enable GMII interface */ - XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); - /* read Id from external PHY (all have the same address) */ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); @@ -1563,12 +1462,6 @@ int Port) /* Port Index (MAC_1 + n) */ * started by the SIRQ, therefore stop it here immediately. */ SkMacInitPhy(pAC, IoC, Port, SK_FALSE); - -#if 0 - /* temp. code: enable signal detect */ - /* WARNING: do not override GMII setting above */ - XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG); -#endif } /* @@ -1600,7 +1493,7 @@ int Port) /* Port Index (MAC_1 + n) */ SWord = SK_XM_THR_SL; /* for single port */ if (pAC->GIni.GIMacsFound > 1) { - switch (pAC->GIni.GIPortUsage) { + switch (pPrt->PPortUsage) { case SK_RED_LINK: SWord = SK_XM_THR_REDL; /* redundant link */ break; @@ -1623,11 +1516,11 @@ int Port) /* Port Index (MAC_1 + n) */ /* setup register defaults for the Rx Command Register */ SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK; - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + if (pPrt->PPortUsage == SK_JUMBO_LINK) { SWord |= XM_RX_BIG_PK_OK; } - if (pPrt->PLinkModeConf == SK_LMODE_HALF) { + if (pPrt->PLinkMode == SK_LMODE_HALF) { /* * If in manual half duplex mode the other side might be in * full duplex mode, so ignore if a carrier extension is not seen @@ -1673,7 +1566,10 @@ int Port) /* Port Index (MAC_1 + n) */ * has been completed successfully. */ } /* SkXmInitMac */ +#endif /* GENESIS */ + +#ifdef YUKON /****************************************************************************** * * SkGmInitMac() - Initialize the GMAC @@ -1689,8 +1585,8 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkGmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; @@ -1701,112 +1597,116 @@ int Port) /* Port Index (MAC_1 + n) */ pPrt = &pAC->GIni.GP[Port]; if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ /* Verify that the reset bit is cleared */ SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord); if ((DWord & GMC_RST_SET) != 0) { /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("SkGmInitMac: PState does not match HW state")); /* Correct it */ pPrt->PState = SK_PRT_RESET; } + else { + /* enable PHY interrupts */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, + (SK_U16)PHY_M_DEF_MSK); + } } if (pPrt->PState == SK_PRT_RESET) { - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); + SkGmHardRst(pAC, IoC, Port); - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); + SkGmClearRst(pAC, IoC, Port); - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); +#ifndef SK_SLIM + if (HW_FEATURE(pAC, HWF_FORCE_AUTO_NEG) && + pPrt->PLinkModeConf < SK_LMODE_AUTOHALF) { + /* Force Auto-Negotiation */ + pPrt->PLinkMode = (pPrt->PLinkModeConf == SK_LMODE_FULL) ? + SK_LMODE_AUTOBOTH : SK_LMODE_AUTOHALF; + } +#endif /* !SK_SLIM */ - /* set HWCFG_MODE */ - DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | - GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | - (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : - GPC_HWCFG_GMII_FIB); + /* Auto-negotiation ? */ + if (pPrt->PLinkMode == SK_LMODE_HALF || + pPrt->PLinkMode == SK_LMODE_FULL) { + /* Auto-negotiation disabled */ - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); + /* get General Purpose Control */ + GM_IN16(IoC, Port, GM_GP_CTRL, &SWord); - /* release GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); + /* disable auto-update for speed, duplex and flow-control */ + SWord |= GM_GPCR_AU_ALL_DIS; - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); + /* setup General Purpose Control Register */ + GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); - /* Dummy read the Interrupt source register */ - SK_IN16(IoC, GMAC_IRQ_SRC, &SWord); + SWord = GM_GPCR_AU_ALL_DIS; + } + else { + SWord = 0; + } + + /* speed settings */ + switch (pPrt->PLinkSpeed) { + case SK_LSPEED_AUTO: + case SK_LSPEED_1000MBPS: + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { + + SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; + } + break; + case SK_LSPEED_100MBPS: + SWord |= GM_GPCR_SPEED_100; + break; + case SK_LSPEED_10MBPS: + break; + } + + /* duplex settings */ + if (pPrt->PLinkMode != SK_LMODE_HALF) { + /* set full duplex */ + SWord |= GM_GPCR_DUP_FULL; + } + + /* flow-control settings */ + switch (pPrt->PFlowCtrlMode) { + case SK_FLOW_MODE_NONE: + /* disable Tx & Rx flow-control */ + SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; + break; + case SK_FLOW_MODE_LOC_SEND: + /* disable Rx flow-control */ + SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; + break; + case SK_FLOW_MODE_SYMMETRIC: + case SK_FLOW_MODE_SYM_OR_REM: + /* enable Tx & Rx flow-control */ + break; + } + + /* setup General Purpose Control Register */ + GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); + + /* dummy read the Interrupt Source Register */ + SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &SWord); #ifndef VCPU - /* read Id from PHY */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1); - SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); -#endif /* VCPU */ +#endif /* !VCPU */ } (void)SkGmResetCounter(pAC, IoC, Port); - SWord = 0; - - /* speed settings */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - case SK_LSPEED_1000MBPS: - SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; - break; - case SK_LSPEED_100MBPS: - SWord |= GM_GPCR_SPEED_100; - break; - case SK_LSPEED_10MBPS: - break; - } - - /* duplex settings */ - if (pPrt->PLinkMode != SK_LMODE_HALF) { - /* set full duplex */ - SWord |= GM_GPCR_DUP_FULL; - } - - /* flow control settings */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - /* disable auto-negotiation for flow-control */ - SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS; - break; - case SK_FLOW_MODE_LOC_SEND: - SWord |= GM_GPCR_FC_RX_DIS; - break; - case SK_FLOW_MODE_SYMMETRIC: - /* TBD */ - case SK_FLOW_MODE_SYM_OR_REM: - /* enable auto-negotiation for flow-control and */ - /* enable Rx and Tx of pause frames */ - break; - } - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - /* disable auto-update for speed, duplex and flow-control */ - SWord |= GM_GPCR_AU_ALL_DIS; - } - - /* setup General Purpose Control Register */ - GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); - /* setup Transmit Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR); + GM_OUT16(IoC, Port, GM_TX_CTRL, (SK_U16)TX_COL_THR(pPrt->PMacColThres)); /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | - GM_RXCR_CRC_DIS); + SWord = GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | GM_RXCR_CRC_DIS; + + GM_OUT16(IoC, Port, GM_RX_CTRL, SWord); /* setup Transmit Flow Control Register */ GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff); @@ -1816,18 +1716,23 @@ int Port) /* Port Index (MAC_1 + n) */ GM_IN16(IoC, Port, GM_TX_PARAM, &SWord); #endif /* VCPU */ - SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26); + SWord = (SK_U16)(TX_JAM_LEN_VAL(pPrt->PMacJamLen) | + TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) | + TX_IPG_JAM_DATA(pPrt->PMacJamIpgData) | + TX_BACK_OFF_LIM(pPrt->PMacBackOffLim)); GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); /* configure the Serial Mode Register */ -#ifdef VCPU - GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord); -#endif /* VCPU */ + SWord = (SK_U16)(DATA_BLIND_VAL(pPrt->PMacDataBlind) | + GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData)); - SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH; + if (pPrt->PMacLimit4) { + /* reset of collision counter after 4 consecutive collisions */ + SWord |= GM_SMOD_LIMIT_4; + } - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + if (pPrt->PPortUsage == SK_JUMBO_LINK) { /* enable jumbo mode (Max. Frame Length = 9018) */ SWord |= GM_SMOD_JUMBO_ENA; } @@ -1852,7 +1757,7 @@ int Port) /* Port Index (MAC_1 + n) */ #ifdef WA_DEV_16 /* WA for deviation #16 */ - if (pAC->GIni.GIChipRev == 0) { + if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) { /* swap the address bytes */ SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); @@ -1872,7 +1777,7 @@ int Port) /* Port Index (MAC_1 + n) */ GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); /* reset Multicast filtering Hash registers 1-3 */ - GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0); + GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + i * 4, 0); } /* reset Multicast filtering Hash register 4 */ @@ -1883,19 +1788,11 @@ int Port) /* Port Index (MAC_1 + n) */ GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); - /* read General Purpose Status */ - GM_IN16(IoC, Port, GM_GP_STAT, &SWord); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("MAC Stat Reg=0x%04X\n", SWord)); - -#ifdef SK_DIAG - c_print("MAC Stat Reg=0x%04X\n", SWord); -#endif /* SK_DIAG */ - } /* SkGmInitMac */ +#endif /* YUKON */ +#ifdef GENESIS /****************************************************************************** * * SkXmInitDupMd() - Initialize the XMACs Duplex Mode @@ -1909,8 +1806,8 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkXmInitDupMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { switch (pAC->GIni.GP[Port].PLinkModeStatus) { @@ -1957,8 +1854,8 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkXmInitPauseMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; @@ -1972,7 +1869,7 @@ int Port) /* Port Index (MAC_1 + n) */ if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE || pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { - /* Disable Pause Frame Reception */ + /* disable Pause Frame Reception */ Word |= XM_MMU_IGN_PF; } else { @@ -1980,7 +1877,7 @@ int Port) /* Port Index (MAC_1 + n) */ * enabling pause frame reception is required for 1000BT * because the XMAC is not reset if the link is going down */ - /* Enable Pause Frame Reception */ + /* enable Pause Frame Reception */ Word &= ~XM_MMU_IGN_PF; } @@ -2006,10 +1903,10 @@ int Port) /* Port Index (MAC_1 + n) */ /* remember this value is defined in big endian (!) */ XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff); - /* Set Pause Mode in Mode Register */ + /* set Pause Mode in Mode Register */ DWord |= XM_PAUSE_MODE; - /* Set Pause Mode in MAC Rx FIFO */ + /* set Pause Mode in MAC Rx FIFO */ SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE); } else { @@ -2017,10 +1914,10 @@ int Port) /* Port Index (MAC_1 + n) */ * disable pause frame generation is required for 1000BT * because the XMAC is not reset if the link is going down */ - /* Disable Pause Mode in Mode Register */ + /* disable Pause Mode in Mode Register */ DWord &= ~XM_PAUSE_MODE; - /* Disable Pause Mode in MAC Rx FIFO */ + /* disable Pause Mode in MAC Rx FIFO */ SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE); } @@ -2030,9 +1927,9 @@ int Port) /* Port Index (MAC_1 + n) */ /****************************************************************************** * - * SkXmInitPhyXmac() - Initialize the XMAC Phy registers + * SkXmInitPhyXmac() - Initialize the XMAC PHY registers * - * Description: initializes all the XMACs Phy registers + * Description: initializes all the XMACs PHY registers * * Note: * @@ -2040,10 +1937,10 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ static void SkXmInitPhyXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +SK_BOOL DoLoop) /* Should a PHY LoopBack be set-up? */ { SK_GEPORT *pPrt; SK_U16 Ctrl; @@ -2055,7 +1952,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyXmac: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ + /* set DuplexMode in Config register */ if (pPrt->PLinkMode == SK_LMODE_FULL) { Ctrl |= PHY_CT_DUP_MD; } @@ -2068,9 +1965,9 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ else { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyXmac: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ + /* set Auto-negotiation advertisement */ - /* Set Full/half duplex capabilities */ + /* set Full/half duplex capabilities */ switch (pPrt->PLinkMode) { case SK_LMODE_AUTOHALF: Ctrl |= PHY_X_AN_HD; @@ -2086,6 +1983,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ SKERR_HWI_E015MSG); } + /* set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: Ctrl |= PHY_X_P_NO_PAUSE; @@ -2112,20 +2010,20 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ } if (DoLoop) { - /* Set the Phy Loopback bit, too */ + /* set the PHY Loopback bit, too */ Ctrl |= PHY_CT_LOOP; } - /* Write to the Phy control register */ + /* Write to the PHY control register */ SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl); } /* SkXmInitPhyXmac */ /****************************************************************************** * - * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers + * SkXmInitPhyBcom() - Initialize the Broadcom PHY registers * - * Description: initializes all the Broadcom Phy registers + * Description: initializes all the Broadcom PHY registers * * Note: * @@ -2133,10 +2031,10 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ * nothing */ static void SkXmInitPhyBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +SK_BOOL DoLoop) /* Should a PHY LoopBack be set-up? */ { SK_GEPORT *pPrt; SK_U16 Ctrl1; @@ -2165,8 +2063,10 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyBcom: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); + /* set DuplexMode in Config register */ + if (pPrt->PLinkMode == SK_LMODE_FULL) { + Ctrl1 |= PHY_CT_DUP_MD; + } /* Determine Master/Slave manually if not already done */ if (pPrt->PMSMode == SK_MS_MODE_AUTO) { @@ -2181,7 +2081,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ else { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyBcom: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ + /* set Auto-negotiation advertisement */ /* * Workaround BCOM Errata #1 for the C5 type. @@ -2190,7 +2090,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ */ Ctrl2 |= PHY_B_1000C_RD; - /* Set Full/half duplex capabilities */ + /* set Full/half duplex capabilities */ switch (pPrt->PLinkMode) { case SK_LMODE_AUTOHALF: Ctrl2 |= PHY_B_1000C_AHD; @@ -2206,6 +2106,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ SKERR_HWI_E015MSG); } + /* set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: Ctrl3 |= PHY_B_P_NO_PAUSE; @@ -2230,24 +2131,24 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ /* Initialize LED register here? */ /* No. Please do it in SkDgXmitLed() (if required) and swap - init order of LEDs and XMAC. (MAl) */ + init order of LEDs and XMAC. (MAl) */ /* Write 1000Base-T Control Register */ SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); + ("Set 1000B-T Ctrl Reg = 0x%04X\n", Ctrl2)); /* Write AutoNeg Advertisement Register */ SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3)); + ("Set Auto-Neg.Adv.Reg = 0x%04X\n", Ctrl3)); if (DoLoop) { - /* Set the Phy Loopback bit, too */ + /* set the PHY Loopback bit, too */ Ctrl1 |= PHY_CT_LOOP; } - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { + if (pPrt->PPortUsage == SK_JUMBO_LINK) { /* configure FIFO to high latency for transmission of ext. packets */ Ctrl4 |= PHY_B_PEC_HIGH_LA; @@ -2260,18 +2161,533 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ /* Configure LED Traffic Mode and Jumbo Frame usage if specified */ SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4); - /* Write to the Phy control register */ + /* Write to the PHY control register */ SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); + ("PHY Control Reg = 0x%04X\n", Ctrl1)); } /* SkXmInitPhyBcom */ +#endif /* GENESIS */ +#ifdef YUKON +#ifdef SK_PHY_LP_MODE +/****************************************************************************** + * + * SkGmEnterLowPowerMode() + * + * Description: + * This function sets the Marvell Alaska PHY to the low power mode + * given by parameter mode. + * The following low power modes are available: + * + * - COMA Mode (Deep Sleep): + * The PHY cannot wake up on its own. + * + * - IEEE 22.2.4.1.5 compatible power down mode + * The PHY cannot wake up on its own. + * + * - energy detect mode + * The PHY can wake up on its own by detecting activity + * on the CAT 5 cable. + * + * - energy detect plus mode + * The PHY can wake up on its own by detecting activity + * on the CAT 5 cable. + * Connected devices can be woken up by sending normal link + * pulses every second. + * + * Note: + * + * Returns: + * 0: ok + * 1: error + */ +int SkGmEnterLowPowerMode( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (e.g. MAC_1) */ +SK_U8 Mode) /* low power mode */ +{ + SK_U8 LastMode; + SK_U8 Byte; + SK_U16 Word; + SK_U16 ClkDiv; + SK_U32 DWord; + SK_U32 PowerDownBit; + int ChipId; + int Ret = 0; + + if (!(CHIP_ID_YUKON_2(pAC) || (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3))) { + + return(1); + } + + /* save current power mode */ + LastMode = pAC->GIni.GP[Port].PPhyPowerState; + pAC->GIni.GP[Port].PPhyPowerState = Mode; + + ChipId = pAC->GIni.GIChipId; + + SK_DBG_MSG(pAC, SK_DBGMOD_POWM, SK_DBGCAT_CTRL, + ("SkGmEnterLowPowerMode: %u\n", Mode)); + + /* release GPHY Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR); + + /* release GMAC reset */ + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR); + + if (ChipId == CHIP_ID_YUKON_EC_U) { + /* select page 2 to access MAC control register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2); + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + /* allow GMII Power Down */ + Word &= ~PHY_M_MAC_GMIF_PUP; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); + } + + switch (Mode) { + /* COMA mode (deep sleep) */ + case PHY_PM_DEEP_SLEEP: + /* setup General Purpose Control Register */ + GM_OUT16(IoC, Port, GM_GP_CTRL, GM_GPCR_FL_PASS | + GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS); + + if (CHIP_ID_YUKON_2(pAC)) { + /* set power down bit */ + PowerDownBit = (Port == MAC_1) ? PCI_Y2_PHY1_POWD : + PCI_Y2_PHY2_POWD; + + if (ChipId != CHIP_ID_YUKON_EC) { + + if (ChipId == CHIP_ID_YUKON_EC_U) { + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + /* enable Power Down */ + Word |= PHY_M_PC_POW_D_ENA; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + } + + /* set IEEE compatible Power Down Mode (dev. #4.99) */ + Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_PDOWN); + } + } + else { + /* apply COMA mode workaround */ + (void)SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 0x001f); + + Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xfff3); + + PowerDownBit = PCI_PHY_COMA; + } + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord); + + /* set PHY to PowerDown/COMA Mode */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord | PowerDownBit); + + /* check if this routine was called from a for() loop */ + if (pAC->GIni.GIMacsFound == 1 || Port == MAC_2) { + + /* ASF system clock stopped */ + SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, (SK_U8)Y2_ASF_CLK_HALT); + + if (ChipId == CHIP_ID_YUKON_EC_U) { + /* set GPHY Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET); + + /* additional power saving measurements */ + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord); + + /* set gating core clock for LTSSM in L1 state */ + DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) | + /* auto clock gated scheme controlled by CLKREQ */ + P_ASPM_A1_MODE_SELECT | + /* enable Gate Root Core Clock */ + P_CLK_GATE_ROOT_COR_ENA); + + if (HW_FEATURE(pAC, HWF_WA_DEV_4200)) { + /* enable Clock Power Management (CLKREQ) */ + SK_IN16(IoC, PCI_C(pAC, PEX_LNK_CTRL), &Word); + Word |= PEX_LC_CLK_PM_ENA; + SK_OUT16(IoC, PCI_C(pAC, PEX_LNK_CTRL), Word); + } + else { + /* force CLKREQ Enable in Our4 (A1b only) */ + DWord |= P_ASPM_FORCE_CLKREQ_ENA; + } + + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord); + + /* set Mask Register for Release/Gate Clock */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), + P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST | + P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE | + P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN); + } + + if (HW_FEATURE(pAC, HWF_RED_CORE_CLK_SUP)) { + /* divide clock by 4 only for Yukon-EC */ + ClkDiv = (ChipId == CHIP_ID_YUKON_EC) ? 1 : 0; + + /* on Yukon-2 clock select value is 31 */ + DWord = (ChipId == CHIP_ID_YUKON_XL) ? + (Y2_CLK_DIV_VAL_2(0) | Y2_CLK_SEL_VAL_2(31)) : + Y2_CLK_DIV_VAL(ClkDiv); + + /* check for Yukon-2 dual port PCI-Express adapter */ + if (!(pAC->GIni.GIMacsFound == 2 && + pAC->GIni.GIPciBus == SK_PEX_BUS)) { + /* enable Core Clock Division */ + DWord |= Y2_CLK_DIV_ENA; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Set Core Clock: 0x%08X\n", DWord)); + + /* reduce Core Clock Frequency */ + SK_OUT32(IoC, B2_Y2_CLK_CTRL, DWord); + } + + if (HW_FEATURE(pAC, HWF_CLK_GATING_ENABLE)) { + /* check for Yukon-2 Rev. A2 */ + if (ChipId == CHIP_ID_YUKON_XL && + pAC->GIni.GIChipRev > CHIP_REV_YU_XL_A1) { + /* enable bits are inverted */ + Byte = 0; + } + else { + Byte = (SK_U8)(Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | + Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | + Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Set Clock Gating: 0x%02X\n", Byte)); + + /* disable MAC/PHY, PCI and Core Clock for both Links */ + SK_OUT8(IoC, B2_Y2_CLK_GATE, Byte); + } + + if (pAC->GIni.GIVauxAvail) { + /* switch power to VAUX */ + SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA | + PC_VAUX_ON | PC_VCC_OFF)); + } +#ifdef DEBUG + SK_IN32(IoC, B0_CTST, &DWord); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Ctrl/Stat & Switch: 0x%08x\n", DWord)); +#endif /* DEBUG */ + + if (pAC->GIni.GILevel != SK_INIT_IO && + pAC->GIni.GIMacsFound == 1 && + pAC->GIni.GIPciBus == SK_PEX_BUS) { + + if (ChipId == CHIP_ID_YUKON_EC_U) { + +#ifdef PCI_E_L1_STATE + SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Word); + /* force to PCIe L1 */ + Word |= (SK_U16)PCI_FORCE_PEX_L1; + SK_OUT16(IoC, PCI_C(pAC, PCI_OUR_REG_1), Word); +#endif /* PCI_E_L1_STATE */ + } + else { + /* switch to D1 state */ + SK_OUT8(IoC, PCI_C(pAC, PCI_PM_CTL_STS), PCI_PM_STATE_D1); + } + } + } + + break; + + /* IEEE 22.2.4.1.5 compatible power down mode */ + case PHY_PM_IEEE_POWER_DOWN: + + Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + + if (!CHIP_ID_YUKON_2(pAC)) { + /* disable MAC 125 MHz clock */ + Word |= PHY_M_PC_DIS_125CLK; + Word &= ~PHY_M_PC_MAC_POW_UP; + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* these register changes must be followed by a software reset */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word | PHY_CT_RESET); + + /* switch IEEE compatible power down mode on */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word | PHY_CT_PDOWN); + + break; + + /* energy detect and energy detect plus mode */ + case PHY_PM_ENERGY_DETECT: + case PHY_PM_ENERGY_DETECT_PLUS: + + Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + + /* disable Polarity Reversal */ + Word |= PHY_M_PC_POL_R_DIS; + + if (!CHIP_ID_YUKON_2(pAC)) { + /* disable MAC 125 MHz clock */ + Word |= PHY_M_PC_DIS_125CLK; + } + + if (ChipId == CHIP_ID_YUKON_FE) { + /* enable Energy Detect (sense & pulse) */ + Word |= PHY_M_PC_ENA_ENE_DT; + } + else { + /* clear energy detect mode bits */ + Word &= ~PHY_M_PC_EN_DET_MSK; + + Word |= (Mode == PHY_PM_ENERGY_DETECT) ? PHY_M_PC_EN_DET : + PHY_M_PC_EN_DET_PLUS; + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* these register changes must be followed by a software reset */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word |= PHY_CT_RESET; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + + if (ChipId == CHIP_ID_YUKON_EC_U) { + /* additional power saving measurements */ + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord); + + /* set gating core clock for LTSSM in L1 state */ + DWord |= (P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) | + /* Enable Gate Root Core Clock */ + P_CLK_GATE_ROOT_COR_ENA); + + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord); + + /* set Mask Register for Release/Gate Clock */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), + P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST | + P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE | + P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN); + +#ifdef PCI_E_L1_STATE + SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_1), &Word); + /* enable PCIe L1 on GPHY link down */ + Word |= (SK_U16)PCI_ENA_GPHY_LNK; + SK_OUT16(IoC, PCI_C(pAC, PCI_OUR_REG_1), Word); +#endif /* PCI_E_L1_STATE */ + } + + break; + + /* don't change current power mode */ + default: + pAC->GIni.GP[Port].PPhyPowerState = LastMode; + Ret = 1; + } + + return(Ret); + +} /* SkGmEnterLowPowerMode */ + /****************************************************************************** * - * SkGmInitPhyMarv() - Initialize the Marvell Phy registers + * SkGmLeaveLowPowerMode() * - * Description: initializes all the Marvell Phy registers + * Description: + * Leave the current low power mode and switch to normal mode + * + * Note: + * + * Returns: + * 0: ok + * 1: error + */ +int SkGmLeaveLowPowerMode( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port) /* Port Index (e.g. MAC_1) */ +{ + SK_U32 DWord; + SK_U32 PowerDownBit; + SK_U16 Word; + SK_U8 LastMode; + int ChipId; + int Ret = 0; + + if (!(CHIP_ID_YUKON_2(pAC) || (pAC->GIni.GIYukonLite && + pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3))) { + + return(1); + } + + /* save current power mode */ + LastMode = pAC->GIni.GP[Port].PPhyPowerState; + pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE; + + ChipId = pAC->GIni.GIChipId; + + SK_DBG_MSG(pAC, SK_DBGMOD_POWM, SK_DBGCAT_CTRL, + ("SkGmLeaveLowPowerMode: %u\n", LastMode)); + + switch (LastMode) { + /* COMA mode (deep sleep) */ + case PHY_PM_DEEP_SLEEP: + + if (ChipId == CHIP_ID_YUKON_EC_U) { +#ifdef PCI_E_L1_STATE + /* set to default value (leave PCIe L1) */ + SkPciWriteCfgWord(pAC, PCI_OUR_REG_1, 0); +#endif /* PCI_E_L1_STATE */ + + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_4), &DWord); + + DWord &= P_ASPM_CONTROL_MSK; + /* set all bits to 0 except bits 15..12 */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_4), DWord); + + /* set to default value */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_5), 0); + } + else { + SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &Word); + + /* reset all DState bits */ + Word &= ~PCI_PM_STATE_MSK; + + /* switch to D0 state */ + SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, Word); + } + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); + + if (CHIP_ID_YUKON_2(pAC)) { + /* disable Core Clock Division */ + SK_OUT32(IoC, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); + + /* set power down bit */ + PowerDownBit = (Port == MAC_1) ? PCI_Y2_PHY1_POWD : + PCI_Y2_PHY2_POWD; + } + else { + PowerDownBit = PCI_PHY_COMA; + } + + SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord); + + /* Release PHY from PowerDown/COMA Mode */ + SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord & ~PowerDownBit); + + SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); + + if (CHIP_ID_YUKON_2(pAC)) { + + if (ChipId == CHIP_ID_YUKON_FE) { + /* release IEEE compatible Power Down Mode */ + Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_ANE); + } + else if (ChipId == CHIP_ID_YUKON_EC_U) { + /* release GPHY Control reset */ + SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR); + } + } + else { + SK_IN32(IoC, B2_GP_IO, &DWord); + + /* set to output */ + DWord |= (GP_DIR_9 | GP_IO_9); + + /* set PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + + DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ + + /* clear PHY reset */ + SK_OUT32(IoC, B2_GP_IO, DWord); + } + + break; + + /* IEEE 22.2.4.1.5 compatible power down mode */ + case PHY_PM_IEEE_POWER_DOWN: + + if (ChipId != CHIP_ID_YUKON_XL) { + + Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + Word &= ~PHY_M_PC_DIS_125CLK; /* enable MAC 125 MHz clock */ + Word |= PHY_M_PC_MAC_POW_UP; /* set MAC power up */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* these register changes must be followed by a software reset */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word |= PHY_CT_RESET; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + } + + /* switch IEEE compatible power down mode off */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word &= ~PHY_CT_PDOWN; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + + break; + + /* energy detect and energy detect plus mode */ + case PHY_PM_ENERGY_DETECT: + case PHY_PM_ENERGY_DETECT_PLUS: + + if (ChipId != CHIP_ID_YUKON_XL) { + + Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + + if (ChipId == CHIP_ID_YUKON_FE) { + /* disable Energy Detect */ + Word &= ~PHY_M_PC_ENA_ENE_DT; + } + else { + /* disable energy detect mode & enable MAC 125 MHz clock */ + Word &= ~(PHY_M_PC_EN_DET_MSK | PHY_M_PC_DIS_125CLK); + } + + /* enable Polarity Reversal */ + Word &= ~PHY_M_PC_POL_R_DIS; + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* these register changes must be followed by a software reset */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word); + Word |= PHY_CT_RESET; + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word); + } + break; + + /* don't change current power mode */ + default: + pAC->GIni.GP[Port].PPhyPowerState = LastMode; + Ret = 1; + } + + return(Ret); + +} /* SkGmLeaveLowPowerMode */ +#endif /* SK_PHY_LP_MODE */ + +/****************************************************************************** + * + * SkGmInitPhyMarv() - Initialize the Marvell PHY registers + * + * Description: initializes all the Marvell PHY registers * * Note: * @@ -2279,64 +2695,216 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ * nothing */ static void SkGmInitPhyMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +SK_BOOL DoLoop) /* Should a PHY LoopBack be set-up? */ { SK_GEPORT *pPrt; + SK_BOOL AutoNeg; SK_U16 PhyCtrl; SK_U16 C1000BaseT; SK_U16 AutoNegAdv; + SK_U8 PauseMode; + int ChipId; + int Mode; +#ifndef VCPU + SK_U16 Word; + SK_U16 PageReg; +#ifndef SK_SLIM + SK_U16 LoopSpeed; +#endif /* !SK_SLIM */ SK_U16 ExtPhyCtrl; + SK_U16 BlinkCtrl; + SK_U16 LedCtrl; + SK_U16 LedConf; + SK_U16 LedOver; +#ifndef SK_DIAG + SK_EVPARA Para; +#endif /* !SK_DIAG */ +#if defined(SK_DIAG) || defined(DEBUG) SK_U16 PhyStat; SK_U16 PhyStat1; SK_U16 PhySpecStat; - SK_U16 LedCtrl; - SK_BOOL AutoNeg; +#endif /* SK_DIAG || DEBUG */ +#endif /* !VCPU */ -#ifdef VCPU - VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n", - Port, DoLoop); -#else /* VCPU */ + /* set Pause On */ + PauseMode = (SK_U8)GMC_PAUSE_ON; pPrt = &pAC->GIni.GP[Port]; + ChipId = pAC->GIni.GIChipId; + /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; + AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF && + pPrt->PLinkMode != SK_LMODE_FULL; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("InitPhyMarv: Port %d, Auto-neg. %s, LMode %d, LSpeed %d, FlowC %d\n", + Port, AutoNeg ? "ON" : "OFF", + pPrt->PLinkMode, pPrt->PLinkSpeed, pPrt->PFlowCtrlMode)); + +#ifndef VCPU + /* read Id from PHY */ + if (SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1) != 0) { + +#ifndef SK_DIAG + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); +#endif /* !SK_DIAG */ + + return; } - if (!DoLoop) { - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { - ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | - PHY_M_EC_MAC_S_MSK); +#ifndef SK_SLIM + if (DoLoop) { + /* special setup for PHY 88E1112 */ + if (ChipId == CHIP_ID_YUKON_XL) { - ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) | - PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); + LoopSpeed = pPrt->PLinkSpeed; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl)); + if (LoopSpeed == SK_LSPEED_AUTO) { + /* force 1000 Mbps */ + LoopSpeed = SK_LSPEED_1000MBPS; + } + LoopSpeed += 2; - /* Read PHY Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); + /* save page register */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &PageReg); - /* Assert software reset */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, - (SK_U16)(PhyCtrl | PHY_CT_RESET)); + /* select page 2 to access MAC control register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2); + + /* set MAC interface speed */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, LoopSpeed << 4); + + /* restore page register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, PageReg); + + /* disable link pulses */ + Word = PHY_M_PC_DIS_LINK_P; + } + else { + /* set 'MAC Power up'-bit, set Manual MDI configuration */ + Word = PHY_M_PC_MAC_POW_UP; + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + } + else +#endif /* !SK_SLIM */ + if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO && + !(ChipId == CHIP_ID_YUKON_XL || ChipId == CHIP_ID_YUKON_EC_U)) { + /* Read Ext. PHY Specific Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); + + ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | + PHY_M_EC_MAC_S_MSK); + + ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); + + /* on PHY 88E1040 Rev.D0 (and newer) downshift control changed */ + if (pAC->GIni.GIYukonLite || ChipId == CHIP_ID_YUKON_EC) { + /* set downshift counter to 3x and enable downshift */ + ExtPhyCtrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA; + } + else { + /* set master & slave downshift counter to 1x */ + ExtPhyCtrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Set Ext. PHY Ctrl = 0x%04X\n", ExtPhyCtrl)); + } } -#endif /* VCPU */ + + if (CHIP_ID_YUKON_2(pAC)) { + /* Read PHY Specific Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhyCtrl); + + if (!DoLoop && pAC->GIni.GICopperType) { + + if (ChipId == CHIP_ID_YUKON_FE) { + /* enable Automatic Crossover (!!! Bits 5..4) */ + PhyCtrl |= (SK_U16)(PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1); + } + else { +#ifndef SK_DIAG + /* disable Energy Detect Mode */ + PhyCtrl &= ~PHY_M_PC_EN_DET_MSK; +#endif /* !SK_DIAG */ + + /* enable Automatic Crossover */ + PhyCtrl |= (SK_U16)PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); + + /* downshift on PHY 88E1112 and 88E1149 is changed */ + if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO && + (ChipId == CHIP_ID_YUKON_XL || + ChipId == CHIP_ID_YUKON_EC_U)) { + /* set downshift counter to 3x and enable downshift */ + PhyCtrl &= ~PHY_M_PC_DSC_MSK; + PhyCtrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; + } + } + } + /* workaround for deviation #4.88 (CRC errors) */ + else { + /* disable Automatic Crossover */ + PhyCtrl &= ~PHY_M_PC_MDIX_MSK; + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhyCtrl); + } + + /* special setup for PHY 88E1112 Fiber */ + if (ChipId == CHIP_ID_YUKON_XL && !pAC->GIni.GICopperType) { + /* select 1000BASE-X only mode in MAC Specific Ctrl Reg. */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2); + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + + Word &= ~PHY_M_MAC_MD_MSK; + Word |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX); + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + + /* select page 1 to access Fiber registers */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 1); + + if (pAC->GIni.GIPmdTyp == 'P') { + /* for SFP-module set SIGDET polarity to low */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word); + + Word |= PHY_M_FIB_SIGD_POL; + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word); + } + } + + /* Read PHY Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); + +#ifndef SK_SLIM + if (!AutoNeg) { + /* disable Auto-negotiation */ + PhyCtrl &= ~PHY_CT_ANE; + } +#endif /* !SK_SLIM */ + + PhyCtrl |= PHY_CT_RESET; + /* assert software reset */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); +#endif /* !VCPU */ PhyCtrl = 0 /* PHY_CT_COL_TST */; C1000BaseT = 0; AutoNegAdv = PHY_SEL_TYPE; +#ifndef SK_SLIM /* manually Master/Slave ? */ if (pPrt->PMSMode != SK_MS_MODE_AUTO) { /* enable Manual Master/Slave */ @@ -2346,27 +2914,28 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */ } } +#endif /* !SK_SLIM */ /* Auto-negotiation ? */ if (!AutoNeg) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyMarv: no auto-negotiation Port %d\n", Port)); +#ifndef SK_SLIM if (pPrt->PLinkMode == SK_LMODE_FULL) { - /* Set Full Duplex Mode */ + /* set Full Duplex Mode */ PhyCtrl |= PHY_CT_DUP_MD; } - /* Set Master/Slave manually if not already done */ + /* set Master/Slave manually if not already done */ if (pPrt->PMSMode == SK_MS_MODE_AUTO) { C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */ } - /* Set Speed */ + /* set Speed */ switch (pPrt->PLinkSpeed) { case SK_LSPEED_AUTO: case SK_LSPEED_1000MBPS: - PhyCtrl |= PHY_CT_SP1000; + PhyCtrl |= (((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) ? + PHY_CT_SP1000 : PHY_CT_SP100); break; case SK_LSPEED_100MBPS: PhyCtrl |= PHY_CT_SP100; @@ -2378,44 +2947,67 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ SKERR_HWI_E019MSG); } + if ((pPrt->PFlowCtrlMode == SK_FLOW_STAT_NONE) || + /* disable Pause also for 10/100 Mbps in half duplex mode */ + ((ChipId != CHIP_ID_YUKON_EC_U) && + (pPrt->PLinkMode == SK_LMODE_HALF) && + ((pPrt->PLinkSpeed == SK_LSPEED_STAT_100MBPS) || + (pPrt->PLinkSpeed == SK_LSPEED_STAT_10MBPS)))) { + + /* set Pause Off */ + PauseMode = (SK_U8)GMC_PAUSE_OFF; + } + + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), PauseMode); + if (!DoLoop) { + /* assert software reset */ PhyCtrl |= PHY_CT_RESET; } - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ +#endif /* !SK_SLIM */ } else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyMarv: with auto-negotiation Port %d\n", Port)); - - PhyCtrl |= PHY_CT_ANE; + /* set Auto-negotiation advertisement */ if (pAC->GIni.GICopperType) { - /* Set Speed capabilities */ + /* set Speed capabilities */ switch (pPrt->PLinkSpeed) { case SK_LSPEED_AUTO: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { + C1000BaseT |= PHY_M_1000C_AFD; +#ifdef xSK_DIAG + C1000BaseT |= PHY_M_1000C_AHD; +#endif /* SK_DIAG */ + } AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | PHY_M_AN_10_FD | PHY_M_AN_10_HD; break; case SK_LSPEED_1000MBPS: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { + C1000BaseT |= PHY_M_1000C_AFD; +#ifdef xSK_DIAG + C1000BaseT |= PHY_M_1000C_AHD; +#endif /* SK_DIAG */ + } break; case SK_LSPEED_100MBPS: - AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | - PHY_M_AN_10_FD | PHY_M_AN_10_HD; + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_100MBPS) != 0) { + AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | + /* advertise 10Base-T also */ + PHY_M_AN_10_FD | PHY_M_AN_10_HD; + } break; case SK_LSPEED_10MBPS: - AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD; + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_10MBPS) != 0) { + AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD; + } break; default: SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, SKERR_HWI_E019MSG); } - /* Set Full/half duplex capabilities */ + /* set Full/half duplex capabilities */ switch (pPrt->PLinkMode) { case SK_LMODE_AUTOHALF: C1000BaseT &= ~PHY_M_1000C_AFD; @@ -2432,7 +3024,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ SKERR_HWI_E015MSG); } - /* Set Auto-negotiation advertisement */ + /* set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: AutoNegAdv |= PHY_B_P_NO_PAUSE; @@ -2451,9 +3043,9 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ SKERR_HWI_E016MSG); } } - else { /* special defines for FIBER (88E1011S only) */ + else { /* special defines for FIBER (88E1040S only) */ - /* Set Full/half duplex capabilities */ + /* set Full/half duplex capabilities */ switch (pPrt->PLinkMode) { case SK_LMODE_AUTOHALF: AutoNegAdv |= PHY_M_AN_1000X_AHD; @@ -2469,7 +3061,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ SKERR_HWI_E015MSG); } - /* Set Auto-negotiation advertisement */ + /* set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: AutoNegAdv |= PHY_M_P_NO_PAUSE_X; @@ -2491,7 +3083,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ if (!DoLoop) { /* Restart Auto-negotiation */ - PhyCtrl |= PHY_CT_RE_CFG; + PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG; } } @@ -2501,126 +3093,246 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ */ /* Program PHY register 30 as 16'h0708 for simulation speed up */ - SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708); + SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */); VCpuWait(2000); -#else /* VCPU */ +#else /* !VCPU */ - /* Write 1000Base-T Control Register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl=0x%04X\n", C1000BaseT)); + if (ChipId != CHIP_ID_YUKON_FE) { + /* Write 1000Base-T Control Register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Set 1000B-T Ctrl = 0x%04X\n", C1000BaseT)); + } /* Write AutoNeg Advertisement Register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv)); -#endif /* VCPU */ + ("Set Auto-Neg.Adv. = 0x%04X\n", AutoNegAdv)); +#endif /* !VCPU */ +#ifndef SK_SLIM if (DoLoop) { - /* Set the PHY Loopback bit */ + /* set the PHY Loopback bit */ PhyCtrl |= PHY_CT_LOOP; - - /* Program PHY register 16 as 16'h0400 to force link good */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD); - -#if 0 - if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) { - /* Write Ext. PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, - (SK_U16)((pPrt->PLinkSpeed + 2) << 4)); - } - } - else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) { - /* Write PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK); - } -#endif /* 0 */ } +#endif /* !SK_SLIM */ /* Write to the PHY Control register */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Set PHY Ctrl Reg. = 0x%04X\n", PhyCtrl)); #ifdef VCPU VCpuWait(2000); -#else +#else /* !VCPU */ - LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS); + LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS); -#ifdef ACT_LED_BLINK - LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL; -#endif /* ACT_LED_BLINK */ + LedOver = 0; -#ifdef DUP_LED_NORMAL - LedCtrl |= PHY_M_LEDC_DP_CTRL; -#endif /* DUP_LED_NORMAL */ + BlinkCtrl = pAC->GIni.GILedBlinkCtrl; - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); + if ((BlinkCtrl & SK_ACT_LED_BLINK) != 0) { -#endif /* VCPU */ + if (ChipId == CHIP_ID_YUKON_FE) { + /* on 88E3082 these bits are at 11..9 (shifted left) */ + LedCtrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1; + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_FE_LED_PAR, &Word); + + /* delete ACT LED control bits */ + Word &= ~PHY_M_FELP_LED1_MSK; + /* change ACT LED control to blink mode */ + Word |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL); + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_LED_PAR, Word); + } + else if (ChipId == CHIP_ID_YUKON_XL || ChipId == CHIP_ID_YUKON_EC_U) { + /* save page register */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &PageReg); + + /* select page 3 to access LED control register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 3); + + LedConf = PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ + PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ + PHY_M_LEDC_STA0_CTRL(7); /* 1000 Mbps */ + + Mode = 7; /* 10 Mbps: On */ + + if (ChipId == CHIP_ID_YUKON_XL) { + /* set Polarity Control register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_STAT, (SK_U16) + (PHY_M_POLC_LS1_P_MIX(4) | PHY_M_POLC_IS0_P_MIX(4) | + PHY_M_POLC_LOS_CTRL(2) | PHY_M_POLC_INIT_CTRL(2) | + PHY_M_POLC_STA1_CTRL(2) | PHY_M_POLC_STA0_CTRL(2))); + } + else if (ChipId == CHIP_ID_YUKON_EC_U) { + /* check for LINK_LED mux */ + if ((BlinkCtrl & SK_LED_LINK_MUX_P60) != 0) { + + SK_IN16(pAC, GPHY_CTRL, &Word); + + Word |= GPC_LED_CONF_VAL(4); + + /* set GPHY LED Config */ + SK_OUT16(pAC, GPHY_CTRL, Word); + } + else { + Mode = 8; /* Forced Off */ + } + + /* set Blink Rate in LED Timer Control Register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, + LedCtrl | (SK_U16)PHY_M_LED_BLINK_RT(BLINK_84MS)); + } + + LedConf |= PHY_M_LEDC_INIT_CTRL(Mode); + + /* set LED Function Control register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, LedConf); + +#if (defined(SK_DIAG) || (defined(DEBUG) && !defined(SK_SLIM))) + /* select page 6 to access Packet Generation register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 6); + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhyCtrl); + + PhyCtrl |= BIT_4S; /* enable CRC checker */ + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhyCtrl); +#endif /* SK_DIAG || (DEBUG && !SK_SLIM) */ + + /* restore page register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, PageReg); + } + else { + /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ + LedCtrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; + + /* on PHY 88E1111 there is a change for LED control */ + if (ChipId == CHIP_ID_YUKON_EC && + (BlinkCtrl & SK_DUAL_LED_ACT_LNK) != 0) { + /* Yukon-EC needs setting of 2 bits: 0,6=11) */ + LedCtrl |= PHY_M_LEDC_TX_C_LSB; + } + /* turn off the Rx LED (LED_RX) */ + LedOver |= PHY_M_LED_MO_RX(MO_LED_OFF); + } + } + + if ((BlinkCtrl & SK_DUP_LED_NORMAL) != 0) { + /* disable blink mode (LED_DUPLEX) on collisions */ + LedCtrl |= PHY_M_LEDC_DP_CTRL; + } + + if (ChipId == CHIP_ID_YUKON_EC_U) { + if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A1) { + /* apply fixes in PHY AFE */ + SkGmPhyWrite(pAC, IoC, Port, 22, 255); + /* increase differential signal amplitude in 10BASE-T */ + SkGmPhyWrite(pAC, IoC, Port, 24, 0xaa99); + SkGmPhyWrite(pAC, IoC, Port, 23, 0x2011); + + /* fix for IEEE A/B Symmetry failure in 1000BASE-T */ + SkGmPhyWrite(pAC, IoC, Port, 24, 0xa204); + SkGmPhyWrite(pAC, IoC, Port, 23, 0x2002); + + /* set page register to 0 */ + SkGmPhyWrite(pAC, IoC, Port, 22, 0); + } + } + else { + /* no effect on Yukon-XL */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); + +#ifndef SK_SLIM + if ((BlinkCtrl & SK_LED_LINK100_ON) != 0) { + /* only in forced 100 Mbps mode */ + if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) { + /* turn on 100 Mbps LED (LED_LINK100) */ + LedOver |= PHY_M_LED_MO_100(MO_LED_ON); + } + } +#endif /* !SK_SLIM */ + + if (LedOver != 0) { + /* set Manual LED Override */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER, LedOver); + } + } #ifdef SK_DIAG - c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl); - c_print("Set 1000 B-T=0x%04X\n", C1000BaseT); - c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv); - c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl); + c_print("Set PHY Ctrl = 0x%04X\n", PhyCtrl); + c_print("Set 1000 B-T = 0x%04X\n", C1000BaseT); + c_print("Set Auto-Neg = 0x%04X\n", AutoNegAdv); + c_print("Set Ext Ctrl = 0x%04X\n", ExtPhyCtrl); #endif /* SK_DIAG */ -#ifndef xDEBUG +#if (defined(SK_DIAG) || (defined(DEBUG) && !defined(SK_SLIM))) /* Read PHY Control */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); - - /* Read 1000Base-T Control Register */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl =0x%04X\n", C1000BaseT)); + ("PHY Ctrl Reg. = 0x%04X\n", PhyCtrl)); /* Read AutoNeg Advertisement Register */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv)); + ("Auto-Neg.Adv. = 0x%04X\n", AutoNegAdv)); - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl)); + if (ChipId != CHIP_ID_YUKON_FE) { + /* Read 1000Base-T Control Register */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("1000B-T Ctrl = 0x%04X\n", C1000BaseT)); + + /* Read Ext. PHY Specific Control */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Ext. PHY Ctrl = 0x%04X\n", ExtPhyCtrl)); + } /* Read PHY Status */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat)); + ("PHY Stat Reg. = 0x%04X\n", PhyStat)); + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat1)); + ("PHY Stat Reg. = 0x%04X\n", PhyStat1)); /* Read PHY Specific Status */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Spec Stat=0x%04X\n", PhySpecStat)); -#endif /* DEBUG */ + ("PHY Spec Stat = 0x%04X\n", PhySpecStat)); +#endif /* SK_DIAG || (DEBUG && !SK_SLIM) */ #ifdef SK_DIAG - c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl); - c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT); - c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv); - c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl); - c_print("PHY Stat Reg=0x%04X\n", PhyStat); - c_print("PHY Stat Reg=0x%04X\n", PhyStat1); - c_print("PHY Spec Reg=0x%04X\n", PhySpecStat); + c_print("PHY Ctrl Reg = 0x%04X\n", PhyCtrl); + c_print("PHY 1000 Reg = 0x%04X\n", C1000BaseT); + c_print("PHY AnAd Reg = 0x%04X\n", AutoNegAdv); + c_print("Ext Ctrl Reg = 0x%04X\n", ExtPhyCtrl); + c_print("PHY Stat Reg = 0x%04X\n", PhyStat); + c_print("PHY Stat Reg = 0x%04X\n", PhyStat1); + c_print("PHY Spec Reg = 0x%04X\n", PhySpecStat); #endif /* SK_DIAG */ + /* enable PHY interrupts */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, (SK_U16)PHY_M_DEF_MSK); +#endif /* !VCPU */ + } /* SkGmInitPhyMarv */ +#endif /* YUKON */ #ifdef OTHER_PHY /****************************************************************************** * - * SkXmInitPhyLone() - Initialize the Level One Phy registers + * SkXmInitPhyLone() - Initialize the Level One PHY registers * - * Description: initializes all the Level One Phy registers + * Description: initializes all the Level One PHY registers * * Note: * @@ -2628,10 +3340,10 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ * nothing */ static void SkXmInitPhyLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +SK_BOOL DoLoop) /* Should a PHY LoopBack be set-up? */ { SK_GEPORT *pPrt; SK_U16 Ctrl1; @@ -2655,19 +3367,20 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ /* Auto-negotiation ? */ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { /* - * level one spec say: "1000Mbps: manual mode not allowed" + * level one spec say: "1000 Mbps: manual mode not allowed" * but lets see what happens... */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyLone: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0); + /* set DuplexMode in Config register */ + if (pPrt->PLinkMode == SK_LMODE_FULL) { + Ctrl1 |= PHY_CT_DUP_MD; + } /* Determine Master/Slave manually if not already done */ if (pPrt->PMSMode == SK_MS_MODE_AUTO) { Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */ } - /* * Do NOT enable Auto-negotiation here. This would hold * the link down because no IDLES are transmitted @@ -2676,9 +3389,9 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ else { SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("InitPhyLone: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ + /* set Auto-negotiation advertisement */ - /* Set Full/half duplex capabilities */ + /* set Full/half duplex capabilities */ switch (pPrt->PLinkMode) { case SK_LMODE_AUTOHALF: Ctrl2 |= PHY_L_1000C_AHD; @@ -2694,6 +3407,7 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ SKERR_HWI_E015MSG); } + /* set Flow-control capabilities */ switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: Ctrl3 |= PHY_L_P_NO_PAUSE; @@ -2714,41 +3428,35 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ /* Restart Auto-negotiation */ Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG; - } - /* Initialize LED register here ? */ - /* No. Please do it in SkDgXmitLed() (if required) and swap - init order of LEDs and XMAC. (MAl) */ - /* Write 1000Base-T Control Register */ SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); + ("1000B-T Ctrl Reg = 0x%04X\n", Ctrl2)); /* Write AutoNeg Advertisement Register */ SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3)); - + ("Auto-Neg.Adv.Reg = 0x%04X\n", Ctrl3)); if (DoLoop) { - /* Set the Phy Loopback bit, too */ + /* set the PHY Loopback bit, too */ Ctrl1 |= PHY_CT_LOOP; } - /* Write to the Phy control register */ + /* Write to the PHY control register */ SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); + ("PHY Control Reg = 0x%04X\n", Ctrl1)); } /* SkXmInitPhyLone */ /****************************************************************************** * - * SkXmInitPhyNat() - Initialize the National Phy registers + * SkXmInitPhyNat() - Initialize the National PHY registers * - * Description: initializes all the National Phy registers + * Description: initializes all the National PHY registers * * Note: * @@ -2756,10 +3464,10 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ * nothing */ static void SkXmInitPhyNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +SK_BOOL DoLoop) /* Should a PHY LoopBack be set-up? */ { /* todo: National */ } /* SkXmInitPhyNat */ @@ -2778,98 +3486,48 @@ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ * nothing */ void SkMacInitPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ +SK_BOOL DoLoop) /* Should a PHY LoopBack be set-up? */ { SK_GEPORT *pPrt; pPrt = &pAC->GIni.GP[Port]; - switch (pPrt->PhyType) { - case SK_PHY_XMAC: - SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_BCOM: - SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: - SkGmInitPhyMarv(pAC, IoC, Port, DoLoop); - break; +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + + switch (pPrt->PhyType) { + case SK_PHY_XMAC: + SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); + break; + case SK_PHY_BCOM: + SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); + break; #ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmInitPhyLone(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_NAT: - SkXmInitPhyNat(pAC, IoC, Port, DoLoop); - break; + case SK_PHY_LONE: + SkXmInitPhyLone(pAC, IoC, Port, DoLoop); + break; + case SK_PHY_NAT: + SkXmInitPhyNat(pAC, IoC, Port, DoLoop); + break; #endif /* OTHER_PHY */ + } } +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + + SkGmInitPhyMarv(pAC, IoC, Port, DoLoop); + } +#endif /* YUKON */ + } /* SkMacInitPhy */ -#ifndef SK_DIAG -/****************************************************************************** - * - * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg - * - * This function analyses the Interrupt status word. If any of the - * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkXmAutoNegLipaXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus) /* Interrupt Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n", - Port, IStatus)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkXmAutoNegLipaXmac */ - - -/****************************************************************************** - * - * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg - * - * This function analyses the PHY status word. - * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkMacAutoNegLipaPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 PhyStat) /* PHY Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (PhyStat & PHY_ST_AN_OVER) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\n", - Port, PhyStat)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkMacAutoNegLipaPhy */ -#endif /* SK_DIAG */ - - +#ifdef GENESIS /****************************************************************************** * * SkXmAutoNegDoneXmac() - Auto-negotiation handling @@ -2879,48 +3537,49 @@ SK_U16 PhyStat) /* PHY Status word to analyse */ * * Returns: * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened */ static int SkXmAutoNegDoneXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ + SK_U16 LinkPartAb; /* Link Partner Ability */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneXmac, Port %d\n",Port)); + ("AutoNegDoneXmac, Port %d\n", Port)); pPrt = &pAC->GIni.GP[Port]; /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb); + SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LinkPartAb); SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - if ((LPAb & PHY_X_AN_RFB) != 0) { + if ((LinkPartAb & PHY_X_AN_RFB) != 0) { /* At least one of the remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNegFail: Remote fault bit set Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); } /* Check Duplex mismatch */ if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; } else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; } else { /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_DUP_CAP); } @@ -2928,26 +3587,27 @@ int Port) /* Port Index (MAC_1 + n) */ /* We are NOT using chapter 4.23 of the Xaqti manual */ /* We are using IEEE 802.3z/D5.0 Table 37-4 */ if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC || - pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) && - (LPAb & PHY_X_P_SYM_MD) != 0) { + pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) && + (LinkPartAb & PHY_X_P_SYM_MD) != 0) { /* Symmetric PAUSE */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; } else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) { - /* Enable PAUSE receive, disable PAUSE transmit */ + (LinkPartAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) { + /* enable PAUSE receive, disable PAUSE transmit */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; } else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) { - /* Disable PAUSE receive, enable PAUSE transmit */ + (LinkPartAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) { + /* disable PAUSE receive, enable PAUSE transmit */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; } else { /* PAUSE mismatch -> no PAUSE */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; } - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; return(SK_AND_OK); } /* SkXmAutoNegDoneXmac */ @@ -2962,64 +3622,63 @@ int Port) /* Port Index (MAC_1 + n) */ * * Returns: * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened */ static int SkXmAutoNegDoneBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ +#ifdef TEST_ONLY + SK_U16 ResAb; /* Resolved Ability */ +#endif + SK_U16 LinkPartAb; /* Link Partner Ability */ SK_U16 AuxStat; /* Auxiliary Status */ -#if 0 -01-Sep-2000 RA;:;: - SK_U16 ResAb; /* Resolved Ability */ -#endif /* 0 */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNegDoneBcom, Port %d\n", Port)); pPrt = &pAC->GIni.GP[Port]; /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb); -#if 0 -01-Sep-2000 RA;:;: + SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LinkPartAb); +#ifdef TEST_ONLY SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); -#endif /* 0 */ +#endif SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat); - if ((LPAb & PHY_B_AN_RF) != 0) { + if ((LinkPartAb & PHY_B_AN_RF) != 0) { /* Remote fault bit is set: Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNegFail: Remote fault bit set Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); } /* Check Duplex mismatch */ if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; } else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; } else { /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_DUP_CAP); } -#if 0 -01-Sep-2000 RA;:;: +#ifdef TEST_ONLY /* Check Master/Slave resolution */ if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("Master/Slave Fault Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; pPrt->PMSStatus = SK_MS_STAT_FAULT; @@ -3028,32 +3687,35 @@ int Port) /* Port Index (MAC_1 + n) */ pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; -#endif /* 0 */ +#endif - /* Check PAUSE mismatch */ + /* Check PAUSE mismatch ??? */ /* We are using IEEE 802.3z/D5.0 Table 37-4 */ if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) { /* Symmetric PAUSE */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; } else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) { - /* Enable PAUSE receive, disable PAUSE transmit */ + /* enable PAUSE receive, disable PAUSE transmit */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; } else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) { - /* Disable PAUSE receive, enable PAUSE transmit */ + /* disable PAUSE receive, enable PAUSE transmit */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; } else { /* PAUSE mismatch -> no PAUSE */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; } - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; + + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; return(SK_AND_OK); } /* SkXmAutoNegDoneBcom */ +#endif /* GENESIS */ +#ifdef YUKON /****************************************************************************** * * SkGmAutoNegDoneMarv() - Auto-negotiation handling @@ -3063,99 +3725,184 @@ int Port) /* Port Index (MAC_1 + n) */ * * Returns: * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened */ static int SkGmAutoNegDoneMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ SK_U16 ResAb; /* Resolved Ability */ SK_U16 AuxStat; /* Auxiliary Status */ + SK_U8 PauseMode; /* Pause Mode */ +#ifndef SK_SLIM + SK_U16 LinkPartAb; /* Link Partner Ability */ +#ifndef SK_DIAG + SK_EVPARA Para; +#endif /* !SK_DIAG */ +#endif /* !SK_SLIM */ + + /* set Pause On */ + PauseMode = (SK_U8)GMC_PAUSE_ON; SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, ("AutoNegDoneMarv, Port %d\n", Port)); + pPrt = &pAC->GIni.GP[Port]; /* Get PHY parameters */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb); + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LinkPartAb); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Link P.Abil. = 0x%04X\n", LinkPartAb)); - if ((LPAb & PHY_M_AN_RF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + if ((LinkPartAb & PHY_M_AN_RF) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNegFail: Remote fault bit set Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); } - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); +#ifndef SK_SLIM + if (pAC->GIni.GICopperType) { + /* Read PHY Auto-Negotiation Expansion */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &LinkPartAb); - /* Check Master/Slave resolution */ - if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); + if ((LinkPartAb & PHY_ANE_LP_CAP) == 0) { + +#ifndef SK_DIAG + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("Link Partner not Auto-Neg. able, AN Exp.: 0x%04X\n", + LinkPartAb)); + +#ifndef NDIS_MINIPORT_DRIVER + SK_ERR_LOG(pAC, SK_ERRCL_CONFIG, SKERR_HWI_E025, SKERR_HWI_E025MSG); +#endif + + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_LIPA_NOT_AN_ABLE, Para); +#else + c_print("Link Partner not Auto-Neg. able, AN Exp.: 0x%04X\n", + LinkPartAb); +#endif /* !SK_DIAG */ + + if (HW_FEATURE(pAC, HWF_FORCE_AUTO_NEG) && + pPrt->PLinkModeConf < SK_LMODE_AUTOHALF) { + /* set used link speed */ + pPrt->PLinkSpeedUsed = pPrt->PLinkSpeed; + + /* Set Link Mode Status */ + pPrt->PLinkModeStatus = (pPrt->PLinkModeConf == SK_LMODE_FULL) ? + SK_LMODE_STAT_FULL : SK_LMODE_STAT_HALF; + + return(SK_AND_OK); + } + } } +#endif /* !SK_SLIM */ - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; + if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) { + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); + + /* Check Master/Slave resolution */ + if ((ResAb & PHY_B_1000S_MSF) != 0) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("Master/Slave Fault Port %d\n", Port)); + pPrt->PAutoNegFail = SK_TRUE; + pPrt->PMSStatus = SK_MS_STAT_FAULT; + return(SK_AND_OTHER); + } + + pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? + (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; + } /* Read PHY Specific Status */ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat); /* Check Speed & Duplex resolved */ if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port)); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; - pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; + return(SK_AND_DUP_CAP); } - if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)(((AuxStat & PHY_M_PS_FULL_DUP) != 0) ? + SK_LMODE_STAT_AUTOFULL : SK_LMODE_STAT_AUTOHALF); + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { + /* set used link speed */ + pPrt->PLinkSpeedUsed = (SK_U8)(((AuxStat & PHY_M_PS_SPEED_100) != 0) ? + SK_LSPEED_STAT_100MBPS : SK_LSPEED_STAT_10MBPS); } else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + /* set used link speed */ + switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { + case (unsigned)PHY_M_PS_SPEED_1000: + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; + break; + case PHY_M_PS_SPEED_100: + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; + break; + default: + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; + } + + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL || + pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U) { + /* Tx & Rx Pause Enabled bits are at 9..8 */ + AuxStat >>= 6; + + if (!pAC->GIni.GICopperType) { + /* always 1000 Mbps on fiber */ + pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; + } + } + + AuxStat &= PHY_M_PS_PAUSE_MSK; + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ + if (AuxStat == PHY_M_PS_PAUSE_MSK) { + /* Symmetric PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; + } + else if (AuxStat == PHY_M_PS_RX_P_EN) { + /* enable PAUSE receive, disable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; + } + else if (AuxStat == PHY_M_PS_TX_P_EN) { + /* disable PAUSE receive, enable PAUSE transmit */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; + } + else { + /* PAUSE mismatch -> no PAUSE */ + pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + } } - /* Check PAUSE mismatch */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("LinkSpeedUsed = %d\n", pPrt->PLinkSpeedUsed)); + + if ((pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE) || + /* disable Pause also for 10/100 Mbps in half duplex mode */ + ((pAC->GIni.GIChipId != CHIP_ID_YUKON_EC_U) && + (pPrt->PLinkSpeedUsed < (SK_U8)SK_LSPEED_STAT_1000MBPS) && + pPrt->PLinkModeStatus == (SK_U8)SK_LMODE_STAT_AUTOHALF)) { + + /* set Pause Off */ + PauseMode = (SK_U8)GMC_PAUSE_OFF; } - /* set used link speed */ - switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { - case (unsigned)PHY_M_PS_SPEED_1000: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS; - break; - case PHY_M_PS_SPEED_100: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS; - break; - default: - pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS; - } + SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), PauseMode); return(SK_AND_OK); } /* SkGmAutoNegDoneMarv */ +#endif /* YUKON */ #ifdef OTHER_PHY @@ -3168,65 +3915,63 @@ int Port) /* Port Index (MAC_1 + n) */ * * Returns: * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened */ static int SkXmAutoNegDoneLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ + SK_U16 LinkPartAb; /* Link Partner Ability */ SK_U16 QuickStat; /* Auxiliary Status */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneLone, Port %d\n",Port)); + ("AutoNegDoneLone, Port %d\n", Port)); pPrt = &pAC->GIni.GP[Port]; /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb); + SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LinkPartAb); SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb); SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat); - if ((LPAb & PHY_L_AN_RF) != 0) { + if ((LinkPartAb & PHY_L_AN_RF) != 0) { /* Remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("AutoNegFail: Remote fault bit set Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; + return(SK_AND_OTHER); } /* Check Duplex mismatch */ if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; } else { - pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF; + pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; } /* Check Master/Slave resolution */ if ((ResAb & PHY_L_1000S_MSF) != 0) { /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, ("Master/Slave Fault Port %d\n", Port)); pPrt->PAutoNegFail = SK_TRUE; pPrt->PMSStatus = SK_MS_STAT_FAULT; return(SK_AND_OTHER); } - else if (ResAb & PHY_L_1000S_MSR) { - pPrt->PMSStatus = SK_MS_STAT_MASTER; - } - else { - pPrt->PMSStatus = SK_MS_STAT_SLAVE; - } + + pPrt->PMSStatus = ((ResAb & PHY_L_1000S_MSR) != 0) ? + (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; /* Check PAUSE mismatch */ /* We are using IEEE 802.3z/D5.0 Table 37-4 */ /* we must manually resolve the abilities here */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; + switch (pPrt->PFlowCtrlMode) { case SK_FLOW_MODE_NONE: /* default */ @@ -3234,7 +3979,7 @@ int Port) /* Port Index (MAC_1 + n) */ case SK_FLOW_MODE_LOC_SEND: if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) { - /* Disable PAUSE receive, enable PAUSE transmit */ + /* disable PAUSE receive, enable PAUSE transmit */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; } break; @@ -3247,7 +3992,7 @@ int Port) /* Port Index (MAC_1 + n) */ case SK_FLOW_MODE_SYM_OR_REM: if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == PHY_L_QS_AS_PAUSE) { - /* Enable PAUSE receive, disable PAUSE transmit */ + /* enable PAUSE receive, disable PAUSE transmit */ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; } else if ((QuickStat & PHY_L_QS_PAUSE) != 0) { @@ -3273,12 +4018,12 @@ int Port) /* Port Index (MAC_1 + n) */ * * Returns: * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened */ static int SkXmAutoNegDoneNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { /* todo: National */ @@ -3295,46 +4040,60 @@ int Port) /* Port Index (MAC_1 + n) */ * * Returns: * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened + * SK_AND_DUP_CAP Duplex capability error happened + * SK_AND_OTHER Other error happened */ -int SkMacAutoNegDone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +int SkMacAutoNegDone( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; int Rtv; + Rtv = SK_AND_OK; + pPrt = &pAC->GIni.GP[Port]; - switch (pPrt->PhyType) { - case SK_PHY_XMAC: - Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port); - break; - case SK_PHY_BCOM: - Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port); - break; - case SK_PHY_MARV_COPPER: - case SK_PHY_MARV_FIBER: - Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port); - break; +#ifdef GENESIS + if (pAC->GIni.GIGenesis) { + + switch (pPrt->PhyType) { + + case SK_PHY_XMAC: + Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port); + break; + case SK_PHY_BCOM: + Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port); + break; #ifdef OTHER_PHY - case SK_PHY_LONE: - Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port); - break; - case SK_PHY_NAT: - Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port); - break; + case SK_PHY_LONE: + Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port); + break; + case SK_PHY_NAT: + Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port); + break; #endif /* OTHER_PHY */ - default: - return(SK_AND_OTHER); + default: + return(SK_AND_OTHER); + } } +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { + + Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port); + } +#endif /* YUKON */ if (Rtv != SK_AND_OK) { return(Rtv); } + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNeg done Port %d\n", Port)); + /* We checked everything and may now enable the link */ pPrt->PAutoNegFail = SK_FALSE; @@ -3344,6 +4103,8 @@ int Port) /* Port Index (MAC_1 + n) */ } /* SkMacAutoNegDone */ +#ifndef SK_SLIM +#ifdef GENESIS /****************************************************************************** * * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC @@ -3356,7 +4117,7 @@ int Port) /* Port Index (MAC_1 + n) */ */ static void SkXmSetRxTxEn( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */ { @@ -3397,8 +4158,10 @@ int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */ XM_IN16(IoC, Port, XM_MMU_CMD, &Word); } /* SkXmSetRxTxEn */ +#endif /* GENESIS */ +#ifdef YUKON /****************************************************************************** * * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC @@ -3411,7 +4174,7 @@ int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */ */ static void SkGmSetRxTxEn( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */ { @@ -3439,10 +4202,8 @@ int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */ GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); - /* dummy read to ensure writing */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl); - } /* SkGmSetRxTxEn */ +#endif /* YUKON */ /****************************************************************************** @@ -3455,20 +4216,26 @@ int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */ */ void SkMacSetRxTxEn( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ int Para) { +#ifdef GENESIS if (pAC->GIni.GIGenesis) { SkXmSetRxTxEn(pAC, IoC, Port, Para); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { SkGmSetRxTxEn(pAC, IoC, Port, Para); } +#endif /* YUKON */ } /* SkMacSetRxTxEn */ +#endif /* !SK_SLIM */ /****************************************************************************** @@ -3482,14 +4249,16 @@ int Para) * != 0 Error happened */ int SkMacRxTxEnable( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; SK_U16 Reg; /* 16-bit register value */ SK_U16 IntMask; /* MAC interrupt mask */ +#ifdef GENESIS SK_U16 SWord; +#endif pPrt = &pAC->GIni.GP[Port]; @@ -3499,13 +4268,14 @@ int Port) /* Port Index (MAC_1 + n) */ } if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF || - pPrt->PLinkMode == SK_LMODE_AUTOFULL || - pPrt->PLinkMode == SK_LMODE_AUTOBOTH) && - pPrt->PAutoNegFail) { + pPrt->PLinkMode == SK_LMODE_AUTOFULL || + pPrt->PLinkMode == SK_LMODE_AUTOBOTH) && + pPrt->PAutoNegFail) { /* Auto-negotiation is not done or failed */ return(0); } +#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* set Duplex Mode and Pause Mode */ SkXmInitDupMd(pAC, IoC, Port); @@ -3532,6 +4302,7 @@ int Port) /* Port Index (MAC_1 + n) */ /* disable GP0 interrupt bit */ IntMask |= XM_IS_INP_ASS; } + XM_OUT16(IoC, Port, XM_IMSK, IntMask); /* get MMU Command Reg. */ @@ -3553,7 +4324,8 @@ int Port) /* Port Index (MAC_1 + n) */ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, (SK_U16)(SWord & ~PHY_B_AC_DIS_PM)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); + SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, + (SK_U16)PHY_B_DEF_MSK); break; #ifdef OTHER_PHY case SK_PHY_LONE: @@ -3570,7 +4342,10 @@ int Port) /* Port Index (MAC_1 + n) */ /* enable Rx/Tx */ XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { /* * Initialize the Interrupt Mask Register. Default IRQs are... * - Rx Counter Event Overflow @@ -3579,12 +4354,12 @@ int Port) /* Port Index (MAC_1 + n) */ */ IntMask = GMAC_DEF_MSK; -#ifdef DEBUG +#if (defined(DEBUG) || defined(YUK2)) && (!defined(SK_SLIM)) /* add IRQ for Receive FIFO Overrun */ IntMask |= GM_IS_RX_FF_OR; -#endif /* DEBUG */ +#endif - SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask); + SK_OUT8(IoC, MR_ADDR(Port, GMAC_IRQ_MSK), (SK_U8)IntMask); /* get General Purpose Control */ GM_IN16(IoC, Port, GM_GP_CTRL, &Reg); @@ -3593,16 +4368,31 @@ int Port) /* Port Index (MAC_1 + n) */ pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) { /* set to Full Duplex */ Reg |= GM_GPCR_DUP_FULL; + +#ifndef SK_SLIM + if (HW_FEATURE(pAC, HWF_FORCE_AUTO_NEG) && + pPrt->PLinkModeConf < SK_LMODE_AUTOHALF) { + /* disable auto-update for speed, duplex and flow-control */ + Reg |= GM_GPCR_AU_ALL_DIS; + } +#endif /* !SK_SLIM */ + } + + /* WA for dev. #4.209 */ + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U && + pAC->GIni.GIChipRev == CHIP_REV_YU_EC_U_A1) { + /* enable/disable Store & Forward mode for TX */ + SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), + pPrt->PLinkSpeedUsed != (SK_U8)SK_LSPEED_STAT_1000MBPS ? + TX_STFW_ENA : TX_STFW_DIS); } /* enable Rx/Tx */ GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); - -#ifndef VCPU - /* Enable all PHY interrupts */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); -#endif /* VCPU */ } +#endif /* YUKON */ + + pAC->GIni.GP[Port].PState = SK_PRT_RUN; return(0); @@ -3619,29 +4409,36 @@ int Port) /* Port Index (MAC_1 + n) */ */ void SkMacRxTxDisable( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_U16 Word; +#ifdef GENESIS if (pAC->GIni.GIGenesis) { XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); + Word &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); + + XM_OUT16(IoC, Port, XM_MMU_CMD, Word); /* dummy read to ensure writing */ XM_IN16(IoC, Port, XM_MMU_CMD, &Word); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { GM_IN16(IoC, Port, GM_GP_CTRL, &Word); - GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); + Word &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); - /* dummy read to ensure writing */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Word); + GM_OUT16(IoC, Port, GM_GP_CTRL, Word); } +#endif /* YUKON */ + } /* SkMacRxTxDisable */ @@ -3655,27 +4452,30 @@ int Port) /* Port Index (MAC_1 + n) */ */ void SkMacIrqDisable( SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; +#ifdef GENESIS SK_U16 Word; +#endif pPrt = &pAC->GIni.GP[Port]; +#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* disable all XMAC IRQs */ XM_OUT16(IoC, Port, XM_IMSK, 0xffff); - /* Disable all PHY interrupts */ + /* disable all PHY interrupts */ switch (pPrt->PhyType) { case SK_PHY_BCOM: /* Make sure that PHY is initialized */ if (pPrt->PState != SK_PRT_RESET) { /* NOT allowed if BCOM is in RESET state */ /* Workaround BCOM Errata (#10523) all BCom */ - /* Disable Power Management if link is down */ + /* disable Power Management if link is down */ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word); SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, (SK_U16)(Word | PHY_B_AC_DIS_PM)); @@ -3693,15 +4493,20 @@ int Port) /* Port Index (MAC_1 + n) */ #endif /* OTHER_PHY */ } } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); + SK_OUT8(IoC, MR_ADDR(Port, GMAC_IRQ_MSK), 0); #ifndef VCPU - /* Disable all PHY interrupts */ + /* disable all PHY interrupts */ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); -#endif /* VCPU */ +#endif /* !VCPU */ } +#endif /* YUKON */ + } /* SkMacIrqDisable */ @@ -3710,31 +4515,75 @@ int Port) /* Port Index (MAC_1 + n) */ * * SkXmSendCont() - Enable / Disable Send Continuous Mode * - * Description: enable / disable Send Continuous Mode on XMAC + * Description: enable / disable Send Continuous Mode on XMAC resp. + * Packet Generation on GPHY * * Returns: * nothing */ void SkXmSendCont( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL Enable) /* Enable / Disable */ { + SK_U16 Reg; + SK_U16 Save; SK_U32 MdReg; - XM_IN32(IoC, Port, XM_MODE, &MdReg); + if (pAC->GIni.GIGenesis) { + XM_IN32(IoC, Port, XM_MODE, &MdReg); - if (Enable) { - MdReg |= XM_MD_TX_CONT; + if (Enable) { + MdReg |= XM_MD_TX_CONT; + } + else { + MdReg &= ~XM_MD_TX_CONT; + } + /* setup Mode Register */ + XM_OUT32(IoC, Port, XM_MODE, MdReg); } else { - MdReg &= ~XM_MD_TX_CONT; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) { + /* select page 18 */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 18); + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PAGE_DATA, &Reg); + + Reg &= ~0x003c; /* clear bits 5..2 */ + + if (Enable) { + /* enable packet generation, 1518 byte length */ + Reg |= (BIT_5S | BIT_3S); + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, Reg); + } + else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) { + /* save page register */ + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &Save); + + /* select page 6 to access Packet Generation register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 6); + + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Reg); + + Reg &= ~0x003f; /* clear bits 5..0 */ + + if (Enable) { + /* enable packet generation, 1518 byte length */ + Reg |= (BIT_3S | BIT_1S); + } + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Reg); + + /* restore page register */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, Save); + } + } + +} /* SkXmSendCont */ -} /* SkXmSendCont*/ /****************************************************************************** * @@ -3746,8 +4595,8 @@ SK_BOOL Enable) /* Enable / Disable */ * nothing */ void SkMacTimeStamp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL Enable) /* Enable / Disable */ { @@ -3775,12 +4624,76 @@ SK_BOOL Enable) /* Enable / Disable */ TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ; } /* Start/Stop Time Stamp Timer */ - SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl); + SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl); } + } /* SkMacTimeStamp*/ -#else /* SK_DIAG */ +#else /* !SK_DIAG */ +#ifdef GENESIS +/****************************************************************************** + * + * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg + * + * This function analyses the Interrupt status word. If any of the + * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable + * is set true. + */ +void SkXmAutoNegLipaXmac( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_U16 IStatus) /* Interrupt Status word to analyse */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && + (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegLipa: AutoNeg detected on Port %d, IStatus = 0x%04X\n", + Port, IStatus)); + + pPrt->PLipaAutoNeg = SK_LIPA_AUTO; + } +} /* SkXmAutoNegLipaXmac */ +#endif /* GENESIS */ + + +/****************************************************************************** + * + * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg + * + * This function analyses the PHY status word. + * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable + * is set true. + */ +void SkMacAutoNegLipaPhy( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +int Port, /* Port Index (MAC_1 + n) */ +SK_U16 PhyStat) /* PHY Status word to analyse */ +{ + SK_GEPORT *pPrt; + + pPrt = &pAC->GIni.GP[Port]; + + if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && + (PhyStat & PHY_ST_AN_OVER) != 0) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, + ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat = 0x%04X\n", + Port, PhyStat)); + + pPrt->PLipaAutoNeg = SK_LIPA_AUTO; + } +} /* SkMacAutoNegLipaPhy */ + + +#ifdef GENESIS /****************************************************************************** * * SkXmIrq() - Interrupt Service Routine @@ -3789,7 +4702,7 @@ SK_BOOL Enable) /* Enable / Disable */ * * Note: * With an external PHY, some interrupt bits are not meaningfull any more: - * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE + * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC * - Page Received (bit #9) XM_IS_RX_PAGE * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE @@ -3800,15 +4713,19 @@ SK_BOOL Enable) /* Enable / Disable */ * Returns: * nothing */ -void SkXmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +static void SkXmIrq( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; - SK_EVPARA Para; SK_U16 IStatus; /* Interrupt status read from the XMAC */ SK_U16 IStatus2; +#ifdef SK_SLIM + SK_U64 OverflowStatus; +#else + SK_EVPARA Para; +#endif /* SK_SLIM */ pPrt = &pAC->GIni.GP[Port]; @@ -3826,7 +4743,7 @@ int Port) /* Port Index (MAC_1 + n) */ } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("XmacIrq Port %d Isr 0x%04x\n", Port, IStatus)); + ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus)); if (!pPrt->PHWLinkUp) { /* Spurious XMAC interrupt */ @@ -3840,7 +4757,7 @@ int Port) /* Port Index (MAC_1 + n) */ XM_IN16(IoC, Port, XM_ISRC, &IStatus2); SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\n", + ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n", Port, IStatus, IStatus2)); IStatus &= ~XM_IS_INP_ASS; IStatus |= IStatus2; @@ -3889,9 +4806,15 @@ int Port) /* Port Index (MAC_1 + n) */ /* Combined Tx & Rx Counter Overflow SIRQ Event */ if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) { +#ifdef SK_SLIM + SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus); +#else +# ifdef SK_PNMI_SUPPORT Para.Para32[0] = (SK_U32)Port; Para.Para32[1] = (SK_U32)IStatus; SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); +# endif +#endif /* SK_SLIM */ } if ((IStatus & XM_IS_RXF_OV) != 0) { @@ -3914,8 +4837,10 @@ int Port) /* Port Index (MAC_1 + n) */ /* not served here */ } } /* SkXmIrq */ +#endif /* GENESIS */ +#ifdef YUKON /****************************************************************************** * * SkGmIrq() - Interrupt Service Routine @@ -3927,40 +4852,58 @@ int Port) /* Port Index (MAC_1 + n) */ * Returns: * nothing */ -void SkGmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +static void SkGmIrq( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; - SK_EVPARA Para; SK_U8 IStatus; /* Interrupt status */ +#ifdef SK_SLIM + SK_U64 OverflowStatus; +#else + SK_EVPARA Para; +#endif /* SK_SLIM */ pPrt = &pAC->GIni.GP[Port]; - SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus); + SK_IN8(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &IStatus); +#ifdef XXX /* LinkPartner Auto-negable? */ SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus); +#endif /* XXX */ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus)); + ("GmacIrq Port %d Isr 0x%02X\n", Port, IStatus)); /* Combined Tx & Rx Counter Overflow SIRQ Event */ if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) { /* these IRQs will be cleared by reading GMACs register */ +#ifdef SK_SLIM + SkGmOverflowStatus(pAC, IoC, Port, (SK_U16)IStatus, &OverflowStatus); +#else +# ifdef SK_PNMI_SUPPORT Para.Para32[0] = (SK_U32)Port; Para.Para32[1] = (SK_U32)IStatus; SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); +# endif +#endif /* SK_SLIM */ } +#ifndef SK_SLIM if (IStatus & GM_IS_RX_FF_OR) { /* clear GMAC Rx FIFO Overrun IRQ */ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO); + + Para.Para64 = Port; + SkEventQueue(pAC, SKGE_DRV, SK_DRV_RX_OVERFLOW, Para); + #ifdef DEBUG pPrt->PRxOverCnt++; #endif /* DEBUG */ } +#endif /* !SK_SLIM */ if (IStatus & GM_IS_TX_FF_UR) { /* clear GMAC Tx FIFO Underrun IRQ */ @@ -3977,6 +4920,8 @@ int Port) /* Port Index (MAC_1 + n) */ /* not served here */ } } /* SkGmIrq */ +#endif /* YUKON */ + /****************************************************************************** * @@ -3988,23 +4933,29 @@ int Port) /* Port Index (MAC_1 + n) */ * nothing */ void SkMacIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port) /* Port Index (MAC_1 + n) */ { - +#ifdef GENESIS if (pAC->GIni.GIGenesis) { /* IRQ from XMAC */ SkXmIrq(pAC, IoC, Port); } - else { +#endif /* GENESIS */ + +#ifdef YUKON + if (pAC->GIni.GIYukon) { /* IRQ from GMAC */ SkGmIrq(pAC, IoC, Port); } +#endif /* YUKON */ + } /* SkMacIrq */ #endif /* !SK_DIAG */ +#ifdef GENESIS /****************************************************************************** * * SkXmUpdateStats() - Force the XMAC to output the current statistic @@ -4019,8 +4970,8 @@ int Port) /* Port Index (MAC_1 + n) */ * 1: something went wrong */ int SkXmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ unsigned int Port) /* Port Index (MAC_1 + n) */ { SK_GEPORT *pPrt; @@ -4054,24 +5005,6 @@ unsigned int Port) /* Port Index (MAC_1 + n) */ return(0); } /* SkXmUpdateStats */ -/****************************************************************************** - * - * SkGmUpdateStats() - Force the GMAC to output the current statistic - * - * Description: - * Empty function for GMAC. Statistic data is accessible in direct way. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - return(0); -} /****************************************************************************** * @@ -4087,11 +5020,11 @@ unsigned int Port) /* Port Index (MAC_1 + n) */ * 1: something went wrong */ int SkXmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 *pVal) /* ptr to return statistic value */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 StatAddr, /* MIB counter base address */ +SK_U32 SK_FAR *pVal) /* Pointer to return statistic value */ { if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) { @@ -4105,40 +5038,6 @@ SK_U32 *pVal) /* ptr to return statistic value */ return(0); } /* SkXmMacStatistic */ -/****************************************************************************** - * - * SkGmMacStatistic() - Get GMAC counter value - * - * Description: - * Gets the 32bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * must be counted in software by monitoring counter overflow interrupts. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 *pVal) /* ptr to return statistic value */ -{ - - if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr)); - return(1); - } - - GM_IN32(IoC, Port, StatAddr, pVal); - - return(0); -} /* SkGmMacStatistic */ /****************************************************************************** * @@ -4152,55 +5051,17 @@ SK_U32 *pVal) /* ptr to return statistic value */ * 1: something went wrong */ int SkXmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ unsigned int Port) /* Port Index (MAC_1 + n) */ { XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* Clear two times according to Errata #3 */ + /* Clear two times according to XMAC Errata #3 */ XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); return(0); } /* SkXmResetCounter */ -/****************************************************************************** - * - * SkGmResetCounter() - Clear MAC statistic counter - * - * Description: - * Force GMAC to clear its statistic counter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Reg; /* Phy Address Register */ - SK_U16 Word; - int i; - - GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg); - -#ifndef VCPU - /* set MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR); - - /* read all MIB Counters with Clear Mode set */ - for (i = 0; i < GM_MIB_CNT_SIZE; i++) { - /* the reset is performed only when the lower 16 bits are read */ - GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word); - } - - /* clear MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg); -#endif /* !VCPU */ - - return(0); -} /* SkGmResetCounter */ /****************************************************************************** * @@ -4222,11 +5083,11 @@ unsigned int Port) /* Port Index (MAC_1 + n) */ * 1: something went wrong */ int SkXmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 *pStatus) /* ptr for return overflow status value */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 IStatus, /* Interrupt Status from MAC */ +SK_U64 SK_FAR *pStatus) /* Pointer for return overflow status value */ { SK_U64 Status; /* Overflow status */ SK_U32 RegVal; @@ -4249,6 +5110,105 @@ SK_U64 *pStatus) /* ptr for return overflow status value */ return(0); } /* SkXmOverflowStatus */ +#endif /* GENESIS */ + + +#ifdef YUKON +/****************************************************************************** + * + * SkGmUpdateStats() - Force the GMAC to output the current statistic + * + * Description: + * Empty function for GMAC. Statistic data is accessible in direct way. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkGmUpdateStats( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +unsigned int Port) /* Port Index (MAC_1 + n) */ +{ + return(0); +} + + +/****************************************************************************** + * + * SkGmMacStatistic() - Get GMAC counter value + * + * Description: + * Gets the 32bit counter value. Except for the octet counters + * the lower 32bit are counted in hardware and the upper 32bit + * must be counted in software by monitoring counter overflow interrupts. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkGmMacStatistic( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 StatAddr, /* MIB counter base address */ +SK_U32 SK_FAR *pVal) /* Pointer to return statistic value */ +{ + + if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) { + + SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr)); + return(1); + } + + GM_IN32(IoC, Port, StatAddr, pVal); + + /* dummy read after GM_IN32() */ + SK_IN16(IoC, B0_RAP, &StatAddr); + + return(0); +} /* SkGmMacStatistic */ + + +/****************************************************************************** + * + * SkGmResetCounter() - Clear MAC statistic counter + * + * Description: + * Force GMAC to clear its statistic counter. + * + * Returns: + * 0: success + * 1: something went wrong + */ +int SkGmResetCounter( +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +unsigned int Port) /* Port Index (MAC_1 + n) */ +{ + SK_U16 Reg; /* PHY Address Register */ + SK_U16 Word; + int i; + + GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg); + + /* set MIB Clear Counter Mode */ + GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR); + + /* read all MIB Counters with Clear Mode set */ + for (i = 0; i < GM_MIB_CNT_SIZE; i++) { + /* the reset is performed only when the lower 16 bits are read */ + GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word); + } + + /* clear MIB Clear Counter Mode */ + GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg); + + return(0); +} /* SkGmResetCounter */ /****************************************************************************** @@ -4260,52 +5220,68 @@ SK_U64 *pStatus) /* ptr for return overflow status value */ * resulting counter overflow status is written to , whereas the * the following bit coding is used: * 63:56 - unused - * 55:48 - TxRx interrupt register bit7:0 - * 32:47 - Rx interrupt register + * 55:48 - TxRx interrupt register bit 7:0 + * 47:32 - Rx interrupt register * 31:24 - unused - * 23:16 - TxRx interrupt register bit15:8 - * 15:0 - Tx interrupt register + * 23:16 - TxRx interrupt register bit 15:8 + * 15: 0 - Tx interrupt register * * Returns: * 0: success * 1: something went wrong */ int SkGmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 *pStatus) /* ptr for return overflow status value */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ +unsigned int Port, /* Port Index (MAC_1 + n) */ +SK_U16 IStatus, /* Interrupt Status from MAC */ +SK_U64 SK_FAR *pStatus) /* Pointer for return overflow status value */ { - SK_U64 Status; /* Overflow status */ SK_U16 RegVal; +#ifndef SK_SLIM + SK_U64 Status; /* Overflow status */ Status = 0; +#endif /* !SK_SLIM */ if ((IStatus & GM_IS_RX_CO_OV) != 0) { /* this register is self-clearing after read */ GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal); + +#ifndef SK_SLIM Status |= (SK_U64)RegVal << 32; +#endif /* !SK_SLIM */ } if ((IStatus & GM_IS_TX_CO_OV) != 0) { /* this register is self-clearing after read */ GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal); + +#ifndef SK_SLIM Status |= (SK_U64)RegVal; +#endif /* !SK_SLIM */ } /* this register is self-clearing after read */ GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal); + +#ifndef SK_SLIM /* Rx overflow interrupt register bits (LoByte)*/ Status |= (SK_U64)((SK_U8)RegVal) << 48; /* Tx overflow interrupt register bits (HiByte)*/ Status |= (SK_U64)(RegVal >> 8) << 16; *pStatus = Status; +#endif /* !SK_SLIM */ + + /* dummy read after GM_IN16() */ + SK_IN16(IoC, B0_RAP, &RegVal); return(0); } /* SkGmOverflowStatus */ + +#ifndef SK_SLIM /****************************************************************************** * * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test @@ -4322,12 +5298,17 @@ SK_U64 *pStatus) /* ptr for return overflow status value */ * 2: test in progress */ int SkGmCableDiagStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ +SK_AC *pAC, /* Adapter Context */ +SK_IOC IoC, /* I/O Context */ int Port, /* Port Index (MAC_1 + n) */ SK_BOOL StartTest) /* flag for start / get result */ { int i; + int CableDiagOffs; + int MdiPairs; + int Rtv; + SK_BOOL FastEthernet; + SK_BOOL Yukon2; SK_U16 RegVal; SK_GEPORT *pPrt; @@ -4338,37 +5319,96 @@ SK_BOOL StartTest) /* flag for start / get result */ return(1); } - if (StartTest) { - /* only start the cable test */ - if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) { - /* apply TDR workaround from Marvell */ - SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e); + Yukon2 = pAC->GIni.GIChipId == CHIP_ID_YUKON_XL || + pAC->GIni.GIChipId == CHIP_ID_YUKON_EC_U; - SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100); + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { + + CableDiagOffs = PHY_MARV_FE_VCT_TX; + FastEthernet = SK_TRUE; + MdiPairs = 2; + } + else { + CableDiagOffs = Yukon2 ? PHY_MARV_PHY_CTRL : PHY_MARV_CABLE_DIAG; + FastEthernet = SK_FALSE; + MdiPairs = 4; + } + + if (StartTest) { + + /* set to RESET to avoid PortCheckUp */ + pPrt->PState = SK_PRT_RESET; + + /* only start the cable test */ + if (!FastEthernet) { + + if ((((pPrt->PhyId1 & PHY_I1_MOD_NUM) >> 4) == 2) && + ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4)) { + /* apply TDR workaround for model 2, rev. < 4 */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 0x001e); + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xcc00); + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc800); + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc400); + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc000); + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc100); + } + +#ifdef YUKON_DBG + if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) { + /* set address to 1 for page 1 */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 1); + + /* disable waiting period */ + SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs, + PHY_M_CABD_DIS_WAIT); + } +#endif + if (Yukon2) { + /* set address to 5 for page 5 */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5); + +#ifdef YUKON_DBG + /* disable waiting period */ + SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs + 1, + PHY_M_CABD_DIS_WAIT); +#endif + } + else { + /* set address to 0 for MDI[0] (Page 0) */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); + } + } + else { + RegVal = PHY_CT_RESET | PHY_CT_SP100; + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, RegVal); + +#ifdef xYUKON_DBG + SkGmPhyRead(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, &RegVal); + /* disable waiting period */ + RegVal |= PHY_M_FESC_DIS_WAIT; + + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, RegVal); +#endif } - /* set address to 0 for MDI[0] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); - - /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - /* start Cable Diagnostic Test */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, - (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST)); + SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs, PHY_M_CABD_ENA_TEST); return(0); } /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); + Rtv = SkGmPhyRead(pAC, IoC, Port, CableDiagOffs, &RegVal); + + if (Rtv == 2) { + /* PHY read timeout */ + return(3); + } SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Cable Diag.=0x%04X\n", RegVal)); + ("PHY Cable Diag. = 0x%04X\n", RegVal)); if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) { /* test is running */ @@ -4376,21 +5416,31 @@ SK_BOOL StartTest) /* flag for start / get result */ } /* get the test results */ - for (i = 0; i < 4; i++) { - /* set address to i for MDI[i] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i); + for (i = 0; i < MdiPairs; i++) { + + if (!FastEthernet && !Yukon2) { + /* set address to i for MDI[i] */ + SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i); + } /* get Cable Diagnostic values */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); + SkGmPhyRead(pAC, IoC, Port, CableDiagOffs, &RegVal); pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK); pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13); + + if (FastEthernet || Yukon2) { + /* get next register */ + CableDiagOffs++; + } } return(0); } /* SkGmCableDiagStatus */ - -#endif /* CONFIG_SK98 */ +#endif /* !SK_SLIM */ +#endif /* YUKON */ /* End of file */ + +#endif diff --git a/drivers/sk98lin/sky2.c b/drivers/sk98lin/sky2.c new file mode 100644 index 0000000..fe8d4ae --- /dev/null +++ b/drivers/sk98lin/sky2.c @@ -0,0 +1,2774 @@ +/****************************************************************************** + * + * Name: sky2.c + * Project: Yukon2 specific functions and implementations + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: The main driver source module + * + *****************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 1998-2002 SysKonnect GmbH. + * (C)Copyright 2002-2005 Marvell. + * + * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet + * Server Adapters. + * + * Author: Ralph Roesler (rroesler@syskonnect.de) + * Mirko Lindner (mlindner@syskonnect.de) + * + * Address all question to: linux@syskonnect.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The information in this file is provided "AS IS" without warranty. + * + *****************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" +#if 0 /* uboot */ +#include +#endif +/****************************************************************************** + * + * Local Function Prototypes + * + *****************************************************************************/ + +static void InitPacketQueues(SK_AC *pAC,int Port); +static void GiveTxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port); +static void GiveRxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port,SK_PACKET *pPacket); +static SK_BOOL HandleReceives(SK_AC *pAC,int Port,SK_U16 Len,SK_U32 FrameStatus,SK_U16 Tcp1,SK_U16 Tcp2,SK_U32 Tist,SK_U16 Vlan); +static void CheckForSendComplete(SK_AC *pAC,SK_IOC IoC,int Port,SK_PKT_QUEUE *pPQ,SK_LE_TABLE *pLETab,unsigned int Done); +static void UnmapAndFreeTxPktBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int TxPort); +static SK_BOOL AllocateAndInitLETables(SK_AC *pAC); +static SK_BOOL AllocatePacketBuffersYukon2(SK_AC *pAC); +static void FreeLETables(SK_AC *pAC); +static void FreePacketBuffers(SK_AC *pAC); +static SK_BOOL AllocAndMapRxBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int Port); +#ifdef CONFIG_SK98LIN_NAPI +static SK_BOOL HandleStatusLEs(SK_AC *pAC,int *WorkDone,int WorkToDo); +#else +static SK_BOOL HandleStatusLEs(SK_AC *pAC); +#endif + +extern void SkGeCheckTimer (DEV_NET *pNet); +extern void SkLocalEventQueue( SK_AC *pAC, + SK_U32 Class, + SK_U32 Event, + SK_U32 Param1, + SK_U32 Param2, + SK_BOOL Flag); +extern void SkLocalEventQueue64( SK_AC *pAC, + SK_U32 Class, + SK_U32 Event, + SK_U64 Param, + SK_BOOL Flag); + +/****************************************************************************** + * + * Local Variables + * + *****************************************************************************/ + +#define MAX_NBR_RX_BUFFERS_IN_HW 0x15 +static SK_U8 NbrRxBuffersInHW; +#define FLUSH_OPC(le) + +/****************************************************************************** + * + * Global Functions + * + *****************************************************************************/ + +int SkY2Xmit( struct sk_buff *skb, struct SK_NET_DEVICE *dev); +void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port); + +/***************************************************************************** + * + * SkY2RestartStatusUnit - restarts teh status unit + * + * Description: + * Reenables the status unit after any De-Init (e.g. when altering + * the sie of the MTU via 'ifconfig a.b.c.d mtu xxx') + * + * Returns: N/A + */ +void SkY2RestartStatusUnit( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> SkY2RestartStatusUnit\n")); + + /* + ** It might be that the TX timer is not started. Therefore + ** it is initialized here -> to be more investigated! + */ + SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10)); + + pAC->StatusLETable.Done = 0; + pAC->StatusLETable.Put = 0; + pAC->StatusLETable.HwPut = 0; + SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== SkY2RestartStatusUnit\n")); +} + +/***************************************************************************** + * + * SkY2RlmtSend - sends out a single RLMT notification + * + * Description: + * This function sends out an RLMT frame + * + * Returns: + * > 0 - on succes: the number of bytes in the message + * = 0 - on resource shortage: this frame sent or dropped, now + * the ring is full ( -> set tbusy) + * < 0 - on failure: other problems ( -> return failure to upper layers) + */ +int SkY2RlmtSend ( +SK_AC *pAC, /* pointer to adapter control context */ +int PortNr, /* index of port the packet(s) shall be send to */ +struct sk_buff *pMessage) /* pointer to send-message */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("=== SkY2RlmtSend\n")); + return -1; // temporarily do not send out RLMT frames +#if 0 + return(SkY2Xmit(pMessage, pAC->dev[PortNr])); SkY2Xmit needs device +#endif +} + +/***************************************************************************** + * + * SkY2AllocateResources - Allocates all required resources for Yukon2 + * + * Description: + * This function allocates all memory needed for the Yukon2. + * It maps also RX buffers to the LETables and initializes the + * status list element table. + * + * Returns: + * SK_TRUE, if all resources could be allocated and setup succeeded + * SK_FALSE, if an error + */ +SK_BOOL SkY2AllocateResources ( +SK_AC *pAC) /* pointer to adapter control context */ +{ + int CurrMac; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("==> SkY2AllocateResources\n")); + + /* + ** Initialize the packet queue variables first + */ + for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) { + InitPacketQueues(pAC, CurrMac); + } + + /* + ** Get sufficient memory for the LETables + */ + if (!AllocateAndInitLETables(pAC)) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR, + ("No memory for LETable.\n")); + return(SK_FALSE); + } + + /* + ** Allocate and intialize memory for both RX and TX + ** packet and fragment buffers. On an error, free + ** previously allocated LETable memory and quit. + */ + if (!AllocatePacketBuffersYukon2(pAC)) { + FreeLETables(pAC); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR, + ("No memory for Packetbuffers.\n")); + return(SK_FALSE); + } + + /* + ** Rx and Tx LE tables will be initialized in SkGeOpen() + ** + ** It might be that the TX timer is not started. Therefore + ** it is initialized here -> to be more investigated! + */ + SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10)); + SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable); + + pAC->MaxUnusedRxLeWorking = MAX_UNUSED_RX_LE_WORKING; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("<== SkY2AllocateResources\n")); + + return (SK_TRUE); +} + +/***************************************************************************** + * + * SkY2FreeResources - Frees previously allocated resources of Yukon2 + * + * Description: + * This function frees all previously allocated memory of the Yukon2. + * + * Returns: N/A + */ +void SkY2FreeResources ( +SK_AC *pAC) /* pointer to adapter control context */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> SkY2FreeResources\n")); + + FreeLETables(pAC); + FreePacketBuffers(pAC); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== SkY2FreeResources\n")); +} + +/***************************************************************************** + * + * SkY2AllocateRxBuffers - Allocates the receive buffers for a port + * + * Description: + * This function allocated all the RX buffers of the Yukon2. + * + * Returns: N/A + */ +void SkY2AllocateRxBuffers ( +SK_AC *pAC, /* pointer to adapter control context */ +SK_IOC IoC, /* I/O control context */ +int Port) /* port index of RX */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("==> SkY2AllocateRxBuffers (Port %c)\n", Port)); + + FillReceiveTableYukon2(pAC, IoC, Port); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("<== SkY2AllocateRxBuffers\n")); +} + +/***************************************************************************** + * + * SkY2FreeRxBuffers - Free's all allocates RX buffers of + * + * Description: + * This function frees all RX buffers of the Yukon2 for a single port + * + * Returns: N/A + */ +void SkY2FreeRxBuffers ( +SK_AC *pAC, /* pointer to adapter control context */ +SK_IOC IoC, /* I/O control context */ +int Port) /* port index of RX */ +{ + SK_PACKET *pSkPacket; + unsigned long Flags; /* for POP/PUSH macros */ + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> SkY2FreeRxBuffers (Port %c)\n", Port)); + + if (pAC->RxPort[Port].ReceivePacketTable != NULL) { + POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket); + while (pSkPacket != NULL) { + if ((pSkPacket->pFrag) != NULL) { + pci_unmap_page(pAC->PciDev, + (dma_addr_t) pSkPacket->pFrag->pPhys, + pSkPacket->pFrag->FragLen - 2, + PCI_DMA_FROMDEVICE); + + DEV_KFREE_SKB_ANY(pSkPacket->pMBuf); + pSkPacket->pMBuf = NULL; + pSkPacket->pFrag->pPhys = (SK_U64) 0; + pSkPacket->pFrag->pVirt = NULL; + } + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); + POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== SkY2FreeRxBuffers\n")); +} + +/***************************************************************************** + * + * SkY2FreeTxBuffers - Free's any currently maintained Tx buffer + * + * Description: + * This function frees the TX buffers of the Yukon2 for a single port + * which might be in use by a transmit action + * + * Returns: N/A + */ +void SkY2FreeTxBuffers ( +SK_AC *pAC, /* pointer to adapter control context */ +SK_IOC IoC, /* I/O control context */ +int Port) /* port index of TX */ +{ + SK_PACKET *pSkPacket; + SK_FRAG *pSkFrag; + unsigned long Flags; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> SkY2FreeTxBuffers (Port %c)\n", Port)); + + if (pAC->TxPort[Port][0].TransmitPacketTable != NULL) { + POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket); + while (pSkPacket != NULL) { + if ((pSkFrag = pSkPacket->pFrag) != NULL) { + UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port); + } + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket); + POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket); + } +#if USE_SYNC_TX_QUEUE + POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket); + while (pSkPacket != NULL) { + if ((pSkFrag = pSkPacket->pFrag) != NULL) { + UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port); + } + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket); + POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket); + } +#endif + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== SkY2FreeTxBuffers\n")); +} + +/***************************************************************************** + * + * SkY2Isr - handle a receive IRQ for all yukon2 cards + * + * Description: + * This function is called when a receive IRQ is set. (only for yukon2) + * HandleReceives does the deferred processing of all outstanding + * interrupt operations. + * + * Returns: N/A + */ +SkIsrRetVar SkY2Isr ( +int irq, /* the irq we have received (might be shared!) */ +void *dev_id, /* current device id */ +struct pt_regs *ptregs) /* not used by our driver */ +{ + struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + SK_U32 IntSrc; + unsigned long Flags; +#ifndef CONFIG_SK98LIN_NAPI + SK_BOOL handledStatLE = SK_FALSE; +#else + SK_BOOL SetIntMask = SK_FALSE; +#endif + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("==> SkY2Isr\n")); + + SK_IN32(pAC->IoBase, B0_Y2_SP_ISRC2, &IntSrc); + + + if ((IntSrc == 0) && (!pNet->NetConsoleMode)){ + SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("No Interrupt\n ==> SkY2Isr\n")); + return; + } + +#ifdef Y2_RECOVERY + if (pNet->InRecover) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Already in recover\n ==> SkY2Isr\n")); + SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2); + return; + } +#endif + +#ifdef CONFIG_SK98LIN_NAPI + if (netif_rx_schedule_prep(pAC->dev[0])) { + pAC->GIni.GIValIrqMask &= ~(Y2_IS_STAT_BMU); + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + SetIntMask = SK_TRUE; + __netif_rx_schedule(pAC->dev[0]); + } + + if (netif_rx_schedule_prep(pAC->dev[1])) { + if (!SetIntMask) { + pAC->GIni.GIValIrqMask &= ~(Y2_IS_STAT_BMU); + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + } + __netif_rx_schedule(pAC->dev[1]); + } +#else + handledStatLE = HandleStatusLEs(pAC); +#endif + + /* + ** Check for Special Interrupts + */ + if ((IntSrc & ~Y2_IS_STAT_BMU) || pAC->CheckQueue || pNet->TimerExpired) { + pAC->CheckQueue = SK_FALSE; + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + + SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); + + SkEventDispatcher(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + } + + /* Speed enhancement for a2 chipsets */ + if (HW_FEATURE(pAC, HWF_WA_DEV_42)) { + spin_lock_irqsave(&pAC->SetPutIndexLock, Flags); + SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET); + SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), &pAC->RxPort[0].RxLET); + spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags); + } + + /* + ** Reenable interrupts and signal end of ISR + */ + SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2); + + /* + ** Stop and restart TX timer in case a Status LE was handled + */ +#ifndef CONFIG_SK98LIN_NAPI + if ((HW_FEATURE(pAC, HWF_WA_DEV_43_418)) && (handledStatLE)) { + + SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_STOP); + SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_START); + } +#endif + + if (!(IS_Q_EMPTY(&(pAC->TxPort[0][TX_PRIO_LOW].TxAQ_waiting)))) { + GiveTxBufferToHw(pAC, pAC->IoBase, 0); + } + if (!(IS_Q_EMPTY(&(pAC->TxPort[1][TX_PRIO_LOW].TxAQ_waiting)))) { + GiveTxBufferToHw(pAC, pAC->IoBase, 1); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("<== SkY2Isr\n")); + + return; +} /* SkY2Isr */ + +/***************************************************************************** + * + * SkY2Xmit - Linux frame transmit function for Yukon2 + * + * Description: + * The system calls this function to send frames onto the wire. + * It puts the frame in the tx descriptor ring. If the ring is + * full then, the 'tbusy' flag is set. + * + * Returns: + * 0, if everything is ok + * !=0, on error + * + * WARNING: + * returning 1 in 'tbusy' case caused system crashes (double + * allocated skb's) !!! + */ +int SkY2Xmit( +struct sk_buff *skb, /* socket buffer to be sent */ +struct SK_NET_DEVICE *dev) /* via which device? */ +{ + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + SK_U8 FragIdx = 0; + SK_PACKET *pSkPacket; +#if 0 /* uboot */ + SK_FRAG *PrevFrag; + SK_FRAG *CurrFrag; +#endif + SK_PKT_QUEUE *pWorkQueue; /* corresponding TX queue */ + SK_PKT_QUEUE *pWaitQueue; + SK_PKT_QUEUE *pFreeQueue; + SK_LE_TABLE *pLETab; /* corresponding LETable */ +#if 0 /* uboot */ + skb_frag_t *sk_frag; +#endif + SK_U64 PhysAddr; + unsigned long Flags; + unsigned int Port; +#if 0 /* uboot */ + int CurrFragCtr; +#endif + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("==> SkY2Xmit\n")); + + /* + ** Get port and return if no free packet is available + */ + Port = (pAC->RlmtNets == 2) ? pNet->PortNr : pAC->ActivePort; + if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free))) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("Not free packets available for send\n")); + return 1; /* zero bytes sent! */ + } + + /* + ** Put any new packet to be sent in the waiting queue and + ** handle also any possible fragment of that packet. + */ + pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working); + pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting); + pFreeQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free); + pLETab = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET); + +#if 0 /* uboot */ + /* + ** Normal send operations require only one fragment, because + ** only one sk_buff data area is passed. + ** In contradiction to this, scatter-gather (zerocopy) send + ** operations might pass one or more additional fragments + ** where each fragment needs a separate fragment info packet. + */ + if (((skb_shinfo(skb)->nr_frags + 1) * MAX_FRAG_OVERHEAD) > + NUM_FREE_LE_IN_TABLE(pLETab)) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("Not enough LE available for send\n")); + return 1; /* zero bytes sent! */ + } + + if ((skb_shinfo(skb)->nr_frags + 1) > MAX_NUM_FRAGS) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("Not even one fragment available for send\n")); + return 1; /* zero bytes sent! */ + } +#endif + + /* + ** Get first packet from free packet queue + */ + POP_FIRST_PKT_FROM_QUEUE(pFreeQueue, pSkPacket); + if(pSkPacket == NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("Could not obtain free packet used for xmit\n")); + return 1; /* zero bytes sent! */ + } + + pSkPacket->pFrag = &(pSkPacket->FragArray[FragIdx]); + + /* + ** map the sk_buff to be available for the adapter + */ +#if 0 /* uboot */ + PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, + virt_to_page(skb->data), + ((unsigned long) skb->data & ~PAGE_MASK), + skb_headlen(skb), + PCI_DMA_TODEVICE); +#else + PhysAddr = (SK_U64)(SK_U32)skb->data; +#endif + pSkPacket->pMBuf = skb; + pSkPacket->pFrag->pPhys = PhysAddr; + pSkPacket->pFrag->FragLen = skb->len;/*skb_headlen(skb);*/ + pSkPacket->pFrag->pNext = NULL; /* initial has no next default */ + pSkPacket->NumFrags = 2; /*skb_shinfo(skb)->nr_frags + 1;*/ + #if 0 + pSkPacket->NumFrags = skb_shinfo(skb)->nr_frags + 1; + + PrevFrag = pSkPacket->pFrag; + + /* + ** Each scatter-gather fragment need to be mapped... + */ + for ( CurrFragCtr = 0; + CurrFragCtr < skb_shinfo(skb)->nr_frags; + CurrFragCtr++) { + FragIdx++; + sk_frag = &skb_shinfo(skb)->frags[CurrFragCtr]; + CurrFrag = &(pSkPacket->FragArray[FragIdx]); + + /* + ** map the sk_buff to be available for the adapter + */ + PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, + sk_frag->page, + sk_frag->page_offset, + sk_frag->size, + PCI_DMA_TODEVICE); + + CurrFrag->pPhys = PhysAddr; + CurrFrag->FragLen = sk_frag->size; + CurrFrag->pNext = NULL; + + /* + ** Add the new fragment to the list of fragments + */ + PrevFrag->pNext = CurrFrag; + PrevFrag = CurrFrag; + } +#endif + /* + ** Add packet to waiting packets queue + */ + PUSH_PKT_AS_LAST_IN_QUEUE(pWaitQueue, pSkPacket); + GiveTxBufferToHw(pAC, pAC->IoBase, Port); +#if 0 /* uboot */ + dev->trans_start = jiffies; +#endif + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("<== SkY2Xmit(return 0)\n")); + return (0); +} /* SkY2Xmit */ + +#ifdef CONFIG_SK98LIN_NAPI +/***************************************************************************** + * + * SkY2Poll - NAPI Rx polling callback for Yukon2 chipsets + * + * Description: + * Called by the Linux system in case NAPI polling is activated + * + * Returns + * The number of work data still to be handled + * + * Notes + * The slowpath lock needs to be set because HW accesses may + * interfere with slowpath events (e.g. TWSI) + */ +int SkY2Poll( +struct net_device *dev, /* device that needs to be polled */ +int *budget) /* how many budget do we have? */ +{ + SK_AC *pAC = ((DEV_NET*)(dev->priv))->pAC; + int WorkToDo = min(*budget, dev->quota); + int WorkDone = 0; + SK_BOOL handledStatLE = SK_FALSE; + unsigned long Flags; + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + handledStatLE = HandleStatusLEs(pAC, &WorkDone, WorkToDo); + + *budget -= WorkDone; + dev->quota -= WorkDone; + + if(WorkDone < WorkToDo) { + netif_rx_complete(dev); + pAC->GIni.GIValIrqMask |= (Y2_IS_STAT_BMU); + SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); + if ((HW_FEATURE(pAC, HWF_WA_DEV_43_418)) && (handledStatLE)) { + SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_STOP); + SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_START); + } + } + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + return (WorkDone >= WorkToDo); +} /* SkY2Poll */ +#endif + +/****************************************************************************** + * + * SkY2PortStop - stop a port on Yukon2 + * + * Description: + * This function stops a port of the Yukon2 chip. This stop + * stop needs to be performed in a specific order: + * + * a) Stop the Prefetch unit + * b) Stop the Port (MAC, PHY etc.) + * + * Returns: N/A + */ +void SkY2PortStop( +SK_AC *pAC, /* adapter control context */ +SK_IOC IoC, /* I/O control context (address of adapter registers) */ +int Port, /* port to stop (MAC_1 + n) */ +int Dir, /* StopDirection (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */ +int RstMode) /* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> SkY2PortStop (Port %c)\n", 'A' + Port)); + + /* + ** Stop the HW + */ + SkGeStopPort(pAC, IoC, Port, Dir, RstMode); + + /* + ** Move any TX packet from work queues into the free queue again + ** and initialize the TX LETable variables + */ + SkY2FreeTxBuffers(pAC, pAC->IoBase, Port); + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Bmu.RxTx.TcpWp = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Bmu.RxTx.MssValue = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.BufHighAddr = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Done = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Put = 0; + // pAC->GIni.GP[Port].PState = SK_PRT_STOP; + + /* + ** Move any RX packet from work queue into the waiting queue + ** and initialize the RX LETable variables + */ + SkY2FreeRxBuffers(pAC, pAC->IoBase, Port); + pAC->RxPort[Port].RxLET.BufHighAddr = 0; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== SkY2PortStop()\n")); +} + +/****************************************************************************** + * + * SkY2PortStart - start a port on Yukon2 + * + * Description: + * This function starts a port of the Yukon2 chip. This start + * action needs to be performed in a specific order: + * + * a) Initialize the LET indices (PUT/GET to 0) + * b) Initialize the LET in HW (enables also prefetch unit) + * c) Move all RX buffers from waiting queue to working queue + * which involves also setting up of RX list elements + * d) Initialize the FIFO settings of Yukon2 (Watermark etc.) + * e) Initialize the Port (MAC, PHY etc.) + * f) Initialize the MC addresses + * + * Returns: N/A + */ +void SkY2PortStart( +SK_AC *pAC, /* adapter control context */ +SK_IOC IoC, /* I/O control context (address of adapter registers) */ +int Port) /* port to start */ +{ + // SK_GEPORT *pPrt = &pAC->GIni.GP[Port]; + SK_HWLE *pLE; + SK_U32 DWord; + SK_U32 PrefetchReg; /* register for Put index */ + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> SkY2PortStart (Port %c)\n", 'A' + Port)); + + /* + ** Initialize the LET indices + */ + pAC->RxPort[Port].RxLET.Done = 0; + pAC->RxPort[Port].RxLET.Put = 0; + pAC->RxPort[Port].RxLET.HwPut = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Done = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Put = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxALET.HwPut = 0; + if (HW_SYNC_TX_SUPPORTED(pAC)) { + pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.Done = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.Put = 0; + pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.HwPut = 0; + } + + if (HW_FEATURE(pAC, HWF_WA_DEV_420)) { + /* + ** It might be that we have to limit the RX buffers + ** effectively passed to HW. Initialize the start + ** value in that case... + */ + NbrRxBuffersInHW = 0; + } + + /* + ** TODO on dual net adapters we need to check if + ** StatusLETable need to be set... + ** + ** pAC->StatusLETable.Done = 0; + ** pAC->StatusLETable.Put = 0; + ** pAC->StatusLETable.HwPut = 0; + ** SkGeY2InitPrefetchUnit(pAC, pAC->IoBase, Q_ST, &pAC->StatusLETable); + */ + + /* + ** Initialize the LET in HW (enables also prefetch unit) + */ + SkGeY2InitPrefetchUnit(pAC, IoC,(Port == 0) ? Q_R1 : Q_R2, + &pAC->RxPort[Port].RxLET); + SkGeY2InitPrefetchUnit( pAC, IoC,(Port == 0) ? Q_XA1 : Q_XA2, + &pAC->TxPort[Port][TX_PRIO_LOW].TxALET); + if (HW_SYNC_TX_SUPPORTED(pAC)) { + SkGeY2InitPrefetchUnit( pAC, IoC, (Port == 0) ? Q_XS1 : Q_XS2, + &pAC->TxPort[Port][TX_PRIO_HIGH].TxSLET); + } + + + /* + ** Using new values for the watermarks and the timer for + ** low latency optimization + */ + if (pAC->LowLatency) { + SK_OUT8(IoC, STAT_FIFO_WM, 1); + SK_OUT8(IoC, STAT_FIFO_ISR_WM, 1); + SK_OUT32(IoC, STAT_LEV_TIMER_INI, 50); + SK_OUT32(IoC, STAT_ISR_TIMER_INI, 10); + } + + + /* + ** Initialize the Port (MAC, PHY etc.) + */ + if (SkGeInitPort(pAC, IoC, Port)) { + if (Port == 0) { + printk("%s: SkGeInitPort A failed.\n",pAC->dev[0]->name); + } else { + printk("%s: SkGeInitPort B failed.\n",pAC->dev[1]->name); + } + } + + if (IS_GMAC(pAC)) { + /* disable Rx GMAC FIFO Flush Mode */ + SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8) GMF_RX_F_FL_OFF); + } + + /* + ** Initialize the MC addresses + */ + SkAddrMcUpdate(pAC,IoC, Port); + + SkMacRxTxEnable(pAC, IoC,Port); + + if (pAC->RxPort[Port].UseRxCsum) { + SkGeRxCsum(pAC, IoC, Port, SK_TRUE); + + GET_RX_LE(pLE, &pAC->RxPort[Port].RxLET); + RXLE_SET_STACS1(pLE, pAC->CsOfs1); + RXLE_SET_STACS2(pLE, pAC->CsOfs2); + RXLE_SET_CTRL(pLE, 0); + + RXLE_SET_OPC(pLE, OP_TCPSTART | HW_OWNER); + FLUSH_OPC(pLE); + if (Port == 0) { + PrefetchReg=Y2_PREF_Q_ADDR(Q_R1,PREF_UNIT_PUT_IDX_REG); + } else { + PrefetchReg=Y2_PREF_Q_ADDR(Q_R2,PREF_UNIT_PUT_IDX_REG); + } + DWord = GET_PUT_IDX(&pAC->RxPort[Port].RxLET); + SK_OUT32(IoC, PrefetchReg, DWord); + UPDATE_HWPUT_IDX(&pAC->RxPort[Port].RxLET); + } + + pAC->GIni.GP[Port].PState = SK_PRT_RUN; + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== SkY2PortStart()\n")); +} + +/****************************************************************************** + * + * Local Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * InitPacketQueues - initialize SW settings of packet queues + * + * Description: + * This function will initialize the packet queues for a port. + * + * Returns: N/A + */ +static void InitPacketQueues( +SK_AC *pAC, /* pointer to adapter control context */ +int Port) /* index of port to be initialized */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("==> InitPacketQueues(Port %c)\n", 'A' + Port)); + + pAC->RxPort[Port].RxQ_working.pHead = NULL; + pAC->RxPort[Port].RxQ_working.pTail = NULL; + spin_lock_init(&pAC->RxPort[Port].RxQ_working.QueueLock); + + pAC->RxPort[Port].RxQ_waiting.pHead = NULL; + pAC->RxPort[Port].RxQ_waiting.pTail = NULL; + spin_lock_init(&pAC->RxPort[Port].RxQ_waiting.QueueLock); + + pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pHead = NULL; + pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pTail = NULL; + spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.QueueLock); + + pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pHead = NULL; + pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pTail = NULL; + spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.QueueLock); + + pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pHead = NULL; + pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pTail = NULL; + spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.QueueLock); + +#if USE_SYNC_TX_QUEUE + pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pHead = NULL; + pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pTail = NULL; + spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.QueueLock); + + pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pHead = NULL; + pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pTail = NULL; + spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.QueueLock); +#endif + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("<== InitPacketQueues(Port %c)\n", 'A' + Port)); +} /* InitPacketQueues */ + +/***************************************************************************** + * + * GiveTxBufferToHw - commits a previously allocated DMA area to HW + * + * Description: + * This functions gives transmit buffers to HW. If no list elements + * are available the buffers will be queued. + * + * Notes: + * This function can run only once in a system at one time. + * + * Returns: N/A + */ +static void GiveTxBufferToHw( +SK_AC *pAC, /* pointer to adapter control context */ +SK_IOC IoC, /* I/O control context (address of registers) */ +int Port) /* port index for which the buffer is used */ +{ + SK_HWLE *pLE; + SK_PACKET *pSkPacket; + SK_FRAG *pFrag; + SK_PKT_QUEUE *pWorkQueue; /* corresponding TX queue */ + SK_PKT_QUEUE *pWaitQueue; + SK_LE_TABLE *pLETab; /* corresponding LETable */ + SK_BOOL SetOpcodePacketFlag; + SK_U32 HighAddress; + SK_U32 LowAddress; +#if 0 //uboot + SK_U16 TcpSumStart; + SK_U16 TcpSumWrite; +#endif + SK_U8 OpCode; + SK_U8 Ctrl; + unsigned long Flags; + unsigned long LockFlag; +#if 0 //uboot + int Protocol; +#endif +#ifdef NETIF_F_TSO + SK_U16 Mss; + int TcpOptLen; + int IpTcpLen; +#endif + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("==> GiveTxBufferToHw\n")); + + if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) { + return; + } + + spin_lock_irqsave(&pAC->TxQueueLock, LockFlag); + + /* + ** Initialize queue settings + */ + pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working); + pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting); + pLETab = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET); + + POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket); + while (pSkPacket != NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("\tWe have a packet to send %p\n", pSkPacket)); + + /* + ** the first frag of a packet gets opcode OP_PACKET + */ + SetOpcodePacketFlag = SK_TRUE; + pFrag = pSkPacket->pFrag; + + /* + ** fill list elements with data from fragments + */ + while (pFrag != NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("\tGet LE\n")); +#ifdef NETIF_F_TSO + Mss = skb_shinfo(pSkPacket->pMBuf)->tso_size; + if (Mss) { + TcpOptLen = ((pSkPacket->pMBuf->h.th->doff - 5) * 4); + IpTcpLen = ((pSkPacket->pMBuf->nh.iph->ihl * 4) + + sizeof(struct tcphdr)); + Mss += (TcpOptLen + IpTcpLen + C_LEN_ETHERMAC_HEADER); + } + if (pLETab->Bmu.RxTx.MssValue != Mss) { + pLETab->Bmu.RxTx.MssValue = Mss; + /* Take a new LE for TSO from the table */ + GET_TX_LE(pLE, pLETab); + +#if 0 + if(pSkPacket->VlanId) { + TXLE_SET_OPC(pLE, OP_LRGLENVLAN | HW_OWNER); + TXLE_SET_VLAN(pLE, pSkPacket->VlanId); + pSkPacket->VlanId = 0; + Ctrl |= INS_VLAN; + } else { +#endif + TXLE_SET_OPC(pLE, OP_LRGLEN | HW_OWNER); +#if 0 + } +#endif + /* set maximum segment size for new packet */ + TXLE_SET_LSLEN(pLE, pLETab->Bmu.RxTx.MssValue); + FLUSH_OPC(pLE) ; + } +#endif + GET_TX_LE(pLE, pLETab); + Ctrl = 0; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("\tGot empty LE %p idx %d\n", pLE, GET_PUT_IDX(pLETab))); + + SK_DBG_DUMP_TX_LE(pLE); + + LowAddress = (SK_U32) (pFrag->pPhys & 0xffffffff); + HighAddress = (SK_U32) (pFrag->pPhys >> 32); + + if (HighAddress != pLETab->BufHighAddr) { + /* set opcode high part of the address in one LE */ + OpCode = OP_ADDR64 | HW_OWNER; + + /* Set now the 32 high bits of the address */ + TXLE_SET_ADDR( pLE, HighAddress); + + /* Set the opcode into the LE */ + TXLE_SET_OPC(pLE, OpCode); + + /* Flush the LE to memory */ + FLUSH_OPC(pLE); + + /* remember the HighAddress we gave to the Hardware */ + pLETab->BufHighAddr = HighAddress; + + /* get a new LE because we filled one with high address */ + GET_TX_LE(pLE, pLETab); + } + + +#if 0 /* uboot */ + /* + ** TCP checksum offload + */ + if ((pSkPacket->pMBuf->ip_summed == CHECKSUM_HW) && + (SetOpcodePacketFlag == SK_TRUE)) { + Protocol = ((SK_U8)pSkPacket->pMBuf->data[C_OFFSET_IPPROTO] & 0xff); + /* if (Protocol & C_PROTO_ID_IP) { Ctrl = 0; } */ + if (Protocol & C_PROTO_ID_TCP) { + Ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; + /* TCP Checksum Calculation Start Position */ + TcpSumStart = C_LEN_ETHERMAC_HEADER + IP_HDR_LEN; + /* TCP Checksum Write Position */ + TcpSumWrite = TcpSumStart + TCP_CSUM_OFFS; + } else { + Ctrl = UDPTCP | CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; + /* TCP Checksum Calculation Start Position */ + TcpSumStart = ETHER_MAC_HDR_LEN + IP_HDR_LEN; + /* UDP Checksum Write Position */ + TcpSumWrite = TcpSumStart + UDP_CSUM_OFFS; + } + + if ((Ctrl) && (pLETab->Bmu.RxTx.TcpWp != TcpSumWrite)) { + /* Update the last value of the write position */ + pLETab->Bmu.RxTx.TcpWp = TcpSumWrite; + + /* Set the Lock field for this LE: */ + /* Checksum calculation for one packet only */ + TXLE_SET_LCKCS(pLE, 1); + + /* Set the start position for checksum. */ + TXLE_SET_STACS(pLE, TcpSumStart); + + /* Set the position where the checksum will be writen */ + TXLE_SET_WRICS(pLE, TcpSumWrite); + + /* Set the initial value for checksum */ + /* PseudoHeader CS passed from Linux -> 0! */ + TXLE_SET_INICS(pLE, 0); + + /* Set the opcode for tcp checksum */ + TXLE_SET_OPC(pLE, OP_TCPLISW | HW_OWNER); + + /* Flush the LE to memory */ + FLUSH_OPC(pLE); + + /* get a new LE because we filled one with data for checksum */ + GET_TX_LE(pLE, pLETab); + } + } /* end TCP offload handling */ + +#endif + + TXLE_SET_ADDR(pLE, LowAddress); + TXLE_SET_LEN(pLE, pFrag->FragLen); + + if (SetOpcodePacketFlag){ +#ifdef NETIF_F_TSO + if (Mss) { + OpCode = OP_LARGESEND | HW_OWNER; + } else { +#endif + OpCode = OP_PACKET| HW_OWNER; +#ifdef NETIF_F_TSO + } +#endif + SetOpcodePacketFlag = SK_FALSE; + } else { + /* Follow packet in a sequence has always OP_BUFFER */ + OpCode = OP_BUFFER | HW_OWNER; + } + + /* Check if the low address is near the upper limit. */ + CHECK_LOW_ADDRESS(pLETab->BufHighAddr, LowAddress, pFrag->FragLen); + + pFrag = pFrag->pNext; + if (pFrag == NULL) { + /* mark last fragment */ + Ctrl |= EOP; + } + TXLE_SET_CTRL(pLE, Ctrl); + TXLE_SET_OPC(pLE, OpCode); + FLUSH_OPC(pLE); + + SK_DBG_DUMP_TX_LE(pLE); + } + + /* + ** Remember next LE for tx complete + */ + pSkPacket->NextLE = GET_PUT_IDX(pLETab); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("\tNext LE for pkt %p is %d\n", pSkPacket, pSkPacket->NextLE)); + + /* + ** Add packet to working packets queue + */ + PUSH_PKT_AS_LAST_IN_QUEUE(pWorkQueue, pSkPacket); + + /* + ** give transmit start command + */ + if (HW_FEATURE(pAC, HWF_WA_DEV_42)) { + spin_lock(&pAC->SetPutIndexLock); + SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET); + spin_unlock(&pAC->SetPutIndexLock); + } else { + /* write put index */ + if (Port == 0) { + SK_OUT32(pAC->IoBase, + Y2_PREF_Q_ADDR(Q_XA1,PREF_UNIT_PUT_IDX_REG), + GET_PUT_IDX(&pAC->TxPort[0][0].TxALET)); + UPDATE_HWPUT_IDX(&pAC->TxPort[0][0].TxALET); + } else { + SK_OUT32(pAC->IoBase, + Y2_PREF_Q_ADDR(Q_XA2, PREF_UNIT_PUT_IDX_REG), + GET_PUT_IDX(&pAC->TxPort[1][0].TxALET)); + UPDATE_HWPUT_IDX(&pAC->TxPort[1][0].TxALET); + } + } + + if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) { + break; /* get out of while */ + } + POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket); + } /* while (pSkPacket != NULL) */ + + spin_unlock_irqrestore(&pAC->TxQueueLock, LockFlag); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("<== GiveTxBufferToHw\n")); + return; +} /* GiveTxBufferToHw */ + +/*********************************************************************** + * + * GiveRxBufferToHw - commits a previously allocated DMA area to HW + * + * Description: + * This functions gives receive buffers to HW. If no list elements + * are available the buffers will be queued. + * + * Notes: + * This function can run only once in a system at one time. + * + * Returns: N/A + */ +static void GiveRxBufferToHw( +SK_AC *pAC, /* pointer to adapter control context */ +SK_IOC IoC, /* I/O control context (address of registers) */ +int Port, /* port index for which the buffer is used */ +SK_PACKET *pPacket) /* receive buffer(s) */ +{ + SK_HWLE *pLE; + SK_LE_TABLE *pLETab; + SK_BOOL Done = SK_FALSE; /* at least on LE changed? */ + SK_U32 LowAddress; + SK_U32 HighAddress; + SK_U32 PrefetchReg; /* register for Put index */ + unsigned NumFree; + unsigned Required; + unsigned long Flags; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("==> GiveRxBufferToHw(Port %c, Packet %p)\n", 'A' + Port, pPacket)); + + pLETab = &pAC->RxPort[Port].RxLET; + + if (Port == 0) { + PrefetchReg = Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG); + } else { + PrefetchReg = Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG); + } + + if (pPacket != NULL) { + /* + ** For the time being, we have only one packet passed + ** to this function which might be changed in future! + */ + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket); + } + + /* + ** now pPacket contains the very first waiting packet + */ + POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket); + while (pPacket != NULL) { + if (HW_FEATURE(pAC, HWF_WA_DEV_420)) { + if (NbrRxBuffersInHW >= MAX_NBR_RX_BUFFERS_IN_HW) { + PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<== GiveRxBufferToHw()\n")); + return; + } + NbrRxBuffersInHW++; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("Try to add packet %p\n", pPacket)); + + /* + ** Check whether we have enough listelements: + ** + ** we have to take into account that each fragment + ** may need an additional list element for the high + ** part of the address here I simplified it by + ** using MAX_FRAG_OVERHEAD maybe it's worth to split + ** this constant for Rx and Tx or to calculate the + ** real number of needed LE's + */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("\tNum %d Put %d Done %d Free %d %d\n", + pLETab->Num, pLETab->Put, pLETab->Done, + NUM_FREE_LE_IN_TABLE(pLETab), + (NUM_FREE_LE_IN_TABLE(pLETab)))); + + Required = pPacket->NumFrags + MAX_FRAG_OVERHEAD; + NumFree = NUM_FREE_LE_IN_TABLE(pLETab); + if (NumFree) { + NumFree--; + } + + if (Required > NumFree ) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("\tOut of LEs have %d need %d\n", + NumFree, Required)); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("\tWaitQueue starts with packet %p\n", pPacket)); + PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket); + if (Done) { + /* + ** write Put index to BMU or Polling Unit and make the LE's + ** available for the hardware + */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("\tWrite new Put Idx\n")); + + SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab)); + UPDATE_HWPUT_IDX(pLETab); + } + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<== GiveRxBufferToHw()\n")); + return; + } else { + if (!AllocAndMapRxBuffer(pAC, pPacket, Port)) { + /* + ** Failure while allocating sk_buff might + ** be due to temporary short of resources + ** Maybe next time buffers are available. + ** Until this, the packet remains in the + ** RX waiting queue... + */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("Failed to allocate Rx buffer\n")); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("WaitQueue starts with packet %p\n", pPacket)); + PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket); + if (Done) { + /* + ** write Put index to BMU or Polling + ** Unit and make the LE's + ** available for the hardware + */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("\tWrite new Put Idx\n")); + + SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab)); + UPDATE_HWPUT_IDX(pLETab); + } + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<== GiveRxBufferToHw()\n")); + return; + } + } + Done = SK_TRUE; + + LowAddress = (SK_U32) (pPacket->pFrag->pPhys & 0xffffffff); + HighAddress = (SK_U32) (pPacket->pFrag->pPhys >> 32); + if (HighAddress != pLETab->BufHighAddr) { + /* get a new LE for high address */ + GET_RX_LE(pLE, pLETab); + + /* Set now the 32 high bits of the address */ + RXLE_SET_ADDR(pLE, HighAddress); + + /* Set the control bits of the address */ + RXLE_SET_CTRL(pLE, 0); + + /* Set the opcode into the LE */ + RXLE_SET_OPC(pLE, (OP_ADDR64 | HW_OWNER)); + + /* Flush the LE to memory */ + FLUSH_OPC(pLE); + + /* remember the HighAddress we gave to the Hardware */ + pLETab->BufHighAddr = HighAddress; + } + + /* + ** Fill data into listelement + */ + GET_RX_LE(pLE, pLETab); + RXLE_SET_ADDR(pLE, LowAddress); + RXLE_SET_LEN(pLE, pPacket->pFrag->FragLen); + RXLE_SET_CTRL(pLE, 0); + RXLE_SET_OPC(pLE, (OP_PACKET | HW_OWNER)); + FLUSH_OPC(pLE); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("=== LE filled\n")); + + SK_DBG_DUMP_RX_LE(pLE); + + /* + ** Remember next LE for rx complete + */ + pPacket->NextLE = GET_PUT_IDX(pLETab); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("\tPackets Next LE is %d\n", pPacket->NextLE)); + + /* + ** Add packet to working receive buffer queue and get + ** any next packet out of the waiting queue + */ + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_working, pPacket); + if (IS_Q_EMPTY(&(pAC->RxPort[Port].RxQ_waiting))) { + break; /* get out of while processing */ + } + POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("\tWaitQueue is empty\n")); + + if (Done) { + /* + ** write Put index to BMU or Polling Unit and make the LE's + ** available for the hardware + */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("\tWrite new Put Idx\n")); + + /* Speed enhancement for a2 chipsets */ + if (HW_FEATURE(pAC, HWF_WA_DEV_42)) { + spin_lock_irqsave(&pAC->SetPutIndexLock, Flags); + SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), pLETab); + spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags); + } else { + /* write put index */ + if (Port == 0) { + SK_OUT32(IoC, + Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG), + GET_PUT_IDX(pLETab)); + } else { + SK_OUT32(IoC, + Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG), + GET_PUT_IDX(pLETab)); + } + + /* Update put index */ + UPDATE_HWPUT_IDX(pLETab); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<== GiveRxBufferToHw()\n")); +} /* GiveRxBufferToHw */ + +/*********************************************************************** + * + * FillReceiveTableYukon2 - map any waiting RX buffers to HW + * + * Description: + * If the list element table contains more empty elements than + * specified this function tries to refill them. + * + * Notes: + * This function can run only once per port in a system at one time. + * + * Returns: N/A + */ +void FillReceiveTableYukon2( +SK_AC *pAC, /* pointer to adapter control context */ +SK_IOC IoC, /* I/O control context */ +int Port) /* port index of RX */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("==> FillReceiveTableYukon2 (Port %c)\n", 'A' + Port)); + + if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) > + pAC->MaxUnusedRxLeWorking) { + + /* + ** Give alle waiting receive buffers down + ** The queue holds all RX packets that + ** need a fresh allocation of the sk_buff. + */ + if (pAC->RxPort[Port].RxQ_waiting.pHead != NULL) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("Waiting queue is not empty -> give it to HW")); + GiveRxBufferToHw(pAC, IoC, Port, NULL); + } + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<== FillReceiveTableYukon2 ()\n")); +} /* FillReceiveTableYukon2 */ + +/****************************************************************************** + * + * + * HandleReceives - will pass any ready RX packet to kernel + * + * Description: + * This functions handles a received packet. It checks wether it is + * valid, updates the receive list element table and gives the receive + * buffer to Linux + * + * Notes: + * This function can run only once per port at one time in the system. + * + * Returns: N/A + */ +static SK_BOOL HandleReceives( +SK_AC *pAC, /* adapter control context */ +int Port, /* port on which a packet has been received */ +SK_U16 Len, /* number of bytes which was actually received */ +SK_U32 FrameStatus, /* MAC frame status word */ +SK_U16 Tcp1, /* first hw checksum */ +SK_U16 Tcp2, /* second hw checksum */ +SK_U32 Tist, /* timestamp */ +SK_U16 Vlan) /* Vlan Id */ +{ + + SK_PACKET *pSkPacket; + SK_LE_TABLE *pLETab; + SK_MBUF *pRlmtMbuf; /* buffer for giving RLMT frame */ + struct sk_buff *pMsg; /* ptr to message holding frame */ +#ifdef __ia64__ + struct sk_buff *pNewMsg; /* used when IP aligning */ +#endif + +#ifdef CONFIG_SK98LIN_NAPI + SK_BOOL SlowPathLock = SK_FALSE; +#else + SK_BOOL SlowPathLock = SK_TRUE; +#endif + SK_BOOL IsGoodPkt; + SK_BOOL IsBc; + SK_BOOL IsMc; + SK_EVPARA EvPara; /* an event parameter union */ + SK_I16 LenToFree; /* must be signed integer */ + + unsigned long Flags; /* for spin lock */ + unsigned int RlmtNotifier; +#if 0 /* uboot */ + unsigned short Type; + int IpFrameLength; +#endif + int FrameLength; /* total length of recvd frame */ + int NumBytes; +#if 0 + int Result; +#endif + int Offset = 0; + +#ifdef Y2_SYNC_CHECK +#if 0 + SK_U16 MyTcp; +#endif +#endif + + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("==> HandleReceives (Port %c)\n", 'A' + Port)); + + /* + ** initialize vars for selected port + */ + pLETab = &pAC->RxPort[Port].RxLET; + + /* + ** check whether we want to receive this packet + */ + SK_Y2_RXSTAT_CHECK_PKT(Len, FrameStatus, IsGoodPkt); + + /* + ** Remember length to free (in case of RxBuffer overruns; + ** unlikely, but might happen once in a while) + */ + LenToFree = (SK_I16) Len; + + /* + ** maybe we put these two checks into the SK_RXDESC_CHECK_PKT macro too + */ + if (Len > pAC->RxPort[Port].RxBufSize) { + IsGoodPkt = SK_FALSE; + } + + /* + ** take first receive buffer out of working queue + */ + POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket); + if (pSkPacket == NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_ERROR, + ("Packet not available. NULL pointer.\n")); + return(SK_TRUE); + } + + if (HW_FEATURE(pAC, HWF_WA_DEV_420)) { + NbrRxBuffersInHW--; + } + + /* + ** Verify the received length of the frame! Note that having + ** multiple RxBuffers being aware of one single receive packet + ** (one packet spread over multiple RxBuffers) is not supported + ** by this driver! + */ + if ((Len > pAC->RxPort[Port].RxBufSize) || + (Len > (SK_U16) pSkPacket->PacketLen)) { + IsGoodPkt = SK_FALSE; + } + + /* + ** Reset own bit in LE's between old and new Done index + ** This is not really necessary but makes debugging easier + */ + CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE); + + /* + ** Free the list elements for new Rx buffers + */ + SET_DONE_INDEX(pLETab, pSkPacket->NextLE); + pMsg = pSkPacket->pMBuf; + FrameLength = Len; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("Received frame of length %d on port %d\n",FrameLength, Port)); + + if (!IsGoodPkt) { + printf("\npacket is not good\n"); + /* + ** release the DMA mapping + */ + pci_dma_sync_single(pAC->PciDev, + (dma_addr_t) pSkPacket->pFrag->pPhys, + pSkPacket->pFrag->FragLen, + PCI_DMA_FROMDEVICE); + + DEV_KFREE_SKB_ANY(pSkPacket->pMBuf); + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<== HandleReceives (Port %c)\n", 'A' + Port)); + + /* + ** Sanity check for RxBuffer overruns... + */ + LenToFree = LenToFree - (pSkPacket->pFrag->FragLen); + while (LenToFree > 0) { + POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket); + if (HW_FEATURE(pAC, HWF_WA_DEV_420)) { + NbrRxBuffersInHW--; + } + CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE); + SET_DONE_INDEX(pLETab, pSkPacket->NextLE); + pci_dma_sync_single(pAC->PciDev, + (dma_addr_t) pSkPacket->pFrag->pPhys, + pSkPacket->pFrag->FragLen, + PCI_DMA_FROMDEVICE); + + DEV_KFREE_SKB_ANY(pSkPacket->pMBuf); + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); + LenToFree = LenToFree - ((SK_I16)(pSkPacket->pFrag->FragLen)); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("<==HandleReceives (Port %c) drop faulty len pkt(2)\n",'A'+Port)); + } + return(SK_TRUE); + } else { + /* + ** Release the DMA mapping + */ + pci_unmap_single(pAC->PciDev, + pSkPacket->pFrag->pPhys, + pAC->RxPort[Port].RxBufSize, + PCI_DMA_FROMDEVICE); +#if 0 /* uboot */ + skb_put(pMsg, FrameLength); /* set message len */ + pMsg->ip_summed = CHECKSUM_NONE; /* initial default */ +#ifdef Y2_SYNC_CHECK + pAC->FramesWithoutSyncCheck++; + if (pAC->FramesWithoutSyncCheck > Y2_RESYNC_WATERMARK) { + if ((Tcp1 != 1) || (Tcp2 != 0)) { + pAC->FramesWithoutSyncCheck = 0; + MyTcp = (SK_U16) SkCsCalculateChecksum( + &pMsg->data[14], + FrameLength - 14); + if (MyTcp != Tcp1) { + /* Queue port reset event */ + SkLocalEventQueue(pAC, SKGE_DRV, + SK_DRV_RECOVER,Port,-1,SK_FALSE); + } + } + } +#endif +#endif + + + +#if 0 /* uboot */ + pMsg->ip_summed = CHECKSUM_NONE; /* initial default */ + if (pAC->RxPort[Port].UseRxCsum) { + Type = ntohs(*((short*)&pMsg->data[12])); + if (Type == 0x800) { + *((char *)&(IpFrameLength)) = pMsg->data[16]; + *(((char *)&(IpFrameLength))+1) = pMsg->data[17]; + IpFrameLength = ntohs(IpFrameLength); + HeaderLength = FrameLength - IpFrameLength; + if (HeaderLength == 0xe) { + Result = + SkCsGetReceiveInfo(pAC,&pMsg->data[14],Tcp1,Tcp2, Port); + if ((Result == SKCS_STATUS_IP_FRAGMENT) || + (Result == SKCS_STATUS_IP_CSUM_OK) || + (Result == SKCS_STATUS_TCP_CSUM_OK) || + (Result == SKCS_STATUS_UDP_CSUM_OK)) { + pMsg->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR) || + (Result == SKCS_STATUS_UDP_CSUM_ERROR) || + (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) || + (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) || + (Result == SKCS_STATUS_IP_CSUM_ERROR)) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("skge: CRC error. Frame dropped!\n")); + DEV_KFREE_SKB_ANY(pMsg); + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); + SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_RX_PROGRESS, + ("<==HandleReceives(Port %c)\n",'A'+Port)); + return(SK_TRUE); + } else { + pMsg->ip_summed = CHECKSUM_NONE; + } + } /* end if (HeaderLength == valid) */ + } /* end if (Type == 0x800) -> IP frame */ + } /* end if (pRxPort->UseRxCsum) */ + +#endif + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS,("V")); + RlmtNotifier = SK_RLMT_RX_PROTOCOL; + + IsBc = (FrameStatus & GMR_FS_BC) ? SK_TRUE : SK_FALSE; + SK_RLMT_PRE_LOOKAHEAD(pAC,Port,FrameLength, + IsBc,&Offset,&NumBytes); + if (NumBytes != 0) { + IsMc = (FrameStatus & GMR_FS_MC) ? SK_TRUE : SK_FALSE; + SK_RLMT_LOOKAHEAD(pAC,Port,&pMsg->data[Offset], + IsBc,IsMc,&RlmtNotifier); + } + + if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) { + SK_DBG_MSG(NULL,SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS,("W")); + if ((Port == pAC->ActivePort)||(pAC->RlmtNets == 2)) { + /* send up only frames from active port */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS,("U")); +#ifdef xDEBUG + DumpMsg(pMsg, "Rx"); +#endif + SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, + FrameLength, Port); + +#ifdef __ia64__ + pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC); + skb_reserve(pNewMsg, 2); /* to align IP */ + SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len); + pNewMsg->ip_summed = pMsg->ip_summed; + skb_put(pNewMsg, pMsg->len); + DEV_KFREE_SKB_ANY(pMsg); + pMsg = pNewMsg; +#endif +#if 0 /* uboot */ + pMsg->dev = pAC->dev[Port]; + pMsg->protocol = eth_type_trans(pMsg, + pAC->dev[Port]); + netif_rx(pMsg); + pAC->dev[Port]->last_rx = jiffies; +#else /* Marvell - uboot */ + + NetReceive(pMsg->data, FrameLength); + DEV_KFREE_SKB_ANY(pMsg); + +#endif + + + } else { /* drop frame */ + SK_DBG_MSG(NULL,SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS,("D")); + DEV_KFREE_SKB_ANY(pMsg); + } + } else { /* This is an RLMT-packet! */ + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS,("R")); + pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC, + pAC->IoBase, FrameLength); + if (pRlmtMbuf != NULL) { + pRlmtMbuf->pNext = NULL; + pRlmtMbuf->Length = FrameLength; + pRlmtMbuf->PortIdx = Port; + EvPara.pParaPtr = pRlmtMbuf; + SK_MEMCPY((char*)(pRlmtMbuf->pData), + (char*)(pMsg->data),FrameLength); + + if (SlowPathLock == SK_TRUE) { + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + SkEventQueue(pAC, SKGE_RLMT, + SK_RLMT_PACKET_RECEIVED, + EvPara); + pAC->CheckQueue = SK_TRUE; + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + } else { + SkEventQueue(pAC, SKGE_RLMT, + SK_RLMT_PACKET_RECEIVED, + EvPara); + pAC->CheckQueue = SK_TRUE; + } + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS,("Q")); + } +#if 0 /* uboot */ + if (pAC->dev[Port]->flags & (IFF_PROMISC | IFF_ALLMULTI)) { +#ifdef __ia64__ + pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC); + skb_reserve(pNewMsg, 2); /* to align IP */ + SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len); + pNewMsg->ip_summed = pMsg->ip_summed; + pNewMsg->len = pMsg->len; + DEV_KFREE_SKB_ANY(pMsg); + pMsg = pNewMsg; +#endif + pMsg->dev = pAC->dev[Port]; + pMsg->protocol = eth_type_trans(pMsg,pAC->dev[Port]); + netif_rx(pMsg); + pAC->dev[Port]->last_rx = jiffies; + } else +#else /* Marvell - uboot*/ + if (1) { + NetReceive(pMsg->data, FrameLength); + DEV_KFREE_SKB_ANY(pMsg); + + } else +#endif + { + + DEV_KFREE_SKB_ANY(pMsg); + } + } /* if packet for rlmt */ + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket); + } /* end if-else (IsGoodPkt) */ + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<== HandleReceives (Port %c)\n", 'A' + Port)); + return(SK_TRUE); + +} /* HandleReceives */ + +/*********************************************************************** + * + * CheckForSendComplete - Frees any freeable Tx bufffer + * + * Description: + * This function checks the queues of a port for completed send + * packets and returns these packets back to the OS. + * + * Notes: + * This function can run simultaneously for both ports if + * the OS function OSReturnPacket() can handle this, + * + * Such a send complete does not mean, that the packet is really + * out on the wire. We just know that the adapter has copied it + * into its internal memory and the buffer in the systems memory + * is no longer needed. + * + * Returns: N/A + */ +static void CheckForSendComplete( +SK_AC *pAC, /* pointer to adapter control context */ +SK_IOC IoC, /* I/O control context */ +int Port, /* port index */ +SK_PKT_QUEUE *pPQ, /* tx working packet queue to check */ +SK_LE_TABLE *pLETab, /* corresponding list element table */ +unsigned int Done) /* done index reported for this LET */ +{ + SK_PACKET *pSkPacket; + SK_PKT_QUEUE SendCmplPktQ = { NULL, NULL /* , SPIN_LOCK_UNLOCKED uboot */}; + SK_BOOL DoWakeQueue = SK_FALSE; + unsigned long Flags; + unsigned Put; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("==> CheckForSendComplete(Port %c)\n", 'A' + Port)); + + /* + ** Reset own bit in LE's between old and new Done index + ** This is not really necessairy but makes debugging easier + */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Clear Own Bits in TxTable from %d to %d\n", + pLETab->Done, (Done == 0) ? + NUM_LE_IN_TABLE(pLETab) : + (Done - 1))); + + spin_lock_irqsave(&(pPQ->QueueLock), Flags); + + CLEAR_LE_OWN_FROM_DONE_TO(pLETab, Done); + + Put = GET_PUT_IDX(pLETab); + + /* + ** Check whether some packets have been completed + */ + PLAIN_POP_FIRST_PKT_FROM_QUEUE(pPQ, pSkPacket); + while (pSkPacket != NULL) { + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Check Completion of Tx packet %p\n", pSkPacket)); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Put %d NewDone %d NextLe of Packet %d\n", Put, Done, + pSkPacket->NextLE)); + + if ((Put > Done) && + ((pSkPacket->NextLE > Put) || (pSkPacket->NextLE <= Done))) { + PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Packet finished (a)\n")); + } else if ((Done > Put) && + (pSkPacket->NextLE > Put) && (pSkPacket->NextLE <= Done)) { + PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Packet finished (b)\n")); + } else if ((Done == TXA_MAX_LE-1) && (Put == 0) && (pSkPacket->NextLE == 0)) { + PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Packet finished (b)\n")); + DoWakeQueue = SK_TRUE; + } else if (Done == Put) { + /* all packets have been sent */ + PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Packet finished (c)\n")); + } else { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("Packet not yet finished\n")); + PLAIN_PUSH_PKT_AS_FIRST_IN_QUEUE(pPQ, pSkPacket); + break; + } + PLAIN_POP_FIRST_PKT_FROM_QUEUE(pPQ, pSkPacket); + } + spin_unlock_irqrestore(&(pPQ->QueueLock), Flags); + + /* + ** Set new done index in list element table + */ + SET_DONE_INDEX(pLETab, Done); + + /* + ** All TX packets that are send complete should be added to + ** the free queue again for new sents to come + */ + pSkPacket = SendCmplPktQ.pHead; + while (pSkPacket != NULL) { + while (pSkPacket->pFrag != NULL) { + pci_unmap_page(pAC->PciDev, + (dma_addr_t) pSkPacket->pFrag->pPhys, + pSkPacket->pFrag->FragLen, + PCI_DMA_FROMDEVICE); + pSkPacket->pFrag = pSkPacket->pFrag->pNext; + } + + DEV_KFREE_SKB_ANY(pSkPacket->pMBuf); + pSkPacket->pMBuf = NULL; + pSkPacket = pSkPacket->pNext; /* get next packet */ + } + + /* + ** Append the available TX packets back to free queue + */ + if (SendCmplPktQ.pHead != NULL) { + spin_lock_irqsave(&(pAC->TxPort[Port][0].TxQ_free.QueueLock), Flags); + if (pAC->TxPort[Port][0].TxQ_free.pTail != NULL) { + pAC->TxPort[Port][0].TxQ_free.pTail->pNext = SendCmplPktQ.pHead; + pAC->TxPort[Port][0].TxQ_free.pTail = SendCmplPktQ.pTail; + if (pAC->TxPort[Port][0].TxQ_free.pHead->pNext == NULL) { + netif_wake_queue(pAC->dev[Port]); + } + } else { + pAC->TxPort[Port][0].TxQ_free.pHead = SendCmplPktQ.pHead; + pAC->TxPort[Port][0].TxQ_free.pTail = SendCmplPktQ.pTail; + netif_wake_queue(pAC->dev[Port]); + } + if (Done == Put) { + netif_wake_queue(pAC->dev[Port]); + } + if (DoWakeQueue) { + netif_wake_queue(pAC->dev[Port]); + DoWakeQueue = SK_FALSE; + } + spin_unlock_irqrestore(&pAC->TxPort[Port][0].TxQ_free.QueueLock, Flags); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("<== CheckForSendComplete()\n")); + + return; +} /* CheckForSendComplete */ + +/***************************************************************************** + * + * UnmapAndFreeTxPktBuffer + * + * Description: + * This function free any allocated space of receive buffers + * + * Arguments: + * pAC - A pointer to the adapter context struct. + * + */ +static void UnmapAndFreeTxPktBuffer( +SK_AC *pAC, /* pointer to adapter context */ +SK_PACKET *pSkPacket, /* pointer to port struct of ring to fill */ +int TxPort) /* TX port index */ +{ + SK_FRAG *pFrag = pSkPacket->pFrag; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("--> UnmapAndFreeTxPktBuffer\n")); + + while (pFrag != NULL) { + pci_unmap_page(pAC->PciDev, + (dma_addr_t) pFrag->pPhys, + pFrag->FragLen, + PCI_DMA_FROMDEVICE); + pFrag = pFrag->pNext; + } + + DEV_KFREE_SKB_ANY(pSkPacket->pMBuf); + pSkPacket->pMBuf = NULL; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, + ("<-- UnmapAndFreeTxPktBuffer\n")); +} + +/***************************************************************************** + * + * HandleStatusLEs + * + * Description: + * This function checks for any new status LEs that may have been + * received. Those status LEs may either be Rx or Tx ones. + * + * Returns: N/A + */ +static SK_BOOL HandleStatusLEs( +#ifdef CONFIG_SK98LIN_NAPI +SK_AC *pAC, /* pointer to adapter context */ +int *WorkDone, /* Done counter needed for NAPI */ +int WorkToDo) /* ToDo counter for NAPI */ +#else +SK_AC *pAC) /* pointer to adapter context */ +#endif +{ + int DoneTxA[SK_MAX_MACS]; + int DoneTxS[SK_MAX_MACS]; + int Port; + SK_BOOL handledStatLE = SK_FALSE; + SK_BOOL NewDone = SK_FALSE; + SK_HWLE *pLE; + SK_U16 HighVal; + SK_U32 LowVal; + SK_U8 OpCode; + int i; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("==> HandleStatusLEs\n")); + + do { + if (OWN_OF_FIRST_LE(&pAC->StatusLETable) != HW_OWNER) + break; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Check next Own Bit of ST-LE[%d]: 0x%li \n", + (pAC->StatusLETable.Done + 1) % NUM_LE_IN_TABLE(&pAC->StatusLETable), + OWN_OF_FIRST_LE(&pAC->StatusLETable))); + + while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER) { + GET_ST_LE(pLE, &pAC->StatusLETable); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Working on finished status LE[%d]:\n", + GET_DONE_INDEX(&pAC->StatusLETable))); + SK_DBG_DUMP_ST_LE(pLE); + handledStatLE = SK_TRUE; + OpCode = STLE_GET_OPC(pLE) & ~HW_OWNER; + Port = STLE_GET_LINK(pLE); + +#ifdef USE_TIST_FOR_RESET + if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) { + /* do we just have a tist LE ? */ + if ((OpCode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) { + for (i = 0; i < pAC->GIni.GIMacsFound; i++) { + if (SK_PORT_WAITING_FOR_ANY_TIST(pAC, i)) { + /* if a port is waiting for any tist it is done */ + SK_CLR_STATE_FOR_PORT(pAC, i); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Got any Tist on port %c (now 0x%X!!!)\n", + 'A' + i, pAC->AdapterResetState)); + } + if (SK_PORT_WAITING_FOR_SPECIFIC_TIST(pAC, i)) { + Y2_GET_TIST_LOW_VAL(pAC->IoBase, &LowVal); + if ((pAC->MinTistHi != pAC->GIni.GITimeStampCnt) || + (pAC->MinTistLo < LowVal)) { + /* time is up now */ + SK_CLR_STATE_FOR_PORT(pAC, i); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Got expected Tist on Port %c (now 0x%X)!!!\n", + 'A' + i, pAC->AdapterResetState)); +#ifdef Y2_SYNC_CHECK + pAC->FramesWithoutSyncCheck = + Y2_RESYNC_WATERMARK; +#endif + } else { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Got Tist %l:%l on Port %c but still waiting\n", + pAC->GIni.GITimeStampCnt, pAC->MinTistLo, + 'A' + i)); + } + } + } +#ifndef Y2_RECOVERY + if (!SK_ADAPTER_WAITING_FOR_TIST(pAC)) { + /* nobody needs tist anymore - turn it off */ + Y2_DISABLE_TIST(pAC->IoBase); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Turn off Tist !!!\n")); + } +#endif + } else if (OpCode == OP_TXINDEXLE) { + /* + * change OpCode to notify the folowing code + * to ignore the done index from this LE + * unfortunately tist LEs will be generated only + * for RxStat LEs + * so in order to get a safe Done index for a + * port currently waiting for a tist we have to + * get the done index directly from the BMU + */ + OpCode = OP_MOD_TXINDEX; + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Mark unusable TX_INDEX LE!!!\n")); + } else { + if (SK_PORT_WAITING_FOR_TIST(pAC, Port)) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Ignore LE 0x%X on Port %c!!!\n", + OpCode, 'A' + Port)); + OpCode = OP_MOD_LE; +#ifdef Y2_LE_CHECK + /* mark entries invalid */ + pAC->LastOpc = 0xFF; + pAC->LastPort = 3; +#endif + } + } + } /* if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) */ +#endif + + + + + +#ifdef Y2_LE_CHECK + if (pAC->LastOpc != 0xFF) { + /* last opc is valid + * check if current opcode follows last opcode + */ + if ((((OpCode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) && (pAC->LastOpc != OP_RXSTAT)) || + (((OpCode & OP_RXCHKS) == OP_RXCHKS) && (pAC->LastOpc != OP_RXTIMESTAMP)) || + ((OpCode == OP_RXSTAT) && (pAC->LastOpc != OP_RXCHKS))) { + + /* opcode sequence broken + * current LE is invalid + */ + + if (pAC->LastOpc == OP_RXTIMESTAMP) { + /* force invalid checksum */ + pLE->St.StUn.StRxTCPCSum.RxTCPSum1 = 1; + pLE->St.StUn.StRxTCPCSum.RxTCPSum2 = 0; + OpCode = pAC->LastOpc = OP_RXCHKS; + Port = pAC->LastPort; + } else if (pAC->LastOpc == OP_RXCHKS) { + /* force invalid frame */ + Port = pAC->LastPort; + pLE->St.Stat.BufLen = 64; + pLE->St.StUn.StRxStatWord = GMR_FS_CRC_ERR; + OpCode = pAC->LastOpc = OP_RXSTAT; +#ifdef Y2_SYNC_CHECK + /* force rx sync check */ + pAC->FramesWithoutSyncCheck = Y2_RESYNC_WATERMARK; +#endif + } else if (pAC->LastOpc == OP_RXSTAT) { + /* create dont care tist */ + pLE->St.StUn.StRxTimeStamp = 0; + OpCode = pAC->LastOpc = OP_RXTIMESTAMP; + /* dont know the port yet */ + } else { +#ifdef DEBUG + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Unknown LastOpc %X for Timestamp on port %c.\n", + pAC->LastOpc, Port)); +#endif + } + } + } +#endif + + switch (OpCode) { + case OP_RXSTAT: +#ifdef Y2_RECOVERY + pAC->LastOpc = OP_RXSTAT; +#endif + /* + ** This is always the last Status LE belonging + ** to a received packet -> handle it... + */ + if ((Port != 0) && (Port != 1)) { + /* Unknown port */ + panic("sk98lin: Unknown port %d\n", + Port); + } + + HandleReceives( + pAC, + Port, + STLE_GET_LEN(pLE), + STLE_GET_FRSTATUS(pLE), + pAC->StatusLETable.Bmu.Stat.TcpSum1, + pAC->StatusLETable.Bmu.Stat.TcpSum2, + pAC->StatusLETable.Bmu.Stat.RxTimeStamp, + pAC->StatusLETable.Bmu.Stat.VlanId); +#ifdef CONFIG_SK98LIN_NAPI + if (*WorkDone >= WorkToDo) { + break; + } + (*WorkDone)++; +#endif + break; + case OP_RXVLAN: + /* this value will be used for next RXSTAT */ + pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE); + break; + case OP_RXTIMEVLAN: + /* this value will be used for next RXSTAT */ + pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE); + /* fall through */ + case OP_RXTIMESTAMP: + /* this value will be used for next RXSTAT */ + pAC->StatusLETable.Bmu.Stat.RxTimeStamp = STLE_GET_TIST(pLE); +#ifdef Y2_RECOVERY + pAC->LastOpc = OP_RXTIMESTAMP; + pAC->LastPort = Port; +#endif + break; + case OP_RXCHKSVLAN: + /* this value will be used for next RXSTAT */ + pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE); + /* fall through */ + case OP_RXCHKS: + /* this value will be used for next RXSTAT */ + pAC->StatusLETable.Bmu.Stat.TcpSum1 = STLE_GET_TCP1(pLE); + pAC->StatusLETable.Bmu.Stat.TcpSum2 = STLE_GET_TCP2(pLE); +#ifdef Y2_RECOVERY + pAC->LastPort = Port; + pAC->LastOpc = OP_RXCHKS; +#endif + break; + case OP_RSS_HASH: + /* this value will be used for next RXSTAT */ +#if 0 + pAC->StatusLETable.Bmu.Stat.RssHashValue = STLE_GET_RSS(pLE); +#endif + break; + case OP_TXINDEXLE: + /* + ** :;:; TODO + ** it would be possible to check for which queues + ** the index has been changed and call + ** CheckForSendComplete() only for such queues + */ + STLE_GET_DONE_IDX(pLE,LowVal,HighVal); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("LowVal: 0x%x HighVal: 0x%x\n", LowVal, HighVal)); + + /* + ** It would be possible to check whether we really + ** need the values for second port or sync queue, + ** but I think checking whether we need them is + ** more expensive than the calculation + */ + DoneTxA[0] = STLE_GET_DONE_IDX_TXA1(LowVal,HighVal); + DoneTxS[0] = STLE_GET_DONE_IDX_TXS1(LowVal,HighVal); + DoneTxA[1] = STLE_GET_DONE_IDX_TXA2(LowVal,HighVal); + DoneTxS[1] = STLE_GET_DONE_IDX_TXS2(LowVal,HighVal); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("DoneTxa1 0x%x DoneTxS1: 0x%x DoneTxa2 0x%x DoneTxS2: 0x%x\n", + DoneTxA[0], DoneTxS[0], DoneTxA[1], DoneTxS[1])); + + NewDone = SK_TRUE; + break; +#ifdef USE_TIST_FOR_RESET + case OP_MOD_TXINDEX: + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("OP_MOD_TXINDEX\n")); + SK_IN16(pAC->IoBase, Q_ADDR(Q_XA1, Q_DONE), &DoneTxA[0]); + if (pAC->GIni.GIMacsFound > 1) { + SK_IN16(pAC->IoBase, Q_ADDR(Q_XA2, Q_DONE), &DoneTxA[1]); + } + NewDone = SK_TRUE; + break; + case OP_MOD_LE: + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP, + ("Ignore marked LE on port in Reset\n")); + break; +#endif + + default: + /* + ** Have to handle the illegal Opcode in Status LE + */ + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Unexpected OpCode\n")); + break; + } + +#ifdef Y2_RECOVERY + OpCode = STLE_GET_OPC(pLE) & ~HW_OWNER; + STLE_SET_OPC(pLE, OpCode); +#else + /* + ** Reset own bit we have to do this in order to detect a overflow + */ + STLE_SET_OPC(pLE, SW_OWNER); +#endif + } /* while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER) */ + + /* + ** Now handle any new transmit complete + */ + if (NewDone) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Done Index for Tx BMU has been changed\n")); + for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) { + /* + ** Do we have a new Done idx ? + */ + if (DoneTxA[Port] != GET_DONE_INDEX(&pAC->TxPort[Port][0].TxALET)) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Check TxA%d\n", Port + 1)); + CheckForSendComplete(pAC, pAC->IoBase, Port, + &(pAC->TxPort[Port][0].TxAQ_working), + &pAC->TxPort[Port][0].TxALET, + DoneTxA[Port]); + } else { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("No changes for TxA%d\n", Port + 1)); + } +#if USE_SYNC_TX_QUEUE + if (HW_SYNC_TX_SUPPORTED(pAC)) { + /* + ** Do we have a new Done idx ? + */ + if (DoneTxS[Port] != + GET_DONE_INDEX(&pAC->TxPort[Port][0].TxSLET)) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("Check TxS%d\n", Port)); + CheckForSendComplete(pAC, pAC->IoBase, Port, + &(pAC->TxPort[Port][0].TxSQ_working), + &pAC->TxPort[Port][0].TxSLET, + DoneTxS[Port]); + } else { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_INT_SRC, + ("No changes for TxS%d\n", Port)); + } + } +#endif + } + } + NewDone = SK_FALSE; + + /* + ** Check whether we have to refill our RX table + */ + if (HW_FEATURE(pAC, HWF_WA_DEV_420)) { + if (NbrRxBuffersInHW < MAX_NBR_RX_BUFFERS_IN_HW) { + for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Check for refill of RxBuffers on Port %c\n", 'A' + Port)); + FillReceiveTableYukon2(pAC, pAC->IoBase, Port); + } + } + } else { + for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, + ("Check for refill of RxBuffers on Port %c\n", 'A' + Port)); + if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) >= 64) { + FillReceiveTableYukon2(pAC, pAC->IoBase, Port); + } + } + } +#ifdef CONFIG_SK98LIN_NAPI + if (*WorkDone >= WorkToDo) { + break; + } +#endif + } while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER); + + /* + ** Clear status BMU + */ + if (handledStatLE) + SK_OUT32(pAC->IoBase, STAT_CTRL, SC_STAT_CLR_IRQ); + + return(handledStatLE); +} /* HandleStatusLEs */ + +/***************************************************************************** + * + * AllocateAndInitLETables - allocate memory for the LETable and init + * + * Description: + * This function will allocate space for the LETable and will also + * initialize them. The size of the tables must have been specified + * before. + * + * Arguments: + * pAC - A pointer to the adapter context struct. + * + * Returns: + * SK_TRUE - all LETables initialized + * SK_FALSE - failed + */ +static SK_BOOL AllocateAndInitLETables( +SK_AC *pAC) /* pointer to adapter context */ +{ + char *pVirtMemAddr; + dma_addr_t pPhysMemAddr = 0; + SK_U32 CurrMac; + unsigned Size; + unsigned Aligned; + unsigned Alignment; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("==> AllocateAndInitLETables()\n")); + + /* + ** Determine how much memory we need with respect to alignment + */ + Alignment = MAX_LEN_OF_LE_TAB; + Size = 0; + for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) { + SK_ALIGN_SIZE(LE_TAB_SIZE(RX_MAX_LE), Alignment, Aligned); + Size += Aligned; + SK_ALIGN_SIZE(LE_TAB_SIZE(TXA_MAX_LE), Alignment, Aligned); + Size += Aligned; + SK_ALIGN_SIZE(LE_TAB_SIZE(TXS_MAX_LE), Alignment, Aligned); + Size += Aligned; + } + SK_ALIGN_SIZE(LE_TAB_SIZE(ST_MAX_LE), Alignment, Aligned); + Size += Aligned; + Size += Alignment; + pAC->SizeOfAlignedLETables = Size; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("Need %08x bytes in total\n", Size)); + + /* + ** Allocate the memory + */ + pVirtMemAddr = pci_alloc_consistent(pAC->PciDev, Size, &pPhysMemAddr); + if (pVirtMemAddr == NULL) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, + SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR, + ("AllocateAndInitLETables: kernel malloc failed!\n")); + return (SK_FALSE); + } + + /* + ** Initialize the memory + */ + SK_MEMSET(pVirtMemAddr, 0, Size); + ALIGN_ADDR(pVirtMemAddr, Alignment); /* Macro defined in skgew.h */ + +#if 1 /* Marvell - uboot */ + ALIGN_ADDR(pPhysMemAddr, Alignment); +#endif + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("Virtual address of LETab is %8p!\n", pVirtMemAddr)); + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("Phys address of LETab is %8p!\n", (void *) pPhysMemAddr)); + + for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) { + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("RxLeTable for Port %c", 'A' + CurrMac)); + SkGeY2InitSingleLETable( + pAC, + &pAC->RxPort[CurrMac].RxLET, + RX_MAX_LE, + pVirtMemAddr, + (SK_U32) (pPhysMemAddr & 0xffffffff), + (SK_U32) (((SK_U64) pPhysMemAddr) >> 32)); + + SK_ALIGN_SIZE(LE_TAB_SIZE(RX_MAX_LE), Alignment, Aligned); + pVirtMemAddr += Aligned; + pPhysMemAddr += Aligned; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("TxALeTable for Port %c", 'A' + CurrMac)); + SkGeY2InitSingleLETable( + pAC, + &pAC->TxPort[CurrMac][0].TxALET, + TXA_MAX_LE, + pVirtMemAddr, + (SK_U32) (pPhysMemAddr & 0xffffffff), + (SK_U32) (((SK_U64) pPhysMemAddr) >> 32)); + + SK_ALIGN_SIZE(LE_TAB_SIZE(TXA_MAX_LE), Alignment, Aligned); + pVirtMemAddr += Aligned; + pPhysMemAddr += Aligned; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("TxSLeTable for Port %c", 'A' + CurrMac)); + SkGeY2InitSingleLETable( + pAC, + &pAC->TxPort[CurrMac][0].TxSLET, + TXS_MAX_LE, + pVirtMemAddr, + (SK_U32) (pPhysMemAddr & 0xffffffff), + (SK_U32) (((SK_U64) pPhysMemAddr) >> 32)); + + SK_ALIGN_SIZE(LE_TAB_SIZE(TXS_MAX_LE), Alignment, Aligned); + pVirtMemAddr += Aligned; + pPhysMemAddr += Aligned; + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,("StLeTable")); + + SkGeY2InitSingleLETable( + pAC, + &pAC->StatusLETable, + ST_MAX_LE, + pVirtMemAddr, + (SK_U32) (pPhysMemAddr & 0xffffffff), + (SK_U32) (((SK_U64) pPhysMemAddr) >> 32)); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("<== AllocateAndInitLETables(OK)\n")); + return(SK_TRUE); +} /* AllocateAndInitLETables */ + +/***************************************************************************** + * + * AllocatePacketBuffersYukon2 - allocate packet and fragment buffers + * + * Description: + * This function will allocate space for the packets and fragments + * + * Arguments: + * pAC - A pointer to the adapter context struct. + * + * Returns: + * SK_TRUE - Memory was allocated correctly + * SK_FALSE - An error occured + */ +static SK_BOOL AllocatePacketBuffersYukon2( +SK_AC *pAC) /* pointer to adapter context */ +{ + SK_PACKET *pRxPacket; + SK_PACKET *pTxPacket; + SK_U32 CurrBuff; + SK_U32 CurrMac; + unsigned long Flags; /* needed for POP/PUSH functions */ + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("==> AllocatePacketBuffersYukon2()")); + + for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) { + /* + ** Allocate RX packet space, initialize the packets and + ** add them to the RX waiting queue. Waiting queue means + ** that packet and fragment are initialized, but no sk_buff + ** has been assigned to it yet. + */ + pAC->RxPort[CurrMac].ReceivePacketTable = + kmalloc((RX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)), GFP_KERNEL); + + if (pAC->RxPort[CurrMac].ReceivePacketTable == NULL) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR, + ("AllocatePacketBuffersYukon2: no mem RxPkts (port %i)",CurrMac)); + break; + } else { + SK_MEMSET(pAC->RxPort[CurrMac].ReceivePacketTable, 0, + (RX_MAX_NBR_BUFFERS * sizeof(SK_PACKET))); + + pRxPacket = pAC->RxPort[CurrMac].ReceivePacketTable; + + for (CurrBuff=0;CurrBuffpFrag = &(pRxPacket->FragArray[0]); + pRxPacket->NumFrags = 1; + PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[CurrMac].RxQ_waiting, pRxPacket); + pRxPacket++; + } + } + + /* + ** Allocate TX packet space, initialize the packets and + ** add them to the TX free queue. Free queue means that + ** packet is available and initialized, but no fragment + ** has been assigned to it. (Must be done at TX side) + */ + pAC->TxPort[CurrMac][0].TransmitPacketTable = + kmalloc((TX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)), GFP_KERNEL); + + if (pAC->TxPort[CurrMac][0].TransmitPacketTable == NULL) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR, + ("AllocatePacketBuffersYukon2: no mem TxPkts (port %i)",CurrMac)); + kfree(pAC->RxPort[CurrMac].ReceivePacketTable); + return(SK_FALSE); + } else { + SK_MEMSET(pAC->TxPort[CurrMac][0].TransmitPacketTable, 0, + (TX_MAX_NBR_BUFFERS * sizeof(SK_PACKET))); + + pTxPacket = pAC->TxPort[CurrMac][0].TransmitPacketTable; + + for (CurrBuff=0;CurrBuffTxPort[CurrMac][0].TxQ_free, pTxPacket); + pTxPacket++; + } + } + } /* end for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) */ + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, + ("<== AllocatePacketBuffersYukon2 (OK)\n")); + return(SK_TRUE); + +} /* AllocatePacketBuffersYukon2 */ + +/***************************************************************************** + * + * FreeLETables - release allocated memory of LETables + * + * Description: + * This function will free all resources of the LETables + * + * Arguments: + * pAC - A pointer to the adapter context struct. + * + * Returns: N/A + */ +static void FreeLETables( +SK_AC *pAC) /* pointer to adapter control context */ +{ + dma_addr_t pPhysMemAddr; + char *pVirtMemAddr; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> FreeLETables()\n")); + + /* + ** The RxLETable is the first of all LET. + ** Therefore we can use its address for the input + ** of the free function. + */ + pVirtMemAddr = (char *) pAC->RxPort[0].RxLET.pLETab; + pPhysMemAddr = (((SK_U64) pAC->RxPort[0].RxLET.pPhyLETABHigh << (SK_U64) 32) | + ((SK_U64) pAC->RxPort[0].RxLET.pPhyLETABLow)); + + /* free continuous memory */ + pci_free_consistent(pAC->PciDev, pAC->SizeOfAlignedLETables, + pVirtMemAddr, pPhysMemAddr); + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== FreeLETables()\n")); +} /* FreeLETables */ + +/***************************************************************************** + * + * FreePacketBuffers - free's all packet buffers of an adapter + * + * Description: + * This function will free all previously allocated memory of the + * packet buffers. + * + * Arguments: + * pAC - A pointer to the adapter context struct. + * + * Returns: N/A + */ +static void FreePacketBuffers( +SK_AC *pAC) /* pointer to adapter control context */ +{ + int Port; + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("==> FreePacketBuffers()\n")); + + for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) { + kfree(pAC->RxPort[Port].ReceivePacketTable); + kfree(pAC->TxPort[Port][0].TransmitPacketTable); + } + + SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, + ("<== FreePacketBuffers()\n")); +} /* FreePacketBuffers */ + +/***************************************************************************** + * + * AllocAndMapRxBuffer - fill one buffer into the receive packet/fragment + * + * Description: + * The function allocates a new receive buffer and assigns it to the + * the passsed receive packet/fragment + * + * Returns: + * SK_TRUE - a buffer was allocated and assigned + * SK_FALSE - a buffer could not be added + */ +static SK_BOOL AllocAndMapRxBuffer( +SK_AC *pAC, /* pointer to the adapter control context */ +SK_PACKET *pSkPacket, /* pointer to packet that is to fill */ +int Port) /* port the packet belongs to */ +{ + struct sk_buff *pMsgBlock; /* pointer to a new message block */ + SK_U64 PhysAddr; /* physical address of a rx buffer */ + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("--> AllocAndMapRxBuffer (Port: %i)\n", Port)); + + pMsgBlock = alloc_skb(pAC->RxPort[Port].RxBufSize, GFP_ATOMIC); +#if 1 /*Marvell - uboot*/ + skb_reserve(pMsgBlock, 2); /* to align IP frames */ +#endif + if (pMsgBlock == NULL) { + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, + SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR, + ("%s: Allocation of rx buffer failed !\n", + pAC->dev[Port]->name)); + SK_PNMI_CNT_NO_RX_BUF(pAC, pAC->RxPort[Port].PortIndex); + return(SK_FALSE); + } + skb_reserve(pMsgBlock, 8); + +#if 0 /* uboot */ + PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, + virt_to_page(pMsgBlock->data), + ((unsigned long) pMsgBlock->data & + ~PAGE_MASK), + pAC->RxPort[Port].RxBufSize, + PCI_DMA_FROMDEVICE); +#else + PhysAddr = (SK_U64)(SK_U32)pMsgBlock->data; +#endif + + pSkPacket->pFrag->pVirt = pMsgBlock->data; + pSkPacket->pFrag->pPhys = PhysAddr; + pSkPacket->pFrag->FragLen = pAC->RxPort[Port].RxBufSize; /* for correct unmap */ + pSkPacket->pMBuf = pMsgBlock; + pSkPacket->PacketLen = pAC->RxPort[Port].RxBufSize; + + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS, + ("<-- AllocAndMapRxBuffer\n")); + + return (SK_TRUE); +} /* AllocAndMapRxBuffer */ + +/******************************************************************************* + * + * End of file + * + ******************************************************************************/ + +#endif diff --git a/drivers/sk98lin/sky2le.c b/drivers/sk98lin/sky2le.c new file mode 100644 index 0000000..3aaae2d --- /dev/null +++ b/drivers/sk98lin/sky2le.c @@ -0,0 +1,511 @@ +/***************************************************************************** + * + * Name: sky2le.c + * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.1.1.1 $ + * Date: $Date: 2008-12-15 11:39:21 $ + * Purpose: Functions for handling List Element Tables + * + *****************************************************************************/ + +/****************************************************************************** + * + * LICENSE: + * (C)Copyright 2002-2006 Marvell. + * + * 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. + * The information in this file is provided "AS IS" without warranty. + * /LICENSE + * + ******************************************************************************/ + +#include + +#ifdef CONFIG_SK98 + +#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) +static const char SysKonnectFileId[] = "@(#)" + "$Id: sky2le.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ (C) Marvell."; +#endif /* DEBUG || (!LINT && !SK_SLIM) */ + +/***************************************************************************** + * + * Description: + * + * This module contains the code necessary for handling List Elements. + * + * Supported Gigabit Ethernet Chipsets: + * Yukon-2 (PCI, PCI-X, PCI-Express) + * + * Include File Hierarchy: + * + * + *****************************************************************************/ +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +/* defines *******************************************************************/ +/* typedefs ******************************************************************/ +/* global variables **********************************************************/ +/* local variables ***********************************************************/ +/* function prototypes *******************************************************/ + +/***************************************************************************** + * + * SkGeY2InitSingleLETable() - initializes a list element table + * + * Description: + * This function will initialize the selected list element table. + * Should be called once during DriverInit. No InitLevel required. + * + * Arguments: + * pAC - pointer to the adapter context struct. + * pLETab - pointer to list element table structure + * NumLE - number of list elements in this table + * pVMem - virtual address of memory allocated for this LE table + * PMemLowAddr - physical address of memory to be used for the LE table + * PMemHighAddr + * + * Returns: + * nothing + */ +void SkGeY2InitSingleLETable( +SK_AC *pAC, /* pointer to adapter context */ +SK_LE_TABLE *pLETab, /* pointer to list element table to be initialized */ +unsigned int NumLE, /* number of list elements to be filled in tab */ +void *pVMem, /* virtual address of memory used for list elements */ +SK_U32 PMemLowAddr, /* physical addr of mem used for LE */ +SK_U32 PMemHighAddr) +{ + unsigned int i; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("==> SkGeY2InitSingleLETable()\n")); + +#ifdef DEBUG + if (NumLE != 2) { /* not table for polling unit */ + if ((NumLE % MIN_LEN_OF_LE_TAB) != 0 || NumLE > MAX_LEN_OF_LE_TAB) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("ERROR: Illegal number of list elements %d\n", NumLE)); + } + } +#endif /* DEBUG */ + + /* special case: unused list element table */ + if (NumLE == 0) { + PMemLowAddr = 0; + PMemHighAddr = 0; + pVMem = 0; + } + + /* + * in order to get the best possible performance the macros to access + * list elements use & instead of % + * this requires the length of LE tables to be a power of 2 + */ + + /* + * this code guarantees that we use the next power of 2 below the + * value specified for NumLe - this way some LEs in the table may + * not be used but the macros work correctly + * this code does not check for bad values below 128 because in such a + * case we cannot do anything here + */ + + if ((NumLE != 2) && (NumLE != 0)) { + /* no check for polling unit and unused sync Tx */ + i = MIN_LEN_OF_LE_TAB; + while (NumLE > i) { + i *= 2; + if (i > MAX_LEN_OF_LE_TAB) { + break; + } + } + if (NumLE != i) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("ERROR: Illegal number of list elements %d adjusted to %d\n", + NumLE, (i / 2))); + NumLE = i / 2; + } + } + + /* set addresses */ + pLETab->pPhyLETABLow = PMemLowAddr; + pLETab->pPhyLETABHigh = PMemHighAddr; + pLETab->pLETab = pVMem; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("contains %d LEs", NumLE)); + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + (" and starts at virt %08lx and phys %08lx:%08lx\n", + pVMem, PMemHighAddr, PMemLowAddr)); + + /* initialize indexes */ + pLETab->Done = 0; + pLETab->Put = 0; + pLETab->HwPut = 0; + /* initialize size */ + pLETab->Num = NumLE; + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("<== SkGeY2InitSingleLETable()\n")); +} /* SkGeY2InitSingleLETable */ + +/***************************************************************************** + * + * SkGeY2InitPrefetchUnit() - Initialize a Prefetch Unit + * + * Description: + * Calling this function requires an already configured list element + * table. The prefetch unit to be configured is specified in the parameter + * 'Queue'. The function is able to initialze the prefetch units of + * the following queues: Q_R1, Q_R2, Q_XS1, Q_XS2, Q_XA1, Q_XA2. + * The funcution should be called before SkGeInitPort(). + * + * Arguments: + * pAC - pointer to the adapter context struct. + * IoC - I/O context. + * Queue - I/O offset of queue e.g. Q_XA1. + * pLETab - pointer to list element table to be initialized + * + * Returns: N/A + */ +void SkGeY2InitPrefetchUnit( +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* I/O context */ +unsigned int Queue, /* Queue offset for finding the right registers */ +SK_LE_TABLE *pLETab) /* pointer to list element table to be initialized */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("==> SkGeY2InitPrefetchUnit()\n")); + +#ifdef DEBUG + if (Queue != Q_R1 && Queue != Q_R2 && Queue != Q_XS1 && + Queue != Q_XS2 && Queue != Q_XA1 && Queue != Q_XA2) { + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR, + ("ERROR: Illegal queue identifier %x\n", Queue)); + } +#endif /* DEBUG */ + + /* disable the prefetch unit */ + SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_RST_SET); + SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_RST_CLR); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Base address: %08lx:%08lx\n", pLETab->pPhyLETABHigh, + pLETab->pPhyLETABLow)); + + /* Set the list base address high part*/ + SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_ADDR_HI_REG), + pLETab->pPhyLETABHigh); + + /* Set the list base address low part */ + SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_ADDR_LOW_REG), + pLETab->pPhyLETABLow); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Last index: %d\n", pLETab->Num-1)); + + /* Set the list last index */ + SK_OUT16(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_LAST_IDX_REG), + (SK_U16)(pLETab->Num - 1)); + + /* turn on prefetch unit */ + SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_OP_ON); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("<== SkGeY2InitPrefetchUnit()\n")); +} /* SkGeY2InitPrefetchUnit */ + + +/***************************************************************************** + * + * SkGeY2InitStatBmu() - Initialize the Status BMU + * + * Description: + * Calling this function requires an already configured list element + * table. Ensure the status BMU is only initialized once during + * DriverInit - InitLevel2 required. + * + * Arguments: + * pAC - pointer to the adapter context struct. + * IoC - I/O context. + * pLETab - pointer to status LE table to be initialized + * + * Returns: N/A + */ +void SkGeY2InitStatBmu( +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* I/O context */ +SK_LE_TABLE *pLETab) /* pointer to status LE table */ +{ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("==> SkGeY2InitStatBmu()\n")); + + /* disable the prefetch unit */ + SK_OUT32(IoC, STAT_CTRL, SC_STAT_RST_SET); + SK_OUT32(IoC, STAT_CTRL, SC_STAT_RST_CLR); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Base address Low: %08lX\n", pLETab->pPhyLETABLow)); + + /* Set the list base address */ + SK_OUT32(IoC, STAT_LIST_ADDR_LO, pLETab->pPhyLETABLow); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Base address High: %08lX\n", pLETab->pPhyLETABHigh)); + + SK_OUT32(IoC, STAT_LIST_ADDR_HI, pLETab->pPhyLETABHigh); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Last index: %d\n", pLETab->Num - 1)); + + /* Set the list last index */ + SK_OUT16(IoC, STAT_LAST_IDX, (SK_U16)(pLETab->Num - 1)); + + if (HW_FEATURE(pAC, HWF_WA_DEV_43_418)) { + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Set Tx index threshold\n")); + /* WA for dev. #4.3 */ + SK_OUT16(IoC, STAT_TX_IDX_TH, ST_TXTH_IDX_MASK); + + /* set Status-FIFO watermark */ + SK_OUT8(IoC, STAT_FIFO_WM, 0x21); /* WA for dev. #4.18 */ + + /* set Status-FIFO ISR watermark */ + SK_OUT8(IoC, STAT_FIFO_ISR_WM, 0x07); /* WA for dev. #4.18 */ + + /* WA for dev. #4.3 and #4.18 */ + /* set Status-FIFO Tx timer init value */ + SK_OUT32(IoC, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC, 10)); + } + else { + /* + * Further settings may be added if required... + * 1) Status-FIFO watermark (STAT_FIFO_WM, STAT_FIFO_ISR_WM) + * 2) Status-FIFO timer values (STAT_TX_TIMER_INI, + * STAT_LEV_TIMER_INI and STAT_ISR_TIMER_INI) + * but tests shows that the default values give the best results, + * therefore the defaults are used. + */ + + /* + * Theses settings should avoid the temporary hang of the status BMU. + * May be not all required... still under investigation... + */ + SK_OUT16(IoC, STAT_TX_IDX_TH, 0x000a); + + /* set Status-FIFO watermark */ + SK_OUT8(IoC, STAT_FIFO_WM, 0x10); + + /* set Status-FIFO ISR watermark */ + SK_OUT8(IoC, STAT_FIFO_ISR_WM, + HW_FEATURE(pAC, HWF_WA_DEV_4109) ? 0x10 : 0x04); + + /* set ISR Timer Init Value to 400 (3.2 us on Yukon-EC) */ + SK_OUT32(IoC, STAT_ISR_TIMER_INI, 0x0190); + } + + /* start Status-FIFO timer */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Start Status FiFo timer\n")); + + /* enable the prefetch unit */ + /* operational bit not functional for Yukon-EC, but fixed in Yukon-2 */ + SK_OUT32(IoC, STAT_CTRL, SC_STAT_OP_ON); + + /* start Status-FIFO timer */ + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Start Status FiFo timer\n")); + + SK_OUT8(IoC, STAT_TX_TIMER_CTRL, TIM_START); + SK_OUT8(IoC, STAT_LEV_TIMER_CTRL, TIM_START); + SK_OUT8(IoC, STAT_ISR_TIMER_CTRL, TIM_START); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("<== SkGeY2InitStatBmu()\n")); +} /* SkGeY2InitStatBmu */ + +#ifdef USE_POLLING_UNIT +/***************************************************************************** + * + * SkGeY2InitPollUnit() - Initialize the Polling Unit + * + * Description: + * This function will write the data of one polling LE table into the + * adapter. + * + * Arguments: + * pAC - pointer to the adapter context struct. + * IoC - I/O context. + * pLETab - pointer to polling LE table to be initialized + * + * Returns: N/A + */ +void SkGeY2InitPollUnit( +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* I/O context */ +SK_LE_TABLE *pLETab) /* pointer to polling LE table */ +{ + SK_HWLE *pLE; + int i; +#ifdef VCPU + VCPU_VARS(); +#endif /* VCPU */ + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("==> SkGeY2InitPollUnit()\n")); + +#ifdef VCPU + for (i = 0; i < SK_MAX_MACS; i++) { + GET_PO_LE(pLE, pLETab, i); + VCPU_START_AND_COPY_LE(); + /* initialize polling LE but leave indexes invalid */ + POLE_SET_OPC(pLE, OP_PUTIDX | HW_OWNER); + POLE_SET_LINK(pLE, i); + POLE_SET_RXIDX(pLE, 0); + POLE_SET_TXAIDX(pLE, 0); + POLE_SET_TXSIDX(pLE, 0); + VCPU_WRITE_LE(); + SK_DBG_DUMP_PO_LE(pLE); + } +#endif /* VCPU */ + + /* disable the polling unit */ + SK_OUT32(IoC, POLL_CTRL, PC_POLL_RST_SET); + SK_OUT32(IoC, POLL_CTRL, PC_POLL_RST_CLR); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Base address Low: %08lX\n", pLETab->pPhyLETABLow)); + + /* Set the list base address */ + SK_OUT32(IoC, POLL_LIST_ADDR_LO, pLETab->pPhyLETABLow); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("Base address High: %08lX\n", pLETab->pPhyLETABHigh)); + + SK_OUT32(IoC, POLL_LIST_ADDR_HI, pLETab->pPhyLETABHigh); + + /* we don't need to write the last index - it is hardwired to 1 */ + + /* enable the prefetch unit */ + SK_OUT32(IoC, POLL_CTRL, PC_POLL_OP_ON); + + /* + * now we have to start the descriptor poll timer because it triggers + * the polling unit + */ + + /* + * still playing with the value (timer runs at 125 MHz) + * descriptor poll timer is enabled by GeInit + */ + SK_OUT32(IoC, B28_DPT_INI, + (SK_DPOLL_DEF_Y2 * (SK_U32)pAC->GIni.GIHstClkFact / 100)); + + SK_OUT8(IoC, B28_DPT_CTRL, TIM_START); + + SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, + ("<== SkGeY2InitPollUnit()\n")); +} /* SkGeY2InitPollUnit */ +#endif /* USE_POLLING_UNIT */ + + +/****************************************************************************** + * + * SkGeY2SetPutIndex + * + * Description: + * This function is writing the Done index of a transmit + * list element table. + * + * Notes: + * Dev. Issue 4.2 + * + * Returns: N/A + */ +void SkGeY2SetPutIndex( +SK_AC *pAC, /* pointer to adapter context */ +SK_IOC IoC, /* pointer to the IO context */ +SK_U32 StartAddrPrefetchUnit, /* start address of the prefetch unit */ +SK_LE_TABLE *pLETab) /* list element table to work with */ +{ + unsigned int Put; + SK_U16 EndOfListIndex; + SK_U16 HwGetIndex; + SK_U16 HwPutIndex; + + /* set put index we would like to write */ + Put = GET_PUT_IDX(pLETab); + + /* + * in this case we wrap around + * new put is lower than last put given to HW + */ + if (Put < pLETab->HwPut) { + + /* set put index = last index of list */ + EndOfListIndex = (NUM_LE_IN_TABLE(pLETab)-1); + + /* read get index of hw prefetch unit */ + SK_IN16(IoC, (StartAddrPrefetchUnit + PREF_UNIT_GET_IDX_REG), + &HwGetIndex); + + /* read put index of hw prefetch unit */ + SK_IN16(IoC, (StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG), + &HwPutIndex); + + /* prefetch unit reached end of list */ + /* prefetch unit reached first list element */ + if (HwGetIndex == 0) { + /* restore watermark */ + SK_OUT8(IoC, StartAddrPrefetchUnit + PREF_UNIT_FIFO_WM_REG, 0xe0U); + /* write put index */ + SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG, + (SK_U16)Put); + + /* remember put index we wrote to hw */ + pLETab->HwPut = Put; + } + else if (HwGetIndex == EndOfListIndex) { + /* set watermark to one list element */ + SK_OUT8(IoC, StartAddrPrefetchUnit + PREF_UNIT_FIFO_WM_REG, 8); + /* set put index to first list element */ + SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG, 0); + } + /* prefetch unit did not reach end of list yet */ + /* and we did not write put index to end of list yet */ + else if ((HwPutIndex != EndOfListIndex) && + (HwGetIndex != EndOfListIndex)) { + /* write put index */ + SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG, + EndOfListIndex); + } + else { + /* do nothing */ + } + } + else { +#ifdef XXX /* leads in to problems in the Windows Driver */ + if (Put != pLETab->HwPut) { + /* write put index */ + SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG, + (SK_U16)Put); + /* update put index */ + UPDATE_HWPUT_IDX(pLETab); + } +#else + /* write put index */ + SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG, + (SK_U16)Put); + /* update put index */ + UPDATE_HWPUT_IDX(pLETab); +#endif + } +} /* SkGeY2SetPutIndex */ + +#endif diff --git a/drivers/sk98lin/uboot_drv.c b/drivers/sk98lin/uboot_drv.c index 263dac8..8e6bd04 100644 --- a/drivers/sk98lin/uboot_drv.c +++ b/drivers/sk98lin/uboot_drv.c @@ -33,15 +33,19 @@ #include "u-boot_compat.h" -#define SKGE_MAX_CARDS 2 +#define SKGE_MAX_CARDS 4 extern int skge_probe(struct eth_device **); extern void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); extern void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); +/* Marvell - Yukon2 support*/ +extern void SkY2Isr(int irq, void *dev_id, struct pt_regs *ptregs); extern int SkGeOpen(struct eth_device *); extern int SkGeClose(struct eth_device *); extern int SkGeXmit(struct sk_buff *skb, struct eth_device *dev); +/* Marvell - Yukon2 support*/ +extern int SkY2Xmit(struct sk_buff *skb, struct eth_device *dev); extern void ReceiveIrq(SK_AC *pAC, RX_PORT *pRxPort, SK_BOOL SlowPathLock); static int skge_init(struct eth_device *dev, bd_t * bis); @@ -51,7 +55,7 @@ static void skge_halt(struct eth_device *dev); int skge_initialize(bd_t * bis) { - int numdev, i; + int numdev,i ; struct eth_device *dev[SKGE_MAX_CARDS]; numdev = skge_probe(&dev[0]); @@ -69,39 +73,92 @@ int skge_initialize(bd_t * bis) dev[i]->halt = skge_halt; dev[i]->send = skge_send; dev[i]->recv = skge_recv; - + eth_register(dev[i]); } - return numdev; } +/* ronen - since if we try to halt the dev after it was halted it cause a stuck I add this + global variable */ +int sk98_inited = 0; static int skge_init(struct eth_device *dev, bd_t * bis) { int ret; SK_AC * pAC = ((DEV_NET*)dev->priv)->pAC; - int i; + int i = 0; + + /* ronen */ + if(sk98_inited == 1) + skge_halt(dev); ret = SkGeOpen(dev); while (pAC->Rlmt.Port[0].PortState != SK_RLMT_PS_GOING_UP) { - SkGeIsrOnePort (0, pAC->dev[0], 0); + /* ronen - since if the link on the sk98 is down we don't want to wait here for ever */ + /* so I adde a counter */ + i++; + + /* Marvell - Yukon2 support*/ + if (CHIP_ID_YUKON_2(pAC)) { + SkY2Isr (0, pAC->dev[0], 0); + if(i > 1500000){ + ret = 1; + break; + } + + ret = 0; + } + else { + SkGeIsrOnePort (0, pAC->dev[0], 0); + if(i > 1500000){ + ret = 1; + break; + } + + } } - for (i = 0; i < 100; i ++) - { - udelay(1000); - } +// for (i = 0; i < 100; i ++) +// { +// udelay(1000); +// } - return ret; + /* ronen - for the SkGeOpen 0 is success and 1 is fail */ + /* the return except 1 for success */ + if(ret == 0){ + sk98_inited = 1; + return 1; + } + skge_halt(dev); + return 0; } - static void skge_halt(struct eth_device *dev) { + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; + + + /* ronen */ + if(sk98_inited == 0) + return; + + + /* Marvell - Yukon2 support*/ + /* to be in the safe side we call SkY2Isr to treat any + pending rx or tx complete */ + if (CHIP_ID_YUKON_2(pAC)) + { + SkY2Isr (0, pAC->dev[0], 0); + } + SkGeClose(dev); + + + sk98_inited = 0; } @@ -109,7 +166,9 @@ static int skge_send(struct eth_device *dev, volatile void *packet, int length) { int ret = -1; - struct sk_buff * skb = alloc_skb(length, 0); + struct sk_buff * skb = alloc_skb(length,0); + DEV_NET *pNet = (DEV_NET*) dev->priv; + SK_AC *pAC = pNet->pAC; if (! skb) { @@ -118,8 +177,14 @@ static int skge_send(struct eth_device *dev, volatile void *packet, } memcpy(skb->data, (void*)packet, length); - ret = SkGeXmit(skb, dev); + /* Marvell - Yukon2 support*/ + if (CHIP_ID_YUKON_2(pAC)) { + ret = SkY2Xmit(skb,dev); + } + else { + ret = SkGeXmit(skb, dev); + } Done: return ret; } @@ -134,7 +199,15 @@ static int skge_recv(struct eth_device *dev) pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); + /* Marvell - Yukon2 support*/ + if (CHIP_ID_YUKON_2(pAC)) { + + SkY2Isr (0, pAC->dev[0], 0); + } + else { + + ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); + } return 0; } diff --git a/drivers/sk98lin/uboot_skb.c b/drivers/sk98lin/uboot_skb.c index 3a487a8..eaa46f6 100644 --- a/drivers/sk98lin/uboot_skb.c +++ b/drivers/sk98lin/uboot_skb.c @@ -30,16 +30,25 @@ #include #include "u-boot_compat.h" -#define MAX_SKB 50 +#define MAX_SKB 128 -static struct sk_buff *sk_table[MAX_SKB]; +struct sk_buff *sk_table[MAX_SKB]; +unsigned int skbAlloc=0,skbFree=0; +/*unsigned int cntrMalloc=0,cntrFree=0; +unsigned int indxMalloc=0,indxFree=0; +*/ +extern int tftpCount; struct sk_buff * alloc_skb(u32 size, int dummy) { int i; struct sk_buff * ret = NULL; + if(0)/*if(tftpCount == 2)*/ + { + printf("alloc_skb , size=%d\n",size); + } for (i = 0; i < MAX_SKB; i++) { if (sk_table[i]) @@ -78,10 +87,20 @@ struct sk_buff * alloc_skb(u32 size, int dummy) ret = sk_table[i]; } + if(0)/*if(tftpCount == 2)*/ + { + printf("alloc_skb , i=%d sk_table[i]=0x%x sk_table[i]->data=0x%x\n",i,sk_table[i],sk_table[i]->data); + } + + if (! ret) { printf("Unable to allocate skb!\n"); } + else + { + skbAlloc++;; + } return ret; } @@ -90,12 +109,23 @@ void dev_kfree_skb_any(struct sk_buff *skb) { int i; + if(0)/*if(tftpCount == 2)*/ + { + printf("dev_kfree_skb_any , skb=0x%x\n",skb); + } + + for (i = 0; i < MAX_SKB; i++) { if (sk_table[i] != skb) { continue; } + if(0)/*if(tftpCount == 2)*/ + { + printf("dev_kfree_skb_any , i=%d sk_table[i]=0x%x sk_table[i]->data=0x%x\n",i,skb,skb->data_unaligned); + } + free(skb->data_unaligned); free(skb); @@ -107,6 +137,10 @@ void dev_kfree_skb_any(struct sk_buff *skb) { printf("SKB allocation error!\n"); } + else + { + skbFree++; + } } void skb_reserve(struct sk_buff *skb, unsigned int len) @@ -119,4 +153,7 @@ void skb_put(struct sk_buff *skb, unsigned int len) skb->len+=len; } + + + #endif /* CONFIG_SK98 */ diff --git a/examples/Makefile b/examples/Makefile index 2f8c4c4..378e227 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -30,7 +30,8 @@ LOAD_ADDR = 0x40000 endif ifeq ($(ARCH),arm) -LOAD_ADDR = 0xc100000 +#LOAD_ADDR = 0xc100000 +LOAD_ADDR = 0x100000 endif ifeq ($(ARCH),mips) @@ -54,6 +55,7 @@ LOAD_ADDR = 0x80F00000 endif include $(TOPDIR)/config.mk +include $(TOPDIR)/include/config.mk SREC = hello_world.srec BIN = hello_world.bin hello_world diff --git a/examples/stubs.c b/examples/stubs.c index d4c6e06..1dea780 100644 --- a/examples/stubs.c +++ b/examples/stubs.c @@ -139,7 +139,7 @@ gd_t *global_data; #if GCC_VERSION < 3004 static #endif /* GCC_VERSION */ -void __attribute__((unused)) dummy(void) +void __attribute__((used)) dummy(void) { #include <_exports.h> } diff --git a/fs/ext2/dev.c b/fs/ext2/dev.c index 1469e98..7790667 100644 --- a/fs/ext2/dev.c +++ b/fs/ext2/dev.c @@ -53,7 +53,8 @@ int ext2fs_set_blk_dev (block_dev_desc_t * rbdd, int part) int ext2fs_devread (int sector, int byte_offset, int byte_len, char *buf) { - char sec_buf[SECTOR_SIZE]; + short sec_buffer[SECTOR_SIZE/sizeof(short)]; + char *sec_buf = sec_buffer; unsigned block_len; /* diff --git a/fs/ext2/ext2fs.c b/fs/ext2/ext2fs.c index c21d2d6..e555faa 100644 --- a/fs/ext2/ext2fs.c +++ b/fs/ext2/ext2fs.c @@ -472,7 +472,8 @@ static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fn return (0); } if (dirent.namelen != 0) { - char filename[dirent.namelen + 1]; + char *filename; + filename = (char*)malloc(dirent.namelen + 1); ext2fs_node_t fdiro; int type = FILETYPE_UNKNOWN; @@ -569,6 +570,7 @@ static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fn filename); } free (fdiro); + free (filename); } fpos += __le16_to_cpu (dirent.direntlen); } @@ -724,7 +726,7 @@ int ext2fs_find_file symlinknest = 0; - if (!path) { + if (!path || path[0] != '/') { return (0); } diff --git a/fs/fat/fat.c b/fs/fat/fat.c index a823b5a..dd9fd11 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -972,7 +972,7 @@ file_fat_detectfs(void) return 1; } #if (CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI) || \ - (CONFIG_COMMANDS & CFG_CMD_USB) || (CONFIG_MMC) + (CONFIG_COMMANDS & CFG_CMD_USB) || (CONFIG_COMMANDS & CFG_CMD_MMC) printf("Interface: "); switch(cur_dev->if_type) { case IF_TYPE_IDE : printf("IDE"); break; diff --git a/fs/jffs2/compr_lzari.c b/fs/jffs2/compr_lzari.c index 828b6e5..31df9f1 100644 --- a/fs/jffs2/compr_lzari.c +++ b/fs/jffs2/compr_lzari.c @@ -7,7 +7,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr_lzari.c,v 1.3 2004/06/23 16:34:39 havasi Exp $ + * $Id: compr_lzari.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * */ diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c index b6c590a..04eed93 100644 --- a/fs/jffs2/compr_lzo.c +++ b/fs/jffs2/compr_lzo.c @@ -7,7 +7,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr_lzo.c,v 1.3 2004/06/23 16:34:39 havasi Exp $ + * $Id: compr_lzo.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * */ diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 9bb4f1b..4e27648 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: compr_rtime.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $ + * $Id: compr_rtime.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * * * Very simple lz77-ish encoder. diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 74577d9..f295eb0 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -34,7 +34,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: compr_rubin.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $ + * $Id: compr_rubin.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * */ diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 1b35585..1ecee85 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: compr_zlib.c,v 1.2 2002/01/24 22:58:42 rfeany Exp $ + * $Id: compr_zlib.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * */ diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index c6c0c2a..bf6c3a6 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------- * Filename: jffs2.c - * Version: $Id: jffs2_1pass.c,v 1.7 2002/01/25 01:56:47 nyet Exp $ + * Version: $Id: jffs2_1pass.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * Copyright: Copyright (C) 2001, Russ Dill * Author: Russ Dill * Description: Module to load kernel from jffs2 @@ -42,7 +42,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: jffs2_1pass.c,v 1.7 2002/01/25 01:56:47 nyet Exp $ + * $Id: jffs2_1pass.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * */ @@ -144,6 +144,11 @@ static struct part_info *current_part; #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND) +#if defined(CFG_NAND_LEGACY) +#include +#else +#include +#endif /* * Support for jffs2 on top of NAND-flash * @@ -154,9 +159,14 @@ static struct part_info *current_part; * */ -/* this one defined in cmd_nand.c */ +#if defined(CFG_NAND_LEGACY) +/* this one defined in nand_legacy.c */ int read_jffs2_nand(size_t start, size_t len, - size_t * retlen, u_char * buf, int nanddev); + size_t * retlen, u_char * buf, int nanddev); +#else +/* info for NAND chips, defined in drivers/nand/nand.c */ +extern nand_info_t nand_info[]; +#endif #define NAND_PAGE_SIZE 512 #define NAND_PAGE_SHIFT 9 @@ -174,7 +184,11 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf) { struct mtdids *id = current_part->dev->id; u32 bytes_read = 0; +#if defined(CFG_NAND_LEGACY) size_t retlen; +#else + ulong retlen; +#endif int cpy_bytes; while (bytes_read < size) { @@ -191,6 +205,8 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf) return -1; } } + +#if defined(CFG_NAND_LEGACY) if (read_jffs2_nand(nand_cache_off, NAND_CACHE_SIZE, &retlen, nand_cache, id->num) < 0 || retlen != NAND_CACHE_SIZE) { @@ -198,6 +214,16 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf) nand_cache_off, NAND_CACHE_SIZE); return -1; } +#else + retlen = NAND_CACHE_SIZE; + if (nand_read(&nand_info[id->num], nand_cache_off, + &retlen, nand_cache) != 0 || + retlen != NAND_CACHE_SIZE) { + printf("read_nand_cached: error reading nand off %#x size %d bytes\n", + nand_cache_off, NAND_CACHE_SIZE); + return -1; + } +#endif } cpy_bytes = nand_cache_off + NAND_CACHE_SIZE - (off + bytes_read); if (cpy_bytes > size - bytes_read) @@ -1167,7 +1193,8 @@ jffs2_1pass_build_lists(struct part_info * part) if (node->magic == JFFS2_MAGIC_BITMASK && hdr_crc(node)) { /* if its a fragment add it */ if (node->nodetype == JFFS2_NODETYPE_INODE && - inode_crc((struct jffs2_raw_inode *) node)) { + inode_crc((struct jffs2_raw_inode *) node) && + data_crc((struct jffs2_raw_inode *) node)) { if (insert_node(&pL->frag, (u32) part->offset + offset) == NULL) { put_fl_mem(node); diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c new file mode 100644 index 0000000..e78af75 --- /dev/null +++ b/fs/jffs2/jffs2_nand_1pass.c @@ -0,0 +1,1036 @@ +#include + +#if !defined(CFG_NAND_LEGACY) && (CONFIG_COMMANDS & CFG_CMD_JFFS2) + +#include +#include +#include + +#include +#include +#include + +#include "jffs2_nand_private.h" + +#define NODE_CHUNK 1024 /* size of memory allocation chunk in b_nodes */ + +/* Debugging switches */ +#undef DEBUG_DIRENTS /* print directory entry list after scan */ +#undef DEBUG_FRAGMENTS /* print fragment list after scan */ +#undef DEBUG /* enable debugging messages */ + +#ifdef DEBUG +# define DEBUGF(fmt,args...) printf(fmt ,##args) +#else +# define DEBUGF(fmt,args...) +#endif + +static nand_info_t *nand; + +/* Compression names */ +static char *compr_names[] = { + "NONE", + "ZERO", + "RTIME", + "RUBINMIPS", + "COPY", + "DYNRUBIN", + "ZLIB", +#if defined(CONFIG_JFFS2_LZO_LZARI) + "LZO", + "LZARI", +#endif +}; + +/* Spinning wheel */ +static char spinner[] = { '|', '/', '-', '\\' }; + +/* Memory management */ +struct mem_block { + unsigned index; + struct mem_block *next; + char nodes[0]; +}; + +static void +free_nodes(struct b_list *list) +{ + while (list->listMemBase != NULL) { + struct mem_block *next = list->listMemBase->next; + free(list->listMemBase); + list->listMemBase = next; + } +} + +static struct b_node * +add_node(struct b_list *list, int size) +{ + u32 index = 0; + struct mem_block *memBase; + struct b_node *b; + + memBase = list->listMemBase; + if (memBase != NULL) + index = memBase->index; + + if (memBase == NULL || index >= NODE_CHUNK) { + /* we need more space before we continue */ + memBase = mmalloc(sizeof(struct mem_block) + NODE_CHUNK * size); + if (memBase == NULL) { + putstr("add_node: malloc failed\n"); + return NULL; + } + memBase->next = list->listMemBase; + index = 0; + } + /* now we have room to add it. */ + b = (struct b_node *)&memBase->nodes[size * index]; + index ++; + + memBase->index = index; + list->listMemBase = memBase; + list->listCount++; + return b; +} + +static struct b_node * +insert_node(struct b_list *list, struct b_node *new) +{ +#ifdef CFG_JFFS2_SORT_FRAGMENTS + struct b_node *b, *prev; + + if (list->listTail != NULL && list->listCompare(new, list->listTail)) + prev = list->listTail; + else if (list->listLast != NULL && list->listCompare(new, list->listLast)) + prev = list->listLast; + else + prev = NULL; + + for (b = (prev ? prev->next : list->listHead); + b != NULL && list->listCompare(new, b); + prev = b, b = b->next) { + list->listLoops++; + } + if (b != NULL) + list->listLast = prev; + + if (b != NULL) { + new->next = b; + if (prev != NULL) + prev->next = new; + else + list->listHead = new; + } else +#endif + { + new->next = (struct b_node *) NULL; + if (list->listTail != NULL) { + list->listTail->next = new; + list->listTail = new; + } else { + list->listTail = list->listHead = new; + } + } + + return new; +} + +static struct b_node * +insert_inode(struct b_list *list, struct jffs2_raw_inode *node, u32 offset) +{ + struct b_inode *new; + + if (!(new = (struct b_inode *)add_node(list, sizeof(struct b_inode)))) { + putstr("add_node failed!\r\n"); + return NULL; + } + new->offset = offset; + new->version = node->version; + new->ino = node->ino; + new->isize = node->isize; + new->csize = node->csize; + + return insert_node(list, (struct b_node *)new); +} + +static struct b_node * +insert_dirent(struct b_list *list, struct jffs2_raw_dirent *node, u32 offset) +{ + struct b_dirent *new; + + if (!(new = (struct b_dirent *)add_node(list, sizeof(struct b_dirent)))) { + putstr("add_node failed!\r\n"); + return NULL; + } + new->offset = offset; + new->version = node->version; + new->pino = node->pino; + new->ino = node->ino; + new->nhash = full_name_hash(node->name, node->nsize); + new->nsize = node->nsize; + new->type = node->type; + + return insert_node(list, (struct b_node *)new); +} + +#ifdef CFG_JFFS2_SORT_FRAGMENTS +/* Sort data entries with the latest version last, so that if there + * is overlapping data the latest version will be used. + */ +static int compare_inodes(struct b_node *new, struct b_node *old) +{ + struct jffs2_raw_inode ojNew; + struct jffs2_raw_inode ojOld; + struct jffs2_raw_inode *jNew = + (struct jffs2_raw_inode *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew); + struct jffs2_raw_inode *jOld = + (struct jffs2_raw_inode *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld); + + return jNew->version > jOld->version; +} + +/* Sort directory entries so all entries in the same directory + * with the same name are grouped together, with the latest version + * last. This makes it easy to eliminate all but the latest version + * by marking the previous version dead by setting the inode to 0. + */ +static int compare_dirents(struct b_node *new, struct b_node *old) +{ + struct jffs2_raw_dirent ojNew; + struct jffs2_raw_dirent ojOld; + struct jffs2_raw_dirent *jNew = + (struct jffs2_raw_dirent *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew); + struct jffs2_raw_dirent *jOld = + (struct jffs2_raw_dirent *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld); + int cmp; + + /* ascending sort by pino */ + if (jNew->pino != jOld->pino) + return jNew->pino > jOld->pino; + + /* pino is the same, so use ascending sort by nsize, so + * we don't do strncmp unless we really must. + */ + if (jNew->nsize != jOld->nsize) + return jNew->nsize > jOld->nsize; + + /* length is also the same, so use ascending sort by name + */ + cmp = strncmp(jNew->name, jOld->name, jNew->nsize); + if (cmp != 0) + return cmp > 0; + + /* we have duplicate names in this directory, so use ascending + * sort by version + */ + if (jNew->version > jOld->version) { + /* since jNew is newer, we know jOld is not valid, so + * mark it with inode 0 and it will not be used + */ + jOld->ino = 0; + return 1; + } + + return 0; +} +#endif + +static u32 +jffs_init_1pass_list(struct part_info *part) +{ + struct b_lists *pL; + + if (part->jffs2_priv != NULL) { + pL = (struct b_lists *)part->jffs2_priv; + free_nodes(&pL->frag); + free_nodes(&pL->dir); + free(pL); + } + if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) { + pL = (struct b_lists *)part->jffs2_priv; + + memset(pL, 0, sizeof(*pL)); +#ifdef CFG_JFFS2_SORT_FRAGMENTS + pL->dir.listCompare = compare_dirents; + pL->frag.listCompare = compare_inodes; +#endif + } + return 0; +} + +/* find the inode from the slashless name given a parent */ +static long +jffs2_1pass_read_inode(struct b_lists *pL, u32 ino, char *dest, + struct stat *stat) +{ + struct b_inode *jNode; + u32 totalSize = 0; + u32 latestVersion = 0; + long ret; + +#ifdef CFG_JFFS2_SORT_FRAGMENTS + /* Find file size before loading any data, so fragments that + * start past the end of file can be ignored. A fragment + * that is partially in the file is loaded, so extra data may + * be loaded up to the next 4K boundary above the file size. + * This shouldn't cause trouble when loading kernel images, so + * we will live with it. + */ + for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) { + if ((ino == jNode->ino)) { + /* get actual file length from the newest node */ + if (jNode->version >= latestVersion) { + totalSize = jNode->isize; + latestVersion = jNode->version; + } + } + } +#endif + + for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) { + if ((ino != jNode->ino)) + continue; +#ifndef CFG_JFFS2_SORT_FRAGMENTS + /* get actual file length from the newest node */ + if (jNode->version >= latestVersion) { + totalSize = jNode->isize; + latestVersion = jNode->version; + } +#endif + if (dest || stat) { + char *src, *dst; + char data[4096 + sizeof(struct jffs2_raw_inode)]; + struct jffs2_raw_inode *inode; + size_t len; + + inode = (struct jffs2_raw_inode *)&data; + len = sizeof(struct jffs2_raw_inode); + if (dest) + len += jNode->csize; + nand_read(nand, jNode->offset, &len, inode); + /* ignore data behind latest known EOF */ + if (inode->offset > totalSize) + continue; + + if (stat) { + stat->st_mtime = inode->mtime; + stat->st_mode = inode->mode; + stat->st_ino = inode->ino; + stat->st_size = totalSize; + } + + if (!dest) + continue; + + src = ((char *) inode) + sizeof(struct jffs2_raw_inode); + dst = (char *) (dest + inode->offset); + + switch (inode->compr) { + case JFFS2_COMPR_NONE: + ret = 0; + memcpy(dst, src, inode->dsize); + break; + case JFFS2_COMPR_ZERO: + ret = 0; + memset(dst, 0, inode->dsize); + break; + case JFFS2_COMPR_RTIME: + ret = 0; + rtime_decompress(src, dst, inode->csize, inode->dsize); + break; + case JFFS2_COMPR_DYNRUBIN: + /* this is slow but it works */ + ret = 0; + dynrubin_decompress(src, dst, inode->csize, inode->dsize); + break; + case JFFS2_COMPR_ZLIB: + ret = zlib_decompress(src, dst, inode->csize, inode->dsize); + break; +#if defined(CONFIG_JFFS2_LZO_LZARI) + case JFFS2_COMPR_LZO: + ret = lzo_decompress(src, dst, inode->csize, inode->dsize); + break; + case JFFS2_COMPR_LZARI: + ret = lzari_decompress(src, dst, inode->csize, inode->dsize); + break; +#endif + default: + /* unknown */ + putLabeledWord("UNKOWN COMPRESSION METHOD = ", inode->compr); + return -1; + } + } + } + + return totalSize; +} + +/* find the inode from the slashless name given a parent */ +static u32 +jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino) +{ + struct b_dirent *jDir; + int len = strlen(name); /* name is assumed slash free */ + unsigned int nhash = full_name_hash(name, len); + u32 version = 0; + u32 inode = 0; + + /* we need to search all and return the inode with the highest version */ + for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) { + if ((pino == jDir->pino) && (jDir->ino) && /* 0 for unlink */ + (len == jDir->nsize) && (nhash == jDir->nhash)) { + /* TODO: compare name */ + if (jDir->version < version) + continue; + + if (jDir->version == version && inode != 0) { + /* I'm pretty sure this isn't legal */ + putstr(" ** ERROR ** "); +/* putnstr(jDir->name, jDir->nsize); */ +/* putLabeledWord(" has dup version =", version); */ + } + inode = jDir->ino; + version = jDir->version; + } + } + return inode; +} + +char *mkmodestr(unsigned long mode, char *str) +{ + static const char *l = "xwr"; + int mask = 1, i; + char c; + + switch (mode & S_IFMT) { + case S_IFDIR: str[0] = 'd'; break; + case S_IFBLK: str[0] = 'b'; break; + case S_IFCHR: str[0] = 'c'; break; + case S_IFIFO: str[0] = 'f'; break; + case S_IFLNK: str[0] = 'l'; break; + case S_IFSOCK: str[0] = 's'; break; + case S_IFREG: str[0] = '-'; break; + default: str[0] = '?'; + } + + for(i = 0; i < 9; i++) { + c = l[i%3]; + str[9-i] = (mode & mask)?c:'-'; + mask = mask<<1; + } + + if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S'; + if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S'; + if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T'; + str[10] = '\0'; + return str; +} + +static inline void dump_stat(struct stat *st, const char *name) +{ + char str[20]; + char s[64], *p; + + if (st->st_mtime == (time_t)(-1)) /* some ctimes really hate -1 */ + st->st_mtime = 1; + + ctime_r(&st->st_mtime, s/*,64*/); /* newlib ctime doesn't have buflen */ + + if ((p = strchr(s,'\n')) != NULL) *p = '\0'; + if ((p = strchr(s,'\r')) != NULL) *p = '\0'; + +/* + printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str), + st->st_size, s, name); +*/ + + printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name); +} + +static inline int +dump_inode(struct b_lists *pL, struct b_dirent *d, struct b_inode *i) +{ + char fname[JFFS2_MAX_NAME_LEN + 1]; + struct stat st; + size_t len; + + if(!d || !i) return -1; + len = d->nsize; + nand_read(nand, d->offset + sizeof(struct jffs2_raw_dirent), + &len, &fname); + fname[d->nsize] = '\0'; + + memset(&st, 0, sizeof(st)); + + jffs2_1pass_read_inode(pL, i->ino, NULL, &st); + + dump_stat(&st, fname); +/* FIXME + if (d->type == DT_LNK) { + unsigned char *src = (unsigned char *) (&i[1]); + putstr(" -> "); + putnstr(src, (int)i->dsize); + } +*/ + putstr("\r\n"); + + return 0; +} + +/* list inodes with the given pino */ +static u32 +jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino) +{ + struct b_dirent *jDir; + u32 i_version = 0; + + for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) { + if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */ + struct b_inode *jNode = (struct b_inode *)pL->frag.listHead; + struct b_inode *i = NULL; + + while (jNode) { + if (jNode->ino == jDir->ino && jNode->version >= i_version) { + i_version = jNode->version; + i = jNode; + } + jNode = jNode->next; + } + dump_inode(pL, jDir, i); + } + } + return pino; +} + +static u32 +jffs2_1pass_search_inode(struct b_lists * pL, const char *fname, u32 pino) +{ + int i; + char tmp[256]; + char working_tmp[256]; + char *c; + + /* discard any leading slash */ + i = 0; + while (fname[i] == '/') + i++; + strcpy(tmp, &fname[i]); + + while ((c = (char *) strchr(tmp, '/'))) /* we are still dired searching */ + { + strncpy(working_tmp, tmp, c - tmp); + working_tmp[c - tmp] = '\0'; +#if 0 + putstr("search_inode: tmp = "); + putstr(tmp); + putstr("\r\n"); + putstr("search_inode: wtmp = "); + putstr(working_tmp); + putstr("\r\n"); + putstr("search_inode: c = "); + putstr(c); + putstr("\r\n"); +#endif + for (i = 0; i < strlen(c) - 1; i++) + tmp[i] = c[i + 1]; + tmp[i] = '\0'; +#if 0 + putstr("search_inode: post tmp = "); + putstr(tmp); + putstr("\r\n"); +#endif + + if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino))) { + putstr("find_inode failed for name="); + putstr(working_tmp); + putstr("\r\n"); + return 0; + } + } + /* this is for the bare filename, directories have already been mapped */ + if (!(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { + putstr("find_inode failed for name="); + putstr(tmp); + putstr("\r\n"); + return 0; + } + return pino; + +} + +static u32 +jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino) +{ + struct b_dirent *jDir; + struct b_inode *jNode; + u8 jDirFoundType = 0; + u32 jDirFoundIno = 0; + u32 jDirFoundPino = 0; + char tmp[JFFS2_MAX_NAME_LEN + 1]; + u32 version = 0; + u32 pino; + + /* we need to search all and return the inode with the highest version */ + for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) { + if (ino == jDir->ino) { + if (jDir->version < version) + continue; + + if (jDir->version == version && jDirFoundType) { + /* I'm pretty sure this isn't legal */ + putstr(" ** ERROR ** "); +/* putnstr(jDir->name, jDir->nsize); */ +/* putLabeledWord(" has dup version (resolve) = ", */ +/* version); */ + } + + jDirFoundType = jDir->type; + jDirFoundIno = jDir->ino; + jDirFoundPino = jDir->pino; + version = jDir->version; + } + } + /* now we found the right entry again. (shoulda returned inode*) */ + if (jDirFoundType != DT_LNK) + return jDirFoundIno; + + /* it's a soft link so we follow it again. */ + for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) { + if (jNode->ino == jDirFoundIno) { + size_t len = jNode->csize; + nand_read(nand, jNode->offset + sizeof(struct jffs2_raw_inode), &len, &tmp); + tmp[jNode->csize] = '\0'; + break; + } + } + /* ok so the name of the new file to find is in tmp */ + /* if it starts with a slash it is root based else shared dirs */ + if (tmp[0] == '/') + pino = 1; + else + pino = jDirFoundPino; + + return jffs2_1pass_search_inode(pL, tmp, pino); +} + +static u32 +jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino) +{ + int i; + char tmp[256]; + char working_tmp[256]; + char *c; + + /* discard any leading slash */ + i = 0; + while (fname[i] == '/') + i++; + strcpy(tmp, &fname[i]); + working_tmp[0] = '\0'; + while ((c = (char *) strchr(tmp, '/'))) /* we are still dired searching */ + { + strncpy(working_tmp, tmp, c - tmp); + working_tmp[c - tmp] = '\0'; + for (i = 0; i < strlen(c) - 1; i++) + tmp[i] = c[i + 1]; + tmp[i] = '\0'; + /* only a failure if we arent looking at top level */ + if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && + (working_tmp[0])) { + putstr("find_inode failed for name="); + putstr(working_tmp); + putstr("\r\n"); + return 0; + } + } + + if (tmp[0] && !(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { + putstr("find_inode failed for name="); + putstr(tmp); + putstr("\r\n"); + return 0; + } + /* this is for the bare filename, directories have already been mapped */ + if (!(pino = jffs2_1pass_list_inodes(pL, pino))) { + putstr("find_inode failed for name="); + putstr(tmp); + putstr("\r\n"); + return 0; + } + return pino; + +} + +unsigned char +jffs2_1pass_rescan_needed(struct part_info *part) +{ + struct b_node *b; + struct jffs2_unknown_node onode; + struct jffs2_unknown_node *node; + struct b_lists *pL = (struct b_lists *)part->jffs2_priv; + + if (part->jffs2_priv == 0){ + DEBUGF ("rescan: First time in use\n"); + return 1; + } + /* if we have no list, we need to rescan */ + if (pL->frag.listCount == 0) { + DEBUGF ("rescan: fraglist zero\n"); + return 1; + } + + /* or if we are scanning a new partition */ + if (pL->partOffset != part->offset) { + DEBUGF ("rescan: different partition\n"); + return 1; + } + + /* FIXME */ +#if 0 + /* but suppose someone reflashed a partition at the same offset... */ + b = pL->dir.listHead; + while (b) { + node = (struct jffs2_unknown_node *) get_fl_mem(b->offset, + sizeof(onode), &onode); + if (node->nodetype != JFFS2_NODETYPE_DIRENT) { + DEBUGF ("rescan: fs changed beneath me? (%lx)\n", + (unsigned long) b->offset); + return 1; + } + b = b->next; + } +#endif + return 0; +} + +#ifdef DEBUG_FRAGMENTS +static void +dump_fragments(struct b_lists *pL) +{ + struct b_node *b; + struct jffs2_raw_inode ojNode; + struct jffs2_raw_inode *jNode; + + putstr("\r\n\r\n******The fragment Entries******\r\n"); + b = pL->frag.listHead; + while (b) { + jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset, + sizeof(ojNode), &ojNode); + putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset); + putLabeledWord("\tbuild_list: totlen = ", jNode->totlen); + putLabeledWord("\tbuild_list: inode = ", jNode->ino); + putLabeledWord("\tbuild_list: version = ", jNode->version); + putLabeledWord("\tbuild_list: isize = ", jNode->isize); + putLabeledWord("\tbuild_list: atime = ", jNode->atime); + putLabeledWord("\tbuild_list: offset = ", jNode->offset); + putLabeledWord("\tbuild_list: csize = ", jNode->csize); + putLabeledWord("\tbuild_list: dsize = ", jNode->dsize); + putLabeledWord("\tbuild_list: compr = ", jNode->compr); + putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr); + putLabeledWord("\tbuild_list: flags = ", jNode->flags); + putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */ + b = b->next; + } +} +#endif + +#ifdef DEBUG_DIRENTS +static void +dump_dirents(struct b_lists *pL) +{ + struct b_node *b; + struct jffs2_raw_dirent *jDir; + + putstr("\r\n\r\n******The directory Entries******\r\n"); + b = pL->dir.listHead; + while (b) { + jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset); + putstr("\r\n"); + putnstr(jDir->name, jDir->nsize); + putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic); + putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype); + putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc); + putLabeledWord("\tbuild_list: pino = ", jDir->pino); + putLabeledWord("\tbuild_list: version = ", jDir->version); + putLabeledWord("\tbuild_list: ino = ", jDir->ino); + putLabeledWord("\tbuild_list: mctime = ", jDir->mctime); + putLabeledWord("\tbuild_list: nsize = ", jDir->nsize); + putLabeledWord("\tbuild_list: type = ", jDir->type); + putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc); + putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc); + putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */ + b = b->next; + put_fl_mem(jDir); + } +} +#endif + +static int +jffs2_fill_scan_buf(nand_info_t *nand, unsigned char *buf, + unsigned ofs, unsigned len) +{ + int ret; + unsigned olen; + + olen = len; + ret = nand_read(nand, ofs, &olen, buf); + if (ret) { + printf("nand_read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret); + return ret; + } + if (olen < len) { + printf("Read at 0x%x gave only 0x%x bytes\n", ofs, olen); + return -1; + } + return 0; +} + +#define EMPTY_SCAN_SIZE 1024 +static u32 +jffs2_1pass_build_lists(struct part_info * part) +{ + struct b_lists *pL; + struct jffs2_unknown_node *node; + unsigned nr_blocks, sectorsize, ofs, offset; + char *buf; + int i; + u32 counter = 0; + u32 counter4 = 0; + u32 counterF = 0; + u32 counterN = 0; + + struct mtdids *id = part->dev->id; + nand = nand_info + id->num; + + /* if we are building a list we need to refresh the cache. */ + jffs_init_1pass_list(part); + pL = (struct b_lists *)part->jffs2_priv; + pL->partOffset = part->offset; + puts ("Scanning JFFS2 FS: "); + + sectorsize = nand->erasesize; + nr_blocks = part->size / sectorsize; + buf = malloc(sectorsize); + if (!buf) + return 0; + + for (i = 0; i < nr_blocks; i++) { + printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]); + + offset = part->offset + i * sectorsize; + + if (nand_block_isbad(nand, offset)) + continue; + + if (jffs2_fill_scan_buf(nand, buf, offset, EMPTY_SCAN_SIZE)) + return 0; + + ofs = 0; + /* Scan only 4KiB of 0xFF before declaring it's empty */ + while (ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) + ofs += 4; + if (ofs == EMPTY_SCAN_SIZE) + continue; + + if (jffs2_fill_scan_buf(nand, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE)) + return 0; + offset += ofs; + + while (ofs < sectorsize - sizeof(struct jffs2_unknown_node)) { + node = (struct jffs2_unknown_node *)&buf[ofs]; + if (node->magic != JFFS2_MAGIC_BITMASK || !hdr_crc(node)) { + offset += 4; + ofs += 4; + counter4++; + continue; + } + /* if its a fragment add it */ + if (node->nodetype == JFFS2_NODETYPE_INODE && + inode_crc((struct jffs2_raw_inode *) node)) { + if (insert_inode(&pL->frag, (struct jffs2_raw_inode *) node, + offset) == NULL) { + return 0; + } + } else if (node->nodetype == JFFS2_NODETYPE_DIRENT && + dirent_crc((struct jffs2_raw_dirent *) node) && + dirent_name_crc((struct jffs2_raw_dirent *) node)) { + if (! (counterN%100)) + puts ("\b\b. "); + if (insert_dirent(&pL->dir, (struct jffs2_raw_dirent *) node, + offset) == NULL) { + return 0; + } + counterN++; + } else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) { + if (node->totlen != sizeof(struct jffs2_unknown_node)) + printf("OOPS Cleanmarker has bad size " + "%d != %d\n", node->totlen, + sizeof(struct jffs2_unknown_node)); + } else if (node->nodetype == JFFS2_NODETYPE_PADDING) { + if (node->totlen < sizeof(struct jffs2_unknown_node)) + printf("OOPS Padding has bad size " + "%d < %d\n", node->totlen, + sizeof(struct jffs2_unknown_node)); + } else { + printf("Unknown node type: %x len %d " + "offset 0x%x\n", node->nodetype, + node->totlen, offset); + } + offset += ((node->totlen + 3) & ~3); + ofs += ((node->totlen + 3) & ~3); + counterF++; + } + } + + putstr("\b\b done.\r\n"); /* close off the dots */ + +#if 0 + putLabeledWord("dir entries = ", pL->dir.listCount); + putLabeledWord("frag entries = ", pL->frag.listCount); + putLabeledWord("+4 increments = ", counter4); + putLabeledWord("+file_offset increments = ", counterF); +#endif + +#ifdef DEBUG_DIRENTS + dump_dirents(pL); +#endif + +#ifdef DEBUG_FRAGMENTS + dump_fragments(pL); +#endif + + /* give visual feedback that we are done scanning the flash */ + led_blink(0x0, 0x0, 0x1, 0x1); /* off, forever, on 100ms, off 100ms */ + free(buf); + + return 1; +} + + +static u32 +jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL) +{ + struct b_node *b; + struct jffs2_raw_inode ojNode; + struct jffs2_raw_inode *jNode; + int i; + + for (i = 0; i < JFFS2_NUM_COMPR; i++) { + piL->compr_info[i].num_frags = 0; + piL->compr_info[i].compr_sum = 0; + piL->compr_info[i].decompr_sum = 0; + } +/* FIXME + b = pL->frag.listHead; + while (b) { + jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset, + sizeof(ojNode), &ojNode); + if (jNode->compr < JFFS2_NUM_COMPR) { + piL->compr_info[jNode->compr].num_frags++; + piL->compr_info[jNode->compr].compr_sum += jNode->csize; + piL->compr_info[jNode->compr].decompr_sum += jNode->dsize; + } + b = b->next; + } +*/ + return 0; +} + + +static struct b_lists * +jffs2_get_list(struct part_info * part, const char *who) +{ + if (jffs2_1pass_rescan_needed(part)) { + if (!jffs2_1pass_build_lists(part)) { + printf("%s: Failed to scan JFFSv2 file structure\n", who); + return NULL; + } + } + return (struct b_lists *)part->jffs2_priv; +} + + +/* Print directory / file contents */ +u32 +jffs2_1pass_ls(struct part_info * part, const char *fname) +{ + struct b_lists *pl; + long ret = 0; + u32 inode; + + if (! (pl = jffs2_get_list(part, "ls"))) + return 0; + + if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) { + putstr("ls: Failed to scan jffs2 file structure\r\n"); + return 0; + } + +#if 0 + putLabeledWord("found file at inode = ", inode); + putLabeledWord("read_inode returns = ", ret); +#endif + + return ret; +} + + +/* Load a file from flash into memory. fname can be a full path */ +u32 +jffs2_1pass_load(char *dest, struct part_info * part, const char *fname) +{ + + struct b_lists *pl; + long ret = 0; + u32 inode; + + if (! (pl = jffs2_get_list(part, "load"))) + return 0; + + if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) { + putstr("load: Failed to find inode\r\n"); + return 0; + } + + /* Resolve symlinks */ + if (! (inode = jffs2_1pass_resolve_inode(pl, inode))) { + putstr("load: Failed to resolve inode structure\r\n"); + return 0; + } + + if ((ret = jffs2_1pass_read_inode(pl, inode, dest, NULL)) < 0) { + putstr("load: Failed to read inode\r\n"); + return 0; + } + + DEBUGF ("load: loaded '%s' to 0x%lx (%ld bytes)\n", fname, + (unsigned long) dest, ret); + return ret; +} + +/* Return information about the fs on this partition */ +u32 +jffs2_1pass_info(struct part_info * part) +{ + struct b_jffs2_info info; + struct b_lists *pl; + int i; + + if (! (pl = jffs2_get_list(part, "info"))) + return 0; + + jffs2_1pass_fill_info(pl, &info); + for (i = 0; i < JFFS2_NUM_COMPR; i++) { + printf ("Compression: %s\n" + "\tfrag count: %d\n" + "\tcompressed sum: %d\n" + "\tuncompressed sum: %d\n", + compr_names[i], + info.compr_info[i].num_frags, + info.compr_info[i].compr_sum, + info.compr_info[i].decompr_sum); + } + return 1; +} + +#endif /* CFG_CMD_JFFS2 */ diff --git a/fs/jffs2/jffs2_nand_private.h b/fs/jffs2/jffs2_nand_private.h new file mode 100644 index 0000000..18cca8d --- /dev/null +++ b/fs/jffs2/jffs2_nand_private.h @@ -0,0 +1,133 @@ +#ifndef jffs2_private_h +#define jffs2_private_h + +#include + +struct b_node { + struct b_node *next; +}; + +struct b_inode { + struct b_inode *next; + u32 offset; /* physical offset to beginning of real inode */ + u32 version; + u32 ino; + u32 isize; + u32 csize; +}; + +struct b_dirent { + struct b_dirent *next; + u32 offset; /* physical offset to beginning of real dirent */ + u32 version; + u32 pino; + u32 ino; + unsigned int nhash; + unsigned char nsize; + unsigned char type; +}; + +struct b_list { + struct b_node *listTail; + struct b_node *listHead; + unsigned int listCount; + struct mem_block *listMemBase; +}; + +struct b_lists { + char *partOffset; + struct b_list dir; + struct b_list frag; +}; + +struct b_compr_info { + u32 num_frags; + u32 compr_sum; + u32 decompr_sum; +}; + +struct b_jffs2_info { + struct b_compr_info compr_info[JFFS2_NUM_COMPR]; +}; + +static inline int +hdr_crc(struct jffs2_unknown_node *node) +{ +#if 1 + u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4); +#else + /* what's the semantics of this? why is this here? */ + u32 crc = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4); + + crc ^= ~0; +#endif + if (node->hdr_crc != crc) { + return 0; + } else { + return 1; + } +} + +static inline int +dirent_crc(struct jffs2_raw_dirent *node) +{ + if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_dirent) - 8)) { + return 0; + } else { + return 1; + } +} + +static inline int +dirent_name_crc(struct jffs2_raw_dirent *node) +{ + if (node->name_crc != crc32_no_comp(0, (unsigned char *)&(node->name), node->nsize)) { + return 0; + } else { + return 1; + } +} + +static inline int +inode_crc(struct jffs2_raw_inode *node) +{ + if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_inode) - 8)) { + return 0; + } else { + return 1; + } +} + +/* Borrowed from include/linux/dcache.h */ + +/* Name hashing routines. Initial hash value */ +/* Hash courtesy of the R5 hash in reiserfs modulo sign bits */ +#define init_name_hash() 0 + +/* partial hash update function. Assume roughly 4 bits per character */ +static inline unsigned long +partial_name_hash(unsigned long c, unsigned long prevhash) +{ + return (prevhash + (c << 4) + (c >> 4)) * 11; +} + +/* + * Finally: cut down the number of bits to a int value (and try to avoid + * losing bits) + */ +static inline unsigned long end_name_hash(unsigned long hash) +{ + return (unsigned int) hash; +} + +/* Compute the hash for a name string. */ +static inline unsigned int +full_name_hash(const unsigned char *name, unsigned int len) +{ + unsigned long hash = init_name_hash(); + while (len--) + hash = partial_name_hash(*name++, hash); + return end_name_hash(hash); +} + +#endif /* jffs2_private.h */ diff --git a/fs/jffs2/jffs2_private.h b/fs/jffs2/jffs2_private.h index 65ca6eb..46ed644 100644 --- a/fs/jffs2/jffs2_private.h +++ b/fs/jffs2/jffs2_private.h @@ -85,4 +85,16 @@ inode_crc(struct jffs2_raw_inode *node) } } +static inline int +data_crc(struct jffs2_raw_inode *node) +{ + if (node->data_crc != crc32_no_comp(0, (unsigned char *) + ((int) &node->node_crc + sizeof (node->node_crc)), + node->csize)) { + return 0; + } else { + return 1; + } +} + #endif /* jffs2_private.h */ diff --git a/fs/jffs2/mini_inflate.c b/fs/jffs2/mini_inflate.c index 4f511ec..834fb74 100644 --- a/fs/jffs2/mini_inflate.c +++ b/fs/jffs2/mini_inflate.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * Filename: mini_inflate.c - * Version: $Id: mini_inflate.c,v 1.3 2002/01/24 22:58:42 rfeany Exp $ + * Version: $Id: mini_inflate.c,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * Copyright: Copyright (C) 2001, Russ Dill * Author: Russ Dill * Description: Mini inflate implementation (RFC 1951) diff --git a/include/_exports.h b/include/_exports.h index 61dcaaf..d823c95 100644 --- a/include/_exports.h +++ b/include/_exports.h @@ -12,7 +12,14 @@ EXPORT_FUNC(udelay) EXPORT_FUNC(get_timer) EXPORT_FUNC(vprintf) EXPORT_FUNC(do_reset) +#ifdef CONFIG_MARVELL +EXPORT_FUNC(realloc) +EXPORT_FUNC(calloc) +EXPORT_FUNC(memalign) +EXPORT_FUNC(mvGetRtcSec) +#endif #if (CONFIG_COMMANDS & CFG_CMD_I2C) EXPORT_FUNC(i2c_write) EXPORT_FUNC(i2c_read) #endif /* CFG_CMD_I2C */ + diff --git a/include/ahci.h b/include/ahci.h new file mode 100644 index 0000000..80701e2 --- /dev/null +++ b/include/ahci.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved. + * Author: Jason Jin + * Zhang Wei + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 _AHCI_H_ +#define _AHCI_H_ + +#define AHCI_PCI_BAR 0x24 +#define AHCI_MAX_SG 56 /* hardware max is 64K */ +#define AHCI_CMD_SLOT_SZ 32 +#define AHCI_RX_FIS_SZ 256 +#define AHCI_CMD_TBL_HDR 0x80 +#define AHCI_CMD_TBL_CDB 0x40 +#define AHCI_CMD_TBL_SZ AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16) +#define AHCI_PORT_PRIV_DMA_SZ AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ \ + + AHCI_RX_FIS_SZ +#define AHCI_CMD_ATAPI (1 << 5) +#define AHCI_CMD_WRITE (1 << 6) +#define AHCI_CMD_PREFETCH (1 << 7) +#define AHCI_CMD_RESET (1 << 8) +#define AHCI_CMD_CLR_BUSY (1 << 10) + +#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ + +/* Global controller registers */ +#define HOST_CAP 0x00 /* host capabilities */ +#define HOST_CTL 0x04 /* global host control */ +#define HOST_IRQ_STAT 0x08 /* interrupt status */ +#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ +#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ + +/* HOST_CTL bits */ +#define HOST_RESET (1 << 0) /* reset controller; self-clear */ +#define HOST_IRQ_EN (1 << 1) /* global IRQ enable */ +#define HOST_AHCI_EN (1 << 31) /* AHCI enabled */ + +/* Registers for each SATA port */ +#define PORT_LST_ADDR 0x00 /* command list DMA addr */ +#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ +#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ +#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ +#define PORT_IRQ_STAT 0x10 /* interrupt status */ +#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ +#define PORT_CMD 0x18 /* port command */ +#define PORT_TFDATA 0x20 /* taskfile data */ +#define PORT_SIG 0x24 /* device TF signature */ +#define PORT_CMD_ISSUE 0x38 /* command issue */ +#define PORT_SCR 0x28 /* SATA phy register block */ +#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ +#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ +#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ +#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ + +/* PORT_IRQ_{STAT,MASK} bits */ +#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ +#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ +#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ +#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ +#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ +#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ +#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ +#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ + +#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ +#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ +#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ +#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ +#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ +#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ +#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ +#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ +#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ + +#define PORT_IRQ_FATAL PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_ERR \ + | PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_ERR + +#define DEF_PORT_IRQ PORT_IRQ_FATAL | PORT_IRQ_PHYRDY \ + | PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE \ + | PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS \ + | PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS \ + | PORT_IRQ_D2H_REG_FIS + +/* PORT_CMD bits */ +#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ +#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ +#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ +#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ +#define PORT_CMD_CLO (1 << 3) /* Command list override */ +#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ +#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ +#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ + +#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ +#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ +#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ + +#define AHCI_MAX_PORTS 32 + +/* SETFEATURES stuff */ +#define SETFEATURES_XFER 0x03 +#define XFER_UDMA_7 0x47 +#define XFER_UDMA_6 0x46 +#define XFER_UDMA_5 0x45 +#define XFER_UDMA_4 0x44 +#define XFER_UDMA_3 0x43 +#define XFER_UDMA_2 0x42 +#define XFER_UDMA_1 0x41 +#define XFER_UDMA_0 0x40 +#define XFER_MW_DMA_2 0x22 +#define XFER_MW_DMA_1 0x21 +#define XFER_MW_DMA_0 0x20 +#define XFER_SW_DMA_2 0x12 +#define XFER_SW_DMA_1 0x11 +#define XFER_SW_DMA_0 0x10 +#define XFER_PIO_4 0x0C +#define XFER_PIO_3 0x0B +#define XFER_PIO_2 0x0A +#define XFER_PIO_1 0x09 +#define XFER_PIO_0 0x08 +#define XFER_PIO_SLOW 0x00 + +#define ATA_FLAG_SATA (1 << 3) +#define ATA_FLAG_NO_LEGACY (1 << 4) /* no legacy mode check */ +#define ATA_FLAG_MMIO (1 << 6) /* use MMIO, not PIO */ +#define ATA_FLAG_SATA_RESET (1 << 7) /* (obsolete) use COMRESET */ +#define ATA_FLAG_PIO_DMA (1 << 8) /* PIO cmds via DMA */ +#define ATA_FLAG_NO_ATAPI (1 << 11) /* No ATAPI support */ + +struct ahci_cmd_hdr { + u32 opts; + u32 status; + u32 tbl_addr; + u32 tbl_addr_hi; + u32 reserved[4]; +}; + +struct ahci_sg { + u32 addr; + u32 addr_hi; + u32 reserved; + u32 flags_size; +}; + +struct ahci_ioports { + u32 cmd_addr; + u32 scr_addr; + u32 port_mmio; + struct ahci_cmd_hdr *cmd_slot; + struct ahci_sg *cmd_tbl_sg; + u32 cmd_tbl; + u32 rx_fis; +}; + +struct ahci_probe_ent { + pci_dev_t dev; + struct ahci_ioports port[AHCI_MAX_PORTS]; + u32 n_ports; + u32 hard_port_no; + u32 host_flags; + u32 host_set_flags; + u32 mmio_base; + u32 pio_mask; + u32 udma_mask; + u32 flags; + u32 cap; /* cache of HOST_CAP register */ + u32 port_map; /* cache of HOST_PORTS_IMPL reg */ + u32 link_port_map; /*linkup port map*/ +}; + +#endif diff --git a/include/asm-arm/arch-arm926ejs/vfp.h b/include/asm-arm/arch-arm926ejs/vfp.h new file mode 100644 index 0000000..051a474 --- /dev/null +++ b/include/asm-arm/arch-arm926ejs/vfp.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + * + * VFP register definitions. + * First, the standard VFP set. + */ + +#define FPSID c0 +#define FPSCR c1 +#define FPEXC c8 + +/* FPSID bits */ +#define FPSID_IMPLEMENTER_BIT (24) +#define FPSID_IMPLEMENTER_MASK (0xff << FPSID_IMPLEMENTER_BIT) +#define FPSID_SOFTWARE (1<<23) +#define FPSID_FORMAT_BIT (21) +#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT) +#define FPSID_NODOUBLE (1<<20) +#define FPSID_ARCH_BIT (16) +#define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT) +#define FPSID_PART_BIT (8) +#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT) +#define FPSID_VARIANT_BIT (4) +#define FPSID_VARIANT_MASK (0xF << FPSID_VARIANT_BIT) +#define FPSID_REV_BIT (0) +#define FPSID_REV_MASK (0xF << FPSID_REV_BIT) + +/* FPEXC bits */ +#define FPEXC_EXCEPTION (1<<31) +#define FPEXC_ENABLE (1<<30) + +/* FPSCR bits */ +#define FPSCR_DEFAULT_NAN (1<<25) +#define FPSCR_FLUSHTOZERO (1<<24) +#define FPSCR_ROUND_NEAREST (0<<22) +#define FPSCR_ROUND_PLUSINF (1<<22) +#define FPSCR_ROUND_MINUSINF (2<<22) +#define FPSCR_ROUND_TOZERO (3<<22) +#define FPSCR_RMODE_BIT (22) +#define FPSCR_RMODE_MASK (3 << FPSCR_RMODE_BIT) +#define FPSCR_STRIDE_BIT (20) +#define FPSCR_STRIDE_MASK (3 << FPSCR_STRIDE_BIT) +#define FPSCR_LENGTH_BIT (16) +#define FPSCR_LENGTH_MASK (7 << FPSCR_LENGTH_BIT) +#define FPSCR_IOE (1<<8) +#define FPSCR_DZE (1<<9) +#define FPSCR_OFE (1<<10) +#define FPSCR_UFE (1<<11) +#define FPSCR_IXE (1<<12) +#define FPSCR_IDE (1<<15) +#define FPSCR_IOC (1<<0) +#define FPSCR_DZC (1<<1) +#define FPSCR_OFC (1<<2) +#define FPSCR_UFC (1<<3) +#define FPSCR_IXC (1<<4) +#define FPSCR_IDC (1<<7) + +/* + * VFP9-S specific. + */ +#define FPINST c9 +#define FPINST2 c10 + +/* FPEXC bits */ +#define FPEXC_FPV2 (1<<28) +#define FPEXC_LENGTH_BIT (8) +#define FPEXC_LENGTH_MASK (7 << FPEXC_LENGTH_BIT) +#define FPEXC_INV (1 << 7) +#define FPEXC_UFC (1 << 3) +#define FPEXC_OFC (1 << 2) +#define FPEXC_IOC (1 << 0) + +/* Bit patterns for decoding the packaged operation descriptors */ +#define VFPOPDESC_LENGTH_BIT (9) +#define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT) +#define VFPOPDESC_UNUSED_BIT (24) +#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT) +#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK)) diff --git a/include/asm-arm/arch-arm926ejs/vfpinstr.h b/include/asm-arm/arch-arm926ejs/vfpinstr.h new file mode 100644 index 0000000..39cbef3 --- /dev/null +++ b/include/asm-arm/arch-arm926ejs/vfpinstr.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * 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. + * + * VFP instruction masks. + */ +#define INST_CPRTDO(inst) (((inst) & 0x0f000000) == 0x0e000000) +#define INST_CPRT(inst) ((inst) & (1 << 4)) +#define INST_CPRT_L(inst) ((inst) & (1 << 20)) +#define INST_CPRT_Rd(inst) (((inst) & (15 << 12)) >> 12) +#define INST_CPRT_OP(inst) (((inst) >> 21) & 7) +#define INST_CPNUM(inst) ((inst) & 0xf00) +#define CPNUM(cp) ((cp) << 8) + +#define FOP_MASK (0x00b00040) +#define FOP_FMAC (0x00000000) +#define FOP_FNMAC (0x00000040) +#define FOP_FMSC (0x00100000) +#define FOP_FNMSC (0x00100040) +#define FOP_FMUL (0x00200000) +#define FOP_FNMUL (0x00200040) +#define FOP_FADD (0x00300000) +#define FOP_FSUB (0x00300040) +#define FOP_FDIV (0x00800000) +#define FOP_EXT (0x00b00040) + +#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) + +#define FEXT_MASK (0x000f0080) +#define FEXT_FCPY (0x00000000) +#define FEXT_FABS (0x00000080) +#define FEXT_FNEG (0x00010000) +#define FEXT_FSQRT (0x00010080) +#define FEXT_FCMP (0x00040000) +#define FEXT_FCMPE (0x00040080) +#define FEXT_FCMPZ (0x00050000) +#define FEXT_FCMPEZ (0x00050080) +#define FEXT_FCVT (0x00070080) +#define FEXT_FUITO (0x00080000) +#define FEXT_FSITO (0x00080080) +#define FEXT_FTOUI (0x000c0000) +#define FEXT_FTOUIZ (0x000c0080) +#define FEXT_FTOSI (0x000d0000) +#define FEXT_FTOSIZ (0x000d0080) + +#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) + +#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) +#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12) +#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) +#define vfp_get_dm(inst) ((inst & 0x0000000f)) +#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) +#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16) + +#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) + +#define FPSCR_N (1 << 31) +#define FPSCR_Z (1 << 30) +#define FPSCR_C (1 << 29) +#define FPSCR_V (1 << 28) + +/* + * Since we aren't building with -mfpu=vfp, we need to code + * these instructions using their MRC/MCR equivalents. + */ +#define vfpreg(_vfp_) #_vfp_ + +#define fmrx(_vfp_) ({ \ + u32 __v; \ + asm("mrc%? p10, 7, %0, " vfpreg(_vfp_) ", c0, 0 @ fmrx %0, " #_vfp_ \ + : "=r" (__v)); \ + __v; \ + }) + +#define fmxr(_vfp_,_var_) \ + asm("mcr%? p10, 7, %0, " vfpreg(_vfp_) ", c0, 0 @ fmxr " #_vfp_ ", %0" \ + : : "r" (_var_)) + diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h index a62679a..f15ce9c 100644 --- a/include/asm-arm/arch-pxa/mmc.h +++ b/include/asm-arm/arch-pxa/mmc.h @@ -4,7 +4,7 @@ * Author: Vladimir Shebordaev, Igor Oblakov * Copyright: MontaVista Software Inc. * - * $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $ + * $Id: mmc.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * 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 diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h index 4b8bab2..2859615 100644 --- a/include/asm-arm/bitops.h +++ b/include/asm-arm/bitops.h @@ -91,6 +91,15 @@ static inline int test_bit(int nr, const void * addr) return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7)); } +/* Return the bit position of the most significant 1 bit in a word */ +extern __inline__ int __ilog2(unsigned int x) +{ + int lz; + + asm ("clz %0,%1" : "=r" (lz) : "r" (x)); + return 31 - lz; +} + /* * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. diff --git a/include/asm-arm/global_data.h b/include/asm-arm/global_data.h index c2d5291..b33175c 100644 --- a/include/asm-arm/global_data.h +++ b/include/asm-arm/global_data.h @@ -45,6 +45,10 @@ typedef struct global_data { #ifdef CONFIG_VFD unsigned char vfd_type; /* display type */ #endif +#ifdef CONFIG_MARVELL + unsigned long bus_clk; + unsigned int tclk; +#endif #if 0 unsigned long cpu_clk; /* CPU clock in Hz! */ unsigned long bus_clk; @@ -52,6 +56,11 @@ typedef struct global_data { unsigned long reset_status; /* reset status register at boot */ #endif void **jt; /* jump table */ +#ifdef CONFIG_MARVELL + unsigned long ram_size; /* RAM size */ + unsigned int ddr_clk; +#endif + } gd_t; /* @@ -61,6 +70,7 @@ typedef struct global_data { #define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */ #define GD_FLG_SILENT 0x00004 /* Silent mode */ -#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") +#define DECLARE_GLOBAL_DATA_PTR +register volatile gd_t *gd asm ("r8"); #endif /* __ASM_GBL_DATA_H */ diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index c2b69fb..919c6d3 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -193,7 +193,6 @@ extern void __readwrite_bug(const char *fn); * ioremap. */ #ifdef __mem_pci - #define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; }) #define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; }) #define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; }) diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h index 89df4dc..8259885 100644 --- a/include/asm-arm/setup.h +++ b/include/asm-arm/setup.h @@ -205,6 +205,21 @@ struct tag_memclk { u32 fmemclk; }; +#if defined (CONFIG_MARVELL_TAG) +/* Marvell uboot parameters */ +#define ATAG_MV_UBOOT 0x41000403 + +struct tag_mv_uboot { + u32 uboot_version; + u32 tclk; + u32 sysclk; + u32 isUsbHost; + char macAddr[4][6]; + u16 mtu[4]; + u32 fw_image_base; + u32 fw_image_size; +}; +#endif struct tag { struct tag_header hdr; union { @@ -227,6 +242,12 @@ struct tag { * DC21285 specific */ struct tag_memclk memclk; +#if defined (CONFIG_MARVELL_TAG) + /* + * Marvell specific + */ + struct tag_mv_uboot mv_uboot; +#endif } u; }; diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h index b9604cf..dd16aea 100644 --- a/include/asm-mips/byteorder.h +++ b/include/asm-mips/byteorder.h @@ -1,4 +1,4 @@ -/* $Id: byteorder.h,v 1.8 1998/11/02 09:29:32 ralf Exp $ +/* $Id: byteorder.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff --git a/include/asm-mips/posix_types.h b/include/asm-mips/posix_types.h index 879aae2..22798ce 100644 --- a/include/asm-mips/posix_types.h +++ b/include/asm-mips/posix_types.h @@ -1,4 +1,4 @@ -/* $Id: posix_types.h,v 1.6 2000/02/04 23:32:54 ralf Exp $ +/* $Id: posix_types.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h index 463a111..03665fc 100644 --- a/include/asm-mips/string.h +++ b/include/asm-mips/string.h @@ -1,4 +1,4 @@ -/* $Id: string.h,v 1.13 2000/02/19 14:12:14 harald Exp $ +/* $Id: string.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h index e757e22..f7d0ac8 100644 --- a/include/asm-mips/types.h +++ b/include/asm-mips/types.h @@ -1,4 +1,4 @@ -/* $Id: types.h,v 1.3 1999/08/18 23:37:50 ralf Exp $ +/* $Id: types.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff --git a/include/bedbug/bedbug.h b/include/bedbug/bedbug.h index 471215e..d0cc6f2 100644 --- a/include/bedbug/bedbug.h +++ b/include/bedbug/bedbug.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: bedbug.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ #ifndef _BEDBUG_H #define _BEDBUG_H diff --git a/include/bedbug/ppc.h b/include/bedbug/ppc.h index 9cc8f9f..4917fef 100644 --- a/include/bedbug/ppc.h +++ b/include/bedbug/ppc.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: ppc.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ #ifndef _PPC_H #define _PPC_H diff --git a/include/bedbug/regs.h b/include/bedbug/regs.h index 938e435..56302d6 100644 --- a/include/bedbug/regs.h +++ b/include/bedbug/regs.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: regs.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ #ifndef _REGS_H #define _REGS_H diff --git a/include/bedbug/tables.h b/include/bedbug/tables.h index 66cf8ea..860c323 100644 --- a/include/bedbug/tables.h +++ b/include/bedbug/tables.h @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: tables.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ #ifndef TABLES_H #define TABLES_H diff --git a/include/cmd_confdefs.h b/include/cmd_confdefs.h index 9ee4849..6573b6d 100644 --- a/include/cmd_confdefs.h +++ b/include/cmd_confdefs.h @@ -94,7 +94,7 @@ #define CFG_CMD_EXT2 0x1000000000000000ULL /* EXT2 Support */ #define CFG_CMD_SNTP 0x2000000000000000ULL /* SNTP support */ #define CFG_CMD_DISPLAY 0x4000000000000000ULL /* Display support */ - +#define CFG_CMD_RCVR 0x8000000000000000ULL /* Recovery Support */ #define CFG_CMD_ALL 0xFFFFFFFFFFFFFFFFULL /* ALL commands */ /* Commands that are considered "non-standard" for some reason diff --git a/include/common.h b/include/common.h index d2570a8..98e4f72 100644 --- a/include/common.h +++ b/include/common.h @@ -388,7 +388,9 @@ int checkicache (void); int checkdcache (void); void upmconfig (unsigned int, unsigned int *, unsigned int); ulong get_tbclk (void); +#ifndef CONFIG_MARVELL void reset_cpu (ulong addr); +#endif /* $(CPU)/serial.c */ int serial_init (void); diff --git a/include/configs/DB64360.h b/include/configs/DB64360.h index bd7aff1..ce867b8 100644 --- a/include/configs/DB64360.h +++ b/include/configs/DB64360.h @@ -29,7 +29,7 @@ * (c) 2002 Datentechnik AG - Project: Dino * * - * $Id: DB64360.h,v 1.3 2003/04/26 04:58:13 brad Exp $ + * $Id: DB64360.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * ************************************************************************/ @@ -38,6 +38,15 @@ * History: * * $Log: DB64360.h,v $ + * Revision 1.1.1.1 2008-12-15 11:39:22 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:12 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:16 wokes + * marvell 88f6281 u-boot + * * Revision 1.3 2003/04/26 04:58:13 brad * Cosmetic changes and compiler warning cleanups * diff --git a/include/configs/DU405.h b/include/configs/DU405.h index 5489a53..cc5ff62 100644 --- a/include/configs/DU405.h +++ b/include/configs/DU405.h @@ -32,7 +32,7 @@ * High Level Configuration Options * (easy to change) */ -#define CONFIG_IDENT_STRING " $Name: $" +#define CONFIG_IDENT_STRING " $Name: R-3-4-0-B20110226-branch $" #define CONFIG_405GP 1 /* This is a PPC405 CPU */ #define CONFIG_4xx 1 /* ...member of PPC4xx family */ diff --git a/include/configs/KAREF.h b/include/configs/KAREF.h index 7bbceb0..887a689 100644 --- a/include/configs/KAREF.h +++ b/include/configs/KAREF.h @@ -26,7 +26,7 @@ ***********************************************************************/ /* - * $Id: KAREF.h,v 1.6 2005/06/03 15:05:25 tsawyer Exp $ + * $Id: KAREF.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * */ diff --git a/include/configs/METROBOX.h b/include/configs/METROBOX.h index b965571..7f3e76a 100644 --- a/include/configs/METROBOX.h +++ b/include/configs/METROBOX.h @@ -25,10 +25,19 @@ ***********************************************************************/ /* - * $Id: METROBOX.h,v 1.21 2005/06/03 15:05:25 tsawyer Exp $ + * $Id: METROBOX.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * * $Log: METROBOX.h,v $ + * Revision 1.1.1.1 2008-12-15 11:39:22 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:11 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:16 wokes + * marvell 88f6281 u-boot + * * Revision 1.21 2005/06/03 15:05:25 tsawyer * MB rev 2.0.3 KA rev 0.0.7. Add CONFIG_VERSION_VARIABLE, Add fakeled to MB * diff --git a/include/configs/PCI405.h b/include/configs/PCI405.h index 9d5c4f4..cbffd87 100644 --- a/include/configs/PCI405.h +++ b/include/configs/PCI405.h @@ -32,7 +32,7 @@ * High Level Configuration Options * (easy to change) */ -#define CONFIG_IDENT_STRING " $Name: esd_PCI405_05_07_28 $" +#define CONFIG_IDENT_STRING " $Name: R-3-4-0-B20110226-branch $" #define CONFIG_405GP 1 /* This is a PPC405 CPU */ #define CONFIG_4xx 1 /* ...member of PPC4xx family */ diff --git a/include/configs/WUH405.h b/include/configs/WUH405.h index d92f81f..93feb06 100644 --- a/include/configs/WUH405.h +++ b/include/configs/WUH405.h @@ -32,7 +32,7 @@ * High Level Configuration Options * (easy to change) */ -#define CONFIG_IDENT_STRING " $Name: $" +#define CONFIG_IDENT_STRING " $Name: R-3-4-0-B20110226-branch $" #define CONFIG_405EP 1 /* This is a PPC405 CPU */ #define CONFIG_4xx 1 /* ...member of PPC4xx family */ diff --git a/include/configs/barco.h b/include/configs/barco.h index 624fa1d..adf0202 100644 --- a/include/configs/barco.h +++ b/include/configs/barco.h @@ -2,13 +2,22 @@ * * Unless otherwise specified, Copyright (C) 2004-2005 Barco Control Rooms * - * $Source: /home/services/cvs/firmware/ppc/u-boot-1.1.2/include/configs/barco.h,v $ - * $Revision: 1.2 $ - * $Author: mleeman $ - * $Date: 2005/02/21 12:48:58 $ + * $Source: /home/cvsroot/NasX86/Others/bootldr/u-boot-1.1.4_mv-3.4.4/include/configs/barco.h,v $ + * $Revision: 1.1.1.1 $ + * $Author: wokes $ + * $Date: 2008-12-15 11:39:22 $ * * Last ChangeLog Entry * $Log: barco.h,v $ + * Revision 1.1.1.1 2008-12-15 11:39:22 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:17:11 wokes + * marvell 88f6281 u-boot + * + * Revision 1.1.1.1 2008/12/15 11:05:16 wokes + * marvell 88f6281 u-boot + * * Revision 1.2 2005/02/21 12:48:58 mleeman * update of copyright years (feedback wd) * diff --git a/include/configs/mv_dd.h b/include/configs/mv_dd.h new file mode 100644 index 0000000..168f279 --- /dev/null +++ b/include/configs/mv_dd.h @@ -0,0 +1,548 @@ +/* + * (C) Copyright 2001 + * Josh Huber , Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include "../../board/mv_feroceon/mv_dd/mvSysHwConfig.h" + +/************/ +/* VERSIONS */ +/************/ +#define BUILD_TAG "3.2.5" +#define CONFIG_IDENT_STRING " Marvell version: 3.2.5" + +/* version number passing when loading Kernel */ +#define VER_NUM 0x03020500 /* 3.2.5 */ + +/* magic word pass when booting Kernel */ +#define MV_UBOOT_MAGIC 0xa0b1c2d3 + +/********************/ +/* MV DEV SUPPORTS */ +/********************/ +#define CONFIG_PCI /* pci support */ +#define CONFIG_PCI_1 /* sec pci interface support */ +#define CONFIG_INTERNAL_SRAM /* internal SRAM */ +#undef CONFIG_SNOOP_SUPPORT /* Snoop Support */ +#define CONFIG_XOR /* Xor engine Support */ + +/**********************************/ +/* Marvell Monitor Extension */ +/**********************************/ +#define enaMonExt() ( /*(!getenv("enaMonExt")) ||\ */ \ + ( getenv("enaMonExt") && \ + ((!strcmp(getenv("enaMonExt"),"yes")) ||\ + (!strcmp(getenv("enaMonExt"),"Yes"))) \ + )\ + ) +/*Dual CPU support*/ +#define MASTER_CPU 0 +#define SLAVE_CPU 1 + +/********/ +/* CLKs */ +/********/ +#ifndef __ASSEMBLY__ +extern unsigned int mvSysClkGet(void); +extern unsigned int mvTclkGet(void); +extern unsigned int mvMclkGet(void); +#define UBOOT_CNTR 0 /* counter to use for uboot timer */ +#define CFG_HZ 1000 +#define CFG_TCLK mvTclkGet() +#define CFG_BUS_HZ mvSysClkGet() +#define CFG_BUS_CLK CFG_BUS_HZ +#endif + +/********************/ +/* PT settings */ +/********************/ +#define CFG_MV_PT + +#ifdef CFG_MV_PT +#define TOTAL_PAGE_TABLE (8<<20) /* 8M */ +#else +#define TOTAL_PAGE_TABLE 0 +#endif + + +/*************************************/ +/* High Level Configuration Options */ +/* (easy to change) */ +/*************************************/ +#define CONFIG_MARVELL + +/* commands */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ + CONFIG_BOOTP_BOOTFILESIZE) +#if defined(DB_MV78XX0) +#define CONFIG_COMMANDS ((CONFIG_CMD_DFL \ + | CFG_CMD_I2C \ + | CFG_CMD_EEPROM \ + | CFG_CMD_DATE \ + | CFG_CMD_PCI \ + | CFG_CMD_NET \ + | CFG_CMD_PING \ + | CFG_CMD_JFFS2 \ + | CFG_CMD_BSP \ + | CFG_CMD_EXT2 \ + | CFG_CMD_IDE \ + | CFG_CMD_MISC \ + | CFG_CMD_NAND) \ + & ~CFG_CMD_RCVR) +#elif defined(RD_MV78XX0_H3C) +#define CONFIG_COMMANDS (((CONFIG_CMD_DFL \ + | CFG_CMD_I2C \ + | CFG_CMD_EEPROM \ + | CFG_CMD_DATE \ + | CFG_CMD_PCI \ + | CFG_CMD_NET \ + | CFG_CMD_PING \ + | CFG_CMD_BSP \ + | CFG_CMD_EXT2 \ + | CFG_CMD_IDE) \ + | CFG_CMD_FLASH) \ + & ~CFG_CMD_IMLS \ + & ~CFG_CMD_NAND) +#elif defined(RD_MV78XX0_AMC) || defined(RD_MV78XX0_MASA) +#define CONFIG_COMMANDS ((CONFIG_CMD_DFL \ + | CFG_CMD_I2C \ + | CFG_CMD_EEPROM \ + | CFG_CMD_DATE \ + | CFG_CMD_PCI \ + | CFG_CMD_NET \ + | CFG_CMD_PING \ + | CFG_CMD_BSP \ + | CFG_CMD_EXT2 \ + | CFG_CMD_IDE \ + | CFG_CMD_NAND) \ + & ~CFG_CMD_IMLS \ + & ~CFG_CMD_FLASH) +#endif + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +#define CFG_MAXARGS 16 /* max number of command args */ + +/* which initialization functions to call for this board */ +#define CONFIG_MISC_INIT_F /* before relloc */ +#define CONFIG_MISC_INIT_R /* after relloc initialization*/ +#define CONFIG_BOARD_EARLY_INIT_F /* first c function, will initialize the board */ +#define CONFIG_BOARD_EARLY_INIT_R +#define CFG_BOARD_ASM_INIT 1 /* init in asm before moving to c code*/ +#undef CONFIG_DISPLAY_MEMMAP /* at the end of the bootprocess show the memory map*/ + +#define CONFIG_ENV_OVERWRITE /*allow to change env parameters */ + +#undef CONFIG_WATCHDOG /* watchdog disabled */ +#undef CONFIG_ALTIVEC /* undef to disable */ + +/* Boot Flags*/ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +/* L2 Cache */ +/* see also env parameter enaL2 */ +#define CFG_L2 +#define L2_INIT 0 +#define L2_ENABLE (L2_INIT | L2CR_L2E) +#define CFG_CACHELINE_SIZE 32 /* For all CPUs */ + +/* global definetions. */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE BOOTDEV_CS_BASE +#define CFG_FLASH_SIZE BOOTDEV_CS_SIZE +#define CFG_RESET_ADDRESS 0xffff0000 + +#define CFG_MONITOR_LEN (448 << 10) /* Reserve 448 kB for Monitor */ +#define CFG_MONITOR_BASE (0xFFFFFFFF - CFG_MONITOR_LEN + 1) + +/* change memory map, the U-boot will sit in 7M */ +/* the malloc area will be 1M */ +#define CFG_UBOOT_TOP (8 << 20) /* 8M */ + +#define CFG_MALLOC_LEN (1 << 20) /* (default) Reserve 1MB for malloc*/ +#define CFG_MALLOC_BASE (TEXT_BASE + (1 << 20)) /* 7M */ + +#define CFG_GUNZIP_LEN (1 << 20) +#undef CONFIG_VERY_BIG_RAM + +/* + * When locking data in cache you should point the CFG_INIT_RAM_ADDRESS + * To an unused memory region. The stack will remain in cache until RAM + * is initialized +*/ +#undef CFG_INIT_RAM_LOCK +#define CFG_INIT_RAM_ADDR 0x42000000 /* Internal SRAM */ + +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for init data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + +#define isync() __asm__ __volatile__ ("isync") + +/********/ +/* DRAM */ +/********/ +/* we don't use the global CONFIG_ECC, since in the global ecc we initialize + the DRAM for ECC in the phase we are relocating to it, which isn't so + sufficient. + so we will define our ECC CONFIG and initilize the DRAM for ECC in the DRAM + initialization phase, see sdram_init.c */ +#undef CONFIG_ECC /* enable ECC support */ +#define CONFIG_MV_ECC + +/* this defines whether we want to use the lowest CAL or the highest CAL available,*/ +/* we also check for the env parameter CASset. */ +#define MV_MIN_CAL + +#undef CFG_DISPLAY_DIMM_SPD_CONTENT /* show SPD content during boot */ + +/* default values for mtest : 4 ... 12 MB in DRAM */ +#define CFG_MEMTEST_START 0x00800000 +#define CFG_MEMTEST_END 0x00C00000 + +/********/ +/* RTC */ +/********/ +#if (CONFIG_COMMANDS & CFG_CMD_DATE) +#define CFG_NVRAM_SIZE 0x00 /* dummy */ +#define CFG_NVRAM_BASE_ADDR DEVICE_CS1_BASE /* dummy */ +#define CONFIG_RTC_DS1338_DS1339 +#endif + +/********************/ +/* Serial + parser */ +/********************/ +/* + * The following defines let you select what serial you want to use + * for your console driver. + * + */ +#define CONFIG_BAUDRATE 115200 /* console baudrate = 115000 */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +#if defined(RD_MV78XX0_H3C) +#define CFG_DUART_CHAN 1 /* channel 1 to use for console */ +#else +#define CFG_DUART_CHAN 0 /* channel 0 to use for console */ +#endif +#define CFG_INIT_CHAN1 +#define CFG_INIT_CHAN2 + +#define CONFIG_LOADS_ECHO 0 /* echo off for serial download */ +#define CFG_LOADS_BAUD_CHANGE /* allow baudrate changes */ + +#define CFG_CONSOLE_INFO_QUIET /* don't print In/Out/Err console assignment. */ + +/* parser */ +/* don't chang the parser if you want to load Linux(if you cahnge it to HUSH the cmdline will + not pass to the kernel correctlly???) */ +/*#define CFG_HUSH_PARSER */ +#undef CFG_HUSH_PARSER +#define CONFIG_AUTO_COMPLETE + +#define CFG_PROMPT_HUSH_PS2 "> " + +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "Marvell>> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ + +/************/ +/* ETHERNET */ +/************/ +/* to change the default ethernet port, use this define (options: 0, 1, 2) */ +#define CONFIG_NET_MULTI +#define CONFIG_HAS_ETH1 +#define CONFIG_HAS_ETH2 + +#define ENV_ETH_PRIME "egiga0" +#if defined(RD_MV78XX0_H3C) +#define YUK_ETHADDR "00:00:00:EE:51:81" +#undef ENV_ETH_PRIME +#define ENV_ETH_PRIME "SK98#0" +#endif + +#define ETHADDR "64:00:00:00:00:00" +#define ETH1ADDR "64:00:00:00:00:01" +#define ETH2ADDR "64:00:00:00:00:02" + +#define CONFIG_IPADDR 10.4.50.165 +#define CONFIG_SERVERIP 10.4.50.5 +#define CONFIG_NETMASK 255.255.255.0 + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#undef CONFIG_IDE_8xx_PCCARD /* Use IDE with PC Card Adapter */ + +#undef CONFIG_IDE_8xx_DIRECT /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_RESET /* reset for ide not supported */ + +#define CFG_IDE_MAXBUS 4 /* max. 1 IDE bus */ +#define CFG_IDE_MAXDEVICE CFG_IDE_MAXBUS * 8 /* max. 1 drive per IDE bus */ + +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#undef CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION +#define CONFIG_LBA48 + +/***************************************/ +/* LINUX BOOT and other ENV PARAMETERS */ +/***************************************/ +#define CFG_BOOTARGS_END ":::DB78xx0:eth0:none" +#define RCVR_IP_ADDR "169.254.100.100" +#define RCVR_LOAD_ADDR "0x00800000" + +#define CONFIG_ZERO_BOOTDELAY_CHECK + +#define CFG_LOAD_ADDR 0x00400000 /* default load address */ + +#undef CONFIG_BOOTARGS + +/* auto boot*/ +#define CONFIG_BOOTDELAY 3 /* by default no autoboot */ + +#if (CONFIG_BOOTDELAY >= 0) +#define CONFIG_ROOTPATH /mnt/ARM_FS/ +#define CONFIG_BOOTCOMMAND "tftpboot 0x2000000 $(image_name);\ + setenv bootargs $(bootargs) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ + ip=$(ipaddr):$(serverip)$(bootargs_end); bootm 0x2000000; " + +#define CONFIG_BOOTARGS "console=ttyS0,115200 mtdparts=physmapped-flash.0:32m(root)" +#endif + +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8<<20) /* Initial Memory map for Linux */ + +#define BRIDGE_REG_BASE_BOOTM 0xfbe00000 /* this paramaters are used when booting the linux kernel */ + +/********/ +/* USB */ +/********/ +#if defined(RD_MV78XX0_AMC) || defined(RD_MV78XX0_H3C) +#define ENV_USB0_MODE "device" +#define ENV_USB1_MODE "host" +#define ENV_USB2_MODE "device" +#elif RD_MV78XX0_MASA +#define ENV_USB0_MODE "host" +#define ENV_USB1_MODE "host" +#define ENV_USB2_MODE "host" +#else +#define ENV_USB0_MODE "host" +#define ENV_USB1_MODE "host" +#define ENV_USB2_MODE "device" +#endif + +/********/ +/* I2C */ +/********/ +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_I2C_MULTI_EEPROMS +#define CFG_I2C_SPEED 100000 /* I2C speed default */ + +/* I2C addresses for the two DIMM SPD chips */ +#define DIMM0_I2C_ADDR 0x56 +#define DIMM1_I2C_ADDR 0x54 + +/* CPU I2C settings */ +#define CPU_I2C +#define I2C_CPU0_EEPROM_ADDR 0x51 + + +/********/ +/* PCI */ +/********/ +#ifdef CONFIG_PCI + #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ + #define CONFIG_PCI_PNP /* do pci plug-and-play */ + #define CONFIG_EEPRO100 /* Support for Intel 82557/82559/82559ER chips */ +#endif + + +#if defined(RD_MV78XX0_AMC) +/* Disable PCI-E scan over PCI-E switch */ +#define VIRTUAL_BRIDGE_SUPPORT +#define PCI_DIS_INTERFACE 8 +#elif defined(RD_MV78XX0_H3C) +#define PCI_DIS_INTERFACE 3 +#elif defined (RD_MV78XX0_MASA) +#define PCI_DIS_INTERFACE 8 +#elif defined (DB_MV78XX0) +#define PCI_DIS_INTERFACE 2 +#endif +#define PCI_HOST_ADAPTER 0 /* configure as pci adapter */ +#define PCI_HOST_FORCE 1 /* configure as pci host */ +#define PCI_HOST_AUTO 2 /* detected via arbiter enable */ +#define CFG_PCI_IDSEL 0x30 + +/*----------------------------------------------------------------------- + * NAND-FLASH stuff + *-----------------------------------------------------------------------*/ +/* Use the new NAND code. */ + +#undef CFG_NAND_LEGACY +#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ +#define NAND_MAX_CHIPS CFG_MAX_NAND_DEVICE +#define __mem_pci(x) x + +/* Boot from NAND settings */ +/* Duplicate defines from nBootstrap.h */ +#ifdef MV_NAND_BOOT +#define CFG_NAND_BOOT +#define CFG_ENV_IS_IN_NAND 1 + +#if defined(MV_LARGE_PAGE) +#define CFG_ENV_OFFSET (128 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) /* environment take 1 block */ +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 4KB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_ENV_OFFSET) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE - CFG_ENV_SECT_SIZE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_MONITOR_IMAGE_DST + +#else /* ! LARGE PAGE NAND */ + +#define CFG_ENV_OFFSET (16 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 16kB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_ENV_OFFSET) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE - CFG_ENV_SECT_SIZE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_MONITOR_IMAGE_DST +#endif /* defined(MV_LARGE_PAGE) */ +#else /* NOT BOOT FROM NAND */ + +#define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ +#endif /* MV_NAND_BOOT */ + +/***************************/ +/* CFI FLASH organization */ +/***************************/ +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI 1 +#define CFG_FLASH_USE_BUFFER_WRITE +#define CFG_FLASH_QUIET_TEST +#define CFG_FLASH_BANKS_LIST {BOOTDEV_CS_BASE} +#if defined(__BE) +#define CFG_WRITE_SWAPPED_DATA +#endif + +/***********************/ +/* FLASH organization */ +/***********************/ + +/* + * When CFG_MAX_FLASH_BANKS_DETECT is defined, the actual number of Flash + * banks has to be determined at runtime and stored in a gloabl variable + * mv_board_num_flash_banks. The value of CFG_MAX_FLASH_BANKS_DETECT is only + * used instead of CFG_MAX_FLASH_BANKS to allocate the array flash_info, and + * should be made sufficiently large to accomodate the number of banks that + * might actually be detected. Since most (all?) Flash related functions use + * CFG_MAX_FLASH_BANKS as the number of actual banks on the board, it is + * defined as mv_board_num_flash_banks. + */ +#define CFG_MAX_FLASH_BANKS_DETECT 5 +#ifndef __ASSEMBLY__ +extern int mv_board_num_flash_banks; +#endif +#define CFG_MAX_FLASH_BANKS (mv_board_num_flash_banks) + +#define CFG_MAX_FLASH_SECT 300 /* max number of sectors on one chip */ +#define CFG_FLASH_PROTECTION 1 + +#ifndef MV_NAND_BOOT +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_SIZE 0x2000 /* Total Size of Environment Sector */ +#define CFG_ENV_SECT_SIZE 0x10000 +#define CFG_ENV_OFFSET 0x0 +#define CFG_ENV_ADDR (0xFFFFFFFF - CFG_MONITOR_LEN - CFG_ENV_SECT_SIZE + 1) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) +#define CONFIG_JFFS2_CMDLINE +#endif + +/*****************/ +/* others */ +/*****************/ +#define CFG_INTERNAL_RAM_ADDR 0xf2400000 /* Internal RAM */ +#define CFG_DFL_MV_REGS 0xD0000000 /* boot time MV_REGS */ +#define CFG_MV_REGS 0xf1000000 /* MV Registers will be mapped here */ + +/***************************/ +/* Relevent for ARM only */ +/***************************/ +#if defined(RD_MV78XX0_H3C) +#define CONFIG_SK98 +#endif +#define CONFIG_STACKSIZE (1 << 20) /* regular stack - up to 4M (in case of exception)*/ +#define CONFIG_NR_DRAM_BANKS 4 +#undef SYSCLK_AUTO_DETECT +#define CFG_PT_BASE (CFG_MALLOC_BASE - 0x20000) +#define CFG_PT_BASE_SLAVE_CPU (CFG_PT_BASE - 0x20000) + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag for ramdisk data */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_MARVELL_TAG 1 +#define ATAG_MARVELL 0x41000403 + +#endif /* __CONFIG_H */ diff --git a/include/configs/mv_feroceon.h b/include/configs/mv_feroceon.h new file mode 100644 index 0000000..1fb7ad2 --- /dev/null +++ b/include/configs/mv_feroceon.h @@ -0,0 +1,806 @@ +/* + * (C) Copyright 2003 + * Texas Instruments. + * Kshitij Gupta + * Configuation settings for the TI OMAP Innovator board. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, + * Configuration for Integrator AP board. + *. + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 __CONFIG_H +#define __CONFIG_H + +#include "../../board/mv_feroceon/mv_orion/orion_sys/mvSysHwConfig.h" + +/************/ +/* VERSIONS */ +/************/ +#ifdef MV_TINY_IMAGE +#define CONFIG_IDENT_STRING " Marvell version: 3.1.131-TINY" +#else +#define CONFIG_IDENT_STRING " Marvell version: 3.1.131" +#endif /* MV_TINY_IMAGE */ +/* version number passing when loading Kernel */ +#define VER_NUM 0x03010100 /* 3.1.131 */ + +/********************/ +/* MV DEV SUPPORTS */ +/********************/ +#define CONFIG_PCI /* pci support */ +#undef CONFIG_PCI_1 /* sec pci interface support */ + +/********************/ +/* Environment variables */ +/********************/ + + +#define CFG_ENV_IS_IN_FLASH 1 + +/**********************************/ +/* Marvell Monitor Extension */ +/**********************************/ +#define enaMonExt()( /*(!getenv("enaMonExt")) ||\*/\ + ( getenv("enaMonExt") && \ + ((!strcmp(getenv("enaMonExt"),"yes")) ||\ + (!strcmp(getenv("enaMonExt"),"Yes"))) \ + )\ + ) + +/********/ +/* CLKs */ +/********/ +#ifndef __ASSEMBLY__ +extern unsigned int mvSysClkGet(void); +extern unsigned int mvTclkGet(void); +#define UBOOT_CNTR 0 /* counter to use for uboot timer */ +#define MV_TCLK_CNTR 1 /* counter to use for uboot timer */ +#define MV_REF_CLK_DEV_BIT 1000 /* Number of cycle to eanble timer */ +#define MV_REF_CLK_BIT_RATE 100000 /* Ref clock frequency */ +#define MV_REF_CLK_INPUT_GPP 6 /* Ref clock frequency input */ + +#define CFG_HZ 1000 +#define CFG_TCLK mvTclkGet() +#define CFG_BUS_HZ mvSysClkGet() +#define CFG_BUS_CLK CFG_BUS_HZ +#endif + +/********************/ +/* Dink PT settings */ +/********************/ +#define CFG_MV_PT + +#ifdef CFG_MV_PT +#define CFG_PT_BASE (CFG_MALLOC_BASE - 0x40000) +#endif /* #ifdef CFG_MV_PT */ + + +/*************************************/ +/* High Level Configuration Options */ +/* (easy to change) */ +/*************************************/ +#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* CPU */ + + +/* commands */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ + CONFIG_BOOTP_BOOTFILESIZE) + + +/* Default U-Boot supported features */ +#if defined(MV_TINY_IMAGE) +#define CONFIG_CMD_BASIC (CFG_CMD_PCI \ + | CFG_CMD_FLASH\ + | CFG_CMD_ENV \ + | CFG_CMD_NET \ + | CFG_CMD_IDE \ + | CFG_CMD_EXT2 \ + | CFG_CMD_MEMORY\ + | CFG_CMD_BOOTD) + +#elif defined(DB_FPGA) +#define CONFIG_CMD_BASIC ( CFG_CMD_DHCP \ + | CFG_CMD_ELF \ + | CFG_CMD_I2C \ + | CFG_CMD_EEPROM \ + | CFG_CMD_PCI \ + | CFG_CMD_JFFS2 \ + | CFG_CMD_DATE \ + | CFG_CMD_LOADS \ + | CFG_CMD_FLASH \ + | CFG_CMD_MEMORY \ + | CFG_CMD_ENV \ + | CFG_CMD_BOOTD \ + | CFG_CMD_CONSOLE \ + | CFG_CMD_RUN \ + | CFG_CMD_MISC \ + ) +#else +#define CONFIG_CMD_BASIC ( CFG_CMD_DHCP \ + | CFG_CMD_ELF \ + | CFG_CMD_I2C \ + | CFG_CMD_EEPROM \ + | CFG_CMD_PCI \ + | CFG_CMD_NET \ + | CFG_CMD_PING \ + | CFG_CMD_JFFS2 \ + | CFG_CMD_DATE \ + | CFG_CMD_LOADS \ + | CFG_CMD_BSP \ + | CFG_CMD_FLASH \ + | CFG_CMD_MEMORY \ + | CFG_CMD_IDE \ + | CFG_CMD_EXT2 \ + | CFG_CMD_ENV \ + | CFG_CMD_BOOTD \ + | CFG_CMD_CONSOLE \ + | CFG_CMD_RUN \ + | CFG_CMD_MISC \ + ) + +#endif + +#if defined(MV_NAND) || defined(MV_NAND_BOOT) +#define CONFIG_CMD_BASIC1 (CONFIG_CMD_BASIC | CFG_CMD_NAND) +#else +#define CONFIG_CMD_BASIC1 CONFIG_CMD_BASIC +#endif + +#if (defined(MV_INCLUDE_PEX) | defined(MV_INCLUDE_PCI)) +#define CONFIG_CMD_BASIC2 CONFIG_CMD_BASIC1 +#else +#undef CONFIG_PCI +#define CONFIG_CMD_BASIC2 (CONFIG_CMD_BASIC1 & ~CFG_CMD_PCI) +#endif + + +#if (!defined (MV_INC_BOARD_NOR_FLASH) && \ + !defined(MV_INC_BOARD_SPI_FLASH) && \ + !defined(MV_INCLUDE_INTEG_MFLASH)) +#undef CFG_ENV_IS_IN_FLASH +#define CFG_ENV_IS_NOWHERE +#define CFG_NO_FLASH +#define CONFIG_CMD_BASIC3 (CONFIG_CMD_BASIC2 & ~CFG_CMD_FLASH \ + & ~CFG_CMD_ENV \ + & ~CFG_CMD_JFFS2) +#else +#define CONFIG_CMD_BASIC3 CONFIG_CMD_BASIC2 +#endif + +#if !defined (MV_INC_BOARD_NAND_FLASH) +#define CONFIG_CMD_BASIC4 (CONFIG_CMD_BASIC3 & ~CFG_CMD_NAND) +#else +#define CONFIG_CMD_BASIC4 CONFIG_CMD_BASIC3 +#endif + +#if !defined (MV_INC_BOARD_PCI_SATA) && !defined (MV_INCLUDE_INTEG_SATA) +#define CONFIG_CMD_BASIC5 (CONFIG_CMD_BASIC4 & ~CFG_CMD_IDE \ + & ~CFG_CMD_EXT2) +#else +#define CONFIG_CMD_BASIC5 CONFIG_CMD_BASIC4 +#endif + +#if defined(MV_MMC) +#define CONFIG_CMD_BASIC6 (CONFIG_CMD_BASIC5 | CFG_CMD_MMC | CFG_CMD_FAT) +#else +#define CONFIG_CMD_BASIC6 CONFIG_CMD_BASIC5 +#endif +#define CONFIG_COMMANDS CONFIG_CMD_BASIC6 + + + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +#define CFG_MAXARGS 16 /* max number of command args */ + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#undef CONFIG_IDE_8xx_PCCARD /* Use IDE with PC Card Adapter */ + +#undef CONFIG_IDE_8xx_DIRECT /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_RESET /* reset for ide not supported */ + +#define CFG_IDE_MAXBUS 4 /* max. 1 IDE bus */ +#define CFG_IDE_MAXDEVICE CFG_IDE_MAXBUS * 8 /* max. 1 drive per IDE bus */ + +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#undef CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +#ifndef CONFIG_MMC +#define CONFIG_LBA48 +#endif + +/* which initialization functions to call for this board */ +#define CONFIG_MISC_INIT_R 1 /* after relloc initialization*/ +#undef CONFIG_DISPLAY_MEMMAP /* at the end of the bootprocess show the memory map*/ + +#define CONFIG_ENV_OVERWRITE /* allow to change env parameters */ + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +/* Cache */ +#define CFG_CACHELINE_SIZE 32 + + +/* global definetions. */ +#define CFG_SDRAM_BASE 0x00000000 + + +#define CFG_RESET_ADDRESS 0xffff0000 + +#define CFG_MALLOC_BASE (3 << 20) /* 3M */ + +/* + * When locking data in cache you should point the CFG_INIT_RAM_ADDRESS + * To an unused memory region. The stack will remain in cache until RAM + * is initialized +*/ +#define CFG_MALLOC_LEN (1 << 20) /* (default) Reserve 1MB for malloc*/ + +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for init data */ + +#undef CONFIG_INIT_CRITICAL /* critical code in start.S */ + + +/********/ +/* DRAM */ +/********/ + +#define CFG_DRAM_BANKS 4 + +/* this defines whether we want to use the lowest CAL or the highest CAL available,*/ +/* we also check for the env parameter CASset. */ +#define MV_MIN_CAL + +#define CFG_MEMTEST_START 0x00400000 +#define CFG_MEMTEST_END 0x007fffff + +/********/ +/* RTC */ +/********/ +#if (CONFIG_COMMANDS & CFG_CMD_DATE) +#define CFG_NVRAM_SIZE 0x00 /* dummy */ +#define CFG_NVRAM_BASE_ADDR DEVICE_CS1_BASE /* dummy */ +#define CONFIG_RTC_DS1338_DS1339 +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_DATE) */ + +/********************/ +/* Serial + parser */ +/********************/ +/* + * The following defines let you select what serial you want to use + * for your console driver. + */ +#define CONFIG_BAUDRATE 115200 /* console baudrate = 115200 */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 } + +#ifdef DB_FPGA +#define CFG_DUART_CHAN 1 /* channel to use for console */ +#else +#define CFG_DUART_CHAN 0 /* channel to use for console */ +#endif + +#define CFG_INIT_CHAN1 +#define CFG_INIT_CHAN2 + + +#define CONFIG_LOADS_ECHO 0 /* echo off for serial download */ +#define CFG_LOADS_BAUD_CHANGE /* allow baudrate changes */ + +#define CFG_CONSOLE_INFO_QUIET /* don't print In/Out/Err console assignment. */ +#undef CONFIG_SILENT_CONSOLE /* define for Pex complince */ + +/* parser */ +/* don't chang the parser if you want to load Linux(if you cahnge it to HUSH the cmdline will + not pass to the kernel correctlly???) */ +/*#define CFG_HUSH_PARSER */ +#undef CFG_HUSH_PARSER +#define CONFIG_AUTO_COMPLETE + +#define CFG_PROMPT_HUSH_PS2 "> " + +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "Marvell>> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ + +/************/ +/* ETHERNET */ +/************/ +/* to change the default ethernet port, use this define (options: 0, 1, 2) */ +#if (CONFIG_COMMANDS & CFG_CMD_NET) +#define CONFIG_NET_MULTI +#define CONFIG_IPADDR 10.4.50.165 +#define CONFIG_SERVERIP 10.4.50.5 +#define CONFIG_NETMASK 255.255.255.0 +#endif + +#if defined(DB_PRPMC) || defined(DB_88F1281) || defined(DB_MNG) || defined(DB_88F6183LBP) + #define YUK_ETHADDR "00:00:00:EE:51:81" + #define ENV_ETH_PRIME "SK98#0" +#else + #define ETHADDR "00:00:00:00:51:81" + #define ETH1ADDR "00:00:00:00:51:82" + #if defined(MV_INCLUDE_GIG_ETH) + #define ENV_ETH_PRIME "egiga0" + #elif defined(MV_INCLUDE_UNM_ETH) + #define ENV_ETH_PRIME "efast0" + #else + #define ENV_ETH_PRIME "none" + #endif +#endif + +/************/ +/* PCI */ +/************/ +#if defined(MV_INCLUDE_PCI) + +#if defined(DB_PEX_PCI) +#define ENV_PCI_MODE "device" /* PCI */ +#else +#define ENV_PCI_MODE "host" /* PCI */ +#endif + +#endif + +/************/ +/* USB */ +/************/ + +#if defined(MV_INCLUDE_USB) + #if defined(RD_88F5182) || defined(RD_88F5182_3) || \ + defined(RD_88W8660) || defined(RD_88F5181_POS_NAS) || \ + defined(RD_88F5181L_FE) || defined(RD_88F5181L_GE) || defined(RD_88F5181L_FXO_GE) || \ + defined(RD_88F5181_GTWGE) || defined(RD_88F5181_GTWFE) || defined(RD_88W8660_AP82S) || \ + defined(RD_88F6082MICRO_DAS_NAS) + #define ENV_USB0_MODE "host" + #define ENV_USB1_MODE "host" + #else + #define ENV_USB0_MODE "device" + #define ENV_USB1_MODE "device" + #endif +#endif + +/************/ +/* SDIO/MMC */ +/************/ + +#if defined(MV_88F6183) || defined(MV_88F6183L) +#define CONFIG_MMC +#define CFG_MMC_BASE 0xF0000000 +#endif + +/***************************************/ +/* LINUX BOOT and other ENV PARAMETERS */ +/***************************************/ +#if defined (DB_PRPMC) || defined(RD_88F5181L_FE) || defined(RD_88F5181L_GE) || \ + defined(MV_88W8660) || defined(RD_88F5181L_FXO_GE) || \ + defined(RD_88F5181_GTWGE) || defined (RD_88F5181_GTWFE) + +#define CFG_BOOTARGS_END ":::DB88FXX81:eth0:none" +#else +#define CFG_BOOTARGS_END ":::DB88FXX81:egiga0:none" +#endif + +#define CONFIG_ZERO_BOOTDELAY_CHECK + +#define CFG_LOAD_ADDR 0x00400000 /* default load address */ + +#undef CONFIG_BOOTARGS + +/* auto boot*/ +#if defined(RD_88F6082MICRO_DAS_NAS) +#define CONFIG_BOOTDELAY 1 /* by default no autoboot */ +#else +#define CONFIG_BOOTDELAY 3 /* by default no autoboot */ +#endif + +#if (CONFIG_BOOTDELAY >= 0) +#define CONFIG_ROOTPATH /mnt/ARM_FS/ +#endif /* #if (CONFIG_BOOTDELAY >= 0) */ + +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8<<20) /* Initial Memory map for Linux */ + +#define BRIDGE_REG_BASE_BOOTM 0xfbe00000 /* this paramaters are used when booting the linux kernel */ + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag for ramdisk data */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_MARVELL_TAG 1 +#define ATAG_MARVELL 0x41000403 + +/********/ +/* I2C */ +/********/ +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_I2C_MULTI_EEPROMS +#define CFG_I2C_SPEED 100000 /* I2C speed default */ + +/* I2C addresses for the two DIMM SPD chips */ +#define DIMM0_I2C_ADDR 0x56 +#define DIMM1_I2C_ADDR 0x54 + +/* CPU I2C settings */ +#define CPU_I2C +#define I2C_CPU0_EEPROM_ADDR 0x51 + + +/********/ +/* PCI */ +/********/ +#ifdef CONFIG_PCI + #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ + #define CONFIG_PCI_PNP /* do pci plug-and-play */ + +/* Pnp PCI Network cards */ + #define CONFIG_EEPRO100 /* Support for Intel 82557/82559/82559ER chips */ + #define CONFIG_SK98 /* yukon */ + #define CONFIG_DRIVER_RTL8029 + +/* To reduce image size... */ +#if defined (MV_USB) || defined (MV_TINY_IMAGE) || defined(RD_88W8660_AP82S) || defined(DB_PEX_PCI) || defined(__BE) + #undef CONFIG_DRIVER_RTL8029 + #undef CONFIG_EEPRO100 +#endif + +/* To reduce image size... */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#if !defined (MV_NAND_BOOT) + #undef CONFIG_DRIVER_RTL8029 + #undef CONFIG_EEPRO100 + #undef CONFIG_SK98 +#endif +#endif + +/* DB_PRPMC support only Yukon */ +#if defined (DB_PRPMC) || defined (DB_MNG) + #undef CONFIG_EEPRO100 + #undef CONFIG_DRIVER_RTL8029 +#endif + +#endif /* #ifdef CONFIG_PCI */ + +#define PCI_HOST_ADAPTER 0 /* configure ar pci adapter */ +#define PCI_HOST_FORCE 1 /* configure as pci host */ +#define PCI_HOST_AUTO 2 /* detected via arbiter enable */ + +/* for Yukon */ +#define __mem_pci(x) x +#define __io_pci(x) x +#define __arch_getw(a) (*(volatile unsigned short *)(a)) +#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v)) + + + +/***********************/ +/* FLASH organization */ +/***********************/ + +/* + * When CFG_MAX_FLASH_BANKS_DETECT is defined, the actual number of Flash + * banks has to be determined at runtime and stored in a gloabl variable + * mv_board_num_flash_banks. The value of CFG_MAX_FLASH_BANKS_DETECT is only + * used instead of CFG_MAX_FLASH_BANKS to allocate the array flash_info, and + * should be made sufficiently large to accomodate the number of banks that + * might actually be detected. Since most (all?) Flash related functions use + * CFG_MAX_FLASH_BANKS as the number of actual banks on the board, it is + * defined as mv_board_num_flash_banks. + */ +#define CFG_MAX_FLASH_BANKS_DETECT 5 +#ifndef __ASSEMBLY__ +extern int mv_board_num_flash_banks; +#endif +#define CFG_MAX_FLASH_BANKS (mv_board_num_flash_banks) + +#define CFG_MAX_FLASH_SECT 300 /* max number of sectors on one chip */ +#define CFG_FLASH_PROTECTION 1 + +#define CFG_EXTRA_FLASH_DEVICE DEVICE3 /* extra flash at device 3 */ +#define CFG_EXTRA_FLASH_WIDTH 4 /* 32 bit */ +#define CFG_BOOT_FLASH_WIDTH 1 /* 8 bit */ + +#define CFG_FLASH_ERASE_TOUT 120000/1000 /* 120000 - Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* 500 - Timeout for Flash Write (in ms) */ +#define CFG_FLASH_LOCK_TOUT 500 /* 500- Timeout for Flash Lock (in ms) */ + + +/***************************/ +/* CFI FLASH organization */ +/***************************/ +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI 1 +#define CFG_FLASH_USE_BUFFER_WRITE +#define CFG_FLASH_QUIET_TEST +#define CFG_FLASH_BANKS_LIST {BOOTDEV_CS_BASE} +#if defined(__BE) +#define CFG_WRITE_SWAPPED_DATA +#endif + +/* RD_88F5181L_FXO_GE include MXIC 16bit flash working in 8 bit mode */ +#if defined (RD_88F5181L_FXO_GE) +#define AMD_FLASH_16BIT_IN_8BIT_MODE +#endif + + +#if defined (MV_FLASH_BOOT) + + #define CFG_FLASH_BASE DEVICE_MFLASH_BASE + #define CFG_FLASH_SIZE (256 << 10) + +#elif defined (MV_SPI_BOOT) + + #define CFG_FLASH_BASE BOOTDEV_CS_BASE + #define CFG_FLASH_SIZE BOOTDEV_CS_SIZE +#else + #define CFG_FLASH_BASE BOOTDEV_CS_BASE + #define CFG_FLASH_SIZE BOOTDEV_CS_SIZE +#endif /* defined(MV_FLASH_BOOT) */ + +#define CFG_ENV_SIZE 0x1000 + +#define MONITOR_HEADER_LEN 0x200 + +#if defined(MV_SEC_4K) + +#define CFG_ENV_SECT_SIZE 0x1000 + + #if defined(MV_TINY_IMAGE) + + #define CFG_MONITOR_IMAGE_OFFSET 0x0 /* offset of the monitor from the + u-boot image */ + #define CFG_MONITOR_LEN (252 << 10) /* Reserve 252 kB for Monitor */ + #define CFG_MONITOR_BASE CFG_FLASH_BASE + #define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN) + #else + #define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the + u-boot image */ + #define CFG_MONITOR_LEN (508 << 10) /* Reserve 508 kB for Monitor */ + #define CFG_MONITOR_BASE (CFG_FLASH_BASE + CFG_FLASH_SIZE \ + - CFG_MONITOR_LEN) + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SECT_SIZE) + #endif + +#elif defined(MV_SEC_32K) + + #if defined(MV_TINY_IMAGE) + #define CFG_MONITOR_LEN (256 << 10) /* Reserve 252 kB for Monitor */ + #else + #if defined(MV_BOOTROM) + #define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ + #else + #define CFG_MONITOR_LEN (448 << 10) /* Reserve 448 kB for Monitor */ + #endif + #endif + + #define CFG_ENV_SECT_SIZE 0x8000 /* Reserved 3kB for env */ + +#if defined(MV_BOOTROM) + #define CFG_MONITOR_IMAGE_OFFSET 0 /* offset of the monitor from the u-boot image */ +#else + #define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the */ +#endif + + #define CFG_MONITOR_BASE (CFG_FLASH_BASE + CFG_FLASH_SIZE \ + - CFG_MONITOR_LEN) +#if defined(MV_BOOTROM) + #define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN - CFG_ENV_SECT_SIZE) +#else + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SECT_SIZE) +#endif + +#elif defined(MV_SEC_64K) + + #if defined(MV_TINY_IMAGE) + #define CFG_MONITOR_LEN (256 << 10) /* Reserve 252 kB for Monitor */ + #else + #if defined(MV_BOOTROM) + #define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ + #else + #define CFG_MONITOR_LEN (448 << 10) /* Reserve 448 kB for Monitor */ + #endif + #endif + + #define CFG_ENV_SECT_SIZE 0x10000 + +#if defined(MV_BOOTROM) + #define CFG_MONITOR_IMAGE_OFFSET 0 /* offset of the monitor from the u-boot image */ +#else + #define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the */ +#endif + + #define CFG_MONITOR_BASE (CFG_FLASH_BASE + CFG_FLASH_SIZE \ + - CFG_MONITOR_LEN) +#if defined(MV_BOOTROM) + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - (2 * CFG_ENV_SECT_SIZE)) +#else + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SECT_SIZE) +#endif + +#elif defined(MV_SEC_128K) + + #if defined(MV_TINY_IMAGE) + #define CFG_MONITOR_LEN (256 << 10) /* Reserve 252 kB for Monitor */ + #else + #define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ + #endif + + #define CFG_ENV_SECT_SIZE 0x20000 + #define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the + u-boot image */ + #define CFG_MONITOR_BASE (CFG_FLASH_BASE + CFG_FLASH_SIZE \ + - CFG_MONITOR_LEN) + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SECT_SIZE) + +#elif defined(MV_SEC_256K) + +#define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ + + #define CFG_ENV_SECT_SIZE 0x40000 + #define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the + u-boot image */ + #define CFG_MONITOR_BASE (CFG_FLASH_BASE + CFG_FLASH_SIZE \ + - CFG_MONITOR_LEN) + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SECT_SIZE) + +#endif + +/*----------------------------------------------------------------------- + * NAND-FLASH stuff + *-----------------------------------------------------------------------*/ +/* Use the new NAND code. */ + +#undef CFG_NAND_LEGACY +#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ +#define NAND_MAX_CHIPS CFG_MAX_NAND_DEVICE + +/* JFFS2 over NAND define */ +#define CONFIG_JFFS2_NAND 1 + +/* Boot from NAND settings */ +/* Duplicate defines from nBootstrap.h */ +#ifdef MV_NAND_BOOT +#define CFG_NAND_BOOT +#define CFG_ENV_IS_IN_NAND 1 + +#if defined(MV_BOOTROM) +#if defined(MV_LARGE_PAGE) +#define CFG_ENV_OFFSET (128 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) /* environment take 1 block */ +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 4KB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_ENV_OFFSET) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE - CFG_ENV_SECT_SIZE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_MONITOR_IMAGE_DST + +#else /* ! LARGE PAGE NAND */ + +#define CFG_ENV_OFFSET 0x84000 /* environment starts here */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (16 << 10) /* Reserved 16kB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_NBOOT_BASE + CFG_NBOOT_LEN) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE 0x4000 +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET 0 /* offset of the monitor from the u-boot image */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR 0x84000 /* UBOOT_IMAGE_DEST - UBOOT_IMAGE_OFFS */ + +#endif /* defined(MV_LARGE_PAGE) */ + +#else /* ! MV_BOOTROM */ + +#if defined(MV_LARGE_PAGE) +#define CFG_ENV_OFFSET (128 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) /* environment take 1 block */ +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 4KB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_ENV_OFFSET) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE - CFG_ENV_SECT_SIZE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_MONITOR_IMAGE_DST + +#else /* ! LARGE PAGE NAND */ + +#define CFG_ENV_OFFSET (16 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 16kB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_ENV_OFFSET) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE - CFG_ENV_SECT_SIZE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_MONITOR_IMAGE_DST +#endif /* defined(MV_LARGE_PAGE) */ +#endif /* defined(MV_BOOTROM) */ + +#endif /* MV_NAND_BOOT */ + + +#if defined(RD_88F5181L_FE) || defined(RD_88F5181L_GE) || defined(RD_88F5181L_FXO_GE) || \ + defined(RD_88F5181_GTWGE) || defined (RD_88F5181_GTWFE) + #define BOARD_LATE_INIT +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) +#define CONFIG_JFFS2_CMDLINE +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) */ + + +/*****************/ +/* others */ +/*****************/ +#define CFG_DFL_MV_REGS 0xd0000000 /* boot time MV_REGS */ +#define CFG_MV_REGS INTER_REGS_BASE /* MV Registers will be mapped here */ + +#undef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE (2 << 20) /* regular stack - up to 4M (in case of exception)*/ +#define CONFIG_NR_DRAM_BANKS 4 + +#endif /* __CONFIG_H */ diff --git a/include/configs/mv_kw.h b/include/configs/mv_kw.h new file mode 100644 index 0000000..03da0f7 --- /dev/null +++ b/include/configs/mv_kw.h @@ -0,0 +1,715 @@ +/* + * (C) Copyright 2003 + * Texas Instruments. + * Kshitij Gupta + * Configuation settings for the TI OMAP Innovator board. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, + * Configuration for Integrator AP board. + *. + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 __CONFIG_H +#define __CONFIG_H + +#include "../../board/mv_feroceon/mv_kw/mvSysHwConfig.h" + +/************/ +/* VERSIONS */ +/************/ +#ifdef MV_TINY_IMAGE +#define CONFIG_IDENT_STRING " Marvell version: 3.4.4-TINY" +#else +#define CONFIG_IDENT_STRING " Marvell version: 3.4.4" +#endif /* MV_TINY_IMAGE */ +/* version number passing when loading Kernel */ +#define VER_NUM 0x03040400 /* 3.4.4 */ + +/********************/ +/* MV DEV SUPPORTS */ +/********************/ +#define CONFIG_PCI /* pci support */ +#undef CONFIG_PCI_1 /* sec pci interface support */ + +/********************/ +/* Environment variables */ +/********************/ + + +#define CFG_ENV_IS_IN_FLASH 1 + +/**********************************/ +/* Marvell Monitor Extension */ +/**********************************/ +#define enaMonExt()( /*(!getenv("enaMonExt")) ||\*/\ + ( getenv("enaMonExt") && \ + ((!strcmp(getenv("enaMonExt"),"yes")) ||\ + (!strcmp(getenv("enaMonExt"),"Yes"))) \ + )\ + ) + +/********/ +/* CLKs */ +/********/ +#ifndef __ASSEMBLY__ +extern unsigned int mvSysClkGet(void); +extern unsigned int mvTclkGet(void); +#define UBOOT_CNTR 0 /* counter to use for uboot timer */ +#define MV_TCLK_CNTR 1 /* counter to use for uboot timer */ +#define MV_REF_CLK_DEV_BIT 1000 /* Number of cycle to eanble timer */ +#define MV_REF_CLK_BIT_RATE 100000 /* Ref clock frequency */ +#define MV_REF_CLK_INPUT_GPP 6 /* Ref clock frequency input */ + +#define CFG_HZ 1000 +#define CFG_TCLK mvTclkGet() +#define CFG_BUS_HZ mvSysClkGet() +#define CFG_BUS_CLK CFG_BUS_HZ +#endif + +/********************/ +/* Dink PT settings */ +/********************/ +#define CFG_MV_PT + +#ifdef CFG_MV_PT +#define CFG_PT_BASE (CFG_MALLOC_BASE - 0x20000) +#endif /* #ifdef CFG_MV_PT */ + + +/*************************************/ +/* High Level Configuration Options */ +/* (easy to change) */ +/*************************************/ +#define CONFIG_MARVELL 1 +#define CONFIG_ARM926EJS 1 /* CPU */ + + +/* commands */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ + CONFIG_BOOTP_BOOTFILESIZE) + + +/* Default U-Boot supported features */ +#if defined(MV_TINY_IMAGE) +#define CONFIG_CMD_BASIC (CFG_CMD_PCI \ + | CFG_CMD_FLASH\ + | CFG_CMD_ENV \ + | CFG_CMD_NET \ + | CFG_CMD_IDE \ + | CFG_CMD_EXT2 \ + | CFG_CMD_MEMORY\ + | CFG_CMD_BOOTD) + +#elif defined(DB_FPGA) +#define CONFIG_CMD_BASIC ( CFG_CMD_DHCP \ + | CFG_CMD_ELF \ + | CFG_CMD_I2C \ + | CFG_CMD_EEPROM \ + | CFG_CMD_PCI \ + | CFG_CMD_JFFS2 \ + | CFG_CMD_DATE \ + | CFG_CMD_LOADS \ + | CFG_CMD_FLASH \ + | CFG_CMD_MEMORY \ + | CFG_CMD_ENV \ + | CFG_CMD_BOOTD \ + | CFG_CMD_CONSOLE \ + | CFG_CMD_RUN \ + | CFG_CMD_MISC \ + ) +#else +#define CONFIG_CMD_BASIC ( CFG_CMD_DHCP \ + | CFG_CMD_I2C \ + | CFG_CMD_EEPROM \ + | CFG_CMD_PCI \ + | CFG_CMD_NET \ + | CFG_CMD_PING \ + | CFG_CMD_JFFS2 \ + | CFG_CMD_DATE \ + | CFG_CMD_BSP \ + | CFG_CMD_FLASH \ + | CFG_CMD_MEMORY \ + | CFG_CMD_IDE \ + | CFG_CMD_EXT2 \ + | CFG_CMD_ENV \ + | CFG_CMD_BOOTD \ + | CFG_CMD_RUN \ + | CFG_CMD_RCVR \ + ) + +#endif + +#if defined(MV_NAND) || defined(MV_NAND_BOOT) +#define CONFIG_CMD_BASIC1 (CONFIG_CMD_BASIC | CFG_CMD_NAND) +#else +#define CONFIG_CMD_BASIC1 CONFIG_CMD_BASIC +#endif + +#if (defined(MV_INCLUDE_PEX) | defined(MV_INCLUDE_PCI)) +#define CONFIG_CMD_BASIC2 CONFIG_CMD_BASIC1 +#else +#undef CONFIG_PCI +#define CONFIG_CMD_BASIC2 (CONFIG_CMD_BASIC1 & ~CFG_CMD_PCI) +#endif + + +#if (!defined (MV_INC_BOARD_NOR_FLASH) && \ + !defined(MV_INC_BOARD_SPI_FLASH) && \ + !defined(MV_INCLUDE_INTEG_MFLASH)) +#undef CFG_ENV_IS_IN_FLASH +#define CFG_ENV_IS_NOWHERE +#define CFG_NO_FLASH +#define CONFIG_CMD_BASIC3 (CONFIG_CMD_BASIC2 & ~CFG_CMD_FLASH \ + & ~CFG_CMD_ENV \ + & ~CFG_CMD_JFFS2) +#else +#define CONFIG_CMD_BASIC3 CONFIG_CMD_BASIC2 +#endif + +#if !defined (MV_INC_BOARD_NAND_FLASH) +#define CONFIG_CMD_BASIC4 (CONFIG_CMD_BASIC3 & ~CFG_CMD_NAND) +#else +#define CONFIG_CMD_BASIC4 CONFIG_CMD_BASIC3 +#endif + +#if !defined (MV_INC_BOARD_PCI_SATA) && !defined (MV_INCLUDE_INTEG_SATA) +#define CONFIG_CMD_BASIC5 (CONFIG_CMD_BASIC4 & ~CFG_CMD_IDE \ + & ~CFG_CMD_EXT2) +#else +#define CONFIG_CMD_BASIC5 CONFIG_CMD_BASIC4 +#endif + +#if defined(MV_MMC) +#define CONFIG_CMD_BASIC6 (CONFIG_CMD_BASIC5 | CFG_CMD_MMC | CFG_CMD_FAT) +#else +#define CONFIG_CMD_BASIC6 CONFIG_CMD_BASIC5 +#endif +#define CONFIG_COMMANDS CONFIG_CMD_BASIC6 + + + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include + +#define CFG_MAXARGS 16 /* max number of command args */ + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#undef CONFIG_IDE_8xx_PCCARD /* Use IDE with PC Card Adapter */ + +#undef CONFIG_IDE_8xx_DIRECT /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_RESET /* reset for ide not supported */ + +#define CFG_IDE_MAXBUS 4 /* max. 1 IDE bus */ +#define CFG_IDE_MAXDEVICE CFG_IDE_MAXBUS * 8 /* max. 1 drive per IDE bus */ + +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#undef CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +/* For 6121/6145 support */ +#define CONFIG_SCSI_AHCI +#ifdef CONFIG_SCSI_AHCI +#define CONFIG_SATA_6121 +#define CFG_SCSI_MAX_SCSI_ID 4 +#define CFG_SCSI_MAX_LUN 1 +#define CFG_SCSI_MAX_DEVICE (CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN) +#define CFG_SCSI_MAXDEVICE CFG_SCSI_MAX_DEVICE +#endif + +#ifndef CONFIG_MMC +#define CONFIG_LBA48 +#endif + +/* which initialization functions to call for this board */ +#define CONFIG_MISC_INIT_R 1 /* after relloc initialization*/ +#undef CONFIG_DISPLAY_MEMMAP /* at the end of the bootprocess show the memory map*/ + +#define CONFIG_ENV_OVERWRITE /* allow to change env parameters */ + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +/* Cache */ +#define CFG_CACHELINE_SIZE 32 + + +/* global definetions. */ +#define CFG_SDRAM_BASE 0x00000000 + + +#define CFG_RESET_ADDRESS 0xffff0000 + +#define CFG_MALLOC_BASE (TEXT_BASE + (1 << 20)) /* TEXT_BASE + 1M */ + +/* + * When locking data in cache you should point the CFG_INIT_RAM_ADDRESS + * To an unused memory region. The stack will remain in cache until RAM + * is initialized +*/ +#define CFG_MALLOC_LEN (1 << 20) /* (default) Reserve 1MB for malloc*/ + +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for init data */ + +#undef CONFIG_INIT_CRITICAL /* critical code in start.S */ + + +/********/ +/* DRAM */ +/********/ + +#define CFG_DRAM_BANKS 4 + +/* this defines whether we want to use the lowest CAL or the highest CAL available,*/ +/* we also check for the env parameter CASset. */ +#define MV_MIN_CAL + +#define CFG_MEMTEST_START 0x00400000 +#define CFG_MEMTEST_END 0x007fffff + +/********/ +/* RTC */ +/********/ +#if (CONFIG_COMMANDS & CFG_CMD_DATE) +#define CFG_NVRAM_SIZE 0x00 /* dummy */ +#define CFG_NVRAM_BASE_ADDR DEVICE_CS1_BASE /* dummy */ +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_DATE) */ + +/********************/ +/* Serial + parser */ +/********************/ +/* + * The following defines let you select what serial you want to use + * for your console driver. + */ +#define CONFIG_BAUDRATE 115200 /* console baudrate = 115200 */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 } + +#ifdef DB_FPGA +#define CFG_DUART_CHAN 1 /* channel to use for console */ +#else +#define CFG_DUART_CHAN 0 /* channel to use for console */ +#endif + +#define CFG_INIT_CHAN1 +#define CFG_INIT_CHAN2 + + +#define CONFIG_LOADS_ECHO 0 /* echo off for serial download */ +#define CFG_LOADS_BAUD_CHANGE /* allow baudrate changes */ + +#define CFG_CONSOLE_INFO_QUIET /* don't print In/Out/Err console assignment. */ +#undef CONFIG_SILENT_CONSOLE /* define for Pex complince */ + +/* parser */ +/* don't chang the parser if you want to load Linux(if you cahnge it to HUSH the cmdline will + not pass to the kernel correctlly???) */ +/*#define CFG_HUSH_PARSER */ +#undef CFG_HUSH_PARSER +#define CONFIG_AUTO_COMPLETE + +#define CFG_PROMPT_HUSH_PS2 "> " + +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "Marvell>> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ + +/************/ +/* ETHERNET */ +/************/ +/* to change the default ethernet port, use this define (options: 0, 1, 2) */ +#if (CONFIG_COMMANDS & CFG_CMD_NET) +#define CONFIG_NET_MULTI +#define CONFIG_IPADDR 10.4.50.165 +#define CONFIG_SERVERIP 10.4.50.5 +#define CONFIG_NETMASK 255.255.255.0 +#endif + +#define ETHADDR "00:00:00:00:51:81" +#define ETH1ADDR "00:00:00:00:51:82" +#define ENV_ETH_PRIME "egiga0" + +/************/ +/* PCI */ +/************/ +#if defined(MV_INCLUDE_PCI) + +#if defined(DB_PEX_PCI) +#define ENV_PCI_MODE "device" /* PCI */ +#else +#define ENV_PCI_MODE "host" /* PCI */ +#endif + +#endif + +/************/ +/* USB */ +/************/ + +#if defined(MV_INCLUDE_USB) +#define ENV_USB0_MODE "host" +#endif + +/************/ +/* SDIO/MMC */ +/************/ + +#if defined(MV_88F6183) || defined(MV_88F6183L) +#define CONFIG_MMC +#define CFG_MMC_BASE 0xF0000000 +#endif + +/***************************************/ +/* LINUX BOOT and other ENV PARAMETERS */ +/***************************************/ +#define CFG_BOOTARGS_END ":::DB88FXX81:eth0:none" +#define CFG_BOOTARGS_END_SWITCH ":::RD88FXX81:eth0:none" +#define RCVR_IP_ADDR "169.254.100.100" +#define RCVR_LOAD_ADDR "0x02000000" + +#define CONFIG_ZERO_BOOTDELAY_CHECK + +#define CFG_LOAD_ADDR 0x02000000 /* default load address */ + +#undef CONFIG_BOOTARGS + +/* auto boot*/ +#define CONFIG_BOOTDELAY 3 /* by default no autoboot */ + +#if (CONFIG_BOOTDELAY >= 0) +#define CONFIG_ROOTPATH /mnt/ARM_FS/ +#endif /* #if (CONFIG_BOOTDELAY >= 0) */ + +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8<<20) /* Initial Memory map for Linux */ + +#define BRIDGE_REG_BASE_BOOTM 0xfbe00000 /* this paramaters are used when booting the linux kernel */ + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG 1 /* enable INITRD tag for ramdisk data */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_MARVELL_TAG 1 +#define ATAG_MARVELL 0x41000403 + +/********/ +/* I2C */ +/********/ +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_I2C_MULTI_EEPROMS +#define CFG_I2C_SPEED 100000 /* I2C speed default */ + +/* I2C addresses for the two DIMM SPD chips */ +#define DIMM0_I2C_ADDR 0x56 +#define DIMM1_I2C_ADDR 0x54 + +/* CPU I2C settings */ +#define CPU_I2C +#define I2C_CPU0_EEPROM_ADDR 0x51 + + +/********/ +/* PCI */ +/********/ +#ifdef CONFIG_PCI + #define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ + #define CONFIG_PCI_PNP /* do pci plug-and-play */ + +/* Pnp PCI Network cards */ + #define CONFIG_EEPRO100 /* Support for Intel 82557/82559/82559ER chips */ + #define CONFIG_SK98 /* yukon */ + #define YUK_ETHADDR "00:00:00:EE:51:81" + #define CONFIG_DRIVER_RTL8029 + +/* To reduce image size... */ +#if defined (MV_USB) || defined (MV_TINY_IMAGE) || defined(__BE) + #undef CONFIG_SK98 /* yukon */ + #undef CONFIG_DRIVER_RTL8029 + #undef CONFIG_EEPRO100 +#endif + +/* To reduce image size... */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#if !defined (MV_NAND_BOOT) + #undef CONFIG_DRIVER_RTL8029 + #undef CONFIG_EEPRO100 + #undef CONFIG_SK98 +#endif +#endif + +/* DB_PRPMC support only Yukon */ +#if defined (DB_PRPMC) || defined (DB_MNG) + #undef CONFIG_EEPRO100 + #undef CONFIG_DRIVER_RTL8029 +#endif + +#endif /* #ifdef CONFIG_PCI */ + +#define PCI_HOST_ADAPTER 0 /* configure ar pci adapter */ +#define PCI_HOST_FORCE 1 /* configure as pci host */ +#define PCI_HOST_AUTO 2 /* detected via arbiter enable */ + +/* for Yukon */ +#define __mem_pci(x) x +#define __io_pci(x) x +#define __arch_getw(a) (*(volatile unsigned short *)(a)) +#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v)) + + + +/***********************/ +/* FLASH organization */ +/***********************/ + +/* + * When CFG_MAX_FLASH_BANKS_DETECT is defined, the actual number of Flash + * banks has to be determined at runtime and stored in a gloabl variable + * mv_board_num_flash_banks. The value of CFG_MAX_FLASH_BANKS_DETECT is only + * used instead of CFG_MAX_FLASH_BANKS to allocate the array flash_info, and + * should be made sufficiently large to accomodate the number of banks that + * might actually be detected. Since most (all?) Flash related functions use + * CFG_MAX_FLASH_BANKS as the number of actual banks on the board, it is + * defined as mv_board_num_flash_banks. + */ +#define CFG_MAX_FLASH_BANKS_DETECT 5 +#ifndef __ASSEMBLY__ +extern int mv_board_num_flash_banks; +#endif +#define CFG_MAX_FLASH_BANKS (mv_board_num_flash_banks) + +#define CFG_MAX_FLASH_SECT 300 /* max number of sectors on one chip */ +#define CFG_FLASH_PROTECTION 1 + +#define CFG_EXTRA_FLASH_DEVICE DEVICE3 /* extra flash at device 3 */ +#define CFG_EXTRA_FLASH_WIDTH 4 /* 32 bit */ +#define CFG_BOOT_FLASH_WIDTH 1 /* 8 bit */ + +#define CFG_FLASH_ERASE_TOUT 120000/1000 /* 120000 - Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* 500 - Timeout for Flash Write (in ms) */ +#define CFG_FLASH_LOCK_TOUT 500 /* 500- Timeout for Flash Lock (in ms) */ + + +/***************************/ +/* CFI FLASH organization */ +/***************************/ +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI 1 +#define CFG_FLASH_USE_BUFFER_WRITE +#define CFG_FLASH_QUIET_TEST +#define CFG_FLASH_BANKS_LIST {BOOTDEV_CS_BASE} +#if defined(__BE) +#define CFG_WRITE_SWAPPED_DATA +#endif + +#ifdef MV_BOOTROM +#if defined (MV_FLASH_BOOT) + #define CFG_FLASH_BASE DEVICE_MFLASH_BASE + #define CFG_FLASH_SIZE (256 << 10) +#elif defined (MV_SPI_BOOT) + #define CFG_FLASH_BASE DEVICE_SPI_BASE + #define CFG_FLASH_SIZE _16M +#endif +#else + #define CFG_FLASH_BASE BOOTDEV_CS_BASE + #define CFG_FLASH_SIZE BOOTDEV_CS_SIZE +#endif /* MV_BOOTROM */ + +#define CFG_ENV_SIZE 0x1000 +#define MONITOR_HEADER_LEN 0x200 +#if defined(MV_SEC_128K) + + #if defined(MV_TINY_IMAGE) + #define CFG_MONITOR_LEN (256 << 10) /* Reserve 252 kB for Monitor */ + #else + #define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ + #endif + + #define CFG_ENV_SECT_SIZE 0x20000 +//modfiy by QNAP: Support SPANSION SPI flash sector size for 64K +#elif defined(MV_SEC_64K) + #if defined(MV_TINY_IMAGE) + #define CFG_MONITOR_LEN (256 << 10) /* Reserve 252 kB for Monitor */ + #else + #if defined(MV_BOOTROM) + #define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ + #else + #define CFG_MONITOR_LEN (448 << 10) /* Reserve 448 kB for Monitor */ + #endif + #endif + #define CFG_ENV_SECT_SIZE 0x10000 +////////////////////////////////////////////////////////////// +#elif defined(MV_SEC_256K) + #if defined(MV_TINY_IMAGE) + #define CFG_MONITOR_LEN (256 << 10) /* Reserve 252 kB for Monitor */ + #else + #define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ + #endif + + #define CFG_ENV_SECT_SIZE 0x40000 +#endif + +#ifdef MV_BOOTROM + #define CFG_MONITOR_IMAGE_OFFSET 0 /* offset of the monitor from the u-boot image */ + #define CFG_MONITOR_BASE (CFG_FLASH_BASE) + #define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN) +#else + #define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ + #define CFG_MONITOR_BASE (CFG_FLASH_BASE + CFG_FLASH_SIZE \ + - CFG_MONITOR_LEN) + #define CFG_ENV_ADDR (CFG_MONITOR_BASE - CFG_ENV_SECT_SIZE) +#endif + +/*----------------------------------------------------------------------- + * NAND-FLASH stuff + *-----------------------------------------------------------------------*/ +/* Use the new NAND code. */ + +#undef CFG_NAND_LEGACY +#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ +#define NAND_MAX_CHIPS CFG_MAX_NAND_DEVICE + +/* JFFS2 over NAND define */ +#define CONFIG_JFFS2_NAND 1 + +/* Boot from NAND settings */ +/* Duplicate defines from nBootstrap.h */ +#ifdef MV_NAND_BOOT +#define CFG_NAND_BOOT +#define CFG_ENV_IS_IN_NAND 1 + +#if defined(MV_BOOTROM) +#if defined(MV_LARGE_PAGE) +#define CFG_ENV_OFFSET (640 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) /* environment take 1 block */ +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 4KB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE 0 +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET 0 /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_ENV_OFFSET + +#else /* ! LARGE PAGE NAND */ + +#define CFG_ENV_OFFSET 0x84000 /* environment starts here */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (16 << 10) /* Reserved 16kB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (512 << 10) /* Reserve 512 kB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_NBOOT_BASE + CFG_NBOOT_LEN) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE 0x4000 +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET 0 /* offset of the monitor from the u-boot image */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR 0x84000 /* UBOOT_IMAGE_DEST - UBOOT_IMAGE_OFFS */ + +#endif /* defined(MV_LARGE_PAGE) */ + +#else /* ! MV_BOOTROM */ + +#if defined(MV_LARGE_PAGE) +#define CFG_ENV_OFFSET (640 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) /* environment take 1 block */ +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 4KB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE 0 +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET 0 /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_ENV_OFFSET + +#else /* ! LARGE PAGE NAND */ + +#define CFG_ENV_OFFSET (16 << 10) /* environment starts here */ +#undef CFG_ENV_SECT_SIZE +#define CFG_ENV_SECT_SIZE (128 << 10) +#undef CFG_ENV_SIZE +#define CFG_ENV_SIZE CFG_ENV_SECT_SIZE /* environment take 1 block */ +#define CFG_NBOOT_BASE 0 +#define CFG_NBOOT_LEN (4 << 10) /* Reserved 16kB for boot strap */ +#undef CFG_MONITOR_LEN +#define CFG_MONITOR_LEN (640 << 10) /* Reserve 4 * 128KB + ENV = 640KB for Monitor */ +#undef CFG_MONITOR_BASE +#define CFG_MONITOR_BASE (CFG_ENV_OFFSET) +#undef CFG_ENV_IS_IN_FLASH +#undef CFG_MONITOR_IMAGE_OFFSET +#define CFG_MONITOR_IMAGE_OFFSET CFG_ENV_SECT_SIZE /* offset of the monitor from the u-boot image */ +#define CFG_MONITOR_IMAGE_DST TEXT_BASE - CFG_ENV_SECT_SIZE /* Load NUB to this addr */ +#undef CFG_ENV_ADDR +#define CFG_ENV_ADDR CFG_MONITOR_IMAGE_DST +#endif /* defined(MV_LARGE_PAGE) */ +#endif /* defined(MV_BOOTROM) */ + +#endif /* MV_NAND_BOOT */ + + +#if defined(RD_88F5181L_FE) || defined(RD_88F5181L_GE) || defined(RD_88F5181L_FXO_GE) || \ + defined(RD_88F5181_GTWGE) || defined (RD_88F5181_GTWFE) + #define BOARD_LATE_INIT +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) +#define CONFIG_JFFS2_CMDLINE +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) */ + + +/*****************/ +/* others */ +/*****************/ +#define CFG_DFL_MV_REGS 0xd0000000 /* boot time MV_REGS */ +#define CFG_MV_REGS INTER_REGS_BASE /* MV Registers will be mapped here */ + +#undef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE (1 << 20) /* regular stack - up to 4M (in case of exception)*/ +#define CONFIG_NR_DRAM_BANKS 4 + +#endif /* __CONFIG_H */ diff --git a/include/exports.h b/include/exports.h index 0eaf66e..7bcd080 100644 --- a/include/exports.h +++ b/include/exports.h @@ -20,6 +20,12 @@ void udelay(unsigned long); unsigned long get_timer(unsigned long); void vprintf(const char *, va_list); void do_reset (void); +#ifdef CONFIG_MARVELL +void *realloc(void*, size_t); +void *calloc(size_t, size_t); +void *memalign(size_t, size_t); +u32 mvGetRtcSec(void); +#endif #if (CONFIG_COMMANDS & CFG_CMD_I2C) int i2c_write (uchar, uint, int , uchar* , int); int i2c_read (uchar, uint, int , uchar* , int); diff --git a/include/flash.h b/include/flash.h index decb046..b6bc9b6 100644 --- a/include/flash.h +++ b/include/flash.h @@ -45,6 +45,12 @@ typedef struct { ushort vendor; /* the primary vendor id */ ushort cmd_reset; /* Vendor specific reset command */ ushort interface; /* used for x8/x16 adjustments */ + ushort legacy_unlock; /* support Intel legacy (un)locking */ + uchar manufacturer_id; /* manufacturer id */ + ushort device_id; /* device id */ + ushort device_id2; /* extended device id */ + ushort ext_addr; /* extended query table address */ + ushort cfi_version; /* cfi version */ #endif } flash_info_t; @@ -208,6 +214,9 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define AMD_ID_GL064M_3 0x22012201 /* 3rd ID word for S29GL064M-R6 */ #define AMD_ID_GL064MT_2 0x22102210 /* 2nd ID word for S29GL064M-R3 (top boot sector) */ #define AMD_ID_GL064MT_3 0x22012201 /* 3rd ID word for S29GL064M-R3 (top boot sector) */ +#define AMD_ID_GL128N_2 0x22212221 /* 2nd ID word for S29GL128N */ +#define AMD_ID_GL128N_3 0x22012201 /* 3rd ID word for S29GL128N */ + #define AMD_ID_LV320B_2 0x221A221A /* 2d ID word for AM29LV320MB at 0x38 */ #define AMD_ID_LV320B_3 0x22002200 /* 3d ID word for AM29LV320MB at 0x3c */ @@ -233,6 +242,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define SST_ID_xF3202 0x235A235A /* 39xF3202 ID (32M = 2M x 16 ) */ #define SST_ID_xF6401 0x236B236B /* 39xF6401 ID (64M = 4M x 16 ) */ #define SST_ID_xF6402 0x236A236A /* 39xF6402 ID (64M = 4M x 16 ) */ +#define SST_ID_xF020 0xBFD6BFD6 /* 39xF020 ID (256KB = 2Mbit x 8) */ #define SST_ID_xF040 0xBFD7BFD7 /* 39xF040 ID (512KB = 4Mbit x 8) */ #define STM_ID_F040B 0xE2 /* M29F040B ID ( 4M = 512K x 8 ) */ @@ -242,6 +252,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define STM_ID_29W320DT 0x22CA22CA /* M29W320DT ID (32 M, top boot sector) */ #define STM_ID_29W320DB 0x22CB22CB /* M29W320DB ID (32 M, bottom boot sect) */ #define STM_ID_29W040B 0x00E300E3 /* M29W040B ID (4M = 512K x 8) */ +#define FLASH_PSD4256GV 0x00E9 /* PSD4256 Flash and CPLD combination */ #define INTEL_ID_28F016S 0x66a066a0 /* 28F016S[VS] ID (16M = 512k x 16) */ #define INTEL_ID_28F800B3T 0x88928892 /* 8M = 512K x 16 top boot sector */ @@ -269,10 +280,17 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define INTEL_ID_28F320J3A 0x00160016 /* 32M = 128K x 32 */ #define INTEL_ID_28F640J3A 0x00170017 /* 64M = 128K x 64 */ #define INTEL_ID_28F128J3A 0x00180018 /* 128M = 128K x 128 */ +#define INTEL_ID_28F256J3A 0x001D001D /* 256M = 128K x 256 */ #define INTEL_ID_28F256L18T 0x880D880D /* 256M = 128K x 255 + 32k x 4 */ #define INTEL_ID_28F64K3 0x88018801 /* 64M = 32K x 255 + 32k x 4 */ #define INTEL_ID_28F128K3 0x88028802 /* 128M = 64K x 255 + 32k x 4 */ #define INTEL_ID_28F256K3 0x88038803 /* 256M = 128K x 255 + 32k x 4 */ +#define INTEL_ID_28F64P30T 0x88178817 /* 64M = 32K x 255 + 32k x 4 */ +#define INTEL_ID_28F64P30B 0x881A881A /* 64M = 32K x 255 + 32k x 4 */ +#define INTEL_ID_28F128P30T 0x88188818 /* 128M = 64K x 255 + 32k x 4 */ +#define INTEL_ID_28F128P30B 0x881B881B /* 128M = 64K x 255 + 32k x 4 */ +#define INTEL_ID_28F256P30T 0x88198819 /* 256M = 128K x 255 + 32k x 4 */ +#define INTEL_ID_28F256P30B 0x881C881C /* 256M = 128K x 255 + 32k x 4 */ #define INTEL_ID_28F160S3 0x00D000D0 /* 16M = 512K x 32 (64kB x 32) */ #define INTEL_ID_28F320S3 0x00D400D4 /* 32M = 512K x 64 (64kB x 64) */ @@ -334,6 +352,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define FLASH_SST160A 0x0046 /* SST 39xF160A ID ( 16M = 1M x 16 ) */ #define FLASH_SST320 0x0048 /* SST 39xF160A ID ( 16M = 1M x 16 ) */ #define FLASH_SST640 0x004A /* SST 39xF160A ID ( 16M = 1M x 16 ) */ +#define FLASH_SST020 0x0024 /* SST 39xF020 ID (256KB = 2Mbit x 8 ) */ #define FLASH_SST040 0x000E /* SST 39xF040 ID (512KB = 4Mbit x 8 ) */ #define FLASH_STM800AB 0x0051 /* STM M29WF800AB ( 8M = 512K x 16 ) */ @@ -401,10 +420,12 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define FLASH_28F320J3A 0x00C0 /* INTEL 28F320J3A ( 32M = 128K x 32) */ #define FLASH_28F640J3A 0x00C2 /* INTEL 28F640J3A ( 64M = 128K x 64) */ #define FLASH_28F128J3A 0x00C4 /* INTEL 28F128J3A (128M = 128K x 128) */ +#define FLASH_28F256J3A 0x00C6 /* INTEL 28F256J3A (256M = 128K x 256) */ #define FLASH_FUJLV650 0x00D0 /* Fujitsu MBM 29LV650UE/651UE */ #define FLASH_MT28S4M16LC 0x00E1 /* Micron MT28S4M16LC */ #define FLASH_S29GL064M 0x00F0 /* Spansion S29GL064M-R6 */ +#define FLASH_S29GL128N 0x00F1 /* Spansion S29GL128N */ #define FLASH_UNKNOWN 0xFFFF /* unknown flash type */ @@ -423,6 +444,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of #define FLASH_MAN_MT 0x00400000 #define FLASH_MAN_SHARP 0x00500000 #define FLASH_MAN_ATM 0x00600000 +#define FLASH_MAN_CFI 0x01000000 #define FLASH_TYPEMASK 0x0000FFFF /* extract FLASH type information */ diff --git a/include/i2c.h b/include/i2c.h index 6d39080..6d30afb 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -59,7 +59,11 @@ void i2c_init_board(void); * Probe the given I2C chip address. Returns 0 if a chip responded, * not 0 on failure. */ +#if defined(CONFIG_MARVELL) +int i2c_probe (uchar chanNum, uchar chip); +#else int i2c_probe(uchar chip); +#endif /* * Read/Write interface: diff --git a/include/ide.h b/include/ide.h index dfef32f..0d2c510 100644 --- a/include/ide.h +++ b/include/ide.h @@ -40,8 +40,16 @@ #ifdef CFG_64BIT_LBA typedef uint64_t lbaint_t; +#define IDE_BLOCK_NUMBER_MASK 0x0000fffff0000000 +#define LBA_LOW_REG_SHIFT 24 +#define LBA_MID_REG_SHIFT 32 +#define LBA_HIGH_REG_SHIFT 40 #else typedef ulong lbaint_t; +#define IDE_BLOCK_NUMBER_MASK 0xf0000000 +#define LBA_LOW_REG_SHIFT 24 +#define LBA_MID_REG_SHIFT 0 +#define LBA_HIGH_REG_SHIFT 0 #endif /* diff --git a/include/jffs2/compr_rubin.h b/include/jffs2/compr_rubin.h index f26f476..b25dc98 100644 --- a/include/jffs2/compr_rubin.h +++ b/include/jffs2/compr_rubin.h @@ -1,7 +1,7 @@ /* Rubin encoder/decoder header */ /* work started at : aug 3, 1994 */ /* last modification : aug 15, 1994 */ -/* $Id: compr_rubin.h,v 1.1 2002/01/16 23:34:32 nyet Exp $ */ +/* $Id: compr_rubin.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ #define RUBIN_REG_SIZE 16 #define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1)) diff --git a/include/jffs2/jffs2.h b/include/jffs2/jffs2.h index d142cd1..982f28c 100644 --- a/include/jffs2/jffs2.h +++ b/include/jffs2/jffs2.h @@ -31,7 +31,7 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: jffs2.h,v 1.2 2002/01/17 00:53:20 nyet Exp $ + * $Id: jffs2.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * */ diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h index 882a80e..1036483 100644 --- a/include/jffs2/load_kernel.h +++ b/include/jffs2/load_kernel.h @@ -2,7 +2,7 @@ #define load_kernel_h /*------------------------------------------------------------------------- * Filename: load_kernel.h - * Version: $Id: load_kernel.h,v 1.3 2002/01/25 01:34:11 nyet Exp $ + * Version: $Id: load_kernel.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * Copyright: Copyright (C) 2001, Russ Dill * Author: Russ Dill * Description: header for load kernel modules diff --git a/include/jffs2/mini_inflate.h b/include/jffs2/mini_inflate.h index f79aac7..f0cd09c 100644 --- a/include/jffs2/mini_inflate.h +++ b/include/jffs2/mini_inflate.h @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * Filename: mini_inflate.h - * Version: $Id: mini_inflate.h,v 1.2 2002/01/17 00:53:20 nyet Exp $ + * Version: $Id: mini_inflate.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * Copyright: Copyright (C) 2001, Russ Dill * Author: Russ Dill * Description: Mini deflate implementation diff --git a/include/linux/mtd/compat.h b/include/linux/mtd/compat.h new file mode 100644 index 0000000..6cdd1b8 --- /dev/null +++ b/include/linux/mtd/compat.h @@ -0,0 +1,46 @@ +#ifndef _LINUX_COMPAT_H_ +#define _LINUX_COMPAT_H_ + +#define __user +#define __iomem + +#define ndelay(x) udelay(1) + +#define printk printf + +#define KERN_EMERG +#define KERN_ALERT +#define KERN_CRIT +#define KERN_ERR +#define KERN_WARNING +#define KERN_NOTICE +#define KERN_INFO +#define KERN_DEBUG + +#define kmalloc(size, flags) malloc(size) +#define kfree(ptr) free(ptr) + +/* + * ..and if you can't take the strict + * types, you can specify one yourself. + * + * Or not use min/max at all, of course. + */ +#define min_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) +#define max_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) + +#ifndef BUG +#define BUG() do { \ + printf("U-Boot BUG at %s:%d!\n", __FILE__, __LINE__); \ +} while (0) + +#define BUG_ON(condition) do { if (condition) BUG(); } while(0) +#endif /* BUG */ + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +//#define PAGE_SIZE 4096 +#endif diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index ebf9a76..2b1c9cf 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h @@ -2,7 +2,7 @@ /* Linux driver for Disk-On-Chip 2000 */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: doc2000.h,v 1.15 2001/09/19 00:22:15 dwmw2 Exp $ */ +/* $Id: doc2000.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ #ifndef __MTD_DOC2000_H__ #define __MTD_DOC2000_H__ diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h new file mode 100644 index 0000000..d0d5e55 --- /dev/null +++ b/include/linux/mtd/mtd-abi.h @@ -0,0 +1,99 @@ +/* + * $Id: mtd-abi.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ + * + * Portions of MTD ABI definition which are shared by kernel and user space + */ + +#ifndef __MTD_ABI_H__ +#define __MTD_ABI_H__ + +struct erase_info_user { + uint32_t start; + uint32_t length; +}; + +struct mtd_oob_buf { + uint32_t start; + uint32_t length; + unsigned char *ptr; +}; + +#define MTD_ABSENT 0 +#define MTD_RAM 1 +#define MTD_ROM 2 +#define MTD_NORFLASH 3 +#define MTD_NANDFLASH 4 +#define MTD_PEROM 5 +#define MTD_OTHER 14 +#define MTD_UNKNOWN 15 + +#define MTD_CLEAR_BITS 1 /* Bits can be cleared (flash) */ +#define MTD_SET_BITS 2 /* Bits can be set */ +#define MTD_ERASEABLE 4 /* Has an erase function */ +#define MTD_WRITEB_WRITEABLE 8 /* Direct IO is possible */ +#define MTD_VOLATILE 16 /* Set for RAMs */ +#define MTD_XIP 32 /* eXecute-In-Place possible */ +#define MTD_OOB 64 /* Out-of-band data (NAND flash) */ +#define MTD_ECC 128 /* Device capable of automatic ECC */ +#define MTD_NO_VIRTBLOCKS 256 /* Virtual blocks not allowed */ + +/* Some common devices / combinations of capabilities */ +#define MTD_CAP_ROM 0 +#define MTD_CAP_RAM (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE) +#define MTD_CAP_NORFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE) +#define MTD_CAP_NANDFLASH (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB) +#define MTD_WRITEABLE (MTD_CLEAR_BITS|MTD_SET_BITS) + + +/* Types of automatic ECC/Checksum available */ +#define MTD_ECC_NONE 0 /* No automatic ECC available */ +#define MTD_ECC_RS_DiskOnChip 1 /* Automatic ECC on DiskOnChip */ +#define MTD_ECC_SW 2 /* SW ECC for Toshiba & Samsung devices */ + +/* ECC byte placement */ +#define MTD_NANDECC_OFF 0 /* Switch off ECC (Not recommended) */ +#define MTD_NANDECC_PLACE 1 /* Use the given placement in the structure (YAFFS1 legacy mode) */ +#define MTD_NANDECC_AUTOPLACE 2 /* Use the default placement scheme */ +#define MTD_NANDECC_PLACEONLY 3 /* Use the given placement in the structure (Do not store ecc result on read) */ +#define MTD_NANDECC_AUTOPL_USR 4 /* Use the given autoplacement scheme rather than using the default */ + +struct mtd_info_user { + uint8_t type; + uint32_t flags; + uint32_t size; /* Total size of the MTD */ + uint32_t erasesize; + uint32_t oobblock; /* Size of OOB blocks (e.g. 512) */ + uint32_t oobsize; /* Amount of OOB data per block (e.g. 16) */ + uint32_t ecctype; + uint32_t eccsize; +}; + +struct region_info_user { + uint32_t offset; /* At which this region starts, + * from the beginning of the MTD */ + uint32_t erasesize; /* For this region */ + uint32_t numblocks; /* Number of blocks in this region */ + uint32_t regionindex; +}; + +#define MEMGETINFO _IOR('M', 1, struct mtd_info_user) +#define MEMERASE _IOW('M', 2, struct erase_info_user) +#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf) +#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf) +#define MEMLOCK _IOW('M', 5, struct erase_info_user) +#define MEMUNLOCK _IOW('M', 6, struct erase_info_user) +#define MEMGETREGIONCOUNT _IOR('M', 7, int) +#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) +#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) +#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) +#define MEMGETBADBLOCK _IOW('M', 11, loff_t) +#define MEMSETBADBLOCK _IOW('M', 12, loff_t) + +struct nand_oobinfo { + uint32_t useecc; + uint32_t eccbytes; + uint32_t oobfree[8][2]; + uint32_t eccpos[40] /*eccpos[32]*/; /* RS ECC */ +}; + +#endif /* __MTD_ABI_H__ */ diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h new file mode 100644 index 0000000..ebd1d92 --- /dev/null +++ b/include/linux/mtd/mtd.h @@ -0,0 +1,214 @@ +/* + * $Id: mtd.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ + * + * Copyright (C) 1999-2003 David Woodhouse et al. + * + * Released under GPL + */ + +#ifndef __MTD_MTD_H__ +#define __MTD_MTD_H__ +#include +#include + +#define MAX_MTD_DEVICES 16 + +#define MTD_ERASE_PENDING 0x01 +#define MTD_ERASING 0x02 +#define MTD_ERASE_SUSPEND 0x04 +#define MTD_ERASE_DONE 0x08 +#define MTD_ERASE_FAILED 0x10 + +/* If the erase fails, fail_addr might indicate exactly which block failed. If + fail_addr = 0xffffffff, the failure was not at the device level or was not + specific to any particular block. */ +struct erase_info { + struct mtd_info *mtd; + u_int32_t addr; + u_int32_t len; + u_int32_t fail_addr; + u_long time; + u_long retries; + u_int dev; + u_int cell; + void (*callback) (struct erase_info *self); + u_long priv; + u_char state; + struct erase_info *next; +}; + +struct mtd_erase_region_info { + u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ + u_int32_t erasesize; /* For this region */ + u_int32_t numblocks; /* Number of blocks of erasesize in this region */ +}; + +struct mtd_info { + u_char type; + u_int32_t flags; + u_int32_t size; /* Total size of the MTD */ + + /* "Major" erase size for the device. Naïve users may take this + * to be the only erase size available, or may use the more detailed + * information below if they desire + */ + u_int32_t erasesize; + + u_int32_t oobblock; /* Size of OOB blocks (e.g. 512) */ + u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */ + u_int32_t oobavail; /* Number of bytes in OOB area available for fs */ + u_int32_t ecctype; + u_int32_t eccsize; + + + /* Kernel-only stuff starts here. */ + char *name; + int index; + + /* oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) */ + struct nand_oobinfo oobinfo; + + /* Data for variable erase regions. If numeraseregions is zero, + * it means that the whole device has erasesize as given above. + */ + int numeraseregions; + struct mtd_erase_region_info *eraseregions; + + /* This really shouldn't be here. It can go away in 2.5 */ + u_int32_t bank_size; + + int (*erase) (struct mtd_info *mtd, struct erase_info *instr); + + /* This stuff for eXecute-In-Place */ + int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); + + /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ + void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len); + + + int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); + int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); + + int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); + int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); + + int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); + int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); + + /* + * Methods to access the protection register area, present in some + * flash devices. The user data is one time programmable but the + * factory data is read only. + */ + int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); + + int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); + + /* This function is not yet implemented */ + int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); +#if 0 + /* kvec-based read/write methods. We need these especially for NAND flash, + with its limited number of write cycles per erase. + NB: The 'count' parameter is the number of _vectors_, each of + which contains an (ofs, len) tuple. + */ + int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen); + int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, + size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); + int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); + int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, + size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); +#endif + /* Sync */ + void (*sync) (struct mtd_info *mtd); +#if 0 + /* Chip-supported device locking */ + int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len); + int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len); + + /* Power Management functions */ + int (*suspend) (struct mtd_info *mtd); + void (*resume) (struct mtd_info *mtd); +#endif + /* Bad block management functions */ + int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); + int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); + + void *priv; + + struct module *owner; + int usecount; +}; + + + /* Kernel-side ioctl definitions */ + +extern int add_mtd_device(struct mtd_info *mtd); +extern int del_mtd_device (struct mtd_info *mtd); + +extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); + +extern void put_mtd_device(struct mtd_info *mtd); + +#if 0 +struct mtd_notifier { + void (*add)(struct mtd_info *mtd); + void (*remove)(struct mtd_info *mtd); + struct list_head list; +}; + + +extern void register_mtd_user (struct mtd_notifier *new); +extern int unregister_mtd_user (struct mtd_notifier *old); + +int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen); + +int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, + unsigned long count, loff_t from, size_t *retlen); +#endif + +#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args) +#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d)) +#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg) +#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args) +#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args) +#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args) +#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args) +#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args) +#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args) +#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args) +#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args) +#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) + + +#ifdef CONFIG_MTD_PARTITIONS +void mtd_erase_callback(struct erase_info *instr); +#else +static inline void mtd_erase_callback(struct erase_info *instr) +{ + if (instr->callback) + instr->callback(instr); +} +#endif + +/* + * Debugging macro and defines + */ +#define MTD_DEBUG_LEVEL0 (0) /* Quiet */ +#define MTD_DEBUG_LEVEL1 (1) /* Audible */ +#define MTD_DEBUG_LEVEL2 (2) /* Loud */ +#define MTD_DEBUG_LEVEL3 (3) /* Noisy */ + +#ifdef CONFIG_MTD_DEBUG +#define DEBUG(n, args...) \ + do { \ + if (n <= CONFIG_MTD_DEBUG_VERBOSE) \ + printk(KERN_INFO args); \ + } while(0) +#else /* CONFIG_MTD_DEBUG */ +#define DEBUG(n, args...) do { } while(0) + +#endif /* CONFIG_MTD_DEBUG */ + +#endif /* __MTD_MTD_H__ */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 5236904..cae4e00 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -2,10 +2,10 @@ * linux/include/linux/mtd/nand.h * * Copyright (c) 2000 David Woodhouse - * Steven J. Hill - * Thomas Gleixner + * Steven J. Hill + * Thomas Gleixner * - * $Id: nand.h,v 1.7 2003/07/24 23:30:46 a0384864 Exp $ + * $Id: nand.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * 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 @@ -15,15 +15,15 @@ * Contains standard defines and IDs for NAND flash devices * * Changelog: - * 01-31-2000 DMW Created - * 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers + * 01-31-2000 DMW Created + * 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers * so it can be used by other NAND flash device * drivers. I also changed the copyright since none * of the original contents of this file are specific * to DoC devices. David can whack me with a baseball * bat later if I did something naughty. - * 10-11-2000 SJH Added private NAND flash structure for driver - * 10-24-2000 SJH Added prototype for 'nand_scan' function + * 10-11-2000 SJH Added private NAND flash structure for driver + * 10-24-2000 SJH Added prototype for 'nand_scan' function * 10-29-2001 TG changed nand_chip structure to support * hardwarespecific function for accessing control lines * 02-21-2002 TG added support for different read/write adress and @@ -32,10 +32,65 @@ * command delay times for different chips * 04-28-2002 TG OOB config defines moved from nand.c to avoid duplicate * defines in jffs2/wbuf.c + * 08-07-2002 TG forced bad block location to byte 5 of OOB, even if + * CONFIG_MTD_NAND_ECC_JFFS2 is not set + * 08-10-2002 TG extensions to nand_chip structure to support HW-ECC + * + * 08-29-2002 tglx nand_chip structure: data_poi for selecting + * internal / fs-driver buffer + * support for 6byte/512byte hardware ECC + * read_ecc, write_ecc extended for different oob-layout + * oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB, + * NAND_YAFFS_OOB + * 11-25-2002 tglx Added Manufacturer code FUJITSU, NATIONAL + * Split manufacturer and device ID structures + * + * 02-08-2004 tglx added option field to nand structure for chip anomalities + * 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id + * update of nand_chip structure description */ #ifndef __LINUX_MTD_NAND_H #define __LINUX_MTD_NAND_H +#include +#include + +struct mtd_info; +/* Scan and identify a NAND device */ +extern int nand_scan (struct mtd_info *mtd, int max_chips); +/* Free resources held by the NAND device */ +extern void nand_release (struct mtd_info *mtd); + +/* Read raw data from the device without ECC */ +extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen); + + +/* This constant declares the max. oobsize / page, which + * is supported now. If you add a chip with bigger oobsize/page + * adjust this accordingly. + */ +#define NAND_MAX_OOBSIZE 64 + +/* + * Constants for hardware specific CLE/ALE/NCE function +*/ +/* Select the chip by setting nCE to low */ +#define NAND_CTL_SETNCE 1 +/* Deselect the chip by setting nCE to high */ +#define NAND_CTL_CLRNCE 2 +/* Select the command latch by setting CLE to high */ +#define NAND_CTL_SETCLE 3 +/* Deselect the command latch by setting CLE to low */ +#define NAND_CTL_CLRCLE 4 +/* Select the address latch by setting ALE to high */ +#define NAND_CTL_SETALE 5 +/* Deselect the address latch by setting ALE to low */ +#define NAND_CTL_CLRALE 6 +/* Set write protection by setting WP to high. Not used! */ +#define NAND_CTL_SETWP 7 +/* Clear write protection by setting WP to low. Not used! */ +#define NAND_CTL_CLRWP 8 + /* * Standard NAND flash commands */ @@ -45,12 +100,104 @@ #define NAND_CMD_READOOB 0x50 #define NAND_CMD_ERASE1 0x60 #define NAND_CMD_STATUS 0x70 +#define NAND_CMD_STATUS_MULTI 0x71 #define NAND_CMD_SEQIN 0x80 #define NAND_CMD_READID 0x90 #define NAND_CMD_ERASE2 0xd0 #define NAND_CMD_RESET 0xff +/* Extended commands for large page devices */ +#define NAND_CMD_READSTART 0x30 +#define NAND_CMD_CACHEDPROG 0x15 + +/* Status bits */ +#define NAND_STATUS_FAIL 0x01 +#define NAND_STATUS_FAIL_N1 0x02 +#define NAND_STATUS_TRUE_READY 0x20 +#define NAND_STATUS_READY 0x40 +#define NAND_STATUS_WP 0x80 + /* + * Constants for ECC_MODES + */ + +/* No ECC. Usage is not recommended ! */ +#define NAND_ECC_NONE 0 +/* Software ECC 3 byte ECC per 256 Byte data */ +#define NAND_ECC_SOFT 1 +/* Hardware ECC 3 byte ECC per 256 Byte data */ +#define NAND_ECC_HW3_256 2 +/* Hardware ECC 3 byte ECC per 512 Byte data */ +#define NAND_ECC_HW3_512 3 +/* Hardware ECC 3 byte ECC per 512 Byte data */ +#define NAND_ECC_HW6_512 4 +/* Hardware ECC 8 byte ECC per 512 Byte data */ +#define NAND_ECC_HW8_512 6 +/* Hardware ECC 12 byte ECC per 2048 Byte data */ +#define NAND_ECC_HW12_2048 7 + +/* + * Constants for Hardware ECC +*/ +/* Reset Hardware ECC for read */ +#define NAND_ECC_READ 0 +/* Reset Hardware ECC for write */ +#define NAND_ECC_WRITE 1 +/* Enable Hardware ECC before syndrom is read back from flash */ +#define NAND_ECC_READSYN 2 + +/* Option constants for bizarre disfunctionality and real +* features +*/ +/* Chip can not auto increment pages */ +#define NAND_NO_AUTOINCR 0x00000001 +/* Buswitdh is 16 bit */ +#define NAND_BUSWIDTH_16 0x00000002 +/* Device supports partial programming without padding */ +#define NAND_NO_PADDING 0x00000004 +/* Chip has cache program function */ +#define NAND_CACHEPRG 0x00000008 +/* Chip has copy back function */ +#define NAND_COPYBACK 0x00000010 +/* AND Chip which has 4 banks and a confusing page / block + * assignment. See Renesas datasheet for further information */ +#define NAND_IS_AND 0x00000020 +/* Chip has a array of 4 pages which can be read without + * additional ready /busy waits */ +#define NAND_4PAGE_ARRAY 0x00000040 + +/* Options valid for Samsung large page devices */ +#define NAND_SAMSUNG_LP_OPTIONS \ + (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK) + +/* Macros to identify the above */ +#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR)) +#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING)) +#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG)) +#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK)) + +/* Mask to zero out the chip options, which come from the id table */ +#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) + +/* Non chip related options */ +/* Use a flash based bad block table. This option is passed to the + * default bad block table function. */ +#define NAND_USE_FLASH_BBT 0x00010000 +/* The hw ecc generator provides a syndrome instead a ecc value on read + * This can only work if we have the ecc bytes directly behind the + * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */ +#define NAND_HWECC_SYNDROME 0x00020000 + + +/* Options set by nand scan */ +/* Nand scan has allocated oob_buf */ +#define NAND_OOBBUF_ALLOC 0x40000000 +/* Nand scan has allocated data_buf */ +#define NAND_DATABUF_ALLOC 0x80000000 + + +/* + * nand_state_t - chip states * Enumeration for NAND flash chip state */ typedef enum { @@ -58,71 +205,138 @@ typedef enum { FL_READING, FL_WRITING, FL_ERASING, - FL_SYNCING + FL_SYNCING, + FL_CACHEDPRG, } nand_state_t; +/* Keep gcc happy */ +struct nand_chip; -/* - * NAND Private Flash Chip Data - * - * Structure overview: - * - * IO_ADDR - address to access the 8 I/O lines of the flash device - * - * hwcontrol - hardwarespecific function for accesing control-lines - * - * dev_ready - hardwarespecific function for accesing device ready/busy line - * - * chip_lock - spinlock used to protect access to this structure - * - * wq - wait queue to sleep on if a NAND operation is in progress - * - * state - give the current state of the NAND device - * - * page_shift - number of address bits in a page (column address bits) - * - * data_buf - data buffer passed to/from MTD user modules - * - * data_cache - data cache for redundant page access and shadow for - * ECC failure - * - * ecc_code_buf - used only for holding calculated or read ECCs for - * a page read or written when ECC is in use - * - * reserved - padding to make structure fall on word boundary if - * when ECC is in use +#if 0 +/** + * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices + * @lock: protection lock + * @active: the mtd device which holds the controller currently */ -struct Nand { - char floor, chip; - unsigned long curadr; - unsigned char curmode; - /* Also some erase/write/pipeline info when we get that far */ +struct nand_hw_control { + spinlock_t lock; + struct nand_chip *active; }; +#endif + +/** + * struct nand_chip - NAND Private Flash Chip Data + * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device + * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device + * @read_byte: [REPLACEABLE] read one byte from the chip + * @write_byte: [REPLACEABLE] write one byte to the chip + * @read_word: [REPLACEABLE] read one word from the chip + * @write_word: [REPLACEABLE] write one word to the chip + * @write_buf: [REPLACEABLE] write data from the buffer to the chip + * @read_buf: [REPLACEABLE] read data from the chip into the buffer + * @verify_buf: [REPLACEABLE] verify buffer contents against the chip data + * @select_chip: [REPLACEABLE] select chip nr + * @block_bad: [REPLACEABLE] check, if the block is bad + * @block_markbad: [REPLACEABLE] mark the block bad + * @hwcontrol: [BOARDSPECIFIC] hardwarespecific function for accesing control-lines + * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line + * If set to NULL no access to ready/busy is available and the ready/busy information + * is read from the chip status register + * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip + * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready + * @calculate_ecc: [REPLACEABLE] function for ecc calculation or readback from ecc hardware + * @correct_data: [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw) + * @enable_hwecc: [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only + * be provided if a hardware ECC is available + * @erase_cmd: [INTERN] erase command write function, selectable due to AND support + * @scan_bbt: [REPLACEABLE] function to scan bad block table + * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines + * @eccsize: [INTERN] databytes used per ecc-calculation + * @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step + * @eccsteps: [INTERN] number of ecc calculation steps per page + * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) + * @chip_lock: [INTERN] spinlock used to protect access to this structure and the chip + * @wq: [INTERN] wait queue to sleep on if a NAND operation is in progress + * @state: [INTERN] the current state of the NAND device + * @page_shift: [INTERN] number of address bits in a page (column address bits) + * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock + * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry + * @chip_shift: [INTERN] number of address bits in one chip + * @data_buf: [INTERN] internal buffer for one page + oob + * @oob_buf: [INTERN] oob buffer for one eraseblock + * @oobdirty: [INTERN] indicates that oob_buf must be reinitialized + * @data_poi: [INTERN] pointer to a data buffer + * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about + * special functionality. See the defines for further explanation + * @badblockpos: [INTERN] position of the bad block marker in the oob area + * @numchips: [INTERN] number of physical chips + * @chipsize: [INTERN] the size of one chip for multichip arrays + * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 + * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf + * @autooob: [REPLACEABLE] the default (auto)placement scheme + * @bbt: [INTERN] bad block table pointer + * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup + * @bbt_md: [REPLACEABLE] bad block table mirror descriptor + * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan + * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices + * @priv: [OPTIONAL] pointer to private chip date + */ struct nand_chip { - int page_shift; - u_char *data_buf; - u_char *data_cache; - int cache_page; - u_char ecc_code_buf[6]; - u_char reserved[2]; - char ChipID; /* Type of DiskOnChip */ - struct Nand *chips; - int chipshift; - char* chips_name; - unsigned long erasesize; - unsigned long mfr; /* Flash IDs - only one type of flash per device */ - unsigned long id; - char* name; - int numchips; - char page256; - char pageadrlen; - unsigned long IO_ADDR; /* address to access the 8 I/O lines to the flash device */ - unsigned long totlen; - uint oobblock; /* Size of OOB blocks (e.g. 512) */ - uint oobsize; /* Amount of OOB data per block (e.g. 16) */ - uint eccsize; - int bus16; + void __iomem *IO_ADDR_R; + void __iomem *IO_ADDR_W; + + u_char (*read_byte)(struct mtd_info *mtd); + void (*write_byte)(struct mtd_info *mtd, u_char byte); + u16 (*read_word)(struct mtd_info *mtd); + void (*write_word)(struct mtd_info *mtd, u16 word); + + void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len); + void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len); + int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len); + void (*select_chip)(struct mtd_info *mtd, int chip); + int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); + int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); + void (*hwcontrol)(struct mtd_info *mtd, int cmd); + int (*dev_ready)(struct mtd_info *mtd); + void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); + int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state); + int (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); + int (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); + void (*enable_hwecc)(struct mtd_info *mtd, int mode); + void (*erase_cmd)(struct mtd_info *mtd, int page); + int (*scan_bbt)(struct mtd_info *mtd); + int eccmode; + int eccsize; + int eccbytes; + int eccsteps; + int chip_delay; +#if 0 + spinlock_t chip_lock; + wait_queue_head_t wq; + nand_state_t state; +#endif + int page_shift; + int phys_erase_shift; + int bbt_erase_shift; + int chip_shift; + u_char *data_buf; + u_char *oob_buf; + int oobdirty; + u_char *data_poi; + unsigned int options; + int badblockpos; + int numchips; + unsigned long chipsize; + int pagemask; + int pagebuf; + struct nand_oobinfo *autooob; + uint8_t *bbt; + struct nand_bbt_descr *bbt_td; + struct nand_bbt_descr *bbt_md; + struct nand_bbt_descr *badblock_pattern; + struct nand_hw_control *controller; + void *priv; }; /* @@ -130,71 +344,125 @@ struct nand_chip { */ #define NAND_MFR_TOSHIBA 0x98 #define NAND_MFR_SAMSUNG 0xec +#define NAND_MFR_FUJITSU 0x04 +#define NAND_MFR_NATIONAL 0x8f +#define NAND_MFR_RENESAS 0x07 +#define NAND_MFR_STMICRO 0x20 -/* - * NAND Flash Device ID Structure +/** + * struct nand_flash_dev - NAND Flash Device ID Structure * - * Structure overview: - * - * name - Complete name of device - * - * manufacture_id - manufacturer ID code of device. - * - * model_id - model ID code of device. - * - * chipshift - total number of address bits for the device which - * is used to calculate address offsets and the total - * number of bytes the device is capable of. - * - * page256 - denotes if flash device has 256 byte pages or not. - * - * pageadrlen - number of bytes minus one needed to hold the - * complete address into the flash array. Keep in - * mind that when a read or write is done to a - * specific address, the address is input serially - * 8 bits at a time. This structure member is used - * by the read/write routines as a loop index for - * shifting the address out 8 bits at a time. - * - * erasesize - size of an erase block in the flash device. + * @name: Identify the device type + * @id: device ID code + * @pagesize: Pagesize in bytes. Either 256 or 512 or 0 + * If the pagesize is 0, then the real pagesize + * and the eraseize are determined from the + * extended id bytes in the chip + * @erasesize: Size of an erase block in the flash device. + * @chipsize: Total chipsize in Mega Bytes + * @options: Bitfield to store chip relevant options */ struct nand_flash_dev { - char * name; - int manufacture_id; - int model_id; - int chipshift; - char page256; - char pageadrlen; + char *name; + int id; + unsigned long pagesize; + unsigned long chipsize; unsigned long erasesize; - int bus16; + unsigned long options; }; +/** + * struct nand_manufacturers - NAND Flash Manufacturer ID Structure + * @name: Manufacturer name + * @id: manufacturer ID code of device. +*/ +struct nand_manufacturers { + int id; + char * name; +}; + +extern struct nand_flash_dev nand_flash_ids[]; +extern struct nand_manufacturers nand_manuf_ids[]; + +/** + * struct nand_bbt_descr - bad block table descriptor + * @options: options for this descriptor + * @pages: the page(s) where we find the bbt, used with option BBT_ABSPAGE + * when bbt is searched, then we store the found bbts pages here. + * Its an array and supports up to 8 chips now + * @offs: offset of the pattern in the oob area of the page + * @veroffs: offset of the bbt version counter in the oob are of the page + * @version: version read from the bbt page during scan + * @len: length of the pattern, if 0 no pattern check is performed + * @maxblocks: maximum number of blocks to search for a bbt. This number of + * blocks is reserved at the end of the device where the tables are + * written. + * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than + * bad) block in the stored bbt + * @pattern: pattern to identify bad block table or factory marked good / + * bad blocks, can be NULL, if len = 0 + * + * Descriptor for the bad block table marker and the descriptor for the + * pattern which identifies good and bad blocks. The assumption is made + * that the pattern and the version count are always located in the oob area + * of the first block. + */ +struct nand_bbt_descr { + int options; + int pages[NAND_MAX_CHIPS]; + int offs; + int veroffs; + uint8_t version[NAND_MAX_CHIPS]; + int len; + int maxblocks; + int reserved_block_code; + uint8_t *pattern; +}; + +/* Options for the bad block table descriptors */ + +/* The number of bits used per block in the bbt on the device */ +#define NAND_BBT_NRBITS_MSK 0x0000000F +#define NAND_BBT_1BIT 0x00000001 +#define NAND_BBT_2BIT 0x00000002 +#define NAND_BBT_4BIT 0x00000004 +#define NAND_BBT_8BIT 0x00000008 +/* The bad block table is in the last good block of the device */ +#define NAND_BBT_LASTBLOCK 0x00000010 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_ABSPAGE 0x00000020 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_SEARCH 0x00000040 +/* bbt is stored per chip on multichip devices */ +#define NAND_BBT_PERCHIP 0x00000080 +/* bbt has a version counter at offset veroffs */ +#define NAND_BBT_VERSION 0x00000100 +/* Create a bbt if none axists */ +#define NAND_BBT_CREATE 0x00000200 +/* Search good / bad pattern through all pages of a block */ +#define NAND_BBT_SCANALLPAGES 0x00000400 +/* Scan block empty during good / bad block scan */ +#define NAND_BBT_SCANEMPTY 0x00000800 +/* Write bbt if neccecary */ +#define NAND_BBT_WRITE 0x00001000 +/* Read and write back block contents when writing bbt */ +#define NAND_BBT_SAVECONTENT 0x00002000 +/* Search good / bad pattern on the first and the second page */ +#define NAND_BBT_SCAN2NDPAGE 0x00004000 + +/* The maximum number of blocks to scan for a bbt */ +#define NAND_BBT_SCAN_MAXBLOCKS 4 + +extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd); +extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs); +extern int nand_default_bbt (struct mtd_info *mtd); +extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt); +extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt); + /* * Constants for oob configuration */ -#define NAND_NOOB_ECCPOS0 0 -#define NAND_NOOB_ECCPOS1 1 -#define NAND_NOOB_ECCPOS2 2 -#define NAND_NOOB_ECCPOS3 3 -#define NAND_NOOB_ECCPOS4 6 -#define NAND_NOOB_ECCPOS5 7 -#define NAND_NOOB_BADBPOS -1 -#define NAND_NOOB_ECCVPOS -1 - -#define NAND_JFFS2_OOB_ECCPOS0 0 -#define NAND_JFFS2_OOB_ECCPOS1 1 -#define NAND_JFFS2_OOB_ECCPOS2 2 -#define NAND_JFFS2_OOB_ECCPOS3 3 -#define NAND_JFFS2_OOB_ECCPOS4 6 -#define NAND_JFFS2_OOB_ECCPOS5 7 -#define NAND_JFFS2_OOB_BADBPOS 5 -#define NAND_JFFS2_OOB_ECCVPOS 4 - -#define NAND_JFFS2_OOB8_FSDAPOS 6 -#define NAND_JFFS2_OOB16_FSDAPOS 8 -#define NAND_JFFS2_OOB8_FSDALEN 2 -#define NAND_JFFS2_OOB16_FSDALEN 8 - -unsigned long nand_probe(unsigned long physadr); +#define NAND_SMALL_BADBLOCK_POS 5 +#define NAND_LARGE_BADBLOCK_POS 0 #endif /* __LINUX_MTD_NAND_H */ diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h new file mode 100644 index 0000000..6e95b3b --- /dev/null +++ b/include/linux/mtd/nand_ecc.h @@ -0,0 +1,30 @@ +/* + * drivers/mtd/nand_ecc.h + * + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * + * $Id: nand_ecc.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ + * + * 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 file is the header for the ECC algorithm. + */ + +#ifndef __MTD_NAND_ECC_H__ +#define __MTD_NAND_ECC_H__ + +struct mtd_info; + +/* + * Calculate 3 byte ECC code for 256 byte block + */ +int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); + +/* + * Detect and correct a 1 bit error for 256 byte block + */ +int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); + +#endif /* __MTD_NAND_ECC_H__ */ diff --git a/include/linux/mtd/nand_ecc_rs.h b/include/linux/mtd/nand_ecc_rs.h new file mode 100644 index 0000000..20e7094 --- /dev/null +++ b/include/linux/mtd/nand_ecc_rs.h @@ -0,0 +1,79 @@ +/******************************************************************************* + + + Filename: new_rs.h + Description: Global definitions for Reed-Solomon encoder/decoder + + + Author: STMicroelectronics + + + + You have a license to reproduce, display, perform, produce derivative works of, + and distribute (in original or modified form) the Program, provided that you + explicitly agree to the following disclaimer: + + THIS PROGRAM IS PROVIDED "AS IT IS" WITHOUT WARRANTY OF ANY KIND, EITHER + EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTY + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK + AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + +********************************************************************************/ + +#ifndef __MTD_NAND_ECC_RS_H__ +#define __MTD_NAND_ECC_RS_H__ +#include + +//typedef unsigned int dtype; +typedef u_short dtype; + + +/* Initialization function */ +void init_rs(void); + +/* These two functions *must* be called in this order (e.g., + * by init_rs()) before any encoding/decoding + */ + +void generate_gf(void); /* Generate Galois Field */ +void gen_poly(void); /* Generate generator polynomial */ + +/* Reed-Solomon encoding + * data[] is the input block, parity symbols are placed in bb[] + * bb[] may lie past the end of the data, e.g., for (255,223): + * encode_rs(&data[0],&data[223]); + */ +char encode_rs(dtype data[], dtype bb[]); + + +/* Reed-Solomon errors decoding + * The received block goes into data[] + * + * The decoder corrects the symbols in place, if possible and returns + * the number of corrected symbols. If the codeword is illegal or + * uncorrectible, the data array is unchanged and -1 is returned + */ +int decode_rs(dtype data[]); + +/** + * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block + * @mtd: MTD block structure + * @dat: raw data + * @ecc_code: buffer for ECC + */ +int nand_calculate_ecc_rs(struct mtd_info *mtd, const u_char *data, u_char *ecc_code); + +/** + * nand_correct_data - [NAND Interface] Detect and correct bit error(s) + * @mtd: MTD block structure + * @dat: raw data read from the chip + * @store_ecc: ECC from the chip + * @calc_ecc: the ECC calculated from raw data + * + * Detect and correct a 1 bit error for 256 byte block + */ +int nand_correct_data_rs(struct mtd_info *mtd, u_char *data, u_char *store_ecc, u_char *calc_ecc); + +#endif diff --git a/include/linux/mtd/nand_ids.h b/include/linux/mtd/nand_ids.h index a3d0363..eac108e 100644 --- a/include/linux/mtd/nand_ids.h +++ b/include/linux/mtd/nand_ids.h @@ -4,7 +4,7 @@ * Copyright (c) 2000 David Woodhouse * Steven J. Hill * - * $Id: nand_ids.h,v 1.1 2000/10/13 16:16:26 mdeans Exp $ + * $Id: nand_ids.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ * * 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,6 +28,10 @@ #ifndef __LINUX_MTD_NAND_IDS_H #define __LINUX_MTD_NAND_IDS_H +#ifndef CFG_NAND_LEGACY +#error This module is for the legacy NAND support +#endif + static struct nand_flash_dev nand_flash_ids[] = { {"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000, 0}, {"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000, 0}, @@ -49,6 +53,7 @@ static struct nand_flash_dev nand_flash_ids[] = { {"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000, 0}, {"Samsung K9F5616Q0C", NAND_MFR_SAMSUNG, 0x45, 25, 0, 2, 0x4000, 1}, {"Samsung K9K1216Q0C", NAND_MFR_SAMSUNG, 0x46, 26, 0, 3, 0x4000, 1}, + {"Samsung K9F1G08U0M", NAND_MFR_SAMSUNG, 0xf1, 27, 0, 2, 0, 0}, {NULL,} }; diff --git a/include/linux/mtd/nand_legacy.h b/include/linux/mtd/nand_legacy.h new file mode 100644 index 0000000..2287345 --- /dev/null +++ b/include/linux/mtd/nand_legacy.h @@ -0,0 +1,203 @@ +/* + * linux/include/linux/mtd/nand.h + * + * Copyright (c) 2000 David Woodhouse + * Steven J. Hill + * Thomas Gleixner + * + * $Id: nand_legacy.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ + * + * 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. + * + * Info: + * Contains standard defines and IDs for NAND flash devices + * + * Changelog: + * 01-31-2000 DMW Created + * 09-18-2000 SJH Moved structure out of the Disk-On-Chip drivers + * so it can be used by other NAND flash device + * drivers. I also changed the copyright since none + * of the original contents of this file are specific + * to DoC devices. David can whack me with a baseball + * bat later if I did something naughty. + * 10-11-2000 SJH Added private NAND flash structure for driver + * 10-24-2000 SJH Added prototype for 'nand_scan' function + * 10-29-2001 TG changed nand_chip structure to support + * hardwarespecific function for accessing control lines + * 02-21-2002 TG added support for different read/write adress and + * ready/busy line access function + * 02-26-2002 TG added chip_delay to nand_chip structure to optimize + * command delay times for different chips + * 04-28-2002 TG OOB config defines moved from nand.c to avoid duplicate + * defines in jffs2/wbuf.c + */ +#ifndef __LINUX_MTD_NAND_LEGACY_H +#define __LINUX_MTD_NAND_LEGACY_H + +#ifndef CFG_NAND_LEGACY +#error This module is for the legacy NAND support +#endif + +/* + * Standard NAND flash commands + */ +#define NAND_CMD_READ0 0 +#define NAND_CMD_READ1 1 +#define NAND_CMD_PAGEPROG 0x10 +#define NAND_CMD_READOOB 0x50 +#define NAND_CMD_ERASE1 0x60 +#define NAND_CMD_STATUS 0x70 +#define NAND_CMD_SEQIN 0x80 +#define NAND_CMD_READID 0x90 +#define NAND_CMD_ERASE2 0xd0 +#define NAND_CMD_RESET 0xff + +/* + * Enumeration for NAND flash chip state + */ +typedef enum { + FL_READY, + FL_READING, + FL_WRITING, + FL_ERASING, + FL_SYNCING +} nand_state_t; + + +/* + * NAND Private Flash Chip Data + * + * Structure overview: + * + * IO_ADDR - address to access the 8 I/O lines of the flash device + * + * hwcontrol - hardwarespecific function for accesing control-lines + * + * dev_ready - hardwarespecific function for accesing device ready/busy line + * + * chip_lock - spinlock used to protect access to this structure + * + * wq - wait queue to sleep on if a NAND operation is in progress + * + * state - give the current state of the NAND device + * + * page_shift - number of address bits in a page (column address bits) + * + * data_buf - data buffer passed to/from MTD user modules + * + * data_cache - data cache for redundant page access and shadow for + * ECC failure + * + * ecc_code_buf - used only for holding calculated or read ECCs for + * a page read or written when ECC is in use + * + * reserved - padding to make structure fall on word boundary if + * when ECC is in use + */ +struct Nand { + char floor, chip; + unsigned long curadr; + unsigned char curmode; + /* Also some erase/write/pipeline info when we get that far */ +}; + +struct nand_chip { + int page_shift; + u_char *data_buf; + u_char *data_cache; + int cache_page; + u_char ecc_code_buf[6]; + u_char reserved[2]; + char ChipID; /* Type of DiskOnChip */ + struct Nand *chips; + int chipshift; + char* chips_name; + unsigned long erasesize; + unsigned long mfr; /* Flash IDs - only one type of flash per device */ + unsigned long id; + char* name; + int numchips; + char page256; + char pageadrlen; + unsigned long IO_ADDR; /* address to access the 8 I/O lines to the flash device */ + unsigned long totlen; + uint oobblock; /* Size of OOB blocks (e.g. 512) */ + uint oobsize; /* Amount of OOB data per block (e.g. 16) */ + uint eccsize; + int bus16; +}; + +/* + * NAND Flash Manufacturer ID Codes + */ +#define NAND_MFR_TOSHIBA 0x98 +#define NAND_MFR_SAMSUNG 0xec + +/* + * NAND Flash Device ID Structure + * + * Structure overview: + * + * name - Complete name of device + * + * manufacture_id - manufacturer ID code of device. + * + * model_id - model ID code of device. + * + * chipshift - total number of address bits for the device which + * is used to calculate address offsets and the total + * number of bytes the device is capable of. + * + * page256 - denotes if flash device has 256 byte pages or not. + * + * pageadrlen - number of bytes minus one needed to hold the + * complete address into the flash array. Keep in + * mind that when a read or write is done to a + * specific address, the address is input serially + * 8 bits at a time. This structure member is used + * by the read/write routines as a loop index for + * shifting the address out 8 bits at a time. + * + * erasesize - size of an erase block in the flash device. + */ +struct nand_flash_dev { + char * name; + int manufacture_id; + int model_id; + int chipshift; + char page256; + char pageadrlen; + unsigned long erasesize; + int bus16; +}; + +/* +* Constants for oob configuration +*/ +#define NAND_NOOB_ECCPOS0 0 +#define NAND_NOOB_ECCPOS1 1 +#define NAND_NOOB_ECCPOS2 2 +#define NAND_NOOB_ECCPOS3 3 +#define NAND_NOOB_ECCPOS4 6 +#define NAND_NOOB_ECCPOS5 7 +#define NAND_NOOB_BADBPOS -1 +#define NAND_NOOB_ECCVPOS -1 + +#define NAND_JFFS2_OOB_ECCPOS0 0 +#define NAND_JFFS2_OOB_ECCPOS1 1 +#define NAND_JFFS2_OOB_ECCPOS2 2 +#define NAND_JFFS2_OOB_ECCPOS3 3 +#define NAND_JFFS2_OOB_ECCPOS4 6 +#define NAND_JFFS2_OOB_ECCPOS5 7 +#define NAND_JFFS2_OOB_BADBPOS 5 +#define NAND_JFFS2_OOB_ECCVPOS 4 + +#define NAND_JFFS2_OOB8_FSDAPOS 6 +#define NAND_JFFS2_OOB16_FSDAPOS 8 +#define NAND_JFFS2_OOB8_FSDALEN 2 +#define NAND_JFFS2_OOB16_FSDALEN 8 + +unsigned long nand_probe(unsigned long physadr); +#endif /* __LINUX_MTD_NAND_LEGACY_H */ diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h index 4381306..d0f4a79 100644 --- a/include/linux/mtd/nftl.h +++ b/include/linux/mtd/nftl.h @@ -2,7 +2,7 @@ /* Defines for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: nftl.h,v 1.10 2000/12/29 00:25:38 dwmw2 Exp $ */ +/* $Id: nftl.h,v 1.1.1.1 2008-12-15 11:39:22 wokes Exp $ */ #ifndef __MTD_NFTL_H__ #define __MTD_NFTL_H__ diff --git a/include/linux_logo.h b/include/linux_logo.h index 9aa712e..a9b4ab3 100644 --- a/include/linux_logo.h +++ b/include/linux_logo.h @@ -1,4 +1,4 @@ -/* $Id: linux_logo.h,v 1.5 1998/07/30 16:30:58 jj Exp $ +/* $Id: linux_logo.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * include/linux/linux_logo.h: This is a linux logo * to be displayed on boot. * diff --git a/include/lxt971a.h b/include/lxt971a.h index 2b5b6d4..b73dbd8 100644 --- a/include/lxt971a.h +++ b/include/lxt971a.h @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_eth.h,v 1.2 2004/02/24 13:25:39 mpietrek Exp $ + * $Id: lxt971a.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @References: [1] NS9750 Hardware Reference, December 2003 * [2] Intel LXT971 Datasheet #249414 Rev. 02 diff --git a/include/malloc.h b/include/malloc.h index 47154b0..97873cb 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -216,7 +216,8 @@ */ - +#ifndef _MALLOC_UBOOT_H_ +#define _MALLOC_UBOOT_H_ /* Preliminaries */ @@ -940,3 +941,5 @@ struct mallinfo mALLINFo(); #ifdef __cplusplus }; /* end of extern "C" */ #endif +#endif /* _MALLOC_UBOOT_H_ */ + diff --git a/include/mmc.h b/include/mmc.h index a271695..6605479 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -23,7 +23,7 @@ #ifndef _MMC_H_ #define _MMC_H_ -#include + int mmc_init(int verbose); int mmc_read(ulong src, uchar *dst, int size); diff --git a/include/nand.h b/include/nand.h new file mode 100644 index 0000000..23493f7 --- /dev/null +++ b/include/nand.h @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2005 + * 2N Telekomunikace, a.s. + * Ladislav Michl + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _NAND_H_ +#define _NAND_H_ + +#include +#include +#include + +typedef struct mtd_info nand_info_t; + +extern int nand_curr_device; +extern nand_info_t nand_info[]; + +static inline int nand_read(nand_info_t *info, ulong ofs, ulong *len, u_char *buf) +{ + return info->read(info, ofs, *len, (size_t *)len, buf); +} + +static inline int nand_write(nand_info_t *info, ulong ofs, ulong *len, u_char *buf) +{ + return info->write(info, ofs, *len, (size_t *)len, buf); +} + +static inline int nand_block_isbad(nand_info_t *info, ulong ofs) +{ + return info->block_isbad(info, ofs); +} + +static inline int nand_erase(nand_info_t *info, ulong off, ulong size) +{ + struct erase_info instr; + + instr.mtd = info; + instr.addr = off; + instr.len = size; + instr.callback = 0; + + return info->erase(info, &instr); +} + + +/***************************************************************************** + * declarations from nand_util.c + ****************************************************************************/ + +struct nand_write_options { + u_char *buffer; /* memory block containing image to write */ + ulong length; /* number of bytes to write */ + ulong offset; /* start address in NAND */ + int quiet; /* don't display progress messages */ + int autoplace; /* if true use auto oob layout */ + int forcejffs2; /* force jffs2 oob layout */ + int forceyaffs; /* force yaffs oob layout */ + int noecc; /* write without ecc */ + int writeoob; /* image contains oob data */ + int pad; /* pad to page size */ + int blockalign; /* 1|2|4 set multiple of eraseblocks + * to align to */ +}; + +typedef struct nand_write_options nand_write_options_t; + +struct nand_read_options { + u_char *buffer; /* memory block in which read image is written*/ + ulong length; /* number of bytes to read */ + ulong offset; /* start address in NAND */ + int quiet; /* don't display progress messages */ + int readoob; /* put oob data in image */ +}; + +typedef struct nand_read_options nand_read_options_t; + +struct nand_erase_options { + ulong length; /* number of bytes to erase */ + ulong offset; /* first address in NAND to erase */ + int quiet; /* don't display progress messages */ + int jffs2; /* if true: format for jffs2 usage + * (write appropriate cleanmarker blocks) */ + int scrub; /* if true, really clean NAND by erasing + * bad blocks (UNSAFE) */ +}; + +typedef struct nand_erase_options nand_erase_options_t; + +int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts); + +int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts); +int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); + +#define NAND_LOCK_STATUS_TIGHT 0x01 +#define NAND_LOCK_STATUS_LOCK 0x02 +#define NAND_LOCK_STATUS_UNLOCK 0x04 + +int nand_lock( nand_info_t *meminfo, int tight ); +int nand_unlock( nand_info_t *meminfo, ulong start, ulong length ); +int nand_get_lock_status(nand_info_t *meminfo, ulong offset); + +#ifdef CFG_NAND_SELECT_DEVICE +void board_nand_select_device(struct nand_chip *nand, int chip); +#endif + +#endif diff --git a/include/net.h b/include/net.h index 461e038..5822d4f 100644 --- a/include/net.h +++ b/include/net.h @@ -336,7 +336,7 @@ extern int NetState; /* Network loop state */ extern int NetRestartWrap; /* Tried all network devices */ #endif -typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP } proto_t; +typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP, RCVR } proto_t; /* from net/net.c */ extern char BootFile[128]; /* Boot File name */ diff --git a/include/ns7520_eth.h b/include/ns7520_eth.h index 5019802..7d32058 100644 --- a/include/ns7520_eth.h +++ b/include/ns7520_eth.h @@ -3,7 +3,7 @@ * Copyright 2003 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id$ + * $Id: ns7520_eth.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @Descr: Defines the NS7520 ethernet registers. * Stick with the old ETH prefix names instead going to the diff --git a/include/ns9750_bbus.h b/include/ns9750_bbus.h index 0918931..227b0ef 100644 --- a/include/ns9750_bbus.h +++ b/include/ns9750_bbus.h @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_bbus.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * $Id: ns9750_bbus.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @Descr: Definitions for BBus usage * @References: [1] NS9750 Hardware Reference Manual/December 2003 Chap. 10 diff --git a/include/ns9750_eth.h b/include/ns9750_eth.h index 978c0bb..464fb6b 100644 --- a/include/ns9750_eth.h +++ b/include/ns9750_eth.h @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_eth.h,v 1.2 2004/02/24 13:25:39 mpietrek Exp $ + * $Id: ns9750_eth.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @References: [1] NS9750 Hardware Reference, December 2003 * [2] Intel LXT971 Datasheet #249414 Rev. 02 diff --git a/include/ns9750_mem.h b/include/ns9750_mem.h index 44c8ddc..55b7783 100644 --- a/include/ns9750_mem.h +++ b/include/ns9750_mem.h @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_mem.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * $Id: ns9750_mem.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @Descr: Definitions for Memory Control Module * @References: [1] NS9750 Hardware Reference Manual/December 2003 Chap. 5 diff --git a/include/ns9750_ser.h b/include/ns9750_ser.h index e6ff3e1..350ed38 100644 --- a/include/ns9750_ser.h +++ b/include/ns9750_ser.h @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_ser.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * $Id: ns9750_ser.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @References: [1] NS9750 Hardware Reference, December 2003 * diff --git a/include/ns9750_sys.h b/include/ns9750_sys.h index c563cad..bc5e0d3 100644 --- a/include/ns9750_sys.h +++ b/include/ns9750_sys.h @@ -3,7 +3,7 @@ * Copyright (C) 2004 by FS Forth-Systeme GmbH. * All rights reserved. * - * $Id: ns9750_sys.h,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * $Id: ns9750_sys.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $ * @Author: Markus Pietrek * @Descr: Definitions for SYS Control Module * @References: [1] NS9750 Hardware Reference Manual/December 2003 Chap. 4 diff --git a/include/part.h b/include/part.h index 318aa3c..77ee0f6 100644 --- a/include/part.h +++ b/include/part.h @@ -81,6 +81,7 @@ typedef struct disk_partition { ulong blksz; /* block size in bytes */ uchar name[32]; /* partition name */ uchar type[32]; /* string type description */ + uchar boot_ind; /* 0x1 - active */ } disk_partition_t; /* disk/part.c */ diff --git a/include/qnap.h b/include/qnap.h new file mode 100644 index 0000000..4824771 --- /dev/null +++ b/include/qnap.h @@ -0,0 +1,11 @@ +#ifndef __QNAP_H__ +#define __QNAP_H__ + +/****************************************************** + * Richard Chen 20081217, + * QNAP for Recovery Button + *****************************************************/ +uint32_t QNAP_recovery_detect(void); +int QNAP_recovery_init(void); +int QNAP_do_recovery(void); +#endif /* __QNAP_H__ */ diff --git a/include/systemace.h b/include/systemace.h index be43d46..b4f7268 100644 --- a/include/systemace.h +++ b/include/systemace.h @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ident "$Id:$" +#ident "$Id: systemace.h,v 1.1.1.1 2008-12-15 11:39:21 wokes Exp $" #ifdef CONFIG_SYSTEMACE diff --git a/lib_arm/armlinux.c b/lib_arm/armlinux.c index ca630b3..143933a 100644 --- a/lib_arm/armlinux.c +++ b/lib_arm/armlinux.c @@ -29,9 +29,12 @@ #ifdef CONFIG_HAS_DATAFLASH #include #endif - +//Patch by QNAP:Fix detect LCM +extern unsigned long mvGppValueGet(unsigned int group, unsigned long mask); +/////////////////////////////////////// /*cmd_boot.c*/ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +extern void mvEgigaStrToMac( char *source , char *dest ); #if defined (CONFIG_SETUP_MEMORY_TAGS) || \ defined (CONFIG_CMDLINE_TAG) || \ @@ -39,7 +42,10 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); defined (CONFIG_SERIAL_TAG) || \ defined (CONFIG_REVISION_TAG) || \ defined (CONFIG_VFD) || \ - defined (CONFIG_LCD) + defined (CONFIG_LCD) || \ + defined (CONFIG_MARVELL_TAG) + + static void setup_start_tag (bd_t *bd); # ifdef CONFIG_SETUP_MEMORY_TAGS @@ -60,6 +66,9 @@ static void setup_end_tag (bd_t *bd); static void setup_videolfb_tag (gd_t *gd); # endif +#if defined (CONFIG_MARVELL_TAG) +static void setup_marvell_tag(void); +#endif static struct tag *params; #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ @@ -88,9 +97,25 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #ifdef CONFIG_CMDLINE_TAG char *commandline = getenv ("bootargs"); +//Patch by QNAP:Fix detect LCM +#if defined(TS419) + if(!mvGppValueGet(1,0x00002000)){ + //LCM + char *ptr = strstr(commandline,"console"); + if(ptr != NULL){ + int i; + for(i=0;i< strlen(commandline);i++,ptr++){ + if(*ptr != ' ' && *ptr != '\n' && *ptr != 0x0) + *ptr = ' '; + else break; + } + } + } +#endif +//////////////////////////////////// #endif - theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); + debug(" theKernel %x\n", theKernel); /* * Check if there is an initrd image @@ -124,7 +149,7 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], checksum = ntohl (hdr->ih_hcrc); hdr->ih_hcrc = 0; - if (crc32 (0, (char *) data, len) != checksum) { + if (crc32 (0, (const char *) data, len) != checksum) { printf ("Bad Header Checksum\n"); SHOW_BOOT_PROGRESS (-11); do_reset (cmdtp, flag, argc, argv); @@ -148,7 +173,7 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], ulong csum = 0; printf (" Verifying Checksum ... "); - csum = crc32 (0, (char *) data, len); + csum = crc32 (0, (const char *) data, len); if (csum != ntohl (hdr->ih_dcrc)) { printf ("Bad Data CRC\n"); SHOW_BOOT_PROGRESS (-12); @@ -231,7 +256,8 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], defined (CONFIG_SERIAL_TAG) || \ defined (CONFIG_REVISION_TAG) || \ defined (CONFIG_LCD) || \ - defined (CONFIG_VFD) + defined (CONFIG_VFD) || \ + defined (CONFIG_MARVELL_TAG) setup_start_tag (bd); #ifdef CONFIG_SERIAL_TAG setup_serial_tag (¶ms); @@ -251,6 +277,12 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #endif #if defined (CONFIG_VFD) || defined (CONFIG_LCD) setup_videolfb_tag ((gd_t *) gd); +#endif +#if defined (CONFIG_MARVELL_TAG) + /* Linux open port doesn't support the Marvell TAG */ + char *env = getenv("mainlineLinux"); + if(!env || ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0))) + setup_marvell_tag (); #endif setup_end_tag (bd); #endif @@ -277,7 +309,8 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], defined (CONFIG_SERIAL_TAG) || \ defined (CONFIG_REVISION_TAG) || \ defined (CONFIG_LCD) || \ - defined (CONFIG_VFD) + defined (CONFIG_VFD) || \ + defined (CONFIG_MARVELL_TAG) static void setup_start_tag (bd_t *bd) { params = (struct tag *) bd->bi_boot_params; @@ -377,6 +410,85 @@ static void setup_videolfb_tag (gd_t *gd) } #endif /* CONFIG_VFD || CONFIG_LCD */ +#if defined(CONFIG_MARVELL_TAG) +static void setup_marvell_tag (void) +{ + char *env; + char temp[20]; + int i; + unsigned int boardId; + + params->hdr.tag = ATAG_MARVELL; + params->hdr.size = tag_size (tag_mv_uboot); + + params->u.mv_uboot.uboot_version = VER_NUM; + + extern unsigned int mvBoardIdGet(void); + + boardId = mvBoardIdGet(); + params->u.mv_uboot.uboot_version |= boardId; + + params->u.mv_uboot.tclk = CFG_TCLK; + params->u.mv_uboot.sysclk = CFG_BUS_CLK; + +#if defined(MV78XX0) + /* Dual CPU Firmware load address */ + env = getenv("fw_image_base"); + if(env) + params->u.mv_uboot.fw_image_base = simple_strtoul(env, NULL, 16); + else + params->u.mv_uboot.fw_image_base = 0; + + /* Dual CPU Firmware size */ + env = getenv("fw_image_size"); + if(env) + params->u.mv_uboot.fw_image_size = simple_strtoul(env, NULL, 16); + else + params->u.mv_uboot.fw_image_size = 0; +#endif + +#if defined(MV_INCLUDE_USB) + extern unsigned int mvCtrlUsbMaxGet(void); + + for (i = 0 ; i < mvCtrlUsbMaxGet(); i++) + { + sprintf( temp, "usb%dMode", i); + env = getenv(temp); + if((!env) || (strcmp(env,"Host") == 0 ) || (strcmp(env,"host") == 0) ) + params->u.mv_uboot.isUsbHost |= (1 << i); + else + params->u.mv_uboot.isUsbHost &= ~(1 << i); + + } +#endif /*#if defined(MV_INCLUDE_USB)*/ +#if defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) + extern unsigned int mvCtrlEthMaxPortGet(void); + extern int mvMacStrToHex(const char* macStr, unsigned char* macHex); + + for (i = 0 ;i < 4;i++) + { + memset(params->u.mv_uboot.macAddr[i], 0, sizeof(params->u.mv_uboot.macAddr[i])); + params->u.mv_uboot.mtu[i] = 0; + } + + for (i = 0 ;i < mvCtrlEthMaxPortGet();i++) + { + sprintf( temp,(i ? "eth%daddr" : "ethaddr"), i); + env = getenv(temp); + if (env) + mvMacStrToHex(env, params->u.mv_uboot.macAddr[i]); + + sprintf( temp,(i ? "eth%dmtu" : "ethmtu"), i); + env = getenv(temp); + if (env) + params->u.mv_uboot.mtu[i] = simple_strtoul(env, NULL, 16); + } +#endif /* (MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) */ + + params = tag_next (params); +} +#endif + #ifdef CONFIG_SERIAL_TAG void setup_serial_tag (struct tag **tmp) { diff --git a/lib_arm/board.c b/lib_arm/board.c index fa3c92e..aaeaed7 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -32,6 +32,12 @@ #include #include +#if defined(CONFIG_MARVELL) + extern int PTexist(void); + extern unsigned long mvFlash_init (void); + extern unsigned int whoAmI(void); + extern int cpuMapInit (void); +#endif #ifdef CONFIG_DRIVER_SMC91111 #include "../drivers/smc91111.h" #endif @@ -65,6 +71,10 @@ extern void cs8900_get_enetaddr (uchar * addr); extern void rtl8019_get_enetaddr (uchar * addr); #endif +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) +extern void recoveryCheck(void); +#endif + /* * Begin and End of memory area for malloc(), and current "brk" */ @@ -75,12 +85,35 @@ static ulong mem_malloc_brk = 0; static void mem_malloc_init (ulong dest_addr) { +#ifndef CONFIG_MARVELL mem_malloc_start = dest_addr; mem_malloc_end = dest_addr + CFG_MALLOC_LEN; mem_malloc_brk = mem_malloc_start; memset ((void *) mem_malloc_start, 0, mem_malloc_end - mem_malloc_start); +#else + unsigned int malloc_len; + char *env; + + env = getenv("MALLOC_len"); + malloc_len = simple_strtoul(env, NULL, 10) << 20; + if(malloc_len == 0) + malloc_len = CFG_MALLOC_LEN; + + mem_malloc_end = CFG_MALLOC_BASE + malloc_len; + printf("Addresses %dM - 0M are saved for the U-Boot usage.\n",mem_malloc_end >> 20); + + mem_malloc_start = CFG_MALLOC_BASE; + mem_malloc_brk = mem_malloc_start; + + printf("Mem malloc Initialization (%dM - %dM):",mem_malloc_end >> 20, + mem_malloc_start >>20 ); + memset ((void *) mem_malloc_start,0,mem_malloc_end - mem_malloc_start); + + printf(" Done\n"); + +#endif } void *sbrk (ptrdiff_t increment) @@ -140,6 +173,8 @@ static int display_banner (void) * gives a simple yet clear indication which part of the * initialization if failing. */ +#ifndef CONFIG_MARVELL + static int display_dram_config (void) { DECLARE_GLOBAL_DATA_PTR; @@ -155,6 +190,8 @@ static int display_dram_config (void) return (0); } +#endif + static void display_flash_config (ulong size) { puts ("Flash: "); @@ -196,14 +233,31 @@ init_fnc_t *init_sequence[] = { serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ display_banner, /* say that we are here */ +#if defined(CONFIG_MARVELL) && defined(MV78XX0) + cpuMapInit, +#endif dram_init, /* configure available RAM banks */ +#ifndef CONFIG_MARVELL display_dram_config, +#endif #if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2) checkboard, #endif NULL, }; +#if defined(CONFIG_MARVELL) && defined(MV78200) +init_fnc_t *init_sequence_slave[] = { + cpu_init, /* basic cpu dependent setup */ + board_init, /* basic board dependent setup */ + env_init, + serial_init, /* serial communications setup */ + console_init_f, /* stage 1 init of console */ + display_banner, /* say that we are here */ + NULL, /* Terminate this list */ +}; +#endif + void start_armboot (void) { DECLARE_GLOBAL_DATA_PTR; @@ -211,15 +265,28 @@ void start_armboot (void) ulong size; init_fnc_t **init_fnc_ptr; char *s; + volatile unsigned int cpu; #if defined(CONFIG_VFD) || defined(CONFIG_LCD) unsigned long addr; #endif - /* Pointer is writable since we allocated a register for it */ +#ifndef CONFIG_MARVELL gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); +#else +#if defined(CONFIG_MARVELL) && defined(MV78200) + /* Marvell Master CPU Boot */ + cpu = whoAmI(); + if(cpu == 0) +#endif + gd = (gd_t*)(_armboot_start - sizeof(gd_t)); +#endif /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); +#if defined(CONFIG_MARVELL) && defined(MV78200) + /* Marvell Master CPU Boot */ + if(cpu == 0){ +#endif memset ((void*)gd, 0, sizeof (gd_t)); gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); @@ -232,9 +299,14 @@ void start_armboot (void) } } +#ifndef CFG_NO_FLASH /* configure available FLASH banks */ size = flash_init (); +#if defined(CONFIG_MARVELL) + size += mvFlash_init (); +#endif display_flash_config (size); +#endif /* CFG_NO_FLASH */ #ifdef CONFIG_VFD # ifndef PAGE_SIZE @@ -317,7 +389,6 @@ void start_armboot (void) /* miscellaneous platform dependent initialisations */ misc_init_r (); #endif - /* enable exceptions */ enable_interrupts (); @@ -345,13 +416,53 @@ void start_armboot (void) #ifdef BOARD_LATE_INIT board_late_init (); #endif +#if (CONFIG_COMMANDS & CFG_CMD_SCSI) + puts ("SCSI: "); + scsi_init (); +#endif #if (CONFIG_COMMANDS & CFG_CMD_NET) #if defined(CONFIG_NET_MULTI) puts ("Net: "); #endif eth_initialize(gd->bd); #endif - /* main_loop() can return to retry autoboot, if so just run it again. */ +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + recoveryCheck(); +#endif +/* Cancle SILENT mode for prompt only */ +#if defined(CONFIG_MARVELL) && defined(CONFIG_SILENT_CONSOLE) + DECLARE_GLOBAL_DATA_PTR; + gd->flags &= ~GD_FLG_SILENT; +#endif +#if defined(CONFIG_MARVELL) && defined(MV78200) + /* Marvell Second CPU Boot */ + } + else + { + /* Master CPU global data */ + gd_t *gd_master; + gd_master = (gd_t*)(_armboot_start - sizeof(gd_t)); + /* Slave CPU global data */ + gd = (gd_t*)(_armboot_start - _1M - sizeof(gd_t)); + memset ((void *) gd, 0, sizeof (gd_t)); + gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); + memset ((void *) gd->bd, 0, sizeof (bd_t)); + + /*copy the Gloabal Data from the Master. */ + memcpy ((void *)gd, (const void *)gd_master, sizeof (gd_t)); + memcpy ((void *)gd->bd, (const void *)gd_master->bd, sizeof (bd_t)); + + for (init_fnc_ptr = init_sequence_slave; *init_fnc_ptr; ++init_fnc_ptr) { + if ((*init_fnc_ptr)() != 0) { + hang (); + } + } + + misc_init_r (); + } +#endif + /* main_loop() can return to retry autoboot, if so just run it again. */ + for (;;) { main_loop (); } diff --git a/net/Makefile b/net/Makefile index 7a70489..98827be 100644 --- a/net/Makefile +++ b/net/Makefile @@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk LIB = libnet.a -OBJS = net.o tftp.o bootp.o rarp.o eth.o nfs.o sntp.o +OBJS = net.o tftp.o bootp.o rarp.o eth.o nfs.o sntp.o rcvr.o all: $(LIB) $(LIB): $(START) $(OBJS) diff --git a/net/bootp.c b/net/bootp.c index 8c56c08..5663097 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -436,6 +436,23 @@ static int DhcpExtended (u8 * e, int message_type, IPaddr_t ServerID, IPaddr_t R } #endif +#ifdef QNAPNAS + /* Richard Chen 20081224, QNAP for Recovery Button */ + { + int vlen = 0; + char *vclass = getenv("bootp_vendor_class"); + + if (vclass) { + vlen = strlen(vclass); + *e++ = 60; + *e++ = vlen; + memcpy(e, vclass, vlen); + e += vlen; + debug ("bootp option attached: 60: %s\n", vclass); + } + } +#endif /* QNAPNAS */ + #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX) if ((x = dhcp_vendorex_prep (e))) return x - start; @@ -853,7 +870,10 @@ static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) { Bootp_t *bp = (Bootp_t *)pkt; - +#ifdef QNAPNAS + /* Richard Chen 20081225, Bootfile Environment */ + char *prefix = NULL; +#endif /* QNAPNAS */ debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n", src, dest, len, dhcp_state); @@ -877,7 +897,12 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) CFG_BOOTFILE_PREFIX, strlen(CFG_BOOTFILE_PREFIX)) == 0 ) { #endif /* CFG_BOOTFILE_PREFIX */ - +#ifdef QNAPNAS + /* Richard Chen 20081225, QNAP for Recovery Button */ + prefix = getenv("bootp_vendor_class"); + printf ("Bootfile Prefix: %s\n", prefix); + if( prefix && !strncmp(bp->bp_file, prefix, strlen(prefix))) { +#endif /* QNAPNAS */ debug ("TRANSITIONING TO REQUESTING STATE\n"); dhcp_state = REQUESTING; @@ -888,6 +913,9 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout); DhcpSendRequestPkt(bp); +#ifdef QNAPNAS + } +#endif /* QNAPNAS */ #ifdef CFG_BOOTFILE_PREFIX } #endif /* CFG_BOOTFILE_PREFIX */ diff --git a/net/eth.c b/net/eth.c index 9341e20..a58aba3 100644 --- a/net/eth.c +++ b/net/eth.c @@ -26,6 +26,9 @@ #include #include +#ifdef CONFIG_MARVELL +#define BOARD_ETH_END_PORT_NUM 2 +#endif #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) #ifdef CFG_GT_6426x @@ -53,6 +56,7 @@ extern int rtl8169_initialize(bd_t*); extern int scc_initialize(bd_t*); extern int skge_initialize(bd_t*); extern int tsec_initialize(bd_t*, int, char *); +extern int mv_eth_initialize(bd_t *); static struct eth_device *eth_devices, *eth_current; @@ -131,12 +135,25 @@ int eth_register(struct eth_device* dev) int eth_initialize(bd_t *bis) { char enetvar[32], env_enetaddr[6]; - int i, eth_number = 0; + int i; char *tmp, *end; +#ifdef CONFIG_MARVELL + int eth_number = 0; +#else + int eth_number = 0; +#endif + eth_devices = NULL; eth_current = NULL; +#ifdef CONFIG_MARVELL +#if defined(MV_INCLUDE_GIG_ETH) || defined(MV_INCLUDE_UNM_ETH) + /* move to the begining so in case we have a PCI NIC it will + read the env mac addresses correctlly. */ + mv_eth_initialize(bis); +#endif +#endif #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) miiphy_init(); #endif @@ -239,7 +256,11 @@ int eth_initialize(bd_t *bis) char *ethprime = getenv ("ethprime"); do { +#ifdef CONFIG_MARVELL + if (eth_number != 0) +#else if (eth_number) +#endif puts (", "); printf("%s", dev->name); diff --git a/net/net.c b/net/net.c index 37c5fb6..77e32fb 100644 --- a/net/net.c +++ b/net/net.c @@ -90,6 +90,10 @@ #include "sntp.h" #endif +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) +#include "rcvr.h" +#endif + #if (CONFIG_COMMANDS & CFG_CMD_NET) #define ARP_TIMEOUT 5 /* Seconds before trying ARP again */ @@ -378,6 +382,10 @@ restart: NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */ NetOurNativeVLAN = getenv_VLAN("nvlan"); break; +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + case RCVR: + break; +#endif default: break; } @@ -447,6 +455,11 @@ restart: case SNTP: SntpStart(); break; +#endif +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + case RCVR: + RecoverRequest(); + break; #endif default: break; @@ -474,6 +487,7 @@ restart: * someone sets `NetState' to a state that terminates. */ for (;;) { + int timerVal; WATCHDOG_RESET(); #ifdef CONFIG_SHOW_ACTIVITY { @@ -502,7 +516,8 @@ restart: * Check for a timeout, and run the timeout handler * if we have one. */ - if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) { + timerVal = get_timer(0); + if (timeHandler && ((timerVal - timeStart) > timeDelta)) { thand_f *x; #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) @@ -1248,6 +1263,8 @@ NetReceive(volatile uchar * inpkt, int len) */ #ifdef ET_DEBUG puts ("Got ARP\n"); + printf (" Addr 0x%x\n", ip); + #endif arp = (ARP_t *)ip; if (len < ARP_HDR_SIZE) { @@ -1536,6 +1553,9 @@ static int net_check_prereq (proto_t protocol) case RARP: case BOOTP: case CDP: +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + case RCVR: +#endif if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) { #ifdef CONFIG_NET_MULTI extern int eth_get_dev_index (void); diff --git a/net/rcvr.c b/net/rcvr.c new file mode 100644 index 0000000..5da75df --- /dev/null +++ b/net/rcvr.c @@ -0,0 +1,469 @@ +/* + * This file impliments the TFTP server with the Distress Beacon UDP packet that will be send + * as a notification for a systom recovery process. + */ + +#include "rcvr.h" + +/* #define DEBUG_RCVR */ + +#ifdef DEBUG_RCVR +#define debug_rcvr(fmt,args...) printf (fmt ,##args) +#else +#define debug_rcvr(fmt,args...) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + +/* Globals */ +rcvr_state_t rcvr_state = RCVR_INIT; +ulong myTID = 0; /* Transfer ID used my me as a TFPT server */ +ulong peerTID = 0; /* Transfer ID received frm the peer */ +ulong packetNum = 0; /* Packet number expected */ +uchar * imagePtr = NULL; /* Pointer to the location to copy the uImage file */ + +static void +BeaconSend (void) +{ + DistressBeaconPacketStruct * bconpkt; + char *s; + + bconpkt = (DistressBeaconPacketStruct*) (NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE); + + /* clear the whole packet to zeros */ + memset(bconpkt, 0x0, sizeof(bconpkt)); + + /* Fill the packet with the information needed */ + bconpkt->Header.PacketType = RECOVERY_MODE; + bconpkt->Header.Version = BEACON_VERSION; + bconpkt->Payload.State = (((RECOVERY_STATE_FIRST & 0xFF) << 8) | ((RECOVERY_STATE_FIRST & 0xFF00) >> 8)); + NetCopyIP(&bconpkt->Payload.IPAddr.IPAddress, &NetOurIP); + memcpy (bconpkt->Payload.LinkAddr.LinkLevelAddr, NetOurEther, LL_ADDR_LEN); + + if ((s = getenv("deviceName")) != NULL) + { + ulong strln = strlen(s); + if (strln >= MAX_NAME_LEN) + strncpy(bconpkt->Payload.Name, s, MAX_NAME_LEN-1); /* keep space for null termination */ + else + strcpy(bconpkt->Payload.Name, s); + } + else + { + printf("Warning: Missing environment variable \"deviceName\". Assuming default!\n"); + strcpy(bconpkt->Payload.Name, "Unknown S/N"); + } + + if ((s = getenv("modelNumber")) != NULL) + { + ulong strln = strlen(s); + if (strln >= MAX_MODEL_NUMBER_LEN) + strncpy(bconpkt->Payload.ModelNumber, s, MAX_MODEL_NUMBER_LEN-1); /* keep space for null termination */ + else + strcpy(bconpkt->Payload.ModelNumber, s); + } + else + { + printf("Warning: Missing environment variable \"modelNumber\". Assuming default!\n"); + strcpy(bconpkt->Payload.ModelNumber, "Unknown Model # of NAS system"); + } + + printf("Broadcasting Distress Beacon Packet.\n"); + debug_rcvr("Sending Beacon packet with IP = 0x%08x and MAC = %02x:%02x:%02x:%02x:%02x:%02x\n", bconpkt->Payload.IPAddr.IPAddress, + bconpkt->Payload.LinkAddr.LinkLevelAddr[0], bconpkt->Payload.LinkAddr.LinkLevelAddr[1], bconpkt->Payload.LinkAddr.LinkLevelAddr[2], + bconpkt->Payload.LinkAddr.LinkLevelAddr[3], bconpkt->Payload.LinkAddr.LinkLevelAddr[4], bconpkt->Payload.LinkAddr.LinkLevelAddr[5]); + + NetSendUDPPacket(NetServerEther, 0, BEACON_UDP_PORT, BEACON_UDP_PORT, sizeof(DistressBeaconPacketStruct)); +} + + +/* + * Send an Error Reply. + */ +static void +SendTftpError(ushort error, unsigned src, unsigned dst, uchar * errStr) +{ + ushort * fld; + uchar *s; + + /* write first the opcode */ + fld = (ushort*) (NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE); + *fld = (((TFTP_OPCODE_ERR & 0xFF) << 8) | ((TFTP_OPCODE_ERR & 0xFF00) >> 8)); + + /* Write the error code */ + fld++; + *fld = (((error & 0xFF) << 8) | ((error & 0xFF00) >> 8)); + + /* Add a string to explain */ + s = (uchar*) ++fld; + sprintf(s, "%s", errStr); + + /* Transmit the error message */ + debug_rcvr("Sendin ERR packet (PeerTID = %d, MyTID = %d).\n", src, dst); + NetSendUDPPacket(NetServerEther, NetServerIP, src, dst, (strlen(s) + 5)); +} + +/* + * Send an Error Reply. + */ +static void +SendTftpAck(ushort block) +{ + ushort * fld; + + /* write first the opcode */ + fld = (ushort*) (NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE); + *fld = (((TFTP_OPCODE_ACK & 0xFF) << 8) | ((TFTP_OPCODE_ACK & 0xFF00) >> 8)); + + /* Write the error code */ + fld++; + *fld = (((block & 0xFF) << 8) | ((block & 0xFF00) >> 8)); + + /* Transmit the error message */ + debug_rcvr("Sendin ACK packet (PeerTID = %d, MyTID = %d, Block = %d).\n", peerTID, myTID, block); + NetSendUDPPacket(NetServerEther, NetServerIP, peerTID, myTID, 4); +} + + +/* + * Timeout on Distress Beacon Recovery request. + */ +static void +RecoverTimeout(void) +{ + switch (rcvr_state) + { + /* 5 seconds between Distress Beacon */ + case RCVR_WAIT_4_CNCT: + NetSetTimeout (RCVR_BEACON_TIMEOUT * CFG_HZ, RecoverTimeout); + BeaconSend(); + break; + + /* Timeout between data packets or between uImage and RamDisk files */ + case RCVR_IMAGE_DWNLD: + debug_rcvr("Timeout, Failing the recovery process!\n"); + SendTftpError(TFTP_ERROR_UNDEFINED, peerTID, myTID, "Data Packet TimeOut!"); + NetSetTimeout(0, (thand_f *)0); + NetState = NETLOOP_FAIL; + rcvr_state = RCVR_INIT; + break; + + /* Client finished successfully no retransmit requested */ + case RCVR_FINISHED: + debug_rcvr("Finished successfully.\n"); + NetSetTimeout(0, (thand_f *)0); + NetState = NETLOOP_SUCCESS; + rcvr_state = RCVR_INIT; + break; + + default: + debug_rcvr("Invalid state received in the Timeout routine~\n"); + } +} + + +/* + * Handle Recovery received packets. + */ +static void +RecoveryHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + ushort opcode; + ushort * fld; + uchar * tftpfile = NULL; + uchar * tftpmode = NULL; + ulong rxPacketNumber; + unsigned dlen; + + fld = (ushort*) pkt; + opcode = (((*fld & 0xFF) << 8) | ((*fld & 0xFF00) >> 8)); + + switch (rcvr_state) + { + case RCVR_INIT: + + break; + + case RCVR_WAIT_4_CNCT: + switch (opcode) + { + case TFTP_OPCODE_RRQ: + /* check that the destination port is correct */ + if (dest != TFTP_SERVER_PORT) + return; + + /* Copy the server IP and MAC address */ + memcpy (NetServerEther, (uchar*) &NetRxPkt[6], 6); + NetServerIP = NetRxPkt[26]; + NetServerIP |= (NetRxPkt[27] << 8); + NetServerIP |= (NetRxPkt[28] << 16); + NetServerIP |= (NetRxPkt[29] << 24); + debug_rcvr("New Peer Info (MAC %02x:%02x:%02x:%02x:%02x:%02x, IP %08x\n", NetServerEther[0], NetServerEther[1], + NetServerEther[2], NetServerEther[3], NetServerEther[4], NetServerEther[5], NetServerIP); + + printf("Unsupported TFTP GET request received from %d.%d.%d.%d (MAC %02x:%02x:%02x:%02x:%02x:%02x)\n", + (NetServerIP & 0xFF), ((NetServerIP >> 8) & 0xFF), ((NetServerIP >> 16) & 0xFF), ((NetServerIP >> 24) & 0xFF), + NetServerEther[0], NetServerEther[1], NetServerEther[2], NetServerEther[3], NetServerEther[4], + NetServerEther[5]); + + SendTftpError(TFTP_ERROR_ILLEGAL_OPERATION, src, TFTP_SERVER_PORT, "Request Not Supported"); + break; + + case TFTP_OPCODE_WRQ: + + /* check that the destination port is correct */ + if (dest != TFTP_SERVER_PORT) + return; + + /* Copy the server IP and MAC address */ + memcpy (NetServerEther, (uchar*) &NetRxPkt[6], 6); + NetServerIP = NetRxPkt[26]; + NetServerIP |= (NetRxPkt[27] << 8); + NetServerIP |= (NetRxPkt[28] << 16); + NetServerIP |= (NetRxPkt[29] << 24); + debug_rcvr("New Peer Info (MAC %02x:%02x:%02x:%02x:%02x:%02x, IP %08x\n", NetServerEther[0], NetServerEther[1], + NetServerEther[2], NetServerEther[3], NetServerEther[4], NetServerEther[5], NetServerIP); + + printf("New TFTP PUT request received from %d.%d.%d.%d (MAC %02x:%02x:%02x:%02x:%02x:%02x)\n", + (NetServerIP & 0xFF), ((NetServerIP >> 8) & 0xFF), ((NetServerIP >> 16) & 0xFF), ((NetServerIP >> 24) & 0xFF), + NetServerEther[0], NetServerEther[1], NetServerEther[2], NetServerEther[3], NetServerEther[4], + NetServerEther[5]); + + tftpfile = pkt +2; + tftpmode = pkt + 3 + strlen (tftpfile); + debug_rcvr("TFTP WRQ received (Dest = %d, Src = %d, Len = %d, Opcode = %d, File = %s, Mode = %s, PeerTID = %d\n", + dest, src, len, opcode, tftpfile, tftpmode, src); + + /* save the peer port # as the peerTID */ + peerTID = src; + packetNum = 1; /* reset the packet numbering */ + debug_rcvr("Saving the PeerTID to used throughout the session (PeerTID = %d).\n", peerTID); + + /* received the request successfully */ + rcvr_state = RCVR_IMAGE_DWNLD; + NetSetTimeout (RCVR_DATA_TIMEOUT * CFG_HZ, RecoverTimeout); + + /* Send the ACK */ + SendTftpAck(0); + break; + + case TFTP_OPCODE_DATA: + case TFTP_OPCODE_ACK: + case TFTP_OPCODE_ERR: + debug_rcvr("ERROR: Invalid TFTP request while in WAIT_4_CNCT (opcode = %d)!\n",opcode); + break; + + default: + debug_rcvr("ERROR: Invalid TFTP opcode!\n"); + } + break; + + case RCVR_IMAGE_DWNLD: + switch (opcode) + { + case TFTP_OPCODE_RRQ: + debug_rcvr("TFTP GET requestes are not supported. Sendin Error!\n"); + break; + + case TFTP_OPCODE_WRQ: + + /* check if the WRQ ACK was not received so we are having it again */ + if (packetNum == 1) /* we did not yeat receive any DATA packet */ + { + /* check that the destination port is correct */ + if (dest != TFTP_SERVER_PORT) + return; + + /* Copy the server IP and MAC address */ + memcpy (NetServerEther, (uchar*) &NetRxPkt[6], 6); + NetServerIP = NetRxPkt[26]; + NetServerIP |= (NetRxPkt[27] << 8); + NetServerIP |= (NetRxPkt[28] << 16); + NetServerIP |= (NetRxPkt[29] << 24); + debug_rcvr("New Peer Info (MAC %02x:%02x:%02x:%02x:%02x:%02x, IP %08x\n", NetServerEther[0], NetServerEther[1], + NetServerEther[2], NetServerEther[3], NetServerEther[4], NetServerEther[5], NetServerIP); + + printf("TFTP PUT request received again from %d.%d.%d.%d (MAC %02x:%02x:%02x:%02x:%02x:%02x)\n", + (NetServerIP & 0xFF), ((NetServerIP >> 8) & 0xFF), ((NetServerIP >> 16) & 0xFF), ((NetServerIP >> 24) & 0xFF), + NetServerEther[0], NetServerEther[1], NetServerEther[2], NetServerEther[3], NetServerEther[4], + NetServerEther[5]); + + tftpfile = pkt +2; + tftpmode = pkt + 3 + strlen (tftpfile); + debug_rcvr("TFTP WRQ received again (Dest = %d, Src = %d, Len = %d, Opcode = %d, File = %s, Mode = %s, PeerTID = %d\n", + dest, src, len, opcode, tftpfile, tftpmode, src); + + /* save the peer port # as the peerTID */ + peerTID = src; + debug_rcvr("Saving the PeerTID to used throughout the session (PeerTID = %d).\n", peerTID); + + /* Send the ACK */ + SendTftpAck(0); + } + else + debug_rcvr("ERROR: Invalid WRQ request while data transfer!\n"); + + break; + + case TFTP_OPCODE_DATA: + + /* check that the destination port is correct */ + if (dest != myTID) + { + debug_rcvr("ERROR: TFTP data packet not to my TID port (port = %d)!\n", dest); + return; + } + + fld = (ushort*) (pkt+2); + rxPacketNumber = (((*fld & 0xFF) << 8) | ((*fld & 0xFF00) >> 8)); + if (rxPacketNumber == packetNum) + { + /* check the length of data */ + if (len == (TFTP_MAX_DATA_LEN + 4)) + { + /* print a progress message */ + if ((packetNum % 500) == 0) + printf("%dKB\r", (packetNum / 2)); + + dlen = TFTP_MAX_DATA_LEN; + NetSetTimeout (RCVR_DATA_TIMEOUT * CFG_HZ, RecoverTimeout); + } + else if (len < (TFTP_MAX_DATA_LEN + 4)) + { + dlen = (len - 4); + rcvr_state = RCVR_FINISHED; + NetSetTimeout (RCVR_FINISH_TIMEOUT * CFG_HZ, RecoverTimeout); + //debug_rcvr("Received the last packet in the uImage file, changing state to WAIT_4_RAMDISK.\n"); + printf("Recovery Image received (%d bytes).\n",((packetNum * TFTP_MAX_DATA_LEN) + dlen)); + } + else /* Fatal Error */ + { + debug_rcvr("ERROR: TFTP data packet larger that 512!\n"); + NetSetTimeout(0, (thand_f *)0); + NetState = NETLOOP_FAIL; + rcvr_state = RCVR_INIT; + return; + } + + debug_rcvr("Received uImage Packet #%d (length = %d). Sending Ack.\n", rxPacketNumber, dlen); + + /* copy the data to the RAM */ + memcpy(imagePtr, (pkt+4), dlen); + imagePtr += dlen; + NetBootFileXferSize += dlen; + + /* Send the Ack for the new packet */ + SendTftpAck(packetNum); + + /* increment the packet number */ + ++packetNum; + } + else if (rxPacketNumber == (packetNum-1)) + { + debug_rcvr("Received Packet #%d AGAIN. Sending Ack.\n"); + + /* Seems that my last ACK was not delivered SO Send the Ack again */ + SendTftpAck(rxPacketNumber); + } + else + debug_rcvr("Invalid Packet #%d received (expecting %d)!\n", rxPacketNumber, packetNum); + + break; + + case TFTP_OPCODE_ACK: + case TFTP_OPCODE_ERR: + debug_rcvr("ERROR: Invalid TFTP request while in IMAGE_DWNLD (opcode = %d)!\n",opcode); + break; + + default: + debug_rcvr("ERROR: Invalid TFTP opcode!\n"); + } + break; + + case RCVR_FINISHED: + switch (opcode) + { + case TFTP_OPCODE_DATA: + /* check that the destination port is correct */ + if (dest != myTID) + { + debug_rcvr("ERROR: TFTP data packet not to my TID port (port = %d)!\n", dest); + return; + } + + fld = (ushort*) (pkt+2); + rxPacketNumber = (((*fld & 0xFF) << 8) | ((*fld & 0xFF00) >> 8)); + + /* check if the last ACK was not received; so retransmit it */ + if (rxPacketNumber == (packetNum-1)) + { + debug_rcvr("Received Packet #%d AGAIN. Sending Ack.\n"); + + /* Seems that my last ACK was not delivered SO Send the Ack again */ + SendTftpAck(rxPacketNumber); + } + else + debug_rcvr("Invalid Packet #%d deceived (expecting %d)!\n", rxPacketNumber, packetNum); + + break; + + case TFTP_OPCODE_RRQ: + case TFTP_OPCODE_WRQ: + case TFTP_OPCODE_ACK: + case TFTP_OPCODE_ERR: + debug_rcvr("ERROR: Invalid TFTP request while in RCVR_FINISHED (opcode = %d)!\n",opcode); + break; + + default: + debug_rcvr("ERROR: Invalid TFTP opcode!\n"); + } + break; + + default: + debug_rcvr("ERROR: Invalid Recovery status!\n"); + } + + return; +} + + +/* + * Start a recovery process - Using Distress Beacon and TFTP server + */ +void RecoverRequest(void) +{ + uchar * s; + + /* get the uImage locations */ + if ((s = getenv("loadaddr")) != NULL) + { + imagePtr = (uchar *)simple_strtoul(s, NULL, 16); + printf("uImage load address 0x%08x\n", imagePtr); + } + else + { + printf("ERROR: Missing environment variable for \"loadaddr\"!\n"); + NetState = NETLOOP_FAIL; + return; + } + + + /* Caculate the TID to be used */ + myTID = ((NetOurEther[4] << 8) | (NetOurEther[5])); + peerTID = 0; /* reset the peer TID */ + + /* Change the state for waiting to connect */ + rcvr_state = RCVR_WAIT_4_CNCT; + + /* Set the handler to the TFTP server */ + NetSetHandler(RecoveryHandler); + + /* Set the Timeout */ + NetSetTimeout(RCVR_BEACON_TIMEOUT * CFG_HZ, RecoverTimeout); + + /* Transmit the First Distress Beacon packet */ + BeaconSend(); +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_RCVR) */ + diff --git a/net/rcvr.h b/net/rcvr.h new file mode 100644 index 0000000..5fa8855 --- /dev/null +++ b/net/rcvr.h @@ -0,0 +1,125 @@ +/* + * This file provides the typedefs and constants for the TFTP server and Distress + * Beacn implimentation + */ + +#ifndef __RCVR_H__ +#define __RCVR_H__ + +#include +#include +#include + +#if (CONFIG_COMMANDS & CFG_CMD_RCVR) + +/********************************************************************************************************************/ +/* DISTRESS BEACON DEFINITIONS */ +/********************************************************************************************************************/ + +#define BEACON_UDP_PORT 3583 /* Destination UDP Port to broadcast the distress beacon to */ +#define RECOVERY_MODE 0xDE /* packet_type values/signatures */ +#define RECOVERY_STATE_FIRST 0x00001 /* First stage for loading the initrd */ +#define RECOVERY_STATE_SECOND 0x00002 /* Second stage for loading the firmware.bin - not used in UBoot */ +#define BEACON_VERSION 1 /* Current version of the Beacon Packet */ +#define LL_ADDR_LEN 6 /* Length of a link level address (in bytes) */ +#define IP_ADDR_LEN 4 /* Length of IP address in bytes */ +#define MAX_NAME_LEN 16 /* Length of name (NetBIOS) */ +#define MAX_MODEL_NUMBER_LEN 50 /* Length of model Number */ + +#pragma pack (1) + +/* LinkLevelAddrStruct - Defines the structure of a link level address */ +typedef struct +{ + uchar LinkLevelAddr[LL_ADDR_LEN]; +} LinkLevelAddrStruct; + +/* IPAddrStruct - Defines the structure of an IP address */ +typedef struct +{ + ulong IPAddress; +} IPAddressStruct; + +/* PacketHeaderStruct - Defines the structure of the beacon packet header + * - 16-bit value that specifies teh type of packet, (RECOVERY_MODE) + * - 8-bit version of packet for future extension + */ +typedef struct +{ + uchar PacketType; + uchar Version; +}PacketHeaderStruct; + +/* DistressBeaconPayloadStruct - Defines the structure of the beacon packet payload + * - 4 bytes IP address of the NAS in distress + * - 6 bytes LL address of the NAS in distress + * - 16 bytes string with the name of the NAS in distress + * - 50 bytes string with the NAS Model number + */ +typedef struct +{ + ushort State; + IPAddressStruct IPAddr; + LinkLevelAddrStruct LinkAddr; + uchar Name[MAX_NAME_LEN]; + uchar ModelNumber[MAX_MODEL_NUMBER_LEN]; +}DistressBeaconPayloadStruct; + +/* DistressBeaconPacketStruct - The structure with both the header and payload */ +typedef struct +{ + PacketHeaderStruct Header; + DistressBeaconPayloadStruct Payload; +}DistressBeaconPacketStruct; + +#pragma pack () + +/********************************************************************************************************************/ +/* RECOVERY DEFINITIONS */ +/********************************************************************************************************************/ + +#define RCVR_BEACON_TIMEOUT 5 /* timeout in seconds between Distress Beacon */ +#define RCVR_DATA_TIMEOUT 6 /* timeout in seconds to receive a data packet */ +#define RCVR_FINISH_TIMEOUT 2 /* timeout in seconds to verify that the client received the last ACK */ + +/* Recovery States */ +typedef enum +{ + RCVR_INIT, + RCVR_WAIT_4_CNCT, + RCVR_IMAGE_DWNLD, + RCVR_FINISHED +}rcvr_state_t; + +/* Function Prototypes */ +void RecoverRequest(void); + +/********************************************************************************************************************/ +/* TFTP SERVER DEFINITIONS */ +/********************************************************************************************************************/ + +/* TFTP ports */ +#define TFTP_SERVER_PORT 69 + +/* Length of the opcode field */ +#define TFTP_OPCODE_LEN 2 + +/* All possible TFTP opcodes */ +#define TFTP_OPCODE_RRQ 0x0001 +#define TFTP_OPCODE_WRQ 0x0002 +#define TFTP_OPCODE_DATA 0x0003 +#define TFTP_OPCODE_ACK 0x0004 +#define TFTP_OPCODE_ERR 0x0005 + +/* TFTP error codes supported */ +#define TFTP_ERROR_UNDEFINED 0 +#define TFTP_ERROR_ILLEGAL_OPERATION 4 + +/* MAX size of TFTP DATA */ +#define TFTP_MAX_DATA_LEN 512 + + + +#endif /* #if (CONFIG_COMMANDS & CFG_CMD_RCVR) */ + +#endif /* __RCVR_H__ */ diff --git a/rules.mk b/rules.mk new file mode 100644 index 0000000..a77451b --- /dev/null +++ b/rules.mk @@ -0,0 +1,35 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 +# + +######################################################################### + +_depend: $(obj).depend + +$(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(SRCS) + @rm -f $@ + @for f in $(SRCS); do \ + g=`basename $$f | sed -e 's/\(.*\)\.\w/\1.o/'`; \ + $(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; \ + done + +######################################################################### diff --git a/tools/Makefile b/tools/Makefile index d3dcc7d..7884562 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -21,9 +21,9 @@ # MA 02111-1307 USA # -BINS = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) +BINS = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) doimage$(SFX) -OBJS = environment.o img2srec.o mkimage.o crc32.o envcrc.o gen_eth_addr.o bmp_logo.o +OBJS = environment.o img2srec.o mkimage.o crc32.o envcrc.o gen_eth_addr.o bmp_logo.o doimage.o ifeq ($(ARCH),mips) BINS += inca-swap-bytes$(SFX) @@ -141,6 +141,10 @@ bmp_logo$(SFX): bmp_logo.o $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ +doimage$(SFX): doimage.o + $(CC) -DMV_CPU_LE $(HOST_LDFLAGS) -o $@ $^ + $(STRIP) $@ + inca-swap-bytes$(SFX): inca-swap-bytes.o $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ @@ -198,6 +202,9 @@ crc32.c: $(LOGO_H): bmp_logo $(LOGO_BMP) ./bmp_logo $(LOGO_BMP) >$@ +doimage.o: doimage.c + $(CC) -g -DMV_CPU_LE -c $< + ######################################################################### .depend: Makefile $(OBJS:.o=.c) @@ -206,3 +213,11 @@ $(LOGO_H): bmp_logo $(LOGO_BMP) sinclude .depend ######################################################################### + + +clean: + find . -type f \ + \( -name 'core' -o -name '*.bak' -o -name '*~' \ + -o -name '*.o' -o -name '*.a' \) -print \ + | xargs rm -f + rm -f $(ELF) $(SREC) $(BIN) $(DIS) bootstrap.map diff --git a/tools/Makefile_doimage b/tools/Makefile_doimage new file mode 100644 index 0000000..9889afa --- /dev/null +++ b/tools/Makefile_doimage @@ -0,0 +1,41 @@ +STRIP = strip + +# +# Include the make variables (CC, etc...) +# +LD = ld +CC = gcc +OBJCOPY = objcopy +OBJDUMP = objdump + + +CFLAGS = -DMV_CPU_LE +LDFLAGS = + +BIN = doimage + +all: $(BIN) +doimage: doimage.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + $(STRIP) $@ + +doimage.o: doimage.c + $(CC) -g $(CFLAGS) -c $< + + +clean: + find . -type f \ + \( -name 'core' -o -name '*.bak' -o -name '*~' \ + -o -name '*.o' -o -name '*.a' \) -print \ + | xargs rm -f + rm -f $(ELF) $(SREC) $(BIN) $(DIS) bootstrap.map + + + + + + + + + + diff --git a/tools/bootstrap_def.h b/tools/bootstrap_def.h new file mode 100644 index 0000000..ad0ddb8 --- /dev/null +++ b/tools/bootstrap_def.h @@ -0,0 +1,122 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _INC_BOOTSTRAP__DEF_H +#define _INC_BOOTSTRAP__DEF_H +#include "bootstrap_os.h" + +#ifndef MV_ASMLANGUAGE + +typedef struct BHR_t +{ +// type name byte order + MV_U8 blockID; //0 + MV_U8 nandEccMode; //1 + MV_U16 nandPageSize; //2-3 + MV_U32 blockSize; //4-7 + MV_U32 rsvd1; //8-11 + MV_U32 sourceAddr; //12-15 + MV_U32 destinationAddr; //16-19 + MV_U32 executionAddr; //20-23 + MV_U8 sataPioMode; //24 + MV_U8 rsvd3; //25 + MV_U16 ddrInitDelay; //26-27 + MV_U16 rsvd2; //28-29 + MV_U8 ext; //30 + MV_U8 checkSum; //31 +} BHR_t, * pBHR_t; + + +typedef struct ExtBHR_t +{ +// type name byte order + MV_U32 dramRegsOffs; //0-3 + MV_U32 rsrvd1; //4-7 + MV_U32 rsrvd2; //8-11 + MV_U32 rsrvd3; //12-15 + MV_U32 rsrvd4; //16-19 + MV_U32 rsrvd5; //20-23 + MV_U32 rsrvd6; //24-27 + MV_U16 rsrvd7; //28-29 + MV_U8 rsrvd8; //30 + MV_U8 checkSum; //31 +}ExtBHR_t, *pExtBHR_t; + +#define BOOTROM_SIZE (12 * 1024) +#define HEADER_SIZE 512 +#define BHR_HDR_SIZE 0x20 +#define EXT_HEADER_SIZE (HEADER_SIZE - BHR_HDR_SIZE) + +/* Boot Type - block ID */ +#define IBR_HDR_I2C_ID 0x4D +#define IBR_HDR_SPI_ID 0x5A +#define IBR_HDR_NAND_ID 0x8B +#define IBR_HDR_SATA_ID 0x78 +#define IBR_HDR_PEX_ID 0x9C +#define IBR_HDR_UART_ID 0x69 +#define IBR_DEF_ATTRIB 0x00 + +#endif /* MV_ASMLANGUAGE */ +#endif /* _INC_BOOTSTRAP_H */ + diff --git a/tools/bootstrap_os.h b/tools/bootstrap_os.h new file mode 100644 index 0000000..eff8ac3 --- /dev/null +++ b/tools/bootstrap_os.h @@ -0,0 +1,473 @@ +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +This software file (the "File") is owned and distributed by Marvell +International Ltd. and/or its affiliates ("Marvell") under the following +alternative licensing terms. Once you have made an election to distribute the +File under one of the following license alternatives, please (i) delete this +introductory statement regarding license alternatives, (ii) delete the two +license alternatives that you have not elected to use and (iii) preserve the +Marvell copyright notice above. + +******************************************************************************** +Marvell Commercial License Option + +If you received this File from Marvell and you have entered into a commercial +license agreement (a "Commercial License") with Marvell, the File is licensed +to you under the terms of the applicable Commercial License. + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. +******************************************************************************** +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ +#ifndef _INC_BOOTSTRAP_OS_H +#define _INC_BOOTSTRAP_OS_H + +/* BE/ LE swap for Asm */ +#if defined(MV_CPU_LE) + +#define htoll(x) x +#define HTOLL(sr,tr) + +#elif defined(MV_CPU_BE) + +#define htoll(x) ((((x) & 0x00ff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) >> 8) & 0xff00) | \ + (((x) >> 24) & 0x00ff)) + + +#define HTOLL(sr,temp) /*sr = A ,B ,C ,D */\ + eor temp, sr, sr, ROR #16 ; /*temp = A^C,B^D,C^A,D^B */\ + bic temp, temp, #0xFF0000 ; /*temp = A^C,0 ,C^A,D^B */\ + mov sr, sr, ROR #8 ; /*sr = D ,A ,B ,C */\ + eor sr, sr, temp, LSR #8 /*sr = D ,C ,B ,A */ + +#endif + +#define MV_REG_READ_ASM(toReg, tmpReg, regOffs) \ + ldr tmpReg, =(INTER_REGS_BASE + regOffs) ; \ + ldr toReg, [tmpReg] ; \ + HTOLL(toReg,tmpReg) + +#define MV_REG_WRITE_ASM(fromReg, tmpReg, regOffs) \ + HTOLL(fromReg,tmpReg) ; \ + ldr tmpReg, =(INTER_REGS_BASE + regOffs) ; \ + str fromReg, [tmpReg] + +#define MV_DV_REG_READ_ASM(toReg, tmpReg, regOffs) \ + ldr tmpReg, =(CFG_DFL_MV_REGS + regOffs) ; \ + ldr toReg, [tmpReg] ; \ + HTOLL(toReg,tmpReg) + +#define MV_DV_REG_WRITE_ASM(fromReg, tmpReg, regOffs) \ + HTOLL(fromReg,tmpReg) ; \ + ldr tmpReg, =(CFG_DFL_MV_REGS + regOffs) ; \ + str fromReg, [tmpReg] + + + + +/* Defines */ + +/* The following is a list of Marvell status */ +#define MV_ERROR (-1) +#define MV_OK (0x00) /* Operation succeeded */ +#define MV_FAIL (0x01) /* Operation failed */ +#define MV_BAD_VALUE (0x02) /* Illegal value (general) */ +#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */ +#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */ +#define MV_BAD_PTR (0x05) /* Illegal pointer value */ +#define MV_BAD_SIZE (0x06) /* Illegal size */ +#define MV_BAD_STATE (0x07) /* Illegal state of state machine */ +#define MV_SET_ERROR (0x08) /* Set operation failed */ +#define MV_GET_ERROR (0x09) /* Get operation failed */ +#define MV_CREATE_ERROR (0x0A) /* Fail while creating an item */ +#define MV_NOT_FOUND (0x0B) /* Item not found */ +#define MV_NO_MORE (0x0C) /* No more items found */ +#define MV_NO_SUCH (0x0D) /* No such item */ +#define MV_TIMEOUT (0x0E) /* Time Out */ +#define MV_NO_CHANGE (0x0F) /* Parameter(s) is already in this value */ +#define MV_NOT_SUPPORTED (0x10) /* This request is not support */ +#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented */ +#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */ +#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */ +#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */ +#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */ +#define MV_INIT_ERROR (0x16) /* Error occured while INIT process */ +#define MV_HW_ERROR (0x17) /* Hardware error */ +#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */ +#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */ +#define MV_NOT_READY (0x1A) /* The other side is not ready yet */ +#define MV_ALREADY_EXIST (0x1B) /* Tried to create existing item */ +#define MV_OUT_OF_CPU_MEM (0x1C) /* Cpu memory allocation failed. */ +#define MV_NOT_STARTED (0x1D) /* Not started yet */ +#define MV_BUSY (0x1E) /* Item is busy. */ +#define MV_TERMINATE (0x1F) /* Item terminates it's work. */ +#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */ +#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */ +#define MV_WRITE_PROTECT (0x22) /* Write protected */ + + +#define MV_INVALID (int)(-1) + +#define MV_FALSE 0 +#define MV_TRUE (!(MV_FALSE)) + + +#ifndef NULL +#define NULL ((void*)0) +#endif + + +#ifndef MV_ASMLANGUAGE +/* typedefs */ + +typedef char MV_8; +typedef unsigned char MV_U8; + +typedef int MV_32; +typedef unsigned int MV_U32; + +typedef short MV_16; +typedef unsigned short MV_U16; + +#ifdef MV_PPC64 +typedef long MV_64; +typedef unsigned long MV_U64; +#else +typedef long long MV_64; +typedef unsigned long long MV_U64; +#endif + +typedef long MV_LONG; /* 32/64 */ +typedef unsigned long MV_ULONG; /* 32/64 */ + +typedef int MV_STATUS; +typedef int MV_BOOL; +/*typedef void MV_VOID;*/ +#define MV_VOID void +typedef float MV_FLOAT; + +typedef int (*MV_FUNCPTR) (void); /* ptr to function returning int */ +typedef void (*MV_VOIDFUNCPTR) (void); /* ptr to function returning void */ +typedef double (*MV_DBLFUNCPTR) (void); /* ptr to function returning double*/ +typedef float (*MV_FLTFUNCPTR) (void); /* ptr to function returning float */ + +typedef MV_U32 MV_KHZ; +typedef MV_U32 MV_MHZ; +typedef MV_U32 MV_HZ; +#if defined(_HOST_COMPILER) +#define __MV_PACKED +#else +#define __MV_PACKED /*__packed*/ +#endif + +#endif /* MV_ASMLANGUAGE */ + +/* Bit field definitions */ +#define NO_BIT 0x00000000 +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +/* includes */ +#define _1K 0x00000400 +#define _4K 0x00001000 +#define _8K 0x00002000 +#define _16K 0x00004000 +#define _32K 0x00008000 +#define _64K 0x00010000 +#define _128K 0x00020000 +#define _256K 0x00040000 +#define _512K 0x00080000 +/* Sizes */ +#define _1M 0x00100000 +#define _2M 0x00200000 +#define _4M 0x00400000 +#define _8M 0x00800000 +#define _16M 0x01000000 +#define _32M 0x02000000 +#define _64M 0x04000000 +#define _128M 0x08000000 +#define _256M 0x10000000 +#define _512M 0x20000000 +#define _1G 0x40000000 +#define _2G 0x80000000 +/* Speed */ +#define _133MHZ 133333333 +#define _150MHZ 150000000 +#define _166MHZ 166666667 +#define _200MHZ 200000000 + +/* Swap tool */ + +/* 16bit nibble swap. For example 0x1234 -> 0x2143 */ +#define MV_NIBBLE_SWAP_16BIT(X) (((X&0xf) << 4) | \ + ((X&0xf0) >> 4) | \ + ((X&0xf00) << 4) | \ + ((X&0xf000) >> 4)) + +/* 32bit nibble swap. For example 0x12345678 -> 0x21436587 */ +#define MV_NIBBLE_SWAP_32BIT(X) (((X&0xf) << 4) | \ + ((X&0xf0) >> 4) | \ + ((X&0xf00) << 4) | \ + ((X&0xf000) >> 4) | \ + ((X&0xf0000) << 4) | \ + ((X&0xf00000) >> 4) | \ + ((X&0xf000000) << 4) | \ + ((X&0xf0000000) >> 4)) + +/* 16bit byte swap. For example 0x1122 -> 0x2211 */ +#define MV_BYTE_SWAP_16BIT(X) ((((X)&0xff)<<8) | (((X)&0xff00)>>8)) + +/* 32bit byte swap. For example 0x11223344 -> 0x44332211 */ +#define MV_BYTE_SWAP_32BIT(X) ((((X)&0xff)<<24) | \ + (((X)&0xff00)<<8) | \ + (((X)&0xff0000)>>8) | \ + (((X)&0xff000000)>>24)) + +/* 64bit byte swap. For example 0x11223344.55667788 -> 0x88776655.44332211 */ +#define MV_BYTE_SWAP_64BIT(X) ((l64) ((((X)&0xffULL)<<56) | \ + (((X)&0xff00ULL)<<40) | \ + (((X)&0xff0000ULL)<<24) | \ + (((X)&0xff000000ULL)<<8) | \ + (((X)&0xff00000000ULL)>>8) | \ + (((X)&0xff0000000000ULL)>>24) | \ + (((X)&0xff000000000000ULL)>>40) | \ + (((X)&0xff00000000000000ULL)>>56))) + +/* Endianess macros. */ +#if defined(MV_CPU_LE) + #define MV_16BIT_LE(X) (X) + #define MV_32BIT_LE(X) (X) + #define MV_64BIT_LE(X) (X) + #define MV_16BIT_BE(X) MV_BYTE_SWAP_16BIT(X) + #define MV_32BIT_BE(X) MV_BYTE_SWAP_32BIT(X) + #define MV_64BIT_BE(X) MV_BYTE_SWAP_64BIT(X) +#elif defined(MV_CPU_BE) + #define MV_16BIT_LE(X) MV_BYTE_SWAP_16BIT(X) + #define MV_32BIT_LE(X) MV_BYTE_SWAP_32BIT(X) + #define MV_64BIT_LE(X) MV_BYTE_SWAP_64BIT(X) + #define MV_16BIT_BE(X) (X) + #define MV_32BIT_BE(X) (X) + #define MV_64BIT_BE(X) (X) +#endif + + + +#ifndef MV_ASMLANGUAGE +/* Get the min between 'a' or 'b' */ +#define MV_MIN(a,b) (((a) < (b)) ? (a) : (b)) + + +/* Marvell controller register read/write macros */ +#define CPU_PHY_MEM(x) (MV_U32)x +#define CPU_MEMIO_CACHED_ADDR(x) (void*)x +#define CPU_MEMIO_UNCACHED_ADDR(x) (void*)x + + +/* CPU architecture dependent 32, 16, 8 bit read/write IO addresses */ +#define MV_MEMIO32_WRITE(addr, data) \ + ((*((volatile unsigned int*)(addr))) = ((unsigned int)(data))) + +#define MV_MEMIO32_READ(addr) \ + ((*((volatile unsigned int*)(addr)))) + +#define MV_MEMIO16_WRITE(addr, data) \ + ((*((volatile unsigned short*)(addr))) = ((unsigned short)(data))) + +#define MV_MEMIO16_READ(addr) \ + ((*((volatile unsigned short*)(addr)))) + +#define MV_MEMIO8_WRITE(addr, data) \ + ((*((volatile unsigned char*)(addr))) = ((unsigned char)(data))) + +#define MV_MEMIO8_READ(addr) \ + ((*((volatile unsigned char*)(addr)))) + + +/* No Fast Swap implementation (in assembler) for ARM */ +#define MV_32BIT_LE_FAST(val) MV_32BIT_LE(val) +#define MV_16BIT_LE_FAST(val) MV_16BIT_LE(val) +#define MV_32BIT_BE_FAST(val) MV_32BIT_BE(val) +#define MV_16BIT_BE_FAST(val) MV_16BIT_BE(val) + +/* 32 and 16 bit read/write in big/little endian mode */ + +/* 16bit write in little endian mode */ +#define MV_MEMIO_LE16_WRITE(addr, data) \ + MV_MEMIO16_WRITE(addr, MV_16BIT_LE_FAST(data)) + +/* 16bit read in little endian mode */ +static __inline MV_U16 MV_MEMIO_LE16_READ(MV_U32 addr) +{ + MV_U16 data; + + data= (MV_U16)MV_MEMIO16_READ(addr); + + return (MV_U16)MV_16BIT_LE_FAST(data); +} + +/* 32bit write in little endian mode */ +#define MV_MEMIO_LE32_WRITE(addr, data) \ + MV_MEMIO32_WRITE(addr, MV_32BIT_LE_FAST(data)) + +/* 32bit read in little endian mode */ +static __inline MV_U32 MV_MEMIO_LE32_READ(MV_U32 addr) +{ + MV_U32 data; + + data= (MV_U32)MV_MEMIO32_READ(addr); + + return (MV_U32)MV_32BIT_LE_FAST(data); +} + +/* Flash APIs */ +#define MV_FL_8_READ MV_MEMIO8_READ +#define MV_FL_16_READ MV_MEMIO_LE16_READ +#define MV_FL_32_READ MV_MEMIO_LE32_READ +#define MV_FL_8_DATA_READ MV_MEMIO8_READ +#define MV_FL_16_DATA_READ MV_MEMIO16_READ +#define MV_FL_32_DATA_READ MV_MEMIO32_READ +#define MV_FL_8_WRITE MV_MEMIO8_WRITE +#define MV_FL_16_WRITE MV_MEMIO_LE16_WRITE +#define MV_FL_32_WRITE MV_MEMIO_LE32_WRITE +#define MV_FL_8_DATA_WRITE MV_MEMIO8_WRITE +#define MV_FL_16_DATA_WRITE MV_MEMIO16_WRITE +#define MV_FL_32_DATA_WRITE MV_MEMIO32_WRITE + + +/* CPU cache information */ +#define CPU_I_CACHE_LINE_SIZE 32 /* 2do: replace 32 with linux core macro */ +#define CPU_D_CACHE_LINE_SIZE 32 /* 2do: replace 32 with linux core macro */ + + +#define MV_REG_VALUE(offset) \ + (MV_MEMIO32_READ((INTER_REGS_BASE | (offset)))) + +#define MV_REG_READ(offset) \ + (MV_MEMIO_LE32_READ(INTER_REGS_BASE | (offset))) + +#define MV_REG_WRITE(offset, val) \ + MV_MEMIO_LE32_WRITE((INTER_REGS_BASE | (offset)), (val)) + +#define MV_REG_BYTE_READ(offset) \ + (MV_MEMIO8_READ((INTER_REGS_BASE | (offset)))) + +#define MV_REG_BYTE_WRITE(offset, val) \ + MV_MEMIO8_WRITE((INTER_REGS_BASE | (offset)), (val)) + +#define MV_REG_SHORT_READ(offset) \ + (MV_MEMIO_LE16_READ(INTER_REGS_BASE | (offset))) + + +#define MV_REG_BIT_SET(offset, bitMask) \ + (MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \ + (MV_MEMIO32_READ((INTER_REGS_BASE | (offset))) | \ + MV_32BIT_LE_FAST((bitMask))))) + +#define MV_REG_BIT_RESET(offset,bitMask) \ + (MV_MEMIO32_WRITE((INTER_REGS_BASE | (offset)), \ + (MV_MEMIO32_READ((INTER_REGS_BASE | (offset))) & \ + MV_32BIT_LE_FAST(~(bitMask))))) + + +#define mvOsDelay(us) uDelay(us*1000) +#define mvOsUDelay uDelay + + +#define u32 MV_U32 +#define u16 MV_U16 +#define u8 MV_U8 +#define s16 short +#define s32 long +#define s8 char + +#define UINT32 MV_U32 +#define UINT16 MV_U16 +#define UINT8 MV_U8 + +typedef UINT32* PUINT32; +typedef UINT16* PUINT16; +typedef UINT8* PUINT8; + +#define TRUE MV_TRUE +#define FALSE MV_FALSE + + + +#endif /* #ifndef MV_ASMLANGUAGE */ + +#endif /* _INC_BOOTSTRAP_OS_H */ + diff --git a/tools/doimage b/tools/doimage new file mode 100644 index 0000000000000000000000000000000000000000..30abf60bbafeb02763ef435a8e20b43e90d5345f GIT binary patch literal 19516 zcmd^ne|%KcnfIAwkP)L36fG*swM|xNAqGq}{IdMI3U7fT5TykSLo#8eCYd;MBcZR* z(8-icuhHm=;#;;K*rmJfF7;(UTA*7}16YGDy0KzkRBB_z-5Ha*X-g|_mpc3Xo^$TZ z9Ya9h&%6KZ-h9s7=Q+>M^PJ~A=iWPW^G$Qn?H-RuI7fjf6vXy!_4+DsK6!_tR0u=( z!~`);Tq`a@7ikr(;6alD5E_9#FIpjKz$>srY`n(Z4 zmsL&u{?@uZ^}l`jwcX#c{Aah3b`2Wi!&tO_q2RN`uSMfA@wx}c?fLS%-Ic$!$E~jl z&|Kbelg7S*^W|uI>O?@})ax7ufN2`J1_bi|xyBv&MH)w_B>f*Wenj){()e#R{fNd* zO<%9^&mj=hzgFWxoQXGT{C16(X?&{2|Ch#Z(RfJX5sg2p@wm44q{eU1^!qj5uIXRX z_!Syw4)Zvsapn+@C(!7hO$3LduT7z17S5#qoyJQwK2hU;()e=XKll1L_oKzta&8~k z@8Ev13H^PqJNVUN4)9YhTvS)DZ-_Kj$E-lqs;(ADyBen3EuwniSI}D#;G&Nf>e$<2lQ6X7GLqniRGz1%BL5n?+X7G}OeKk!RMO{sOBo+iIYDJps zMMI#zK2k%@U^FTknj0xz7pn<0)`_|e(XbVScr@H-)k!zj2cZeFH4RPhmo9358v@}* zQ5Ovc(OuVqF<9b`MGNQ7tDagmB@2~f$XL%@Dg1Q)3MHgIoxc3DM{;nj6tE=7MqQ)B z;Y+#7Ue$fY5-$*Mk%(h8;(HMm8sk1p;LfjkrdLdi0M(J~Z(Rw=AB)-@-E{ z@&TT)I9qwf;%?)4q!8^q`%tHN#)9wUc@%0C&zA_Xo#!GUcJK@jck+Ch5W9Ky3-J`s z7|0%;N2C7oj3j%OXB5u^JfnadSyws#ALabc%;*rc3Yay8_4dIhAnNmg~L@?b4 zu}mo=5+W_#D{)39#L%a^CC&(i;DJc*l{h06GKlY#I3pICK)h4pj9iHGpKg^nBN(bA z-Xw8GGBlg`T8T5Fp#{X3N}Q1mEhRo%;*4-;CGm2JGt!~8#0`lv;vo(wT`X}%KGZ~9 zNSreeY9T)O5jsja6QNe(eG=!4gxZPsN}Mwj>LlJRan4X^JMp~|=S+om65lCt&RFOv z;++!b%!T$6ZE=9f#WQXDZjoa`A+=Q;L;V#LaqD2(TR^c?+Vqn zV=wy~FrMzrJ9Hkj&hjF`Me}U?N*{m&4`SP#+>Vb!X9_x2W~RLv8{e^y20G??{)!x# zF$t0t`?NQs|N6oRYVgFL_pVxVq~m_kaqvd+Lw|h0x2qGpiEit1`Y!-n+~X}_U#9oP zBb^0=s@F?;4bn(s6sY8F3Q$3cdWg5ii zc)czoNtqRPg0YYHdD^r%N&#!Y!xfQ%oV`WIXWI8mFG^{^oQ zZx_Ks72*6?{Lm#(^yxgjRC>sDlJDUK>UTj^G4!Sv59i?(E`hH@ z;8Vo#-ajIS=H4FjDW*}rmj_F7k-8%5WvM{oN(x0E;Z{3g^^i-FJhV-z@MIDp% z&`7^fFpP%}x&+>Z$xq?osXx#|Za?`RPIIa3gi0r`4V{cvyXZ}z>tqBuJ$^Vh-viYt zfHOaxo3o^w+&S~zeAJ~f4Ial$k9ITaqQ3~bb`#`u3qH(npBwceh^pX|?Apsamg<6q zoi(pHqNgU88{6D1v8k!{{XX@~jSd zrQ&aU8zy-X_O~!;%L^G^Qj7x|oV>ax!MhJQg{!`mfN<-F8w4%#be>51cWx2XS1ob} zMH;loGkGHW@c5XBUdiMC$2@-eq9RPFe-8P7mdF2{ zJbrB0ntv<#N2kW(;ea#85wNP9^IBK*k4>G$6FG;roV4$ADtFm(M(u4YfZWhKLt@C5 zS6tks;I?Hsu1hBVh)Zx=US=i}gAyJK$zx6&grFD<2 zK}?Bs73ePX_I&hKpfAWfftH@cI4Hs65)tp>t}m?1Y`Oj8N*)ILNA<`v=%_~=LMeHX zvmnUj<|4>T7Ju6tnEMwJXCUoKzbs+ibA+8$$#PVbGfN9}p;am(q%5Z&&5C~Q0-^>) z9q-30?`KGz(b4X)q-R5;EeYDhO<5E6r!X-t&qRK>iro5bc_WA^{T0S<%L{_`#5;h~ zys1_bu;V|&uu{GFKSQ-HvaEZYey=}KBXftTc#%JG7ZB&_7PQ5TxO-ok0JdSaEZ^`X z-p>vr#T$DUN!eLH4^=-BPURoQvdVU zxJ%df+!?@5YzzH~H#wgF@3B2c05`xc)+`1(Ge`>*J7dc4ERp8%sidQ@k{t1+~oBLZg?O$SDgwMw2v54pw!J4X3W1$U zZ>UxqDp!U$zSM3?B_4x~S)yEs&9|tHwy=4!91ptSQac0p5=N6X_A(GBM+4F@omGk; z$Zz&|+gc2`h<0%H@yrt9jPXY)IGLC!2g6U%Tl7>W>^2UStc)Nl34B#oz!c_D)zx-erCO{4SQf%7yo9|%A%}s z7KL*e@BLR8KZ$tIxMs>4f5sv1A_tSgDIs}j?HF%^ug-?kcAb3K!^uh}PT|wN&5e8^ z@e#T_YW@nW5(RjzYZV}@%M~!vx>y0eX1^`f#JjypUwqSEVNJHpz45+6)V<3AB@f4c zRd|4_c4Du`+^Yoas=c0G#|1i~_~)znx3{qiGwoyAVzvjFJ~qa!q}?i$=5EzlXzo@D znH_^j%I_Hvf@|BDlY(pC^ya^@ou;$0OG6aKbafoN{?AjPl4 zgIHVMyHPv^@ub-r-_$B{E0d!1o$Sua%z)9!_89!?G39gp{(Efmpu;5;|Nd?Qi=ZT-9bb*l~KEr+8O63}R|uV;`i|jIxtG zUiRfxDJN~-hD>@rzQ(oXcQ3ZEujCiVPRM5H?Ai~u{#8z<$~zv+NWS^kel?u=p%vOO zUrqBVe4CuzklzB*V;*A=ddyy)RL#THqrB}mPn^Ap6McenSk4if$K#uhBe8ZtQq?iF zinudzu59x-c^`v&_BNJa2v6)y9#*`Cpkiv7ku*lmYsd)$a&y&{QLa&`7yLTjzj`M- zV5v9Rd+5ygL#gXMI2YJe!vbsx$rFAA2 zee96JjuUI(ghx&{qhMX4NBeDb>tL9@>09x=y$a(9f8sNE0?}ihq)WLS_C8KD#{Q5T zlZDX5yZDK?E`+e7s;|d9r37mk-9(Dty>#)j*m^(%8!l6T&nihrQRNh7_}lmlMj^BP zZQloyUJkM?FC>y?yKT1fJGp(`j2q`82A}K%y`X0m@GNe&d*X7io_IqauIKth^U?IB zE-jrpbbX$rc`Cl?l(6o$%~KQ2zPO2p4rU)U{jm=k&6BoyGHG_QPur6NLnl~10~S4I z5Veakmn3-s$!4d2zwqzxj+>nYj*5+WE^h&wa<>5P7HD_xk$aoWPIJ5CZsAaOk+{;` zFJIW*&@a#H?vo_L7A}IfdmUH5ndj=y!J=IC!d0(y^;r5DnIj)_b>vW2v42WecS6er zBHQ)$d0qX0WVnj0bUOmz_`IT|$niUo=lAtlzkTrAC;fg-&zxQrC*`V;^VTGdI~f(t zxq>xv1@=C*M(|AF16;55m?@R&^0Lhw9J*KnP>_@fnq4g8pe1+d=&Y(r$=H(NV&NxN z)$i~$FWxnYh;XZ2kh@LPs@RK$Ti+^3SIFoeir-N_zOFYaGkT4>wE(Wlfn#t+q+qw+5WalP|_>$ z@v(K@Za!?AgEP#5&3E^hJ87@~3;uoP!`-Qot`hKY-egbtMJCf5d^nC3WVY!EeUP&9uhz13B6-8Jmv zgT)e-gWU>E7Z~jBH_toR*GXnQNSZtJy79M-L8jT}fTw$gIk@RACjvLx=8i+D@#h}= zuc7DF;Ew#UzcO^}?}0D9R_d2odVcLrDm^@m_K&C1R%$PR_VfD8h0i>gHjGwDcO~c) zYTYCANBX?{yxN^I_|_YrEF!Ogum8^Ts&vB8K8(tbhoKdGEcDr(XAnCNSJdSn!B%PB zoT`v;-0&cmt&16n2f{fNWDJv7-v|Cu8 zSK$C_@^GPKwgGAz9rEW{^m8lyl-H5?&KRo6!Qi4!3;OzV0B%oQ15%f3+WIel?uN>!ip=G!LFUwjOF2EVoXf-VP00|>jSJc}W zWapmilB}Az*^8T8-cZdjd#%r&>rs<)Bl9?f`oX~;vki9>6$MYci}&5~8!P7q{H@pV zcuqe`wJyy*MlAui^P~ygyz%4AT`H9@3xqXR=RP8=cOEd*Q%*m&gd8Ety$&n#*~gaW z`J=_Ju3FO(ID16>=+W6XJ>X#$EW%fF=v#qPs)K#rl4ip1D7b?#^`ZZ-3BRb|=LmNx z_ypm9Q1EXEe_z3Je}3|~lpXbB^lSZN2yan5s|hzN_%Xs^1s@~4M!~*=fbUdrIbl=5 zwS=cBcst?A3hpC(gM!C)0lrefs|jDM;GKm3q98_{tE^75q?C$McsfC3Z6-Lqk``u+@N5Ka6rL32v;fiB;kb$ zo^%NCECq)MPf_q+5-wHnLBdxnI7RqU1s5L%>{0Ln!oPn_&QUAjw1N*3{)K`E2*2v; z|EYq<@=cTffZ`2g!e*t3RmV7uo++z%Q!Y#q+u1c5?t% zjsxvxzis-G=2_c3iyKK{_Q%b$xKAv?Ra%i~PJ^dkOO1gPE{(J7w(yt(;KsdA5q2PO zzmLlbhq=c*ivonLT3#0Sm)PcM|Gw5^@Wj8b_W*u%B9ezDzIuQg(`$Vfn`h(ZXo{^O3&UFb-fgFWUMs_Mt1+ClYuP(PqoQ+CzaDTk9)1O20T!F2f5_W{ELNW{%E z@c+!n%`Za(A4?rBtirA`m@J@~Et^jB!RqE+($_5mEZ``+XHm_t=4YWwd|2g6kCT@% zMYg!v^p(m7v5!d}j2}-nr{FHZ7dMM=t@huLCEiesyT;;?{;h9f4*(>eqhBx(5W}<- zi{{r5#1Hw~aFo(DM>?!ObN!zD?z@(!@VbK7a^$D@txkNPD0S06<6-NM4a`eNoSzeW z4rK}w8LMQ6x8u(jt-7ar%@KQC$&pUl!+Q}$ z;7{Qzr_7ck0rh(zY;pXu28!f0LTY9&6hLwfWZZ|6_wM3*X?*5=#g7Tqb;kR>nO?h) zk48_&x zt{=ri!~#}8GzJ=LMJU)J*5TcnX1o<7>gofrkXRRqSkXv>XaXrbwFXMHzJ-l=)5n06 zf!BTrh8qIwgE0ed^W10|>w<O-1)#nb z{ZXS1&~#-9if5J9juPgwWnWolOgA_ZyiF8nD#H+sSoj-3Mq*uf{rX@O&ITHd(pqEP zMhjzr5QApm{iG(kQ5utqv;BM@sxhA+M5s1ewhr$%-MgHsXBp)!r7cEXjPER2WihK- zT2$SmL{yZvI9B-PQ@%3T+Ymq~5h@D<8zmMpw#K|rpyu9KbAvHK>ng3Cs0@`?LfZyW zT0V8O0ibQFM5kznT(T#GvF_j;X``{t3 z@2B7K`qtZC-(8QY_I9V&SKX1rJ0JG?1|G@biy%YZ1p59Ce5)Yu$leOsiy!p*o<)0i zo7cDaaj&l(Z6Dx%oPUb*akSbeyuRnqrj(VJbG{b`qW1^u>yZ~S+l&>FNWFm+iZQQC zW240K>{ymZ<{7oY`@=QC*mOe}I2_^1%G+-#ubgU3Hs(wjLYPunPD1%m!ZayyF2XPp zQ!A$^Rn0NX9-I)u@q1=NGcrQ0$JlMgDx`Zb>fmeCQmRIl%28Hhff=hpST^Kow$=zS z>SGEfbJ=mxVZ9hk+(;DXI=KexB6#a=0}^cdC^313R%vZ)f=31xs1;bv<-S@j_tkp2 zuVy(|jdHM>>t4uUfID}D>s*SMNK`aQ+ROR8AzWX7F4@MK`erP7H6plNzme}}PM)t- z)&^r1eN$6R3@NE9SEErI4Iuv!8aOvmOg6Pluq9YS8J?RZZ=kj|8jQsZu;$C;2BD!L zW4Ter0<{WdMvaC}aFpdOb^18RxG;x}=Wqa-$x^7wDaW~7D~&~(qcxa?A@&(d$|ynk zjwb6vELdYlCS|o2|yU@8X9E57Z;9$N(rXIIlPI~)#0^I z>CGqc2W2`N1vsQqKTxlVHg_7CatM!@d^hK|dPBI@3ZZNp#sYJtD!;O8l9TF{lcwA< z>E@}EP|U>S#fG&Z7Oqz1A2NYhO*pKi8nFk#HXNvlG+KCdG$uV+ICUO!1642@T#xj{ zP}XfULN{$-Dh`bewj-oc%-~D0Oet)Iazl~X%k`MIf^Tz=km37es}o~iCX-c<aFoU-aB6dkqcOsEakAdl;fFHV^{$(UMRQ8~#dE1NjoSTbkHd}ArM z7H%k%ou_1jH8s@@5pK&)z zgz`c+S!yTB{M3bt6DcW<{M3ATYePhBo0EoUP~%2_u8O-=YkzLe*T-6ZK7Uv^4ab*? zPbjNAQKF-2B6x!vqe4Vu;dPipE6m+;RCb@jeu1bPSdwZvs=zS+oe1UjH1O)(LsRqF z+&X1}Lmku=EwAz$c{N?l6{ZWvC)g!(;msR^EM&%c%owZSjovY^y$WgXli8Hlq0YXJ z7+}LZuO)XJWNH1RZW&nE*)$CY@5s+9>Ogz%7FC6nICB^o_ct zsQ9YS;Foi`qwh=-_?FcKir^CeBacyb@>M?=l%)KgeIP;q3XwGU0i^=ef4X z>*fDW7>hpq8eXgbKcCu)IhXko1#>SY%>GKW1)zNm=PYere8jiCTMH?>60IHdsc!oG zI9(CA2ji`E_DqJuEKgvWN+=BP?f$xapJ${@I0_Wtu zhlX$5r5s+5mj?~3eckKhT^4`n!tvpkAp)<{JlN*-@qalOX!xxi-|OR(-AFh3 z;aY^g4C4GP-~d1M!T(R<2wneeudfX4Hnb&Z_nqrM$Ad zVrr!^VHtMG1=w+A|Kv*S7XRg$%VHt^pNqgcQHK9u5sWs8GTdAR%jV2oIN1uU*Vy{T z=CXCoVf>4iaIGjK7UErYS?$Kg*v1BRwxWun?`!gqYS5y=dh#ovsotVN{Fjb0E7*e1 zIv^lLaJ?50Wx-H&9j=&z)wny&VWNyzk};T5r?1z52$g|`a1G2wpavghQn%8xE(UIH z7r{o$NxDyP=DJ~?bDhZl*#m@Y!8u6d!9KoCLq7SxbwDrxI|rVk$>RomI(#9l&k*=Z zG>s>RuLAHNu(qg=>ze=Lhc}S2#%MnB-iAgW$;b765PW@TT>m&peXJL^qjAlXkM&^( z5Y`3fATN(4XjmW8F4y(9V1)J1u}gWjRcNdQgjo-|!AJkxc7ckoqg{+fKGu^#@EL#| zeH;T9Ca?P(KGvUNFdWrP%#D`<|A+t;$u*1iHV$nVf z-$552|5-&R_#7Q>eTRT>E@)T&&nfV6-q^>3GW6pmG{^30>^rN?q58=C&n`ahPiw)~ zgg)mW58DYeM_(`adco(+6?w_S<83tBr+<7^pbvbL06T}Ffp>AHKIb6cWv&hfbZk0& OAKWg)fP>)d@cjn@6_+Of literal 0 HcmV?d00001 diff --git a/tools/doimage.c b/tools/doimage.c new file mode 100644 index 0000000..6c224bf --- /dev/null +++ b/tools/doimage.c @@ -0,0 +1,1263 @@ + +/******************************************************************************* +Copyright (C) Marvell International Ltd. and its affiliates + +******************************************************************************** +Marvell GPL License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File in accordance with the terms and conditions of the General +Public License Version 2, June 1991 (the "GPL License"), a copy of which is +available along with the File in the license.txt file or by writing to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or +on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + +THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY +DISCLAIMED. The GPL License provides additional details about this warranty +disclaimer. + +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _HOST_COMPILER +#include "bootstrap_def.h" + +#ifndef O_BINARY /* should be define'd on __WIN32__ */ +#define O_BINARY 0 +#endif + +#define DOIMAGE_VERSION "1.00" + +void print_usage(void); + +int f_in = -1; +int f_out = -1; +int f_header = -1; + + +typedef enum +{ + IMG_SATA, + IMG_UART, + IMG_FLASH, + IMG_BOOTROM, + IMG_NAND, + IMG_HEX, + IMG_BIN, + IMG_PEX, + IMG_I2C +}IMG_TYPE; + +typedef enum +{ + HDR_IMG_ONE_FILE = 1, /* Create one file with header and image */ + HDR_IMG_TWO_FILES = 2, /* Create seperate header and image files */ + HDR_ONLY = 3, /* Create only header */ + IMG_ONLY = 4, /* Create only image */ + +}HEADER_MODE; + + +#define T_OPTION_MASK 0x1 /* image type */ +#define D_OPTION_MASK 0x2 /* image destination */ +#define E_OPTION_MASK 0x4 /* image execution address */ +#define S_OPTION_MASK 0x8 /* image source */ +#define R_OPTION_MASK 0x10 /* DRAM file */ +#define C_OPTION_MASK 0x20 /* NAND ECC mode */ +#define P_OPTION_MASK 0x40 /* NAND Page size */ +#define M_OPTION_MASK 0x80 /* TWSI serial init file */ +#define W_OPTION_MASK 0x100 /* HEX file width */ +#define H_OPTION_MASK 0x200 /* Header mode*/ +#define X_OPTION_MASK 0x400 /* Pre padding */ +#define Y_OPTION_MASK 0x800 /* Post padding*/ +#define I_OPTION_MASK 0x1000 /* SATA PIO mode*/ +#define L_OPTION_MASK 0x2000 /* delay time in mseconds*/ + + + +#define SATA_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|S_OPTION_MASK) +#define UART_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK) +#define FLASH_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK) +#define PEX_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK) +#define I2C_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|M_OPTION_MASK) +#define MAX_TWSI_HDR_SIZE (60*1024) /* MAX eeprom is 64K & leave 4K for image and header */ +#define BOOTROM_MUST_OPT (T_OPTION_MASK) + +#define NAND_MUST_OPT (D_OPTION_MASK|T_OPTION_MASK|E_OPTION_MASK|P_OPTION_MASK) +#define HEX_MUST_OPT (T_OPTION_MASK|W_OPTION_MASK) +#define BIN_MUST_OPT (T_OPTION_MASK|W_OPTION_MASK) + +/* 32 bit checksum */ +u32 checksum32(u32 start, u32 len, u32 csum); +u8 checksum8(u32 start, u32 len,u8 csum); +u32 crc32(u32 crc, volatile u32 *buf, u32 len); + +int main(int argc,char** argv) +{ + char *image_type = NULL; + IMG_TYPE img; + unsigned int image_dest=0,image_exec=0,header_size=0, image_source = 0, twsi_size=0; + char *fname_in,*fname_out=NULL,*fname_hdr_out=NULL,*fname_romc=NULL, + *fname_dram=NULL,*fname_twsi=NULL; + char *inst_set; + unsigned char *ptr; + BHR_t hdr; + ExtBHR_t extHdr; + struct stat fs_stat,fs_stat_code; + char *buf_in = NULL ,*buf_code = NULL; + int override[2]; + int err,size_written=0; + char *tmpHeader = NULL; + char *tmpTwsi = NULL; + unsigned int opts=0,required_opts = 0; + unsigned int chsum32 = 0; + unsigned int nandPageSize=0, nandEccMode=0, hex_width=0,header_mode = HDR_IMG_ONE_FILE,ms_delay=0; + FILE* f_dram, *f_hex,*f_hex2, *f_hex3, *f_twsi; + int f_code; + unsigned char *hex8=NULL, tmp8; + unsigned short *hex16=NULL, tmp16; + unsigned long *hex32=NULL, tmp32; + unsigned long lastDword = 0; + int i=0; + unsigned int bytesToAlign=0; + char** f_out_names[2]; + int pre_padding=0, post_padding=0, padding_size=0; + #define IMG_FILE_INDX 0 + #define HDR_FILE_INDX 1 + + f_out_names[IMG_FILE_INDX] = &fname_out; + f_out_names[HDR_FILE_INDX] = &fname_hdr_out; + + memset((void*)&hdr,0,sizeof(BHR_t)); + memset((void*)&extHdr,0,sizeof(ExtBHR_t)); + + if (argc ==1) + { + print_usage(); + exit(1); + } + + while (--argc > 0 && **++argv == '-') + { + while (*++*argv) + { + switch (**argv) + { + case 'T': /* image type */ + if (--argc <= 0) {print_usage();exit(1);} + image_type = *++argv; + if (opts & T_OPTION_MASK) {print_usage();exit(1);} + opts |= T_OPTION_MASK; + break; + case 'D': /* image destination */ + if (--argc <= 0) {print_usage();exit(1);} + image_dest = strtoul (*++argv, (char **)&ptr, 16); + if (*ptr) {print_usage();exit(1);} + if (opts & D_OPTION_MASK) {print_usage();exit(1);} + opts |= D_OPTION_MASK; + break; + case 'E': /* image execution */ + if (--argc <= 0) {print_usage();exit(1);} + image_exec = strtoul (*++argv, (char **)&ptr, 16); + if (*ptr) {print_usage();exit(1);} + if (opts & E_OPTION_MASK) {print_usage();exit(1);} + opts |= E_OPTION_MASK; + break; + case 'X': /* Pre - Padding */ + if (--argc <= 0) {print_usage();exit(1);} + padding_size = strtoul (*++argv, (char **)&ptr, 16); + pre_padding=1; + if (*ptr) {print_usage();exit(1);} + if (opts & X_OPTION_MASK) {print_usage();exit(1);} + opts |= X_OPTION_MASK; + break; + case 'Y': /* Post - Padding */ + if (--argc <= 0) {print_usage();exit(1);} + padding_size = strtoul (*++argv, (char **)&ptr, 16); + post_padding=1; + if (*ptr) {print_usage();exit(1);} + if (opts & Y_OPTION_MASK) {print_usage();exit(1);} + opts |= Y_OPTION_MASK; + break; + case 'I': /* PIO */ + if (argc <= 0) {print_usage();exit(1);} + if (opts & I_OPTION_MASK) {print_usage();exit(1);} + opts |= I_OPTION_MASK; + break; + case 'S': /* starting sector */ + if (--argc <= 0) {print_usage();exit(1);} + image_source = strtoul (*++argv, (char **)&ptr, 16); + if (*ptr) {print_usage();exit(1);} + if (opts & S_OPTION_MASK) {print_usage();exit(1);} + opts |= S_OPTION_MASK; + break; + case 'P': /* NAND Page Size */ + if (--argc <= 0) {print_usage();exit(1);} + nandPageSize = strtoul (*++argv, (char **)&ptr, 10); + if (*ptr) {print_usage();exit(1);} + if (opts & P_OPTION_MASK) {print_usage();exit(1);} + opts |= P_OPTION_MASK; + break; + case 'C': /* NAND ECC mode */ + if (--argc <= 0) {print_usage();exit(1);} + nandEccMode = strtoul (*++argv, (char **)&ptr, 10); + if (*ptr) {print_usage();exit(1);} + if (opts & C_OPTION_MASK) {print_usage();exit(1);} + opts |= C_OPTION_MASK; + break; + case 'L': /* Delay time */ + if (--argc <= 0) {print_usage();exit(1);} + ms_delay = strtoul (*++argv, (char **)&ptr, 10); + if (*ptr) {print_usage();exit(1);} + if (opts & L_OPTION_MASK) {print_usage();exit(1);} + opts |= L_OPTION_MASK; + break; + case 'W': /* HEX file width */ + if (--argc <= 0) {print_usage();exit(1);} + hex_width = strtoul (*++argv, (char **)&ptr, 10); + if (*ptr) {print_usage();exit(1);} + if (opts & W_OPTION_MASK) {print_usage();exit(1);} + opts |= W_OPTION_MASK; + break; + case 'H': /* Header file mode */ + if (--argc <= 0) {print_usage();exit(1);} + header_mode = strtoul (*++argv, (char **)&ptr, 10); + if (*ptr) {print_usage();exit(1);} + if (opts & H_OPTION_MASK) {print_usage();exit(1);} + opts |= H_OPTION_MASK; + break; + case 'R': /* dram file*/ + if (--argc <= 0) {print_usage();exit(1);} + fname_dram = *++argv; + if (opts & R_OPTION_MASK) {print_usage();exit(1);} + opts |= R_OPTION_MASK; + break; + case 'M': /* TWSI serial init file*/ + if (--argc <= 0) {print_usage();exit(1);} + fname_twsi = *++argv; + if (opts & M_OPTION_MASK) {print_usage();exit(1);} + opts |= M_OPTION_MASK; + break; + } + } + } + + /* 2 sperate images is used with SATA only */ + if (header_mode == HDR_IMG_TWO_FILES) + { + if (!(opts & S_OPTION_MASK)) + { + fprintf(stderr,"Error: -S option is missing\n\n\n\n\n"); + print_usage();exit(1); + } + } + + /* verify HEX file width selection to be valid */ + if (opts & W_OPTION_MASK) + { + if ((hex_width != 8)&&(hex_width != 16)&&(hex_width != 32)&&(hex_width != 64)) + {print_usage();exit(1);} + } + + /* get the minimum option set based on boot mode */ + if (opts & T_OPTION_MASK) + { + if (strcmp(image_type, "sata") == 0) + { + img=IMG_SATA; + required_opts = SATA_MUST_OPT; + } + else if (strcmp(image_type, "nand") == 0) + { + img=IMG_NAND; + required_opts = NAND_MUST_OPT; + } + else if (strcmp(image_type, "hex") == 0) + { + img=IMG_HEX; + required_opts = HEX_MUST_OPT; + } + else if (strcmp(image_type, "bin") == 0) + { + img=IMG_BIN; + required_opts = BIN_MUST_OPT; + } + else if (strcmp(image_type, "uart") == 0) + { + img=IMG_UART; + required_opts = UART_MUST_OPT; + } + else if (strcmp(image_type, "flash") == 0) + { + img=IMG_FLASH; + required_opts = FLASH_MUST_OPT; + } + else if (strcmp(image_type, "bootrom") == 0) + { + img=IMG_BOOTROM; + required_opts = BOOTROM_MUST_OPT; + } + else if (strcmp(image_type, "pex") == 0) + { + img=IMG_PEX; + required_opts = PEX_MUST_OPT; + } + else if (strcmp(image_type, "i2c") == 0) + { + img=IMG_I2C; + required_opts = I2C_MUST_OPT; + + } + else {print_usage();exit(1);} + + } + else + { + print_usage(); + exit(1); + } + + if (header_mode == IMG_ONLY) + { + required_opts &= ~(D_OPTION_MASK|E_OPTION_MASK|S_OPTION_MASK|R_OPTION_MASK|P_OPTION_MASK); + } + + if (required_opts != (opts & required_opts)) {print_usage();exit(1);} + + hdr.ddrInitDelay = ms_delay; + + hdr.destinationAddr = image_dest; + hdr.executionAddr = image_exec; + + switch (img) + { + case IMG_BOOTROM: + header_mode = IMG_ONLY; + break; + case IMG_HEX: + header_mode = IMG_ONLY; + break; + case IMG_BIN: + header_mode = IMG_ONLY; + break; + case IMG_SATA: + hdr.blockID = IBR_HDR_SATA_ID; + header_size = 512; + if (image_source) hdr.sourceAddr = image_source; + else hdr.sourceAddr = 2; /* default */ + + if (!(opts & H_OPTION_MASK)) + { + header_mode = HDR_IMG_TWO_FILES/*HDR_ONLY*/; + } + if (opts & I_OPTION_MASK) + { + hdr.sataPioMode = 1; + } + break; + case IMG_UART: + hdr.blockID = IBR_HDR_UART_ID; + if (opts & R_OPTION_MASK) + { + header_size = 512; + } else header_size = 128; + hdr.sourceAddr = header_size; + break; + case IMG_FLASH: + hdr.blockID = IBR_HDR_SPI_ID; + if (opts & R_OPTION_MASK) + { + header_size = 512; + } else header_size = sizeof(BHR_t); + if ((image_source)&&(image_source >= header_size)) + { + hdr.sourceAddr = image_source; + }else + { + hdr.sourceAddr = header_size; /* default */ + } + + break; + case IMG_NAND: + hdr.blockID = IBR_HDR_NAND_ID; + if (opts & R_OPTION_MASK) + { + header_size = 512; + } else header_size = sizeof(BHR_t); + if ((image_source)&&(image_source >= header_size)) + { + hdr.sourceAddr = image_source; + }else + { + hdr.sourceAddr = header_size; /* default */ + } + + hdr.nandPageSize = (MV_U16)nandPageSize; + hdr.nandEccMode = (MV_U8)nandEccMode; + break; + case IMG_PEX: + hdr.blockID = IBR_HDR_PEX_ID; + if (opts & R_OPTION_MASK) + { + header_size = 512; + } else header_size = sizeof(BHR_t); + if ((image_source)&&(image_source >= header_size)) + { + hdr.sourceAddr = image_source; + }else + { + hdr.sourceAddr = header_size; /* default */ + } + case IMG_I2C: + hdr.blockID = IBR_HDR_I2C_ID; + if (opts & R_OPTION_MASK) + { + header_size = 512; + } else header_size = sizeof(BHR_t); + if ((image_source)&&(image_source >= header_size)) + { + hdr.sourceAddr = image_source; + }else + { + hdr.sourceAddr = header_size; /* default */ + } + } + + if ((header_mode == HDR_IMG_TWO_FILES) || ((header_mode == IMG_ONLY) && (img == IMG_BIN))) + { + if (argc == 4) /* In case ROMC is needed */ + { + fname_in = *argv++; + fname_out = *argv++; + fname_hdr_out = *argv++; + fname_romc = *argv++; + + if ((0 == strcmp(fname_in, fname_out)) || + (0 == strcmp(fname_in, fname_hdr_out)) || + (0 == strcmp(fname_in, fname_romc)) || + (0 == strcmp(fname_out, fname_hdr_out)) || + (0 == strcmp(fname_out, fname_romc)) || + (0 == strcmp(fname_hdr_out, fname_romc))) + { + fprintf(stderr,"Error: Input and output images can't be the same\n"); + exit(1); + } + } + else if (argc == 3) + { + fname_in = *argv++; + fname_out = *argv++; + fname_hdr_out = *argv++; + + if ((0 == strcmp(fname_in, fname_out))|| + (0 == strcmp(fname_in, fname_hdr_out))|| + (0 == strcmp(fname_out, fname_hdr_out))) + { + fprintf(stderr,"Error: Input and output images can't be the same\n"); + exit(1); + } + } + else + { + print_usage(); + exit(1); + } + } + else + { + if (argc == 2) + { + fname_in = *argv++; + fname_out = *argv++; + + if (0 == strcmp(fname_in, fname_out)) + { + fprintf(stderr,"Error: Input and output images can't be the same\n"); + exit(1); + } + } + else + { + print_usage(); + exit(1); + } + } + + /* check if the output image exist */ + i = 0; + do + { + if (*f_out_names[i]) + { + f_out = open(*f_out_names[i],O_RDONLY|O_BINARY); + if (f_out != -1) + { + char c; + + close(f_out); + f_out = -1; + fprintf(stderr,"File '%s' already exist! override (y/n)?",*f_out_names[i]); + c = getc(stdin); + if ((c == 'N')||(c == 'n')) + { + printf("exit.. nothing done. \n"); + exit(0); + } + /* for the Enter */ + c = getc(stdin); + override[i] = 1; + } + else + { + override[i] = 0; + } + } + + i++; + if (i == 2) break; + }while(1); + + if (header_mode != HDR_ONLY) + { + /* open input image */ + f_in = open(fname_in,O_RDONLY|O_BINARY); + if (f_in == -1) + { + fprintf(stderr,"File '%s' not found \n",fname_in); + exit(0); + } + + /* get the size of the input image */ + err = fstat(f_in, &fs_stat); + + if (0 != err) + { + close(f_in); + fprintf(stderr,"fstat failed for file: '%s' err=%d\n",fname_in,err); + exit(1); + } + + if ((fs_stat.st_size > BOOTROM_SIZE)&&(img == IMG_BOOTROM)) + { + printf("ERROR : bootstrap.bin size is bigger than %d bytes \n",BOOTROM_SIZE); + close(f_in); + exit(1); + } + /* map the input image */ + buf_in = mmap(0, fs_stat.st_size, PROT_READ, MAP_SHARED, f_in, 0); + if (!buf_in) + { + fprintf(stderr,"Error mapping %s file \n",fname_in); + goto end; + } + } + + /* open the output image */ + if (override[IMG_FILE_INDX] == 0) + { + f_out = open(fname_out,O_RDWR|O_TRUNC|O_CREAT|O_BINARY,0666); + } + else f_out = open(fname_out,O_RDWR|O_BINARY); + + if (f_out == -1) + { + fprintf(stderr,"Error openning %s file \n",fname_out); + } + + if (header_mode == HDR_IMG_TWO_FILES) + { + /* open the output header file */ + if (override[HDR_FILE_INDX] == 0) + { + f_header = open(fname_hdr_out,O_RDWR|O_TRUNC|O_CREAT|O_BINARY,0666); + } + else f_header = open(fname_hdr_out,O_RDWR|O_BINARY); + + if (f_header == -1) + { + fprintf(stderr,"Error openning %s file \n",fname_hdr_out); + } + } + + /* Image Header */ + if (header_mode != IMG_ONLY) + { + hdr.blockSize = fs_stat.st_size; + + if (opts & R_OPTION_MASK) + { + hdr.ext = 1; + } + + /* for FLASH\NAND , we have extra word for checksum */ + if ((img == IMG_FLASH)||(img == IMG_NAND)||(img == IMG_SATA)||(img == IMG_PEX)||(img == IMG_I2C)) + { + /*hdr.blockSize++;*/ + hdr.blockSize +=4; + } + + /* in sata headers, blocksize is in sectors (512 byte)*/ + if (img == IMG_SATA) + { + /*hdr.blockSize = (hdr.blockSize + 511) >> 9;*/ + } + + /* Update Block size address */ + if (padding_size) + { + /* Align padding to 32 bit */ + if (padding_size & 0x3) + { + padding_size += (4 - (padding_size & 0x3)); + } + hdr.blockSize += padding_size; + } + + /* Align size to 4 byte*/ + if (hdr.blockSize & 0x3) + { + printf("hdr.blockSize = 0x%x fs_stat.st_size = 0x%x\n", hdr.blockSize, fs_stat.st_size); + bytesToAlign = (4 - (hdr.blockSize & 0x3)); + hdr.blockSize += bytesToAlign; + } + + tmpTwsi = malloc(MAX_TWSI_HDR_SIZE); + memset(tmpTwsi, 0xFF, MAX_TWSI_HDR_SIZE); + + if (opts & M_OPTION_MASK) + { + if (fname_twsi) + { + int i; + unsigned int * twsi_reg = (unsigned int *)tmpTwsi;; + + f_twsi = fopen(fname_twsi, "r"); + if (f_twsi == NULL) + { + fprintf(stderr,"File '%s' not found \n",fname_twsi); + exit(1); + } + + for (i=0; i<(MAX_TWSI_HDR_SIZE/4); i++) + { + if (EOF == fscanf(f_twsi,"%x\n",twsi_reg)) + break; + + /* Swap Enianess */ + *twsi_reg = ( ((*twsi_reg >> 24) & 0xFF) | + ((*twsi_reg >> 8) & 0xFF00) | + ((*twsi_reg << 8) & 0xFF0000) | + ((*twsi_reg << 24) & 0xFF000000) ); + twsi_reg++; + } + + fclose(f_twsi); + + twsi_size = ((((i+2)*4) & ~0x1FF) + 0x200); /*size=512,1024,.. with at least 8 0xFF bytes */ + + if ((write(f_out, tmpTwsi, twsi_size)) != twsi_size) + { + fprintf(stderr,"Error writing %s file \n",fname_out); + goto end; + } + } + } + + tmpHeader = malloc(header_size); + memset(tmpHeader, 0 ,header_size); + + hdr.checkSum = checksum8((u32)&hdr, sizeof(BHR_t) ,0); + memcpy(tmpHeader, &hdr, sizeof(BHR_t)); + + /* Header extension */ + if (opts & R_OPTION_MASK) + { + int dram_buf_size=0,code_buf_size=0; + + /* First we will take of DRAM */ + if (fname_dram) + { + int i; + /*unsigned int dram_reg[DRAM_REGS_NUM];*/ + unsigned int dram_reg[(512>>2)]; + + f_dram = fopen(fname_dram, "r"); + + if (f_dram == NULL) + { + fprintf(stderr,"File '%s' not found \n",fname_dram); + exit(1); + } + + /*for (i=0; i< DRAM_REGS_NUM ; i++)*/ + i=0; + while (EOF != fscanf(f_dram,"%x\n",&dram_reg[i++])); + + fclose(f_dram); + + /*dram_buf_size = DRAM_REGS_NUM * 4;*/ + dram_buf_size = (i-1)*4; + memcpy(tmpHeader + sizeof(BHR_t) + sizeof(ExtBHR_t), + dram_reg, dram_buf_size); + + extHdr.dramRegsOffs = sizeof(BHR_t) + sizeof(ExtBHR_t); + } + + memcpy(tmpHeader + sizeof(BHR_t), &extHdr, sizeof(ExtBHR_t)); + *(MV_U8*)(tmpHeader + header_size - 1) = checksum8((u32)(tmpHeader + sizeof(BHR_t)), header_size - sizeof(BHR_t),0); + } + + if (header_mode == HDR_IMG_TWO_FILES) + { + /* copy header to output image */ + size_written = write(f_header, tmpHeader, header_size); + if (size_written != header_size) + { + fprintf(stderr,"Error writing %s file \n",fname_hdr_out); + goto end; + } + + fprintf(stdout, "%s was created \n", *f_out_names[HDR_FILE_INDX]); + } + else + { + /* copy header to output image */ + size_written = write(f_out, tmpHeader, header_size); + if (size_written != header_size) + { + fprintf(stderr,"Error writing %s file \n",fname_out); + goto end; + } + } + } + + + if (header_mode != HDR_ONLY) + { + char *padding = NULL; + int new_file_size = 0; + + if (img == IMG_BOOTROM) + { + char *tmp1; + int tmpSize = BOOTROM_SIZE - sizeof(chsum32); + + /* PAD image with Zeros until BOOTROM_SIZE*/ + tmp1 = malloc(tmpSize); + + if (tmp1 == NULL) + goto end; + + memcpy(tmp1, buf_in, fs_stat.st_size); + memset(tmp1 + fs_stat.st_size, 0, tmpSize - fs_stat.st_size); + fs_stat.st_size = tmpSize; + + /* copy input image to output image */ + size_written = write(f_out, tmp1, fs_stat.st_size); + + /* calculate checsum */ + chsum32 = crc32(0, (u32*)tmp1, (fs_stat.st_size/4)); + printf("Image Chacksum (size = %d) = 0x%08x\n", fs_stat.st_size, chsum32); + fs_stat.st_size += sizeof(chsum32) ; + + size_written += write(f_out, &chsum32, sizeof(chsum32)); + + if (tmp1) + free(tmp1); + + new_file_size = fs_stat.st_size; + } + else if (img == IMG_HEX) + { + char *tmp1 = NULL; + + f_hex = fopen(fname_out, "w"); + if (f_hex == NULL) goto end; + + int hex_len = fs_stat.st_size; + int hex_unaligned_len = 0; + + switch (hex_width) + { + case 8: + hex8 = (unsigned char*)buf_in; + do + { + fprintf(f_hex,"%02X\n",*hex8); + hex8++; + size_written += 1; + hex_len--; + + }while(hex_len); + break; + case 16: + hex16 = (unsigned short*)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x1); + + if (hex_unaligned_len) + { + hex_len -= hex_unaligned_len; + hex_len += 2; + tmp1 = malloc(hex_len); + hex16 = (unsigned short*)tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + do + { + fprintf(f_hex,"%04X\n",*hex16++); + size_written += 2; + hex_len -= 2; + + }while(hex_len); + break; + case 32: + hex32 = (long*)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x3); + if (hex_unaligned_len) + { + hex_len -= hex_unaligned_len; + hex_len += 4; + tmp1 = malloc(hex_len); + hex16 = (unsigned short*)tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + do + { + fprintf(f_hex,"%08X\n",*hex32++); + size_written += 4; + hex_len -= 4; + + }while(hex_len); + break; + + case 64: + hex32 = (long*)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x7); + if (hex_unaligned_len) + { + hex_len -= hex_unaligned_len; + hex_len += 8; + tmp1 = malloc(hex_len); + hex16 = (unsigned short*)tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + do + { + fprintf(f_hex,"%08X%08X\n",*hex32++, *hex32++); + size_written += 8; + hex_len -= 8; + + }while(hex_len); + break; + } + size_written = fs_stat.st_size; + if (tmp1) free(tmp1); + fclose(f_hex); + + new_file_size = fs_stat.st_size; + } + else if (img == IMG_BIN) + { + char *tmp1 = NULL; + int one_file_len; + int hex_len = fs_stat.st_size; + + f_hex = fopen(fname_out, "w"); + if (f_hex == NULL) goto end; + f_hex2 = fopen(fname_hdr_out, "w"); + if (f_hex2 == NULL) goto end; + if (fname_romc) + { + f_hex3 = fopen(fname_romc, "w"); + if (f_hex3 == NULL) goto end; + one_file_len = (hex_len / 3); + } + else + { + one_file_len = hex_len * 0.5; + } + int hex_unaligned_len = 0; + + switch (hex_width) + { + case 8: + hex8 = (unsigned char*)buf_in; + do + { + tmp8 = *hex8; + if (hex_len > one_file_len) + { + for (i=0; i> 7)); + tmp8 <<= 1; + } + fprintf(f_hex,"\n"); + } + else + { + for (i=0; i> 7)); + tmp8 <<= 1; + } + fprintf(f_hex2,"\n"); + } + hex8++; + size_written += 1; + hex_len--; + }while(hex_len); + break; + case 16: + hex16 = (unsigned short*)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x1); + + if (hex_unaligned_len) + { + hex_len -= hex_unaligned_len; + hex_len += 2; + tmp1 = malloc(hex_len); + hex16 = (unsigned short*)tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + do + { + tmp16 = *hex16; + for (i=0; i> 15)); + tmp16 <<= 1; + } + fprintf(f_hex,"\n"); + + hex16++; + + size_written += 2; + hex_len -= 2; + + }while(hex_len); + break; + case 32: + hex32 = (long*)buf_in; + hex_unaligned_len = (fs_stat.st_size & 0x3); + if (hex_unaligned_len) + { + hex_len -= hex_unaligned_len; + hex_len += 4; + tmp1 = malloc(hex_len); + hex16 = (unsigned short*)tmp1; + memset(tmp1, 0, (hex_len)); + memcpy(tmp1, buf_in, fs_stat.st_size); + } + do + { + tmp32 = *hex32; + + if (fname_romc) + { + if (hex_len > (2 * one_file_len)) + { + for (i=0; i> 31)); + tmp32 <<= 1; + } + fprintf(f_hex,"\n"); + + } + else if (hex_len > one_file_len) + { + for (i=0; i> 31)); + tmp32 <<= 1; + } + fprintf(f_hex2,"\n"); + } + else + { + for (i=0; i> 31)); + tmp32 <<= 1; + } + fprintf(f_hex3,"\n"); + } + } + else + { + if (hex_len > one_file_len) + { + for (i=0; i> 31)); + tmp32 <<= 1; + } + fprintf(f_hex,"\n"); + } + else + { + for (i=0; i> 31)); + tmp32 <<= 1; + } + fprintf(f_hex2,"\n"); + } + } + hex32++; + size_written += 4; + hex_len -= 4; + + }while(hex_len); + break; + case 64: + fprintf(stderr,"Error: 64 Bit is not supported for binary files\n\n\n\n\n"); + break; + } + size_written = fs_stat.st_size; + if (tmp1) free(tmp1); + fclose(f_hex); + fclose(f_hex2); + + new_file_size = fs_stat.st_size; + } + else + { + + size_written = 0; + + if ((pre_padding)&&(padding_size)) + { + padding = malloc(padding_size); + if (padding) + { + new_file_size += padding_size; + memset((void*)padding, 0x5, padding_size); + size_written += write(f_out, padding, padding_size); + + chsum32 = checksum32((u32)padding, padding_size, chsum32); + } + + } + + new_file_size += fs_stat.st_size; + + /* Calculate checksum */ + chsum32 = checksum32((u32)buf_in, (u32)((u32)fs_stat.st_size - bytesToAlign), chsum32); + if (bytesToAlign) + { + memcpy(&lastDword, (buf_in + (fs_stat.st_size - bytesToAlign)) , bytesToAlign); + } + chsum32 = checksum32((u32)&lastDword, 4,chsum32); + + + /* copy input image to output image */ + size_written += write(f_out, buf_in, fs_stat.st_size); + if (bytesToAlign) + { + size_written += write(f_out, &lastDword, bytesToAlign); + } + + + if ((post_padding)&&(padding_size)) + { + padding = malloc(padding_size); + if (padding) + { + new_file_size += padding_size; + memset((void*)padding, 0xa, padding_size); + size_written += write(f_out, padding, padding_size); + chsum32 = checksum32((u32)padding, padding_size, chsum32); + } + } + + /* write checksum */ + size_written += write(f_out, &chsum32, sizeof(chsum32)); + new_file_size +=4 ; + } + + + if (size_written != new_file_size) + { + fprintf(stderr,"Error writing %s file \n",fname_out); + goto end; + } + + fprintf(stdout, "%s was created \n", *f_out_names[IMG_FILE_INDX]); + } + + +end: + if (tmpHeader) + free(tmpHeader); + + /* close handles */ + if (f_out != -1) + close(f_out); + if (f_header != -1) + close(f_header); + if (buf_in) + munmap((void*)buf_in, fs_stat.st_size); + if (f_in != -1) + close(f_in); + return 0; +} + + +void print_usage(void) +{ + printf("\n"); + printf("Marvell doimage Tool version %s\n", DOIMAGE_VERSION); + printf("Supported SoC devices: \n"); + printf(" Marvell 88F6082 - A1\n"); + printf(" Marvell 88F6180 - A0\n"); + printf(" Marvell 88F6192 - A0\n"); + printf(" Marvell 88F6190 - A0\n"); + printf(" Marvell 88F6281 - A0\n"); + printf("\n"); + printf("usage: \n"); + printf("doimage [other_options] image_in image_out [header_out]\n"); + printf("\n - can be one or more of the following:\n\n"); + printf("-T image_type: sata\\uart\\flash\\bootrom\\nand\\hex\\pex\n"); + printf(" if image_type is sata, the image_out will\n"); + printf(" include header only.\n"); + printf("-D image_dest: image destination in dram (in hex)\n"); + printf("-E image_exec: execution address in dram (in hex)\n"); + printf(" if image_type is 'flash' and image_dest is 0xffffffff\n"); + printf(" then execution address on the flash\n"); + printf("-S image_source: if image_type is sata then the starting sector of\n"); + printf(" the source image on the disk - mandatory for sata\n"); + printf(" if image_type is flash\\nand then the starting offset of\n"); + printf(" the source image at the flash - optional for flash\\nand\n"); + printf("-W hex_width : HEX file width, can be 8,16,32,64 \n"); + printf("-M twsi_file: ascii file name that contains the I2C init regs set by h/w.\n"); + printf(" this is used in i2c boot only\n"); + printf("\n - optional and can be one or more of the following:\n\n"); + printf("-R dram_file: ascii file name that contains the list of dram regs\n"); + printf("-P nand_page_size (decimal 512, 2048, ..): NAND Page size\n"); + printf("-C nand_ecc_mode (1=Hamming, 2=RS, 3=None)\n"); + printf("-L delay in mili seconds before DRAM init\n"); + printf("-I copy image in PIO mode (valid for SATA only)\n"); + printf("-X pre_padding_size (hex)\n"); + printf("-Y post_padding_size (hex)\n"); + printf("-H header_mode: Header mode, can be:\n"); + printf(" -H 1 :will create one file (image_out) for header and image\n"); + printf(" -H 2 :will create two files, (image_out) for image , (header_out) for header\n"); + printf(" -H 3 :will create one file (image_out) for header only \n"); + printf(" -H 4 :will create one file (image_out) for image only \n"); + printf("\ncommand possibilities: \n\n"); + printf("doimage -T hex -W width image_in image_out\n"); + printf("doimage -T bootrom image_in image_out\n"); + printf("doimage -T sata -S sector -D image_dest -E image_exec\n"); + printf(" [other_options] image_in image_out header_out\n\n"); + printf("doimage -T flash -D image_dest -E image_exec [-S address]\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T pex -D image_dest -E image_exec \n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T nand -D image_dest -E image_exec [-S address] -P page_size\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T uart -D image_dest -E image_exec\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T pex -D image_dest -E image_exec \n"); + printf(" [other_options] image_in image_out\n\n"); + printf("doimage -T i2c -D image_dest -E image_exec -M twsi_init_file\n"); + printf(" [other_options] image_in image_out\n\n"); + printf("\n\n\n"); + +} + + +/* 8 bit checksum */ +u8 checksum8(u32 start, u32 len,u8 csum) +{ + register u8 sum = csum; + volatile u8* startp = (volatile u8*)start; + + do{ + sum += *startp; + startp++; + }while(--len); + + return (sum); +} + +/* 32 bit checksum */ +u32 checksum32(u32 start, u32 len, u32 csum) +{ + register u32 sum = csum; + volatile u32* startp = (volatile u32*)start; + + + do{ + sum += *(u32*)startp; + startp++; + len -= 4; + }while(len); + + return (sum); +} + +void make_crc_table(MV_U32 *crc_table) +{ + MV_U32 c; + MV_32 n, k; + MV_U32 poly; + + /* terms of polynomial defining this crc (except x^32): */ + static const MV_U8 p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(MV_U8); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (MV_U32)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } +} + +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +MV_U32 crc32(MV_U32 crc, volatile MV_U32 *buf, MV_U32 len) +{ + MV_U32 crc_table[256]; + + /* Create the CRC table */ + make_crc_table(crc_table); + + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + + if (len) do + { + DO1(buf); + } while (--len); + + return crc ^ 0xffffffffL; +} diff --git a/u-boot.bin.410 b/u-boot.bin.410 new file mode 100644 index 0000000000000000000000000000000000000000..78c9cf4acd990d2a8a59dce05c45cff7c780d2f5 GIT binary patch literal 466724 zcmeFae|%g;z5hRFe=nkC)}yNV&tFXc@`US@;Lll-wejKq70iDP|NEp# zliHkThQG^Sdk`Dbuzk3x%Dg>6Y%&d}*ASm@tW#G@{H7XX(!@^zwn63mHHC2t@u^kD zxWwm@-%32Z&zMBx_Tl}*!xL(V$xhc2|AFU*;Muf<@p=oV!)&mzF`I}d>@lXB*ilFS z|6e5q{xZ>+!G?YP<->(;CvOUbY%Fg)f{Eu%o-jao>EW;bI^dVQ**AQhd1~DC#+V7k zW6Xg6tm*d6zBd<-G-hatxww=`A5(Trt_Y{4+TCNy?U`fBG576-nA=@=rF!e0SE@h1 zCr0^ShlhW$&>U0lHrZ0`_G~FnI!{~UdcJYH%L&t65**b_>^r91ar8ANJt4iOc)1pEze0RDSI_}g9w{+>g?f8`Cp ze@h6z_1V{^&n(JE(`Uhy*Qd|85Pt9Lz~6ER_z%7T_$GuuJi(ar#z+h#5C0hU&-DDI z>Hf0GE-#OFz2Xv^zOCGp?e+6v{(>-%_Wq;^r|g}R?Jv&>%Vv?D6{csBo*Aa=ki!n8 z^S70c$^X!A$glFJ+2`fu;o;%ISRs(nZWG%+)rsxb8dNaOeyu@mJQJCA;zX6Re|(?C z+b>K6o>^XI`58hF4b9Gb{&wZ%mzTGZemqPw*r73!*{^uM<6Tku8!{~!7M#tt&TVBE zd^UvjlUss%(l@K4a&v_L=i%X0W!d6`%bF|8W`$)n<}$Tw?#+9}YzTkn@bJ*Is2p0j zVgAp^Zwm8W`a}1O^oJg7Hd)XA1Um1DG-`4O(`!{=-W>m$_Z4fASgyDV(Gg#4~iZLLhe+Y7?B z^Hkn-TfqP1r@^T`Y`>890q@^d7EW%Me;N4=A>5i^yv^d{xS$rh;1Y$_+sdy2?NbKG1~9Ba%Blj$qhx_#wX zrl;U!-d<8Z3+u)N^_7N~W~6DSGi~ftyPS;0(eKrcm(58?Tt@{vMXtCBDgc zwDF4IFrN7WdxQ-KU&z&ZF>-n_}{n!ljH_2f=%=t;it>;&;5t5X@+8pFR z!+4dylYF)NW0)V+e>|+eFU%DecnY`BCmP&{OXM7r~5p=iuUcf zvE{Z5Fo>x)=wv-VPQBQG=O;wZsNMkeveYBqM7_?_Y7epWy)8%`cR)y z*#^p#R=Mh`P7QU`pJ*c9I5C_bllJ@DIwu`3X};RrN#HpNel-P^)psnnWpQ(b&(?zZzrs(P+Mjglo~?$DQ!zagvnC9_ zIK98@Oz$aV)6c@s&?DoNVy;u_$#})P(>=xQPJj77)8ZM=e;?(7$=q0&!cVXSlVx+z z1J*Rg34Z3;@-*lUzJt@i)ydS-Pi@eT+f#&R>^Q{-|G`)Vr|yg~ z1&w`-JAj-)<4jL+I2$j)uf-cgt9-7MNPBe|r@s-M-b}hU6@2?GzVm%-@l+LgqT%h- zZ_7X@;Hv+Hlj8-I#WMr8yb^Y&VCR5M`<({)pxzo_I?&+F;IHS$$zMqx^HgjlFP*-# z{2+NRvsN3=^HY8BD`i{IR}CS5Ucq_=FZklYWF8(O79Xmf^k^!q_b%1T!nfp0k0!$W zcayI?*%`xc3gq~zFfT{mU&6er$$Kw&v~HhW+V{1)_H@6a)BJ8@r&&pSE8%A6IK`w2&!*J;isypwP#;Yz~QgzE`bFEJ1M&`pwK>8E%WSupF$HPSPbDc|Hh^yvC> zyfQE66>G`+J7Y*fH#5~MRxyTSiT7L{=(v5MjuV_rsQ&~{ebk`e)X!ep+dilxc~Un_m#~tMxfd3%yrAsvDag&xFYIe+0pS7f(b+X>cc&HBPAnND z(kma(@XX4*kcOv*G(14RJIm{Vz4(7XKT|*^C6*y^Qn50u`eVC43iDd?M!(W3L*Yjs)W|!jbz;1k2rI&_>Pt=;M zJSV%d6i@$jcL(r43w*1?LY?HuF3Wh&I+^$*f-nAPqTVseC%uCDF8q;zmP6VDP_`sH zyY$o$bHrF*hPQSdiS3)Y61(wI&2jVlNiQRfO=NBHh@VcAK7k%C_(FF-##my&SR%YL z&+JzJvTepd?}V9KkDgA|lO9icJn5rIH<1?4A4^(1KAkqP>0X? zbe#0^lEXYrrH#)RppV7PHZAymlVr6(6*)zKR#-zylv4cm(O#S+~G@ z+d9n-p7*@4*!+@M{C_iT#p|n~ht{t4bS)LxyvhV z;`u#1d#8eTEAt3{7`F%ii{wrA>h0xj*YkU+_l*^1NVf4Z(#l&3jC;xJ;(2JCc+vAe zA|F*>uGC`8cjf@|805-O*J$r&yyCU=bxdYQ8U84C#QGcU`pxqd%yWk4aq5%xGoGt2 zwek#KG^h1!>cP#V9P?2>O+GTzTpQL~K)wNoC&5ATCVTQnq?7cg^d9(p4{PI<@V4|R z<4Wxy?>X`=3-dC->pLfyyQ)ii3$=_pk@1S3o^noU_=IyypJh%Y>yq=Wz*b!4ibh`X zH0H9g+6?uvkBH+3KMMGDJokpr+SiZcd0F_(x|gwhBC>^!@PD81R(+)lL2w%Ed3Sgy;XE9vgx3 zPmnKo%3lpXcEgJ~U@A{^bkXg}aLiA^vswqApB~KRfa!1iJo5Mua25kcFlGWnvd|8k zw*hA}Wmi+?5nn~TiTK^b8;HL$h|VYO1MdDKf_d7=9^qE(De?aBaP=$V|Ma-)%;47+ zn@#Zimk3V~ULs7m09hbhMUX7Zp6a=((|m>J6?tQNt|kyKzs8ugr27cngdeLu;V*>e z9qJIbytC7E5Z+1HO4zx!)68vnFY*`oYs6#ng|xWH5Nm(p)D`6#LM@?z&_rkci#7RM%CX~Dm1+li3ueH(WbTC7r8$qW?hf2i zo;3ij#2dluxn|KL(EB^#nVs;=LkaSUwLida9Q+A&kVV;V&D+S^M%jJTxtH`qq_>iu zGtn8Ed-3ejiMiP&4aFFb4KP(;d&sqzik=C8| zEIt%y+Ri$tz4PranxQ7vpDuLxv@<%5b6Ka6O>zS9$%HL8EjHH?e~>Wmlk9hizee~S zVK}~hICgob`P;%y^GV_<3p&jtLOWqU;rw@Xn)!q?-`!~z+}LSqGomB547yZ)yu9`z zX0crxw4TX^(0Z24271fR%Ta;NX4g0H*LV9QryfhqH`Lx&S_n14fC|l$bJwHoX)&!d{x-5KgV|6$9SYeq(7EI`&ERE zgs%~PK#;84H7Jzze#Ro6mk!;eG-F*8jK6q1Ji62NIj^X-7<;K1zk}~UTjP5E9jpPG zBgeJ=2!AclmE}8G6DrG}t9Y&j&Z@Az(t@#_a>rcmLnqeJ%Y5v``Z#I9s1ED=h&u9# z#wbIMY?<_y(wGZ3n@=^WiENbpy`iq@`x?+IxI6eMR}7p@ry| zrryzEJ?6Q&Wu)GtwjOp=dA}3Pf%@8x9-cU=uL1JLg?XL8cy4mgmlO8Il4|?X`BS{2 zudO5Xg1)w(^H2V}-76P8(we(x!oHEm)I8eD?$!K5+mxMu^7e*#(5f+=d9)tg)GWHC zGvWN>E3G@_?7i9PoL>TWYF$sc2|w+3L)c>l3phJNII{f&TYH_Khk07h>|C@xicFZn zAPp@;JhxQf`5^6{7=@?&r`syB$_=bNGW^p)iX_sVid#`ABR;udPb zH98a0x}!CxChHa5%m%wQX%0V&E_6+A*)Y&NF4lpkpTWm*0;~)rYOIXl#G^EX^G}r8$;9&yn{H#g{+0Rxjf&~ z6xcMfuUNBEvR$nHB|a5eZ*69sa=p4O&Hc&iPxj)mtmnYngByUW^7SWzKV!c6o$OJ_ z?+)|3$-j{NW#lutgYT3L25nDG&n_)UF@|hU`2&oBFfb$~hpQsPk z0_o<5$ln*Xi{|1f@`fs4JxH7NA*_2zcawe#u(ptXr~+0O`M(+kOLd>CfVGr1vqD&l zNw<-n3amWoFNd(CN9K|L8o3t_pWr;=_2Rx9Z{D)4%)slWWKQLy%q z_st4e`)aUL$rHVHk={f)2CSW=dn#b{lD~Nrtfl1jSHRjrn}s2)O{5o)ehL0tPr9oD zRy+B(je<3myqm+k^ zP5QzLT<$0TgJC=Ei6!5vdwrNEUfEgQU+yIjSs8qsbT{d518acvQqm8QevtHH()W?x zO1iBAU)7mE3f~U$auxXAK%1%LX&$;rH<0##wV3o|!NPu$+C;jrUY_mWoKFITflr5p`e$v0KDBH~QX39D# z^GN@uqO6bSKFZ!h+0CS%uPD2L=Nl-yoU&!4p9{;7<>nL~t6Mf*8C z&!PSKl+7ajctu$|&+U|DDQhGBgNm|No?9uC&UZg{94lYRg}G&>@UCC zh!2mlS4iJmQMQNYJ(RUlwu|%^R2J%~2J(N%9#XW7^i(T(KM3=*W^AR+i`;j>A2zs| z^mC-^fVGKwb+zn~(X;ExzZJNBhVfK*D zQNON*I}`BDEYcsZ7*jjX?bLmVvY83wKOB?Rop$iMjrNseno8cyVIFHsv!VU9Aw2o# z_5oubb&`y67wLr+eeK{`W8OhuO3$w-+s5-Y%ATfdfb>NbWm|dPO4$!7yO;F&6=j=v z-bC5=RmPqo8xIOz&=;OJ&&uzrr3kj@~-g z#eczk=DTK>u3l<}&NWw-|Bl}HS8sM{`#H|gIXn;N>PpIs<-GWRl6Q9YO61-vX0fe? z^L3>G`qv&=d$+M>e%#1kl3N)|X1wA&_z3%;sPqQvrD&(}i^#v3vH$7s2V}k)JeHC7 zA;zLT+8@z9vNzZxurKud--XYb>v`1MQ_)ub#4LHz`5nZ?in3`uPowX5Q8tzIFDlBK zcy6L>E@cg*pRFiM@SLD*w(ueSR7Kf7_9)t`&7^D>Y56d=sXVKFHfI@(b1Jrs&a2VS zsd4B)-P;*BmAaJ2&11Xe%h1@SX1S*l_?~_C^b@N%7va3IS$nmwSM<4>=XUlCC(vg% z=`9syT|9Szk4xDS(x0y=TgdZ5%HBlT0@52R%4YGr3;W#aeCD_gIzJ7aHI58rx2i7p zIkcwTPra?&H;QCXKAFwreI?9;Z<}9bZ*ntve}_kPHm&h7UxT~Izk&Q$$luAHNPYzQ z^YM=i9s@l%pa59ty=p6MmMqP!V6 z@NnJ3f8i|5q>K2qlP1@bbhmS^a_?Pxde|SxFSU(0+G}W^@eI%Jes8C_4aC+GcJk~K zbmpkNi1s1cpX?^@CBp9r<~zZDBiegtFQR?P9|-X)JI#2)k%XfO#}Q5;oJBaFa4F$x z!utsyB7BN)6JZ@;BjL-0uMxgYc!cmY;dg`>{J-yl3f_z9sz_%k8#p1@Z(mUsu@dBP|0K`;3m_gaWe+U)OYF#B&MJw1>Ans_VW zVM2lMBHa<0{=#|0@((T|{t#gqLB6$w`x%=cN@I~UEY$4puIZO+>%4BaTFNR;>6ML57%|%DD-->a!FAk5kke-7t>|31U z&dR9XhH?Wu;dF?vHn5LhQLZ|pmwSSo?__#+IkoeA-4!g--z#ql{M2KCAw83ZU$lqy zRypQH?)OY!ffTMfKa2K$PybCa5y-(j@Y-wdNgY^UXOj2AfxPB++RmvC^q6c4#6DUnbVs&F_dk;(f$AyV*;; zf%rvY`N#)}`-t}ti%!2GUQN7}nlmW27z@w3R+URLya8kmN0{2^urHReAtj>%VdnmL4z6YeHFP53P#eNCrnBV10X zq}L~SUQLM3cjS9U!CBw4_7xAFmNx^0#|hgB&k?o|GW4%A9;YTa4{8mc-7szmR$LIc5JZUv8dvT^jRdBk@;GA}#e3HThJdvJFaUO63qOM8rGaDv^u zdih_b(&h>3%CFt(vS!stKJ*Tb?rnN?s>5DrfA`hFxfpMB?U!F$=VR(K;)7oU!v%)g z!n3KDGCi!PIh_-5{*E31j`&gW=(a!kKeW|7mH%zO-=OWZ5NF9>gtPG9Z|_ULG5q_1 z6PzF9isDu1z9t>E7mu=D4`#xC^c?l0{Q&eC98DkSZs`=!InCYgnrvU$4D^*9cV?+J zQ-H>o7C951QB%0BY|L%sUxa=Q^1)$7!o9gLKGR)r(&v_fyWb0$i%V~#Ppi;D=CaOvr#TsKiV4y^IzyseJ^WZ#n^|G+ znA1nmxYTo1&!&4AkM4{^o19;h>Hles>3_^P>wd1hjx##Vo!4|CS2^9&OF8LtO2*U` zbuJ^?c(naIy2vqg_8kR#KZdv3z{R1Q{k|EzC!_Lu|5etM=v<4}$*g=(uP8k*x(@xs z7>k7gz5cP>bjKq2-Qb}9g@@jg5Z)2|NPkLqnk@BlUhzNS2YXiL$_@|iC+j|nY|YKo z5e)kF>(AACGOx&4+jQyON*|}*sj)D*zo0RJV{;p_`fL2-nRI`7d~Cos_}&cnN2k4w zy)3e;=UfIK|MVU|$C|4$!JLNf&LP8Fu7(oCk*Em5P z$yr(eN-|Y4$ zJ@)`UvGzyfoGI1IcOiUwDetZ*uL0j0@YT7i$`?`2{il)f#5!o-(NoX8PFp^c@@z%9 zOM930l5@2uZg#_Ya?S{7ulcDR$qVK#nzKkg#ov-ACp)tw8I^4^7Cx%g{*XCR|9#BM z2Es#x)fM5nFnxa*Zwuq6h>-<*_sX5_74biU<9r|4j>pbqeKqx#->FkCdGXq1KkNMh zdp}~(YYTLfcdGPD+}`hYXBgo->gC z@=v*sC|#p-WYv)^Cm0FpETGP?N!q?@Sj!{&2<~sy4muU7lc?#o`bd1tWq-@ZSAqNH zj=b4MSo+qyd4=#Gp(af0d0v=aPptWx1OLu~f1BW6LL=`d#ABS%&9Jlz_;>0E|3bGD zz4|80zblGK>eP;u!P_Sm!m?PQse&h2Q=4}&Zu}blZSgp3p654B?kiVegVaq~!99I5 zxb3jzj})6GcaQM*Cirgy{1@Ttbo9iXjz@JL(emF7lrO6&M;4LCN9)yx#=DU61r_D+ zHvIi)eG~d5;K{lEa^^#FE88#`-c@Xx-dCPDy{FhTJ-|hFU{JF?2e zy@hu3na5Pf*D3JIzb$VT6Z!}X2wTEfX@%8cyn)#Ans_y%JMaNN$7Tfg+2in!$;5eI z`qBdREKj@eF!s`*_@4>4Jk8xw?1d?o$5sNzak&G}TuhuoUEb}fY~K{}c(fLENyo!) z$O~qZ=eIJJ{WH6*59b)tvQG`+*xGLYSiP&xnkU(+v z-IYb2*EnbBUA~+>1JpYXi^FnwD)mx(V0WYYo3$sBU6G?-&5`!SdPc{VFQI>}0kS2O z*G3-iuMX;-sh)M$l=lw?mHr_(h<2iLj9V=+tp8^^JI#aO`zYbZg#Qk4UxIHddcSWT z^FCnkALKpXgC>u0uPjITEb^C-{{x=4vq#pwmL+x2(+l3I`Rzo~_%H4F83*@SitnyjCcw$^k{xQESqrbw)zRDCMRN7HV=h)!>x&l!)=dg zy=fMI>mCa-V*9u$>|84q#z)M0R)1+Iw-Tu%ydee>(!I)(D;3S0}|Dw;;`g>|uq*hY}u810#&eY)yN z@7BO8Y4$s$mkUqXMA+~o?f!-Jk>^;Tmt#}AOKP{jbp?0j*Os}jMjYtxe=OtfN?3M~ z?82jtov&c+oD8oeW?};pw!J+Fb&N~*XC=#Hq47ALgZpa1_cq4x9LY9_rjk4_4C~wZ zJ~q&4vGx_ExQo6<$Kqcr*J!Wd26~Y>^mX4#`Gz1FK9IMZyyZ4;`CRt*yhz*w4SVvz z-o7imm*Ft)t!d<#G3id$HuS+b=y?=4ebfC}F*z5#UbC{)%AFg1=R@)kTd=Z(OcwXI zK|6fQuFBjy%F**3(kakqe`2M-PU*}Y<1{kl-CoU>BG-^f-Ii zbOGMed&9xKNzq<&9N~;y*}WJ(|DG0b&Y(A;S<0~Iiq-T6IL_)VEv0Xr!|2`L{fS;5 zS>xR-?%^5EPq}}jcfb?rm9*D;viPz;BzeyHli(q}^IuJjy~h~wr)E}`oiliMnYc=M z#E^7wDr0vt_3XpFdey1T++Nllb@Wb3Wv#$Hf%BVvteaD?1(9#)HMTsni@sdon3b#> z;N=#;@4%S5!+XP8^DEXLU++?uK99^sYn^;>i>~c7pX1%0e<8k&u!3;PqG0_?hkOTr@LtA+$f6m9&h~6y z=Q!MDviK!K{Dhn2Lw7K1uzR?Ry3u3{c8rlfS^OdYLj|4eJLf3rC#%Tk?opin*xLs8 zK{Zyp4$|LsVSkc2d+&?>q?0vw>@{U$kMzxZej|NH{%PzO@um1B;leZclw#~DxIYB%>0ApO(OI;y{QLvzyVOsZl_k+> ze#ooGQ$Gz1-Q{+fH|^t{%!;^^d8A%^W_Sl|JiI0u72Fnhv1wqE&Vy3J9q2dsCDtbS z<6Vi&qkiqFJw>(qGW{hc%2wc=?e^v9o}N;yX?aO9zQ19)m3xEk5nSmR=4()OmDhkC z>qakFzQ$J*(MmiW*|(an$d-^UZHHE?nXj?v>Q%(tYYY4=UHB)$`Ra}G@?P;%kql5Qv6 zK0tla9|eEmr2e`{3zuo)LHd@?P31f%+2=WuhiPUKI;-1%yYR{}58?CKdhQEgw9$4! z*cSedC%m9-TUfVEb+h=M!sm>hy`WF^eF4vcp}tu(IX}dH4B_d%O$OXGpH{E;_3%vs zaFWjF4!GpQroA5CnGe%h?p}sEQSGvBm=7%K=!cH*GQKBo3UxlLYJ(O z9@bfl`}g5N`4+WKCo)-EpYg1D0b5-3k}V^BqCI(6v_1oW8nVGVL(Q)uS0=x%{Fgru z56Sl<+XA{Zzlc752!0Yy1=9K+O#GdRQtNr>56%g?+5aRQY&ym}K)HP5)%fPzq-=~k zc1sppkvZULU05TYoXYv1)`_Em@225{0(cBa)(gJmyw$K)u-=)0mFTaP=$4h`bb6&d zXWkf&UHFVEcs=Z|*JOcNOTNkESTook10xR14&X>e+UTP;yRtlnZ)Md0Ck;$H*M;Ca zC6O(V!Qa`99TWKwHJ%aOn`1u>t!8olelPjw5o`U_-GR~T~}+^QQu`8-#URaM#_`WS^7gT*3e$^rL{+8 zx-X`6vzB%9zelZ`8?Ws&n^`x%Osw^CC9&4euM)%;`=Yh8i!~(xkt|Po}K_4@OL!2`Oy?+6J&Is_G=f4O&1S?uEB3X#~ z)Z9uAv}ZQCb>(*OzM(=6Wb6DzJeCd4l>bEfaB?t_3!$ieMa4$!?%YAh|`SirZr ziMbX1;CZ??gOcG0$I<*K**zS-wTHm>#})Yg=j-4r-}vG1-6uG~9FEYPHADEK+W&X> z7GC*B`rciEuYC5eMc+GL1K(|<@RjaFh7cX`s`r}o?TX}pd6vIdcBJ^?#ZW(f6TEj- z@WoE%dTEIFcG4ey4ZOEfetjk0S?R}l{$%(flMmk8t3qzpQ%7>m9>B`ho9JKfUn5uc zn+4+II(SHOr8;q7z)N;*klgX&jrGx}-bMH#v{q2QQ9fq$2I``K&%g|-?s?ecnp@~X z74=s@&jov9(?a^}BdvA$aPunqO+EyD-VA*- z7UBCW<$*rwj7PwSUF)*tM^4KSSU8(Av`w`g>lFe$hJxvITW- zW*Kmg7C%9+U6ZAEJikyEti8rvo^&%SCSw0K>V3^$(#KQOs|vqgX`G%i`)F*P`ONKn z>jT0*+L+>*Gn3{G)YW=k1$^#Q*>UK7O|6fQ3*W3)?B@9~(ubN4bm!p1lpW9sckI@< z+r)RQF%22dzx|#mg*10_v?tvu-%8%|J7_207X7TzUBWZPv(P$C+kLZxbst_y)+Bq9 zwS-fsZ)K}%UHO-P8XkJCLbeL4=1yw` zW3uz8H2iPz(wK(DpU8md#=2|mNAcP@p`O;6vVqSs%yj}-8F)rKrTKpZK9EmM^tj`m z##8vbEF#VS!8eM{#ImfYHgCuxi8X1UD#U8S3Ixp zK$tbvoEI?nYaD#%T9?MWyQkD8{lxosaoxQzD+~Lv?^$c{0YiHi-!AycH(LJ)zL@lY z<>^G`-z{An&Yf!0%j@bVE_dX=72YiYJpArnT|5Ik+2-k<@;=#@lq)thtiEHa4BvtC zW8j=9oK#L=ld<1j(<(Rx?cwkxAVY$q?`*yKZ9R6MX9jx6r_H{*b_s@HY24Ksclez* zCyO1D^NKFAl7;5y09R)v=&(3@-;@!L!|&2DV?KbN5#9Dx@h4-gU(X(`%M^BbK^^f@ zit;LaK?&wd^tqe5@M)nM{7z(!*G{<1{~hyoza2aJ_8jbG&iaoV-&;E2qF#LG-IlKF zY1bFlQF%PuTWB|dALtg!v^PnlS6JUqJ3g8ZzaPHm+>ME8mOVO+yffJ=Prz?84WEtt zML$;^=1==WJZbC^JkBmXUiJ4J;5Cw;O!Mw*x~nINo*5KRMf;R&s%n3BY}Ni~K19b6 zJ)IAHA+lAaUp8>($s?_G=62E>NUtN#u-~op@%)VYVUmFxDE|!Ql3_h3T-GPXD0z_` zCVOk4U?Wq^JKxlpR9=f5>)U6@R&gd}pQOEP`l{p1kjwMOd6o{TVeaIUmHfz`{!`M? z+9O}j1J`1oR``0p&$GrR9*B6vc*shhwTI&opBxJw;)m6mBgQQIJ87=KKJ@A||C;+L z8bcR6f}O~|BxQN#^dk$hZQG$mG*)=Vo_!|Ly(Nt~%Q&EYz4Ykuj8kioY|v;tvTwy- z;wA1jSsf6~(`Y`A=16vi$p^N^$&zcvH)fnyFJGbNMKnJ%r1|mWC0xBT9L&de$QKT- z#yrmRZ+0~om-+g>h?P0`Q{P#{H)Q2*?F82P^ty5!n0CyK%ZnzxqKyBk8U7r!`&-)2 zdc*C1Fw))$`7+>7?H>X=V)VG9xzoJGJjTxWHFpau)y2o^B+y5aS?v|} zCwhF@o9*a#`D>B6;`;XmYn9e7mQ}v%H@kExGAe(JU`#`Pks*h@SebpQ@p2rl>x8W%#D11dKUqkBKU?R^|*9pZCKV+#t`iF+Xm!ATxk8n)tTFO zYac6E85jTJz}T{2W;A!uQR}O8p>(7CVy(m<3}t{dx;cUVnA4?qm$3ct)kC9oGnpg7 zl|6#27s2NY}`35z)cPdqtRG zO*iX8V{LCqv}~LcoC)ylDeFtqS-@WLYXj?T)+-)Y>lNSsN6}~%WAC!QaGkF?ZX>j3 z&9ZkpR&f?5Ii(JIzc#a~vDRIcv}-JSUa@c)u^-WCR_}G81L#AxBR{zITcAXZA}Y?_B?pB~vQ5iK&2O+vqE`b9^fuP*U* zZrqv+^yb#EPuWvekJ87F!#s3tbMIv6H*G~J!Ff~VSs8kCu$wZ`~eZaJ{$ zjPQzdifAr<`eyKwFG{)*of+7G*l>|AT=d|(Gflmk%MRvnbC0jNl)l%w&ZlU*e`&8T zf2e5mFM_2x&0|Z_hra#yyro;0y_;PN?BTX;zNzgg9;HNj;cH} ztB_|uiTq{JRl>)yy1*+wEZQLt+h5k4h<@|%t9knV%8X2?mvpWY(MYl_?E`xr;@578I7uo}tXv~F;yOZdzg}F)Pd=@!C78XONS$)BIo8Bwbcg5xu zum`XeWaG`sVk_jvmaT3ECiY`WHp47e=jOqg=jFg&Ru|}^rT9B;yo9m9Bgs$~eIC0n zKbdz9?Ou{^(||X3&cgj%kNlr|dxPSrldeeT+HXW#{QKzrZ~0Vm_fOwxqs4=sE3a&WFJv35{jz*)1qbz`{&a_v^OV7ax2CiqtNo5$7kYrZE@3wAmhHhh0sCI+bMDX#PZV`$M0){; zc5%&XdO2&|T+T!_-z!Rgrk;4sz(+aDPnX$w?NALE1o;L&!i3*=3*uzjxXM|s7|8K?Boy}v(LAF*$rp>wcJ zmkFN(_M2ojg6-rEtWhq!B|9#~osLv(a1M^X8R}x3yqj1E?sfF|L*!{K()svQ)|`L6 z?!a1PbvAR+LjEy)%W|I^D;>+-8s2^5&feH^iMrD16?Zt;!>`2s$hj7JNxCZX^(Rs( zySE(+ts{ITgVGnjME6K$WXEhW&_2h#us;Xu&1T|0^6n-ceGXOTyJ=cy5?ojnB|lYtBu?x~I`FIaqU6@+@7bdt{^UY5ers!>>7& zbHZ5IOMq8}?NEzOOSrt7A{oxq7p8!x?hPckbFTe>&QPXl9vB1n$5EN`JPfycNqnfv)H)9JzS+%vad`vaTmeuDQMm#cc~WcCFo89 zwx_k7EA-~*xf_``=12Rbns;FzWcf}ya7Cv?wx_UvX0Kh(<}(MPn}a`B_7>}@-9L3O zHsQVwzpdWcmEPC+w$@3lSNgV*4ISIlL5Z=JQ|y9IN`_Ic#sXZ z^}WnjKF8P!_2N6x@^JT;8tmL!87V#o92Sz`4ixs9gJ z9n1!vALQBc!XaelSFa&6I!7NFBQhhsfPEj>SKuvP;Cq%=m%3j0fL#1vZxEU-r}f#45Yr(QltHFFN-P{AJ)E-6H#LwEcuW zZ@v=xNba@o)cEnt2+@xgpEM%AaR#tYG_V|)r z*}3}{_45ycM7}W1y>N^4t$bh7x6-xp z>FCZ?V85)gcQQ=o#&SnmW4^?$Lu%Vi9oew5VYF`*4Va%E?6q}?jBJ>X>Nzf&ao4b! z1Z#b0d%#ny-y^n%_^69;1Ga|c>k7YxbXqJQ+@BCE{3}i38?BYH#rI)H+<3(SJ3{YK z+B1$U_Mdd%@#hrwq*;dtJbxE59fOa~nX#heq*oNu1HEOF?k%st7b)Lk4R>d2(eDZJ z|4C!ZoMZ3ipaa)*A9qe+O942UU{AS1aGqRI`q!iREgjm8FRUnh`o}j1aDb_GLhx$~ zz4k6t6||Ed+TdR>=&*BUT+6pAddr`oZ}qFYy!eXwEg#{ayO5Vyebph{YlL&&`ta0d z%3FgrPCC!`i4U}ueCYkoRwy)$@ZymPvx~5ewB#AtPT|u(o%==8b>AsQUK2J{EVOTQ z@2D0UDXv!`@T$PZS;M)y|27A zw*y@vek{~$k0x9q+gtX$?l2p7{m4CK*$>vw=B{tVhOg%?bECc~9pHSaZ2A#g;eGAT z8j0%;g>$q&I|%2lkY3yeHy{VfAKzVN$y#tY{p4{v96XG6b( za=G2Vx1sy3zHzmuKVZ*lZpJbJSqJfHrh>*XI5eST)!;-hB1kik^y%$bEa z_TV`)uruGnS?Ho3&X2sJkG^%x$8}zwk~~i#RJUuNzN*~&VQ@L~#uDG99I3B&V|C{N z8S$r_=sDD{vvbM&EW>RB@d;-3!B6u!`h z1qt?^XTPs6T#+sRAbfQW?CL#HY-7eL{VBUtZFv62@r~5in#lR_S3`d%v0&?2a~RF1 z{I0@-cZgD)<=XE;j_8OybYMOtr{aevUJ_4VR%{LVp0#O>JqH0F{Z<8g1Mr(?b!63< z?$xb>~equGAkR zw1kf8Q?%3_o{w2t&M%$}E%D*_)1W2#s3_m2enaA|@Y_ryofh~8rBluzPxijMyUXA;m_0V|4_K)_(E$9NtEO*p>bVEF5-*+Gn{eD8lzPcf^jeT`5 z--y{!c3tlDu+JW|2-xV8$Y-4(9S85q{lUnX^Pb-zR29mXC~ZVWv#xI_OB4%LaejRCh!^H`6ix) zPvm134x)kZ5FMTXhi%mR^r-&xVgK@@s=qbjHTt@Nx=X3Mi1;JKm9QQFmdcleuq2E4 zx%>-9!TNXzD?{C@soO++6|v6yey~^LzO2Z5A2T9;kUzW)+v8sD6?72mK5TRs_5z;u zUPno#$lw@;#9;UHQF zkLX<*>(fFm)4b=V_X_l^y`c2Cep871199?_+@~+=eY)xBQ^9COH_k+F3{QK+kGHNU z1~w=6r`UhSk6ppOYf|G>^yL25<=Dh48Y4Ze`KZdAZ|5I4x3^~cZ;xkUefwLx)%WdM zGpr32p0{c)qBVqX!UggWoeku?;sWW^^w=^V_=MNy%a=FhCgwrw$1?Ey8vaDtaLo6h z)?)^eQkm9#<6;+vbp9mtiF{S~!#1jowF|@_)Kl48LYeBKu4Ltp=tcS~&VnvKR6p?G z^@5YJ`nf1tsxRFsXoC;57oDXvvG&NiXV7hBBF=dOK%Kbd~AT@WogCW1Y_9gfWlX3P} z(o4rb&OXC6C3hFPnZ33<3!9ugjZyNhcPw=`Prt=EwZOZS+2G#rSrsxIts`0!9%rqo zv@Nu69r(Q&x}W@qiMJ9zL_CFY>i(T{;)6VE4Ih2q?l0Vl6Ar!9`#N=`kM%6t>yDTB z2|8Q5PwS=l3_qW}Z}$Ll7o8E$p{$?wvLjBMq`1HQ?>t97#{zSpwejyS3g%_yZv-@3JQ0tte@Hv$|wQ&$nZ!W(@Kn2?y!_ zRpEHXFdq4_H5S=GiS&*3{zZ=Qi2sgN9%~wNX@8F?!TvhhXWit;hQ+`*VSjD^>&g7f{d;>JD~rh{a5kQQ>dDJX zPaK24pY@QvRMGnV2Ug&pSq_c|^Q!1!((GTN^{5NkfCdim9nSHRQ&*HuJ()W$&`j{6 zwN>kzNO%bG~%$L1i~k#{Q)c>6Y7&y-fuDPQn)A zZxMb(*h$z&sP5!jo`lm0=babWr_sD1d&Q-Ehf(h_$rml0$HG^93(5MX@n5Evgk^Q` z)<>wT-_zyWO7cTm9gnUYTtdF?fZF?@VLr?`_+Ik$?T_|~`pE8Jp8TogOJ7BB#0T#f zHiO3_=+hlz=78@4!u5nM!p8}cqcl9VIUAfg%o~871@=(L(ggGHo(bk&!sz&OYFm9;F)^vgByOI zn%}0PPAtPW505jYdl)M+S-N{hPf=|=&g}KQj4bt|cfxDW>^$f_LE(RI1^xl<_lLNT zj@Mhy&GL+o`Mj%)+;-gYTkMGY-D5?lp0$49 zZ0b6`NhyBgyM*}k@p;BfraKwoup`tp`y$<%_llhF4}p_k3vbL4ymQv=&gORLeU`zQ z`mH|qw%u{FoNt~4-}(cVuu%p6Du$sQOJ_J<&^(Vk59tIqFb(-^b85m>0!f}KZeKZX3kJ|(PE zh}ZCbufFA|@@S4D`1{#oXgu)$2>gMtt#~JbT^r7GC5)2xCt1%IZM0tfhIZNy(Jtk& zCWtTeu9DpY33v2Wd*)f$Owh8ofc}{g!5__o!tcotH|q2NYqfp@PWGYWLT?9H1KZ2c z1$y_DITH=(t=}!ZRCJEjLSvm5JM=AF4%LTfyp?`f*X?)pSl0*leI{=T1jP#4%ji6Z zHCSV_-=qnigKw1S9eaIWCi#(_ zSNlRd;ThIj&;J!?A4R`=J&1CqH^PHN=J>^=`I@_rw{deJ@cN6WmRc!yoZ-sqU z%BH@DDY=ASM&{}UcO8BuZ{7MSQ~Fw}g4*g_-L4PF%B;+GD|d|J#2eT{ zNPp1226+DZ_>_XndoPk3gRVec;({$29IPt^rE-W@>g7+Ksd*82z&-X)kqK|lceLU7@`4%3(0UpQRI*7+B>9sX%TPYWF zXwy4NE-KsH6Sm>oIV1C9+f482OPFU5nwyB1?x2nC2-t6GLElP!eJf>$%D+i%n1{pZ z@8uyLHI|OS`jCTnG{13pmNkO?ZFfoghP^L|_x^FM&^Kg8*Vp$H9|-G@?)!&(sGsGG zg89;Z2pv}+%LTs$s{OORk)UrW|3&vl8RznA0{>>3wdwKffj!9u>{ln4(YAc_9N6@- z-@B2y3)y3C;BMrX=zDe8uWbB2%JYzi@EMQ;efqA4?Dg4>I2_5 ziRSuK;MtJox2IeJ_+tM{@7VjPqNix`mB}xSF^>$56(2b8d&Rp*_WbZToyCEt_6{9d zi=nxb_xx%2&}MewcO~Wwi#tHt7vEAo-kV+8L7&Fedh8Y7G$Xj*+iqdZ=eNqe_;K0U zje;W|eTsT|KfjHj_l!F7_-Vm~epyF2Z^+=|9pHVw0e&Bs_>s2+@YMEr?q#d|IPNK> z2cGh4c?ZXFJIhI6uBM*h-CX%us%fi!)JF9MXDj7uuRfHoHYyXG;|6Azm#IBtW&;HO z7Dn!|>31kzi&hVFPVic^y5luy_2aXGvHjMq?Nt{s&8nF<|)nPak<$^@s{{X{1x$*=Dd=p zgnz^bl|1E)qSNo;<=5h=Nr$16;D}DX+P?-*bw&GPWW(C}dA`HSUj40Z=(A=FRnTN1 zbl{BK%3CC7XG4!9<2oLC=&qmAXNxxQK6;Klcp zw+HX`MtpuKoOG|CmG*)m`+I7Li+-mh!e>&5PYfJ7=tuZWs=z0cXFkB^DDY_;z{d$J z;VpcgusS1GWN%o1l({lF8mEdi(9%i%S^YkZOL!Q3+(Y2=r}lt8M}ULIEqqQ9J}!GF z(Z_`z;L`{`8kfeWb3ozqg%BU~Kz$?lME7bV8tn_`ZSro`q@3qJl?m6ReDM3!>gz=G zpXOfQe9^P+vTC2A@4PsC*9*JHkMrGe?4`jycVhDsULlwbc~c-xrgi6v`whgpcg22B z`=!A+G5b1u-wItdh%WO5|L=@#7VDhS1?<;uzD-tO|4;)S+Gl88R#}4Q1kb=|R=wC+ zLA~%kK#@J%$nRInW|Z#3KJ%kB=4JZPxMUOG$(RHyvfs4EsO}JTM&}DoG>;$VonpZN zhtvm2>#kuEc)ZJO^I5-}rk}xC2e29#V<&Zz)PWwUYe)+=^;1`o*4PARA!*s44se8n zXm&Yy)(4igdolK`o}a%WkbT)EO=kq(ZjRaZV-<7X=##X2p!M>dbneuTS|gOW zXokl9FXSCGZpJ8C{&vN%B3?BH7-5W-$M0#u^XDIx;@mwq&tMpvU8U^G)Y` z)uI7BAl^Z*#($sl;?O>+ar`@DJlf8!=O2Y_q58^?xyeFo;AZ@ji^>VwUoCp^4#lqSyp+}&-j7b!cnX<7YIJK&*{L| zn8d%D!#ja}H2O_ASvg<~lqEYDqt2n=mwJuodX0lVTBv&zeW*<1RlC}OWTCe3S$we9 zluuDV;HWdZW!SS$mhT2!#czOxV^Y7L2>V1vEsR9Ye(xZzJ|o)MzG*WXcMhLl@t*#(M>5{}`g42hc;>G4v%4+b@GN%@?sGgSrooAc~%tPVtO z!M8r)7My+P6YROc$VUshGVn$>oZ-ZkYO%OcJ?6Lq)mUd;Pki+Dc*{Z-QY z?~8ahA`!w-e~WDqEP=9e?o7US0$;_AcN%r3s63NhY--%Ta+Y%DowB+1oUBdH z;E-W2WPf*#`Njuctm1nG>>G66;W*)Y9_SP6a}>N`?!~Cj=f1x9AX>+vG4fK3<-KBw zb;|Y!-oj@r{tcZokoH-lc#nv6*hSxD;JY-xLy^9^@XhH~b~wlI>NS4RN3r@^c!+b0 z7=0mMjGx~uJ2j9y)`wKoPWn$WQ)N`Ix5QcWMvYf6#UtrRE`XuCfVHe^CcVDAW+>2q zFP{QT+V7%lC3ywnM0!Vg1?lHVKak#0{50tr+C0VcCAkY6y zTD;qYJ+(Fy;L0A@zPnTt+BrHOf6mLBrq5&F5bq)EBfLT|JEfS z^e6AIb2ZoBYs@baW<9@E&hOa19MDF#lkWHLCf>d3-vMq*1>70JC%e9U z5`EWptt(ISbT7awZd4zAIlTwhtZ!H-FXejvJ>37)JCpJeZUUCUk1zWE8}+J@yE~CP zt*bc0zOwL0z>Uh=85v!3K*ZMfU!D+u_}bo3k=8HR8s$H+gs7@Qx)w#5w=^V zcC5J{qaAl!WQ+Xbqr!pTX~lN8^#A&x86w}#YYV@7F*Bs)bYSSW7tnysdjCy#kTp+g z_g?zdoxqw5XQAjT(Ys0pehi&zKifx-`A5ziw1o~5b z^^>N}Z0e_}tNv7<_hd%;k^Ew720j!Q8<0LvlFneBxxd`V`{B*!hGUz9eKjr|8~0c3 z*fNJ0+bORzHtDwn{rm{ubmh1vA7WhJ zR5L#5kqbh;U2XaszX(j}opkz+vhFW;KyT?Ct>;$1(@rwh7y2=|o2@e+KYC|g>rx-O z?{}JC5LYke9>@;#3h`Nl?ss&WcM*S_@H^^XPyFwM{~(-w zUZ8)Xeb_nlo6#BmRN7uOp^g(R5{yCn zzRbzmPX)G>>PPkz_*r=yWdG1zL0jzI6ZKm#qATlIv+jPfE;XV<>sgPI@Q~9H@=i5( zDWPAy8v5vN$3u&@m9;)U^MV;V+cet!=``kK3(xmwe$IOude31#w#CYl#uBaJ;-yOa zK=<7%$EI~hyr?q>YwLu3z`AhaeIc&NaLkf-eX9rAwf0Ab^-%B?ix&=}0Wf1-z=jsO zH}WN5Jy<~t@kTv;Y+(!^XAJ0!!8^nLu!EY{lP^B$JJ}5B9<$bzZt`RYh$h#CbkZ6q zd8#tp0|7VTgKxyH>sJF8n`}_D5$$?-*4&-Ly7Ad#^*g?oSUR=>_cY3?v4xV9^X<}& zY4T1cPjrm-3>u^8Ctja;eL%+=_Vy!u0$lnpngQ8!oW(NUeJ*=Zem^sNavVG4lHyt8 zx_K{jc}ZuxoNfC%vV2eR1!(GOohkTw_p$+hOTyh&e!$&Utl?SjYwCR#;l4ohXRU&H zQa1zNQM>fI@Y_k3__-5$sHc0=0lm7@{pDjA2X`R{moX;Mu>lx5Yd8*DOz$WjDY|5K z(1*Qui9Ns?;(A5dLP>r{ZUW`vHS7d`J#w1_w)D4jV21o^wFkF|4`gRchD0anuVbLq z(z80PEqo2>4-)PU=@-e2cu=&HZM>ikc%jb(-ffbs%dSVxlRVeF$hhyztY?q>_EH?2 z<^O^w26z5P-s~bo@lBb)$K?>qrbAB$XWeD{$EM&N&e90EByj#t!>{Ut@%^^mq?G9ys99- z5Bk=^O|b71obM){v~8WP3re^0?DXAKQay+FyZP3sZO`4_8T!7M#+;rI+pE1)dP3aB z4!`dy+1Gld{gTr1;ZaAwG36g|cD1dibYn&O$S|E?vR)rXO$Cet=_Ah$(iR4K1Nm;& z9Z`c1Eq%5V;Ax*9J?Pn)@u<)5`uVCOydqq5uT;N>$~(8kDTI3_6Z0NuwL4M1I`&ws zb7|gvGrSkd7|j6B0}jj2Lg|=#jalmmFnQ-d`FelkT<(o{b?Lb0h;Gtrwx23faDnZ{ zk!9{O3O@YD_g1@0^~{;-4pWesklyQ7F(2T`_>ipw<)On|4*bhXSdq5>(&2{ zwYPzjs<`t0@9meFp=sg5%peXExxhrxOtc5logiw1sAM5Y^P*xzZ4-zjvSv(3)-@XE z6_EvZls7dbcA|OKBjmc`}`TpwOJG8{z z&HwrT`}3(!-LBVDr%s(Zb?Q_VeDOH4+rJZb3}5HDk02MindM{Qb@f)ZGihbJlDq*( zpMQ+|usa)5w1N8-8ddfeT>I!Qc!$-|bZ^MUv7RaH@ zb*YWiam%lQ|KgvV!}B`{+x;4ASMq_6!Igw{5Vngj@LaiNYEYi7w>BBWyD#q1*&O=2 z`|y0~mMknjzx(vgik*fRIoumFqYFOQiA>aexHU|pdzCD~Ru$J!6*q#smg*p1bscY* zaS+rIq&ZRcp)gKmk2LvD#OX;6uliHomp?KK>V9KJtYDYjEi1<<@B{ms@AyX5v1I`z)^6&RZ^SDy{|h_T|X8 zS1h;I6K5rEu`CzYf}4tK#kJ#R;Z&DpCgHZJ)m z{pS8ex!J8TcK$Kzno|5i-c`QR*mO6=FRUp~NnXi(#oe3q+ZksE{DpJhCB5?TD;X)?0c8}vttxXEXGr5LV}`VSMPG1(G^IfT_&r&XRsPQ@kD{Fg2v$(+mH#bE9U z-u}epaVv1!$WL1bAIGOYbIwI`@1y*G`{(SP-yXb~TZ{iY{@a2#_eESpL*FL;Iou%b zx44GCSZg;Y)YZ)s4qFX%vcp&q9YfQKw5z2VN(X6KfICe9a#`~E|!PQVc z%~%=fPwcSEx;xcEA1~W%_Boq+sc-Y4fIeY~soUtYe|$aQOHtphAnb`SjB&;rrVp8Y zC$%Fw!=v;0R_2~Yy3(8#zKk;jnq!r=78&BLVytZ1P5W2SX3M(A*E}|i(<@e3eK)+5 z*5Bezyh!(;K2K!U`?Dxl0Ds67th)my(zpCxKq$n0eaTm^7KQ=VvP+G=A0RQ$$b~n6~(iK(iYO_ z%)+n$LGYixd1G5Y}r!r_9f~cWbh*b!dn78jTMBd&E=5 zpher1N4k`qgxTOKvQdcLvfLVvYsY;MCt6I;b+rJD?lV z*fp;1d$20)b>aaapuSmzF_IwJrK5UEnD&n2M@B(yb`Xy?^j1ab$ z4QyslViIf4_d=UzOMVbP`c?=F_)CIETlM0Pxhbq$JoY=(cMx|htkFMhf=X7v~BFNkK4UBN+V zE_I9MZwGhBc8~Lql*ajAoOn4p==+WwW=^+q>yKPQ8r>yv5&pfGFg~CW-6ip0{UqNS`JB zDB`Y|Ij?;0xxml5+bW=I#(!|ynI5{@!KIlk@SjD}y)@;mExzQI>Dev5gKXvO=6qOg z3-Gb8RYHd|3El|p$QHq(j>--2Hz;H}`xuk+UX|9&_aXKItmk_|-O+u|3C4`cJU z#oyv6(W-Y&}7WwG~DcZ>fj;gU~g zI$QjW#J$9StwY05ddhBOX^kazEwM+#!Lx z1@|QGySU%uPVHE3wcy%tSK)ebn{kif25}RTpRk&7Kj-_GxY4&RN9p|uYZ`tdt{pcY zCtmPBjh|16muI2ts`10T^WG%mNAw+?lNV2NXs>AdLA9B-XxwPLE)DC7#*6N=d*fe+ zI5#)aZ%80l{8V-1%$eP~hKK#hzYNAjG^f1DKF)i>Fl3OXW9->P?DNzDQ-S-3J~~S&*%>J#A1vl?C6e zG^3Yl03O}TFdkp~aSr}M)k8lpH`Q+iZmo0puIR4BOqhNuu(#k^`5z;WbpGS;phWI+ zbFX0`yV*xC=0A=uPj6yPMaJC0cR%0T@YmrN@z>yQ$Jbj~yYLTXwdU^)=$10R!++&< z2m|I)?PrAlYbx-wdrLtM%Y{wvPSv0s9$s5H9AVCcZQN}{;l zKL)H(TBQ?@Rhs`KT=^d@2IEm_OgZq)*N9`Rpfla@Kji*$}&ebyB z=injhko#7l`yKe`a_e>6zvCVw{5A2H&#*^@`xveV_Xut;u9rMV@Xz`zXPuG7pY8jY zwPN+htY+NGr}EauZ?o6Wx0OBqx@5PZW^}dSYG^99ZHdm(WZaZ=r_p8Aa9%{?2c36Q zUHC1TDaE(OndmQV!arMP?mkcJlLo@!V~ zEI8D?koU14WtTcV_*o_Hc6!iY$xg2;|McAMa;tl<-+5_|zp{R>-y84oJNEYYci?U# zY!&}?ucDR14uv^vnOmq}yW$D9x&_#+Ag_zoY}uK~w1qR1 z+zq33kmVJ|XwHmfx;(y1wtHz=ZLzH}73r#C#bSe9EGCt1l*L?J)E?bZ+Pz>5HXt*= zF*5Rxe7(mN%s&f;?1J;xmEvn@IO}dU-R{^%7Gk)JS4kSbbS5(1BA<-L;w5vK0+GSC$x+AHK>C! zOns!`&a)HsNe}g}q_ycY$?p*ylIed!xaJz^vZHXV^*Q5b{wINVI{y>&rPg}?LVERm zWY637x#iZixO;Hl!M%-}_j&d_aNBS{#tDb&pJ;Biz@gT11@O0#bzHxrcZQfBc;CHc zKl1=G5&f0Y-LB)4>@%xQXyP`~UTgy=dk&&y@Saj%9cMmXhwOSB8@I z-6^yo$Nyt5a}NTrGhRxgjtQ@UPDB0CPWXs04BL#RpIy;gd2BmFhrNPlC;1izE} zI6FHEQ|@jll*~8yp{|FpoiS_jx0w5Hpgy%lYxCoa9`=Xw@v_!A*G~@g(W+ZN2yga0$DI|D7K9G41;y z?=`LS?8G9i&mU4AhxoHj;m)l&E6aB&9dp={^N`OUN-_s8^Ac0(2iCwNIBPnYZ>@)) zbo;Pv>nUgdoHS<@Do;9nCF$`QV}s38c*|fWdkEZ9qB5Sy5J#Fi%2YnuSm_UOur$kg z0NRr%e#zH;LreHSI#yrl2Ud7Y{kF^IVaqs@`%>>f7A~BZr_UCH@9(afS6V^Z9oW~- zCu}?Z9Q-avi=k;)&}~_)SCPR|F%4DK2YAq;soe| z`Kh?n+gOASyn8*-Nk8x9^=!Py!Pd~}cSkmMK(lLrRkV0B`9!m#EtPXeZlu2oU$hnV z({%cFn9lYUN*$CvR&*KmqxxR7EBvmbe!;AJm!_y0s;s^k$|lMWPZeT^>>b>Ep?>G=c_rQlp|6@N zJIeD)x8=G2rMS-Pr`%D+zS35F?sh5F=2v@~wxTc#_--ALw82 zcX-^_Nd7wbqiASFabEempP9$GsP+D+{(C%&^ffI3UBGynR90sZeqe!f<~xk~p(j510DX6x#a(C5qBCQku>U&dzrVy5hC*lHFT?!?c_Y%V z-pT*RktdG-%?fKf6Wdd`Lf;DOvE6xC%?j&V#Q)`j-M>?e<;|KmMo_{Yo z)@t2Tq{FhS()68_X8258mc5@GddmXxup8(VrK5uGN_GeHLSemG`+gDpu%B5%4olXe zYbm1VU|TLV72MW9Q%a{biPp&~2Rv8KLC)Le?Jqr1++VsS#BUP(N|vLHQYUzv2p+{x znJWg(+au&ndM}zXRhG&WpKFCyW5u*L+WS#Ob&bOIJdxe+CyV?2t5r5Kegqr3nIxOE zsigZNvQ}_EobH*^8z*Qam#SG#w0tShrrfGV*@-_RCnwUYmH1!vQ5+R z5z^%rO8*aVCcxqR9CAdiP&q{S(}d+0syy*d7k%ai@wU`H;#Q62Zp%*xG_Sh(|8-=q zudNz8^6T``HVXHpC zTUj$(d9MgQvuC9LIyPlG%Lcz~T1s34Y0|F>e&(6XGyW6yGo{mjTW{`4SH2Qh&&bXz zp9O3y%M<)_>fk}__jjf`i@4Ij4Sp-*vunB6b*>^Zg|+_T z+*&_J{A2u|k1yJno|ZcP{s`T1q&L11e0GrT zdyN6@E~yLdR#n*NPYc4-zjMfY6=^Nt89**k{9O9<+F2A-shkg?;P+bu(xh0%$`)kqR31`IrGcXyLvszEW zGu%SyRM$G%H)gGO#zkG+?a@~eOY1(^h3vN%xoL4F!M@(z;uAm0TkSaci}fA0 zB@HaM65j`$l8eqT_r&*G)6_YMdGzs9onw0p}gL@}r)PF0@Lsm?^ldjB-au7xMFW*9Cz8r?T(2tL)Vu^-j_UF1*U4qjpEewKBB+NAb< z)6^aIgHzoPFOy`guUuc^RFKK<58_Rpx`9f(v{E1E* z+?jd4w6r|IUvx2TWPSQm`Y;+ZcTD7NF2+Hewk~CS3}r3!DvZmH;7t#ui~8kBXgH!L z@qwq2^M#L30RKNwPp!on#_+t}w}fACBU$^thv${&So6w{Vyh+{M?H9t>Q~v>;yizi z=t%1iWRO+Z-UCBw`;1pg-1TK>&MFq(k>{KART?@m{e>^t=Z3Hh_1Sb_6Fo+Kb`dbH z7A`J$rSvK1p7LUFq&u!vUz+;fU_RZ}{))lRNUu;Y{Z_1_zMSS;6!jUSbJ7Uk7? zqE++)z*5~F%R@&5JktLNt`AhT?J;zbuTalK|{-5C-T?JfDF?pA)u(dD7Se3Ld9WI!L@nxDCz^@cplR-}jMu z<*TgK<#V`uVT4<#`~$Qyp8pr{|1AE0i~mzjpI4qmSR?=cmjBzZ{i}hlI$4`DK6#Jz z`~Gd%>OD2%Aooh58@rHjhjW^l?%lScsolmVjrhh`EBZU~jKnpN{uJl? zjqkmYb?+YOHG_4$<_q}2px%$^!xn6r##EWPV$vk9f%TPmZQSYdc4nR{jlFnpX=i4) z(O1l8Y&3ArO!Ecvzu}AbQT9~!Saipv!Wp06=6$wrFQvbiv9`~FC)F+4N#oXLF33$| z{IZ_cc-5Ybfq}AfW#9mo{wb3^=|*ku!{rra#;U8gOr8hd3re-{6zF7d1?8H2l>L^` zSM`)vP;L?Ve(RJeUhuA6kGGZi@6?$+;OLsBh4?}B(o7CfL%i6=Yv&g~ln`Mlp6_aTnFib?If(|yUd3)%gLoP5gHpHix zuPd!HVt(eCnBNI4L~DpXKg?TSBm5cMapI2PYmM;$@s?Hd ztCl@^YyNvI>*sg<#JaUoYyY13>3@YC3GR!yE{I?2i@)RB$2H%++?tK^-X0oSiT?<0 z#21!ZFW^tZUy75S@5}fHaMm4! zi}Xt!tS{EEwvtXrbb-BA1%98Bo~*#WLTpuFTdsbSZY1K9+E@MwwtdWtrP~-Yy$7ZD zCJl0z(j=_=%|7{$NMrJmu8urfr>!B)T=F>1{l3Z-FO_`NPS{VeHL=0JWDD_Q?USSJ zJnBN*%lO|vZHkACSgLP(!5@NVm5=&L+Gl;8ysx8+(;gh}wc>&^+%xd8@oLmNW};!i z7iXNB@@eJie!mIb>aKji?_VZ=E4q9aI1=RFI_6>j^Vm75 z9_i%z`LA%rcZA{amoaxx_fN>%iTseHj&x?7cuGk&U9F5I%?m|fpShbhdcl4`r=xMl zzEcJmesnf#Ezv`eTmH7W=^)VS;kNx3r6*7y(wJ7!w0o*x{>KbsdbEZ?VZ0z_+gzWekPjH+H#fB!;8$G5NW;T*3r+KcAnTB>6G3rRaN^P*V;>CB$aHE6uRZc>6p z{d?~Xj4R~iWx-jHrn9TcT}ip$3(M6Uo~K;P*#ysAPwVxM^&HJXg z-d|DXg0P%~`iye^F2v7=gbS6EXPjl>2f!E2N0Qg2Pi78IiT_RxVVp*Jf?Y5QR;|-@ z9_Aa&_g09{VO)&mY@_Nz#wSseXetE^ve|iD^rm_VldkdbA)O_;sJy_xRf=qZT}>PX&Y8n+1kj zL%c!nM!tw(_-kO8O1$dnkH?n=}D$KW^f!n(AdC|O24P3;x`iT*$ORp9L>j_^+j4;k^1&sM~{xqI8JozuiA z@0uHV4?}5KKZy4%%OQ`^SC$K3q<&*BR(#0NRV`tXk)>bQw6ZniQCk_q5BZxuKE-Qp z+u(1gwYA4p(mmeJ0&FbcvpPQ`*xD(teNtfK(P?nG*kg?7eRYFRm-f|%?SnSo(Z2So z_U-GSeTATX(@gthV?z7#n(H|83SU`4`KJqS)T?%?y=R(sZt-hqL)6CYq`i)`O2>Wr zCGpc5mvWHrdf{nnT*RYoZYS=4<8*d!8UBxPb|*Gf zHM$c#*n6BLTi!bHrr)}C-TN9+X?@lMSP6-vEhFkIO@ai$;uno{WL*d14lB)+V(_QHvb#L|B`X-M2`2Q zg7_HU6V;ooj|#?)@{4(*w~C-j}s zV}i38qr)>Aqw9n79q@H+#%dy+%eo6xVLaoTbR;ix(id^*YF+EC{E=o?r#aRu=7e_+ck9YUi8p=E8U#Uv7H`dxT`8P%*&!Zr^MX> zI2Sh+m%+8;vbec8XJXASWy3fo^v8yNedsrYeq-p53;k0=Ut>-(y(6-plq1)TOnyT zbw+g}c&TA7)w)S<>$GP_`sZf3PY8DoPWIVa54>jZ!F|c>S48)?{hIGf371YwWhkHC zvdHAZynIJ@vHh5I(!2GIF>Dk|(0SrV!!YIfBiM5%>;i@3n}B09Z+*sH=mhvxKd{4}wHE~}{EuKWbV1lh$)mQq z!1EoxqkY7!(BVJfw64>+l6`#Z?8%)d+eM#A)?bnS!^&b`(}8{%n$$Wcx*tRO4Z-o1 z!^rH?C%BT+xmTc2C?VIUW@rtEuRCdEqp3Xt=@ukg#=*JrYMpzp^0U76Ea(!aJ0x1+ zjl4PBw3R%&$orL7tfSxHTl9I)e?UXIV9oa^ak6RtC*r?K`~$2VtUPC{39kX}JCKdn z=$kY*ecLj3Sw8EsM=@r@0QWL`;IEW}M%OL1j^@Cl?8$4;8E)pDSlxdD{7w1HA~SEB zK7zJ&=0Wd2c2M8T9{cC$EVO1xXS%&~mbWilNTZ^Uh4dw&M5l|3;Mqo~4tK{rdUD$zQ?$PloU;<^Owt$Ih%S*R-K8ryZOP zpDn!fT;k1o1V|+ z-((DE{uoPIk8jN>e+HbIOLox4H;S~IaFqw&DD5JAncG>eA^kqSA1Cg8VY~M6y_K*b z?CTXbojNritRcKDtp5)F``fLf8lSC%Xl^|v%pv}ngh_U0-T6m4u)`XwPOt}Z z2s+jKUUk+M|7V0xv_4vSng3S}4ZV5|Ybcv>8R^N)93hNwvy)SbG z{v+2hH{f)a*fQd*hEG_F3I7D{I^1V*e}ns5ocJJn_i=Dx?k0pL&6twxU9hl2g)TL= zB)4lEM`w)fJnOLnYqSpdbCz#-BD6i2a$g+KT=@hzt`=_LZ9Aj8Fiby1?WdmVIxO8K0Y6iI z@i6hupuU5?;N}iVQ|Cohb*fF`oi((#x(>;(DqHIk(fUg41#9h9+Ut0zWg@mDgxy3~ zeAYpoW2n^Cs|&7S7it z<`qg=!dvhcRHbbp>_bWm{-XSvqs9}ivyhj+Yz?jk|LbrYaGP*jagX2}&ecb>9oY?G zb9q#@-qBgMD4e@nj*hOe%5Lh9!B@C%7T>}b-KfrJZ4%2CN}5-6zlmhrcZ=_!TlN549T%6 z?huLMHKwe*$9RFSnm4wk*ExYdcD#mhnW*}1srqgobt28o@Ov2F$h?9bK4oi6VIyqj zd+{yv4Ig3tQJ?D!bh}_4>)1!%f%lWjU_S?1-so?zEKliV-)d^)^lS7|sS`!yehLA2+&<08Y&%;KDu*tTWHq%v~;=d66w? zrqH&*PI}*?Zt0iBbA+?iY7hG2Bzj}=9BDs?_gbL)ZJFoLv6*`|Y@O3&t;qO5j?6qq z_Y~@fIM*A{=zYdc9~_boT~fPwo88`)*=-X~Ugk!(E2(eIheMfI%*yQ6|6nc@>>b>< zlnZ!ZERPHWe1d-muqFAfaRYd3fp-sK3H>Kr|BtWu@{!k=+yAfY7kyH{`dDNAR^bCU z;Rj6~dj-D%|1SSoFJO0s&XMnt<~s<3mIuE_nD!p`g#JDF%tI-yF$$ESb+z^~e)E#- zgxLe<8<}9RAD@04T!+uRKDb6{@YS|XzJEb_wecgsw2Hk7>_2~^+t ze9tA$3gh0-f9XKaM^~cwGx;yxlM4T%qe#sp{lRGgyug}j4$E@+ro6#jVcgka-gua| zh5wX4SP0|wKOW|t!uJ`(Y26@v_TqmP{E%kw4!(s?t>1;uRrtbZ2fpyR5}$czQ2QV7 z@WEyH+HcjluYbc|iqE|~gG=zamuPS?K4Ww+htIq-I3J%ow+H9qbMfim9DLDS7GLky z%*6jGzWQxC-(Lv(&FD|SFL-`Pam~c7B5pkXXTmhUVf~j5+pBeieR-kBo>$oLp+ceO z=0ahE=HNe!vX4Fr&Fg!k701>X-kAHihn}BzSX}Qvh#x^c8q@H{?o>A0E&jLzIe!WD zXg(KhEB|AJEh6mENx>Se!2geguzUmbdnFwIv9 z*SN@sZ@aTzIiLDwh#xE_4A*!8X>;V6jz1q?yuXca>9RgP`ovvj(}{Z@;eubZf4yMJ z1>d?uP~n;b)K3@DoOmY{696Fd6;t+-2Zb;8(A`O&UMVc_*7Szt%Il zYgp+tFDRW=q`#a_Kj9WB8~&qu-Ms^P%aD7Z%0q6Pec^=_>9CY1p|fu)4_>142Z>A( ze)+s9Z#b?9PjmJRB#K2dXC=6w+79n8iRL5MMP>?R@>{W)(!8(&Sy1Z9Wpqay=O~LI7ua@*b_i^?chrR1{#ohi!oaXRN_>R|&ZPb1K&?S2- zadi0&+#xo;*p02zeSS0FF5lz%ZsA+Ft5aG0mrROI!`xZ9nEM{J2V3X%G^UBK3*+m; z_*@vDCf?wfyV&Y*QClT97`ZGD+>9~7qkA${W*j=v8N;QSXOrMGwlq^rCK)>#fAG4a z$?Qw)rM?6%`pVn^$~{PZW$}hb__pa!&fWU$?31fM+B5rUE9WfHMI~u}yXouaO`M(C zW7c-eC6!LfkGY-Q1+f!U?M6YS$}q#qlyTd}Ra z-%odN7dLSCFn@RQ7P9T}_FT4SU_5qciOjtQj->mNZ#n$8XoKFoGMy$Ss_ z^M5qqB z&c;n=A2{qMY&&w5GqBIgJB9eAj1~RAfd4o0{}TRdJiHrx5nK^G5e$M`HoRHx`ikmP zT?Z)h2b9UYJs9EP)DREv0WRU;|F+%LZBt$6Q`dW`OL`x{uX6w2!ut$mJWUy6ogev+ zP>!JotC}7$YD%<&1-{|`(z9V{R zB+m~1tH1QUlkbRbl2vqb?M3V}!;g2h6_LHI)HN3sDof*!Tn(P8>4!EN{Ew?@ z*U4>B`y%+&t_WteD}qt&is6B@&!Xwo?xhMr{IXnjp%X9 z%r4efdrBMOkJoX&XtN_esX174VBEWovqc->nKkee!Yeh{)#_Vs4Cs3!>17ks>Tcp3 z+a|wjTHK4dchj%D;mmw-oO9MW=HxiMQhR~HdGUI)Mo9+e#gUz`b!MIt|AXI1e}E0X z=0oxB17?n>qYTMYztkF=@L-a|XeUFCoV|87L zsGbnEcHVZSj4?wYP9k_DTUECK{ak7^FrcSd8{@7}oq7BKb6|VsS>|uyChG2?%^L*g;UayIVedjXb+N;9d+4tSpX&noM*0Ic2s=*yd!E{cOjW$!Ka8zv z+UpABFZ2dTtQ9A=dsr7OStpha*4}#K+{lEJ?jLvonJ{K;7}$9k_criW_;lflen4L_ z-eu0x{Gj{h6-Hfg!jDL9lis8Q+0MvN^kY=E&08I;l~V^p`eU#9p-3jx+F5v89LgRe z_%Ar(*iZ|G2Z2Fnu@bajcXHBSz|u>fOD+udt*Yx+f2e-RHjLrnIuSjG>!kjm&MfbL zvOa=XnxUP-4hXyz&Aipq1IDlS^ZjJUEKWe*Vs$qRsKA_Qql7qk%`}EWw z%-eP_w=t(n4&LO~%-S%p=OewecjLfy)R`t-&7?k$bl5-@skf6c(Q9Po#q_ahJ8|G% zx{_hs8@!*SZ^{Mt3s;bv%>D#pZ4jCD=s_3zz)VuQt&()_(z}HBUZUp++NJ&s+7!^p z5&9*a@Athd{bOw&mXxcFa=HnnXW;7!nh2?h_G^PIGCAP0Zs<>Hd`#$T%Itc*=}vZn1B(E2fvwaeql zYh@QpFIulM%$m2o5NH0bS6Ou`i~8c3T4R@Q;>Qy|zEH2cjqy(8y6%BAaLI1phVK4z zPGCb)jo)|ZGYi4~L%f5#1Zk7ghHWkF`G9F((9fJpYyQ0>fNjoYU)F7xw?ZQt#?%jQQdw|8CCvd5pE1_r6C{!VNd zdj}eB-0e5tx*Pd7q^)8hPQ9r&t#RfI)|=GJIA}^{)_M&$?j`MBe?D}Vg62eL=Y6;r zUCzdV?@@0}OQCeP>UK8ywXLzT>b8r8$`?lk^{H;Vt_a;hiyD8#VUuTcuhAHY#-4PV zF%O!`qQe57SZ0=4o4o~&<}ntA;CEAjD~CKQI^eiL>R9;Agp*1md#733$351M^htxa zj&;*I=!QF|v)u#D*>(PSoJSsHHFS^M#WQnn$1@u|?`)IvN>{+QP@;COxT zIP|IduXRDTFBnVE`-{j^L#|bhE#NK#)_j^5*^^i+9bZu1f{Mygnf91<-ib1~n>2SA_}Y7b4Hz%jTk$gMm=}Y1#$uD&qcn#d+L7rR(Er2y7w`KheG-kuh}RtG z4Bpy|_B|p#$~=R8cR*XiaMI3rL${|j^i=xX<_+I?b5GguSL?ok*_0pGo{5=rb2K&J z=h}ZU>+npj%sgak4I3x@1#`l;;G#Ra;Wgvgce|5zWMbV=LFT3Y4CGCkfp=GKY8a&oxVdK-xwPn>L7PL6+oxH0dRuV44DZtzp@ z7RR_P5Ep;9IL7k)_y+&2OW|w4u6ZYe{)nxn@;I0AZZ(#Yv`=uva{Ei~XhW`tw;ZsS zIys$lQaa?NcJ{V2{p?p4un}>wRq6QSwk6Qfu(toBHruUUW!aP-KUdu7GiC;B+(Y1Y ztht+Jy5M3gi57JBD&}=pwol+Lc;pVvoAuMiu!q37B@OegNh2AM|JXXqR{4<0)8fu6 zf0eatn(?pxaoqYKf7@8E#yikhR}}p&t)K@TzGGDUKA3-kxk7r7R+srA?BluM^?!la z?H3*_xva6bU%1cQsUPLjd~Ib5Mm7V-v|u%i&Q7RRgJ_G63f0n>5H6aFn{Pswx4zTo)7gq!zh z9OfXt51W46Fd+TXHJ6@vf6>aHD37_Ww2d<3*e}`#3Kb9A?dH8+X$j*zVKr1V-^G>y z?~+1&gV$ZYf;*Zlr;9pQ^Bx&|AoKh{vUu;nappY1!#p=$c|86frmTP$@y&nnBJH(Y z04&vfp1IbvZ!3K*eN3yPH3K@t?ETtDti#sKn-k~l9Pl_ASwpgn=8!q@USHvA-=ueI zALYhqp9Rl3jl2n~i0-y;Ky$HhYh;oL7gcFTnY7H0)oCMM#Xe7rJn??caKN*6K?8Q% z-Cj#h>xU~VJNUnZ`7mABV%Apb^Ct;QAwQ(tZcq2o{>N_#a2Z$46t$Fuw5 z)AN1EL@Ezm9AjTc{BsDFU_ z;bOJD@mTG?`eS+3e^n(`*Gc`@5?chel~5Zs#|H9PY0`EzJf5p8?`~O&aMix=?nFb-gk-8+3#cSq@3u#+O9IElSb{2 z+AbQbPNT9fs46EJmVE|c@F?bA@%|HbP{$LYEP*T**%sRU1=QluccEZUWt_A__cO5x zoCN(%A^&{(I_^FM|5)pZHYMXa;>%934yXO-ju%u~^BWp7xeZ2F-ICvc+_nLm%niPa zeb)3Wc9a>$xAPPKlMZJHEogxGN&j_ca*{aBk#*Vi(A#>G=K|KlI`co5bFtTBYp?rC z(M9i!Y`Vl3Y}S!cJFEi#8S5F^kfjZRVJo~${mA$=V^eZatN0}Igy#J}%sR2woCf_4 zWi4bS?rI3rXfF8;X{J+-`kygt^yJ#-TnKKsOVIlO^Qr2{S(}s62~_J~KFI$_@1pfH zxN1r|&vH&{L1i{^%*nh(7wBDNZ*md;tLv}h+|?tjps1uyL?E;O!_juns zGq3zb<^_#C_(STw&b9tra66wi=>EQV@&18$M>liU(n^y0#V2Iay&YFn9fCv~~14^i{6KeT$T91Ecl< zu0wZ~Elx1Pn4t{vqo@NJMqkF z%bp2MxIIbjpN!I;VOy`68#FKH9LcL%U$F*&R+{Y>{9k0O*wYznY?i);x2Lv-JOY|9 zcGaWlpXn+`cmpT3?rKjm*i`B0n8&1)Rog6=H%3Bz1#%2?Qn%N_SP^V0cL}nL=m}nv zV$QED$#(ny#CR4zVU9hb@ho3u9cS)0b0c!OkvqVX<~;k>4Fl(q{~+=TWtB2U7ZJ!I zq7j?6M*5et_^-J|_0@#F_B`}|GIUYTyBV}`a0yg~OqFX21@^iscuaFYi8PAzi9q^dD@C3KsFzPTe5yx=n*CEPA2k?EqUU~RIU z{@G4H35ROCe90sZ0-|tWWYApD{mxKwmxq$eIQ+ynSa@* zWUnI?pWg*P;H)d_03zNll|Gj4-)zaU+!#h$upcMx_s%&R<6 zyVQqjk9@Uf4XZKJr;+?ZKT2*fa&><{_i?f(SYVBlyN5H2FZx&9)mJVeuZtc(4-H!M zgXTwgN|Wr3Tvv9FdPk=ahu798+V&fsTZf;(}$Q<{`l-+#`x z^6L8vzLi(sbNC()&8p5OeAU;CuewghS3NGi>X?i#*r(uInIEv%8MI$?8|`fhAM{cE zxs>bfe$m*ei%%^p7Ahm4H}NFdRdkP%-9)a^LSDs3Yiy0jHO0VoLh0}1zH{ZdK1?tB z7mK;+9{NFVxk>Nh!bde|^IlYs5UCmAGKRgIu%Vi}KVc-8I_H5$kl#kq3Qof*G!r)!H zcT;WG{V$^JXpBa%ik_?SGoAk-u9}`YCFlp0C*G&JU2BuS1ij5aG4H9aiPSHjw=Rcy zqUsPIwDa%~WCH0CRA0{N_gk{+i{NcM8=4e8J6T_94p$qbJIffHBZGn?$t4NmGvIy+ zPBfskW5|=&qH8g2*53GJz7K)V7`z|eRkGb6ZnRe@xyJ(;@VlWbc03&K@(sMzwvq+P zq8{;~bjPL;=EX)wR)?NZ_>qom32^9Jyh$+Y+pKN#g6}Hri8Qqm9?#tEY5o2EORS@= z>}%!dXXM9JYfa_BAF7FCzbZly#wGA^M5> z_WV|FYzOx==>PNl7tO0Km8-Eg!dm}}KsIE3$ruxkTaIrwWx>Od%dXZuWn}pq4bFo# z!FhZ~W9J=h$zksd{J=4|{lXVZr%tZ-#5LDPsrY!^(4~6mo;Tm2qAW{d#7+JLq+a*es#u#f`($qo2`erUDrL#Sai}}tOJ?J9t6W`=7&h{lm+v*RMuQo~U zvl(wi#-8T83xrp6vlcM8&L)3)firNd5p@0{HmS?g*|7|+1-_Hc-G{s-8tgMN_Ishh zOA=1y9Li95yL5#`WLo0qZ0Ip*9fv!3-TuQ0TZ*oWI!m(kG3BtP5nfGt;&e_aDqm@% zZ^`p1>WZfv@qEcIO`qhy&e7#94x2)UC;!)p=4(c4#@sImJZ}e*)w6g z$dF!Gxt4S>cxEiUu%h?kp5=Zf(Y(g?V%|}n$h$G>6ZOAj{T}$AU}Qc`z1Iz8efmUi z$Hv|J2I3uE$odN_ml3aX#mc8QYncm6S?aPFuUgZy*5E#ET|LY#r6#qqkir>lqQ}~|_|8F~QUgujTu z&sisRTJ`F;)Uk`Lqb2*d6v9Oo+v(!P7V2CIG@T@{ZZZ5Rh4r&TjO(ydQg- z{SoLT{&bs7m+O!Box0eQ3+AC!qN{LDx|Q~?o6Y$${@1W? zr~W$cE6_4&(&7FXG7>mq-wB)uACuHJ`mSco#)0#=$2->6S$UfNu(h9q&A=UD+f`na zr{RzC6yK5O)5IqxYd>3X+&|D3)>T9JPUpqaF?jDW?JaS?m+pkWD^aYBs3}&ynG_zG zJ7&oKc>#UMJ%`|T2fCx6toy>UdIr=+wXeEu$Pi66ZTF$W-Q@4TtEb%d_iE#ofg=~8 zR|wOyZs(mxvxYZ#h+7X0c*GM9jj7DuN({ZA%AVi$a35!0IumYBkLr)RcMsRg|76@* zTWi9t2M2yk8IskK=pY&$x_FNvx7QDyWKr; z_nv`hKa+b+#_wQ%HfaCGVO%~*ebr&7$BUIz`~)4UzxIcA1dmmvRhTWBWgj=9b*24z znD)z6X%%LVD4IR+x+)r1`hhV0eO2idc5-^%%cAvE_X5l6W&vVb&0q6IAD^kYU+-6& z^)h4Jte5kQb@oNC`VDs3^dUN`ir&G9WqQq+)Vl9;)W>}wm6ud6X(R_!$NvT4hCk7t z$0R4yZ{poHv>`tAbXB}`>W#k{8rG>xcV!jAwR^wL#&DK{H*RzAIF*47K`JpzeZgHg z;6VH08bdkC)Y?DIU4hcMjMz;abBNAMNk{V~?LW@wVV&MRpffe%cfw0NXP32qz6Ur} z=I|bR2fP?rIJxWuAJM+}cmS$o67q zjCEUx_kZNOjy~GyzF0a4zqhpbPVng45upB~1`#vm$F`{`Z8HHUG?o90|bJk0xL z{;Mpjs_f5^{tfO=R@wIu|9S|=YQAqF?(~rhE1wJVJsYNz&gdrM_J#ldg8$k(R~et; zJ5QYM!^(Mmh8KbZ>J99#92D&zeCx-WC5t*=?jzd8$AAG_*UOJNA%+ zRfg__GB6OYH!BX~SJ!i)*;3a(aO9u~}d7|AX zx5uIWgNzH)CVUpqgIoWn^i?=G4D1##N&ZmVVjajIz;s+Nx}5{Ujl#8FUuAXs=>F)7 zZhvE;Tlbup`7?oiOT>dD>!ha#a@NS1fvi(=p;h+Szb|lZ^pW$q>)YPL+_=ZAfy7g% z(9g$0UcvmG(wyd?VK#87qPT`XAJM&AOt}Fln!$?PmFUj|lo4%GZ|T#oDrE zp--69=fw)pAGp%mjq`D9!Aoh`3HVDl@(mvuY~j9Xy|J&17;ow`ozS$Jp;!`D;hIn0yqzx|8NqAz1M0}j%;&kNT)LEs=j3( z6NQUsMBfcn-7##_kP$gc%D;^Pw=kgS?bErDwRDD+sr;MjuuA+b~T-c3&m) zp%ZB?CLCI*Jd7XVk8zed!udb7_wW?v5BG%ZFI|{$`|PE%IoL38PFQZ7@s_9lgcZ<_ zWZ4nGdzdl;+)I|l)``5Qu@7LO|L70vm=5mf#|m=~wqZdZ!dK8?b3Y*U4`Jh_eolsU zx6)=OtXJ!x*09amk4}Z*sqv9VFz(0JVG91x6xD}rw-@re*N zg^AwHdMSkebKDUx_z!cAFAA?tqcIVM=NOM#fdU6xRLgrs&Mtk)DSk|bvxx`phMtI&7mH%mdeCnv&_kD zd+IN~cyIljOkblFwoBzlZG>)9(OQTtj;1-3uY0$h%wBT`H}r-)AQ*%BJ<5k(<{fEO zzVhn+Ze$4Ly}cE}{0Lsrn{c2s)=b6|-*fq%%D3)wRG-WzOgvb1L9^Hz5YO6Bx-Ip! zWJS$sjuYAwVo%B$=Q!uvkb&qIC&2A^Z1%)Mpo0N3=G{@{*lz51x#v0Jot!mY`>ad7 z@Zngd)9_W{i~FOKxJD1yHAlx8qi^V&dPn`c>~zK35~iP}-;it}If}i3wKii_aSCRv_0BB*_cK9s zE-;5V+`Uh~Sy}ib{S?dGZTLu>b@nLeQfsVFi_S?CpDA3Qh_4~svbj?OU*kqP`)>n} zeEolnb)UwV%78AKt|OhD;SSoY^o5JHhY_yX9~}7g2dtwzj9!VoN-I|{ejdoixzZHA z?aZH-hYI!O7s#`bbW^$0CXOBxy&q)1z}S*R<4^i~!7Ev3Dtgr2>?`G1bE~}({95zo zpfSlA2dR6GS??hW0DDc9NGdo9}g0PU@r)a$JZ_rj}f!R=J18M_;aQ{GOi zNYS$M>#Qs_<87la87;saycYZjXL?7WhW+WqIl+CU=G1!jV#Y`D^I0bgm%%=b?gCjz zzXf~H)q6L>=PAW--#Nlvj(Z@0A;KN#W$!s?8}*nyV%hSvhVUhUFFJE@9c>jIBx$dB zjO_h0;a-vasJ=jN5$Fnl)7<$G(Gzn`$0`af?cfk+nN4`k(Q+-sC6m z@&BHW0k8J31~oS&CT$tUMHBghJ$UKhb7L&m+!tcTnfgY2P%r~u$_r)J>ijA4Cnmv% z!Kd&Twb$uj-c@^nmoxnV9}RI^JvP*@!}dh|+*45q_TWE2efFe#j7?xmNO#CB?8gOT zfc0AHVD4dmIW(5eKgb-@RCyZwJj3?&E6MN30!3Haiiw)Dh;q}!0 z4!hr6k2lrY#G6O5;l%C_UNAM&mt-#IJb-vzpRf1=@uD}I{&FqG33~_c!8TAhXwU5P z<1TcW!Db1$pZNsaxP_Gum2eZGoG`ElY6MOyj(3$oS1KPk=&1D~yGAw9)F7$al z`w`OXYVU>lbEnGJcxN9HUegOMgFW7-_`i*B*(ewBS5vOqukk0E&>SH<6SbMK%|30X z7wju9Hur;QUsk-(v=ew#PmI1*U6a|%kS}}8s7&EFD%*_fh>zsCkI$43uXTcb>lXft zuV@W83BIxp9um+Bd<{P0X1n}??45M(jXIa`E&C_&pX=S-zD1bM#EDnxJRJDpz2Pon zBewa{Dc%QJL(k{G@YbB!jh#hLc{4t?pp^#*?*?x1PtEIU$6iBI&`C~wBH))1j}l&V zX2$Lyy+iw}8@8$;&aCd=gxp0H2V zZ`F2K8f&U+39vmK_M6T~n6VMj1o5JYB4-|l#{%uk1G*~adXv!@(A~n3tpSr7w!Q&fK`Y~@F(yy8Sx-b~2B3T0Qlf0t_TsAbNG4_;m&>xK~#2HhwpRP0-a~gZ! zcs>uIL4{2VE=x<4OHFw6Y_RkAxRW$kfuetM;Gv}Jurr?Wj)KE_YbS?jD z@MV)9dX8v2qHFP!YFiCAUy4U#QGCVFWgfewQH+UPq4agydFO`<6`eyobAB)SqRrTq z^_HhIe<#~E4Cu^&&IyPf)R(4w=zRRvI!5~-f=%VUMtM;?M?D;o8T!M>Ipc<|2hd zSMeOS0FnuGSM2{*zX*5KYj78~qq@#LRduR9)%)Mox$<4=JdZjP)E})czRl0bP4Iou zo9N7f<}6otn>-6Iyt}aQh!uma+|C4Q?Xj>i{);%~&v41&Y@V#N+X3FT`zs}{Xq_3I7 zN=fS0c^kNpxwD z>)EC}Y;86Fsl2okgm1r)H@w}hT9pIu6YnpH1_M4M*b9|8wEdsiZ;8gWU=pnAPs(W| zUwy}gfsUzzG17Hmq4Wq&@g3HLq?;(%;4k^V*uTrucG6eoT*#Zu^SI}d_Q&Ysxh`*Y ziHBgXI*L8oQS8s2Li?7IzRq38-97Mzj91EAdW%fsrguPi6%Sz#C2nJFx$r zgVzl2X_3CZ)$)eK=Xt-lp0}r$dAvjH-CtUjp^xnVrn%xBZC#wz#qO*lUaoCh?X?s% z=V1F|eYE~(w0Se{do2OpR);-N_Bl6MuQCsf^0Jg8nc{KY6t$go{GZ_WOzJMRAd~$N zn%(Ta3SD=aGqa0H+sS#nT6?v(SZ$-Mn49)CxzG6YgZE_SzEVrBpSP>$m7d_uyQlCI ztP6CnxZW+@j1FnX*lSDki<{{4c=@T=wb&Z){uuS!Zp^!X?-Xwc8B6b8&jaSD&lo!? z<(H04bEUptPScf66!c<53#PV9~i7Xs7Aj(!(nlItz^5O~&c-m*A@F*V|q9oNr+l!Mt`BcjU8= zsr1M;3^VK=7?U@LWh-2`fd|ApGd=af&sN$Zeg!N|^XbDR?Tlp$*yeu4mrdMEWH#U* z6rVL~B>ef%j$n0={nWm?{_e7L0a3fOUYLp9mT)Hg+2HT7IA>&$H#GihscU*z?;O6j z5w3bQF1ERS$d8dmv?tt56&Dfk}9g2O` zOzf+42e#f#jBKn_-e3LO&{3U#Q$5mUsa|~>Sr{L=&YWwwpZYb1Xt())3HGiC0F3h> zy>waTJP>?Y`B9p1jv#33@6bg>=Oo}MM!&DNDZTJ{gtGNtdt8@!NY!(}Q}2p9sGnWIvhydI!&q;${;UeQ#oI9erEibsI9L`jl@QIo2l5)>wR;dK}s> zea5@ht#J{R)5f|s`o6QO{M-4CV2yCpe`SE9ul*M|+IkX>9{3|172koQ{wf@a{so8H zbvx~{)h?%Cf1WnnF5G}?)0erRFW;R0a1z&u{>2l$z8BuE^PpO5YFtNclFfMrHy0X? z!V=J{WOdPJwY+{7d_iIVi2g_G0;P{+^{auwPB&FXQBUvUKt>h)MR%@TM_b~yQxScz zhk+hccVKK9cn(=na^jU?Tca>L(aBiU{e6KfVfH=vPH|4W7QGR7_?5L*8PTdeQ_3PN zTEDbhB3?12{OCvOz4NFmf>nH6>kf3YC-9XG@WlkmT9~^w7z1aw)q60$R7QFh_+&Hm zptYi81<~a;zJ*iPjY;N=!AHY%@IzR}BH`Gi8Sb+%ZGyT};81eq3Un{>y>LDF8UBk_ zZSpF7BK;xU4#V!AkV96%`!ttZ*6F3yz?p|vXwHr?XPfz&{5KpMI=V6=UgDJQ6b>|p zo3<{lOya-Vp!NiNbDMq1B05{XigI-ilFq?vu8SQh#I<&|ie4#x1i33ysEjJIUq~HV z&szM~n)mPEvkJQb{&u7An-h-A`{v*^m;=BaJQRK!@=)P2!qH8%e-ZgyCs^YPmbArO z(0pQ@Kc?OrUgukGx7UE~%iaCFf5ks^mz(k9>~pI8Atzn#v&gs2=C0dF z&yXbSWc`30-alaAgCDBjrvR_)?U^G|w5^RbL>uGpys73M(5r>J)EU5>r7p?e4t!iV zs6+PrHT|bCs(DXkHiT`4K+x~JiX2y87T;h{8XbVvC$+A5&tfo-{FLNe$Q(Fe3Ji8E-ETQoL$${o%~!X+!=yb0Lu zAU79BF?TF2edg_<8Ok?@d|%bPi+)n+=a7C*aRPQRN}Dd{i+cZgY3V}JzhQ}Qo3j^9 zS_^0#fVU>C6EqK)^Y%{90Apm(vW(8l=w6Y(hWYw0{}9|IFPcb!i`gNc<6LoSEc)Ci zTzu!-@SvGh`#;*htLwCl?p8Y7n=x7*`IXb((%L;b58ROHDobDBpzkwlxGelD4^PeE zLVdI5Aju!lNJ?Y7+2Y-Gr@Pz&J{$gp{hE`)MiaIaIYl^KitK37Uei9tSHj%M7@Td; zd4@Vmx>(7Pfe(&2U&>hp_-~GI;fym2RNWiiGudPAnN&GR=>5bUlkmRqj!CUaZRsP8 zjV1hAYtw$()xp};%mr6UKO1KswJwr_?C^g++h^$KSAzkqUPGH#acPtEBOqgiw zr~DW17Vcl>dp@$9SxdU6;0{imh{xWW$X=$+`spWwgz zZK417q5n93bK6VijD+s_I$4+ZDDm9W3xB#&dv~ziK$kas4kFUyFiv85^fozgl4Y(b zdB&qTp&ms#bBz~`$9J?H z-F1zNJw&F5*xEFyif_LX$+O=~{b2T1449T|r2=uU|m z&P$!nnp^Xp>>_Mw$er@5u@B%%X`6qg> zBsynmkAa5*tN3O-8}wTanw2ep&f!ZQXoa6r-dfo<>RpJ(+JZeCbj0IpihZ8tLC>WF zq`ewD-$U@deViFN_Jy_c5a6XDN zN4ueqFc0QONB(vx& zW;Bi^m;XEZ4xP0T?ZV4a5igS*YC*S83eUn}R&p8RJSsmtJ86?IRse_n@$!^g$-~%( ziGXv?4TXC&x?}Gea98KvBYC@0Kbbtpsdd(ue8F(VCB0>H-iI+LeU{N{xn9Y3R}T!+ zAH4Hhl#w9M|Do-D;N&W+`~Q3A&g`GblH6rCc3q;}&2C@`D^4K61y&hkvC+hK0s*5$ z9Uy3`(GG1yY@<$gXY*&9&>FD>0xZmRf45 z`+I+$d+%nlfcDq#_dBoGyzafvpYxn^p7WgNJm>k>nOFKtIX_{n#+@78VSa3F@=M2x ze(5c>NwuYr?xG*t!zweL+Z4?S{vCbDVMk?drkRc&0)DW1yjkIV?J@=1@#H_&Kr z%Qq6k*IIJHu1B!{-thaoXlo)o95e2tREqd@@uSt4oznX zgP^npjpD=Y#y=Cbdpe#eA025;JAO0#NoH;}eexhS?Bsx>`s*ITW}S;IJFl}`m5=e% zB>UzLFt_wHwj<>y(GxB0`-3)nf8gG~Kj^IP*V=02@M1G(IoUSb*yfXMf1tjvdkDLB zvTaUXIxY+B$+p+(-PF}=aJY}WgBIa#b4_W}h0VT6=cVvvTAbV7R!c5;$k@;=Jr8l7 z{6pMt@=(xu|3kqr`MP+I{g2{N=ptc3eEmH(IIUkL0S;HK|q^$jni=OzftO@lKW!6^z3y5N%$zvuM)fU-lIrzLk{ zO=Ior$nVyU$HSZpfRAlOl>bl3uQp3vnt7{!YesM}`E-`S0Q5MVt0149W1U!KZ3%v{ za9r>@@_7qX=EY`R!9M1+q|@&e%RSEqU+Sjc#1=jv3-P@+| z=WpQ00Q||3CsTnhp8DOk+Q9w$s`3@Yx<&KHotg2P{0Y-xcSf+~2Szu%r0nPEdsO!6 z5sverZJ|$D1K0)Dd+Pm_lVYv)q8V~S7&C~j|)HBi0|^Z2I7yG z4gI=p`K>`8VJ`G`mbvecG;?xW4gdcE`a6AO5uV3=m)87<&q?oA`b6}Ncm$1c-xbqi zba~W&nf||w+)adfRd{GlHkp$ST3LstZuRr3bHS`LA2$oRY6Bk+y!r@F`rymo<=@F) zbj;zeyFN5V7JjDzM{OjrV6)%meF{6{M#|yrFKodUY(d#vR)&2rJ?v@54$!-+cg`5p zd#B!q!guE14?7xz(k_IX@XzXe2iJUyegE}-pRe`C?=ilT zU6tE-UuotDSMV<0Vs|4Se^nEnk`Kv&1#a@`-xT+Q7Q8-)uRrR8)$eF;x|=II*cu&1 z4$HLjN5|^Sm6G=D>~n-Kg;1B+dE}tHHAp}gYgmzo@Vp4M!CPLBkCJ@N(4%o=(!(xM zUdmUVhe#jqr?v=xDzef4&*+7>z>n!w9g5y}z5>0m4I>$rt)ctxh}m8_#s z`AguJ_>_WA9&3 zjk{1`+~0+*ngQ1sH}w^9e$EOobhRvJqT;NR4 zI}!0DMV!tB{LL)0rqsy(Z_YsGA{gqQPNc1ijwxJ7uk|S0*>vtc_Ild%Q58egQ(>H#qi>)L zx-!NNAu<*J*59$w`WJNb;}hTnvZv^tpr1oS9)qclc1R$JJ@vR;9OE zyouSY@tS=DPX5?8!_)4xCW1~+dzTpVuuqp=5@Qp+y%Te+8*fs&$~obkqk<9ZF12yt ztGvpGP9Fu&ah)Fzj5_(*vyATu{9XKq$TI74(Ze2XFOv^!m$?<%8WSSV#`?Lj95=38 z)-^~c%XdCiR<=A!+2e~F%9)RM3jAtv*j12ayC|6(OE(v;u(IbVe!O6KL z!OhK^dCHXi$5Gj@%3PkpU&67G$Ldb{ zU+WiCZ<(mx1fPE1^huYBSFCYly?dQ;!T4-Te)y4$pqR9{?UQV&Dw{PwBAb zv|iM}Q@fzN9|tO<>(RRQ#({XJ=NYU<{6pZ&>e{e zAL(H9!Xv_$Hky`yMfgb<4@FPazp-6-s;({O97uZ@TcQ4+^b`0O>Z~)z&snasX8bVz zox1K7)R_Y6N6=019T+?lmSpspjS$y`>OuXGbVrIb;{V6cee#D=XLalj!zcBN@SC~6 zaBU^Yu;Ml^ zxjBa8F~4J{tNFQQs)O`JeFn=(X` z>K>Y_qW4wMt22{gdewfAW9*#{V=Jc;;od6I8n>UA=D7XD>quj{P89GV#@9`Na~Yg>_WE6#qs+V+eUS7y=aaRTI(M}^ie4Sp`NzUlaxa?un9J|OFJjI= zf-dU3x^3qGKFm;$o#HPE=Ap}Gz|Vek%l3#?+JTwNSP#6|mT1J=2G2>iUGq)0z3U2G zne-bP2O<}Sj&ixG_7%6$Gr=v#n4&2=?laG0@Wns3Db1O;t=aN|bhg~1`5&IPd}y-Y zn!y*DHT?ckL|3w~(Q3+ zQx^+od@a;VcPHn|N)P9d=M;3&2GM0(1L=3&ubpt2PeZO-s0Zoz7S#iJ(J9@sVNZ@= zsa|A5esCb%?-$$5F&>SwFS(lP+o4-J4?SUY<@IJfoHKU1^rL7V9rD}n;4hj#nQ;aFWL;a#x$93P5M;SA~u?5++kM3bvwRL#KpIl+>;=h=Gj{he9 zMgG_EFYsT@|AA@w(5oij@5+-WpX_?t$5eUJlW}>kRF?9o52rmdkItBqr^OS6dw7Va zWNHpiblBl8p4i!kJ9)|;b9t&gbI*Fc=&slK-9{E1~@eV`fZk+H#&Vl+}-W6WH+D*Mcv^ z*iyXTUap=F&RTz?{YSg(R0g>}i*aTKeSdBrJi20kh(G+)xCs8f!}xs%(47g+(bpPe z`W-WO#+KZ}^UzhD%%RWg3u)B3|4ml8dWyHi=<9jdVA9!b=xm+iR%no6>1^>p^h;-7 z8SxHW%zCarHfcke<8gf4X5xOw!k$c8#e`@+gSxrbVsBdn2c=-_cJ*^z-jdoz`O#Kj_uxF*sEiu+A1%KZh@)+4P_{siy5nAIuv3Tj1W}Xl3WLnHQFP7SLA~HtxxT4~BZ1c9h76^(|W0zpY$7-|3Vc)O{y-c+~w~_`#a- zXEm;uZ6g1!!X?Lc!ZrJsN*?c0U?d5P1KB}i!?qn~^ zu8`c_BHEA%+Cw)wsVZ5cuc>Z}!sUa}cRTsJiTkT49KCMjZ7|}MSF1IVD79@=63(|n62rIB8}l5gP>e<#ivHTKf-v{ytlys9DZ`=hXSg;8I^;}pVT9A-s0v_|p5<6TjnWJ8`;H{_WS z<$3X;5atkd^dG#(biXai|2$#BO=Y$=IuL!KEC-uE@+nMIzs z4XMpgSEjFC%Tuxv+dHqyg>6Xo&fk$=b*nymKk#GO8v(v#?z6;y1$-3$@5GBQw-ctm zK8rkS9$aC&A~>S&e??(}H9F{5@8B<3H4%qZh&;Hk!RYq>;TF0 z!7S@!!PUXu9T5!rEZJQet9^oR)wOv4ZD1<=V}!*rF57K8a22k4{xjlY`4+tj|4;-& z^?Y9xwmJ$^+tHkf(p?q7olSYy5vKZ6cqWp;%Olu|zbndfSp)39AuO&R>02w`eDp+= zqv|HsZ&o(c8;cvt*LmCG@r8tmf2r4D|3+bNiozzSi@%P-&S@xfJPKPFg^5pNQP}GV zQ=3>pUd?r?jQI_D|1t`jr!aJs%04#=n_jnbNE6rXhe#9asqA{oigi^if1JL?pWKwmmv{~YZiO)B{6g|Jic8S}Bz8m%NS>%yF?Gp0D zvK-fIyk6$uE6DV{*<&*O&)+;=rvH&|wXa>?o}imDMC-Z23p^hnPO`1`_ycfL*w+b@ zOe<`}8>ycV(fYb5&zFf;J?Ejdi8%Gur$ljo7r_&4`y+Uti{Kf0PaCQK2jQLMc{O>a z%Wo@fH>NeNU)k-kyr>PUp6>#N`fANhi=V(YZAW+OB9lfx{0nLDVIH3B4{4PS6P(>q zUfIUV>)|(0KRpMWBr~hB!?mN6laIvy1KT?0GbwKf@3{G0xQ)F6ZjE()PlVeO({Q`? z{~~U$%F@Q*mwc^@sRPw#65eRuS#+zeN04dBZ8nORF5O1F;?5&Xa(Sw!*)NgKb(hUOlSNXy`-DtG9N$p^6FaB#WEl3Z^4N5 zn5qA4sLNhQTGf4jRDX85qh7Z5%;ul^;+I2Tv}`oxnH#0Wk7w%IIfp%2t(VlVBW<(n zU)~G6gA+qgvsR{C?RqzG@;q?Ivq_r|q=j1>rzEe9OdtLzE3 z@@;gCvGM#V8}Iy0S6lDmzlr~~{6EG2bNuh&|4sgn^M8te<9LDf7E|{rS$VB>I>_1s z_P&-628juttiPJfrI=f(1kKc2>KB{=LY~x0{5Z=~HS5i+X(4>_=hm|Y&hb;6#Xa>( z+kCD=KUk{Xq&$4jVhz0F6*fVb=A3Qj*c3KvC`|iv;20R^hI7)+*`oaYJLCu2C^CtQBOccuY9rLiOYJ_Kx~X~b_eVH%@O$M3-y zF8C>aR)pV5(#scWcM;abURCf)f|qUX0yD90^5HGpVLEu!@VL)fjfM{1Ayu-nYFm#zOepGgo~HpHj6y zH)D}CQC^VA%vhAjvF0H^W0B5iF?*&t!=r`yBG$8V{yq9SSFY>)fjPNSFm`IVzDMgj z)-M>rr^vm48GK4SldOf8zluiA*zOj-Zw*rN-45BcJIunDP6wzqb@H zt~=}kSN4q7(vKno3D04zICmouCwn4IAJ{=#5*{}u(mpa%-4Cz&;n{7npOLqsS2X91 zXz%Jua8#R$eLogF{jJR&iio$GzmMkzmyxy$I9q_z37i(MG6lz4z5CExPn8eNJ}MZ; zWS4Op^`Uwd@6bWc5$-#ouIc0OEdoorQ@)wKY71uH;&Pq;X2!PL-95pdk;W#C)(qny zI&67AfZlR-9q9!p2_27-MqwXpfVcc*;0*)sJrTSaz*C+N@ZAr5$WE(o1;0b`N7=cH zkb_I>HE>ChPT}ftd$eUE*v$3K@|L7# zdfZ*_E=jrcL2hPA>VyjKl_j&~Ux?>S4gaDw-|90Hd3eVfWUCPFi+wBna)z2~s-HW~ z8mZpRxqe6JI}JbZIsEjL(8kybOyNF{XUyji4WJ#ks_}O~je|-ns`UXCt&4SXugsOu}yiPx(YN zR#x~V_F9bB^Dk3h&rx3*g9$I%ioxr*eEZXIIR#t}D$MALrW3U;-P9FN$(8UhvW&b4 z5Ba8;FM+2c!L1Rmw8mUG{ip$_{LA395}f`y!s!Hjgp}2yd`}RT%`gwmo(aP{o>3nj z$`!c4rCo%X~U+LzXI7Tj-Zz&%4-^vI`k$CXdG5!NNRdkK3X!k4f^aoZNI z-)X?l;0BI5Qwtocn}9dUdx`R8zk2KuZm~wucVYd>Hy~P6hVI*o>t82kRkeE*Cz zs(a-sP`d*aVnYl)xT_~DnCdlw8H<%kaGA-~!4 zbz_9@Wexbkq~mC+M)-=3mR)S|pGIDioO2-A z5=`}Z%Ydu*pG9^y?SMVFFNJ>>a;3Yh1Yh&$%5#YC9N(1F!8{QA?c=r_-S33X)3{7+ z&@TL8?Gcmzk*Bps;RoPt=GB4Y!Vgn_@MDOy71GHUn{4QJKQS+~$7SoOY)3rJ=Cpq( z)D?uQot=-o#`617-jnKI8+`Y|-{=SrzN){;$~N;yX(yZ1M@u#|hIg!TJ97*0#`4vc zm)iExHvawIo(lRgy7*F;2*j-x3V{iq|D70_tGH{v4@sJ1L3ZB6ec;XHG zx8VQ(2oCGN4PJt?7#J=8LpV1#z=1vs`XYRe*?bp$fjfUWk7^cYPQhd9DfG1`x|yGW zHhupKaG<+>E@@|RCv%)mV-)SRly639B`1&bP5Z9D{$H(wEq~T?Ni!@@&#A+ zLyUvc-p99ac=gMqT}hlL9EdkKuikx#H3Wy_cC-a~Qhi44$jGYNQ6fj(oiZAryp zkTvNj{4hqR(T=)Tk}uX-*mPRk2Taxrc&u$h*6dto4SkW;_`9xrr12QLT9)oG7~dqP@Rt`BVI19fI1V=0?#YEjD}JHBV++vqgXRIuAawS4NLC;Cv*)S^c)1nXR>s-9^fD^2p~jys6{EU$$G&e#>G#J~(QfvG7-Z<%I{7XXrL~6FxQOkJq{hccWW`mvlQgBI8a-!-;0EwD@mm zaXSqy#;!$f?ZWYOAY8s;-BL|3u92M^eF0Is0$b?!x{f9#>A@rTd8Dbc|t0C*2mO z+l&5;*GH+HShcMDEv9 z{hf^6VQF3)T+u7lc>H|#x%APr*BE!{6xE%Xr$!DXZ^K#6D2C?b+1sNwQVM2$e)8Fj z(I>eodLcc7Z}rJ+WsLzZ`7Y8V?x>zguB{gRh6e6ii&t%Y3ZE;-frJa}(Q zhN*Mb4g%_3#J{5hp0ak)_}i))vq{DTLwx{pTaDLRNSDOz(zH4FlMs&JEc}q?^tA>D z+PUxoC()a3zzcjLys*uz%S_o#q>)|C;qFsqYpk!bC66k%v2CedG`6<$==!XDhq4dC zd#Nu|J})d+Jki(~TB@3F6)(Wk%&UZQ9{RQ9mok1XJ7w&n4BxSg(=M=$+`7kE__kN+ zklxMqjLt^ZqW$T}Q*zYEeU|)|#XlLs(f!J?9H}4ivdBfIShp6I0{LT}ieTHBqLW=v zN@dh`$SW9v75mskyZA1;!MjUvZRnSs(+A9x@h6J5NBC~S7C)LS8U321-B8b86|H^1 ztJtZjv8iC?KNrqHN>*pU!&A>6RV$x0JbxuolLO z>#*ln5+*xm1$ZUSF4hyL?614fEB~b1R|;+?&OWzTx99JtPvx8p!ac&}8$CkXEC45y zECu4l`YXfx0VZfCMgHs1KWd+D#3PSqCgQdFLGftiF!p*Z9|i1yvnV^s`cs}Gl#u{_ z)}~y-K4HFHt*7mN4Yc)hZ%Rz-tNET2eT&vk(#y_ykvlhB=@4f$a7klDX^{8s1U3x$ z>+C7nIf)+7n3l0xx`}i@CZAxdUA{n^Y-MbXos)Mm&)5)mlsLfv-p+l_p5Ri-+(i5* z+bZ=F+KTl&<^GC1JEA;-{|mmiMBiGAbC~a9^sRdRDc@_OZ`Es!@72+_>h&qUS4Q8$ zPi>aD`DgzZGW7%EUOOXK_Xr;Xp9O@!@a8>1^SPCJhHrb(XuXL$+*HT&iEBEKI$yBA z-bGyE?EO>qtU8`c{EOV1W)WAw#%MZcznQmufOHx1cN6anRq9VC;1%<4S;A%$mf)_v z95S&LeEuGM9@hOK@KQQp9(dhL`Wd9lU&)va_&fNv7H$Zd2vghtEO}Dm{aX$=>GMkU z>*&+6+0lAA3UAIFa8{EinH|L!zQK(D*QgBcsasCC=G!vBlWweJEA<__OpKU)n2EO{f8<%)0Aqk}+1tWLih!Q+BWmTRh%LXWosCK^SG3akX%;z(sw%%8Knq zi#8&gSa!y_l=~!br8{4nD?9k5==U$HGcT03xr^p;;l8X~JqR6pC-zm{vV2qG$++Q( z`X%|InrSl{-=XWyP3W8VUfS#V)~o70$c@HYC-ctwR>vW3PV|kz)Qv4#U*k(I-f8?8 ziGi`2R~eH%!db6nn|`Pr`?Km~#(mox@sBQ~y=O;*qkSXTo#l3uCO?91*%HRF#vOmR zZB_U_u%&KGKXAu6LU1?~WD#D-ZfiytFdnT_ zCToFNk1Dz+INOUkH7hd?EegAyzs4cr%gAwjiEZ~-c6?;jM`oYq{}Mh?o*nUtCOa;h zD#e@#dOH1Bt)!w0Zk~YcrCwa#Q%X#qOJr|ddZsjuRl4Nbg704aF ztG)12`?lTeXboQ4@DzTA?NMv{#LuQ&xt)3JusuS*W9Tn&M_mZF1-P1PQQ8*tZo=hE zSQj`tSJi_C_<+0~KIDaIo~C|Ynr46f(QFuBDe#1E73w_+KGG99k3sz2RSDDV09LY4 zZa@9QqcsoQXZ(D$CVL9F?fAcJ$rSr4>_i6H&TsG?|9b!EsttA7f=8dezHT!PRbAWg z*vXaK#lMrWR~*i@QQaDzWj0W+&`5o@ndcbq&}8bBdmSY2l&P|G=EGFoMsk0UIz34J zKF;&;2Ave!*T_~?(0%^*juG2mh{K7h8n09=T_z_0^8rQ7P1Y#KZUF`h?hC z&_0wdYzN!D3V7@NaP3A|XI7@j78K^rG`E>qKU;B|NN;(hN7rdhLvy7(s=Y;KUaCT! zdf085Jwb_mZ1Bmx{`GIhhcb%q13BlrNM7ABXlL*(bH9jWM{tX$G#@R#uleZWRn0~Z z+g^BXV?XI`aC&{&FE;Jf%4>hzC^iD?Bfv%Xu83|ISYBnM=2Ab>{VkmL==$h>{z=kl zPQa>6q}nP);?N;Y;lBMg@U(ob(@>ga)t?y~Zi4>xlIl;HpOIe%|4`M8!?R@@U-Gl5 z3rfCtE?$erhPTLIf8oxFc_r5AN63+#F@f&XTSHzS?j;iyZ|n z4rL_XT=I8Nj^L*%rZTn zc&s+k27Ybex0o_%C)IQddkiOEzkVqCPBe$#SIlG|XA~#;mDY~py5h9NqoZzA-5u(+ ztT*xhRm!q{!T&nas6A_JZN}Ak^bWj5n0_?5?*9447>yK9X&`sbQX69AA#3hl;1`9ojf~vnzIQ-tJ%`zngM<{B`Bs>|-DByDZKy;Gf70a5iJF zpXR^T+8s0zx0-x;(mn10hww^vH}co(uOM9M?(%nI!_V_~ktS(*{=q^Rukup4Q+(U= z{2cEyy}ABO;#+y9`M2^eID^FL=|#^SdJ=ztXA@7w?Tg~pMRDcmdu{Z+J^Ee~eHWu| z;VxL$McneFrQJkvaz_$$5;#p|4jdo#O()%o3l3JIMtg+m~d5jsw0IB6DGQb2yf;)O`g??qpZB*C|`VC zqkNR}gyKm5xZ;4*nxF6QBWwlV&G}P&@oA86owp&{`^YCaY2c_HR}d$e$r0WxI)N#? zgj1*D$g`a|(IA+TnViDGtxUKto{}dU<#}3rycJKm1?2-y(c2w}ewBG3ic{X9Ovq#5 zbscF6O2fO#+(*0v+?7frT!FKSysf-1C!J^=CXMQ7J9!<-`!Q+7i&exolXp`g#6xwJ z;9Gbo|90Zj&US%jAcqYF@UNN1CN72m3>3}H6;9_Cwe zsc@V8eR`6vg{Nh4PK(8p@Z~&3p9TDtybHF{TEHmrZ3FXe%kyEv9nveUMZ87) z;wa1_tUt;x_$`DdcsBEo@oEOPXc9ik+Y;jgER`uf2%iDo1#juJ@>P%Gsp`()P~L6I zw5|Dm3-98qc%5+P`z5{yyb$J6#ZmTRzKvY+-Z?=WaQcZ8kDthshVqw^Msgxt1{8;k zEmRzEkN8_nJCdv)s&LL6xJW+KmY#za!BO2mpWPa~klPx(2n};AZ&XKS zebvT4p|iQ9C*_~*%4`juN587Sx!_;6){bzNjcr|1UyrTGT7(4pSa<8TW24tOOQRjT zy*)8!v|V#b>fd5p2tDuXo_me=U2Fi^Nz5H|t53DgX2f=Fv-N)p*KV5zcOh`s{y%`b z2)G{!Z6DL$7A`jSTHOC9-SU2XE|1vON9))D=_F^DrCiP@qyMkK7oBZ-ulinJVfcS4 zoL`px9{QKDENLxwBq+PsV)T)1Iu8vyAjvr;+ACzzlg^Cw^EU@Y;H1dAj{aMHIrU_> zF)!$_zB^?Vjj!TOWl>-FN$gwx8uwI7w&_nhIx_dSpJ(GP1qaB%y$hACooQ&Pkm}Upf-}^jB?>7TI3Up)5=DV z<3%g}v2hFB9ek9s7bo9q)wI?s#y_s7$IY4g|9!kQ_E0_Hv#U<8C)tU!OkIX{q7}6T zYntqu`oaE7t*iHJ%UU=kLI4P~&jsQ>_BNH0U++<5sEm(Q`?AF5~?u z?H%TB3w1n>y9{)bhnOQ=i~t=gqmok2HgSyYvLQaxu6po`%beh%Yxg3E!N% zZ)E%u);`EDz_}`kO0_#tJXXGm56jO|hgs@ys{H)2uzczUJoopgTNIKm^*R%C7H@#Rb2eqXux=uEkqN75X2 zT<+}+G z3YPRB@8*vm z(a_;qyMm;*3!IAhv$miMmQ_9c7QZrd6Yjw`Yl~^~A?>`AuE>3LmV29_y~w=4G1@tQ z1zq)8uzhF(Q!-Bapee) zT@82`SpyfmNnFc z+9Lf%TI&=ot6Z0_Qh7vkGNPHZhddL1DffIEzK1-C>Jt8%xrT=~t+t+qmrujfxGtx3 z2yI_wVN-u~)Zn#T{z`*aGRBMf9Qxt((!6k3UROWdMBT~Ons0c;`ZRE|;VE+6asRCS z=sxr*X<299jxM1e6HT1YM>^!k*n+}qIXEo`x8wMwel^1D6!3a?gcml==eLW_7%yya z?Uz#@t+I+%C{rnLV$E_r#d%x~Wv;yY3TqYr0{?aV6W9UJ!})^JkNB5aJ`cLGK$-p9L>W^gLOlW!n zxKlC!P0T%WX5(_;Ugn@n9L6H)dkl@2*6)sJeDps=BkQoC5xyKA{PGo6mj6=zEBPnV z+B3qO8SBTIpeGf*Cl*0la@5e5fW8E6LHl~3owbpbv)~8w{2Du2Y5Crhtiek(h5Se~ z6-ie#a~7t)w6gkzNl?X=Zok)BD)2?7&%mZdlSI{Xp8&N?a-%j zg$3WXFt$LL(zal77y63a_TXLn*!%6WUNpa)*IHjKcz*~in{^>pjyUWOg=@`AM)_%%mWTYZ4nelw6Q+L+(>&Yoey@2C#|g2W zB>%U@##*NxkBuc4_lo{_-(w+^4Z92vDieX`)HE+b+ikx@Jb*Xf_=1AW>#5#a z>iF&3OC9*uJ3ed5V9uQ~`Y0nwd`|Ep*l#zm$H5I6vESE1*IMY)d6q{e9cvEXbNDV! zo*dfr@fZ*K>}(M7DllyyXYKPKg7H7gu=}zQz4S5y5 zn!ItIfBHRnWN-DcMxc-N3ua#^b~V61-_>P3tFTVvH$l%ZZc{o7e~RSp%OTwGoVHhh z(Hy~e!pPV$7zZR{z}Wi=Fz(8s>%fEcoR0{nfBSD990Gty~uxd8zDu02E zB)pX$J@v>c(ugN{@=~U~u^}yMh`Wz|S$B@G7xX8g9BW?dR^C1Cn($aR@qNlhC!nuF ze?WY;q~>EaFRMA(#mKbIRMU80wz%YM6Uu11e5qc|9C03dQ#u3NUu$Mx&K7w$c*b^- z`b^m&tG`4T?c@MB$8D|vu0zl`;W)lI8xGo~W5e^}F0932(ow8kW}FNitRac%i2I@# zU)_l!y_1~_-~4jj*ip0%t2_~8PDI~5pgG@nRq3N`vqs4cpPEZ{DrLKqe2jCemXAFS zEX&7!Rp0K@w}ZEh{q@4K@LZ4Qd$6zhK7vdon5%bayK89o&{i+G8-pT$_*6yTbRQ(G zO}URME%1^abrR`l?fKUFo_$fAe8oENKzO{De%|22_x20+1lKftmv}FcM|o$ic#!$i zTLLFrwm&Z3=f<$dO89+l30CC52|V+;jloL(tN5?xuQd|FwV85W#Lu90pF`~-yg_hs zBHoBsTF>Jw@ay5awe`V*v$Q5?1YXg9MmT7%XEMt70(Gi9tUECD#{SepS=Mh--qU%? zq3pf#v4B7N&Q_cMHuwLIWza?V%?sLVLL6fk?#Ut_{d(%W(P}c!evd)k@fGg{-pn`b zuaBKGTHTe~6YTQ&S4@4_hrBn}67VC*m@DCz?Jhkl)Fr&PXVd4ao;5GcIMnj4H~ooO zbLOFM(f@hcL!S1qivMc|J=*nUDTKOlIj_KCbsj0TMX9* zu5kF}KZW}#RCnsP7yMm#K7sNWeG#AGkq`Ss(ev5es^iP5H=&o4*eas;2IEKB9xTm#vkk$0E>TIf;Vv0xfK!x23>=oy2a#pKIc@CzLw zJA7>eJp<4qK5HH0E77F;>_peg(e#sFAEW6<(R)mj?ymV=Gz~z5?y?^8#)5^s5Arv4 zLY;|zy_-6RU+Nd)HG*0rB70o&xE8%38CH7r1rGc)XL+K#Wc&ZgZNRFCmpS?Q)AA?k z+-RLIGE83Sz${@2bhcF)#h1w1L}cUWF4_Tg27jvw%6^XfJT%@4d@7ogcscp}{;lC2AYi2*<9(R+;n047 zmHsy0gV8s3zJV=xmIqAWpT2wYaFX>Fp?IIfMq18v zS^pBS)!vd`xfh#izS`UOps$Pa1YdThEgxKZ6dfA27ck%)qvUZup+r8EBgy3M2xjV> z@&fj*F6!m!3~pFpoj0-wesiYF@p&cx$|o4tM|nxtPk#D|JpuWvUEpQbe6cSEIKf@u zsB?{Dc-BcFOrw`LE5hg{c=s0(Jaj`Zyy$NOj^y;@7OUp9g!Ck#C+3UQkoSWxllOY^ zPI9i7$NA#GJJguh*u@boE2F&hQ}a*8AAw#RS6kxlO=BxO##8f$f59_F-JQ%CY~uIH zEoQyC@iQmkIg0Htbz|(RxV)HuqP4Ni^P@6VmnwHseh|+eWz1yC)_E<$;clLNlzq9% zX1&}bXT_=PNv$Wx@83qq<%DRY$l8=IQ3Yx|*f zlKIF}c*+L(7-dVo^sauH`SNPqUV%ju2Pf-N`VIAWx(EEy_CGM~S!b|cYODQeFMfD# ziL15a-OY=!?K7>l#091L*hQu4V2<(4aH+bGbUKS~)=+EBSzM~Vuy`y;m@=2M@8?!} z(6aO5;8+S==@xx+FG9@Q7rKt8U2Q=&n&@{X!o4TDqpzRy+QfqcJ4MT-+OLCrUB+H3 zYrL8LC)$@H`dK?NF8!l5nxbFt7xA7fU*_9o%_Ch#Kl={4DBuI{E^z+=Hh_)IH4hq7 z@CmswdX0Gaq`67v^Euy2wv@)9@waSCv$lfr@lAL4dnX0rk@&L#{)m6A@aM%$0$V}+ z;R%0a1H7h`OdUAILVsi#F_Y3u_=rV^5NZwzW7`1kN2l+67f!alWa9okstUeyZKtfx6oIucFB-@JXvA9=E5Tnp3A0zSGt2o@@ssY)8ZB9_(jL@ zCBw+2&zeS4&*)^eSL@jQMpJqvI%h#Pzmch^{uqb!e+c$oaGC(-;@DY%mKvOCUiLT9B(hb?S_ zvvi5{xOiBI+FheQ8Ho5q;q%p(k;n8kzq(a*5cXxJt#YrR(Ln{$lsTIg9`};>9>%Zg zzfK3wlli_Y`aYHKllU%2-@SbQ0pHuBZ~5gr_}&zKvwkN%i|=*OH*GULgYQE0E&pya z->af;^j_NGdqwm;gYU^tg?+1R(P75>!^92S^l#^}9~S<+)~-LIRJYCDeJ(itUkneKt6(C=$eBA8A)&3O0vMy&otipkn0H!r#gBh1+ILmIG zkq@nhK*sUMIP#YWck1FlSuZ5HhIV-SE^|(<R%}m%?QW!~z8C*-(Q=)m)=AFMWTeZz+ZnH`?}%(3`9=p_{@`Pssr_b- zZ=E?}-gRC?{Qh#`W{sblKH6M)bh7I;?PeU(D6badbKRdzeT{2Pzo&I7GtC*270vuo>TkuJl5+h;!JkV9#z>bu6$E_f=?S-OM!I29^N%)>`;#I)|gp(jk`6B zZD_Tpk0$xI@bBz6MyuwK)i;P<>A0=rDdW%9yVlOjf4)g!z>UL_gpCrWb9~~k7Q*Du z^zg^WVQqw|UoK-q(eKt=i!rJ6k#LZog?fC{+cW!N51-(fH_Yar!q?1Ni2Y6ydC@)= zrMZ(ddmGZ=*Jlkxn1(z5Od95LW)~aM;GgVBMrpK%MR4+@S=o?=vw1qaD2-%EX*hdl zHu8H6pF!{$49k-2DGm1bZ0;1CO2a+0tZNO^82R;%@ps)c{w{(a+UF}C$={$e0Ls{f zG0(*B0fja2QM^5sFt4Ew#9N&K;5Fn`y}U+wRd)^iPR>1sPi#kOF7!mwYW|BoC|aXc zW$t-gz8%rH3L4>8s%6m)v-zhIi=c7Qey3#->oJ(;(t2Onx>*lhgD&boX2Us<@az!# zeEOo^N9)!bY47wSnu~EstNfAy)6ej1nMd1$Up*ik_o3NoJkwc;<@1j5Nc^Z1HtVdA zkG*dsjp1M)k9mJ_G{zt-E z;xM&g!VVCo{okSeQVJ@3yR{w+*bX~Me-B|@aXUoMB>A`ScN^NF&iH6-hhHF% zN1Ko3LiPPwg*CJ}$;$17l^epuhg}Lwg)-0*x4B5atpvyTJeC_s$5^n|B>RJTV*1U) z>mIwpTFbu_J-0;9H9SRMcqUQV>@%01(RXL`bfagI`m`Q+cE+Xaf7M+4&XJZc^!&0l zu7~05@pN7z9HRDc2Qs9(T|=1nhGVpg&i9KZC!{GE(WG)>xUpR4z+ok6lNHJ6O8i_6 zGRj`1SVj>yY~9elQ5$GOhR*M$k08uGf0Q|E)>C`PD`zA~UR(OoM{g&SWHl~xU>Ysz zmp$ZObtas3kHRd+s(B|UEYy91gE21OL1_2k%PK~`ERV9M`wSL;G3@tcH=Y7K&D&}n zQ4{?cc020;tnn3580|3)y@!`hrNIu0-U-JSE}KI8WU*U#8e51bYc}iZCoSTS8>>O9 z>QD8kI#iv;^v7o`NoI$z1*M1OGk-t$$PTbG*_ytu;@ib1+H7^y^YC0gtj^H4T3yK= zaHUIH9aZ**ciYM3^>>hd6?T|-co=&nSyA4V^<{(`JwqM-HL%_eJ#E1KQ&;`^O~G)P zbM@ihC~b6vIS;c}j5?G}75Y}?&t={%vwb%Il#A|n(fx|+-wTha6UJ8EItN?$>VB~S z<^gr4F=t-0KSOtYVbgK$Q_>x;{rVQ#IeBEqy4FoW;x^eGw4(y&juW;bzoaI=^rgF1 zf4N!@c^6|3iYHpPt~kMZI)a1l?Osm2=oZeyg&FMSnStN^B=$kg2y#3Jc?!ltp7{u8 z?B4D!@D=S^H#xbGGlI@i-^m%QjHz_bnQRuVL)Th5B-r?2eOj*hF(6?}{Ds?SR)dkOXFM)gS@P1WZg5vTfGO8P{`dKF5uD02kD}Hv?S4*CB=Be7Y6Z!ZY)-!2N868J^ z(40v)PLy7g99Zy1u#B&+K>Nv-smJh)EzOt9f08ghg0l8M2TiRO^EP{e4W|~X_Gu#> z@<&cu$(nrq@-b>({%@FXm%m9o@U79G9YLpB*%?Qlh~^q%IvjjFrtEAuo=5j?(wx@< z>hEFlC!;wo)&ZGyPeuB7xj5iE&vG;qp#+euVy;@p!FQHWTM( z$_J;tz@#_xn%I)Z=*ubYhU4g4jQyxPwRK0SbhOL(6g<0%*gt2SGg=#D{mIc`d_=%~ zBjw4LCt0Q+b8M@KYoIj6ThUg?zV2tfPd{nOx-Bd#SMEiI=9{vdHh(5(#!Qu$D|gIS zJx-@NS9bcO-!s?a&)VW=uoLd?eY~psGnOw4um?KuAA&mf>Uw2I zZA|CIxa>!nncLz!UFZd5xQ8cWglaSC`$<1Dv+Eg?KXX$mdB%t>eY1YSsFn0aQyKKT z^m@4WI;LN;FZyqS{+m)U?Pr`;qHf1hT3euUv_4|cy(t(Kt?o!LjJ`H=IbNCbn5?vP z+MwnSBfa)j>>q!)kx<2N^Q_DOJ!rtPMB(sFZv0H5oa$5ob(WrfB5A z&{HXQbjJLsl$~}{_gl=}9}ab}(DaEHSDQ%(KHdEq4^|l4utr*XaG^U9%<<%t!2Y4` zpc9{g>g?Eg4w6r`A?aG_E!Er6<@jo%afwa+l|&ahvkjV9UyARs=x9t6>ks8E(5BRO zWq*bBeXLEpkKIe!HouG$pgU1QXhd?Vte<}e%i`98{(U84R$@&*3rlTz?q z(y46nPs!Uc-+j4y5B!zS)ts4x-+GGI=&yMZuW#Oen%`Ca6u7+0;DX)MEj%`W&sTwe z#yOG&+WA_Y$y2Ug2rlw3n>!_-QT!IpZmw9*G|0d?q?0W$>&yr0vl3Q~dO`S9V+2!W^vyE3vmu;vWT|R1fI|IBgoKZoig==)_w-5XN z71ne7U*P{V|0DeE7HoBVc?iH^z00p>MemXc!EDrz|Avhv9^2p&$&Z8l7#%6TzBjH* z*64`t+>G~|akqSiMxL@!-w*wb{g7lz^!+jUOOamAtG*(7bWfS&OyxQbZP7tDJ1Uno zB$TVUq3JSY`XBA>DjX{_L0vl$KWCwjXIaZ`w94fh?J{;j6uuFeQJqR2P6zIa26^~0 zc%-3h}$XV`KG67YDmMnaJ#AKv`kOa z+>oZ3G|fdvcSfi`5`0_F)}q;arMil3F3rt3Rwq1Cn$9}=!s@iO?u2>Q-n34WKdC3{ z+*!lkk%_`Qr6G(x9>^wZ453?kLiaCD=h@;O>PmM^z$>F;%RF8Av#+6l)!j{u_cCR= zkxS|qQNHlCCa{+#G?zo1dA_s$CgSeSe2;bA7uGbl-QEn}B+JZYwj#&l=mwpYX!Ha6 z?~J!@s7Y>B*S7dipQ`-f-kpo<`_TPnUvaWhciM{hzQBn&U7LM*37*17d-Oz~+TIb? z2`azl!7ctyq$5?Ys?TQdQ<;r@0UJFTCz<{ScqOy0Q@ql>(Hg_3f6;oXoxO8?!M=OJ z1IV8G{t@*5EdjO>yxC~(@q)i*4m8%Y$}7G;T%b-h&X@qN3g=F_8*AztcXjmn>Ko@^ zVrUBV>Kl4;g z@K0+K%vpiRKpSz)snE^RAFiN-fSkF#W&o(s4UP$D{BlZYutb<*K-^AEuyPRgu+u3-` zKF8iN_Cjo*V{g+Y9egI>`%cZH8JbdFx%$3{Ce0B+(~a10J6&(Qma3rdyp8??(X<5bbS{)U;1>jsegDve_F0K+6@2Qx>kFX{T0_W zV;ED{TIs^wYNDagX%L0P<~Q&-0ylt&j3({4X9S`Kd3H9jSfpMo(o!{;EA1 z-XeeK%=yys@0C8`DZTI%ypl}HFXFPUaXW3f%fEs4bwkjGP2T3-aOgJM_B9XwCY>pd zoX7V;Hr8*f8`X}p`$Jo>(FXiSm2G_oU6a%OKxsSk9d!AH_$n@`-;ci{;VJIo`hC=u z&LE@is$XNDQPR~pj?3!zm^>HYPwc3E8M$up6n=62OD3Fk%7lNBaC^qZ^}hw4Xxh2| z*mzQXgFVCaDfqs^`y>->%j%ydE&Rb>@WYhreJX{WU?l{TFzEnu_M+8M_o%xae2Z_g zAEd8OfREDG#s-SUrZ@kmc>6m=ZSsG*)2LZ>)d|pq~MH?ZK%=V`Ty_@_UnL~@I2!mHy|s>9A~z4 zl2-V}XO?!+t|b3f#%GSmXUwyqmV*xTc7ndM!}813#e55n*21?%euX)VL3JMH&NJuv z;+1WgKPoW}0d|(L1Y?e+ zp4LZy3f-YK(VxQSr!~@_!Y8P;#GhhZKNg6W%PV6+mj4jn!#s61zu*YwU(%ZK`PVd-#Ng3A$%0c!ZzUd`tI$V5#(+5lcbq= zl(XKi*&3vgg_Z*TU_GN#+#jQef5Z9y|< z*S3&m`BKh^ShpvbvkW-EU%C<>1#xbETd?Ml5kGquXJ}usm9wTX*w6vK$p-~Fs?PR@5Cef=5yKcvZ$rVQ*PPn`{? zybB2*=397j?zvwg-il#mW|}mEq*+YZ9O08K`Kw6tB6)=qejt-Z;W@%rU39%ar*_T9nrq-)EZ;X9cm{)%2dm0Rx*oTPmkV}AeX@^g*(!OD{VV|Obw_4$3|aWX0Y zaZlg9et!?=Kjqi^7J1t8oH@(?g-7-T@B6?QZJe{M3M0U7@&`yK8JJnv=sWzMIJ_r# z=A#?@RE9Ip%1YDhXGoJGO|m@hJN)l?8~Y7Evyn5{PW4+Slm=VGo6k2iQGRM-v%h*i zIP(12u5o`M^ly3>xO=0}%sFp8tg*_p8v5IaYl^~Ge}FwJf)VjZvX{=B=3hB~v!5f+ zAb6a1`kQNijGsk&J92!>*J1%v@iPQWwl+_BH#Ke5Uw+7F^kKt=nR~!9UUM%w+^26jKy$dYCb~DII;Z$tBQ9oTc z&A;m0&8D2?!X2Czo3cm!7nPp0%LS{@Y|^|)e%U`UPfQ#hIS`QeyIERvatse5GhyTY7GNc)gI4gm8(Ku`bDxEO@N3@$ctKOTyxA`S_hHI<{N|8!&%; zV`8g0mo%9j_YZtV={NgJ;gR^cf-=OrF23(Fur~Y4ffe&j=QfIO+iwc_HUWJuG>LCH z;Fc+C-MkRy05H_oi+@W=C;ib%-<&62ZAtuFOt^U12MqDhffvIc*%MS>v)Rv5zIZiU z*cxQ7*&WOwjd-*LerLg{HPb_1HR4NGi&ve{Viz`YhNR*+=Tr4k9`RMLL(uiYUg5RT z&j3r|_0!k;hqx1FkT``e1f~t|C37X{&^f4&u9f_T{81aq0DA(s_iPVg^#e<7?y8R= z8xx#635{jqq=UqN+jabY!rR=fLD3ce*ZXZe6JC$6zE|g%uI&>)*86?D51FvAKkedO zXY{Wie$6*Gn!Z`-Hj&>Wt;2gWHo`i-uRMdZ{KY?XNc~*eQ(?V1gSD+P*LNxdzHF34 zS!Hkb6O~^7ihl4TT<3STRp^hQdu;(-c!0bSoU7iX`vK@ryaC{CX0Bnb-$vfmWs-Ybn#4Zz3NSr z7vU&AC;VPtXL<_WbC00M$=gQynLaqWzy+5N4>ETIE-MP+BlaM6O|5U#;3k@s*CG9y zZwU`@hMokt$^MZ|rE_DSe%ls*DX?Xavc82V8__5S=4;H7@HSLaz)et>O_|Mpt)FoO;q+5gojGbVC!0owS}GGkeKz&$Di7lb#y; zz2VWezh3mKbHCoxa`#)af1j-^d)IqT`TRp)`PurP-u}eH|M}Q6KmF%w&-a_(uz%wT z-+TV&o$tEng*$%v;tvyl`u;bc^P9=_zrJSU+$(l}sBJL#ui?Y@?aeRw+OG@ue&fDx ze&W{t-<*2;;jzpwA5XnzQ}UdHkN@z6b)P=@>dWprFg*9P=Wm&uf8pQsZvVnLbeM&6lh4y||1m?qH42`K)6+-@U5lc*qrg2HP5`ebV#mj`!d*E#3tq_%BBB zb&lH}c^P}Q?+NeUO)+-=bH<@5D-0j>@N*ESy}(^wxc50hnnA|SorDeXd_U=vgf)@J zCA}NL65J%;+E@1u4*6C7k=w$()LNILvB~*{9_#So zC|tN^%j30k2+!up4TBD~@>6~3x^A{DeIPi^KbYv^i&iv83GWHl zk+rm+Wac_WyL|N@#_yoChoU?xTX}AZ!dv-PUFvQLrB}Wyc#nOavHVHq*1``vkG$kU z`Vxh5bp`zRP6IyTrPhQuN3i~g_jpZH4D0D^=(99(0Sv)2cUiJ7LhHG-=0|(nwMS_k zYu;Y#EvX@k^=(hGFOazVdM-y6xWj-m3-OoD#)rk8rgHTfvp(+sW9{9;|MFQ-si-(0cDg%P8fbDSL@6ZB z8yQAph!|sZ3TPlQ84M6EBI8?^9J}eDW*kNtMEd=FcbyZ8yu|tap6C5zKj)l%U3=}d z*Is+=wb$wKd&nbwsbjt@y^uqn9c;J~*6y8pRG<9ze1rPlnsP-^x+?y^z2|cDuq&so zu=7Oe5jR>m_5EGtACS)jW{q`N_VdS-RetGq+Nk?F(!xGxIBWgG&;JRvt1-jZRqUOm z>)#jRfc{6psgnzI{oq1XyH&hbF!|4!i&dI&%zhfZoYrjyQ~s zGX^}&5Bj1y1@}4B`KPIG<3VF+bzh`qNt1qB`PNKbX>lXGOa?EXB`wtbzoVa@3;G$% zBa@}Ir5lxF;#ZT($tW%`heB?Q`z#QeioBq$r-R@>D&HWqn*s53U#d9lJUn*zd4?S{)ty|yB(emgg z>q}0)m$N`KbeUivJ#1g;^}oO;A|Zs~4#9v9u^I-OkM>XXG&fe1xYypScH5=fE8OkB z=eH*pu%AhI?@~@>>M84zepY}3C(k(`ZHIjveRi~j?yOk94_F8xEKA8B=21P2S@~4K zR~YYC_e1gT`3Si1SR?ZF=(EQA?|Jn9uJ3Zn3jXQf&*=ki!1WY;Q5(Wn*v1Kh6Fhme z^B&HPV;TKxs#5oR&UoDBMLxFhs;t@<+|2QE2)pdLIH(#@StrkZx{ebIj6vd0oHK@F zWO+Je={x%O3Z2-vfHn>*FEleZj|>NVYU@~S&?-d#Lv{c*jA~Ry>Kl?6h7Bi*qJ=c+zD9*F>K7%X7tlA&=VK z#~6g=mDb8xLpN#i%Ou{ab8GpMnn*ig8y9@I(nr~IsqEx)mfQMO{zt^!K%J`l*m|#j zmwIIrpG>Z>c}2sbgKyI3`^XC&mmeP<-lBSh59FZoM@Z9si6+J`%lOHE)4(!g1|Bvh zGtHRfX%!mK`P!~jWv$X0WehO8!CD2)z3(Mp=iABvq)o2+j_^G}-?S;88sqtXFW)DM z=MvYz_rLuL8fGn%Eq@p%y<3zzADS|+IEMW4Pc;Ra5I>&gR?3Ye{s(!@QTQtHb;O4> zlA~YYd0pyGV>(l;JAVN36%IrFPX7c>%FatGPdZJx@*Z=b_{Cmmg8J$>Bccz*ot*Q> zIQNwegU+VBfZl~0l@|@G>`wOp>(;^GT$uZ+v^AHy9Fr~Y_708#Pf_Y^Ff;N0PrcaK zTD#OxCU7#9x`b!d_Yn2%_MW%()$#8$ooP)E>Qi0Zg~qmf1@yInb;SNBw)y5;`Bx~o z)cGf8j?H;+_b_wD0Ou~=f6jaKf5b|yA4R6acD2)R-UIz_Chff;jj?<3r4t=Ytoz|e8@E%4dXVKQ)h5iah zvc2oP${3G-_IhTCxhAmN(tbev)bfukd;;7hu#bfv@X>FY&j!9jRq(w`yWb4pJHWea ziQf$m!qHc%;M*R+$2~lF{0n~Pgl7gMli;tuxw^fRY43)r_H=K>`q2RI8QwF;X>Sf` zvLz1jZqLTS`*hliVe`;Af%8aLHja}0IiqE6i=VS*mLGv<)8FIbDCDo$3|KipG$30F zog>v{@JR!W>E4v+Y8UX=v)>S{#yG#lHU@uE>-|;(|8Wmu+ljwCcb>2NmNg#rkvB@) zA^#8!iw1*nsmzIt@>Ry;`8E9awhBMH>Gyc*5=;;9-gF%N^pQ5E3O`n^1wWnCCH#vv z4Ya8-{~2vqUycFo>t1OjXhZ(Khv5tFHs#O~#-2kIY%?Q${c{`n4SukJZWv7;U3WbHB$-z_#k;~k;zmjnC$eUF^VqMB^k-7G;sdXttn?0u2e03zk@zG^!aqf0k7n9`4fw=x2f34HxwpOR(WS8 z=V1@dI1*%&EL@4tXy4IJ+GN_2?Aq>LVd*lNT<;IhdQ|_EDe7GQ2=|7p?I8ESR1bQE zD0hk*^j+K9B*yTBWHD&rU&)~vOAwC+;fLT@(}b^4&}jj&Mj+bNUToHSvpqTKn)5>gFDG+}yKs zz*~*CVLr*N|@Z2kT3CS9A<8>W=7zo%9&`7*^l7*t;Mj-kBDy6yNNnrTYIubPtf4rd(VJ8w!Z zZ7E+XW!V>&Lm1i$6&Tv{D||y8!?P&sQWiVUZ#E@Mdnc^$^HWy%{bN?dBg`YG4xJ}! zcK?(Wao64Ghp=jX?IRy)4;n9b-+ta}WJ^d}uk+6M;Ww85CNcLS`CN2neq@|+OlTdL zDSRfG>&cP6)m88mZ&rW8{zcAXo)VX2j+)eM{&TO&MppMVbLDl5C!*W$@@x37gUNwE z%m3I1(I)Ve7okga+-CUE_;KWKKsONQ8Kqp3^oFfhPcj*=i@W&UiZ82P)tL$Gs-oVL z4eXbj>%3;W)?H40GhOl-?nHP`mix#%U2!U#WNbw*S$G!rl-6B$T48N8R=7Nk4HdRg zHEs{*eelS9&w%)lc!~ZWtiGwQ4(qk<#I{q9#>;t_H2^#$vHKFuZKB`PNv|MccB0^LmSOv8|ntE!9P|lR?Il9{7_%nd4l`a60$uvCwZrD%lxN@jqJb`o?4K zvT@?2R(8l&@TWcqhMCzM_mmi`bayF)S1^tPHuXiYhcGL>m3Zl?IFo@+TG6xh07JS= z%ZX!g?Z$2!j4D6%Xg%L_^(5$Xo$Vj}h(^6f@Ws({lrAgvc9zyHb_;8lwik>Gogj;+ z++KJO`Xj+&<2wB`|KC_h{OeOTGXDe*_u{ZI)LhiuRbOY)uI`()L%Z4^oQSQW%Y4R` zyZl9P9nS5~^WFr0kA+{fJ9xN4L*g;+tMH|L6+VLss3e_Lr&HlkJ+#@vToR7NCs#dO z;ZeQC75)pKH$ZdsBxiy7iA7u^C&G4)B)HeoPYA#3)Bo6z|w_#J= z8as{6!_>Qe%tpU&!bacK-n*@Q9xTu)i|IQ`m5+14P<^8Y&c|Jl^R(@hkL zh7jd@8}Q_S&-M#^g!KI#%9}Rw(%!_=<&QOK?=Va{yHJeq9p$+lI3A$vZf8Y&2Vob1 z^_sq=%kQIa#QAMi@Cn~x{cEVdoqnso)#E}Pw*OtEQ?Du)ON}I(fWf`v|-T zD0dLJlvnwLPxbG5@;kwQc3vdiJrjSPJe!~y@jcGSnx|8r@>j#8I*arOhJ`(?0*~yH9r6=571W>NP&n$9S=J zNMEjX=#?Sz!bd;6Qe{3}JRke&cJ&e1Q{Y`T@!UB{pzAM6S9AjKXzs=`Iff+XOeJk5 z_|*C*d9pn<-oO3aifyy@HIkt>oZniw{oM2IdR789?T1g+m{Laa?rT%v2iUgi{_AAo z_f0{Lr+qeA&Cx9S={$AfZ@AXeei+>^^-A};;gR-&>K88e2lcXkC0ec+Nt{Yi6 zQHP(qA>>ruRZzOU=TBP)h|`|uo9uc11-+h?wbHA7*4QETFUZ~Rl;33|8wTaod(6|` ztJ~Vo-n@E=k3;)WaeZ2OtQ~tpmz9CCq@c!+t;lpp7f}ZVhe^uPxXF(;K5J_x-KDC!L!H?#>o0zoYCMjG=hvIx2fbb)|E~{n{4*^OHQ|CIcVO z7XLCl{OM}lovn*JRzGI0DTHYjpF#gQ8&zMeEF0n`+}{s<*BrM0nWB!%g8uzN?FYDd zT<_40?uf+LgR6e^=Vtn-y25&-t7C24BKi6!lu>{BqVWQI$|3ce{v7S^4}(63^jUu78`*oQ zPU-rS%#}vMiO|B&gb(7Y_4tir?(vW662L{Li*DJ>EA>)#?k02udG@b`%Katofnzt! zJtpQsfxUbx&0e^0n}4VmT(X~SC4Kbbc!~Q)en08IAwEg@7SftX(>c7=Nl^X;(hOT_cfk<*Sh~&qsc6c>gLg@1@)ikgvzjCv*3G zB8i+#*@r2cqOO+Iyi&Sw5C3y!UzLoOq?2$S?kRMdhVrOnZcK#p#1!wHUW-4<&5iN$ zm9~FK`EWnke|CrYQg4U(G2z#Qk+*f2a|qk7>oBo@?lALszxOwly^ZxJ6pX>b&GZdC zn z{p9^6dF2}>Vb-z@>?{QH?Cd)B5PFB^@8my%8{n5)G*6@8Q9Q6G;5pO5ujYiuycDlE zhc?=nyKRcsoiN@F_rk2c5V>y}>2}PRU(ej$Vdk7eFd6eJ-ske1PtX{qm>=PMS(L`^ z0e+F9&N>opVi{H^< z%p;C%r#^sRu)lJv;ka;kXcXy!LFeypo>%GDeA<<+cX}u59&JpgjXK&ZEV#%2C~eK+ zTk*5Jx#U{~uixyai0|k8OlR~uV~=`^3%e&^E6bh>UN&^5))?(o=nMEwyu`S~GUF(F zsq74zUp~XghA!dd3i9QXCI$N-!pNM=DU7%SVB8f;sn7p#GP*3f<}a9rKP|6R}l zuA=wUiinh^-nT!W_KY<+b&^JU1!0{`~fVY{cxQ_ zw!+p+x-0xg;^z__q1L=<(p$YnXAJlCCTg7QKfGs0h#A6fmoFa|?D1K1F9M#O?3@&~?UjQ1>ipz}-m|1A3L<&5(hjk9RI zw1II8`tn`i6>Ot{ZJ5ndbzfFNm%k0t6(8~!BY)q}r_Oz_8{>$EGt-P<=f0}}N6@R< zp>K&NXlodsHcFFx8DA(rFDBt4CmZh|v<5CxJ!A2$Z2vhVp0tuSL*7#j&o!DStTDfa z#uPtYv>L2!JIu4iFHuhXv(>GfRYri(;J;Tsd?WDYu_o6r%Al*IzxDOkadqtNK8JFX zlgbr!uBJ0H@pA?!G5YNDOL_-xYq#Mh@xcQeXRSvjX5XehYd=>X#NV;WKnBLV_L&az znQJS&F&V(A`h_>yZ)pwCn5%p{bk=@|AiZ8;RB1S0Z~tX&kYl8C_OVnoonKbgqW|M|m%P<|S*!!2L3P zdym_37(x2aNmJe$-p7)*!+9LsR?Zx&$7L&XHb#5S-f=?3HuSTb7W?mGv(l z$&|4)zP^+4GdGUAjh$Af6ZalDDSmmbcmeIy*0OeZPxzX{PUZ>g+hHduTU2 zI}tAvK7^Z){_DMYC5waPB=i{QbQzy&d0PBC%&T%qWNGF93i*--|8LNi=7s9jz0ol5 zALv7p`J}t2b`Buxa_=*)yn>^Pou z*Hh%5P@Kt2r}>y4$G=q_?>oK6ipuv8&pPZ*@V8m|IPi_)*_hl|u{j{$N#q|(XdpBa z#t}{=NH?YZeB?H5bt%MNuA9~*F7EIQXXr~ zWXHU;bq@c7T1ent#tw6^c%jBOgTEi%WfR7{8k2Byj`VIR(xiurGY8r4JJQkaWuD3h zW`_3c-0aicTJz-0w7AE(}? z7U8_5cM7k+7Yh@?y~-&%su%bjll>PJf~LT!wdfn$!^wxT=9PT zA8CP3lTTQ?UirDySdL}R-@A^zDf3D4_b?YzcU z|BhNSrJLTl{Y7*7wZh7Ibr4{BQEDXNvDF zwXB=Wo0;Ak_7!XV6rnS~HEY_FO_7RyXbXG+eb$h0at}CRZ(klsI~t3-102=zt+Ch? zjD^<3UG59T7m?egFLr?S0J5&?*>)at3f$v2yVOg6=V)KS7=h>JImC@3Z3XdlJm>PQ zwFM7F@ICk%_%klSLr+?O?vAYYFAiW{z}{+S>IF-SUjYv3iGb^V;rNSu3->BJA2>qX z7FS6}_X6kH(NYQ+Qo!&KaJLI?FH#U(=MX3UD_*?X)?4viAlW^v=K<! zY-`x3glG!gUW4?sBWO!HJpJ3DG5Lbu2n|WLluaFeuF5X)4)Txk$T#K#@S_c@v_IkB z_0;WxgRspPX;W~CcREM$vDHUh8yZ7-oh?1&fRD^pe~REvYn^$ac!u6n@EG3TAK(Sv zk8GU6AI!><_EWZv?^k$v_1gPN+*m$0qtlpI;B_@j>c8?F+s9cevdtu(QwUlwG;X?= z;Ia3z@@E#AI+rVdf_niAld`GE6@R@JddyV(*+t$jzK?A}YB}>4KEgigIpEV8jorWvspLMH;b-6!Sm;3z@ zxqg37w!ip0>TV(rex*zDgRAisOv9Ady7SI;mVby%;ooRq>@V&n?3wYLl}*&{o*9o7 ze?=K!2TuA;9ec?8JK~T9ph4sk*7!+;hlpR4lb-_iiK(j#EvcSTivGU#20R?S-4w=H z{8|39!u8x^{cL3&(mzau$7|9(arA1i`CR#$WRLGtc4?abSF&%EzAY>l%0(u-pro;n z_Cf#ILbQedLuxIGo&-d`>0vsAc*>o&~AFW}mw8z%E zGZEUF#aga8rE!~?X06O}{+q7g@H+500$gZMYtPDZxB1e$3cq)fHj8z;g*BG74f{6k zza+2XPT8_T3;UW&MH8gS7sev$6`t(5SE{>^O0Dp}XK}T{|1I?h#xc;l_8_AyU2 zP8y%oE!4$WF%J{FkbkaXpS^>p=A7XD4By)K!0!@HI;*jn#xxo_jrwH^sWw!<#!|lR zClH@y{=-Ay6}f54Ev%dUZ9H!Xc_;Fh+PhKTl)u51@7asd&!UTzzT7@pgUQDfPDroR z229tocC-q1WSI}YISenX(9pb0hk4~w9p+=qWzmytboaZ9O@W~Ps;?PfQ-7sD6`u@g z@;r?XadTYy>|I^Z+E3c%MZ`&dUPK#OlY!$Uwf&iu;Dh<5c)=lk8X5xoe*IsEht$6Q zpZbY_uQYKNR5GRIDVlQ`_#b$^+v~zs4d2Yrw#jbxv&k<1M#4;jOK2ywc-RT>Pp=n| zO(I_BKn$5S2~8`GeSPy@&UuRah}A=-kkw`}7Wue2JOX@cE`QYGKV4>V*mEE8 zt1iY?4V=qIjAYY)V0^(lykNOMg8l0h_Sg-af2|qa0DpnMw>Oj~^Nga;<(^D4>%vgX zu7}G@`^3AV=)!o;I$!!f{wv7$Y`$B0_jn)A`wsY88}CiLa~}i$J^kQ-b7S6hK9nSF z25ECBqxsS3F8AMLJ@<$^G#mXN@rU@X3+j4VYd!C(XFu-|-uIGE?d17>>o1kGk<{2eA)BG{;&U~b{ZjRljPmz4`$0>1o(e5w;UtLL1@6;9GIk zVH@8A=)F#%Tqkmk=H6cF?L#(bWDaT`KMU@VYy2%ybC|Ii+Df|eDQzNg^k=BID(<^6 zgA;f&^a=VXxTT}~F>q(caQ4Bw{Maq!xqy0Gc{k)e6q7Tc`5(;-UlDJCa?dwF4Enc#1ig0E_L}1<}P%#<(kwoe-?7VRy(J) z=eyYE)jX!}$j29#(eYb*n=Eq-`_Q5NY3?;NZlK-;<+0>B6@3KwF79Q{cLT@4R($T! zw&0kHd?#5)>;Lue&ut!d-9ei4-YL?Rww^p4q`wS~4#wnL&kX&Fcb)BpcfiCiyzNWO z*WnkEUAlSp5^g1A(7iOEfVh+QU4&-|(kCoCr^6iKee|6j<^zNWez3&sB7B_pH_yQ4 z4*nNAb+PIF-V$>qan}-76K*3&N4b&b7J}A)#GrT8O^R>MXNExkvCIyC+;=(b|exsCTr7>gXw5771ntb6*8iW97Vn%k}5W)}baj*icjfAVwmg)ZkL#APYt zoU;sCl|F5`|2SiA#}pZ08vH{#e~s&Q#_w6i^3`BG_wucI*|fI9oKD!y_qjX=$^U7d zpC#y=Q}eQu_YH)DGqHzdftvZD#YgGE$|u2Gl&?a`Cav%;^c`AHUXqM-CjFFdc{y@O z3*S@uZsOTQ-%q07N~;4_!Fez3)R}8-J8Dlfr~MEAWA~#OXardaoE9Tl^;doa7f8-; z3VnpKPTBu$Xj~O9U%xyzYiuI9p3(rk9^Fs*@5rbB$tXX2OXX=2e~1hB+2!z&<-YD$ zm-xqDgnQUwJv*uAdAnY4P6izMZw++Ce;zh)4|s#G^Q}m0m$eU>*v$D7^|ZVEOPW4o zBQoS*8>l_fT*go|MElK?pcCOp{6S-_^Z8Ve4sUL*qfWoa9DWU)>EBN1gv;!0@gGZ? zZ0?|ih=se8bo>-hZ#%vSJVF~meUxndXX-eeHXcYJvv3aRAxj2$s`Di4raxK|Es7?8 zi0mT0c3pux#pqPp^XtXepnL8p7d}zCy}uWK8OsshdJE@3b2qwzZ7u82#pt%XW~>KC zk@`!7*R~9G{)o2iT@PT@noazma2ZLhDRq%o^h-amWn})7S31P)JT(S?My3{R?1MJe z(3zKb{)Ql06pe^RGtljO*Hz@~R-W~QzqO9ow7+r2CA!1cqm|LYt))9B#S?i|yofyj zdt&}=28@n3$Lg-M*O*1SG5YwY+Zjuqukj3N*wSt$S6uyrPTf}+a z57zKLo_E?v!V}^eBPHY z={?9kq6_gN@uzDT(^Z5U!0C3LxA4qC2ipj%co$xU<8W_zte$=Ya8>KxHEv;El?(Os zx03HzJ-yBf!@d92Y0hl2k}2T1tasYGYtR1;w}6dV{*Zh$I_`eo$#b?@=q)|X-p6tC z%){GDPO7ssgSMPB>BtO@`;_lwupe`|7v_;CPu^s|{~_vj(6c*zy`>24;X93cV~_hz zZZ*$G;H&$!2T92O_mkk&DXb|udFoI0md>PZ!P@iB@owmOH zzJW(w{P)lSvNE)s*m@i5ALBENIyJX}{}A`qOQxWC^`v+f^CwpvmFq3MUuz}bX9ev$ z`J8k>;NwZoF4Rxj5>5>P9Ji&xH+XiEFZt0_2kSU_(Rn1&)SY}1TnS$<5x^mJ$X4It zx+?Aj8wWnB;>OrG`cxICbEt^-lz6DML)872TE;1*Ggr>G*zdk%*JsXn@RL2bE1=8G z;6wDY{$At;)+{GWpEAs?J1ggD_2`=GGHdWz#o0IbsYh>oN4Gh=6nRCq4ofC5SJUhK zI5>J5TuMK5IqQPHi^u^rz-rRVktxyrWFN!!iMu^szc0OBG}G@-`BTOAZ_HlC1l^wW zdb+o)y0t%LPh2{Kac}3TxcBq!1@CRVPY>R8he@`jHPG-(;_|?U`V&Yk261fR||BBH8!%abu*flDxF{g2iSxM114y#pYJ{miUZxHKFX0 zHUP43F?PzJ_P&u@Ul5( zK{VuNrVrT(xPOfNaG3gjBzr3N0CYdQ6t^}K7dOzx7TrDhK6&u{3(vT?{ExiLzpu`P zw(}k{t4rJI*H&~6Npud#QN`~NkAdq@FM5JcejVCNgM0cSoy7~*=H-&|UBV0fU7A{5 zT1%gWBk=>_;7h_mE?w%Qo;ed4Q^xaE+R;D3ZlkSPw54`{ulWe^rx7=Ta`Fw+N*k@{ zIJ%IbUGgDk6LM&94#eLC+=y#E*PYOj~M zJd?Orfhk73%li?f0kiIr{(*P-O3>VzJ(@kNyAJtsynh*Oi0(BP<_I_N!wdedlQ{zp zv1J%ZpIYG^`0TRu$RBh4rNqr*OoYc-lz$yM6b_Ggt0U|qkr~X;491$Zn(=)W9%Fs& zTbaY*JL)Yf824FdwYxM-KH15%1@*O2-}a!sa7-Qnc8!V0nDDPt?iA(9l07tr)1ZOP z29^flrnb3A$@xJ4FcDkh9~!2djOa7Q~H#U2!yF|KvxGsvaL+e4aDF6AUM z>)vl&R`hpS8T%6Cq07pT^88QcZm5fv+#ufkYr@rC7hf&eQS-cd?u!>3AzgFn3z>>6 zIcj}n4prO3)I;l5r+_Hx0>@i{?aasD7#?cmyD^F1L3Bde*D&vg)VB6DVVjzhFS-@| z>p}91uhgVjCo|Atu!qu`fGvQZppU!gpL9ICC==3h2Hfd9Kknv=InwO8f3~NfGnZKU z3C?z&C`L(_EkzyYQE_ZC7C>vz9{-SDS&~lS<9uJkQ+4Qk^<$bJN!ChtWx?7;vGz40 zm({VJO0TPbr)k`Dc3%tMdL9_sfxn$PzDs}Gc-MLU&3_smlHO+$xD$TGS7&q@t0NL_ zg@??Ai%kq%RxGWN3NR2k|1qo#5u+kOO{1$#8{C+XX@w+PGH zaiF}zxY;#{c0;(pO`Z5{SWm0!sVdug434VHg=N~R%E;bMcFVFERbKLp332k))s?w1 zpFBs`$22gdlvnm@x>sG=v+qkKy=5sp0>4r(;6(Ao$z%t zB>bKk%y;!?3H4R*`}X*#5Ap+|_QN_i2oB<*Q*1fc`wsXnX5cb+-N0w12vtpZrWF?fLVY*qgq zV3Hl4^)~`7PEcEEc!H%hWZY!MmKPdJbYed%9kP5tDLrZ)8<4!NF*?>h5?=vj@PR)7 zE1$8q7d;{)2zGpJXsxvT2wcdPRJN;0=J~0#r?vbq^gYz0hI3T1*7Vr{E;GQ$yhsW5 zOpk8}AClh%+UOWtdH%2-T&4A2mrJzoZhn*fLp+x&Ue}3k1vrlIUBmYqUxn8CpapD@ z)z6oSzmhyJDnE1W7T$HQO5>pVCA*Ie#zyt#kSTVM*QC4sG{7Nl`M-tv<$?Z-hpXJLs~p*QvaBlM}kJjef5pYzAK z&tc2<9JI#$64D#<&-t?V9LKYc=QQ%ZKXrwFdj1OkeT6IhGm=;MAHY{bJH9%k2TP)x zKAk**XrG#8q%z}E}fomzl8F42xnD%VFxyG`VRSm^dV8^ zh-9EMX-D#BD6fc){=!+xs4F_mqp@qvGaVh~!|(>#bbplRs&hJEdHBj8JV*%V%;nIq z=CS1&Y4nrOoMeU($gjg*yu^Rw{U|#4$@rj<%=>d}DRdsOm#1WH-EWjUrTv9?W4&2B zxR-T4+-GP#?+3Q(GXW183g>Bf9`n1`B&Q;aFhA6e&S4}QpA7ycAXiAXc1WMd9$k4N z_=J%R98IG0AQY1LOdu~~U4D`GR?;T$t#SO2@QQ6f0z7wt)6-L&zgWJPyAv9?6Z~%x z{fZt&Q~q@Fh!1V1>_gu)hu2fz>C|^J@x8=NwzOTT@AJf+jDBj09k<+_tY5aiDD`PA zn?ijj2K6nZ?02XyO?@Yu6{Q66+J}CNIO)aH;4{Uya4KBDM~j~Ymm#kZE+r31?))8N z_&VX-4csvzTt>Ku@H4_N%vXCl$qj-x9N#~Gr9w}ff7^d%tBu*MeCq+Bl<^tjDOn1*;k4d<(EYFpX(Vr>0f7(|AW9Qdx9R;i+19!r5@d> zvEzy!S3FyH3`7%UU{zmo3o7RXTQ6N~hKW0BOT!(OXa+n=ho43tkcG$Q*auQyNH>2+ z+oDs=anb2QUuea>bFzta^IXAv%8xJFi;GCg{JFJ=h;L0k`%> z3HlQHeiZICr>f~V+#g5tz?S2z>juV<`7*(EI` zZPMmk5iu8??M3AptmE~sppzW-&+uc-`3TPs@f_=zp$p&>Nz&$Gw<;Q+gAJ?JP0_7% z0@p%IaoO;*20KZf>4U!huN}!8^qcd~_)*dt4{1F<=<6)4K86m2bd$f`pOYHtkLOG- z+TY8b@OI`i@B1q6@8!KNiQRh|zu)`ud6>D)A5PYnl&^h0XLGI4O$s0T^hrJmhVfZ6 zj9p(6{LSIJk!Ol$6VEbd$iZ4sPAA9vz1V$(I+iZzMSXmMHRqbZwj*=?JNx*7cj=@4 zC0^Y}ul#l&Ww#+;GJyZsk=GP%j$={{Q=_9AxvOq|n=9%o?@JCf#QqZi43)9wwv!9C&5 zAB(qD&d0XF$8_d=lXEn8ecX7}C|IY)qFm zE-#!#dDaH@WWY$Bud^nKAJzkJj5#lgtt&W^ zd@VZLnS7?0v^>VKIFh_MAtpX!?;JOWy4-M{Ip`NcnL#`_)c=XEP2bpI`Uw9($O4G? z@f*CSH+7gx3F6B-H`BVJHDy&AdV)9Cr#K%+&XXJi+~@$r%NA;1)+D)R2{`y3xYN3T z9r;jYpO7mr6#n30@}n8z_@1LU=1w&@o~}H>x)J8tSd~Y6Lc{(*>x%j#U4h`fDS$VG z)vh5a+1nlf){AxLzqu3G?*0aJWAT4JIHVf}aGnON+X&kU|3r9@ z@MFT)uI(^C71ob6cbF?1Ho^&Mr83yi7=brc?@UC-h^-r?9?3P9#*Cvo_du%^9 z_~)S;zcjxb-6Cg7O+ z%RHy^OlCJ=pSHo@6dhZbME~w%9Zh7=!7?8=MWcmv{Nv+$_~>18w(hd!iqkgg41J{k zzkh@*NFI}`_;dR;-zNn9(7r_bkeg}aBeb!lCQ^{@w=Fl`Uthz2whEHdD|+}5`K5(e z7FobuT#!sqSGdieLYZ(5X{^J!RmWH+?&>hk<_?n}oJP2Sa5>>>!u5n32;GEL1l_~D zljlzeuMsr9p*||4Q|PLBpQ*@gR#$_~mGm>p8_IR+59hpYvFgrX9Tih2%E#aG_>D+ zEL6S+f1dvCX~#kLVkZW%WMx;+HF*3#ao?8Pn#`2XafJsL~wgI*`IN9(`Y z9R3{ic5QZEsWyYGmwKMLc{l6uLUi})YsFqyIxEiF(Ft?zCH)8eIfwd<`@Aoksk;2# z@PHMiPGmLaO#`rj?_PgC=ege@f1Ry!bpgMvCBwh@g@&DWB}m!hGPu z#>xIHjGK!*Rp;I9?pDM?|pZXF*rqq1GFJU1;-Qdx=iM)cd##~lR za<<3CP4s((ayZxC!`zxf_$=Xzgs&623AYix^Nq^=* z`m5pnOzlyj-#Luq6S8YkS&JL&W}!{dt>{zhM>2Vr-%8x*iC6ed(Cc}`UF*)Xb0Crh zhRh4#@KV_?GcKQIo@st_A1S~&>u$4f&ShGAj;6bjf7RNWs+^nZzuo%^_xSQ<9e4Ss z3jOlNGAE2V@0fYUm;IE=f|o=a`RkxF-KT6PUFFq=Xh7#bqJg`BQTb}Ez7wA~)UCVo)ikhy z@fIE2MRoZqU3>)(Jwur~k2Psb_kieLys(M0 z2WL!YVK9CGJAga=wVrEvr0N#^hzHvGs2{yBeLGg=D`3A9zLQ!h*pm zu#aRcwU0#>9@4)`Yxeh+Bxlykc0&6~@UDJD-L3+>jXum~-IrOEy+e)OpTijN z4_Vm+G@086RmQ@X63&pv#~rY8*((98QFF3%R1WK4L&V!ZAbS$WETX?l3!L>et9$0PkbW7$17(NO~@74B{8ngy#p7L*$)T@gydpmpx~)@1w&{;R&VvL zfd4<@k0igocj4QAhxZ72%gT4F>;TZciw9Qn&x3~74K|ss!BC$jc;)j%YybVwO-OGJ zaQ};7HWfYAC8X6UAGH1$w0;Sb_kNg#%4Y+8Uz9SME7GN$N7;DT-;DTOt|))sqT%Xs z7p(pC=Kx_ZVK8{=UEwu?#!mYzt(odG^ft7^eZHvv>Kub~yKV{(#@$Gs@xIQ!qGscu z%33^-4?N&679LYoCIVccKJ0jX5kEY(FIv0atuK97Bj*!V5q1Ypy({z+#1}Na#-lIr zY1&WUwnT8X<=PsN&gh-k_nW?;%>{e5wAQuF1W{k zfVDyY|7##lbv|fT6qWW5#BU~E{W7OM{*M0aBF`>wBmI$YhzftYoW88@SZv-TgwI## zTQ_t075c2Y2OoPLeo^7;N|T>X{O51!C6DkjNL(HD;WvNF+3eX=Cd@xfKmMS#jX1~6 z75n&Bn*LQGUu%EGZ)BMN3&c6(Gc}Lf_CCk={{Dc6Q&x5D4f^>$(GYo$5T|-o=X2!O zQ}J){uD1GGE9Djcuf(a%LRFg=5m(*jC-}ac`|85yE#RKH*Nl%V3-g7f%|Wj?ns0+n zPj$9pfAyo(ilXknqmQ@mVSfad;QIk-A$^2tx{uu+)cf+6;Xf+R_c+E)_wZHsG~#{? z9HIf;H`U>kOH2e01$`0qTKP6rI zpa=6Sit_J=?*LnWJ#}28G~n^vk&Le?2`A8^y<>iavf3BVQvH-g|FUJ2oi`hc9&xgN zhA*v&ocX+e-?Sav>o?7;u|r3&9}@fz(*9`L`Xe?ioCB7b=ZUZ_hkOor)7{QjE_mJ_ zjB5{qJ;P3OcsJ#B{wP1kVZX%xq(?FNoU@-W3;(_HDPXerj_J!4Q(5$T_&$9f@JY}4 z0qWLVmcBL4y&~kyX88|@(bpT%_jPlod>-lYwJX^`a;RX|_~^dq3l`?eJrVgNl|RF0 zh?9R!={G|k%l2GqxPKG9vOox(rxIA@uYM+ctn zE**TBGce#&d$LiA0F&uk?(fZS1fPq9Q*=j*q>tc#SN-F_RkQA+8`F<(0oDM{&*lJ+ zd@ahRQog66oImP6wgbp6>a+S_eJQfer)W2ZtRuVI82C}Ta3|eBg!b??)_fZM-j#ja z(mU&CnfnHZPX{jbRXD*Ps!fystreuroWi|O;-O_5FCKa$@skyos>I#Ex65~9@crrq zEBr4I*IJe5b9~FUq4H>*UBLM3X;KU5TdqNAKlmZ{+bE;6FyZVq>iG=iCaIourL9i| z_2@fJo^z>3&+2-bEuXZ)pwI=MM zEyMlYP!6w$=p`T4@O&NF;!Q$?cgYzso^^ybcz=uFO);i+3;v{d*LoHHH_ypJ2e}IU zEfYP^k7$OqO>NP>_?+68jG}(6BR-J?AH>!2{XXnpl}~9EIG?k3Fz^@f4jcOFc9vJQ z6FW{jUq7au(Z^|rajmoy{sWBu7z50?if&Hx{0jLf?c&e+cnL@m`lAL|Dj`VxR&!@rAuG+#timl^ylNi z>(K6e+7OLC=xut(T6h8RnWc+OCn0=>b*OwNc>YIQN9C^bS>#v!N>jc)z>xya?UIF4 z72LbzAEf0b!UKiM+55$;l384H;y*8rZl)3APU7IRu>8#TPQql1u)98EigSSC^sElBS-D?P82 zF&hTsl&?YN(%$FW%z2$37_|d$wrB9*Eu`rWK%=5%OQV5|Y-utJePz&hA-A+y{BA&h zh&~HkIF@f+T%OH5lCDI$q7Vj+n{Yb;T&cb3q}5E}AC|yZ@2>Nu>pWRDFXRi$c;ufO zO3xa&JFTxBTodLA-zL&o+NqB4D!^aa#3(=^_{$ze}gSf*q+8X zLSFf#5RA%qIdH|uckq~evK0*bqJGO}=U4m=B&Y4|}#I{H4}iB)XkK6Ja_s@NR~)-*8O8PqQsUvU}YdWn;6gm%XeKZf`Q zhqZ)nhi|9G%{d3qjdqc*EzkO2$y=0fN7eJ{Wc-Z6`|Ll2z(d^YF?+9hG_F284Xn?G z@N&0I{6u`mPm40drbf-Ox zOYsd{tclbgONtaL`1UPG}3BdROoWI^UPCFx4O8WCwPt z(CUy$uVgG`-@B517P1n3+e_ax#{}>Fw0UIm7HgvdY&K4J#NzDFBBCqq4~a&#Zv8PF z-uF<{_Z(*k*^3I?yW$K6TnV2UWIHQw zAosZk56Q;qe(0kXovG&EboPhrd-tec`rnDu_c1HmD4*j#dq`*7-?sFGO_KX5;&KgP zIq6c-y^c9TdEr6zuOn|b#&oAydWtZA`2R?BR(r(TZ9M#3_BwNe{g`YIVmbCc@#p+k z#y#iX{sYdhwP)})*!$J%P{vAz2hl^bh@Y7qZ_{e=BQ+wMn^L|1dX78?zr_DhZs30^ z!E+Y!SJ-wNJiI+O()w6{e(k(A;7f3ce{ZHQ;k(iY!KwNe#=SOqgD<}kCtDdYT?QuG z-|Bg{3mBGsd9le7TE2=uf#9ikg-*U}QF@Cpt{=z+wqxHNCzN_oed8cUP-RgOzx}J9#o9cQrHt(y#^-H#F1@EHq zmsy`)3f5+Li{;^U23d^uH6EH%mj8IQ1?hN4^j%$$d=$;CDJWe&-WrC7PZz&H{&ch# zK9)bJ&zAp)@36NDdCxb2MRll;;#DEf5uf@ad_=rPeCI32(2wjZDtaQ#ub!{5&Jk`VY$nKNP&{Bi z&xa@{{2+_jbLu=#om21S`2*5+Q)euL{4fri57vt#$Pp%+DIhuq-Oejv|T-vzC0jkeM}q zkXu*-E-PwJ%vsqU*1L*74)FB-ub83N!RtwPcbFN3*XhK?JQowbNVtV?D?#J1nddK7 zc9=5Zeer9}AkW_uPRPH#SCbs<@Eys%EuR5qwK93C{aM#nv8dvfL>o@jg(jiEvz#WpYwa6?EdQaBHErC5xBFQ)} zq~D@9_3>-Gn_RA}eTww5Dm#^SUe)-rR#mSM|GS_ z-0R20iGOO`R8DzYpn2U@>Lflad$_7hV=#}yc0BTxN!RzQ%}6g6t}5=J%8&4@-Ar{eE*UE*V3*gO5a| zk67n_hJJjcAy=M#{+v>bab(;Xvs_tcZ60u5Lb~oB+J9;XY5z=`^a+xu3+N4W&L+RS zI%n#`t_Y0*Lq78LCS?By&7D@it#_vhI{?Ci$*!Yu(PYQ%*Iy)1-BgtIZN8b6fNml+hAEfDD2|7zs9kP4XKNhY!L-T84d3}TnJbC%dF$9o1;_2gE+kj}VZO7tv+xM#O{G?Qvs(OZXGQ!6u8a8F zPm1`t{}r*ivaN~(ADVaCCt)uf=Z=4(20aU7Yiavl(#M=!d5;jcS^0rUxYnH$dp3d2 zlYL`cb&RC^EaF#B?JnGO#`&ck9)4>^H0T~+!oDXO%J`WZN8g%vV87N%-xkp~#LJ_5 z@e813;io=7JbWeZ8lPKv-XG9-4fE*;bl&i#Wkq`i#`urL*U2d0)4vBa)`yb!=)Vo+ zrF_?Ca^=hTC$7GoRAY(#t(B$6j_)Zu`0I!ymz8B3AUYm3fG=d?RfqE9Bd>f#kXB2Y zW4>zrxhuUhXhU=LBJzw*RbW_3ywW9i%n!=G{#*PpLw|~&L)@I8Yz`f+&5NA5g7Zz; z2TxkU-Grdr5ak?mLwOK7QogXCXObSysmNSoq6Eze(YWSC9k7SzgSuPUNZ($dF6fD~ zLDHz}^dSCe;`OcnZ;Kyk43#ey04>iVJ+ZWa%aRel(BJ(13Tvj4bpuy%U<*+ zUp9vez&F#t@3QE#;m0Ff_JL!7p>K7mHU~e=SbkId8uu{dH+p)y$LjC@)2Y~#OUB=W zpE22py4ZCd;@Qr#z_XR7=58C$Cf#QOw)_8Bq1h9F(FI2*0;6P%&jsV6`No=AJ{MeW zr>yjbHR)VKT{;()j2;I*)pHi<4)@^oztmWMO+j=SD=aHGxnhT$ zlQ6#vea0>50B>U7*U9*zH`Z$#_jKEjeQ(*6~){o<7Ci+?8 z3Bu1;rSE{AW;3=2vebJezRcmHs&if3DL4iE2}56_9R98QA^5fn&fq#bIiF{J!)N-k zq8VK{Pdwe_>6p&h;_ag*oLuUAOzXhx*^v(x&Qt#;^4ytxw1`|Yd-rLz{(f*K*||}4 z1}uvhR~I3*8#8Ki-8~IS@-D)g^vXJ-DG7R&fwef0DMV^ zUus>M%{VL~EGIb3v5+SS??-t;8Xpdn6;F7^r)}U?n&!#mAbvmb`flah1b#Y{Pw*&S zeyH_aIJN?d{%4_Y>yw)Nl4oXd?lhBrRF`X?jqE|*kRPaw$v^`^`4*n_oQLhYF6Jw( z@2r?__(R`32t^FV?;x-PhMVhL%bmur^L$+>89f-CJwv zn*D0RzW;&EAJAuYQE}E7e<& z-`+ar@z1lp#aOP#|24K{g6aE$pZl;{hqX7kiF!j?5}k&9xR-qISpWGJKN5X*T3&%| z0_(qEyqS6=KQ5sz$z6i+-DCk|%8D#N-yD-`AYYSY0qK-KRn@<6jSy{{PS;5zC5pyH z*O8PlcbtPh89JAIAlbknPIAHtd1xxwPmV6+iVqy=J8Gv@9lzr^@w<)_zxz1xdyf;J zuZj<4)kuo*Ph-c4{-=ra3(0!F3D!}3fqXaW#=g@vA$KqG(1YOczG+i=_a6IhwGGhU zs!Mi2;w7pp@-B7l@E*Ijx-R`INOHoPnMldPma}UOcGTzxfz9syve*Lz^|BAz6ZK*x z-S_B5b{U4Q$3D8hD4J@1wAY^RvR>e$2Ak^qNdG56IrYV0h9o&JyjP`hI@*5r?e=Ra z|Bm)E6`vjIm)h6;`Uo(neZir&1%r6Kg@N*6`?4uixp!+{Yf}q#0oPEJGV-UO{iN<4 z8+@Y~Y<9KR==?4IEunRzJZ2sGHe?)6cYQA^GXM8TSD|9cnID3rB#`tRyN-*?=47X1IH2Y(pH ztq1!c*0cX_@ci&^)H5Nd$C%~zzWIOGH_q>l3saryV&5gWpl`d+{O{^p^Ec}IJ@;f( zmobkWh3$35|ETPeLte>33w^8+c8+i-T{Mx|VDAIf%w^r=ySBbjGKsyXB-wv5^5=`R zD;wd?KK7L4k!--aVdZVfvf}MOC6DCz(}QnpkPh#TTv6P^St&G#E>CxY>^*aQu*jBI zchDDz7TND!R(7%%a>v!YREKUQ;jJAIO{24G#-~!r;l66LZej5S_VrQdua5f_(%C(Y zZz_}49sWzo$Sln!Rj_hLDC=ns$iIXB*+eMS;inlGi@-LdG>h-x>?GQ!xg>o7cuFH< zX0U++PczX?#(;kpYrLg#%4^)zXW0|!sr5r?I@{e$oP3yRK1~KkQ7>N}oy;SbUtKbV zt4jJWgp>RPcubZ}PUleP)4vN#=t7H*$9W3G1BWOlcUe@}O#%Qu2!oYt!tIylNT zIJsOjN}f@D-39TD5H`WH8W@h+LQ9?|E=*S+<-;jP{3K*({Oxgk)cLjaLH>&tRkT#1n*@#^c)Z?ifaY|1U_wz@tK<{w3 z-AC9qNvogPT~vN}UO5~;5B)}c`dj`s_){|VEx)nwEua4#3_0dzd!{A380fG$rgN?! zPPRD>#M!g2AWk;4@Zje9s(jcR=^sPQ$*Q;*al&z95a)INtZo!>dbT0+XiW8PNSBWD zWoSVT~hBo}-uRlirDB9ClXns1(JzdUZ$Ml6XX${D_!FvjP`d0S>TsSX6_nh4XUfk*L%;aRK8(w(u^@2RD1NISxBD07%pu6PsojYNOC-=_UM zyxER{@)%@d;a}@oj5`IUkZZ`f>&Ib7+k6A^-3`fm{K6M1<)xQ%@h=?pCbQpauy;Be z%~s%BAbL8x#insriEsLOdLv`}?eixU)_W5y zyrOy0w{(^D-qnS80sa9DQ472Bu@B|DmhVPrUN*ndOL9M8Pm;PDsry@ku^|02I0nus zz!$n5Yc&(cl`^`(i;EAmduU+`%0R0mwEaEjFA*Hz}P17*{u8q9M*wT_NXQF zT*Xnqsj~3G0(77`x@Hu(6rPgYWirX0iakDjISNd=|DO!!B>1;u9Nlc<)xmPBsXQtRLVgQHM{Y7Tr%kcH%7N^nK_<64cR8 zevS3t%8$%;dO!JP*WXBga@Y=uUm;8H>E{lv_zQUw{{+9-7kq=?I??O)fL_D(TsSj% zc&f{qm8q;*G0yk2W+nT2SZ7A!b7o%2L!OmgRx$-1;2pK-n6NLjHl1ex_gkb<2WOiV zzOK1FK%8t7)$dl|;lJ_l+p*X;UtJoVf23T){pOgt+c!D!bZjp*CsW!yxrSno-1$&MV+}DA=YCUMV3XT^A19@fpsd*N`7RIsnBD(Q~z?w{% z5zuCJ8Li7tvYx4*#Fw9-4z;QF!Zq$8;=;a$>zjN5SM!YoWkWoRf1bAw{AQ4W`|3+p z&zI)BpEBZW+u7%f7Lb|1lW63kVju78gZLiaH-YB^`3-&?IQDT@Q!;-)JS{>yqJ;zb z<-Y#ar+?cDZjHf#RFE$ll*?`KmkD;tHjzg)_hc3Y?eCoOl7+z|k9^yyKIXBlua!9d{dE-POGp>Irv~wYCmocD zRkeXm#l{~rUO8-c9J`g$*T`l0I4`TJSarL$~!pp{kBf7z<*KD+X$ z?TKm|TPWEvO|kjk_9Lr4|H9_qWXJHmab08wPpP~Lo#+8TE~749Am4Hf16g6*N{*0#GAlyz{76_^mYLM+tA+7KEA{HYLw5r z%@>XRJ9(@1pR#q8F5(Cqx)bv3*8-hGyTP{naW9~8q(Tw z^5+f5hQqAW>jw_upEK^RACONT7u}-H-1ObfyL7U8m#_3W!FwC;DyO;I{5#FV%Zjxw za&wydvz!S_N6480_C=gm9>Cu$Ys);=mIpR1HggI68?lWcd@fiILwRdD>&)EbI)602 zUc|HF;IEA~wLX9|&erc7I4x!l!@rRo@nPDstaKy%cVnWm*6Mz8-!}q$U@vE7Fzt17 z!U1?sq6^C+S0h7A2d8s0>wK-l$dn1`&eR73zn+3^)z??i zCPtZ|gy z+dbE#VECD(}lMC(hf*-gcq>hoZehxj-9nX9aN;UHW$Fx&WGJ0nd_; zwQjAJ%_`;e@3@142^j+Ys2`s|T`B2*7K-Mr>~|(*e_Mid2DQIm%ZO0`R`=v7jA@q z_4R)G+D{M-OXd@fn?F)nKSTL+o#PZtE?3llezdPiv8TqDNFf^R^VdN~x72fg#zijB zJ}bFp;E2~%TEZSGimo8ix27PwMB}b0$i_nVU}h#q#=9uT)7RZhq&rF1yxQ;$}8V;@fD8uHw0-7)25?ub2w49#8xnF85n zT8p=OhRJWmXD)5A|LjC2qFh4_ZO06-6UTnOd1iq+@src!;717fLcgBiAU+-Zm_qkB z1CDf0ML3EvzvfKc;z#Nm%C+EBK45N{wWhQLn$cQ+J$3~SV-jI)U~L*oseW^%@;2wl zyV=gwEdx<+%fO*iyZyf4TlBPwbnyts4bo5Re*4>9GmxTv(aXB;Of1-QynrUeTkXA{ zK)(qcCnVEaKb?%JCv>au0cKn*SDg8wPYwYrl8TxL9^=Jeu8bl3?6)@fn3%T5d1B$lAe=V=TTMlZ!GJ z>I{1q@ujWQDHvkzvbgd_-P;F}Zf}YINcaWH)w{jG%75*y;>nzo-9>$hf7ElYw4Sj} zG8S4-^saxYN1zLpmCuG)WuH=vGbS_ft!eVz4W2rq(%5HG?*DC?RW=bO>a!m?TT6l0!lr!ISUfjK7s%yq0ivYR4(V#K@3 z+u?OjM1M6Ef1i_)$y{iBV${9LHQ3sU7DTsy;jYLmGv4oj$%)y`LDZMb;-`S@D2SJJu}jO z0$LLdr%Z!Aw_HVe*=jY?2DG$gR&u<*Y#Q~0qe0<_{%D+xyCO~)SC{FIYc6+H=gD;Y z|3bZ%?{g2@;I}A-zok0v73t2Ea8d7VqVHFE!b3F8yf7eU1Ukc5o$sN}99se3N-y8h>MC2}A9 z*XlE8@-BYP+S_~sJUGUfJETS3y9WMvF86xwa|`g^@s{6tWEOpko?Fi2-WGCGj5}S! zrlpL%ezT>Csy@E!cz_4-fa-Cxa|>K_gt!0?(~ahT@4%J7sW!#KTNo?(Zit$`LH*~% zNg-!KC$dr2K0ih}V~6iwe3s$sqzju&@o0O0C)o*~UTOJyB-J@k>pkq(q#yQMQu3p< ziS>Xxcfb~wU-l?=3)G?Vm3qYISNaj^5r1EXkAnjHya@ji6ns0TJX@?OJnZknx4=j2 z+VL>BQN1htrYS3!>s$R%(2L1*kBen`(DK9yuj)%v<||L z$_{hM+I2zu@RvAqg#Yo0cdj7srT>Ss_m7k6s_*~rojbF;3=2EUvVkm{a2H6#xWrkq zQH%s80pn^=Cjk?pG)@vwwA9aPQk%9I_xG~6(B((?B?+U!mZqpksLh9BobV$dDO&PV zj5MD+Gu+O)M8!6(v_|Ge6<$TV!?pB2 zCg`OI8mDmC;pIlQ)91x`_A118LOEf*RpE4PVEkvHrBolZIN(V3ePDJ^q4QW5dh={? z7d%w+QI*r>?g5ukhjypwvv%6*47$@q*Th*)PpOK2kZ;&S?st+m^1dtg+VY+d^U*ey znbr6w|LfY%_R>Qq`16tV#6O&t9rcEDsD4zk*U_3+`0lXLx!PH4H+g?K-Z=fh>^{c# z$BKe!?2K$(d(#M25#>CG^Be}i2e)gZYeJRM-PCl!ddmftg)+TEd@+zN0zNLaI z`BF*z5t!p9{kMD0)9yELE#%uXr{CrN$KrAPu)esR&EGm%vY~gM5!2DkNF_+EnVZFDDKI?4eUG~Iw_i<=gcgzXKsKc9D zyzA0g>yJOlU3zOt^BwQYIPJ`*vXT9Ea&3M&-xhPg(jbiYanAzFwuMuWHF>LuxmNr8k^{1G(B$lHc0ZXDH{$*UIrhJBqSwa*+C6}O zo>rwRhThiSYkTw=$#5Srb7h9Q!#kTFXzUnw2D@O%1X|};r`67n7GvNj+^c$n@z-c> zbYDRq(0EIaC;x1^cZ$<6M>1j$vR7B(L|K`vonqV>S8t`dyt#f8^{Za-UN2pW^^s(f zlw^`cS{oscY-COD%OaNDQ4$Z3Orm(zA(>w?ykvnhIJFUZ$CHQDuCA#aj@qhm7|Q9L z&0XUhyUS~v)+g2QboIYvvqqEeRJQna+9X?W!}jLpVq;S;ebR}HgVP*fGj4&UZ)(4z zbtz?fJgq8_^Ne(Necv_xPBh&W6Tgcj857Wp=Iko&bdDmQ37=jYy*Z`JgCXQ|ic`7l z6?*O41ADn?95u+urFQkGUPt_}Fx3DViR1A4_BBnP!|)R^PlH=dUTN zll_VuW1%YD!#W84#_orPC7Uh>|3g6^K$YipkGtNBEfVmxCXh>+w=~Buf{&;9Zi9cf zwdT2nBewchAuW~;V!43kPrP8C_Z=uT=Pg+l({|@mg%Au@q{`BN3#$Yld zeKU7fWM6i_l(Gs}QSV*o;qIb5BbT)<<)3vh`{0{PHPFkrrbGFK*hfg;YuNo06sEXw zc|TnCkJ4Rcuj9=`=3y(bxzxkA7(YvyD^tt=CA$QCDo|Y*~hLJ9;BsZ)>ig&CP$y8N+XIKL>6X?hJ0r zH}5u_z@N^y{{JVpnE2uM>~J%*&4mA1c7G|tyl`Ta|DMZ#V^^FsCb{tAyxyreOxn&B zU4`A~8?^7Z&pu9Ds~zo2o7LcveIH~Sn$4LZaMN7HT9L3>Y2hAOlQDD#*+gpxjicxg z>l@u2m&zW}KK{FCx4~LfboVBi!5CmoxY^ZwIREX;hso#B1sWtd=L+6| z{n>rVALaE8uD4NceqxKt6QAjG8=JPW2Ibrw{bJC@v7bh_VQzK5g1*y84Y;cr>!Cbc z70Be#q3&3DxG~gKUp0hW37oT_Wxd4{Wl!jB^j(-vvQU(Dgk&1L^&Dn$UyJV%{(l{Z1qHo01*gK|Ph^`!DpR8?Nsy*x=PvUZZwXOeLj3XIUu*aoz@jydnHH|6 zI7SA&5VZTwIl#kOC&pT*BDK>wGqcNm{l+f$iBEJDbPiv8THHaH)R&FD~9Ok*Vlj7i{l zoI8m2rC-WFmhR6(8zbV$I~A6BIsaIupSANO*T1KTy;E*>i zCb=t=FYz2_TgYcma+mVI$9_KlnBC9X9b5MlVdUSNdNKc4sz2|QLw?<7qVgsMFq!m$ z?tM*VM#Ilu%3Hi6I(0VZX7FpUF>Gdji?nt-tlLL+j)x|w$7Fta3_DZl$i&M<|E7_B zA!UqyDTdvUN&lPR^(6NUrO3Y*TWi_Ud;5ney*K#0J3BSn{Sxy}C2RR~l(wL!FqlI` zJDtpR+E)zcyPJN)9WCI`lP5CSy8isFU9$m!^8%p<4MrEMOlpVrS=+Dz- zBDb9JbeWq=%l-B{%tOdEl3(CaxqwG82KYw5*YAz_PdXl^Zfr?s9=z{stxuO31tLpqgfah67W3ZM4Ci_ys` zyu3}-S@@aS8|W&%^3i{>HljY=X)u7S=+7VA9fq8Y9+ffBcmsOVA%)-J*(s`Dw2$ZY z2R!tF=FY;2fWN3tXC^W;vSc*NnlRm2DSf@@MtcxznD;&Y4_}QiS4^dx4C_aO^^EjI z%wZeA$F?hgN$X0<89Gm_{85{=kimKloXIW%o5}s6>vH`V`XEQL5H^-qoYx5@@3QBr z>|}NW>!WTDFVq{@dHZEjPXqO+Tc) zA^g``S~`XmgiEg=zPOLPI$s8k>d>{6niK3FPTA~!ZE77lmCX~5UVaGq!;716bk4#0 zH;}tEem(l5?yzjb&K7^nxjvm=3FCF1LGj|Zf+y5#Jja_^hQXb2Dd7yApw_0TZfC}C z&Na+OSD|&3@`=BT7EEED-B~0ejEN7&ZYb(PWoBtXok0ryI>hF8auj&LF+}Wr(~BmJMGg(Gdh-5%7{5br6hf)JA$H|G0e?b z%ef(VcdnxpOAM7Pd~ZI%Po};*{ErFd6x#V24EThz4xG163+yrBeR;vDJ!xoaM0!Q; z62SGk^U)7i;Y&AcB?f(c5B@~xDVkVIIPYNbFW%6|-Nl<8X?FUgKU>mWFrcvqUX$I` zZJag0R*rsklD&l!*kcW&J3Rwl9LAd3oTtr=*f(@mXuSJp2H;889fc>DA3%pqUMsb_ z^mA~g^Ib6`Yu*5jiASiOue75(xenQ{o%v1vkocarMvI%*^%l-OaHv?*{&cZ&2%9r_ zujZ@EX)FAvXbka&MQV+EeZuh8p!zl&27sTty{UJ4hH>1?zVx<%!iI_p$Gon;5c!M# z!UK(cg$Gvj6_z6>WoZLvtDI)akj;4o-^wfaRGxHvsz+-f*}YFuI!EgU_QG=8ym~t9 zY;kQJxIqaP5b30D2KVZc+N96zpgG6_|cuX|W6_c#qLHVMcahG>`_cIHIZtC~ujYrrsSJwUIC0z^eci<<*5Emk2D4Pn=W`CbCGCKb0Gbl zmHx&?e`9z0`WxyMT-vYk(xDR>cXd}mXW9IDYMVDt?FG*s9#aX%q0ykei!p{pcan`3 zpp)oo*4yRV-20jPQoyV2&q&u>Y=cUS$hb>HSyxyboQN_JQ^=_B5`= zOTsZJ-7Prx?EZ}?^viv|-g!LiJ+;rFYOiR%aLyW~5&2`RZ--f{H}j&YLAL_f?F2GQ zqK~!JL-^gSWAJm`tRwKjVPoL8WBZo_{xdht_=);woz?7gF6546n|Gh!C#SMI+*9E0 zR7z(uwzEHnondBs$z0dtjBVduirYh_vCg2=S-TP0@RLq11OLa4;6OY3*T9=V4jIol zG}(WtNc1|pfP2se_7r6it}-i(hlk@i_@1-W8Jk?^{NN*BbH*nga;GuYB>P9PWxkJm z?ZCiW&n3%#uvCeDwj%dnDV`iEMeMtrYP-wP`fHTk4ew;_mSQd?K9PQiex~f?3a5g# z$~5TDO0RPc{hzNnqcR<(#^Y-WXZpT7+!pj_3V+voml+-O@%^}2{I9~7y#$+~;NI_3 zohKjftaA@M{an7$Sm)ZQhuxWn2BDc$q0#7cZ#z0z9FHDP@?RBgsYbq=X6t*c8`@iH zuUC7j>hrCa^%lCTJFxlWtd*xne6Z98tc$@_Yi5JnmfGYl#g=q|;je+($jhA=;6i-i z7Rh(7NUx?bC;aF*Jj>q z!fAey{d{{kCqk2=PYYO=Ko{Bzsbu}Ex9KIvpjYyI!E%3MM@)8Eq!~#B;dbCx;WI7A zHBae1C&{vUGmEg11^Ak0+wdd!I*$zIM^gAJu(`SxI}N= zGq14BqQtpGNaaW3rbvEXs4Yctb+r{HxB_0vwdrIi5OH zmKm*Md{76x5dYEfyd9}Lk%%8YjkUbPJ3Th#sScYmy?m{Qn9qC|Uc;U)VN+gCdKRsN z)&ryByWltL;dkPTjQ2oqsWrzdAzT zlks3tTLqKghOWKyKCuLLsX@HLq34F_;O5`vq61LsZ(uHnvNxJnh$kshT=+1NK z$>GV;2f;(?NpD6I>tgt|R${wn+aZ0}1LyT&9S-)^r?WNSl5#`43DMqo`XaPDl&rm& zbMWFlN;eqv$Hi%`{{zxY`2*5?;SWf2#~+a9t>94`Li+yL%e0Apdup+N@9V7X@C*7* za>up)cTqGhe26!T{w5me_Mkt};auq5(3y&K*3=qZZ`V#F-6aZ#b`1Jo<3!`2D$|R- z0J1#v7^D2KA62HxGuokeX1XAl|_z3$AZUB%m`cNNFyfHi?#fh`+{4(7WKXto1e zhReNus7B~qco1Dmj(HIs@A-BF>lu@FXil6CKb{W1@@?S2IWoV-N_aa#NOyEnakZ0!bFCDDv@Y)BhZn*7AXMvX= zd(OAi&-Xg5v{`GEtEo%v)g2`puJ0?9>*sX`fn^^lX{_ijZ0Rx(j65Cv>$Sd)eo9ad zdcOwgMg_-)TcKMXAQQIGV* zlJliQW4?={qw@a6pQllWWo#S%&WUrUn}yi@Qr zZ_Pc!8ybN-dyF?IzJIroBu-&_{`qbr!@vBCozh8<+wq;*$oskgUq%W>Yu5srvR%L5HDkYw@) zWbxk>zq|pvect}ic!6&;^sx7;GQx8LW}?seGPu@Sa-+pw6mb`1g+Ax60$2ox))0?Z z(NF9(W9L~?*zQ?7VwSzB5*go`IOkw2BDm~LrMjlB{Ln1q3A?YffceEDz4ov>2(uD> zzP^mO@Js>q*23p%V|KRoPWH^gcJiNJc!|#+JpP8vJdHYW^|PvW#Bd&Nzjc@N7Cvs2 zw-LR7e93*+V7DP2sqiXw{8|;C?o=UZGU1>Ei$wp`EJyV@T%L}e} zz?MqxR%4SOba zOUZ+)Z!gPJ7u1t3tEa83o)q7>`g_PT4jNP0qKjW5zi+%}3UEFznN&2_a0%and3=yx zFjw=9t6xa|D(!#LuS#Q-)gc|z>lHiP*R@v(-M5jJd1z#qu=nwO%G<+y*`puA<0lB8 zOZbZlrysOVS;OAvKJC$wUu)I@Xad?|j`jObW2PgqW_T@q+eJUkV*gP#v3|dFN7OGX z2|ruE!@VK7y3jf_+Ew4o&LRV((aTe()}c+*D|=JXL=|gPjY*ZQbLSeP;+LPG4%tL1 zjpCG!zJJpgzKt}^)RCfm(X{rln1|wK%7<6<2KH}%G8^^idUT8Ii^2G zepkNxF7@B-y*S@z39m_OoPV@2DrkNLHX>r|4vIszEFNmCxL zHx_jFyUN&TmaiZBoYk~7^*iFai5t(Jrt%4A>d$@9md3o^TSk7ZW8SfDWc+E)e=WMB zz7KdqKEN5A^J8Co(u?Z-bc~tv;o496a1gFJc0Bu(yV&y-t$ZVM;hd7@OTBx{*>|ly z&*xXUd$0BRgYd5MzRADvq5lwf53Y`1ZOT?sjam%_KBT zyK6ZM$o&rRI_BLu2R*tFed>IS%4r2Z)$ECdxEd9Ft9-#IUNyx2QCO$oRM?jZ)A@!J zb&boRTeoO?ZI`2aV-u_it)?zV{5iq;x)t1;xkK2B@EKK(WS zJMsa2z6o7IjIie@Z-Z!^`SP_0=Me(DoEYu5`7~$PzD)cq`g8!l8M$>-ONTR^aTZB# zpgkMBw+C9B7l7x^Vh8yf4{BUzi!F&m9_)ud!CX)J3*&lIsoIep3-b|vlJTu~L_Z1c z%lpy1<@YYR>bR(3h2iH$o3}x?h92)S`bU&N+tt5BBSob)tFiO&QUXgGGBzbS30k7?$x*n=ihY7=OaoRO>8QyhJN&ZwPdB1 z|v!pl>O`Y>@s6IPJ5S<3$=e4+QdqKyny}5 z*~BlyJ%HPSdkps+?ldm?)n&$H+;zAmxG&-!!aa_A3HJ+JRkvY`{@OC*UAVJdJT-?e z8{AHO?S1aRm%inNN0%8-DGYZGhBqeX%O#;5r}U1k?L*i#KJB)pH+yfhYfYiKT5FpQ z_>5`4RPy(8;it(X6X>Ic6|85KPUAvvHfFBb5yP=JbENdo^zCBeW8i<$BYwI#a<vjp%)%t5pYf;^JYdV?K2#jnaDQ zC=2*Tn%^Q^w!vPzsM|`F3C`kE%i1&=+-`z@s4VFimQ!yi-z)3_ zpXqfr6DNE|ZNHxtzZYI0KkWBEwqj4$;K?E6IWK1jH|#O}F|cB@;HtdNH_0Kr&U=7Q_!9hzUvHJmBE8P10{A=N z6^f67!>#~+eJk(#`0ti&0DU4})8^R+a9_-FB8XC&Fn z+$nzZH1v`!hPKTq#`S!h_)EA4qp>aCqOpDo_dJNze$AL1y1zi@x9@KDP=fKTv0Xtu zqC@Ehw%_QtK{yud!|-eIUu;9_dzc@mlSbi+S6hE}xxarKhW$)7-evJ)kWWIKD9?|R zjEf+z(tTzo|Fo@wHd=&x_CR)T=?&IDzFk{yDGI!TQDYVu<7cs(QJE3atBmgjFw#`- z{1$IOyQk1eSS`IyB(b6NfjemfykUiCjP%N<{NF2sU18q~U=QP8h5v-GD{MEgm;b*P z*tOOa>_&z;u#EmCL#BbV!uH3s^bo51de(4#0ez_~?eB~Jwn9T;*`k+sTmxRPFAz;j zC#iG$(yfHJtGbK!1?4H<^P@Dc`uyY!^W%K`!I+hd81s|8v9N!&c0R!z1&^h_7ZnBL zF(kNbG+m!}CO`O7%UVKJrdc6Fe&4Z&miQZ2d z(e89;*UCvAM?b}P+SuXEEhajh`Lt2L2m<=cW_(fxSQZo@o9Agz!V$bGUGB8xQV6{kykkk=CBYgQbaqtudxU=k5B@y;q?( z9WkrMd2b1JHue^TclDLpn4zx@3s%~$eN%6}-g*!{1GbrSdp%p!@QmM4&a)r8vDe)w zyi=cSum@>7w^gDxPV4UR2DN`Bc(Lq=V!-;pKUWzFO$rzr2KhKki7$qAz8S zAb3OvUw|jG_j3L}1uchgD~(|1vCz}i^pEP3E=@SsK7;VNewt~1VEr3U97bjslgs9_ z;49=8Z-p=BgY)=87he_0pu6^PcF9}ftd6=Dh<^VUIE%#JT-MnD{|04wW1+09eF6SI zJ?G8%A9@$Kzo{2JY=D3E#gBUUuki4Xy|{<}#}mRoc0OhJm)$|Ak7hoLZ{fcj|10?q z@qY>USAT{7PSXYahjjBiW1+lH)SmAX=HFfE_j8PTG+tCrBzXjzD`231k5S&meWyK; zx9U65xt-P+WiDcmC&oUSXiaoIO1x0zCwofj`!n>t`g_k@`a9f98A2bBW?sya&gL$j zFR`D&e6bzf@F?Iia>#b*mZ}_dY2>TUaX0eK*eU&q&g~48#$3-@J2g=1VEkH{fznu~ z)0x8AE6W)ueQGX#I!J@BGg(%4pfrUwocsk^le16JT(hJ8ZO~X{Vk`3}dJF1Zcp3L@ z1D7gYMYV04mHt8jkGhfvy z{=^La>Br-Lg3OV=xzLf)T`=eZa$Vd9d0=?9(^oh{Tt#-E6y@G~`8CGZhZQGZ_aW36 zPvEnM2u;)&I|+XRw{zIJ8kq%JisWeb%xAoGHRw5JXFl#$eqR4OhsWLWj63?SXWaVF zJ;OZq@NkX%yY<~OJccxD*q>_sA~e*}@7!l>V1F&0XCEiN_WrcZ0b6#d#@<*NyQsq{Y zZ|4&3$!QGp_IhwVN7))f+HX}EhpSZvag^HO4B> zLYr3wWu>SSn+vaPyUXG`%3xw@_Tq=i;_naQ8CwmM;lU#Lf_rkjx|WZ=fb$nWZk*06 z@bOy1{CEv?^xDV#_Yq>w{rDa9i#0%@l862l&aArAr0rqLlL=0e&>1p241bD`VO_ ztMly9JAAlb4{*es9X|n#mj;~=1P4NmQ|7IW5V;(5mwyE88+(h#?kBG;$yUhwv9-(Qv61H zw7dL+7y6w(efIUmJ{+y4-|ttbJm5bS)YTM}zaW4^>HZ~%Gw5^XIjbQ^(_EJ3#Sm83 zx7s&XTM}jQ$HI8>M@SQnFU^~;u}4MOUZ1wsZg8gueX6i%mU)?eBYgw=4D{b3otW?AWr&t8CGWzc+}ti2v6h zepgxi9|!Rf;$IEo$5Uqr$2~#3c;L%H{0i-j2~PUu;K%%X%a#!KJ-)^N#OtDEZG)bk z9lFWSvoC0yOgfJ^j5Pza9zA}std0|>I181NpXJ1*mU*F^Nfshv}-XQI%SO5?0 z`?%Vtu}`>n)=g=C4-ec$e(}HsL7T(_ITYhQ64Vv)z_tJmrQ06F85i-u z>1Am)gs{@4kOx+m#eX@B&;B+KoJLzH+v9=v(T>s`{=BBJ-^Byb6~BoG?qXj_Jn#g0 zSN$Fy_&8~QKsuevD(92Giw6z{Wk2cV@p+)?_?-G?9uJgkbP~Lac0(Sx9Q~O$ zK7)P`54^vQ{oepj;kY}AUN=m4T@WW8_;|!0bGfqknL)fo{GK3wXIcDJLA-e2t{^@^ zoniS?f_U-3Y!JUO62#LlowOgBYXtqC`vBkKfs!|kvbF*DvxDffJYEsBP2*%caKwZ1 z#S?{#owXOzSz+DqFmx(DKPij<74|5S2hgKg>??TjC(7dgJ%|?%)Lf+U9Wy8&*lz`1 zjg2kr&uHC)JY3&~zEFJez~`iY+ghqjYE5%%@oTig#+Bud{f8)1_5CQQhdLTo zH7P%L&Kaz?$h)#d>qYjZsQW$-Ha|ZmIUek+y&4vg#v*+}_5%3*LHf3`^f{$xZTpv` zZ^Rx+`yN$%Pp3UL?MQ_6ru=%NDwFT~DC>3fHd+q|9`8H_{$~l__1*4J&Ah?_fNRvxc|nrvH0l2ox=ST_Y2%_a992HGUHEi zD{)=8M{zIUX8g@EV==A^m&0AYYnkyu+=Dpjv5!vWz8Kt%d)YhdT4sEg@JWBW%y=Je z5$+z`3fz4-;X}GW?Rl*M7VU?9_0?s@H;CJZ`!C=)fIt3G(&1`wV{qee6L5{VCft>{ zD0x?bw;bh7*=`u`AWVB|Z{SuDCSBxe!d}Oh9%ai)!}weNWj8K8{Ih)TwiE1I1{F(*@#p;_dWfM(wV z&7Mq5cALYo5zv$L9wlQ&({>Bt!N*prW zAU;C*mC&K!yF93;rz~A%kWS-BG%lEwhk7}8Gf>jHXmQJAcb^GtwDobmwf}k_IQaxP zIn2KS|B>!Od)&G+Qs+cYHcgH}{}%LLxwK_+3|&ZNmb7PX@XOJ7k0zff-LLX^(^5Qz zaT%{3H`y)R<&RV4Cr#yvTYS9lB=7XQ!8y1Re8N>KSQmlAc#6C)1bMZ;rF3b+!gR-i zIPtC!XDiC$4~OxzUwRVZ3?Aq8%}`mo{ULk-o`Bm+vnLYN#X4vrxEZ=}vb*@!$>((m z9RaM@1KSD8+ZB|P;$O1CuvbT~qjX=Yz3PD|Y!nU=nJTr}BX#F8C}C3anGv0YdH+BKpd#u{mr z?(Edb^fhq1kQChZW8} z7*X?L!l=;Ib@t(OxWV_^sAk5qK4i!Ko=+7DR7yz zqgvmD-6>ruIIKzih%vFSc&23_b~ZTx8n~MV7`IRk@0%2r)+8?x@ln)a{KB_+*%zH0 zd;Y)A#aqEoBf7}RgG45x}SW0x@h94Ei>3h$DMPx2qlke@wO$!mity+1lo(p>mD zaY>_V*fIu7H=(=DGXKsT%Q-pj1=V3bh{~MS9-L2 z=>r{wxHI6GL7ezS1Lrg&xdCS;=Sc^Vbtk`Lu#jyZ?Pl2z)IM0}%C!aUi|I~(;f6D? z#g(zivF)@g>_h0kVepE{?gJ|Z3PY@obZ=t?IGja3&7b#k4mnDB`j#FmTYHIX=2%BH zUE=DV_$v0c67*NJeT`e4UE@9i{)ES&fL#m9h$do+iDamX1g ztm6FPSlU!g8={mY8@?!E(bU?4XuzPJ>Xcu;>KUZ$A#kF-GKoFucM&V&3eBun=X8l zvmLXb5zQ;maB-FmZ^-cO4*X*Q;ddyUa*TFt-HbkT&+PF~#zMl|jDD{U$!D$H#c2#V z#r=%mR_uuHC(XXwjMMkw@5SE;o-$K*xT@nnu@lpt`jVOar?SPx<94`TtnOuRgMDm` z<4kX93*(J@l-*Hxtu6gA^6@Ov%2uNS_~PJOw)4{oOQiatpMLk>PjQDn@p|(?@mJ8k zt2ifojyJ>pg}A8A{z77s`!(JM)t!qqMh+f8edx;R+XmT0$d2qJa%La!!ZY*zv_;{^ z2pLZXU+W7={s>*WTC(h&z)zBt~^-{xp$-V5AipRa3|5=oy zG`CZh`tvm9PtS9A8|92;Zwx%=AEi9?=_%r>YjuAaausLIP0DG7XMc_Ovq|oRawsdO zyN-H!KZyORRIl!$fA$a#L1eG98TldxV5eW z-JxNypG03E=U|_gE_Nr`pQP_K_nFW$=SNrT`w?vCC5u(toxCU2=}ydbLdTuhVRa(o zb|Sm*&-roHE&lz!4|f)-a^OADQ;2x?6?8cAtLcl0&IVxVD2+#ci7?MpC%KnP>nra1 znu^=Y8?1U)E5cr;%7h;jJ2;bXG3Uy^?)#mE@tpNs#rH(~L43UhyU~UQE-GjK%pteK zsPp#O@28(?u5yZx*`4_&%G^EYNzSKdi{HS{5T`pi#G7^ge>C`LBPz4R(i zZ(JkyS%lRo@1^kgWPV*(pnn?1f}82k_GH^B3QvapWNA;bCtt-q z06M#GCT}{AL)}#eEY@_pGlIRkZ0{`izSpm$tx`VaQJFr@d-754{?z@U3LgV}+HW>e z%so0!$eDMYgPV_Srs(54e9z_^S3g_y&-wEmYvH5xK_t1clrp<{2iXtT|AJb^8@P$^ zwnbY@muH_a@!UJC)E)O$F8;H>jcWZRI*)d9*SPZOTr%mER`^q#U<&uL#oIM+g#1c$ z44{`JE;H>kT#1e4zW z5KPA}f~gspbjQBttn#)g&r#BvY3MGavj-c7_wMNDoYK}|Yv>N-jAtFz2P1+*bAj?| zyoY!Q>&BjDDzidx1~6>74P1T_T=FkGg)oP>Xbt4aFuj>v=tNS7 zy*CSzDefW*;0x;!{JN_utmiy#1Ncq)B|^XGO%?=*;ZZQ#c;c&048JwSn@+~Y;R^ma z|K`N-HE-ySBb`a%{B^@?!GBwe-c<8>M)z!FdeW$!2j^m=$i6l7zgjj{@KBw@*j8y| z^Srsq9yVwEf-=JNKJ6LsQ1!9i0QS>gN&1@LY^Ch1;&?ehIG>$`CDvf)cotG|4_9a@YGZn=fNz>ijQAnsB?kB3A&fYui*IQc&=C`m+mA8_# ziSRr!<>?L)l_`9y&7#pN=&X_cdKmi^6MAcezEz&y;fd3xD1LWyk5`}Upu}ey1G>?9 zHp$$AX&rofVgmjTOmSdJ9Oqpg>|g{>HBRpatF04NM$j(!iYZwH8K>bO=LdNg(}Ule zKY`b97z5aVMD15gl{t79@_}j87QZUr+jq-ab-ANVLI{z!*bCLNH@ZEp7?8&HbXHmzQGTdp* z>YlY|`YW#Yu9v}DmVPlQ7h9*(rd?mia(1pVZ4{)B&4NqGFPp%N+F>TTonGvBqKQt& z2Cs(wT*=DyIKp||6DCRdr5x=PZ#vputM66HXptV$vt_TDIU$;*z58Z^EmTJo!QRZ$TxhiLG4>_P4#d! z-J?Hb6rIg(@8|urNv_VA?#aE9*O>{~!7IJ?Pla1AeXiTR6Z}V<#=>;RyO)a1*$JLa z`U=Um)IU2lP)y|pih7%+H9b(A1+P;-%+BGbUS%!$svA8#nE(6S>b%8&B>2}oYx@X` z5f%-?bg!$zDhaC~Y_`LB2J${Z*f_?4>eiY+JlA{$ZEPlu;BEzmS=6t0SM?s#rsCDk zF^v!CeKv5WfG;&PP(0v`nO95PEt#*dd7m=5+B@sGD~Ekg>eZ5HzdHA7DTI0BTZHTE zu;5(z7IFWV@Y36`bIfUvrjaor`-cf$e}u59Ug3zi5ye3duv>4hyrDeJQGZqCmCCKS1pMDS z#W9c#;$Pu@SqC~vKqK^zWjycMi(AR(OU(}D(hteRXt#GvSK;sJixhn&TAGf$uC<<( zxRBl??GvQgL%4T-{Gzyh#OXdm-nV(nd{N{+-5)JI-+j<;r6JpWZ2xV)KmI3r)mXWh zUIjxry{g`jUM>3e;_~mJKfN(##hl7y@A+}2H*Lau!pIjFJYinF^VZ89yp7;c{bHxU zVS>HA%mBE5&g~n+x}Cd%r5`hL{myi7EZT0i!MQEDYmzIRCCMN0?sa4>MLwkwzG8ew z3D^I3_&4Ee2IaxW>J+9vnN2$_!Xxn13;9lx&;M8X!0o*`6!q@`W&X(4g>);LEvHw} zaU*@9wHW!Xst(ran!9cf=u~oYIS)iG_0FQV(WXY$Hf_cvcRqBp0NhCy8KNBKzx-PK z1+-ar8q6BU{SE7ltz64T^B`v8zK>Bi20?Ld+c<-m&QRP zGvLiHvoq)vvja}N9l3&h(^I-zE}OrKxqf=Ot3ZDhAH%**zVs5B^S{Nvc&r!3|5b^b z3z7DI<|yvS1?ImYUhkhs$5KJx=}v=0Fn?9px(fDOb8h z&CLrEejD0yliUsKnw$;Wn;qQ?-#eod__@!Ic6fXo-9nVRl)N{v6TCGP=#kkQiKnSw zX=edf-(`b^s?VW+8MC&~I|E%HYq?pJk#e9dwI!XYH0%!7$RRT^PIQ;}0^&3V^yUe7 zQ(N?zK_5iWYs55XhkdI4)cV$cj{w`=nS)Np)B$HL{bsccI7#4Ldzoad^}O>U8D&Wx zndG`Q>XfcxK5%>j86*5wxgY0Wybt>G=HHNRbuZ`r(5^>^$S;vJe3L$Y5L%H;skNk; z$>v2f7G;ZW)OQhN5$ROLCk@iCvJd&Z5*+IeD>KPme&{b)movBO4FO+P*^*%FkzVr3 zkd3TTCbM9R*MK}d5~dw0OS|PQ(nioZYfOq3r9+F^*?fn0SA;L0{2_Bj?xHzE^F<`f zJdk0X1e|LBw#XF6973L>-N##zk(oCP@YDz`=uHK$pGX_70mpJb_fjJ})o9<~UTJbK zKXwqni9NZ_*w-NsW$SFtu+wRcAEIO?o>7jIFh zosHlon|%J1(u^j}*x;^C;ag?RKD@)-yb#%DMt7kJU3Jukmgx_Rbzc9JE+^8|>(P+L zjA%!9`HDZRCr`D}UFw4$RFOUgKKCUKm3}?OaeGf<7GE~B{IP~ z7{}0KW1_2Q=emm1*sqeD^6lgRYnhjs2ccE|5AYx3KN|e+<=;S`rGAx;fi)KIYWR1{ z{OX-r>#rHUgY)>GqFutD@Hq<}A$+PmvxD}0g7!3WHx)EqfTp~;20Wgp?}fy(zvuB6 z(f4x6NkL!H2bRW@_Hbp-DSh|{Lj3$5oa^l3FTi^?%YZo`TIBRV99A z^g4pIHYl6*8EaqKoa*6@S>~QHy!$xcKCJc~70vs3u8ee-S1(w?k)78|lR>UOx#uzxCgKv5n)Mc8YE z9S*`!=f;l{c9O8~1!0W8_yNL>5w<@FixMV#w*!RzeGq0t1ADGvFUbLJ&TK{Kx5X_7 z-R<*$DYw?yLfWQkWDMG?J4{X1WF|a#tbGXi!2iFI`vuGYYuT^WzijQ4-m=B-$j3OA zo=&xTjpy`0z6e=m25PjZ`9^cLnIL+Nc4gL_~q zlTVejKgwIgp3dX-8`txg-60k!n?E#n#DlWMb9z7ImpzWLr?SPbZOZRB2oFQHmz-H0)C;fjcz!kYP6%L# z^DUXdKZD6W2mIn!jNxXGP*5 zGJ1>s0#3wZE(zWaf+oDZx)9d?fChvc{cCUP7yJu1mn07(XO{6+`$gz?plDEzZ44Br z<-&E!B=_6NuDtriB29#NtugknZxZ7_8vGyNUuzkYyRNH{gVj#yl+|vvNxI3WX?Kb? zwy_s?<2{^N!#8SoxT6C))mUsM>`a0^#2`##VIpA;VP+7fu@EKfIAL!D`>z@cXN(7gu!wU1(6La?zjps*x$$4@r`7CU zW=zGs8+Q}#qd4gitBmEwEcn@B_?r0K65M>8_}%TeXUSh^4%YF*?wDqC+g4 zLKf7!JA&7fi%BQg)?2oda!BW7>vF7dayi!6#0}d+_4DR*VyDwRF5+}g&|Z_mU%NOQ zT}!y9Q-O|?xejvU9YX4cN7fn1C%roTIRxEwpd&SfuQU$&l1`V&KF+zX5$)+MO~C7* z1KGqZ>}NmMW?vFmb&q?mE={p20fbyQ5O;G2)py{WlE_$G>|ziOy3rrh7LO6WYXTiBYcX`=!sRXSADvCfTIZ5= z$k^yC4c)zwH9OMm38Rli=BTqh_!j1^Z1&qmHv83eam&#?Rgp~g&|fed)Q8A-vC0(X zV%xEpvSY$k27XGPRML0IVR?ALhia)@;s5QACx;Yy^@k8d5CHX{-G&%OWx&J$wx`+MfTez2ju!Kj`&fihy zVWZbQi;a%?kutnUXt;mtDc$X`Jl#7Ao~KlH~Z|E=Up1Cy6G`59+J z#BlB?gL}QVZoaLUu&LLkuk0@8fZc;_0{elF(inFO6uN{Jwy^Z~{O%Pm}XuCyLT%0xp%wFo5=4OC&Kvf@N9Rxxpa47iQ0uc8%_1PjN5!D2Wm_h z4)Pv#X?%_e^j6Sr)mZqN_+rZp-u8okNd{^`cJ}S?Itr`kn=1OInlXAH(UqS+^I_Ml zsw?i(TtQzSNOt6FlIY9n|Iy$R+_5Hp*wx-NgQa0Y5XT-9JcKnB{c>bZPvKhXIAC|@ zCEKb_;<3fcl@8b)jI)Q`edGteiKg9Kn9ms3y&%eG(e_LlIUwNK2h!d74)PyhF6OTK zlJ2lmzH7Oszv7Q1>vR{CCeotvJ4za_zhXlDCHL!hJ%D`#@)P4OZw&dknGU~TZ%le_ zc-_;Lt+c1vAuMr^^T?B=c}E}oX^p${25f|`zo8H@2xC0VWo;||ueFBco(S{9BVQ%% zwCv)_8j0yB*@Sr%n0Uq)+wgtZb8}8T_ z{}x?^_Y$qQraADGyxH#QN{Yi-)}pKjYV70g0qFZ!ZX^AC>xFTH&7Jg;wC@o3dO`by zrx*`MN&DB(;*0pv%ob7kMicp3BorKAKt~Hw-6*NYEGIa zJq_(^G=}Qov(`kLy+>n>t9eFmD!|u@*3gs4=MQneDR^a1tr|BLS4Eii*s6_(+)?;Z zTntx%Q+OpVj#HkAFLKfot^*+;sIpZrpHvD%T0i|h-|tf7Ho zG{gF7XpP(OaCdP${-yX){AD{xKexM>;JZ4>U4U6|oEt1goV7*0|6my%#YW0y9b1f~ zdy7`4uZUbxR5@q7#Ytp1$$vrfj#R42-s zV-(}N_K*4sPENX`?d~PS>m7lLM&49nY)6u7OWRq8D^A}UOX0WVgU1rR^c!zCf^+tL zu(j4+gxia z-TDvf4!?&f0~m{{-!FHHa~S=W$~^<$8cuW-ytV{+Pr#3&W#xq56}&SeJ?&%mg?5mC zqS~Q(pLDU>>-!?`?nuMsS!-{i+a!LtF2JdH*!b}KwJg8vbG(-Ig#!9u~!n0VV_-jV!$+u_FGBQ(SKxicSK>D$JqBiAFj4& ztsa37M!2^^atUL|dlSWo7#+4@n35x_7$1g}&ENg=j$+04JBoMJbjaqcgpS-BS7YS| z`*B^24^O{(Q=nIdw&OSV6pp}K(~Q;XTu-ruyDJtUv#1{zIoyfJT)w1zG_v3*NApo8 zCw+WRF~i)LX3iWn)Zsjl+mwI8+3cs&b3SazF z`?IT3+qoxbyEg~Lk(VRfK{+ae+)Vo`uqE5>Y+Zgp$C!`7g=8|}VDCGh&mWj_bDpS!8 zmt3#%RYnrNAe-)wmBAk)UTqNUO1F?W<*Nw7l`o9L&hvb`D=*6TKH{|gP+pZ+o^K9u z72vTvEKK)q;<_$p4NqTa|0_QhI%FJfw;!gjI!lWalU&)`jQ_zlw;5ify*csD8s3|d zTp*cO^Ce@hoAJ4NQTrtKAFzRlVcUS5Ui^3T6^0?30N&E1{5`oJcz3MoF48@TgZTyE zH%*>B$*1$W_p~iY6UuorK6I1up<8cTAp1tm?V)bZaG;$Gv^+$6(>UT}i!nCEenoUo4BKbyNN4ce-8p4M#GfQ;zw zP&3=d-0brY!EPWMqZ6t>ptl&fPw_+C9eO;8U0ITJ%-f>BR)cfP;4Y^$$u*RBGjk62 zC6ZS0`aevZ)=l(Z{)EwwoYV)boVCbx6qHx#-$i=uV@9xjFj5=y+}%}AT&-mM7lC6d zG?;|O&H{HMeX4vadtGIvqjiYZYuX=Fn~vK3g>-_q+u*fFY44S^PwCaa$H0edR*qv& zAE7_5AZ`r%4eCSYA)PH^4}rZ+8~fWUe7pJZ|9M~xzm;wgx^B%KTko0X=sy?CmF(Bn z57cFAo38F2_obx6`uN}km8ZPlA&=y4ji=XHpT(%(FJr3nIyxH7{V(V}WBM!{KkLye zP5Q<%<9qnaa6iR;fPampi*@B@#ve=4mt#-r>B>LP`Cs+t;RyTme~JDy>&w^lM{%1K zaiYlyZk02^Wh@q}bDK|@;7MmrB6hE{h5cp&c-!z7@TREr9?G}T>0%w;2i0WYkxd*(B1RL2lFZZGq~lr z`M3kdLHB#O9C;4ne;5Br{6qMMGY8!x_)p=E^8GaKJGkd@CxAyfvy=GTfn0F#rH2_d zy4=_J{!h}p$oDDS6VQ|TESc$b_uq9SKMg;1cdwhlrE&9dOL2>EZMfyQ#kd8y6}Tn1 z2e?x|l0%MbXRki@Bs9c#wzDv)zQf(kog<>jXzHn0H1||&@sm%n)_=(hgMLhSeXV6@ z^N%Gr<$uAvzBkz?n{H&vr|7Q-y*gz}$)4ourSDx3mO>_ggC;atLE|LRuaUNU*_)gq1Am^7i=gIUv}$l`h_&r_~&>-W(@vV+;_e44j%;n zUfXN4wH>Ub#&~@pTlQXe4`t4#K6o8#Cd#B7WN)fd9l!|Q7rjlkh>U}GU%-8((df|{ z3FA8BAh_$3N9seGWEtS;Bfm{~#93pLM`GAbQ>Ih2n>M*qTb{!CeWbj^*V|2f^;#c~ zq7Q|4ojG!@)ENQ)j()9uBFU#J6|c1&^CtJT`(vQy`mFW2>vi85Yh3QsroW((zS14k z$6m|%vBKQu;Z9>vb?Chf)j9a~dyID6uE1Z3Z={$j!GTG7;MIn_qkd;}^Uys`q$O-h6M?`n+&&=p7BOKcs6p&y&<2HP?y0`%2T4H}R5dU+dA5 z($$vby8v&luO$AbHdr?2`{*}hBhCy02YPf18ArZg?_v%33)ZxfrL=E_Ezf?&)a;1(nU1VvJkk#!-&BppSJz zwkRG_<5-1jX`kl)Xijz@mSfO{H1m~Z^g4U(lTK%{!;wrQ9o(LG9`fGn8xypziF!B_ zR0N)FVVfntcy~hy4kv3-XG~-IiR*ItaY4SA!j%p@{sXWJUg<b=m z!s6wv(4)pgO%SF&`5tjPUwar||Jv_e4n0?;dJ0+gAkZUJroIR-?A}FqGSCq*mgACXpMmdG0pFyeXP;DL z|70W;=yM>5__=8gbh0o{UvEocC#XCp$a8{q!dUX8sK=N?-+lNgZ;nx4Gfus67ml~4 zvhfDK_KW9LAm4wNds)Li6|W6>`BZ3VCF^IEbAJ>2tnkAFiB0*%%mXW^x5j{{+oof_ zy{oAGDfX0VA49jX7=9>zv4A|fJ9aeberx`Zq_u8~3kIE$&C`}?r2TP$_5+h>-k?6k z*Agc?p^tF)reuxr$v(=H?t=9X^e4L>;p17-onl?^EM-{4Gag1xU^k<*sirTT-%SW~mzu+NH*!vhwZ^;$`U=D7Bct#V=^Dfj^)?=BiM*BT zFTEyRCH~()v-4SZrig1xqWd9Uw74A`!;`uv7+rq3Zr8{{6Y1+O@_J--Vu$Dfq z^l9WS%2=mz1G}k+k#?-ala5Dw$k5PsLkv2-k}~wR2C|>G-zgsOcDhvgJIOD&tBrcS zYhNG2sJOPor1~w%b@kZ%Pmuo2G8*#0QqP*OetU8|?^*OuP#e@9wd2wMWjh`Y+9A6S z>Atux&=IYE2VP<(`Bi;_ginAf<569%~jrB?(3|T7+)jN#8>FA zTQoJ1WGZ!j4Vit(1kVi5XW-><4M@Tw|weF8fTppB^*VSHg~=#;;#G z7;jIYmT|Oo-W2D3KjU3>=ui4{>BTLhza(0a@BOns<^AI`w|n#E+1eeh@_KZU2-4$g zPVEAQt@D~3?H$5Di?4ZQ9;6JFeXum93=hIdO*3;deR(Z9cVx*(%s5o3xliqoO>@K; zSCk!L0DrM5fM4g`1w+@Iz5@9QrxLPtWj@5#3VIt6y=|0U$bKFfhI3WOEQH6KX3$_>XPq(fdXD{K|Ge0?NG@BHPWKL!xHV2T-|=tk(O{3F@JM9bc^gTyophP3r#qcx>kJ2b zkl4~JNOs_7>n6^5vL1fKyUOD{9hds~^{Kp*hKx0qe%AQ{%c?7a)3}Mxp0n1SwWO=t z`p#?}Z<|UNXYy|yow_4tWU&uGCIiRC-#D88Uv?iaVvhx$_F<4GnQ0> z?ajPf!~NJc@4++P^bWbkp?9W2~#gX%Rl1=V>^qv>= zBz^q%xgjjw&@}JN6zR*@tn{S%sf)7aT%*4D=fG>@Bj?1U?1|~#Al}X@Mw&hN&ByG1 z$xznBDLZ1c$LsS1@@itrj(Yt1KJb}%i~QzA`5$^GdWx0{Wt?o#8i@(Axk$cK85 z=1!%7?qak*j9W>Z?(e&uxDL|K}JKRRT50Edy9&dS>t(4hH z+>OLp#9dsb`8&#tk}pcWR`SI!dvlp*kT1``M`sW>mbi<{R69jqvO$Tb{V_Evg`C5? zABtn{DC!+Cy_LF|Fvhwk_gX_+ooMz^&H`+5m0mVJe+JJAW+W%=iM|)A2ure-r*4xKH!F0{=7k58w~s z{(|qn$Nw|@SMdKF-`KNE7kGJmTRiamdFBl5f}iQ!%NXp}Y~)6Z`A70TZ^@y*V$G)c zif@e}+wk|k6GoP~yR*;_jfu7*#vyNR+I-J6r>aH#-_vU_d~YvSf|J9%&nCJP?RVH0 z=vMT1A8)DP>Yx69{yvcUzS)ZdLe%ntmQl!xY4h^HJ|TRRJ8`}*Up9|RAP94e%MkD2q zagArKA#@gYJL5?9Aa~Oq-L<1TF9fgpMr{$SF9TDetW5Lwl$oZ?G-ZD1e<<@w%B-SH zXwKUksua$sD}7G9>CNFL;U6TNZI&YXw0KpTwv@FelkVrOt_y9_`cn2GGgLowknXOC z*&bbb?b5ncxM-&RJAgy&)tC>{>RgA?Y$1+g5YpSlt4KdcnM+gs-aM@Opl{b40+uX! zhrnl+vys#pr7q!5y=~uD6<K#1Q`qxfJiCDh}# z&b`OT;Lq2ubET+s~zE{ zy5&{3?#Ul`^^*qMP;}`nKj3bo?+)iCGS+kKW&eMyy?dNg)s^>sE>+!4Q9?CMOWUFz zZrW;N3c-Y6o0N)%3B)Nb8lq?_0uv^2Oed0OOhzY7cLUOc(9nQNP|C>6Wb!yOD8>+i zrnq<`$Pg7{h{@+v74{nfg z3xml8elq$`^hB_A7^oyfy*A+Fep>qc6c@e z{j*#-o!y$FuTye6~E)VJCTF-5#LG9{jQdM1BQ$$Yy7Ble3eJz zL!}WfX^)>N@Za4(L-$%{oxbTe;zN&r9{-HI1J*D6?9@Oc`@|!6LX=zKn=f!*%3b)? zm_RrdoMWeRW*u!2o>SJyvRNCMBMrFMc+&NV8A9eZfG64WpBZJHcy`P!#ijId&c!nJ zpkxuWlZO|oJs-y^#AZh)rH^FHW# z8~2B}f13NZxPONGZtjP;Zs*zO9_hV7djNW?Z`rwkZ>QtebgdEag>`d^SeEZGC+|3o z!mh%ad2-Y~lL| z%DS6>7kp%u;rH#{zM>tb>j=|n?XA+?8K#qcu5=Fdl5d24Nxp&idOLh~!gps#vsrIv zL&pg2DU>;d@+9AKnN<~JTzNj_YFwZ+Ip`~%)&G~FrM`(@W8~An7x^YTg+TB`b-Bm! zLz?P0mr zAHl+L?9*d!DJtIgOdVn9Og^Q*`1kZ*=C-sq zo3Sxi^PuzMON^_WSo5H~P}-ew+RL{58^~wP6<9T2e`^Xh=8$&ewR~>O zx6fuh?YlD;S}n7fZ|6G6^Sm3d*FLe(TEO)HhF(TULz;d`5k9Z+W&3nxMLLeF}AgWDHbgyTD8KTxW@eVIA#V-e zbY^B$uF|#feK%!l-yBHLypw0m?Z<(mI$d3uH%#SFEDlp+pm~+m8bSk1Lg=fdRM!f!~eh4+1@-WR#4y1 zhF;32a$3nJznf{(oUwijKDS!t;L)`MYU{A8oRa1%_Tk4`$NzJHE12uJ#=rzEH;dLD zIAGfCJ^1wL8&N%~_iNaOns@wHXz*>y*SF~Z5z=lyJ59hHbUd(vzXglP5#xA)7bt_0h_jvuaDXt!JzdT+J{=Py4w4s z23!l5Hh0BKM)7&Hv#P(ud@J2OXv@Q23H*8nR)V5VRJZZpXro{k+^SRUsR4HJtm+Vb zvR-$|M=t7r1dr&XxIn@1A!zxz|C{W`!w5vC(9BQc_WuW2{1m0ikH8=j2~!fW0gzJHf*7gOGda6a=w z@*4V|0YhV0b|WxwuCLKm5ufzgWBilMODR4{dmj!T^F!?^TvYst{LjND?P=sZyk^Z? zXs&t__E#1g_JW^ah8pV9jGXdL(Fr2i!G2Cdk<2Iu6viFe7^NH5%l{FmI<{)hP$ zw&guqYu(Q`7OENm6tj~z%A;z@fyNm444E>-TeOTGh zI>py%<5>m9?mwOQmKn1Hx09z2WU-qCOD<@K@RsDAy^sCcDp;U{fkpBrH)(_Bg3Gx{ z-IX@r(7qu?U*PIg{%RO^91UW~PyX}6$Cb~SlY*w) zWAer5oqEi91zv}t``yI5Jp%0&bFO}>wpq|hyr8|9lt(e-7n5(Q)m3R@ACB!8?JIhP zeU&e9X%BAV%PXU~l3Xno`vsF`B+pB@Qe1a%HF05oH7AL=a|2V*|s*{fsXt&{pyZMdx%3}pEh*G*!t^RAhp3*3v(%{cG@;rh=<>;T%YYoa5_@Bf-^Uiqb8Rk_p zEBb4pYp`F%I?2Ow96r_@fu5b-6}2}1>!?FnH7F5XRF1r>3)vf zDa;`rg=^N_h1NE%<6Q0Yc)xL>^#&KVQu!iq6=QBw=T0QKZ@*}NagpLkc>Y&>;wkQ% zI3Ku)yZY%!?mwYy><*K!ElfL=yYl}6S}M;F+9r89ehTqn_|M1}rwm<A3q72)XbgSJ%0g*ci_{%Gz|e&lF=MRNC~Y!&Kwo4eX^ zb=Z#Cv_t+_wME|)Uq`&1N&8}$wk=G1bJ%9R6Sz9qW{qd^VIIZYsr-AxJokoq^p4yg z=m^tkJ&w}N4AadF)9HOYG!{NY#|Zx)t7;pvJCO;?Y2z+D%{+srpnHS(N4%sxWtvE* zGL;USdJy&)b1htk*88!OR2Dp9`12(1296Lv6G9%*x{iq6=#Rw3;QvKzB=M=sv-mT` zn*W_DkGt@`ooC^gIZ;z4_Wi&eJYPs#)lQ|!@h+T1ZSD^9+{->dg6r-uuWV__59CGp zU$G+=@%^kHpE}V*tb^pV`mAL2X!2Md@;QZG0}h**5@c#|iN$^d%+1zuZ{c4n|Ly=! zl0#pjPjpKMrdU_N9`pb4`%}A;v`u9?Df9(n#wC+_fN@1XzSMzv8Lbrv_K}A7jgE+pYq?JZj!*o}Wye%77ny`9wcvp0~p?Z_)&kL;S?FI;R%kH)x;p+`@0 zy#~`wrPAN>{4CFRLdc;{a%LLW1_*H>_o-adxh?~kkJ6!L^SlWmc{}$--0$LkH65ah z`$aX(n{xjW_jUZ+#`Du$A19x8gJnI>^YbjM$g&vh0L=R_82vEcUb}6fl>)AP==cin z(#6N{Lq#@}-H!Z62hXsGp#wLP3-qzQPP*d-WbT3E&}s(b<2w8h(#bCS=i7N~gA{(c zUe+wJ{|369aajIUyFiRO&*-&BZEy7s7rGZN$QPryH0gHsaF1)9koL4tJgoLQ*V?HX zYn_>UnkAV6Zr#*6KjwYIPXzH0J%G;|yV*qs?VD}>&j|C_X|H6~y=35>H0S*w_p9>~ zg4hE(Ox|-ehJ+8q_clB?wRdHuEx(f3;gx3XpY|k`9-qPYS$vN%FERb}JQ;hI*e0d~oS8F|3VD}U#kl6@VzfC++4Cqn(uZ0n ztGNo*Eq~iQ`abM1pgAZ=O)OpTFG@F+G*d~VcG%Rde64&_87+LD!ra{z@Tlz36f|ps zPKps!Y##mVRolz&)4og8Pe0B-M)^B5=c#sQsn6k@2iVEbM=*#!xhnd+NdHYj*J>O? zn?InB=rTXd7tu%irmiM`bza7kgY+?De6^i6i^dsnH9e${&g7ZT`vTr0n#i_DzYjeE zIx^PPyb^Kq5q(5I(pRQHqt8O4bVwu3vxqi1%3l=HhBD&d)b*L0e}Y&OcnBMHuJCQX zA7l=n{|)Sm7w20ezWzq$Ng7}OQ4s6a0$t3wF})f&yNq*m8t7Mf7ha2d_zAV129eOL zegz%S?=Mt-Gi**7dG;LFk*4&@=ddgGrqU~qptoNkw&yv{={cgj>Z9;RLNtF;F(lMA z57}ho5#y0>|LD}v-yY=t68C4g z-vDB6h8cgxvl+jx*&hxc8?k@l;VW6oIsqPe zZ4di!vDe;V_$inNV=O_;qLrghwqyJG%lkh{I_WSsl=OKF3b> zZ0bbbbh37 z}?}%qJc{3lq zgm_l*rtC9~J*RS)ewqmlw~snf1W&~;v4*8h_CynV1TZev`T>oNHP+SmTe4ZcotVYC zt4ZwL0lu1$aqDEv_yLyD|DC)o-+E`ipW$Q!}eP3`UzzaIK9F5;=rgoKk zM~o##b~!v2*lDtX1gFYS{*H{+g$}K}MqL_X?7uc&>|%pycH*btY1wPKYd?-w6hk}y2qy>q7*nS*_nR|QB>R>kdyx}vJF=H~n8Y2F zbKcvO!}#CWFpS-GkL7}UU50UeHh5<3rKv;vR8zM@-41ou%5SCpmK^$@`dvHmA!-lx zlrP6$-Ht!w)32Wz7z+c}KegCu0Y1Ta8P7&GMm!0;vZ)mFAh@M7$RfE`ehFDU6?yat zaHQBiH@m6-8t^Ayx5hQv`#^CfSMcrFXBgvh?dMu_dvL|LgMSmZBb!=%Ui_}Lf-6{W zf-et0)cgNmgUpg$@yGuEJ2nG6`$zvjtaIAn3HqDPnMptcXtyGu9qW4KH$?v71D{ir zJ{5f83&pF+cbKBh8Z(|po)osdXs&aiTKRX*f)!3ncDdtbSMoQK!8mnKi ze8Cnnmsb-z75sJn08 zSR=>wruV+5?r0ozaysWxyo~)l<=W#lv1_N&9!y(zbruWX@*y z^9}e1n#Y>@Hq-9girD`Ni@n-axBT9F!)L~~%^&nun;1Xa^5M5$-|UH;dK7&)mwi#K z9`rEqnKPEKbyc_K1A1Arqcfdm7i+^bG3E%6i9PZ~9tH>61A}u!$xFL|S^eT<_cO=k zYh8by_C(Uz0`O%4nVEUGqJ7s`q5ZwA=6`?}AJ!6*nc@NNKURQAyqLGA++2JMirz#EXq0UQFrPd9hLHH;{HlRa#_{NsFEu zObe_HR%T`6No0A{rg!0$8rpO;Y!m-Xn{@x?c-kZ$o(Qf;2aQcz#Ji*0X$!PL-x&TC z&uRRs{yPf4uFl_)Eg{(K-0IR6biQb_#kJ`(o&I`cQ6K$KtAD!|8u z4j(h!;QieY@3NPKck#<%_77Bj$cEK(Mxt>Nl z!`g)`asBMsbQpfr9xlPT9XDy7g1#S={r`rJ(rf=6Ix3y$_{;wW9hFveRNDW~bc8o; z>#ni|Z;JkmsVYtmK84?=zx^m&f^i6WMbS z-BD+CnsY@{&`)$sTb;+#)-tXxu8!j?Ca>|W3}xvb@Jr@N-fBNItxMK=WyvP-S$>>l zMSG#D9_g+1?uEV?R{@Vr|JnF+bSpH=^b*sD4qH#T4t>m(?t&L;tO>>vq#zsdB?_5JZNoK0=?&W*%PE-&d^ z0LnV9vpED$XQ;QKL(%D_ecnoc%|CaR)?UT>GmSIhQSH%GCwORIEBaBmwQ|TIbePW1 zl0Sp>bF7P^Z>Ba^bgqtU%;~`QTqsAcrf;tOL`O;M#pA4zQoCqR^ICNL^Yk~fKR&db zbS-o2v>}dfaSG+F;cOM@e&K_)f&TN9E!jAg`B&+l7GLYtkmK+ayw+g*!yKKpr5I!I zlc>Y5!dx-^__i|REzUO07x5WXJm|HA_8fSXvrMwcnVb(i*dcsBi|>jz`Uvz}H4gh1 z9bQ}L^f!=i?aQl6Lpa}{2^eBNXJi7i1J0DU&OcOUKcx!rq9cMipCn_yTmd_l_s?P@ zB0rd;Wlbu0)LsVKpLNwfVj*Zpt+m=;gPu5TE8JH67W7&*Zly0*dFXiA{b{I!=l~!}_NL^#r zhkuRx2L3JO+cwLoi1ySCD{!Y<#$M4nKs;J+TeiC zS=jKg414UP0^f{-&qU{~4B{6VU}c2c^_4~7HfkrlTuf2sYJ4b>9FpwY#x)-!XUh0s zod0JR2C_hM&~2v=(C@`78esGX zsTF<7zsg_x&&Y0gJ(fOd`aJO-3C&$7tz^I)$%Tol7!w9Gk_YYcO6IeGa9aIg=4dHjCRi5bI z48CuixH7P1gv*p)cCpz!2J$GB2`G75hE#3SAXAg2+BL=;mq?FE&phP1gZj|Tb^Ar+TGU3# zw@8;d@NFA)i%0(nnQrB>CH(2;T$@;7QzhDOW$>&9Yq{S7A2LtkYn^tIy=J6Ov_8X5 zA3jzCU35m6_+NCp#)7|qX}HDulnnifvoMoB=Ow2OA}N!Jd1XlysNUlb%v-vlQ z>wKOs;PSY}aE;}g+NX0_zDd6~eF2+?z0=Em*NpWa|M>JF<^r)T zkQJ;)ZqATaGSBk-^5pbEVo}&Ho3bzA>I1)Z;Pz6UTd8Xz*JWHE;9c!W^L#m1k~OQB zkuTN0qLSoYedw(8L2T?^&X4Z%oy<1B3EQd$UX{&ol5^)|H|VSbgZq%5TyTy(P!wLo zOIAK#zJs|CbIvBbuJ&o{umK&>lI4sWm$7}Q=WNahlD%h>SNa5b|* zD|y%c3;6y@U9RHdI{dZR1XiXGncoHP$4c0(MSRQn59gXOnrwzhhiaaOG4E#ONuf*B zf0T}~!cil0dKs&y@2^;Szq}iMSUWKodqnYXj<>>B`(*=YUumsLbJJV;m$LR(wnvQm z*E9f^x6J5hOZJ%O7?|b*6Z@h0!nySPnol5ypsVzad=iq^Z)@);o^9x0{07va`sAn5 z|7Y2s#A0qlXAm=mP`mL3Qe)MyUUWY2vNw5gH~l|qA2vi{$feL0T4b=9B=cLKk7%H=vTP`) zkZ14fAXZW~)(Gej$%8z4Z3;Hf8{B^huZmw~6UjEJ=2xdZkQHvu@M|%a|2q2^eZBJa zSHLx~KYs=sF>D9*FV1#E@2|#&W>0QChcZI)0e=(mG=BNQSRfCSz8&0)m+R?Aieq@7 zZ>&EPe2n0IBKHRF6Zk%o`z+oYx!b&-&ApcUDDILgP1eE6HrhNab&&mW4pz>|X?@%) z?1y!*qIErbK96VF6M8t?Q7xP)(?J-{NL zU?+T_@r4C0E%;Y)XKU~6ELl1DEWf`0V$Lg)UW{d#m-Y+&kH|JlukV+im~nZtExM;U zHt<3i*>kawug z=pB%p_zd-|JulchUuSyi+XB9=VJwuCJwjfclNhu5h=aiH2ZzJprC53o{ZnJt^~a(y zoBEE%ocI`v?}G2kh^<=1K8AuTfqyj4UIfkwt7R${j#smH#E>3z%KJSOzq#rvL$RC66biO#|Ambw7jv=3>V#{j(YxUFfkuw@A zO1_)~Hz9qHo5;p0`myQR2_`HCbPoJl+12=>Lm8gXS|hzne&Z8tZfOtJTT9l&J@88X z+DCaeZM8C4#SjI1exC9Fl=)9u$>B^MU30pgMqtz0qNpD2m8tQL#s+_^z7t`6vZvIp zGvRq~u)cX^M3dp=_baP|*uo+I6~HcEt{rF-{d*zc=*?$bq*~$woB`bvYY8WCoXN2Voe}752ignZcL_5#o#Z@CzH@t|C zUiQ$&g&uv3^I=IRd9&{j`jU5zwOWupF6WIooM$7Rx9fxcyapRpeOhBO({FtGrjHy^ zd^LTcYn*%sL&JUkbq3mDcrcj1kN8foOV+_dX8sbs8PJ-Jw6)>*8uDKVY})%gN*5!Y z);@j^UKM<+=1>Q6NdH~N8hH#<01{dTN-0I(McDWy) zO*?O8zNV^wpIOF8%21!Y+h=bg`lQM-x|wg%*QQUN(I2NV9~JdS($~}ehI5fq&~soa zdPHSt{^+xUgKsTW-#*8;d;ab8m~tmfE!``fyPNxe;E!;=O&k_JKsO6ca`d%AU?1A; z`C_2IdiyoUBtM{SeW~pDoa2cdbvJX0oLOX{vs~9(Rx6u8XBe%)*B;q)^7SyMbp`)F zgxsAbIR6TmGQfB;^UU!Z|LxSkiiXwLiJYq6`Gs&L>^W>a4i?E(>3fvE7K7`Ni)}kLxtIp>eCm8gFok4#sav{EP8TfN$}Y)lM87cEp&F z4t>sL`1#kE@wT0l&b&$MmWT;|1sH?M~>jmarFk{ zB*p&eoN>j@Ne1@C<9?d=DJgiVeL1|eva}vL7#Szr!&45nh{o%ZW5TES|MS3*LvKa+ z+;HgB!1_<%d%*s)Lx1Zb@f*CUex&#p*TasY-t!HAEq@Q+DR!zU{4T!Jd&GMq_%8a} z_-HAktTr4c7zJ+%3%E29F?K|qH&GYyN;Nib(M^# z`AGCUp33W^MN9m*d&yz1JxI%jl ze@}BY%<`qm?rt(TZz#(i(pevQ=ry_+z@jphr!R^9m&X1@w=BmmuCsz8d+!@z+!lOZ zj8O)1$JhwSTeFtxv%dmYnE=Pzv&fo7kV&AcxqWp8IMe+y0Dtg*TJO+t4q(wS~G~W6oU2>(YUB z8OE8}U~S0V;4K5Br80r1} zR=Z#R$su?hn!QLH`X;U}^}QVE81*yxG1bT7;7of0N`6(xr#%P`#9wW+S9K_z(m2dH za3*5E^nzlLu@48-wp@;VdR)inEHS@^@0!cTE=^2m4Sb|2@M-c>Z;Uc)z`1ZcSgyAh z8-GK8jo008;X{bz*PXvTtq+82=>*|exQ^zoBHTI|>EH3e{2h3RWNRPzlMkv192&oM zYAAc*_8m_$ru-^+8^mv@r}5h-6#MT2qme<#9DI@Vb1yPTSR6D|=JV(bvJ3Ph2zn5wjlX?;AGE_;Xc$ zUu&zc^@q!UzNVzP7xi}!`(q>hA6Zb2v47_nNGJwM@Th(2gCj#87e5{ZZp9KueLvFcijNde zevIga8C*9=27K=j&Xm;YxN@KlZzLCQlu*rG(dwu6z0{V$OJSX_Mwset9MOnz5Sr z`(RBFudDPY!|!pv@2vVh5Prwo&|H&aZ2)PffP)(9(VR>v{BOp@g#hn@!G#~T07Eo? z?G}3c9Ugl)S((xW@~0GLm2^I->_GG;e%^L-Ui1olBg4YD>MrU`@mz*R9Xv#~<*lb5DP7)t6u7 zIl|*}JV$uk%X5Us@ADktaW~Hq9>2?TgvY0Oj_|mH=O*t*m2<$W&Yl+Bij`3;<#2G> zw3fAkJqxWR_b;?ouV$T~S6`YAe$*cE@A}8a8NM~Tj9R`4s3w_2&u1V{49FcB|-Hi{3KlnNik4)^ESb`Wq+r8Z!E(G6Zc_ zUg@o4JWH113-*E@};@i4h>*e&{S&qqeo=(Dy#_GsBo5@A<;hCi<4e2b6tOYaNs zYBO;fr2FiErAfe2WL(Id$TTRc%wczHf~6-$Xx}zMbl;%=|y}f6}NQ zT>}q)8lI3m5Rnp-l&cfu1**+5RpZyBfD`#!@Q9=MTTU5h< zTJ37J7+Zz%M02Y5hG`_@wFb{gJv2C832YecHxSt{8iPbO%(A%JAX?V~w*}rdRLgMa zcy<_TQ>VF6Wc>5k*wWAPYe#)idUqrJIMTaucuh2o==(|0mUq=7oG+1%_13c&?|QR` ziQtaXYAhDnfk%FMY9RWq@}lq8{@}EI7|r#}$1a!tjr<3Lb~$=EvKgcKV)|9l&e6~P ze33EEK#KjLE#W__`x@ZvD)r53^%Xm<`9A63uF2i_l!#~GUo^jlK5q7C8@Azq`cce6 z7o!V*&loaJ*@`=={;rt9>i8?+BeD^+N210APM&=5hQeT6!T*ntW0Yt&y9H(}9F#?qe1 zcKZP7qyONjsPxitF8OJHLV5o4KZDq_+Jep)vy8mj><%;W&-h1>r_ALiTm87z;cNb1 z_9Ju4CE1R#4CkX4@O5BA4)d4$vK>`Nj93802E2)06P}j#Zmn#dJKi6HeID85#1R{t zT)Zvcwe+^?Q~qBv){EMyG4>FDL;ps`LK+8Ew|NTd4r27_DbStv(I*d9)TU=?Q?=bE zz7ns=pJV({Q9MNsJXZN}G>@h6MJN7Drx#pdJ1Cw`JS5uP1uR-O71fDBikYKZy2a{hF`0 zGWmVjCkOCnFsB{F*4XdkgOP204K}!Z-R~F6LQKQ7HZR!cb=6&_50tGubKDtX-)>bb z1mjc>UCDT6EipA)=$9J%H(_sSETr-^=FwV?`yJ~n-*~W{#2kW=zc4%FLlgd~$f4W!6r~ZzYL!U=XPUH%_&ai-A4B4AF+|} zjO?sAMfz$2T{IB-n0xLC^8>;q#0(6yhwqn??grisACT{(yvHa%D(6GI&*WYDe|ngQ zvo#YR#>c)OtXFkKFwoQla%dpt(cj?T>(QNBe-XVG(94uL_`aHV+AyHGlZ$vxSN+?{ znz7cZ_a8DAr2T_=Kfr(5Gx$D-|6bMmIq=r#s`uT%(p2^SHO5QCfehw<9T|t8V(|S{ zWE?VL@cnvZ2jm-k|DTixt_Fs|C-S%c1^Q0w=cc_R8G|45@XS&>F*2`UfX*VJ#)CiP z`E{;0xb8+b{ej%*MaJj3-~-8zD7H?rem4Dh1~hOo@~di%z`Wut=-EA&_?LT$@sJ!y z{m87F)*80!NI!ay_9O__PhCygR6X(}^!J(=8{)(?hNPX-0!U*flIv4*!%|YTi~1eiM}c3OtG7(LJ*hQ%{+VcJht)qXZrAK(=RDo@v5>@ zW7wD4Z_LCh5K}2$F=_D6ZH6X-OR|20OZ-0d$WO02lfdE>-W&VT$J}{fYp(F8(syM~ zuVG#B$P}<^-WZaW@hNi-9Eq>Ei-E_5jh4$U{Lf9w+9 z$x(kMnE$b9&-z;f`K)<4JM^Q#Z_SJRt(AR;mX$iM)&4!JOE&l&mf9THV)WM*_P3f& zn{3V{bG-w!{~*4g&FHgWjfwQB{K^0H3-}6Op5(IPJ{9LDo%A+*9JMF%Mf`aPyX0|X zOE_vn2HwgV9y5Li`4~P!`HFS@oa*6z6qvQn%ApPqeS9fv?VkORbz(l_ljRe8N^3Z0 zTE6>PeaKtdGd9^%a=jjO2y&><)4$Egg`R%J#Q(KoHnKha+9$|PF(zs6>0hM(?FU2) z*6N(T@2UPC{pY?%GL3xNyI_n?KdlZ(!kW;H)aYF)Tl&ajz(32@|xWs^p8F!!juOxP~|-GeL{?e$jP zrH`AqH}+EcYiJ=J6U~lc3rJ43LvM{)%v?e^2L-t|+lID&Ig+(q^qq|l6Jwb}7GX0< zE`N&tEFRv39aiHZM|j>Sy9+oqUQ!Hi!eU%XpVL@t82GjdKgQQ|PDN*yyFAA;j1~PK zGtT>QWjf!oq>W`-eJk@4{q0A@DqZH={!66gIXl63vM*Jp`^X2q7cTSN!b_FIz;pRe zupupY(L$#KOOkf0Zq*zAvEtU?m-J@V9WgF}H|>HMznT9^=hJ88tN)GGNs>RxE5FE< zN0I&M&89q;Gg}JS5*GOtCzJt}ORy{K^cvq{4HIYc_B&N^Ty9}?QRlB|+(Tb2W-Q6J z4nJ+pEY*?TNf)sFU+LF)r-uIGrj`Zik-6;I!1^ZE9Axrt9GEXj%`BZu-;vG9oMEGz zIWWqBrkZ<}98iCc`tH05ft~QwILrDGa!9f%8pl+}V@v*6^kvB$Cy(wyPYh#U_VY%s zEVVK2Q#-93Yl@+FlgQ+mY};C8Z|ZY`O0 zdS>0Ti@R!WnYAIzl`bJ8a)xs@zM{9izr+E za_KD>Tx$KOV6}MuF7uG*C6~j?tj`427&Z+$J4lo6s8}hboz0x}diM5Nr~RT+P3dKg zY4o%M>=yk`GLZSdW_=S(kq$60fN!G8Xs&_OK>f``<9u2WD{7?BwOoqi(*}dVwx&YVWB~^?>;fPNet#mNL&v zt}<=2_!bv^(GhOC)7Sbk@Y_Rw!Zx6+l-e=d_)=@V+kHJ-`3~avg#RA!&_nDnXOX3E zH|>{yTXnd=)l@a-@^R=R90(`ELz-9&(Zujz1|EbSuGdiuuIePSxHsJn4K(JBL+kXC zhmWsDN`0vX~ zBX7XZfqYxf7*y-Y-Si^xF}Dc4yK2GN_Vka6Y3LL$Xg}Y%MZP7PSR+Gq|QE5AIEza}Epj*)I;HA5;oIaQ@ZZH0{sPoEQOM6i|{%*g! zm_=@AEU`Pifj#Tz7C}w(v(2v*E$|^6ba>0l4lyIefA20WyP~To*xjkbm2*9r?k>)v zU9I$?k>_tPez%}apE0mwD{Q7+<#yJzZBHL5x`lkvGdNnHzQWq4(WPIQKK)2VY19tg z)dsai=dCD@@ue;9klw27>Tf6s>ZuA=LP3%nMZXolrWybCGj@MPjz9}a;t1am*>o;Y#t}*eU z(l;q^Zu!3(YWepLHT|lpPdW6dvqBuu@e;e}_wOPRZaq%V&o*FqO_tH zdT!wTXy{tWl4wYq@YiKe)3LSF6$K$Uv0UkNvXlbv*m>r^XP!_0ueq|b zyq)vPMKAHb;L|=WP6n9(-m|iW3LXB_;d<`Nsbe?KE;bK+tc(uqc_I9FDf}O`VZ87^ zH^4vqQi>rPrqO@moDr2^?O4p~EIYY1{xjr#(tD)H8Up&(+y>dIlBJo;ds)ZVS+?B< z)sgrf=~N%G{LI-w!9EbmQ(!*oimTQHK0IWYGlqRX#^f8~oD)@Zn++T$KR3aFt|F^ALx@*NN?dw zWBsW8l0Cx@24e-w$6mp{9zmTk|6sp-Z^y9xqJ30c+AO&G9M*QSc3bTf3?6ej@L)sJ zq`i%zk6_i^0he}CdT8QXi4&cr`@A(}C$r2qva}#M(Zw0^%jka{=**6iWZs3tvSrT7 zZQfqk&vT|Ez7@T-zp~^6@}XYzroAI(aQ1>@={)*%_2_9A`R8(P0M2@Nx53Wk>r;gMqUMf_ZCT%ySnfZ|kS zzsR1}e5>^5XyO-B;6Z8Sm-{5N);?g;51VF>^VPO@=+lz78OmpzTGIZ}PkFC$=Dkx= zAH*NRe1lWc+{4BA*v`)k&h-}0qrN!!w=(xvZiY`LbKbn>U}YoMcp7g9KG3=RyFC0? z{axv1@o!SqKYfexUB^H7rPK9A-<9Sg{M&O7+JtrJTQ~<@{1E>PK7_l%x$$^`zD0Z~ z|Ldv0o;`W=Zu4&QZu9OcKR6yp956UGZBW~u-aB(JMsp11I>4jvQC)4=T*}+bKjxwb zv>*KY{nvhil6kh(;egY`FWEC(eHi}T(ZYUK>Q}KmXFwv;j4aD6_wl6cJmFMa`(0@%GQT>7|N+j>@xaBj5RDb)tZ>V&GPO16dqHo z&AR=;*h~6DIzHyDHu}L$u{WC6S$rb>2(aamefzOF9^u-L{qwV;(tkJfTSa~aVrz;v zxN>rVFC>y>L$IeHmmVD%|=3%wZJp+rx6<76?GNe}-vTwBqo63=YM0Ra7)|j{d^!(80 zQ4YtWc7!pcI`?xubBY%2aN2`5X)m=bGB}y-@S}G1QYXI6@+BGK>@xRPWIu`z%x8Agm<6iyKsijGa(p= z(JzZXRkq*~Up4}h`hw2GP=BDjZ`ssGzgFKUK2KRM;HR2TdG?SIjL(BQ^j&3`J^x9k z^6SZ?GA+v7IRg9)tuHf1G5aS{R#|Ypz;zvEISKwz7I-!A>YTsuZ2D$WA)!?UFqN-LLv-kHfR_tG!C2{LwiD!pR8l^~xCR>z$X+q+N4NTGGXJ_Ck`qp!J;? zumA?iQ*1D0nX>D6Rz0HaKFZz)9yNy`-cvoYDX1e+;Jf59@bo;xv&yjfu6}0$bBz1S zaq15}B?o&(GRDfVo@yaBT}T7rZPeBKD*pt|Vtk8Yhux>cJ*~p|rHEJ6=d3Jz)6Q5c z;?;bIKZAbucmbc2>hOCj8GmSHcZT)W&|{0@FnhBl4*Ioyn z@s85xrkB)S3;hQUx~5Zh9b>H<$v-27yhUeX!zGBpt?U4|b>In}Z~i{@T?T(ea!;~R z^_#lTe=&R{UjY{McgZQ7)+><=ja?J)BJ*s1~ z%Kb2VB|%rEjsB%bznk>fnFI1kX)acB>ieukR~rSl{7*a5SDQ97f3P`S)dtPSt31{5 zaq5sSN$2$g9S;Af{|T?kAL$Y0RU4G<64FKZm;8v%1yTPNEu>EZd!@^*=bPH=w(TqD z7@IsjR{h|%GJgNTw#zQAZhP&ty?xkeeeg45N^3yn<(S`k8k|0T2F@dx+JqD879TLL zGYAv&I?eB;aaSqAqt?}2Mn1JOqOZ!+|Nl*_o#<6fKZEa=50;0$yxQPlH#WifB;LKKf;mvs|C{wn~N%C1f-%B%1|J%v^Ie2l`2;Rw$yku;K9JvJj zab@1!Id-OGm>uyhb8F4JNpI4O&bv>Km}x7&@*>-)yUSI2!{72Z^Ib7m;9=m7?VP*A zbsv|WpCzB5SV)|G`z^rnHS16jz}(mdB()m0`AZIG{iMEP4Nzn}7FAh#r|kU@qQMo^CU zP_pVf$XM~%PWn}K-$h@Te%nO<+QmQFFHyf$I`!##{>?yEMfoJ3)o0H2@@dXnGAyb`b?E=e!a<||w-XZ= z$(XlEdky2L95|A0*^$1%^p$zo6ldzvs2$%VkJ0nUKDANbRYwCd@D2VMnI7P&c^0vU z)o{p0tIc3jsy=X`KFfQ9DV))SJZetw)mo2ySu}9?&Yocn zPr-wX74aP@PGoNRqdcFgYQsqItvXf5SE=J9bMFz1O~4!dyNiEsRQ(%O_3sY;6{`MK z=UdFbZ&v-Q&UYLC#H*%`kPm`3v#$W{jBufEDpN3;b@7JA*aq|^*(<_>WVHHyA=8a` zV!sjiTspG4jB_aCYU-?}(_sCSt+iE`5N9cUtU9B->W9B2u0p&f+XPu*>>H&~pVjz5 zX$9XeNS6-Fi1I6)Y^4+YyS%EuN%u$jj`43w_)q01PxSw%{QF>4KJkB)?{)qu-lw{* zh^K34Pc+^hhb=CpcqR8wa(!#MW%=6=Ca=Dl`75r6zQumD9%m1H0}nU%;Jm!U;CF%X z&m~#cs4=_j|C5Y872|K_Q`&}&byv8wH9=s{|X-yXixR~<-BJuXWwhalNuKca&H3pugQPIs+CPOJ;^ zjP-}(s}z6LrIxvp-O)Hn?G*n-=QiJ$TGkNdNd{+Um32NB>rNZOw1I6z8IWVZX7SW%YWi+PLG@?st1`06%`U!N^(DSi{XF2c*ZdC3KQnBZg6S6h9R zm6*wyB9pYQTQ@dAcR7{nE|2uP%kCA(xGUWfZ7U9&CSS?&qSl!`!M%m_tz))Srr295 z>G~}d_e1QfH=cQ{R(y9Kc1ze9%mrXuvEKcH^YLrynd@2dwvl%#d9Sa3voad_aslI0 z?3QvTb3y8(*L;9Ak@$926g&NK_(tU?-0X7J(z(kTYSVrF!Y${HlWT(w(%o0zql zGay!%no`<}p|glQBUWe`|9};~+?l?u=rGTuwg@k3gXTaj>Yq=WGnB{KZRH(><;8il z|4HsoaBb&`#;DP`kb{09_}T7-r}Ov)7@JN8r_p(wmqD{0GZtP|QXTU3Yi`&n?CTf) z6Yyxn&zeuwnMqm~f3bB-C4sN_QqBdGuXsZ0mdcb|Cu>pgzgnI6jD~98bL4iX@x8Kt z95VZsiW}=-&HgQwi?X*=E-Bnn(VEj1z1D{-|*+!hj>nrJ~O7Z z(5v&@%Ca#Ow@xfTrFE~FJMGt45gskMen)63_tbWObLyUH;2RNdJVZ$RZq9^Hq(>}1tElw^?R z#T;VIWRu&A@qsMLW9rN?J|xzbu=mdf)2=D@#>%XA#TXN(4o};+>a4*H#Dz*%5`Tak zajmn9j+e8LR|)ku`8Qss45gEw&SkxyX{)uN|0I4!!7kXQgz%j?@BA!zRfft+nfx2V z_I3Ab-uc9@PPc84Cu!4jKV$Do`0<|6Lo1udDK_KA@&ui87LK{c@+=+j>xt|;Ih4JR zh>h!xfx}+ETtD7AaW3muuD^l!5#c&By=2baJ*7lnG&PS2?< z5FQJy3<(yPd8jM-CpnIOqMAACd)$p2B&IS*j|^^BtcjI+#pr1EiDjJ>v9*OD=KgN# zlMm=+>Rj=+=v=|o{;`t%`QYw=pLV6m=ZlNU$9~ggJOA;LojGz0yE3r=9UsB40NO?{ z$lg~B$F1CB9yBGr@|paMA&EyE*#7K7>us)uc{1d7NqvGCmj=bYfHY|S z{x}7e<_LB-C3yfHxeLGK2PXBen@w38C~L*}(35$J7;EH2Bj_AHzaTqxKzmPVU+N*? z*kc})@f6jwj?Kf4n$%fKqC~vDvtRqX4yF(HV)d*!%-1QNcuraCHh^tF?O2kY>BPr$ z)k-%D7sKfv7W)~oFW=D)J2=!Uok99n4om}kj!6aR@!x8YS2zm!8( zrh1Pou(lqdjYqY|K5`y@(|&NvOYP7}V-~}6z^Z-mr_kPC(gt|5EV=wG=GL^Qz0F!p z=+f-a2lTxL+`esK57G&i{}aNYb2imqjGYUuY~XM*)WiA*?X@PJy%^lu>HlGPS+WPQ zKk#kg4!UXmpw2kcb2spCR!> z=L1_F|9U=eYyL=cUgDd@;{7~2fxKU%?1P`d2FMSsyu$OTjK#XddB#^nze88fD{CD~ z9rq7%*EsAQ`nF=}8+lfo6K&`@i)WZ5aRuK;@ys4kiLY@NF7dh2#yo3U;n(!@mD{Oj zJ~5Ux)D~mV`;Z}4;q{8gcf}!nANxaP6!JEb zR*UWJvgYXgu&ohasJ)`S+OK{rxvp=wlFrUNe@t_Z`X+jE#^(TamT%(U8lEE?`1o5( ztk>)R!V+Kn4x&fA5!oNIJGLO7QqI=OM$U6rKXbF}YXrTd2NKX@xMXJ*{sO=8j9=Ww z{9g}gweDtkd$4BC=o@SWI~~K8m|LDn{{2c%+lK;^_=R>Rt}xHRxp`B0-bNaK4DD$T zbr1LMFMw+!tMayujH=1z8^(hNJ9}LT8i>~h#;Kfqwgk^5F4S{Ydchj_GI{4A*DWtw zf}i5EDBl|26^CIH)|7ShuTPaJ&t=V)WAx;dWtDq}8~bKjf;I{c_xkgaT*PWcqk+Pu#5TrSEQGm?BLmj zH*+cSqGOiwjto3{&ZWR6oTcPX(0FudS@cvH^GMT0xjYX{=lN#J5`EPUZ1W@Z!B=DB z_Z?v``hmas^kVCG3l>}T-&t%;;SxWkE&@27ui;wE)zY=t`ZD*of4;=(;4aw{$@yv- zZ)ftaW|8yg)}z{=Q1ixuDVFUjT`yUb3HoIknEn>{gk#&fzBENKL+RijaeK6LZi%uQ zzDyeR3(0!P_WP;(+gwU}YP40dlH6O|lFe9aEZ4YX5c4GXwukeUlKE~gI-P!ygP$Gt zFP(*n`Aq;{9vKwaizn%o~Kql>;3(%O!$2U_bgWv*MgGHJhTSpb4S(;%;T;( zoh*0BlUdv)%V%&m{f@hAsSNk?fNOXNm+Xh9C~r5{ey)RDuW`M}b&Tt6u6MY8%N0Ag z&`NTR1Pa^*mlkhfo*^$S&YaZ$tcgaqlJGy+}P42?O8{84v1MCG;p>GZx z<}N$(Aa}LtMeb_Te(q{hfxFtYo4eYyle^mV6nC|0JNNTxlj3BBYvox4Y!yAj?iKMl$@(b)o@q3!@x$xW1`8J+*v|o&F zB+Xk&122x``G3jYBt3Gn7$eVI@~FM?8*1F}j$~9j@i=^^FAvP*F5Z0&8NGn=GL#X+ zzSH@IvTe;CtjO*d=3Qh+m2jIes{4oj_W3_C0uuMeTA!=>&C|xTYtyBkLw%v zF18-vzLo1Kt^(KdTnD&bzp#GHy~6c#u3vKfj?3M(*h+CVa(P@6xLUcUan0bm zg=-1d|KM85wU_JLT#s_~a=pUkb8Vin*!n&9OTV|+`Y@OJ_GsD?`ACr0#e2^N5487L z=B@I>!8h%bZZUEolE=OI;(|~XFN$w9vRLD&JIN~@Xycoj$DTOSsT!x;nMM~d4wWpk z(d|>NK!2tCjx0zIJrYOHEI~#e4fmlcdbq+~;|~iq0{1747RF-$Ue+9+b_ga%WMl z>S!X*bn;+V73mX+`J{bk;(advUi-eX_5z0Nh+iy(z2P$cp*2$Fj7(VRgylyI@z}6o1Fk zjXVeX@5RT0J}muFaOoe!w%$g%oqYe*x>F}QuB9)BdjQgROq&FgVADKtit%6_6xY9%I<-ukadYR z(tU(_J9684;F#iBw~>zV z8+c+bn0$xXFC?+!i|j4S-BNNXY2d$|ji zA?&Gb`hfDLI!YGnYa|0ThoQVSd6fScI^i<%yosz_#$CLo=gZ-ZH?Zpr-%%&^*1Ng9 zEq}h~eVuq0d`K2NMfxYt$Dak?Zu6Aq!AcE0AiFtEc_TCHDjP^6{C$&j`mcXByb;-M z^S*~3V2t?o|6XF2=PP(#_&uf^RD0x$xV^_@=dOi#%eckumEoALrBW*h40( z{x?|0$jqk7&M?n3zN`L4wCRhVWb94VH#vA`wDHUc+_R|1$vg4etZLSir9|_ zlHLkvN2<6`e7lEliD{xa#LfMB=_g2OY#|cIe-teGM>Bz zzNueE=i+K?oqu+*^)Fm|xkl1Qf52ViUCpPB8QEd_vDTt&pB9X%BHxY;o~&MUX%775 zyL`!7`FqeW10C>xMe@?#WFv5WngkXe2#hisyK_(B>^rQ@Xuu~pbKoRM>I zVJVSW?4QD4C0#2SW5dJpQOa(L{K2LlhW6b5Qy9MU|04`q3mxG?cyKep8riGh7uhnh z3lq$}7atzUm1zUo_S{bF;# zW1^)CjjQeW@xZk!gp2;$d;z>f|2d$tG|zeT!>8!K-vHoyPwp zv=uGyOAW1T57SK{-K{FGome;OQ<{jrO7{<8x>WlHGxm-CDcx4dl(1gaDY`4&LwvuF zciL|H?`zl%%nj0Z0jF1Yk)Uj}^8Ca!uX zlb^KOl1-a0PMRZL%@)soQd&tDHVG|VP165!6BIWI*zHb2A)7_AROvx(E zzf7V1oYz$OEa~RM!*Ne|r;jjRn8kn9GkauUTStB3?{8vky*B6zM+=LsUvVvEtbN{| zV9fml&sXq#BUdMvY^cY%N4Agpk91VT`%e35IRs7*NbaY=>ovfH%&6iK=An9-8wz;O zv|BQvSv-P|Pxus%s12_H`{m@ft-N&MAMnXg@FhNxj(c3~BrR*n2i}igj)~qm;pLOq zy#ami$!u**W;VqC0~$#$h|bh&FR7yQxHIT1xP(*Dc_{S(uhFTus0?fX@ss?#f@LOo z{|$KljJxO&;a)l}!uK=aG{W=uc@|zHoVwuDDq!FDBD*s@`+=Od^SpbsCH?h^Rp>JP zbV#bRzm|)bqtdoX@D09H&G|+9tTSIet#=RK=>twy6WR};uyw`Hq_$0=-Lv;y0<}!B;VNWBCsj$s<)rQaD_FGzqM?K4~<*H3DUkOia zM2>8(O>OKSVkysT)$uLaMBV2GymHYXY@GK!X?4o>JDrr@*J$wNvBzmzv3)sW?ASL` zIHd2$j!Lp$x!_0cPPW;@LuX|1JWg=Y&l>+1vM7RWzP0u5OQ%kKOZI9F=k93zu*OA- zc@S>37l8hW1_{bRC#*wvjDwdaKME}(UWi#stT+C3iP;li=03(BTwA#ga#iy}HqDs1 zFtaox^dV7B(MjQ3_UQZAT_bg2Z_|9ArHV)@|`c> zVoVPoY$n!FKA|~9{1OT6-RWkvcgBtKpX^foZu>+1wb)DXO#X+^=4d_n{_?Rv)?Q{Q zZY1Au2Q*Mx$sFx*p}uB(>(E(r#|L;+<7_*<5*jS_i6!>u7vx*HiLs;E6S#Z}Wh@Y0 zAMYt8bzUTU*a)wJRpUgB-vi!WP&^DSbG&O`r|GG!6^+jo^V0@DxU6#>OIh#>x+{lkF!xd;@BC*A@MB}#K)>kmAx}8OK104)`|+_ zB<3wu*6cF6n6l>SPFc*A1J9d2?E;2i-n@(P-ipdWaALLhnf*=VTS}%MiCf+y@l<+? z_G7Uu_O?*mj^cAnpEdkX936gUeWN`3KYP|>=nwQ)#WFrcjHAke#~!o2{0=kT^b}Xc zd_6dpzOH$j{mJPIN#Y!BZ>ix&@s0Wtym-0rF$~|eW#t>>$51|lm((Ww`dcgCHt|4y zS>q-6d~m!Z8i_uijc8KkTb2IQcv$;CY99m58_g$%Ofs3ViVgn36}Cg3{=%AH>3G?& z32=QYxK`g0u8B2A2Mf>W12adOe^u~7XWPzoVQ$={I0183ZNP)sA`Lq5hPSmMzeexn z7x}Mouk$!d4IExddE)ztz$6_o8JMDa1Dgn%<(?ba7Q$e7Czsb=C4;;Jf|~y?^4>m9 zj;hT2uIiVWPG<;}%nW8HK`SJ|5Q0`9NEU+@BtSF)J7IVcA~uphbU|CqDk|b+W)eaS zaqvz~k_aMVAmQbXELL}?OlVw<_afrzI?wlasw$bV?C$4zos)W=I@h_*L&Q!I+@Zy-W?j|_Z04awm1X)uKTaId52XqBn9qq1d_%Uk zv<$|2tM-Y*;~G|_H?qn%McQv|ah8l=F5lWLZB1!IFmL0dr|ymUl<2|8{`5>3U~kdp ztdGvY7#x5%Xx^Hu^wl43$Np!0|A1!@*m>F|d4D(W_ayI;XW3uUKIxAGyni}*e?0H{ zF93%r+pYwX4e+TA(UMbG8!O4zV}1?)gyLfUi+*yFFD`a=%2I2<*N@~= zXYtvVXq_~nPC z!+px!v-j@|DVlS?bv>y3R^2{QAf0F(g(tXM=AVUkp8I>J-4DW_n&w@9X zHvWQMy=NSJm^Qv9UBe4%1LNKmTF`>l+K35ehc;suGS{fCkJ`dJxmJfB{~i7-?uO#j zk3c5Ko}d^H571}H5XAu%j!I_^|#3TA<}d7^IY1ceq2x5>B1-G zAJ8fGEOblyFCP2Rgg-D=MNefW`V#oENikPdwoe_Fvo4a)fTcXtn*+9gfls}LyivV3 zQLiYNJMdfOsgU=(^sg@4 zYZ=`bc&C0g_gsxV^q&`52lp&Gq^G3vaUFbEyy3gtPwWgX{V8|xi9c|EgUjN(sXLiN za9zqJ{_*q0i>&u;US#$0UwW{3N$Sg`wF~JpS})gr7U>b%yMKgUoA;kB;U0xKC3$8?Jnsrl$nFhv2{V0^#7XW^)~s% z7<{-ikz43gvaMn(R2&J(FzJKBr76I#0Gu_hsh%M@X8S?oSEFOyKZR#1!)~GfscvzE zPl@_R`?DoRlb=3&r0zS-Ka@iRqeZG{*1h%KGpqp z>ik+R=11M6oz^P&Z6IFaoccS28>DYf(&v&so%)CJqXo?OeclfXpN+a{(==#u2K*?; zdPcfNe&>ww;RNWjE!4Ts_^QH#Cc%S7c<=@IP|Aa(S8Gqi8rm*@Ci!E41n|-B#!1wn zcD(@)I8Nh&Ekbg-z&qIv#9z)8-$~|#_k&w0e}VQk1^m~XMZ87646@ORZ-0)uHoIG* zdxVSp7e7&4nk;y!Hftxn*x23AD-GFpS*6-FY+gY?74>WuB0q{o11CdZFGT{ z?r&j__Lk@}(pQmwtmGEBk)e*%Hl5PD=zA-;n$q}VJip^7F`YMg9!lFoX?mz#8@kK} z{+4_m96~Q?owCmNfZbPD0NV0%z7PhhK<(J5@H zW7Bm0&rn&w_BiUY)9)$I<^8d|b6w6wBj5Uy-SE9ej>dJQ^!a}JD4vz-J(6Yrlke4= z?IGf&Ss!~7bc{dB-n8xNM^)`l`l7NWs|E+M^=-T_z}I=#umb4Y-M#-^=$}P!E9)(V zmUc&8X(nTSq4qg%5)T*d9ANEK{Y-T>@gdQj4a^l+L;k{cNj5~vPU_u4U5@nJaxm2? z2jjEYM*jUn?2+Lc*@cx4J)*I}z&h5K^DcIOa7}*FvQ62i(htf|Jr3>o2JO(;-nMe^ zRdlGPczp1)n9t89J+-&Oa~rpkchJefOM}J_r^V%fyV!r?ae7dFf`7@Tk58`gJ>0{) z6d(Q<<^CcmJB59=3@=aOc2=Q%#hiKsK44-&!Osf;c8!6TuvfG93wpw4y4Utc)=x<4 z6>jCMjnO6aS?$pOcziaR@tLpjVeLq1R+aH}pE2VD50;%W9-lztbE(E`(=2$R7RT4YbP+g2oK-PUd%QrC3jHqaEp3@ve3Xbx*h0e^ucuD#og{ z9DI*)L$^of(H`l18WWAr?Sd!t0X&O4fcqKLFMk8{2gCmt@L%#uc{NwVFL1wLeG%_B zlc$CGI)2~Vgj*V`lXy>mO#Uoqq@nlJT;_b2gIn}t(?rs_H?f^XXX}}=%1JrDryO*S z#vayLl&6-oO!q~aJp>&ZR z%6tvKAo+?}12;#L7|V$cG^g=})>WzZ0pr8`SMald-5ZnRJ%8FOn%Z@(AjZpF>2`D0=s4P?7}K^ts%~RLYs3D~ zF~C|+WgYtcaMn-ZE#Qv)F#KUd_)?j%;N3~|<49h$AsS5Z`S>JFcp}}zI)Y!}!y$Px zAbkF?!RKznuQo;939QdgVf|))1b=smcJI&b@%-O`- zS+`&>6LZfY{nGwe@z{w&@WiLS2)~xthC*x$+N1pxL-8TyUw;EmxLl`moyj$u>qA`f zKNr4;&aBkd$g>SBMN`Jc$egH+_Avi@wQU!6EY>04D!*`LX#UHGod07OoMu(_+7^VxL;%OY@rd#wN);$O^Lh-k1KRcDw7MR^VTt z4A}>C)}!S4u-H~0Ul!XUO?yZ)mh2PrrQe}8$8j^;{%vvGf5z8IU|@%=MZjCM59bkY z7vIc7CJ&rSeW$Pnak}d2u5RH>Ip$#K{Eokt^Escz_gi%kcgbb$?cW>)jE~wjf<0%l zr+`1$`PR^uIR3ucLjN@v0XM|Yz#rgy*)JAZALY7;%kV(L5Q^16!7JgQcVGEz20UrP$wB>bq>IKSX~M-&t7*cSV1p{lnPj zSRm~+`k{6obd0@ZBz`Zf=^Ed8biIM-CDN~@FDDAl_z}r}WeR`j ziXH~e11C=j9|~C05gc93?I{ocHLVl1Rao!vuBI*6m|cASDW^ybckwh6m!14-(-P{G z-j4k^GBJ|*Mz&JunEcp@DNDM7h5cCXsRP)?-_GFMvGm2K&A_#xy<8e^-P8YTfUV&C zqXf<`bC=#NT|B!BTHzAxHHS*^Li@c6KJx*1GJ1X|_|VQAwF`R`bJ%&B|96RxPJlP% zEaF$whK#!^%n;A?IIbw+iwkKVlM;g)k9f~OYl`!|D%5({c;ZaXpibf3E8vF5a~n2z z`B-#AQw7EYnbH*Rl^lJeE#|`=JpX~`6o-V@AGvCg^>O;~S+4BVN8#lcG{(I?u*aE@lHhtr4>3nFM)x3f7`nXnb-OMF8 zNyqLfF`ooaHTNj^@O|Kfd@dH;^#&$w_?HVV3xJF0Ml>V&SE|PNH`k@F)OC9TC-Jx{ zeL5=fixO|0fzO@#KY=vC;9;fvJEL{LCiU}C-`CJCjjw3vwxo^Pr--bpITh9wq_6wv zldN+{w}}#)1N2&K;lE^xL%V;$`$xPzta0?!A7Q`#JE?mY?JR)LvfGN+v^hF&JgDic z4yUv}vI3QhuOL2^9jtd4dmQX6>9cj9FS6Zs%~xCDFW=G)$+jLRrP zF$4rh_>%Dv>?2LGmUEr*=*jG<-I*_N-qIq|POGVNf7DO;!=$|X;9Im67&RAD7QWTS ze^Bjv|68qYa>O)#KZ7}{iqx~4S3+yXBmbIKSlfKADM|*nG{ApV< zf(`g8eA7Bnwt}r+cn@t@?v6;j&_xIN5q?AJFKc-D4E&I^JnhH~XUyd%m!*szzWd&g ze0GvAOFrg4o#2gPp5ZHqPQy2sfS(q8I?JAT#X1wtX&x;6`g41XcjRws-A`@YX8c&$ zpJzSJSfT@=x6+j`l>UiOkYdu zj1QLJXmJ*hRa%L>+yFmgp5fobeSP$)q;J^gSU=+Y5pde%^`Rwj-q^NyCp=+Z*Cm{D zC|~=#z$xPotvG`^V?k>S+D|2Vno?%ZCw*2~T65Sa+;Q2{1w3R|gZ`lFUHhgm4pZQb zqGg-?_Tqc+n6CSQ*>@9o9Z!2z)~A4#Z01%;>vil^^rch8F)#Yb{|)lX1~HMiB*znj zWRJ0rtt4-$p)s0Be3CNwragw5t7>1(@$O}^>5p8`w++4>Ea!}G(Tj;~O?6n-O;O%L zuP8s>skUiOwSxQ>=T3-^q;n|YVd0rY);qaU{x^r`GMD(Y##^*$Q>N(hy&8M$ky?K| z5B?;%0KTj|muK3``C#$65Aen2-|?L1-L>4M(_WpVS$WD$u6XSFn_`(S0^o1$rrsy@+(&P&w{L!~|iF0JA6PVTr5Wu{5 zZ#2x=8!b*?j?E)48l+q^?s>|5i1ob_6MSGm;qL?Rcjipqx`?&yP_~^!m&2|yJi3uQ zI@4Qg?>ev8_LgNVH_ZC@-!TWs15?UpJ^&rw0&e=?paoadk^6Th#^cSUQTX{?}J&2MD;5nKdY`4$i-rCs=R4eJBDM_I3) z&HD-En^->~rU`N~u_<+xNdFn>=(J72xrH$~n(?0vJx+kn%f>Sn{;d6qPPIQ$+_M6E zYdV~M$u1L%%yvIeKT&<~WOHNBF5jwsZ;T|)CAJNl_igZZ(MbWi0C||FK;zy`q2hyB zK4o!rl(E@cpW|HdG5HR+KR>-ZCf^S3Xf0GUpmT(+N~w;`9KUbLPH>;`%Hj{KGj)GV zTq=#n4B9F_(k9)HOYOAW=XhuK%Mue{e&bqj)&`e>QJ2msItID+5y^MPSvI0VxHp>d zDE3DB;J`1X%THt8JB;|gtbdNY0hrA*`7e}Dc~N7d*fevAondg2`2#e;k9YLPD)r`( zpGD0JKE<~&U79%xIJhbjFB}ce`K#eS#@^TU5P27p_cYbR*o+2#_W)PQ( zoE^mS={GR!;I0@6S@_>-uJ3T|;hNXC$ZB#Q^Xww)e6EjhrTp?*p4V`R zUy65C=f|?&_G4f9OQ1E?eF^OqkGaH=ti;yi!=JrJJ8xl3F0sIa@~rv_XlFk>*7yho z8=_&Q-g-aqD=@6b+wcihK{o?S_DjO@9g^N zz?ZY`6%#46OMP{xvMIWPa%WdKPktb_m3OcPE<2(4?O$oDY_>n5KI5N3Up`KK>c=qf zJ4aor<2=gO{$%mx9QHih{j78ZmY_^5qipKeC0QmM#g^R#&Ol?gpr5YA&WK*@_QFTz z%U`dka#ZijN&UC0zttXO+CHj7i{h!kgeU)??2h^1HX3VF-V17w@kK%DmQN7CR?c6t8I9RzQnhU%gkNDi|TiPW3 z1V6Xyk@?cy4Sn;i=Y-kj`&W;KmJ|N>J;p)$WM+zdWcushPW~UovqS!SHO};565q{YU+6Qe zsagU2j_0TKJiwX`&p*>M`Fw8<;dyo1+OjbGNK4fdAi9|LCM$3@Ei3VHvM z+p?^OIE27*rD9QtKeD$pI%{M+w-(+3$yYONrrgu_kd_%6G)^b|eqeeJdpf6_yvN`} zp0d?H`8NH`)QKGS1A86sUErcvE*5$#*&k9B@{ zlCfoId>O9^^Lwf1vB>4VnD1pLl%6Uc_WOi~e1f*izeckD4DfRbdrZ&b-9+NrNq$d( zu08Zb*<6?}b~)%m@%rO@*&Vj#_%C@f#nG8DneYwiJDj(zcmxm9AL+P)FR9=a9J8B&|xcJ;NLu_)|7is8+FAQN@PJcCb(x9Z-KO{MIrU-Cj^YaohE8=EYwydL zx9^Njr0ov#PJO=*{+#u+pKvBR{W9^q=mlaKny~<0^p`owE`uWjwA03>u^Jd%b296E zXJHE}#q;8y^Nncjo8VTSHffHsf;@Vsd5dC)eS)!uwwj*&Ai!5(T|71^Tk`f;tEVph zr}k;AZ0eB>hN%P@F*-D}aY>1&z;9=04>88!hN{^aoow_Bm|$Njal4 zTRLU))V#&6Vy8nt(RfmLQ)fb`u5r|*vrohu*|SwFpwkXBcBkFZH|U#unxuz;KSkwJ zT!J0cseFa%ZtC0}t(qE-pXM@G&^G20P1&*g1e+?jDV_!13;(IdtP`fbsd&Yw`VRdV{bDFxo-0_>U(&iJg3oGu8)sw479oCo9lUol@J@Bp zGiZax8hc<^c^DLcb z+MY$0(;fsNL?@8)~OB-8hK%KR{C`cCl}A0zLbz!aot>P#cS zhP{Gx08=Ozqz{U)G(L;ud6>Iw5zNDw%L%7$=KMzJnY(P3(%ZjF9`Sdbizz#VXxYRs;``JV5gI-g z+u6iZo+Xy4+6(;_#b@uN46_c#JMqaj^zWMTluLE+1p6rVkm^R(SvY5c`~_!iRPc%W zr&xa2M^|lE`@0)XxG}m8-YA_u7v2oN+sJn}N6RUnx|-MVZ6D7|xG&{i;VwRT1J8?- z=P&Ur{Mlz6C3FFvkK(xlABeo)&jh+(`~&&i9}fCCR@KLGAgZ#&QVXypS=TQX(zkBM)B@`}%#5_xFjP^1aGz^MBF_ zA80R>mUm7!xYKQXHXLM#>|@fit~c+EJp9V&Ma?Jnz)To07WTNnQG88uc9T z#sA~Di_%F;Qjw1HUcqPlLar^VmK<6Px@_+G!OP`&;?fa1Y?4((_g)@{+oW z1H5~Ly6I0-d{=x%G^6>^_5A-nX_BQWuZ`e?LwW7L@?UdF@z2+I7GLdrj&&lgi@2`k z`a0K7xt`-{aDD%>nCJeU=XX3G@9%g&_b+nYz;y!U&Eft%F0I{*@5(l3c&-nx5$?lp zWmnMnA(xH*0c|}g`LlvH$1$`vu--MN-U(j1(CMujD{xMFe7CzL>U1uHuOYvj#~82P zXe}_({~6WTXKjYVIAX`@M24Dm8CT~GvW^L#`4n|%yaijqCtYLtDQy-!1c!Y*3ob+3 z|LX+y$m6bs%w5totZy)mN!yC!Pt#m;OEj1I)j#p)S@dguQfGR$GW|6;*GqnlncDOH z8G2^lkrkYxwE(p(T@%Q>u*e$5bu^dSBw3ciwOrcLnJcZ!%l@J|1*6iC_I)X7pX{K2 zeoss{(zjHn=J#Gc*pEk&!^E;*u*p|SvhtZMFc=<41X-(14YY^*4^ug>y z6~77i&PGp_4_sP@>bsnJmZ+X&EX_QQGw2HN>x)SfURl7$@-;r1L(Zy?!xu&G6@L!h z*XU!@sN+WJz^;v5E)prvBy7c2!W!o3;&VmXHJN-Zv`uqLtBQ_>4v@!wB>w{Woq-p{S>$O& zKNC*nDNpOiu`e%cTLT}jTji@BXeozx{Suwp{s(w{g)t}xjpwD41LsTm9vo{NB>tY_ zseFO!>s;UF8XWwJ!Jm|m*tAKy$$rKq0}Y|i?9CIOCgYW&ccBXyySr72t|2Yw$9@jb z%*v1PpKr71D@E|H`C0Qn%#v38JkN{)kIXs!5c@Rp0Gx|?*kNBT;2ED!PHbI$Cm#(L z9+RW}>?LcCJ`-768C93=kSoD6pl#-DsO_61_Zm-W9Sq$Q8NMyYyLhde{eSoqYAq-W zF1`rtgm1r-e*ts+r|^j)K2Kh}K)y`yiTwS}bM_<5Q?Ms@GRc2cHsDj5F<+%`*w|K2g77Tq7>|b*BDMf_2It zGCbQZ|ACoV%S?Qsu<8B3@`X}7m!ZB>W^R?p`K+%wMa(k<^L4=SWZ^h`LSuD>#)`S) zNsLuWSCRwgX{<<>EMR9aKCXy%mf4}#9P5&+LdGlWR zBwIv}hUZW>vAFly#CreB;NWCphnsKToaX`WnQ&;Hq2IHHdc^mJroiJ=$H@)lIn*nj zBlxDcTmhHo0S9yk0|!?yKtDyt90G$4Q5*f84Xz)8!@zphz;u2gwwFhUh)d?J&s*NIgibH!jEOzAMSRu!J?O;S+1bjRsTEqY ziMP)>^<>e;Vhdr^8sdjGycw29FcoBRRN12s^F>R8M+Ho2W`LK%)+~+voWDhto-}qeKO@4is^AZ`O zHMr^?Q!cn))SMwrSDE)xruwXTjP_;;rh+Z=lG+Q5vBm-)ojhZk6^ytyv}Z*1&!R0^ zH?aLGZA5m%x{zxf*H5{g<=VX{o?E=Yv&KsD zJOg|cCnoikHhL!lKx3u8e!ybL5l1V4)gF*6}DCFY*BnSVo+i$HFzmG zoc3M)N_7?S3!`&UKlE067~NTWE*|={y# zV_#?O7na>pa2yNHXdQmEE8OX$Ev(J6=c0{yXv%k{p}$Kf)mXn-E~on~((zCAFX36% z7yiY%>H}XP=BMxz-92rS<7|jDpZqa>u!w;sT?*dbnAyiz$L-!aiFCz&`M&x|n)2v> z2k-AU-^K6lyD4tpfyN?h_`ZbB((?dli}+cF_GBwTZ7w#bvEXBeeF#2U(=xL9qu_~$ z9Zc<%PAxo={w!OG>@DJ9*a*Q1*`Rj8v#@h9widnPX|uWMALCLMfdaW^Yl^wCG-BH_Ye;-H1JX0518_yb>Nk! z?isS5gPZ?AIl3>QjEghyhW{ep?MXh(fzKmfX(WA5e5}B+qV_7C%X|M#@8!R6Chxuf zqTFRkxgF#?jePP4lgxQ@JHM3VdyVltiF}$Hzg50ZC;9e}Z#?;SIY+j02k(#Nz1F*g z=jbNI#ie*2BOdad8wOt$U%kbO$6VuiD`h;K_(%*FuYrFk#$`YGru&>_1zo-k_!oh_ zU}-Z}+G~20(V@kgS$Ewvr+)ChI}RvzlIFS1@5Ffc2>AGg0p@bt`?#;*{juQXJ=~Ai zo%ic5WB)Yw@<$d~3wi%;-Y@2UDtE<|{37&rHFxj{o*gtkAiYrS;Q5^7Im`3R=#ZE2re@@mc@e{Rz^Yz}K! zyMMc})k`KJSK&+hfWa+M!h4eWgGIa5fBYj3^&gpH`d@le8`Ay@);FvFv z2QD6Qxb3omr2RGYMBC$-Da?&&N7`=T!y(%N@Q@7l9b}tFOjL0DEbMstUgx$Q&$(MU z_m(I}3?AW(6^Ji|;5&N@k#QhG)9i8Qd`jU2bN?>I3(>i4dFNxHnFmo8`omVc#9nyt zNcr-}akCCX+I;$={4-bs+MDR-&|OjQrtt2$sY>*kBW4Hq8l{!8QPC^ z`$tY8@6>hsshhb+H@L9zaq-8hkHH$BmUFQW`R1{>($lI zJAG3m|FgV*FZZKJW1fcJD(5h}af|@blVHc358T|jfwMk(jh@Om3i2mOVF%5^lb)py zWh}CGoyt2NeEG2O02*e_LVviEt~ry5<$X#HX@q?v()ZK#p!o(zoZok6+xL)>{0DIQ>LsJHA8N^pZXA@?l z81J1^GFx_j)9kB@+oAX%%KHNl&b4?k6~=b`fZ{cpfkx zBz9=L|BJaH`kwe|!P+jJw>ZfkbEvJra}?(vnf=%na$j`&k2ga9)u3@E@RrY_dHWgv!5R5_ehR)h zqx1FbgkJV`kBP={pE#wrrZ#E+m-f^MF84SwTz;)JbU%)Fo7l08-aVYUSHQ1wRl%t* z(mYuG(cT;N=f&i^d=>k)U`qdcXt(Chf4m+Y#(c+EQ*RqEPIc0U;IrGf9_4z1EB`fO z6}}%^5znRV?63Sau{5~;@uQ2ZQ@BqpGbg)jk(J76*`+0`kD~mcHfJkDR+@L6|4>=*N3}PV`@hgy z8oV0)Y@76e^^|vp74J*Fp6~MI!|iyUG;r3~Y2+`C{4{-%PXoHaAz80Da6{{ptd~EF zbVd5SRrXbnK5XVY$vDnS!mk?Mitd0dR%IT-JIU57z^7}u{z4;l#+vy5OU(DQmk~qf z$}InPCI9pMm(36T)TCp3T1LL5@1%Ws-ZTF*@9(#^oXY#DinV-C@~)NVAbHk0;t2k) zPyQn}S1N`!b`SGCI;;79IPb1c-nH?(Bzcy6QCx?`$^V5({*k#e0=IhO`#SEF@`9lcsZSE2MXj zHk|iLS6d!entz$0jW46Gi54ukz8vZ`|t|KXT0pIGo#eDx$zE#@j zB<;c^twh>mN!r*X?ffKdI%z*j(%dBN+$7B)pG?Y3 zVLdJ>vx9H1PSXA+DYq+0(|6@0tt&}uPtx|0_TeOLOp?}?q&-F2{3I(eEDXQ_8R(qds1eK6AvV1 z%8!iw$)2hqg4rz6{+OhtxU@A%n?l+_ z(o#GUT)#$|$`edqA?;ppM&+jTd3*Bh4Dvwirme>$?dc&+-@SotjD=Fuo)n*MPQKeg z+U_JR#i!*-+HXjEDoIQ6=_^UvdeU|#X(>Kkm!v&R+K)-oSfu#$LDDo90ck%>(o(#b znWV8-DY`#NOUHgjl7J(lcb@)L<^EKQ=Izqx)?6<4ZAQ& z^OO2sOVSkY&LwSD@?K-Sn>5Az(D+`+T=os>eII#JJK9oogL}E2 z;rbKTxaK1316-fux|8cCT)*Wy=2c<_a$Uu>n(GH#FLSm0W|8$Su8X*C;QA)l(_F7} zz5QPoS?6$ll4~Q^kGX!$HR896toLwT&b6HDJ6z9m{gvzZ-{FhP^*OFPxqia+Tdrdc zQa{&KT&uZ$!1Xd$%kQb5>msfjxW38tG}r4~Z~s5k&-F>Jja)zG`Zd>4)mXoAQk#*F z+(ZwO|IsGk)y1>)X6ZQ_`7b{*{g*ECP5vLlf9V-|_jRS?^Z8-)=wqsvF>k%Bwr$*H z%-e2ezA1bBmWYoJ#UXe-ssE53R%U(>U=xup!#GI~d)~y>WBo|;vx@4$w~%sn@qQoo zr@3n#TJs`$eqdGAWn7XT;ChjiBOv&;z;+tpta*MKujLT@E0j@U ztjn?gna*bxjc9(fgf?rAu6c4gUy`ruUnz_ACPPzNXOQ2;&^&^7L2xCH_#AVRX8OJ0 z*-0An45MdUMjf~Ed~Z$di`Nu1e?j5vQarvR{X{Npu$D>^a|nDyg!=4TFP5RWz7>QSHHTF)%5+9MrgiF9Ch5wt^oQC>>44p3v?`+Op z^}$)~0i=xGiVyx}twFJ7l*3-dd3yBWnP{Oqle3mGoE4!s?$*l849*KeF4`{kbe>0z z7k*|~FE)FV*to=_4vZCJJ4#a zI#8tk`>{>Uraa9*EjQSm83>-ql!IqjpW6E%Wfi^uO&q!lj1T27|6}3w(wut6iTx*X z!2ERT)w%DY+g!Cb%rYKodxtkS676hG(p#qX;*UT~EB7X7gY)2-A8Svq=EtmCZqr#q znoFx}@gTb#WTzQliMTxV^QIwXsf=`AuV}pY)V`W*Nts!F(9e=aKYeHIw<)+~rVp-#rA_7m(Zta&uMDbHdLq;U9J%EBI9 zx&PkbxTUfpQCd@LEq zxur4DE%|&%+)>uKFKpzKSc+yZJ!9INwal6KbAciBU})9s=cIhma}j!;kjO~w(NR9( zglIa=Cz@^-4`3a z6VXS=zky5mK7o2#N*9Jt%PvFSag?pGz%FX`RHkjvzS33?I;m>!dW^e@X{J5QZ_Z1$TV<8)0N)y0)Z`z);yl;_*acOD~O*NPn!1AcIw6Ez9+hpXXHZ00+(e&eXn4{ zd&vsszIE-_lKo9*MR6w7HsL?KUHcy!o`EB_4g5JJCpzeZ?1GLHuODTSbn*VP&sk*6 zdM|5-{z+oh-ZrpVg^2QjECd@(}6v$R#X0zPqD_Y_Dc6n z{buQZ?W_1ysSK-hl|x}>EpUzA0m}tGeFLX+0d{`I%!1E;GRZGGwWw1vb(#FK$b-FI zJ^{tCz;S}?c`jpOF*evHerc%jAq<{kW(pGlQ>zS@Fan#Fr!l2d;`{A=E6znc2=1mBEh&i8~nX6G=kw`%(r z?97v1m_WbikJbdV2BUNOT^TB#h6`S?3>^Q z{KCX7k?g~tKt92bMfh3nl@7zWHcWZ+U1hFn-;#freqgsF6qVH+g?@7VDO>Ww$qF$X z&J_&Zk;L;t7gQU7XBj!6{hDLh3$3-!_o+>k4NgDlO4qWw!3VXe+sK5))|jX_S!YyR zM-!t==Vb5<4d8DI{A9~Dbudoae8;;YYXud zbKW!iwI^L`Nvb!`xY$;|*0#1;rG=r+&B&F5_T8O{XF(-~kma~A^FI?|S-eu!6 zgzAdhHjBLU^3|s-)x;~y7W;zQ2AFEYI7rL~+X4S=E> zuw*gmp%vql_l)Uz2A?`B-nFoz0tn zy~w)etc8}=haUJrJntB)^JaiqmbDnW!a7lzJ!+4EA-IVp!xpg7wu_Z+j!V>%8!&0khuKwC$T%uj#1^e~XMaJa3y_`JnbfHnq1` zx?s*je`P&X`!DtzKP>5>>vtj(A0uriy7o@X>)+YR`i%AhXgyW93LX~i$~krEPK^2X zVbC%9(WCg|J}Df4xi<4tZ`&`~>iFxT3S%NTiq35M$M=*YUIt$zP4X9Bw~f9xChgK$ zoYK=aL~{jy`2KM6Nd{%e>oTSv;BNMkBEwnN$Wvza&-esMZl6UOL(0CH4fIiaw6{cW z;{PSXK@%amltXG?)o6x51rmgqf@q~%DhA+g?A^PaS zb&>QGeIp$IpYl%{k{`ZPi@#B<9OMV}46P%R)ZzYr_-4Y8Z%lh#+R6HIhI+Ji^%U*R z(QobNN&goFR~KCc*ro4|w$RIV-CWmy8-6CbZ}V1|bhZ6OzDa#(;7^TWnX#-W-#W8j z+Ja_U8JGK2Ht)1B=QM0+RkjAv))&-gKc34Moc?+PzZc=M<|}5uiq&QIhKOzq&%5@H1E<2<#=-~n z{g?P&wgBmdqI>w>UeSnjKebQo8o@Y;rX1RJ*7?kZ*>eTlh(-F<`q4a}^)mYtT*`<4 ziC5&D+szvL?~xz*q~5E6Rk}Y?WoEk2)l;1GV|cGUFXr3OQ$cXeSnUnTlLZ;^Kz-=<@!b7$@)&vp79{vy2A z9Pt`Qdj)#x&l))&8huu0xldEMj%=hsZ5MPfn|#DLs~^P2V#L&dJqE-)ByAey>Ff@V zyW&kx;jZ|QqFwohuz$q#Asq|#W8NFsAi19S!9r_2*AlMlxh6TPLvtwB_}QnDqTYMjyOXe-K7IJlS&ElF(e}p%Mj+p1pNd8;MC4H~{D!na9 zS8OEu(WNof`&^PQt#3AM-)rS0&~a`@K~J@}CH)CWgYnQK)W z_6PmC{7=Veo8mJWcym!49Btsc63LF)pEBAI<#4cD6TcKU*)j)LmW8m~00B7NGlW*WO0jj&GN< zO#3&w3Vb&ryb^of(y-0NUx^sas7Gf$l46kik*Ol9P0hbe>e zL%Yq~g!8XRYYTfL&07oH+g#eiB^=iIqdIr9Kzp?hLG3mA5N)=d)%$7h=u8`DVp!JX zyGBCK*uZptXP*tO0-tfbD=?RpJa4mBNA2T!Yi;4GD90J@9_8OP;r`lPc3=ZH=5O;G z<4y_IOt<>hG6&t%!T-yw-nEpysat993D$g)G?>n&3y+@Pxa+iF&FA?K57;ySj%t24 z?r(!NH&{X6^}H9Ku-%?|@3_9OP+e=rh_ZkKc4Xo-F|WQ$ZIljf!zV_Lr)}VX+9o}s zP)){FZ36~b>E?_P>no?XS-^$YNl-c)~CYFmhm zp87Goa|W;%Yfd;&CH}~V8_@3LgQsHmAE$Z3O<`MA=fr|vX6$vAY5bpYEan)WLdZMX zQ*dab`&dJ9v~$>23&e$QBaZxs=u3uJddydw_X6*Ghrs)U{|4SCyb0d-4uN+!?GwCD z7y|EEyfg5w^@VNt=8d90_D9BWb3YEvO84|Jv0G2JRo6t=*Cc1QWxb_gAzWI|xx_~z zE(!DCM!^w|fOFNQ(P_lBk>8)@yYj8JOFi{n`{1*c)#x6#Fjn2Q%gh+DA6K+#sV=il zvUix<5AELsJ@zyTVLx-Fe(?K7@cBmS@7>>P^}f

5bm5Ix2cc>{;%4+J(J?cIlh7 z;IH(#-iUoFP2oFzF!)}=UUeAX?|c)!_ZxgKRH@Tff4~#JC&v5SP`od_3GYkbeNTe- zq#ZF1r6chEDPw0U9f9|cG}NY^df&L!hwvW7psV1luDdq)&6wCO^cb?X;`Q-=>Hm!H zA^0BlgX?i$3jXS7?s)O33!x=^AE71DQO*HYlszgd9j#QuuD=ok26((P>txUyN_`p4 zqr_W!L~H1nO2>!2n4>SYOIc;sAx8Fvlv8ViZjlq`$#k*?AtF{rT!H-PoWK8+=6!_{EKm~@Sf}Il-cHQru~;EI0(%c{Ck8p z^cvU*|IncsyQR@awV^8gYe9`Y@m-pCXRTuz1-Ez9bNtWK)+{o+;GJ358DQRHoR#5i z&RgDgbfr~!^||1PZs*lFE2-$<18({+`T$PQ!AjvCG6UT%fsLsnhD}Q;sQmyw@**~a zLYeacBrhx58?6bhe+-&>;x6p-6R-n#>>nY9tb;v4dvgch*FWlLuW!`g`PZ>fWw!zp+xJ6k=cUU04)m1Tbx^y}o@WwfiePP^)Z@7vxu zTD%pTh)sK?lRcHRZzAp62OqcGMd1MlJx}y3{!r=zZWl4<5PzX<;4o!I=mf>1v1cG} z*0HZ|1H5#Tczm08uCcA;E&NxV<=_x&3T~#3ZU+7@N9W>uE?~c@U@fl?vKB4B=mKX@ zcxH^|qbKt0E?p+RH;wz;D(T>*WNa)O4)Yz4Z_!!62WZU!PhDhC*vEdbKIZHm;*}pkj#+mNOddeVbZURuIvXj_Fr$)IwNBRZSfs*pR3UAhg(b0vxt4= z2kRtPS}WDhw2P9+KoJGVPC69Xrc+i{39C+LiUYYZbfe&Tt=sxg;mS`(5 z&0!-ku=1`p<$?Emg-5NH_F?ug4n6Q&Y(DzVyOFV37H#Icg0-wJ-OOVAbRT>>HnAeM zd-UnSw{tdw^JwEi=mUMfruX+JGS}D)fE~J%nQN@Kt*}rgUO;7I^fzX{fL=vExE?&g z=%W`lu!jPRPGrgB;P=_Ug7aqFc&$fmS6oy6uao=&&qn6lne_=gWA9qo&Rz3oMLA>~cu~()`|>>Ju@ht{UuDh?wpItef#zH_{%gEfb38SmraF!+GsBLTkc@R6600iuh;IB=7} zf#1^iVT^-ptdPexohw88h=ny^@=G^;iafT}(YTpTd(q6JF!7KCvcY6a{Y*FoL z@p{9v$ise?Q1d;tNqcd!q|Kr1Htec7>m26%oW(&I#AD_;*4ZbRF^0CPtg(ebjWOTU z>ITeNn2UOA_c`bbI`<$~W&aB6A#FSh7ep5-3mH`(O&-N|mP}JV#doGpz-w*fk~TU? zE3hu17~QM^$Uhr6tlbCRaEa%vHnb+$Em>-jM>Z|33B42inB)*k7+$FuZ#Hn2987f> z!6T+G!M0!fFq>^bAM=7sYr_-R=E8HJ`2pH2`ADA_6Tw)q{@VCH{f`dXYzcbJx9?72 z$G0);l5Z2(jW@8n+`#TI+%AvdraIK`w}cyc1UK^hmvAHPt>7kpa3tKIH{dL|`Ltay z(>kpDENAfF27V@nSWv3ZGdPY-*Zm+oQFyNTDRGItt~|JB!wa%4L7(+5DUg4#LwPr&!ltrR;#vdhflHVHR|S;P+XZmQX?=BNG0 zFwN&u{)|jB`tZ`|RLVeSY3iFI_?Gon8k`c0Q+yNs2rpARy=2_z#Lm>=-P&33*q?9h z0ws30$_}vrd&qxI?{TtLkCmnyo|nkPG%x)tuGOAmuGKKZI zjCU4#=0%$OZJkD2ZLgpI3u?@HxAxOV?OnttXutGP{Gpoi>q>pOaxVS)H0#l%9Y?wP zUTeuY@A3UP_r}n!u&2*i7~0O6^=b6k_E#GFsO&&P`+Autgic4XfX*kA!@qJv;hF@;cRTrh!jON?W2OWiHCwi_O-B-V(JLStafw=JS;1!YNsoJIf?7Cv1)q{Nx{Di;m+Aq9Qe$`iSgj=jR(~ox^wpH5avM!(4o9`pP{X%SWuF@vOcv3mS8Lip<$h19Z^pkG|usZN^Y z*Lhzy<1^MJ&a9~m+$NvONo}0!llnF|IQ)$Vfx`~2G`@|-S3ZRr-#NfhV=Z43+2CZ~ zd{le?ebyx5D_LY}p0>h642;ofI8Ss%bUxonZYkD9hr7bi;%MC|%S*;V_@S{7>@&RA zU2rZbPeS_z`t&Wu`ffm>QzTkp|7ua`OC(s~J=#`<{IB>cf>epWu zEwrqw7FyMAY{v5!S~LFUW7Z>F(-thW#(rd>^~R+Oty_;PTTeZP&35}jD;J(*>PM#% zZ%2or58=89n`l!ykZih=N$`_m8~-&wg*Tk8b+0UXj`7{qyMuSEZ)xknPSjI3egnXU z{iW!JjQhbm_9+&!;vf$WGV<^r^f&yc6yL_gYh%3>{|=rR0~_DqCUZs2!LixJ_b%SK zJcE}eulBdm#-e;ne4e4(Vo!4CyQcQDY3{?iZ*;?-28~ZJd$Y;AC1Q=+;H&(Yr}LjR zvL^mi5%XqZWD|3dJAA12FD`xo{O2sTXn-<)1&;oSYxtkoXUa8~>&sjlxxUTyG*^Sm z&?@uvR36AaFCGs~)G`(B<@o$h?eDx(wtsL;F=KBx>j12k2SIHv{SiFiN!aL(-{Z*1 z;Q6`q=^Dpv_yg|~_?TMp+AGDfLCwf6I8u*Xg!ef(%-40qtyoLRV#{Za6G zY$J}lxpR^`CNCST{8VH=pzo(ZN8?!o)bse%m+6sdF9TEgWCZOKX^S1Mu6vYY_GL4N z&*0xFUz`*V*t1yM&AIZql9{h?ejqxt4-Z|itj?Jdbz%pHIsd9q_O(_&7?%U)?8y%Q zv=pD}3Vt*AbqEFkqDyQ4w55-BF)so}tP@GDsXg-VYH@=a{#BsKVP6i7LplaoAGilG z{55Y;O!kMY-PnJSvG7RS^NkO>>Kji#q_VvIZ&|r?+C0+HQ zgg%(t6>V%qHfO0y&*d9p=LUUktOa9}7-u_u@%Lrfr~;dY7NLPAu#W_{nT3mL!|K+uEsasQeaXjfVcsGkJ8TO8VT9Jj-rmGcMvg8Mil+4H*;Kt+}o#-%ZOu3tob} zI8?{D@Xkyo%!POCYt6=MjFRcng(N4CFSRqRfdiZ)QbSKMv_rXOPI?+LNxWb#vfuWW z$S%)VXsxlYJ;v?8Mm866{xasE-SlHw1Y9@e+^bk)=?N|P;)}=}=-1c=()&>S%9OFs z4Sy|Oz3{4k*hc7l16TtS*0aiMz27R9~(3z>DX`{~4 zSm(Imx{h(-YRVc~uk4y>xu(u(ah?6-V=NEVIW+A`($rUtr_Re!tW){T2v>&k5$L$l zhfL6TOE0kSH4@GtZvi>;Rbn`c?&Kpd3^^e=VsInTAsFx4M#aPiSK;N2b$X@@K89!D z6Jqd@n2-rRQWjga`#W>x{!Z|6wD{b=;m@HueyM(= zD%_QhAU`~v&)NZP>n^_`-5tL#A~tYCd1W7g2b*WvBPioQ_XQuAt9nLS&LN%1^1*T1 zelcYWcCEy9C?(H1o_mm)w|!#p(7Qp-pQzA=3UXBTlWRzqo%Tn69DH>I|JBy+tj*BimX{`p1`f$5=M*G5Nzo`6rR~Inpwu-8Cfb*obo_X#d}G-NE%wT+eg; zj_cq#aeP6m9MG=}rC1Q&t=`Cf_%PsX5r7s+h%)hiDTfwve>~Z)>F}GbQ-)Qj<6SF0_v@YFU z?bcc5*{N&yAJ2D+7t>;ewS&w5=|J%Qxc{QBOn}V$zo!4_HA(-qE^T;C5(CTz4&pPK z7un~aFU?_{0yv*n3Htu760H0CcN5>pMP~ADy_F3GyL{=&P&{D6csIP3^kL9}XdK<4 zx9I!5(kJ8}`3v?xX^t%ZukXk5?n&Mm`x9l#m-Qh2UOQjs+|0qF3EEEFcdjKj#yW8a z>7u=KZ^VyGc`>~_yE@q$L4Vk@vtK?auGcea(8|g`rKWRE(|%gz`Slj;V}|bq@wiK; z5>K-Iz5DFa3;Sp%`h)a<3#C666%R!+0v*xl+j%RfalWVeW8h^=S0E0nV&deiMWOuB zEcz734|Cc*U#nO7q zGNu1u*XBE#!Z(y-c`qIMCTGf-U)OuJl|$rX9gX-#Y2EVmi|gG5pJn}mv<&_#gI;_5 z4Rxq(**5qPm&wbxBZrz+HU1{;Ph0XG^&*=f3Rlben9(6M#_8PK;9v=vXU3_YwWD2>Nt_~da>)!E zKPKjfDu1$MqU4pv%)n3mcjn1X!CW=2NAvWw9_gQE4#juyoMtkwMfcGeZhdw2Rrxh{ z6)Z19o{8r!pA<+@^F72;P zU+MEmWQ94W!SZGQi_h&wUexjqer5)L1&ckT%~!nIdmR8$`2eZj!Ytjn+m zCGJ0Z278FA9oR$pmNgLa31(ye68qMr?GXQv{;In3l&O5%lk(Csq$8)_s}Gug523R4#>|Ngj1S=~-2Hok25`m8N-v(rn_o z+w5BuE*d;HbBa}U;h9ZaO*z%rE@gW!?T0@08@iz^=KgV6j2ZN{4p?uZkCge=`80pd zREdRa@_d?luc6+=K&P~yHluN7~#^WDx44v3I$N~7HPt5#kKqhv*?)!4qAvq?+A~;1HvrBWFXd0$HdG&$KHEaw z>c?L3cI<@o(a4G{ZQp9vL+P_0+X97q9`F<1XK0gP;lV?h_rfC&M%VF7|9A#Q)tiP8%?rzG$ zr^3K+6!U7G+kHMfV^l*r$7$8`GpAK&j^Zq|8gk)u$rA9s)8IYhm&&A6pH%zJ*}{~k z7-Ek@WIu4Ic` z!^N)TVav(zd_DFM;0_C6o?p4*0dV7ilbql|&Vl;=aOR^q@|=jhf%l`XBet=|rJypz zQ}m9rkcBhq+jW%XI$iZ1=D)y{{m+~SSvosIda=MW`RTr~;k2{AtzD%jU}w}iPRd7&44G2C7IE6g*qZoF@)LcK`lde_+30{r%KvERwhHZ>V6o?$wQ_wo)0qjqim#!c(7%f6!e(Q16#OrMJ3Lrr z^wz<#C&3rRp)$0S!bG@`QT=?UeDI_vQ`=Dodfnf0i9gAoT{IwncKNXb>-bCz>vq<@ zheuOi8#H@v7IBx(IO=NgC*eM0O1&2C_y}iurSb8C<#w#=rTzv3@P{(_d~{6kT=vZ0 z(6@=g=OD=bGjNyf1RI-4lYBW5`qwyte=A*{!QtZg{ctNEy3p}tyg#`*c`zRlJYo{yRN#$LquobtKr?P$e~=ar;%YuT7TcjRf)F{tjuzDPR0svHhNVqxEcE!_)dM6gMV3>b9dAq zp7EmsuRb1Td1v9fb3E?_lL_1lBh~t{GJ|3ogX3w?Bm55Ym5D=eJDFURpsoNDPQ z;&Z9|MQ=ogk%#;rX0MOd6WYqRM-NRL9$ix%9zA^O@aP`ycXI_?o4Ib~TF*7WwTf#6 zS3g$|*Y#Z2aV_DhaOJ!^_f24rvF0z?ajU|9ZxlG+SMT>Sk@UxVpzAz3qvdYww0-u0 zhPUT!i#dR^I&V44^Jf#^`5x_sX3w4A3~qNx|8vmirB`b19-OUxqVuG8O+7jY8k;+5 zGkdU$Q`eYp7~3uz8;s^anRS~@%t ze~-=kvfli#&n2FOZGBMtN;OBO?$gz;;z;#rWR!L1hfDZ=G=yP^tZwTHNcW8eM*7weoS=HyMPyZmw_Ai+?jo0eqOJ!{aaSKUZI^6D>$2?EyN`0^?~Uwk+)bO*cdN9T{Ll?`S&nSUtD^y6AfHst57*O&Dd6R1 z%DtX%rucKBT(C4cu{tL@y-JMuiDQVVIL54(ST5_!#J^d^xMi*01M5l40V|c)vvUl4 z622O(ig*WamVd>1;J=yj@v#pF=u;bbvI>|Iza|tsTb!H1fHJOEJMlx6tzU4v4V|V! znfFs>8{?1xwkHzT>iu3gp0-ZJM`Ch?dLE(-i~Tk5O!QJ~@*r|l?J2Xy2MpF#sEhoj z?a0pNL$oDVy*+xEZ&hYxBI73ib=oUj%DS8PXT3Z3m-tT{7_%?zdcF~z1*Wbm!uC2a zp>3zbn^vER&-$Zkv(6M9IMC{ajXSrG=YQXU>-cU8dI+};qK?(~3fZ5KU| zGTTpLxuP;oEJdbo9!87I}P z|90i7a6RR$$`6m$qGJVoyMk|p@1oUUCwvijub@3S=2ZRU3+VSf6SXEfuQr~2q)Yfl z_zDc#8IvsiZqLFOb5_W5m25m=Bb76TpQrQc5;Rdp2dHp&P@yN4g%1n$$gg9pXDg^c8zyi4p;Y!Nf? zfAP@2)JDM}O+SS+{u>#Y%2%_#gjNggn$Mcg8zlXB52bnvU@sluof|xa|*IV8y_HYhFTHn5jcIT)w ztuOU;N^wp08sWp~s*61X(!WmQS#hcg8b9zg9`~S~^iI~}I&S$MntOY;BwV3?{rte9h)u1!N{u68IGI%VM5yY+%r|Rk^%wS411w`B@jx99sL) zwMViISdTU3lU7|WJ6)Iy*}s5n*Zu`)sGW8YpMW`@&zZrcjgi)l)t?M7mu_9~m-BwP zp%3AOV4vcLbSRzmAvg%<**{T~{w2E87;5}nbg;457d1xs%oeSH_1T~Yo#P^G9#=gu z7M}?GiNz})9P4iQK5Nw9FL>wFSv%L940~QsyNouOdfD@!{3>5KeQ)Ir%s(Zg~BeOd`efpGSHcw{4d<4 z#UF+kd+6DqU8PeQ(ab4XlDPt(D)^S+zi6W!dhF~Q^1IxjlF1MGFEbt+Gq+NQz~`ar zF5RBySe@6<_d>quKl{CVQ?HS4=dZvcEnQiBE-0CK`T9s7xLcL4Z{=P1odjJw=y*80 z*8E=TaT9Bx_^|ed@K2D=&y40Jn{)RK|5E9z{S{VI3R ztIJ#szPSrDN4z`WB}ixZuFVGD=tCGAgI-l3_|_c__#5%!?$wNA-7BK``_w##7@8aiOX4seRH|FMx;@Mq{u?jyIuh7^P9qV5$@0GN&$$A4eH0_L|SZckk zM;kQN!FO99V+(%R(YH3P?-ccJgnvZS*L#u^sO!uK^^LgH7hQUaI-aa=>h$_zANH#H z-tj-K?<=y&psp~FVsdyLb|`Coji(CkH9i>cR-e?uyeb|{eYNgwZp_^7r*m7G2W4NX zyGpzU&P1_R4dyP^MhVFhTEDltTao*Sue$4q=-lO7G(ClXoy50gxfcb!dm@{ksy-2Y zCGso4jrwD&AM}IfRqm>xuHq9)#~hN-KgCJ+Y3UL=e3W)Ik~U7CXgoA><}jTbvULdU zxSQLkyW*nhmG=Be#c%3C=uvhx!bvN9NcJr7(@ za4PisD%`=t7qRy3MxH)gtvQUoqu!FWGV!`5m~ldUSN6}E+oJdk_yxY_?%CXHvbXmd zkI?n?UbBJl454iocB%Z^M2Mukat63hlHP%zW@gm+-19IJb5+K|^7nyV18nI(b%&SE z;2H+Xs}F`q=&$zQgYVw~e_i@K$7r8I)1D)AE7NN8q){4xE!rx2Nx% zfowm^_>*V2d5z}}x-sx2{hQT&(x2b2G9%lz^qPHl_L|&X_=5Okueon~ui5o!?2mWS zmtXBQ=4;p;6S|PqoxWRa_eCBNL^yP3+eO~q3mW`YQ=-&mq0VjU&ry4zkr;X$tpneF_WaTz z);}@uAiV3T{Wa&jH8w4Cv`zb#InpBs>s+Oi4rc>0so;s81#jY|f1c*p3pz)eFCX8B z@3rxigZ{Dge4P!=lyY<5=ubQwTEZ`64LZjIq&d*VKfYHLxRZnDWwLuGzw*WlltVrR zQ{enF<3l=J>7zFEaEC|=J1X+4FPHo@<_`l;ur~2j85?-Y2W18J8-T6x(mOZi&r_N# z|9;crFP_`t=O(oHOQy8=T7NFPpoRFPe>=9DNyFU1SZ05yxf6O4Z*=qYzstH#a|!*@ z#k$iJ7<+x}Ps0nuC#nmpv11fJTk9L>t)sBccj;@Y2+V%;SG0;EdHZ-pZ=$~>#kJz`5bk1O3hx(|UDkH=9tJ*nys-3m8Q@p6w z<*rl4OoTCmJ)j*k#p_z5#Ayk0{-;a)xy9ARqq2_`XIuFzy<=6M5rKUpBHVY!Z@VO?>hUWR0|V75r(o zG1t4Xc-@Sc#p{Cd1>`dyftSn(=tbprP$%J0=YBhY2Mus15KqZk@I4d41Fq$Hs)x#= z-#F(XnT#`@ln*ZhZ_Crweaqe0N9ruUR2`f?+XB45R5Lk!(lLAHg|w~I0* zx5a$wLHnbo*VEWZ7J9w$Ua!~n2znG~E(ZRgKRaiye`T~;>r2f$syn>H>QTm1kFI!y ze(jy+0sX=YEdNeHzvMZ|zoFe=E(yk%=;-YsU5*RslKr)SF5d*L!pqNszfR{}XXRPL zZTuW_@RU@P_ywYw?WfaecV|GShZrMv{n#}iJraD9d06s2_^PbcDtu!s?TKfMrN1{& zKg$mo591m0Z#*3G0?{yVCuP7B?~?2OQ(Oqw6Iyhuj&(SCZl1zKeFoDK8P{+se!Q7hQjWG`la_$(ew)zIaH5M{1rD?P(37u|F2? zKY};Jse|e%{B9s^ineS0aW?P5wemXVR?bEuGtc0=AXzJGCT{FNj@eOYnusHAJ zn{hYN$ryaqxC6e%g~q-ecknJdSBRgDog@6o{zo}`hyU23p?~Bz`@{^+kuf%$sRN#P zc8|+?!F9ZWnb2ART@3b36X09mW24&Wq(4zoA0+b2xqmvCJH|gqe^7^aP`8Ps6)x-g z^3m!HcL`^DCPw@64a{vLb`E3w+4fpk%oU6^jWP9|#;3|?Nc0Eo<(u_{otHEZ-T+QH z$LWc-bdE%Oj=!P}9r({tz8H1xK`u{EWi66oFCpLS&FY3P(ypi*@j9=p^Q&Ff&>7as z@E7`eV@mafA24S_%GWRlFN-pNG@m{$@9#J@e+d7!uS2}sxnttmBbqxjpH$`#*2&NZ z`+>+~$@HB~QImJZ&m2tQR}nu`;2e7^#~^bcPiY-4{Sv(JS5qX%od>;kA*(YMK70Nk z>#A#t9W(0uztWh1CL5tm16^uNG*S=r{&pWy^S#br#rS{VVeY=b|G)u!100L7cL4oK zW)bbD8NX9frj%Ac+`NYKPLkJdLzZ37K0PuY?^-ASUUvEDjL^q1FWp$)jsIrN5pmwn z1y5=APE?;?kZuR%MA)aXb1eOK?9gOCOC8cP(3Ml>*CytRH)Dr#9KE;dF$KHq4rH=w zX8>Abe;B%H=UaPf8mCW(WwTdd%kCUgHhtIJ5tjWu(z#>GuGHy%AM-Nfv$Di zW-|uUpFFt+f>=j-^Q?2e&}-Z;_L@9l>%F{xiFMGId(FLHVJ&hWKJp0nqJL|no~^!Q znq|ln*9^YLG22`Fkh5r;ZFVGq^&r0@FT z541ZDT^GO?@yNTg)drq3qUqJ?R*&&S`&^^;taekhr-gb&rm_bkz5rhnZdV{Mvsd}D&z-}**AD&-5jVkgO0fcaFX-AL{I7{m z_UC+-^O2b?{)xTlTd3a(YzF!XTM1txOlo<**|P>617TIe^=41<{pJPi01olKm-l6j z*P8;*0%@Nl93wQo%$^;%E+C#s+Gp)gS*s<5gD-9@>ioiZ z*|R~<4)_o*CV?-Px?(>O;-VkD+5W>pdsF2l=_$UUJ<=gwLVK>Hz06sq_~v` z1%3tJm2!@EFn3X|#=c}y?2s>srFNiejd>^bPWF$(OC&?S+<|U`GT@`=Ebp{^sxv5HFquk)U*c37hfhn_EU!i631rgE@WAahEj$CeT4)CToh}@b?Ym)4P#J9n(cc=+%tlX~S?(F| z8hcgx2W|SRDJR3(Bgt-}OZlTy8$@4`g4*!pVXZ$R>`f+VpL9Carn8u2k?!~$TUNb2({`$?fR=4poJ-K%MGI(0%GMWORM0_6 z{UKX@$~WdZZ%&zV-F=4)a>udZ2hRK_PYEg8c)1ZeQlBD2sDG05ZHoF`!nmx4R@@7x_^BDt8F{sitThV;k;%5umcc*1 zGP<#v`-kn?5#F4qpK3^}@{`m(0)A@1z1nM#J*20vHEWL`qYxkPX7RX=6zdSui`Jy~ zvwG_M9e(Q!$SUoB6X^N zZ28bd&_CCdyDQ~uUlZB5)u(^xqe}UeK2Z7lDF46f1L3&R2V-#^8-wd4xc(C|kZ=u+ zHS1fxb<`(+ApVq09N>H2MX!Nx+8}&ey^6P%Gnm(Tn)fR*aZ)%pV`!583EI4@TwQ51 zHp|AN&CsLt&XqR*XEgasjqx!w`5g6%GZsYqu}sd>e55f^q0fu^n8WFVB=~QG*Gm_p zwBxC(_I%piJ7+uT>(cQ084>robo&hSFRA5jdsE$v1(ekWe~`YH{q8`QGb7*^Cv`c@ zOVY8^r^ub0v!5*)?)Av{;u+!>`k!Wg zNx~<@Ba-k6$#dcr6}Xzaq*tQsP^YsD-X^3|0Ccap*~R`i62+m z)T;g~1TuC-Kb#n|_Ltru*dw~tukdx{7d|v^h)=#scfgn(n_u-4-lV%YJ->MFe^>7e}cHV88JVQEhjj>>l2t6o$XKhrV z*9hgQFSU;B<6OMX{AwM}dT%Y~lLxG<#(LZte(M19{{VWNwMr`-RQgM}(DS`%hzV^UVV(ebPpX~#n+fhGDzazYz)UVP<(&Ytx9jqTKWvZVmYf0JiRrI&Qm-?{s z4<2yxpW^giebh>wrQfydxv;+s^>~$zDeR{|qOa|yz1Uz`y$& zSo?SQ-vFPRnQy_b$6l*n*Cbw~Ju}&YucJO&d;d{u5YMPmKLjrM}4O?602M zmo){+C)$r4EJbTr$_Jnlr`XL9)Brp*`&LPoT?#9>Kre2RHb9(!NkP^n(q!^^Ifk z363KLuPi(ZkCna_42SfN$3Ji<+NkX38|*>s`9AtM#kYiYMbpJS-!p=qXh86eu(z=@y%iE{S+4VSh%s&skR|cY;=Kn4=`1C;DA4DaU=cK*PH6- z{1?)&N27LP^AgDgI9Hpo$=h%X@OZcL{Xc~7RVnV&3zwqer*$&3^h( zH==c`L0^K8C-F0E1?m_RvE98UNoXXr5ai1PnSVrn?_xZ2Jek8rmhm(^m+<@qa7C-~ zv*NNxxi9xmD@;qHdFj18 zKS;QRFig0cP(%FJc^dNEK-zu0t8MB-_1}3J?c*~(`rrws=*YW7?6ls@`_OE}AuRZ>~5T^Yo z-^Wt;3*=icmG%hrx{9>u?5*9~x&@3e{0pv=u0{Jn?E4bxvHOV=n(z^4$QNyK2jje_ zTDUtx^Q_5i^MA|TnD|`sTx@GhdYfcUumbts>(`@v3HlvbtCh3DuvHF?5-zy!~VzTT!9VEu)U8} ze#vBScSdTy&zc2+t@FgFcIBcVOdA}99ZZX_*O}=x| zobjVyQ`F^sVc+$Qse{hTsvdtsy0f^yd`fO9YXf9IZ>c{uyVRe?-MSxV?wf9w`mOF# z^mW`%kQ!ni5PEfo{8SF#$=;AZDJy&VA-|=-JLUCJp8Nu|rSs*@(RNS$kn-@k#2Ig` zIivJpqt1In*HPva`34Al2FsTzcQ}N;mut`y>At?*>7Nw$q@RFBunS~P+>?H&J~0b= zA)PJbigxS(b%zT2Ncc=6GFcEm9i8AcMb~^{V$AG_CmAm(qj@pQoQrNLDEoAq$npn& zc~z9#`2M<#IgoOB01ROg@hW{ofQ zqjLC>mFz~kt<0G&@AA*n&T|vbR-PMpw(&HqO>28ckJf?Do1o)4?)=h?Ddwv~z=CJd zwnPUqYoQhgz#&I@DYJ((doG7xlefvwKgkiG7FJjy&n^fVXV}f5$3g1p4d9G7h1;Ybal` zSIi9JBRhz*@;+mC)pBsp9)xr~(F>i@BK!rUGSGT7xR3mw($5uR*j36d&ieRf4DD7N zbEL+S;KdmCtSN!r4}Eg>4PS$9dK23WisHbs|;w(-L zGO6ngly>JHBCpmJIzP6s=(_S>O?|!LxYn=69gZhG{7k$3{!ihTcD+KmlG)``PqK&B zT2<6dXKJLI(!Jd^JY^p&ouKd`dgN^MNUhm=B*MI(WX}5bdq$5gpQANTp7FX@^8o4Y z@X?9eaY9*f#%F}G;$K1jX@vHG!?_E|w6bZC%(T{?Ba&~k8=wWv9g@NHU(fx>QYRRg z-wgTLKJ{04PCk;s&H#QUo7*J@|CRZmpRT8_ooVQ`FJJCq&)b1kztJ%tnTYf${9ty^ zFKz(NyuLa=%l|h){Xv$# zm0vyplC(=c0aSjLv8yv^qF>cR{5@;;#l^n@-?<(1=V*EKsQk+=;a@vr{f~UBe+_h` z{;iB*^>Ozrk9E&uyv}31s;?g)bcJKIGQW3ZbXGt#yQrL|OxXwj8@y0FP3LL~lvSb( z5D1;iC%@=?hSP^W&VqL#JS}x^rQx{ipRr<)4kG-d~#w-^~ueGx_Jj ze<@46I}OeMkhYHya^NEeK6(klkz|Sr?VEhyQ@5i}G=G=>d*oip`qD?*yQlg7=y}u^ z`vi@-6V6V2(&vlY)n>|qO^#^nnhbV~i~-FB&oCyOEV@~2eLI;8Iv5kGuk8EV^iDaS zrQR{K9y-YuIb)O1*iWT4mbShr=!aBxeVjSXfhH20!ZJTjnG01O_O~wm{%PhU&Z(A6 zE?ep$-30FaQQt_`T}GY{k$w{C;+hMnzveN~SU3MZz`rW$Pdi8cMBgZn`b6{uuWD{3 z&GInKwft9Gb3A8}er_G`;04QnLc5u}WXl;PzuJ&wti=qv8{mA;z{`wB8sr@MXis4; zzTWmS9wqnOR)y zj?!xgp3X3zbx8noHUFqX6uYQI>|LWrv80f#L9^Ck3F^6+arAofrgV0JaUi-)(8dmA zUdjAQqq90LX~vGRy3rLzG;{{fnS^8c`0`0uz;JT;VmI}Z9135t{quJh zP*?g;{TFwwexj%{TA{(#T%G?IFzp#SlP}IAt;S`gjEe6R;UZO;#|xIOi!GEP-zgFL zxV2EHwQizC-=w8p4G!xx%?*>(rZoG$l`PV4-cFG-F=GgWBC^Tq!;~4!C^Y%uq6R?vw8pG~+v@>euw$YjbV<^zWERLPh z6)k4{ZBoYSisZkuvL;jC^wHi7WuTXZZ<>v1-p`gCZO_7*ku2Y{!tWgKUE#YOJMghK z#*)@`TKkI@q!*~b-v|7bG%_@II!&TJN&ewK%8n~*H$lEhW9p`MZpb22vksliIUL#j zX#K5w9X|99oek*6P7OaN+(r6KYKZwMU;Ys9tEW!Je|@kISIs&0DE%FQCZ!`+-)r1k z-pf1mF`_uptp3Z!uJRwgj$F3Z*SVF-x!M!h)%>9Jie1mDe#qQq)i0h2XjtP~`j{AF z*ksqrUrMuRS3LgoG4?XFs&(u4YXkbm56@BYN6BMOs>zOxdhXsmuDSuE?*-t}-p}*C z6TO1Q-Y)XW$9ar1#ya16D=_4v@Xod%D6G$_AkS_pPW-N`SNsd+Y>=9npo%e zX6pR!{u^r^H(TnSR_9+FHHmd|=a>Ft3VeJPzTBJ9XJi@U)Z}arxBgUG-z=7>!34yx@WWpWtyLm?uk7C z(J*?~atvOCV4cv}ic}juibGnAJ0GLH=*oxd{2cwk+_F))T?JqI6nZe>_Hi7VWg@hl z`pDmi?BMTsc)BNF-m3HdsSW;d@T>dBj?V-JXO2?rP5lVG^-wq2VK^!5av8tKPKmSm zMyC}OzwDtO+UPT_5qch)?9XD~hB*wsah$UeEb7@q*?6u5+BS%CReCr=$bFhK``ltE- z5dWaDKl`USR^ynoMb*(U*%JN%nrS0x(S7|N)~WHdI<-jY z^97z-103PmNqxjmwlHaIq}*qS8$Ew-c`kS2MUgQXyHmv*Ol`jC5+clDn(M_MA~pRD z(dt6k%0bor4Uy{p=oPK~W%+GPGM2KW*;J#l7L}I(*E#p02A8pQK5goPmSyAJ$NkB5 z;E{T5tl?WU|0irwx~5^T2JZEp37>x;KFxfkwq$s!Em@vwOOB_;@{64Hdx3KarT~uw zhU^T}HG}>Vbi1pyE}$;9k00DrFI{SDr{X0F)x$xI)zI@ZaklveLTAZ0*nqYPuNnwvY!F=L~-Y1x$BfonVegh3GChv2| zz+K?if&Y$H70Oxgm@@syt@aF1h|fTu@Fn4sy1D`H0H1+>-Omw^PSxTQIo{$^V_o&p zxZce;b)fBN1l%Ts--Y6D5yC|Fwb^?cOtq&Q;$7*6CW{Ns2khZIhTXTPjY=QqJ_p^8 zAUfQ@zY5OiL;D|lpNX2AWNVL{GtxgM4K!@isIOO_16*LO;(vrZI)}uXU40mF+WQ%g zA1?njec!|Xo~oVxuJZ={E#RnI@W8v~q^fcKQOZpi;;P0K%9Xl6N886I1NylJ7&ZLg zl^Ddgl6bQ{50q$U4A^tUA+KH<_FMu_Tr(j*k zQ+S#|8(TS>VLZmj?UViS(A4-Wp)X$?e#4-zanp${SQqv|-Pm7E{>eZogPqK3tr<0k zW_1n>y|S05=*3!_%#5HLjP&JaCe79IUE17v?PULr(9R6@X~bW)R#kbOmrwS$#A042 zxRMNYdo=2`BFEIicl2$t3rbEl-=Or@Pl5-M{#;;K{zN|PPduf|@lSDW@JN0CJKvn0 zDM#}8Et11b3OK2JLpw5*(k%|t8``J;zvkP0h`y!$m9`_N6z8GS?m?%WMc22Qu@|0o zqixp|Bet#YEKJm)_JXw$$qm<|E{v) zB0211b8i8knUenP;$Iuj_G#$Y#5XdTQkrkhg?O>c(P_I;=DxSlzuY;KT{}@Q;@v|< z{uiS?gs?2ZQ@$O1cRUn~52a6;mU8?pL&fTOL&d7IhloomyOWv{rHQ8Z z-~Umw*2;5#rSYXQ;bHLd;x@*z`g;letA2Iqi<9%f#5MJr=Q-bK*ZI0La4O@}>S7qz z6Y1m1JOJ;o^T3(FKaQ^E_+`=+Ft17{%KQGQJN+G(3?S3y%foLT@NZ>}es-O`*S7g) z_O>F>2Xa7SkoXksDmnVGO^0qG8DgF*Wj{++pKJHw^I`j>N^5`2MDmxv6$mWB{Dx3j_=SF4?7M)21 z`f3X4la$*|nL8#A`d5rCxA32oOT2jM$#VI&aatPjC&Z|{ zc}UwLE6w8W6(&aBcU|#(!{~!Y>ni&h##Fu3swqU{ZwvCx;4!U-q2*`} zznQtgsI3G0JmP`yFxj9qY-7#)O>n*oc|&@)S^plf1jUxR7snm-^QY_$GXw zyT9g_`l0XkT%ePbe#j-H3w8cqNZ&~vfKmTx!FAC~v2Py1U$XQA{rcxV?8~3P*V0S1 z-mvtmc~f+(eGkM?Y+mwFh)DPS1^NJ<5y}LX|5ftoEX9!Y1B{3J_};+#S9osXS)GnX z(Dy}nkAIoCVdB1MmipVYo<|R@_3s|^jGyP9uM0ycfg)^X>>0y zeTMmf{;~e?wj?9oUh)l_JN!F<_bBkT^4!OB3(x&LZ|8Y{=jO~(e^*BPdQ1Ih`2Jr! zpX0far^j<0&llXa{vqDCz0MrnMET-FvST|!oX#-ZZlc~X-sAL*?!`ea;|_sFtu-6Y z<6YxU>p>?SD?z8|u@{x~R2pk1$TLM+m$(|Xq`Ha%J z$Rq}t23w>a#*gM3&L`P1F_AH$w2zW@i_%gD_+j}f&S&(P;LN27{r;W_y(_Kiyo2=X zNzZ#(bKG_5r+nF;G)%;&1MszW(mbkvHd(*82F)PKIP)Qvt@D@hFEOn7 z-zoK=H)v-aEZxZjY_D_{^n>JkCA(C67v;EtcYr6oGoKgry`68}!!rpuDvSB1IEp<| zj(j!59jDCq@_sJ;KChlRKYdwg8uXzxEc%v_tZ;)oL~;()8!C$Qao=W6bPxG zV=qN$BXkflge8Q%g#84iKlU7Heu00V=X=eLUjmQN;o;+lu%FOX>}3_kSxG{HkSzC_ z)r5V7cJgl`WVFtuZj6KGY#n!zQtx@JfuskIaCYo1w_H)$L!Gt%)ls)Ij&6~4)}nGd z?}R4y_eR>tw}*8DG&~+Hp2W^3$*T7g&zY2w z3+tEq6O4miGh05>%}3FhFb8GJQ+XE;=5CSl<-CjkGIuflv*qDv#G6mtO~4Rse2j8u zO@$`-pSf(ZKTY&PpKI@Y^Yj^BZw7xH8RiXWK{Rq>6LK%_CKr5@QciuPhelPD|&##arY4SWySIQ z40YJSa|iWV$NN^^KgYieG_HA9{LIN9d#Y^4+r-ueY-3EKk8}?D@ol7)e!2#nX@BWE zTEme~{M6{Nju7t%10O+G^WWo(~>FSTVAafJAtCBgBt{acWlwafEm|j8nVXh$FRn$W~G7ZhQ{$KFO^BP~xBlq&{ z0;|F!Tf#9kow}(lQP+u_iJZ$?z|ijwvK0IHPDy3|Pk8(Nan_?@8PlAg40j@WaMwg8 zaJbW@43!7ZZx|-+=IPT?$Q}(U|98wu8Rp3>Ja_74%FA6Bd2A5!`GzR`J!TS~Q@EmZ zCiBJ1!}*5M;e2#B8fRUAPuonbH=ljJ4s;N4{5x%Z*!7My1h|mgG|C=m4>DN~uv;jX zy^0a>SoguDHZG}phjCNFxR+y^Cl_dbD?4F5D&;1MB zCD^hTtH3`VMNT+)sy>2$gt*^_aTWN7h~ee=mKbcdf7W{d>MOW;!TCvh>@@EBKTDhw!gF4gT{X{AbW*3BJz73x4ze z5dQh6!T&)B|K<=rY6}bh%>N<$rqkemErjoe@U`Zf1W(b}OcCd}jMY@FCmn<4lMm8Q zvj3DEtaXdl4AU9kb$=S&K2`^lHY?2%!g~e-+x5TY{WFAz2)`ywcUGFW5k5$`gYY2X z*8~$;X<7;M2&)NO3Ew3=M;Ikci>@?R5jIfsQCBj359}pfR z{DklX;aS3;2xrGvnhOZC32!FMC0t3ENtjRQC48K)neZ*bLBcD9=~XMuUl9I^a693C z!Y>HX>XoLA@OHutgijK_M>s^Nt)VQ!V!|52X9;r)bvAnYa_B#aVzk}J*4gdYD1z|p65#dI{X9+(g{EjerLZDwlU->HilJrPc$HZAr z{8$D$rc4mWSZp|fe(5U4^J@68)&bM81G|T3J$@(`{*kq7A9fA=AIgazS{r1mmq10= zoMK&}wSloZ4`fl+^^#v$U;DZjE6G#$S;=x zcAi5&kWBlp4~h9(d|Kl<=F}Mx z=`pml&E6Z~d zVc9u>enUE-#f<${gFX*ChZdfb2uiCp{=Mk%1P7Z+tG6b3uEoIiTBe(u~Co!JkU z>*rqZU*hJ>|K|Vpxz+z={?y$68u!j64`X-ra5**Cc`-FN^C+B%%%%y8-+^$d-Y!CXweh^2qmx%90$r>@~`|nKWtsy_0`Q+St}AU)Njw(T<19q9>QU zllXttYvje>9yZFz?C3qUZ@``$_TYE<_!cjzp0Y=my>v}xedzy@e$dqr5kNq zteqoiuC;Z27qq`}Vl3P5u|?xYvujh!6i<6)`&QkzHWk-iifBAX9}%y4Lj4I%agWFr zKMrl^EJ$N^pwx@sJDm|p5_BdyWuN*V%rE^@2fc36XkUarp=|Wl?1gGx(>X-Vb1C{j zyi`8)bSA-I3ocsA0q zAugZtW%Htc@{Qk*?cR|8!oF9aOX^De^Sq~cXYXNTQ)q8Kn|dTEOLbu^C*E~hJ&xD! z^cRG2aq3ZE&(qO3;T%CDXEP>VG{{=QjL3i9tK%OoHtMVfdiK=guN>`U9Ra{FBHZr=IEq z!MQwya}+qLoA?rYhiY?Tw_s#AhXwyxn;G(UMfY0%HY;qe;E3l5)>E`qKJyIpV^W-* zojTy@3`L)X!988b1v(pKGMvRAEPZ&*DMfBT&kW)tCV!XCn7gm@%sR`TC5m!bN-Z1Dl?>uY(&&E<>tzGsE` z)z!ctm{=?tjhV|fk+v`)0!31bas}?Q=Q5rL&MV1)crI7Z9>6_i#7X zau&Ric6QLd4(7fNZ>K*zYr2;tt>bPvjL%SSJoXDoTd66 zzP`#NVTxB?`r|guV?E&h*e{Ul?uPEQPn-$LKapcDDGd9^v+xn%AM2wJ!CNhNX5RTZ z$^>so`Z;H5DL5ZBp8j*8E2V2JY{iyEHq%@D)AK}H)|3{G$+ykywD;?7NKqE&lWv*w zPKB*#SNApz>{<~=_%5&=UY}f@MNDA96dvS3QzabH$Nu)o^VEL zrAZUU%5e8t{>|D1JhLA@XRryT(K2D@Xc(2@Y$)h1L{0bJjL2zx#JsS!0wl*Avh| zPMeM_d(nUwncD9OcRGi~gwI{V@;%8tCXDfj+v}Z2oN!>U^ET8CTs)wDNMvq5EZc6u zXFXTc-91&QAy4v5rHtuS+?9nMr487>;*221Bu6!0SK6X}@0xn*jHN@rtL`rK7GG*K z0dK0s|Fg~>Zw~p7VIHZ?hz1V$$^1~s_Wy_QL*WiV8^B;5iTCB5*{AnEcVnyncbNm6 z&75C4gSP4HEV4||joo%+wDlp$ti@g6{pim|kM2qzu;V|GSX6fDL!Gf3UHou4P8&W3 zf7hHV`Or<{Q=5DmSL)M7?@r6dYT>E5G~*!+4>McfkNw_e#&4YYhyJ#E+sGHiZt`jD z{)95&DI*$JKjK|g!i%Rk|~f=BUK@sWo5mFUM;ns&nWd7*EM@cgQi z0WW<4O?--Z$@VGsCp~Hxu>Sg&L0qLgmwEJxFi!le5&X|%4(o=;igreOky{r4Gm|e% zFX&1h1bXe}Hi{k9&W_o4a$j`>j{7m%e4X7lZCbdw)<)X5sJI zwccjR)A*2_;V|dRN4jvW`)ExnTY{%J^aJ?j9Gt5=bpn1bSelpQ$MYZEEv$P6y$NrK zFh1=)&a82;836A=oAa12=O1SN;GF63uf)qod$IqfEu2vpxteszG;4j)JTyjsB&v|@ zs4rAD^!HN!ek7NSecd0FTogwrZ&IPX(yln$t+dR#K zLA!)6;c5f%!rKry6yAg{;qCS^Z4U9KeyZRNy)pD3;Enwq+h(ovRE}s{^LVWr%tw{7 z1b#}=YNc6E8jbj)hyn144!nf@M%FOfuTXIH@e#ppA4gHYK7k@@wvBP1WCO`E`oApPM zx%KGR*84l;1AxA7GKgw!|3U(M@GbX-@_((EH?+}lkEqWvAYwaD> zteN}v`jUHY><(y0=aehDD+4aZ;Q30^M5Qe+(chAt1q;+M1OWP>h6d45U@9u zo=EF?$px{DdXE<_{rAF_2&KI>80je-tr zuIm;yKqHq(u6ssf1Kp1J^NoDV$Hk?ztB+?d-C$r;{ZNlhWx?h{fDK`in0E)Yd5t!HP~cQLvcbAKDy!>d&lU98W{2uD^{4V zg1;YxI6TS!Xp7RBe7>B3<|U8ljI3mhC$Z^?^?{$^eDSRomv{L$fy;5J{aPm%$D95B z1otU)1lW3kSJR0tZ_l1p@M`&Q1*#tVb!Uf{jJR~s~MnVCI)AAPSq z66BBO)!<2I(>H=E{fFL1-uk}zr3)BGaq_%LeV5CYo&*mSII8peLKx^|@H>l+4HzF2 z{`uF!`$u`#oYKg@8+aH0clYC)>b_4OiB4qy2|PX(;!bs}&~Xa7Z5$qEu3|j`{p#LK z?H~MurQ1*X*mDGQo3GIALFo42DH?>1w5HIxoHdr-4nl7Sp|ykb_p8%Mju!u*4VRon z8kKW)>LB{EgZ>oK8)(AOSZLQ+&>2y!RTh>15*k0BbZ;cj1*B^q3pW{zn+S5}a^@Q4 z>Bf&jr{K{aRkC5gMiJfZ$bM&qd6du|!9F}1gd2I^Logn?Fw)HSXdk${sBqA~m~uLR zGai~vLbK8Kf#OH$pT7`pz+p1|lf$})eKvKw$dH!w7nAo=TFZu|cLX9<4S&_Dh^ z*XKRJfu=`Vp}SU%|0l$EJk6^kvEfhBcUPCu?>4s^_U}ZC+@q;6JOz5x+;(z~%rb_R zC$q)>7ic%hUSZPO11~Dc_EmG@*z}V!nmZP24PJxJuymBMA-=~t%sw@*e(T9VR%%Bd zU7>X|tTDk}lo^CZ@K+PckUxaJQk;>}`mGyZC-UP_0+wr#|Cwhd8QrsM&wnH&>$&g@ z4#FOt#91o%PkA3U3OeWfVcOr3=U!YwhVVt&q`OAm!2MLyY6E}D+KbGSUg@GP`WM!# zU6ePBZdmr^vD6d(AaEKvw*@(SBY%R|FbA7Hcu6=9ubLjr!>bu@)zDE5^)b}-t=Nv# zrk?f_g{P6>p7!fp?607qWH`StmWuBqkH+?8-qXO(moF!+U}Q2+bGLB5dHsFVF5U``qWp^hGYWkkLBFdpFMa*g5Z1I1mJ2N5X!>ceriQQ>XU)UZL3-&K zYAa{cbkB>E+UWh3_6pb3Gm!yznzwal;yI*0S$^X{vCo#j!202ir=Iq!%+u(bX^R`Q z+0Lmgv>p4Qd6At>tP`5qOBl&WFHPDw>8c8}1$+8x4}9@I(t%$Ga5bKMb>yq10~)Dg zlD3>pJ>%q$wD!w>#qxvkj7#~0IYa*hk9t&_pdON!#LJ9$0DT-q4;RgE^ritrwrYm- zQQEPGwWsPJ{|iy#BK)&?=_~E&HbR#v=q#Gq=xGhuoxMWyh~57f?cjXx#esg0`X}P_ zlg2>|8f`-+V;sKWuY^zJJICCh{oI7$#q!r7l>q}ChxWwf7i}>-O1>XESR0og*Em8~ z!gqISvj0oIMJrkhPl7Hxc%JMFXracoVPWy3jMY`hpflAz(qEc;n*8favkFf$KA!gH zWS{mg^aA?n$~^6hr_Lp974#N|-h@xl++EnJi00VOX|}W>I)FA(W}x(!A$>eeTkfW; z8NgLp=MgfPXAGSFHtIQm6G`kw`5_JSov4IEm6ETM5FeQaZH*!r3_?8CKW@fU$jTaxsh;s+U>1I&i)1gU8+_%Ush?A?D$15`oMh^ZBS~zEoYdCC+K-d|MmoPm z&`S&aS?et3yOTaL-|>SL=4S9&)9`A&Xasom_{&IRAE^29CiZ;(LAXL@szxue4SYe< zk~zz_g#F(}T4=O6%lOQa{vyh3b0+(@iLQt5@{zO4s%KRe{onFB|8n9Dw0kEwY?2(F zXARDL{W@@T26M0Q(}ulZ1xFf_&^hvRAkRpakxVldk5+zW9q1r4BWu&G=w_|_EcXwA z{Je`Xv>Q4YFPs4DKEB(~h0>N{Epc(4IvcoyG;zLFMw2<{kINkN>vPnPawleyK|Evw zY_=MKaYh08!9~7lT!Z|0(2q`9Q&jz8q1|OEc;P`xtqdWYoz>!_6fIqEOlF-HkXk~2M@o`s#?wV(N2N>f+rHcv& ze977uleUAjV`ZicWA8tsHObzVN4jgQ>}+OUj*LhjW;yqSt`l1g&gbfk8U2WT-dm?2 zD?|6fc@*6Jk-BP4B^nhyWT3&t(B?Px2m9af@Db(JK6)D4w>csGz#G3Td0GC{zDQaF zomR&GM;}^Y<>f`t>DaYLAK#xK+{I8C&85sm4105Mrzx%$T*xEw8aw zNz3kU>{>Rt^#U!Jv;eqfCZebms# z8f+Yvf-mLK+WVFkAWWt{_aM`2etuk0jAR2 z%llc_FE^@QF8k=M+-J*ovI9CshxY~S%~E?O`<6cQ75Y2~eZG2Z%69=rI$1kwj2~p} z%(xkwhPAU9&NnnRPHt-K+uX$ZxA_?Dk*z_VGMYT{Wy5^H7|(dp7~;-AeA4dctUYV^ z9Am>JFz#Z^WmTHL;N1yeoke-w>R0*<+mkXh-7MH21-28GvyOM_aB}Ud^e@9>*?T7K z)#ZKQu8prf1=wHkHqqS9d!KY`sh2KIhrrjxL7#vEfHGIO05O>aIdd02Hp*ZF0~lf40Q#^TBTM+*3??nah_CUWU@CF9-Z z3rDv5qAJ)#HIQrB1rCww?$q0tA z{tWzg9yVPXD;gt`(eEX0FFg5j;%A#@{fnT>?)0sti`{3r+v{07=P6AR+GGD)GC}cT z(n>G2m3$q%CmY4nHbbNMrfL=6SXh3MJBm}5he-FzxdF^$P9@;-_84DV<2K6Z|H?!gtNqF3o(;Fwzo-+*CCUd$7I#vJhnLRDj+yOQpuj`w5T z=t1ctC&xZ}9+`$Y!xY%tEZlZj{w~phivF8T1|NXp6Itfn^KN5*Xj3Vf{lVe*%mL3y z9q_r7kajI7lh6$k#IjCjV@weXI?$m<_sPmQ}%(^E^4GaoBo%pTVo;gNlEWYB>Dcd&RXG_3V< zbQt=@#xzpfTz0a9rP}mH4;?|X_7kul-5vw}*F2?p{IGEH$!OG@-T^FV5&7bqi4-x>z7TxRL~n3OBetx^)_vFNEJU9b z`_U+6k*)~smnA2t+(!7fNnb~J@UYH-)zGJs{qdt#8c#dEiXI}lpET$|BI$nUfOe&T z;qLTb1V{V-rq@JfTDa)6@o}wt0EtJZZTneq@{4R~3i~eY;iT~~4t;?W@JgK+cO%Bd zE{u82pnp&s9qy5hr3>`WK!hOs_lQZ! zCo^ygk3&C!-z^I#y#_e_alsOtWf9>yxQ{_=C9RW84&J0atv>!`0@+>kD7}t!_2PT$ za_s42hZ#wW|9G5ZUvK>$%b#uh!C)Uua|S-k4{O|0H`cscnX}mQN58ASf_Hy;5_E+np@Xx)Se~bZV^I_@zRiDS^^p~VJy71HeCDo~hbrtn1I@Arna8}Nf{!+MBT$Ks* z@9eYMeG3)?4~%NB-k8Un?7tjJvX8DgTkEqVcNMV~A90fJWPi>iE}!tu@+M8z|03WJng!V<#PaLie&#osJ z57p_M7fG%6pwkD`hVRk;71^67-}0N!9}~cjC!3>YrqK4SP4(V$sjitBU^6{XJlSE#9X4e8xYheqScM zCj?7AzmqdJAC49W4qM#MTw`^%G13YK{qTTOkgYDd4brE=^vS8WALhiLv*N7w4CL%9=RF{e-u@Z&OLM_RYDQO7g?~Fwc2BpXAxi^8o3kvwSDt z^2dlD|B`Hr@CQ-8iDw=CD;e$$mr@4&;N|u@&Q@?2>zsV~BY(ZAB)^CszhzS?HLlKI z`*p_sS#^GSCvCoJzO{Ak%Ob;3k5xJBvcW}fALj~yokNGYco=(a4}GVL-V-?O1$-9v z)cGd}%ZMAdj53k!;wE4G18e#Sct}!?zMl*AA(Fk#rAsaEKe1Z#HS3K_CpVdK^P7~8 zew!G(w5}<3zHFp47M?uBH~eLg`RfT^@92BHM}Ze}kxwpV{y$51fem^mx_F0nPIPg% zyT?7XFY~Sc#3|n&==TV6%x>y%qTQ}jpdI)r{ZMm0I0q){lCpDOzik6&PPO(aJLt}w z;UMnIip%wvB#UdGZy8T?VMjAOZ{%4=8G@N7o$m0Cvah6lq&{Tkh%*SiX3MKw+B@_1 zGt^cybKnf&O|}_P$`bxwgzf|%-dH{tnAI8GnZO+Y$XkN_Rbb1G9Y@%%i02AN=r4-G&mQn2yvH&h z@P0|!*<*0Cl5gSW<`6gNIZon6`p*h(w2w6wH`7DhG*UO=MfJM?Sk*=F0S}@s@O^BW zfRXGQJRD*=I?Y zVtmv<+W{U2yt&lPfwmlE^y6K1OOwd33fDr@MJHvX*M&$nK2a2n# zY_d>$*3Ac~qsD}j&6oFQhWy3#Lt1+lmn@KP_k3|5XAmU2s@;s^M4G(n6WNe!KTm6{ zAN~kFL)>Hgpk4kO%B2p-wn3UjzhNdv7r&BqlWdV>N3$P1N7?IzuIrIyo$u@$9Z?#! zO>^;%OkfwKI}KDe<1=B9@w8S_J@zAGYrjx(NsKzKCcSK3lonYh@kQ#Qe>y`^GX}=p zVLbM8)YC&}KZMR)bsof@!Kt$D3eyF5{YXCLt{>9HNN2#W+OGQ6G+l4&T-lqfoPU~E z5KRu-b5OdgM7kQ)NAtPXB8;i2ve)S$o%YB%zu_e~JJ8L%D;m@s?2x|UcG1mSOOgj= z_ZEkC^qw)Cv10t(!#8tDQGS}GUz?Yj?AKv`p*tccrM574n#bBGBTf7~7yhPoCv#>y zI=CmrS12Rlt|>Ke-XH&StT`5!btj1U7qoNt6|6~;dHexTp9D6)8P=aKERx-%^t#rc zi(NB3558*bS(a>he{^U3EA+uWos$8_+6NYXcau;1!P5UAKPGAnFmhhG>tvtk&H=5( z*4lkklNS%<=sGcvvSY60?ey^$e`^Fh zF-D-B=1%r)TSA)M3J!#`PT(yAXAPXA)0vlSt{7Ljj!du!j_-o0d{a~$&Scjt{grVEpD6uH_X!ss}D;tZorS)c9n3$xM>5%rNSL;6JB%RwSje_ z@Nr@Rez;HT^W~JE3j6$+voroi^2$%6+SN!OX{;2;*BJIWzQ*vy8ua=1!*=PMu-c__ z!}7rxqh0gIz*T>3WnX32W5GVad%(S5chI)#{0F=Qd6!YfTzK5F`hXrRZE|kHAoEnE zw;Zm}g=nrq6KczZu-)*BX6>2YMH!a?U-^Z*mvJ)pT->tU_SD|4xM-A4Gg_}w0!hY6FL@Do6| zneZh-+NJLcq8G*^yg@uWX7nD+9g-v1_msR<{zvR~#Yd&bsPO#?4;4St*$UNb18X_i zGHG2T-X8}q;;S)teQ79lmtTckAozbrS!NiSmwIbn7T#n}(as!xXPD;0tewxnC!o@Q zfb?1??}84`ahD<=;Y&9k=p8iw-WujvL7q+2^9!O^_{VaUBRgeaYi`jwgdv{i;O{T$ zK6ZEpPuWHxuO~KOrx%|e=)4H#;C^dV~n3TPxKXbUQzuc z?B^{rJL7T6tmb_&@0y?GU!aF~LesZ@D48|5tEGlH{#$$t-ai3P_1w+#{#i@W1K!Gc zio2LUt}d=cKPURB(5DCe9VWElBjQD#zavPNsL+(w8733ZRfV3G()I{=PVWzF<=XpL zTe7B6*}8Wxy8kL~A!%aJ(zq=1u-ngh_miT$$Ew}J{3Df;Rt$&JDe?pPoN`P z6Cb3l!pQ~De1~v7oRy7dy?72dvG!+9n!VCt;HRIkHjnI$By|1;I+EPngj`-P|1s^k zVE?V%#RmX%Ex9or%4YAkIPEK6&r^9tYm3RV4IVa$@hF*M5VClI_Itl~=nfX`_8*AGVyj zZ9;%TFQvT8y=@^BxR=`p1wtUaLJIUj%e{mU9^vUEq=od}LMgpKU%ub(Z)VOpyINT$ z^nU)I|L2~ykIp%Be)F4|-^~2xH^1L+W}c)k?OwDsl=IiSx4rD~_km_@z{|cx`jQ8{ zmw3W@OlCcALY&>e1K#%(ad6z*82-z@kv5&sa|q^Bd||)`$s=vvmw=0O?hu;lI$^%; z_mlWeUvrT?Pu~4F`KF~K<5fw=1A0Hat5_DuL4N!R#Am)CTRdfP9%lYw-$VNcPk8jn zHsqge;H8)wlP{nhJi+mzlYI$(%Isev6F=nn(OKTN4KnX0q%V5Yb69)v;5|>&kYAn) zbk&1*KS}<}JGu+)=ygy2ma!p|e#{To;Zv4pzqkrzzsdo<5d3V9^$-ids19?kSt*=j@e>xvI^e3<_V&5w2JwMfd=ebL;pE<_|2#zt8@t%SgN2JaC|npMY%k)W-4bI5)WeR!?=s{M4$B1{2ja}9)myhb741m z-sY1>U~jo+6J-&?GM|j6^9dRtZU}P?onPQVe%be6yL&F|PT-5LI`=Br@U|emS0i8S zcb3nuKn}V3$^~Zz*RSGw2d>ZJI;8Yk9$Ci|zUgtchlKM|wk51Jd8z24DZ}y1S*~jb z{h#``8%Z0ajXnXp49;LhJ3Py_3H1SPs-SsLHoia9_eWv8O!twzj)W<-|&TPgC0WqWEtzf z%J+Oq`ed17`s@?5X>UfHO$T27_-54Iix7|SFF<}SQ*VBfHU*}!De~%b{SW?}p3_1v z$2hR>oqJRKx^tJ|eih<@hdy!1fs^N+;k@kJ$MJsEwpX}&^d?5KPGN($)`R7StRZ9P zceY_}1Nd{eI|J{iS@cj$FZS&RY zo=qEAHg)%A2W<|;5ZgQLaqRDqOaF$pS;mFU28@F39cxU;)3+fHmjU1Rq1VT` z=ugoeOj|JNQN*>aX|BH!x+L~>u6J-iqYWnyJj}DvLgl+2&LrOUBMqoO2=EH$tEPX4DaQrrtjdVT=pj^tV?bpF%U#*&E-m9k!O= ze)9E^YtOymCUuU!*mr*7eXqb-8_ouG6ZhWP@FwsU^r^>Qjg2!lI#)dQ8|a7IZYVu= z#g5Wro5Dlqu7F65pTLiv1Hd!9I8r-ZdgFXo3QhcE|v?6szSz8>K}hjgxZRtfFyz_}}+Z)KVruVLSU z4CuB`o_Q6Q_K9$`&*1(4C3?^v4E_EP+a*qsz-6EB>HF-n?%9BO$R>ZAC43*+t%YOT z1v_tOyYQD^)pj?cO>afJd+dIk5ds_W`KDiHDP6|c?EbzzpLPBY*N<^+OlO_Ta6K2- z)wnuwMRD!MHG(UF>lR#%zwPG7&|&%M?|t|=_|G4o`!?z4E9AGq3nyID&xcZQVsyRW zPova0n*c{Yb*+SK{o@@x-$R~X{fdJw)Q+W_-RGb6fobvlk9RzFg~RmtjB`F(p@p0b zal`w8X*IliU;Z7Rev169O7&-?<9g*~4U-;_863hw_LX&UfnWcToBvC;YzjbVW zt~{QuH;&6SFSs;{@dw;#px|E}E15^vwM!Rd8Q zZhhsFbKnOri?BW4$;OQ9PB3zZ7uv_2xX7Z}=1C{QA;=*=FyL}`6u&w*zMda(AA9}3 zJn+I7I`0~L|G)D7z1Lr-zklt`68^ofeNczL{hQ7FTH;^ypCEofzl&}xEdc-j-hQM= z=$v=*;tM+FoxIxdd>Gf8aXp6Xljwgh!-uWt*xR5vY5Ki6{EXAxsb~J(M{a8SPrvZ# z!ZUvJhqsk?zAOFRcf2X{*61t0_RM$Q|MfG!_}wp_d*!1K|JIAgKiKy1v+w(rXY}0v zH?O<;6R*u|`_R=tQ189%(Cr`ohi}Fnc-b#M^3~`4?YF;Cxaqz}e)#7v|H9oz-je^h z2j9J%x#K7E|N1{all}FnTQ@xC(fpQldf&7D=^roO`Wt_tihKUUw%qu)V<*2@xqb2X zKL71adk;Qx$>D!}`Q;BU-xqqaZ@TlQFaO1rsfRvs-w!`<&9$Gt_sD;G(?>q{tap9<{3dI`t>}dKNzT+Su1mZMpqx8$PBUe#`aS zzWBXYz5IQ*zwo{fZh6G{NACa5?|tSOEB!xlp7ok{x4rqQw>l2|M`9Q-h9{PAL!k4>&HLzNBNIDsP4Z1e|_-YPyFZ09{=E` z|NQX#YP%19@u@#P{qXNT_eEd3Gap~ut`R(65 z-}Z)%_c)>Vz4aNtJp6`degENiZ2h&RA8h!=fBWQ?+=-*}Kl-c1?47so%KyUOY*{Xz zdj2E-cJ9Src-1X;e0AGrZ~Vq$>02NE$xpubz-!_UeCX%D_?q{g{LVYR^rc^U!{^`r z=}&%TVEPB&n)>_2kA8mf=*RxcH@4h&!{J@;KlIfXU;dTx=ZF6If8V%i*U39BiGAvO zC%-lOt;KhL?={89nFn&Cuf8|+SI@h9;bZqaTx#F-_|o*7PG9!fO$RUi=!dV|xP8Zq zHqSn==OcgGdFjXB|N2`#@Zw8uyZ6@rdj89wjC}5)`~KrwAML*SJ>NY3-cM$J`$a!U z|Igof$8Gh{8wwl$+m^Q9xnb8c|MumJ&|QD^f@Z~VlYo^!|jkH6=|@B5{J=YR0B z-+s-*ufP0(FFyI9?|uF3HQ)N$rH?%Pg;xwc{>b0|_}*_U74QD)3;+9-58QS9MIZj( zkDY#R>GZ)5UG>+uY<*?-}=#S{_5x6fAG8K?+d@+2Ot0VuYd9*e;Izmy~+Rbjt^Y7dDlZ9dBc`3 z|M#w=-<iOT=e9LcqZ(|Q- zK^n?o^N=59L=OLybveevrYYn8rMPo=ho6It|Inw2EKF{~(H-_1`SF?Z0dX+wg}9(= zcYYPud0qfG4}kLkI1hmH0N`1L=K;WV!i7^Ki@C+rcqx^!&oe9bX-o^W#7|ko=F_HW z!{%W_Kf9yn)}6Qy;<^FX2(BqyGq_IRvbskk@4)X&@(EF|;m&WZ!r%+q0B2!Z!6)m* ziBfT0=-98YR;K#)wvnh%u=qZ(xpNnh0LT=MKzyQ^=dYwO2zycm0M756a~O)wsuX( zIg-lPvxA_GS}4^KEmcz~B%Q5-h9p>v?>bBsA*f57Yk(%5N-t$6N|~%9Gpe52Ql(U1 zTyheJZdUCXH3;WiWF3zaOLugu$#smLz-qz2rlu!dG=O^CfKH>BYyG&Meq zMiiPHIV!j8X_NRqop{KJm+JY9CPEH$8<{+!lG${vR0%n=#hyf^RKr_C@JJ<9&4TO% zB2jvKdzF(Z6|>%@ zl~Uyzl`DeWxs1vc&@j~!dJ-_Ameb4Cdf~!QW5XBz4!ny}jthfjvejCyn5topcVWP4 zsa{EESHWagYT06@W!_m6prZEXs`4dXDxXock`m3s z>N=EQg`SyXHCM|iX3W#s-aUr=TuJW|Z$QpF;w869@9#F|6O>7`T= zRnj>=(zAbPL?M|WJdKZZb*q`BY;je=mZYhI8I&+%uH-V=VsCHAnKCa;;5VqwGdqf1 z&U}5oCV$#`)KI-rRNyDNDU^z;wv<&eQ`bZYIf@ObrwCfAP@4uQ!nRgt-EmHHV(=t9TYgv%>i^iu_h`EAdS*xMq>e z1Kgpu1R8`_*h+lRVZKLDB*|ALdwV@s$z~L?p3e3nLV_az5g_~M_C!;vV`wOzF)1%+ zvt?aKon*bJTV)2+$fWbj@(08;^pIpgLo?oj`wQ7zddc@xUFuF4rzWi>oD3eU4?S`q zjp`!)1Ai6coRpMA!DxeiTuasJ7)4QvBnQD1`6E6a%q@bLm70bkvW%`Pe$7?XaJ`(* zu5_#MTyYsgR5=TJ5GpolP$Jbrsw`znNhRA_N2$^n`aq>(rgT~-ZOhFjP$}i}Afjm_ zP0)iXo|x@ciTGGIv)HYMCt}^|*wnNn9-o?+2su*FS_*kjmCN~DT38~7Y8iHsO+8|( z4nA~rTIS9-3|IYO{4l5rm^z-SEOO{MLHe}9*@%oOaG<&7nrm9&?cWhzi86uyu25S! zrQ1vglIT#Ws=~d_;i?*H>-_136J&V-F8?`De3V11ZfK^-7P5s>!|rBIv2-r+;vfqwe*%9bva3l9IF zeDP8NBT-gONU7E@6cV*j*t9Py|6a+OvM)SBQ_;}n=@toU_H1J545e$sC8v&u)vsW@JK@W< zo^fHyV2Y|+lrAjCnYFOwisgFEk4UC$lK*NJ#*2(jgJXAAh>7lpuk!ArCqg;w`zVS` zc1OBA68}^PLE>h7O;o=Cx|cNMPsr{^=BtO6Nc=USi>Rx@CDPNW z35{q~RXCOOsfzpocC=UwvlR^J5RcEOa;21pB&0eqp4TW7siABNW4acsW=3Zcm>Zx% zD;TU|6rw~FE2^=C%Wn0AYxqz+fl(Lz2Z`m%&L~t35HL`?l`IhFPN5SvM8jBGFA$p@ z%{$wxU6^UJ+2wFn8pk_+CXbqK&aNLV0VthI>Un6J$da6ioF1!ffR&A9cInE-t21H5 zi7>M=Th6cxaB2w)DzYZBy1ZlLud3@hL8)pfpY2i=!0g)rwy*>9t+2c#*Q1V1|PkQzf&H6a8+P?E?}L+VWgAcSm*~CSkTx_O(~l9!aGjlkq+4CET2nmzhE> zGf&PHMP3W1CbPA8sko3^?2^~S66WS6V2>(N78HJWU8f~l7t)VVx(ed~W=i~Q#(Y3~ z976_s-&d=hNunP|b|Oy8K!uD!AgERMRm-`#1=_d=ZBhrqE8)&MiQZKyfl@kMgzB7h z)@8!gg)j31%n`oy@gDAExfiPZ60u*h^3aJ2*B=%H(nBUmcYzP!yRJV=vc7)@s#{`( zR~80z?)Nw$)107wf+WpJrfubVBH4LBv2}DwbB4yLj^PW915?MDVTj5NA+g!vv8kr8 z>4OtvV@+W#f@YE-2kNq;l~_Js;#0g_Pokry3Qn=)OqS3A`NF*6BLw6OL=rCy4c7)9 z6_q1qAtlJ|oP){-t3GtYZ460vIF1R}0+SunPv~0X(KwZCM`s*>jzQabHyy?K=l;|V)JCZFrTeB@mLZ$a8O*QoLvz;-$=sA zmYr&9QA5Xh#m8W)EdDh96; z;+Ipkr7nej<$gyWRJpSEo-21L9mgMPuqcwqgXLS7T0HHAES}bU7iIPW4H3E&Du~3v z7xTo@nX=*rmPJPBkO&3ui=hHTS!9<644@ZHrCwA93CIXG?F+DUY7Ave=hVvSQf0Zy zc7fXI40ngS)KaNh8$7jglplJlHBgu1ENWFP?Q>LipEJ0CANiH4?@JX+#WRIc9r}{f z`M=@dbNL!l{o@+2yq!%bmlGEoTo%0bP`gVayM{njwOfV6!W^>{4DUvJ~iQXh705 zbW7(47s!VQ<xO=j z`EDGFNg#hdrQ$MKsNKj6Qxm5W#j+C)5AF;P_V*38hodXrA2Oy08$K*;KCF0~D|5V` z(+z(gI!$q1!SKT1uIS)Eq#FT)(ZRm1?n14; zFR~NEe7!m!7RJeT?VPDE&zXM5oa+B0BZE7EMmQLy!ZS`}*KRV!UJQ=Bz^cNgavUnl zSR))HVtBSPpfj5sQsF@}1ykh9kkoV-lQtnCXq{k5;TS7s6y{fLIkVs}n6DT0m*}1c~ z&dqht;m&;B3Lw1mb&eTeL3Cl5Ekbxdl!XcLpD9KcQ;{h6i|{!J0|taRiHg~F|FZ07 zH4N@&1?KEr7ov9h{t6n&6-vPzJ$APf>xLY2R!_%>exp*?{*r$m5 z6m_5a98A{2a}y&I`eAI!8JnCLnVy>-Ihb@NN5^ByLqOsr6Jxv$O-;?rO-~W8Gdyx+ zj_-JkPv4xFnH!lr=pU*(D+ItEg|fkn2*XZ$ zcmR4_;RO)PV5&n?7mFg5Od*0nhJ&gjy%ch&Xl>5`iyN6yM`jM`P>~>My-d#H@32^l zF$YXlqL4q$&%vv*^p$jIxtz{|uj5OYP!8$Fw}_1-caldE4<(@c$LA`Ib@BqcIC`!+ zYE;TlsvCm3Q=HzfrXd+dtquIdZ z1P%V!uzVE*G)5ICq#J}9%eb*D)_#0VYKvkL^H=vfux1X!t}Jpj%^SwF2mpRU<V|WiZBzq`Y!^gFM1I`kzE%7G;k3x z7n7qkGlW)&Ihq24(PmnVhO{bWGtgQ zML}co1K=#J{Qd+aKqs*TU5I2#rq!_H=E{xeHLPtC?U|l-s8z;{A>L@l-FNCmdK(l; zkk7=1L6r~7F3F(C76W78)hoO%G)meWqhQoS(EJ+Cri5)P>TGDwmeE8fAYsrBqbcWw z$l$`oWu&7GuXL)x3%c~k^z_v9pz_+jCIcia_~2Akb|np)n>H%OM-R?T#E#ABv0^AT zc^LEYYZ4x5aBP%i2++H{2GW3{ntXNAeOz} zkWPf!M=^%(1#!=!pDyfI28ZUKG~&WRpi1-bs`g6-W~*lBV%Ir_0>VWq4l0;I)KG&^ z=c8SOS4Ky>d{}goHQCb$lB36alH(_A#@51N8+CFN&~6??p{5%)`Y5DRHc^*OXwT3v zro2Y28w?Cay2bh&M69~i#jNR}Jwr%3mdb}5Y;+L{Mpy*r>+qYYcxjj@oFj0Qa1+yM z8%&)SH_*Rs_vRPb<*=wNhbU|m*pW#WtekeaW;n1Y^Q-ibj*1GG#FQmvNKIkbUO zx!M_iQ>RmB+^VZesPGZF)3i+AV+p7WAMNV&~Pvwz+k*@zq2~j zQB0C?cMJ*P`RJ(0Qc>vF{Gn}fYAzO!k0g^0A7_)(b4Q)FgGxs6NPyijb5W4lVk$Ai$=3uFVf;Jmz$U>u%apR! zVn+@93^oJt84zm2UP(7QG+o=YsCzR`OVBKv+=Mim6%~V@A=;lvv^ECn9WhKgL(q00 zxnw>C;{kCg?JTDUI z+#n{|>72M>a2Uv9d;-goX($o{M@AV~Ciu8<43NiBxRS`j5vVNyJ;u4Fg)na+r{`z? zp@l=S&h#+}PC!{nZzX0(XbHCgr~)!gVbGLT;2cCnu7yN5oPz9L&6;>^cpc9bay5BJ z7wC%)5aaqCd7-)d}SAGzx6@-gFSHI-_=k2{0wB0qE6lmk*Gwa zv;f!_oi}+^bo*J*nU@l2h`uOXxpZmJRI&wUY{wKE*xXQT8npW>=ez%@J9P?+MzV0hL-C(NmiG0Wupkl@`Rg;lq8fq)?^nja@l6j(@kLtoT!j8b$lz_h<+Ku&&0Me0T9FB~$ zgcWJwgDO5t?Deeypv_-a$0F-|@7LckAH8rQqylYqdM#yZ`i)~wm`4YJsFx&F(2YGx z!acii3g(otg#@WPP0r^Mt_qt1eXOLaNf{6vC4=32M?_qf#H9<=k>X?Q5&teLLSh_3 zb?8_MF~H5Ao^wtii#!lfL9<59`h58q5mqabk>}P1mnXv#krBp57C07FEjG=on~s zc^INVmE-N1?)JP zIbVmtPP|$ydc=SWb#@Ut8@M9Czg$`?{emN%a7Gt5JDsx~I$bt8K>?RdC{$sZhKM$D zWGp^{NdR1@oA7tD>4U+*6CdSY+z0bEL<9;5oI?S{X;uMhDg!CL1{Z!-B={;w1G+)_ zHFj?f?IwXzIt_gUl5GU67uN)(HxHEgpa+C6kQvJy+_AZWW;V4k1?{nRbEEgfcVQ2b{oVMy^?KCYK>m7U=5d zwiDY2SQB6a8WOVJp?1KhV zM~(*-S|uvpE}gJU+|&XE1jVVMw2TBT$~qtJcYZ_)s79I3Bqr3sWPFXK! z$~4+ha%^gHRYY4`gOZb0iA|0oW6)RWwb4nK%Fv=?GcoA9q#|K))+-8RNWtU>-B2Y7 zfQm_!PG{)=JhiYO(~7M9&IV{2h%EL9QFZDM0P#ol$`R9EFb^k3L+7?|?Ru>PS-QCD znkI;buIb3p)}6;lj@&G30Mu*Y6g+cMnnA+%WpR<&O+v7qEkoI3F}Z+oF<+vSkOiW- zQ$1mlMb3QS;zwhF;D~9!W!hP-RqCSolcrnul7R@KYntl)r*$#UvB+@vt%K5u9eurq}KqV0&)|Z`G1B+AWl#;`2-)*OuC}K?H#H zwj`)2oo%yT)6*S;?L1jps6oZeNi|wKx+0yNB`F(Aw{)Ef#^j0N?5SyZ3qmd4h~8k= zfWUQB^l(Yh6}gZt$PF*PQiT)I32c&suh43YF>B-rxIvNug3DkH2~BtY ztT2=Yy{hUH@9=(jSZ8Iht=7x*ZReQakKpAatMOY5jbKfQ&%y=0Md}_hO9)daf-_r< zNLPJSW|l`PnWkzix19SqSOWt!fEb}Isw3f2F1op^{57GWl%r-Ki(3Q~|sNhuF+k5+>)$OV?yHe(G zzgU9Los?1QV%*FQ7JV8yyhk3AZ2z2JDg+Kf{7Y+ z$1DvYd?K}&OIt-LvrcQTjNcAzz0@qFHKicYiT?q`6iQ@T`;tFK7k^nl168|SNS4TF zIqjoMMh6FKhy>YM2UZE9RZFmN=Mn@q45j#P8mcx*f$e*R#pvy;1kDHV6-(uy`GTI+ zPZb1O`9ZTiEO5liH<1QTD+n?b`WV|!jd54ixBqi~j`m`u(7+&d zlGr*#16(WZkUmzBMG>w%d6Lb%0|rs}hO*DQ4?Vg^H1*4nLobOKy9P)j>;V1DXGNRE z7!ExqB{g(^@TPfm61t&6k0BakwGVz6hlil9z@J_H_!Ef^;BRy%Lw80P9GSqi3xE2e z__M2@uh9Yg1rYuMh#?2@j;kM+8ZrLppT*+ zoADedBiX+!M3bV}GjXx#AS9+bk_Z-Uq;uxU&m3EF)5P6uByVZt+e?gKk6+m2gIe~C?7 zCowc5h90TDG6#6^5`=jCbfbn$gO+49ZfV;l`^=(O1{m1r=OmglctZ4L4h|{j#eA5+ z18#@)4S$m}6UvEA3@c}J_Qo-IHlUHgJ!2eSARIXp$KXt0?0ZH9ONA(6M0bxL3HOJG zRA;}MfOfB2&6jEzjc~)zi#n)v87Qm>yEv#B4_B>J_7IgS78QImfofo#1OWw97HSPt zkzGWE<>433Jivg<1zQ7IUzEt88@(_xfB~5cwhCD?5u20=UoyJ;;5c~3B$AHmf^?z( zvz{h$oZSxPYCRZ{;Wg@@CXSklVCtBBlMAU8HPEG;=)fovy|FLmCfmiZUHv+2m##Yr zLqY=QCP+ZMB>KW?W-8&!iSNVE)XWTAPP|<58`zv13C}_lNy2=vk-TqcYkj+qjKZHy zb!sAZxy>#P!?*}c5JQwSK6MOT6CM?!7k1jC8Hba7N42Miz%!s}gr`hK+r^||qR&xc zYz(Am2WbQ)gU=BQ;lLqjc04xiCQKpCQ3||+i?@ZnSa*?Zbr5cF3TbvuPjw+>7?+PB zZFHH5=*|S3Bg_+gDa;cniQY68R};sgJI7H0JK^%=R`MyEY4?B5Pui5MaT{^0n%NEHbKf~dXDXhqz;^5>8lN4+AeH%&>F?G>I)K$MIj64 z1dg1X-Wl7L4@NuinaQ1#%*jf`I3~ySqFv(bL8Fs%?xNQwDoj9gWlU3`pmxT%*3Mw5 z!rGl)7Kwn%q_Fx31~gg0RjQz?YMmIhQ+~upvGg4~X*33cT-ahT2fDxnvtz0u0yI(l z1{)w}NUd`_QcPFQl$nJcaOE?P4Opayq|#V4R@F04${$teM4`5W;|GnuEQmj+c33tf zEvMl#c6={6(aQc4ZD3CMia#V&Ez_w?ykOvNZJ*oJg8K})Hv(s215?@U!Bht9Ghkj~ zpOvcYvd?X*veP~zyx%?pzRx}*JZhf-AF zAU+C^3&G)JzA17ajrk(gEx=5p%~q9qnd|q&&Ol{lO}4;+6h?-Wg83E_FYIx$cE-L} zq0Kr?RSG&6G|9k#EmN>_2vjjyEG;T(MIh>up49MTh4&%y#T)X;8yymGn?2mGZ#(sE zm%hD3-v;z;x4uQf<{mNksJZuKj2K zOLKNU8O?*pzlisa|PVc3)~n`Rj^#tjGP)n5FedzYT?Ovk1ZX0IGfJh2xGfn6xOdk#ZkfEkNV zB-A1LCvZv7Y71+}*aN1FL4>R!wV2AGNxHdpuqL6v zbyLMt`BV`~rt5VT3@ULz;owR($ATk zWW2^dy}81o6wYle(2U6hh-qS(Xd$}??UVJ>(O!j~LKX?j#7$FJIeRb$!>`3#B8<5@ z0^uGeibdmqrA)nIng+zOwGI*XI@-Yzal}tW6J(!qsF$=#67f*ZW5R8em4oW~txo9T zniF=+Y0uZ;FbOVtN*iF?uoIRP0~9Y+AS%kajFZJnaxnmE#QxBB zk8$l&%Rdb<{aYy!!CH|7o9Hwk)CuL?eqfiB`%z)xu;FM;q ze*#{Q*pdV?!I0k%3Uz-tLaM%71 z+R|VLDvVgFlg$A&1hv^3f6%9wX+EHh5auIn+!F>I)b< z(Baj!jvtq409DmL(8GzRX}xIekVAaGcnTZVY3JiSgd@xhF%HNGD=$zglEFjMBy4_- zs1z_xwLrdosa+WffCV(qf z%^fQ%%~Ph7Hcu-n8fG*$Bbkh}aeAbG;kNcjIG<^2Co*{F)iO@|&P*Fa5h#C<6ga%s z3K&sqgN$m30bo!@Q=}O#>kHBct$LiQYJ);m3q;*0C$?q8M{dYzgkFwxMi{Z?J8~UL zGBR7igAY>1-X=J>u$t{YlkDyE!y4fb4PG@Q=9Cf1iVYh#lVf?eAcV`(XZT3Dtj1wu zve5M+rlDMapuNc{n`&Qq$GFUkLC1-Yj&YJo%XkVypVC0Z6uCeKGz~1FnGf!^ zr>#-Vq5hJ&bz`HLkCZD>2>2jFQZ`K$6$u%b#AdKNB%-K>hFNzLNqFADp2j|c9T_DG zS0!;wXX~N+5;_5TA%+|=KY?^eiyvm-;Vphn5E8Vo?I{NYAv+lNL~8&xxn_d$9TMp= zgQqH6<)MGeAa=~UZoow!tM~<;=ED}LAq{CI*u2hwYWtMJnor{&xF!gdwNNf$q7Ci? zsN4Xyc-Va{)VtGb=8FZwNI+>6rfEHek-~U>ZD493V^gj$ii^|R1&RPaaxONCPYln+ zrzS_o4$e-)j%|wt1Zz?N#@~iv8&%&$?@1?O#$LE(h zAb?^@$2YPB3}=v<)P9vbj0Lb<4i(4B>m*dXhj$N>Q^JgT`}(tx!*gVH+jf zkbc#3Vre`el0eJ>0?x}CTDx{o2$O-vVu6sY0EQ^6faLPQEN9u`d=xV&n%36vZOHpp zUEVzagV>-qYHGh5%m_>qH?_G~DxsB6v0>}R3C_kHD6BKLVe?qXuGmAqg1WbdT7h$@9&M0oF2K`J2Rq zNTy5tXjXudfCh*>DvSKm>#RETIH`(=if+p%?}s& zveu`%w*6_8^gC%VN?@<)HNF(#m&V*=#GW7yK~%CRxVF-iz^7H87R2VjPYe0d>2$4< z*HI7vhh+>tGAY)PS3zLlLhZ8ouK`d!Q^4N7m7Jm5Dg@lrLq~=48gyH}AJiylJ!^cd za>dOW->@86f5}yD7aC}-I*^mu!fS^kBbsJ)2kfPg(wXKe(99W3_b(RKH3bnBs0eii z2FNtlkMU>x26PXuVynmW5~nz#k1(x@Ov7zpt2(-74dmu4<(x4QptqS;B4Z@z#At_( zvU|b`gH3J3J<{+78y@wA+c50&;=;PTVwf(JSdj+_5C$l0L^J>ws@`aC9~hotCpNx6 zEt<(Zh_MEr?(OZ>?Sc?og>qW2(i$elK{jbV8y)6N|2@QKdBl^O=!H=diy&Gzf>`M0 zVvt~MaT+nR;0C5wrf(?-Sh83<%?SX$9vo3eumK|8gz4zA2wzYv3K(h8NoI=}ebz|A zr3VQxnO$UVhT!?-&ZL*6wXZMbFjMPpa6lD1TJe7rrDUKq{ai$Ew7DjNefdAH&zxC z7uv75`d5`Hey_Mwx(W5R&Kw5RGli)NCS-hoZY_m@5q!k?rq zv|b9ceMoan>OI+5b;p2ygk5t;`nWsM=S-g65lZkfKb!RcsgIGQ5!>tU~&qxi3&Qh493o|9%$FaLmYbSvlM_9 zMnq+iGR5Xt@WD9KE6FlEF{W4Wgi~E+R`4{V!|=K$Ju;fynCMm$*$QUKz3?{SX8)W7 zLiLULtdTM`%eR}t=-L8XYtMn)Fvl35N%qv6>&vBL6mpVYQ(ML>*8$vYfk#)FcaN+2jU?l(LOzkgX0YM9@Mhmn>5;QG*;fJk*0d zly*i2B0a;y(~+LUbYddDDs*D4f$jTeU^A>7N#$jUt(_1d zJ!uE0>3Sy25LT+*^>QWUkZd^6PR7Rd#G2kjY;Y(F_YV+kn1Nu&O-{l)r&qchS?3Am ziC99>mGq7_n6v9e3djxI0;Ev_NKa#%zG-Q}{gy7lfST6c-b8K}D(kq=enJtffyvvs zgB9$1RJ$NAEj~ss^bs*dJJ!v zir}i!E)ne_fY!v6x+qi)P)#{ERJ{OAEzu|f_SkkuKXqM4qhq5}a;nP$Cw@9CerP0q zSQs=F=hG3VDInSua4gvjaxA$DCbkMD)(lfdH{loye<*mUvgV`_n?}Y1sI2k^eO#*X z0^f}>$Es(ikFkbDCF%u5ov2Ercyb54601u&tVr{93h{2#OL2``p7EQuz5`xAgMf!k z@F8v(4@Ki#&cCUZ#)<) zrV``hUdTkueLfPKJ?6f|xjH9uq^~(3>IM*5^vF*4-Nf($2oUiB@O`K;b%gXG4Uzq^ z?oQ7i!O5{2ExTf;`+jBv#Y>f(9{d2)Q%%8)HG|>+0ZS-qXb4DuMMx+hE}SilhVzu6 z;RQezpkQwG`KWalST89T@Ir~XKx-vuG7Mjwyev}|F0S+Cj89;rM4^KzBUL>pBm4?# zn$u9_BOXd-{0aL%x*gaAR^cYZZLM)S0tP9t^`^K~07SH=8%lAGgn$u+j!tnDi&n`Z zI`uFshM+8XHUwr+GFuQ^1q3F;91*!QljGVEW|zw^;G)2-6?uLO%~&P{V5A3@jJ#dF zvIMm{TSn$g5APLk;ijN5Gf}rgG9`VmDWu84PGb=^0Fp^L=xGHu0{>EY3c&LiTPI@r zPk&IHjsm6aIRLJ~5;FdoOgyGP03&M!qoOFI!-99wt(0nGWEvv9!ok zHVVfL2Erl(d!AL>GZ(@`=<_TLn685G8Y~I{z>+F8IMYh0gl$8;0{sHlw5+9p0s$(geFT;VUgWgS<4zvU;B$F*CE%8INhmUBVAeoO- zPBU(kaLxgJnD%m3&P#(YaapA>ju9PX?Px|hTeogiVg8l3nxXCr1nIyI@yFe28kNG~k z5*JnrR?^xqmWN$zv4sD6W`KowVp3{4iOIAMa|9D?ENG|RSxYi$ySSJ-l`>qBIGDCL zO3BeSDJ}`b91+5HL218AG;MZJ_{6$)up#i~#XEA)9qOIb+z*TOB7!YX7Hc!Oj6USg z1;WZh>XOGWZbu=PVoPEiyar6PN19qUAkAM<2<@*ye;+EM+k3CqbE`P`B>0t9POJ8Q zY;hQl>OX*r!h-^@@<+|i#AQ0BF==lIIBibPj7%imb_<^jyM`B!U~xmqVdse6_}jT@ z@|ZK3D^+{O;Ok-7L=0y^!F5~K^}A6)GbffWFQvGvC_-sxUKxOUZw#wBCdLv;?2ySN z0^oYsCm|7c#)c+TvTrx`!L4JQJH&Mz({cURf==ujIP6U1(v{MDJ_S!iX2eO#T-(iz z6wS?renY!8dv4P~gqzekhiUD_8cf+-9CA2aK+Kys+V_Ynqy9{n6PmZ2c~mfT#2A@% z2ZBelW|TGvV+6wN8-y~p6n}(vv*->s3+(jHHY`5tdJzsQHKSbbL%fOuqT$cztyn(E zC?nulXTa^DC_$x5sDof~GK@D>_^;tjvJQNRHURs)i9*P-P?J5CjvjVVSSXiIqs_h~Oh08?2WC6JE*|pGKRTI!sHb=b7bi zGTPEd{gJICAOFDdvh-NgrD21W86?PPxT}=)7#u$lgq+Lf*|Tm9FkAM+!P&`M0B7uv zs!*qs@CZ-y)SlBY*?=9B4>GH=bb=EdbWU5JlmKeX0(&dW+3>$1<23|yzX-aq40fe~ z3j*3&duC4fTSEXG9{7%G5Ul`5aAp>Bb{UP38Qt;78W*!YQJA5G_MK)?x_Gs48A6w? zunQoP-mTV($PyGB`HR{#>m&V~ST_$5hO`O{dlEFVV!KhL5My;zu6O|z!3<6OHp_}J zgzCfWgekKi9edPip0`O}5@6K`qznmrj^tVU zqM}f?R7SPet#ZBDUW`Uuw9kZa$^yn@K4tXZi;XfZt_;&Nap^PcQfTzx{L)C_OUfk= znn5_|3e-3@FlX?9OzI3aI)`H#lp*-+XV%c`$)(u?UWih)SnFZuRWc2?ug(0cQL5RS5^Ix;9sAa4UNe<^3y0LVA zS)ZULJQ+qt67;)00LcP!1r>?X+i*lUi!&N6ZND`9-Y?ga(WVXG`0{VN$8ZN z$A}xW5%ENf#`vjGq~{4sJvICR{M4@XM>_r|r( zoB%=FyNrT005dC|;#ekR+DgQ89UCF((k1SrV53}%v4c4gnFbq1)uId4xqKBu4YSDi zeAV1Y%seIq*rkPsFM~~BftxJdz-g42N1099cfhj0S4;!k;%~p&3)+~iNcLmf1slQg zA|FPnk`91(Q0La+;*hf{Q>w#_i+Yiqfz!GV$Qxem!Mjpbf-gnaIGi)fJj>yJ7s?&m z*a>x zI8D$}A^!H*n$wj-32MGU+~EQ3W^)M>>H^B(cClEE<{5`Lqn;ti!8wy#TjS7evVAZB zPONbJCWa9`W^lzs1#?Ag5~@e$9;dwuDNd_u*)Mb^Aq$%_n*0dWSWR zu3As-?)&YgZFWH)Lgw{mC|X1^6f+8M%&{Rf&=O*DY+@ya=IoW&j+{;2qCvlz<%trF z;F$mF^^EQCvLv|>v0Hl>f(M%If$7<5sM}rz7bJnYCHpDtx^54Uq(g9V8O{vQ9%{c* zCS64lA|gM*)fp7^xC~i|B?>1-9MneWlqqYle5B`m9*YjEOKw@f4>ahyg>Hnq$kHlX zT5RmL6uod|yNYrLChOD#=<6=|t4z z1>>%Y2kK993q8`1Inz&mFc^Hb*Cjl&*zFr(G)Lm}xI@4?EL%`KSGOai@o5Y%1`oPe z6daG)fgoG4rq$^kYzj7!7k2rMDEp+4Q;L`8&2u0x%n4T%iuRW_C^nQ{)XAu`o%4sRU2B3&sPKMAzYvQNJuYR z@u$;V4U$Y_9k8uQ(_7s;{FoXl!Fz-DSVQ4be+D7t?xnznu&kbb%20>)5Z zu8;SIyH#%lR}?~J>)tCWFW9Sy8FSx0}V2MmOc_dx5NjF4Nav&a*EbdaJpE^~M|Ebbm#ze`NXyG)< zd)k!OB&s=RCnVYY1=2D510R=ZoTX_?4AA2iI6M-qgA=rIRLg5rDaTsf2?x z`ByhWxM@IbfrBU*0@i5dEwSsZ-7;D?NFw194&5bE7`VkoXmHZioX74uaP~w)(Vi|I zJHT`vXOmI{WS?|rpLnOfQhW56iLCCX^Vu`lB}_}lvb08bH9}JL=wW7j4M20sd~Q)A za{<_Y?P)doSP-rWS__X1pC%(;?l&$hGkJvju$wtcR?!!N<a~Ia;Lt1N3V`2*wJe|!Z&g$_3UF6J(ZWEw`h3%lF0VrH3 zuO7wE32g%tCBcSc+{MNM7j#*^jr@DDIQ4~;TPVW?ra9DKLhfS?%N%AHsRb4Qht+_I z^kC(N8>^wrjYTEZeR8WWim@bX?hok{0yGS=l)T`@!lR zS8ZMq8M$|<0B%Wl0--CJY7TkCq{?tIDusNca7ky6m(fC|IJ|XOg6#wGO!W1$!q(=` zj71`+J4k7pI4=6WsdC)&X!qFG!Rq`#J5V18kR<+xdz4WZ> zt1<%Wc?H>!&zM#gu=OihHNVSC58opi~uI@ zWdyoWc1U4^(v7@NXw*LD?S)%sPoQE;1L0w1f@yLz>D)Lv3I{T7`$Ns3QLXC%ga$<# z=b^Z%imsB}U-kiEmY_a|TFCbma**~b0>Q1mR!mE>*M1{B4?xxSvc2sq`=v*>SK$Sr z&n-4LoS3nehSZl=V~{z{0Z~DemU6HaD=YN1MxsRlPH{xMQra8UjH(^Dqj%=3%)`ZL zkdOOR%WleRMa4vB0mB)UMshkFoy>N^nF2KUqf}&oyJK`HJdQ6YfBHIoEc*834ZW0i3dQDT$ zYu%osS(O3Roq}VwACVu{W~ecOhkealyGSTr$v6SV0M$SF-u~kU_Ud-9AMI%`+Y%ot zC0nhGz!*IIJa;69%+#ht?A)KY|l1RO5A2|kBW z8cCsW;EYTMvY%@$C8tAeiv%Ht&=wb9%gY-c#Ww^Hh%Jh1;nNOu|5AEQ9d zk?kK06(JE5hk}uyqepbdki@uBn0*>LiWDR%3@WhM;H+oc=`<#fm|Au+oS7mNMr_LA zx~+wD2eldK=fMeb|5h#msCfk)B#h_GCG@=5T~|1vh_zNM_6wD z!BYb0(8i9dJq5t=hNw-CY1^1SUKlzcj;I$>ImuKYbYp(YlMj$hc^4%WPD;jG|B7=9 zj$*c3;OPa=@lyGW_?&mE$yuBcU#7ngrbBx337pXlix?+6Rx0yMR@dxPYktIDFIZ99 z@-t6+M$`*^hxG_n?p3Kqb?XQoucsvj5?XflSV1LGe&Wu>+7R4WLDT0aMV zW>i70a_)HVJd|;#aph0AdXkokx#pNgALrq`kTR}SGG@duc-K?J86Di}r!enBcSICCAH}fu4Ya5ulMzA2?gFah=gIWiL&={&9~v$`pk`zAxCWLqdHa9N*=510=WPWQx^X*~#E6mt0XCxyt%4NqDPFeS8#hfI zi65Gpn;yAo7OOYe&@72acpb+O1Ab|#Qn0Y+AEqs(@@gJW3<)J*p8S)N0Nd^h%1qW&0eXz5^mNS4RmH@R6 z*Z8tWL8fXQ!zLiw9VxT!Ihv^m1|nz`SwZA3WHA>8Bf)p+Z{Sj`K+ymQYxqB_%=FJS z;0$v+hh7jetL&SO zov`7ysk6){%TcKyf=f{=Od$vJGIbo;w!DZD#agMSbKolay;bZ^*eyDM0K^@(t4J5j zG7P=FDa17#myo0Tn?Cl53qP^_V6->vm<`#r5NtPOXP$eJb9c9Q5mk*=2Sqmfu)~R+ z+pwFsO}nr=3A+iq({c}XMD})D_a)`uXx&Xe&dt>67hhh2FQ-i~nQ)ZS8@b}FB4`s< z{~&wz_Cu%^cS?FHt_x@C3)6~4R&1pat%na|NeydmTZ2*NHR-}V44b{fXx1`i!pW9| zN~#Jp$3mbM1<`QE$OS)-`uqhVct|l?a4`W^6vK<2!Z}?NUHl$gIt3YplP&L~kCq;s z*=9%_c3m_sqz9)Lm1tk|)ur*^hQ`3lR|6P~9-K%cR%!`1#~>UQ9-xvN;35|Z$Ae58 zerw?CyGXeHi-g;`HXL{P;huT%v7|e#@-pe=kL|#8%NG5BaJupP;94|84-OMRY_iSP zO6TSVY9e_rU1>|Q14gShLpa^2JvfZ%&BYab8V(Iq9fYBV$J(s^dH8sq>o^?BvDH-z zNDmGpQh}$q^VkP1O8UV)IBgMK3(^PYI|F_-P9L0DSc%WyQ!Eeh;Bcm+5VuunHJvqG z04K-S`g8Bm$HV89!?2|W#DvrBz)1OPq`eAmjkG;Dn9KB`3M~<@4cCZxZ8*s&^jx3~louAyX0xTZ2#`mMsJ;TjOO#Me~THSr0Yplc}a8tJ+)YvS|e&jNe- z10Qd}=Y@Fq(*UQ1q?S^L2bYLr*HdWeBD=Urn-s;4vY<8L*k0@!A-hym$Cp%nk1*!; z$@v7*w%voDDQoJyV0M8;QQ*k58)9@D&Yl{jsC)!dyi#S1Dm4T_Nb^1F%{NT}llA!? z*^D#f%>67sSf8<}bg%md=$+80C_=s5LhI>=fn6ATxAKzA7<(S)fvGf)?ctUXT;S;2 zzBDQ7Xy-VJjQKfT8mxGaV?D817Bn^D=OCsm%$vNlT}pKzZbyiT8i{JYH`D9tWOz8J z32%swMPv19uO@o$0+xHy^Gu^Ldddc!i{Qk%WmlEZ%8k%OluSZe_Z3sL?y3_T>UK#^ z;pJ>xVP)S5=j`29$n z9l~IMbLjj{b3tmE1*5<*0e0Fpk4#2 zfMWJEg*#}rP+s|?6VTa!eS@4 ziaTzs$}6*Km&v#h)tOQqdR$D$x%0cpzBuGyM@V+*0(Wk)^q}?uS;Bw2SP{+T2H_yA zD<}%_O-RDjF@ukL`(DvA2sSU$z%~@aN8#asV`cCi3)pamiazQY=;pB$2G*mdjqm&_ z2ehjZEaKpFaFk17P+wTTY`m9CZWxZA;a7)?KIuHb&cHZmQS!m=P*3$1@nz`^@YtE2s8sOW?|$lU^}4NFZTd(5Jm@XEqKR7c?B zg8cTVbh&pPs8Ze+1C*7JJ!t+0BhQ~ALYV%{rWxF3p3apVr?~qvwh3m*8o!HSP=A<# z?%4Iz(OPf)f$G~GLsL^T3G5ccP6J1ywEol{&1W2*7vY2>(Z2qjyIwM|J2n&_9vMA& zXza$r;}erpiJPXAGqXpI9=rJ#A5dyO4ZHN>Qtr0pe4$t>-(IQK>ZeYxoVmld>JJ3>wor2{4ONVJ(AJ1v^jAm#}D*s$9rv++lGZsoQ;>DPS2i z7#Xt6CksS>tqZ|ucRVjL6i#LArqP@VPbS34h&xQaniFXKS>wjYt_wijlUw|z80MQL zA{I?!e`5N#JK^5lI}^~OV>7{ZtYcNfSxj_N!~<}fr}(gRbRz`I#(p?; zw#0^A#mTSO-!TenJ&zrPT2>ql4gkf((j96%+8hMi!% z@B-KSTWa?=-H*A54;$r^*RgnJPfys+PL0%-xINRb+2d4$!(WTwbkDK?qoqnZJH29J zdH_HM=SYm-%NjX4Xfj*FK1(skm2NuqVh@J3#iFXL7(W4=^zAN;#kk5L1p_slHKT{SU&Awz>4g4Y6t|A7WIWpuMXqSw+j7i}0C(m@$UaR!9zoGbo1Y=P{h zSi6DsStPeq@3O91WJY6*;s|XV92SLT2-)jJqw}gLeJ0JA7)deon;pfxR7CzwCWe(y zNW$-8eEl66ahljy}qLbg&6h13*%50GgH^O=R;O3_%#9u%(!6 zPGxpUF}QG++;0I}qZE3_|No;fUWN=pg-m<0@ZMMaq-qS1O+|B~!G7YU}g zZR<|~8}-8)rs5WEQm;yZs8PWvWM(>8P=>;_fPwY48OB2}gt1$uf1n%Ai84PQ9?(5y z&$zaqiq)`H(29y< z+f~!v)bSz~$T^xXVFZ*ppK1pCX%PfJwT@)!%u zr&sk20|Qo<QnE70N*C8c3>Cc##fuIroK+?F`M3Vqw1jaFm z(c?7s=^unDV7yDg`QL$yxGt0V>qL5YGCBF%ho?Syx}o<5JWm^YTNb-AktcOd^M;XU zwx}J-+z+$v2R&&Pa8Ad-U_*x8#A-ML1p5kN_SH%DIz+FqXato7Gtm%)5BPIs#QAOq zls2-Xkr*>swwvipvL4VRPd@SGnWJ1YDvf9zAVD-$>=8X2_6Ef&NQw`(SqbTYi1}Uz z3aSY=-yq^mI9tmtlUol4l_r57s)3_wRKA>h*gQCcY8@zzYS?ZziCHUjdX%>Pc{8Zi zfzqf@aoBv3wxVe;Thg6#f+COK;m@F22TG$F#ok)R$-~lCkLXyN;-OjxY85K%yP^*v z^5HVM@}X)4rBQij}zIH+>zDC7)C z``lr)kzDIQNyc>F0yk~dwW7Lfjif5rw__R%A%QJfu*8qs*n2-ihIODc8Mu!oki=IZ z(dZ1Sb)YmVH!mud_f8vfvt>}N1Eo<>TY{Z=cTB@YOqi;_cy8-k2TG&j62gi)635n} z(9yyA*(mtzY;Q+*UI!==7AS4DS_joSKn4}Kx@`BVj%HIBPvlr0Ul|Rp)`7aH0)~5| z7}&AjE6sar=G{PnOWVZ>ta3Ilf5R}@S_evJ%gy^}3S%O-A8q(Gm#{UIpmImv23aEt zqW}#;&I`y@_Gs}hf9wB%$HCkyuajYwMr@bbD390v@4S;;&|+kX6!4U6lUDfMW6u34Uz zV>BvV=nEoBRf&Ldh(97^kc*0|67@V>@sG-u{xEuRA09b5x@A%ijSL zU2bN?Q!zFUv)l(WZLB_CO@8mVXFv3z5+-%6fJMyIPF*c9YGPs@#2JW&T8+s7g+#5) zq08tX8zIBw?c3MYBx;BAsbpi z**DvI0ekEAJOI6v+{5952x(}VcxO74jw1OFT9g;6p&x>4;+BTZR)ZZ9< z6lS7r*jt^;G_WxoveUMN;e&VC4a<`lBVWF^#=%|M%9!ugC$N;_ME z6Ge6bMf>$wNk7=2zYujErE6r0i|CLwz_cHXmg<_zky&mH$kV;~0A(4QBWQ)SCs>e-u4XG^AJm=23|3F01Xd+R zbrlUi`y5P4F(*~=sfh$Oa!rm+P2#ZBnL|_bRm8TyP+^e}vUXODCOHmaU+nfY|Muc} zY6_bW$FZEe2xlg=UrC)!hb;wT2N%O|+9_}el!DlpLqE)30kI|#$tPkVEq` z0BD`q5k-gj_aSye9eTCXHT#92FTc7bO#B&cc= zY43#}gZUFhL+<6Kr}mFfQ@3$h8-zz`rl+v2_1MIS zGd(*rHpvaAo%mGZW@q^3NeOXo86O*RR!&zOuMP@aZ-Ql74SOfT=p>tJGI)U=sVIv! zTXdpr;;alDm{<^V*&|1>MI zi@{du(2@$NV5HQftLlR99UhzJHuK4wCwRmDOt|s5a5i!WtRap*K|QpzQg@$D9hs~{ z*U22%8LLIMOh@g&rYbg2Z_S`Kk4oc0tTAKO(tE59>lL!Y-l1KcG>m~4ubo1cT5>7* zdN42>b2`30GPt}@US^&{&iUXMP#~Z{K!Jb)0R;jI1QZA;5KthXKtO?j0s#dA3Ir4g zC=gH}pg=%@fC2#p0ty5a2q+LxAfP}%fq()51p*2L6bL8~P#~Z{K!Jb)0R;jI1QZA; z5KthXKtO?j0s#dA3Ir4gC=gH}pg=%@fC2#p0ty5a2q+LxAfP}%fq()51p*2L6bL8~ zP#~Z{K!Jb)0R;jI1QZA;5KthXKtO?j0s#dA3Ir4gC=gH}pg=%@fC2#p0ty5a2q+Lx zAfP}%fq()51p*2L6bL8~P#~Z{K!Jb)0R;jI1QZA;5KthXKtO?j0s#dA3Ir4gC=gH} zpg=%@fC2#p0ty5a2q+LxAfP}%fq()51p*2L6bL8~P#~Z{K!Jb)0R;jI1QZA;5KthX zKtO?j0s#dA3Ir4gC=gH}pg=%@fC2#p0ty5a2q+LxAfP}%fq()51p*2L6bL8~P#~Z{ zK!Jb)0R;jI1QZA;5KthXKtO?j0s#dA3Ir4gC=gH}pg=%@fC2#p0ty5a2q+LxAfP}% zfq()51p*2L6bL8~P#~Z{K!Jb)0R;jI1QZA;5KthXKtO?j0s#dA3Ir4gC=gH}pg=%@ zfC2#p0ty5a2q+LxAfP}%fq()51p*2L6bL8~P#~Z{K!Jb)0R;jIJY5QGJuvn7`NX*= zHXpd;+}@ks_T+(U-uC3?JBQ9~y>s}S^Uys{IOpzpB8>3O&dg&Q9VfIQanBRi#oqR$ zlX%&a>I&RXzV69QC$~I)6`nUZM;^NZFx$*?2cEZ@=UtBTJjcMF2mB`I$P*ESeSe$A zvEizFp4f2m6_1^h_q(3F-f^CK$b2Kb1Ne5PkNfj*--!FOaK8liOK{(eJM*^%cL#UC zJoQEs|FyVpIJxEAtL6TR$IeRlT~8vfPn8W!-oWVlD;_&$V73Bg+`t?%FnniT`wa|e z|J2rV_dNE@@89#7keCW@4hhAA}rh@?6o$GcczEm_w~)$z^gqm0>JTs~>6T4{v_wHyg&geP%f6$Taz5 z8Z0C8%6em65C*q~Z;Zq5#KZbzISAJZ&swm};jPjkK8D*L^QUm}evP?z;LbdcoBM>h zPvXvU+-UC1FW>ol0WQWzQ*~a1i}BHS<<7KN9>QIDPox55nwkc&KM! zV02e>AQI~tO4v~E&O8n{OOn^|OBUS^4Bv})mjCOU7A4K+;GKE9&cI1|@ovkF$5lV( znY3p-))ULYAMx8dPD4DB`#tL@v>cIIt**rgrbR{x0W(B?(K`AXdRV|_3@VZsmKPF&vs&6u~71`dyo z?M(mtJ;M{WG1PGm;QBG(iAUk${Tg#;nThXW+Y#G7f2>Ew^V0~t+Ifx%zY=%S?B{WL zG+EtXOnZv#j;`IF@>_J?e+PH|EKO>7XFjgOoq4$xch=v_3>@=Dnw&rXJxdzAHU8Z6 z!#`X4r0LU1|B4q}EqP{{SQcKy<)JbtFX4U74qy;1{hvn6Kenp!jN{KOBG<`}3&>Vf^fHXOMpkZHDqTjCTjpFhT2`S# zGr~N#=RMhlS-7@!mdMCO%+f70YbLsm7*nFz%ABMzgx&~hVQi~zXmy)j7N!-8EyN!+ zHm-kQw(s|z=j}NvF?*6vzvp?s=Y7w6-uFG{ytjBiJb`yf9?wn&^EQY&)tHZQokKls zT6kYJBItxYre+R1)93LZ?1hibXU_Xnr7uX>#*rem}xFk9kD~pG5}C(5qrO+vGhro;Q+8I#Pdii*$KL@=ID|@`#a%wMHBqKYG~U z%oY4LC9&rfqAH(?J;O~!n^0=W%ddjREpvDEQJ@J(Oiswq|JR{t@y!SnD?a6Wh* zwNdqURYx_g+M?>J&TJI9d!fiW#}UlNT+C9Y9C zx#Yjkc{1a9PiBGHU?ErxmH;-HDz+eU_?#!tfaAbM-JBl^X;hk_#8EO(l2tmPB&T#i zNw?AiCA~@?l=LfkC>d0Spk!DnK*@+Q4kZ)H6qLwZpD2{Xlu{^(D+wq`D%DVuQtF_j zQE7$}N6A1*R_TP2oYDm)-AWIX^eTN&(y!#9WKbD`l3}F)B_ql>luRg7P$KhuqEHf3 zN}(jKB%mazR6|Khse_V6r5Q>bB?Bc{r4veWN*9!LD?L!stMoxhzmkWNL1hR^hLr-8 zj40z!GNDXCiNt)OP!dy0p(L&(pd_hOLrF@hgOWz28A==_10`9d6H0PQ7nF1>Jy6oC z^g&6#l82H(We7@!l>(HEDC1Bvp-e%E%=d{xNlYn)lDLw9lB7}%B`L*!`<4{nyDd9* zbQtfh^v;?}X-VH>+R`0fO?i1$MKURO?MR#UJ3TkEqb4a^vuR`6YRZ#kE6b{qW#zY2 zNxRqfW3O#%cDk@i+R$7!-I1wT(Yn23MeX{AJ8#>tLbiJyt?Bk3)l^hfm06Ph+bGt; z_j+{d^pq!28wrL@0_}}`Ixd?IEw3#`&k{Z<#XU0jz})vP12=<8@C|^^jcfoe zXa{@2uH4M62{El0lfjkVq?O}LNVUWt8!gkpX>$48en+15^ykFic z_x(#jIj99`um>CmkqC|f|Dh8>BmAdJ1Ophs;6&kSnhxO zKmV8W%-`!&?z_SoKDOS=-}Q=P%X?e-Wk>#j{1d=vTI)^E>8?eNY(f4oU>t{X3|Oyu zp(7`eUsUf)4MDxh1&+)^UI`f6L*71kcO&ms?^mrsyelK7o8w2m;Tt}*q*8|3k+p$lg0tenacZ@LT93F_VaMmkweJG)O+R*zfF3N!h0V1 z{yM+Sk*!|wd8gNLz>zWJ*KPB?Uxvo4(C^42$o~Wwx3vdz^u$p|zJq)VVBGgm;F-K5 zr%--Qz1-Pg%z6eKxuyf-0vIp874$QI#E~q@?^kbeF1WwZf+I_iuL6who}k{)KONbL z{5OE{!d|}~kB8oIns5;h5fRPRvfcULa#mKEyMoVuKAAFTuC5r0E~*kV2=6 z55_b3Z`=d&*a_cjgYsR$Sotqk?n8b^y@o#r*Qdk&B@CHA0Wg+rPz{o=FSUc#;y~v+Z?=`4xGxfeJXOLh1vS07l zuls#r8>5SiJcj%gz&L}kwR2?P-B|EsJz(4qwbvWI%E-@<52$w*%6g0#yz|JfJnh%} z>#M;W^~^Q07Uk{gm0&H|FQ!QVthW!|QIwCV z*9VX95cahxZY1%RC*KB)>+xI7dXv{0*^Tmt)q4SIy}s*=oI*aP-W-gd^^SeT$hBuZ zSq&Jwp|&qsczcomUcJ{*&)(l8`g!%+p4d~OyA8s_V2Kg?) z*dOwG;XNMmPKUgG@Xm(3CAfFnmo9i;MQ-1b8*yy!Vfiv6o00z<)Mc<-ZN?e^9f z`4IUHlfJk4<6sTmy2gl$+{ObqW?y*CW3^bH$PcQ2F68a2Gjaj>tpE6R`*2-bk6zVO L(B==u&M*BR9MKYM literal 0 HcmV?d00001