initial import of first Haiku WiMAX USB driver for Beceem chipsets

- Based on GPL code in linux kernel staging
- Low level communications mostly done
- Probes GPIO pins and detects LEDs
- Sets device up and pushes firmware
- Detects MAC address
- blinks LED through a spawned thread based on driver state



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40302 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexander von Gluck IV
2011-01-27 23:31:50 +00:00
parent 0d6b3b20e1
commit 49b0cb3b8a
22 changed files with 5682 additions and 0 deletions
@@ -36,3 +36,5 @@ SubIncludeGPL HAIKU_TOP src add-ons kernel drivers network bcm570x ;
SubInclude HAIKU_TOP src add-ons kernel drivers network atheros813x ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wimax ;
@@ -0,0 +1,3 @@
SubDir HAIKU_TOP src add-ons kernel drivers network wimax ;
SubInclude HAIKU_TOP src add-ons kernel drivers network wimax usb_beceem ;
@@ -0,0 +1,156 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <[email protected]>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*
* Control the MIPS cpu within the Beceem chipset.
*
*/
#include "Settings.h"
#include "BeceemCPU.h"
#include "Driver.h"
BeceemCPU::BeceemCPU()
{
TRACE("Debug: Load CPU handler\n");
}
status_t
BeceemCPU::CPUInit(WIMAX_DEVICE* swmxdevice)
{
TRACE("Debug: Init CPU handler\n");
pwmxdevice = swmxdevice;
return B_OK;
}
status_t
BeceemCPU::CPURun()
{
unsigned int value = 0;
if (BizarroReadRegister(CLOCK_RESET_CNTRL_REG_1, sizeof(value), &value)
!= B_OK) {
TRACE_ALWAYS("Error: Read of clock reset reg failure\n");
return B_ERROR;
}
if (pwmxdevice->CPUFlashBoot) {
value&=(~(1<<30));
} else {
value |=(1<<30);
}
if (BizarroWriteRegister(CLOCK_RESET_CNTRL_REG_1, sizeof(value), &value)
!= B_OK) {
TRACE_ALWAYS("Error: Write of clock reset reg failure\n");
return B_ERROR;
}
return B_OK;
}
status_t
BeceemCPU::CPUReset()
{
status_t retval = B_OK;
unsigned int value = 0;
unsigned int uiResetValue = 0;
if (pwmxdevice->deviceChipID >= T3LPB)
{
BizarroReadRegister(SYS_CFG, sizeof(value), &value);
BizarroReadRegister(SYS_CFG, sizeof(value), &value);
// SYS_CFG register is write protected hence for modifying
// this reg value, it should be read twice before writing.
value = value | (pwmxdevice->syscfgBefFw & 0x00000060) ;
// making bit[6...5] same as was before f/w download. this
// setting forces the h/w to re-populated the SP RAM area
// with the string descriptor .
BizarroWriteRegister(SYS_CFG, sizeof(value), &value);
}
/* Reset the UMA-B Device */
if (pwmxdevice->deviceChipID >= T3LPB)
{
// TRACE("Debug: Resetting UMA-B\n");
// retval = usb_reset_device(psIntfAdapter->udev);
if (retval != B_OK)
{
TRACE_ALWAYS("Error: Reset failed\n");
goto err_exit;
}
if (pwmxdevice->deviceChipID == BCS220_2 ||
pwmxdevice->deviceChipID == BCS220_2BC ||
pwmxdevice->deviceChipID == BCS250_BC ||
pwmxdevice->deviceChipID == BCS220_3)
{
retval = BizarroReadRegister(HPM_CONFIG_LDO145,
sizeof(value), &value);
if ( retval < 0)
{
TRACE_ALWAYS("Error: read failed with status: %d\n", retval);
goto err_exit;
}
// setting 0th bit
value |= (1<<0);
retval = BizarroWriteRegister(HPM_CONFIG_LDO145,
sizeof(value), &value);
if ( retval < 0)
{
TRACE_ALWAYS("Error: write failed with status: %d\n", retval);
goto err_exit;
}
}
}
// TODO : ELSE OLDER CHIP ID's < T3LP see Misc.c:1048
if (pwmxdevice->CPUFlashBoot)
{
// In flash boot mode MIPS state register has reverse polarity.
// So just or with setting bit 30.
// Make the MIPS in Reset state.
BizarroReadRegister(CLOCK_RESET_CNTRL_REG_1, sizeof(uiResetValue),
&uiResetValue);
uiResetValue |=(1<<30);
BizarroWriteRegister(CLOCK_RESET_CNTRL_REG_1, sizeof(uiResetValue),
&uiResetValue);
}
if (pwmxdevice->deviceChipID >= T3LPB)
{
uiResetValue = 0;
// WA for SYSConfig Issue.
BizarroReadRegister(SYS_CFG, sizeof(uiResetValue), &uiResetValue);
if (uiResetValue & (1<<4))
{
uiResetValue = 0;
BizarroReadRegister(SYS_CFG, sizeof(uiResetValue), &uiResetValue);
// Read SYSCFG Twice to make it writable.
uiResetValue &= (~(1<<4));
BizarroWriteRegister(SYS_CFG, sizeof(uiResetValue), &uiResetValue);
}
}
uiResetValue = 0;
BizarroWriteRegister(0x0f01186c, sizeof(uiResetValue), &uiResetValue);
err_exit :
return retval;
}
@@ -0,0 +1,39 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <[email protected]>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*
* Description: Wrangle Beceem CPU control calls
*/
#define CLOCK_RESET_CNTRL_REG_1 0x0F00000C
#ifndef _USB_BECEEM_CPU_H_
#define _USB_BECEEM_CPU_H_
#include <ByteOrder.h>
#include "DeviceStruct.h"
class BeceemCPU
{
public:
BeceemCPU();
status_t CPUInit(WIMAX_DEVICE* swmxdevice);
status_t CPURun();
status_t CPUReset();
// yuck. These are in a parent class
virtual status_t ReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t WriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroWriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
private:
WIMAX_DEVICE* pwmxdevice;
};
#endif // _USB_BECEEM_CPU_H_
@@ -0,0 +1,411 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <[email protected]>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*
* Description: Wrangle Beceem volatile DDR memory.
*/
#include "Settings.h"
#include "BeceemDDR.h"
BeceemDDR::BeceemDDR()
{
TRACE("Debug: Load DDR handler\n");
}
status_t
BeceemDDR::DDRInit(WIMAX_DEVICE* swmxdevice)
{
pwmxdevice = swmxdevice;
PDDR_SETTING psDDRSetting=NULL;
unsigned int HostDrvrConfig6 = pwmxdevice->vendorcfg.HostDrvrConfig6;
unsigned int uiHostDrvrCfg6 = 0;
unsigned int ChipID = pwmxdevice->deviceChipID;
unsigned long RegCount=0;
unsigned long value = 0;
unsigned int uiResetValue = 0;
unsigned int uiClockSetting = 0;
int retval = B_OK;
unsigned int DDRSetting = 0;
bool PmuMode = 0;
bool MipsConfig = 0;
bool PLLConfig = 0;
HostDrvrConfig6 &= ~(htonl(1 << 15));
uiHostDrvrCfg6 = ntohl(HostDrvrConfig6);
DDRSetting = (ntohl(HostDrvrConfig6) >>8)&0x0F ;
PmuMode = (uiHostDrvrCfg6>>24)&0x03;
MipsConfig = (uiHostDrvrCfg6>>20)&0x01;
PLLConfig = (uiHostDrvrCfg6>>19)&0x01;
switch (ChipID)
{
case 0xbece3200:
switch (DDRSetting)
{
case DDR_80_MHZ:
psDDRSetting=asT3LP_DDRSetting80MHz;
RegCount=(sizeof(asT3LP_DDRSetting80MHz)/
sizeof(DDR_SETTING));
break;
case DDR_100_MHZ:
psDDRSetting=asT3LP_DDRSetting100MHz;
RegCount=(sizeof(asT3LP_DDRSetting100MHz)/
sizeof(DDR_SETTING));
break;
case DDR_133_MHZ:
psDDRSetting=asT3LP_DDRSetting133MHz;
RegCount=(sizeof(asT3LP_DDRSetting133MHz)/
sizeof(DDR_SETTING));
if(MipsConfig == MIPS_200_MHZ)
{
uiClockSetting = 0x03F13652;
}
else
{
uiClockSetting = 0x03F1365B;
}
break;
default:
return -EINVAL;
}
break;
case T3LPB:
case BCS220_2:
case BCS220_2BC:
case BCS250_BC:
case BCS220_3 :
// We need to check current value and additionally set bit 2 and
// bit 6 to 1 for BBIC 2mA drive
if( (ChipID != BCS220_2) &&
(ChipID != BCS220_2BC) &&
(ChipID != BCS220_3) )
{
retval= BizarroReadRegister((unsigned int)0x0f000830,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue |= 0x44;
retval = BizarroWriteRegister((unsigned int)0x0f000830,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
}
switch(DDRSetting)
{
case DDR_80_MHZ:
TRACE("Debug: DDR 80MHz\n");
psDDRSetting = asT3LPB_DDRSetting80MHz;
RegCount=(sizeof(asT3B_DDRSetting80MHz)/
sizeof(DDR_SETTING));
break;
case DDR_100_MHZ:
TRACE("Debug: DDR 100MHz\n");
psDDRSetting=asT3LPB_DDRSetting100MHz;
RegCount=(sizeof(asT3B_DDRSetting100MHz)/
sizeof(DDR_SETTING));
break;
case DDR_133_MHZ:
TRACE("Debug: DDR 133MHz\n");
psDDRSetting = asT3LPB_DDRSetting133MHz;
RegCount=(sizeof(asT3B_DDRSetting133MHz)/
sizeof(DDR_SETTING));
if(MipsConfig == MIPS_200_MHZ)
{
uiClockSetting = 0x03F13652;
}
else
{
uiClockSetting = 0x03F1365B;
}
break;
case DDR_160_MHZ:
TRACE("Debug: DDR 160MHz\n");
psDDRSetting = asT3LPB_DDRSetting160MHz;
RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(DDR_SETTING);
if(MipsConfig == MIPS_200_MHZ)
{
TRACE("Debug: MIPS 200Mhz\n");
uiClockSetting = 0x03F137D2;
}
else
{
uiClockSetting = 0x03F137DB;
}
}
break;
case 0xbece0110:
case 0xbece0120:
case 0xbece0121:
case 0xbece0130:
case 0xbece0300:
switch (DDRSetting)
{
case DDR_80_MHZ:
psDDRSetting = asT3_DDRSetting80MHz;
RegCount = (sizeof(asT3_DDRSetting80MHz)/
sizeof(DDR_SETTING));
break;
case DDR_100_MHZ:
psDDRSetting = asT3_DDRSetting100MHz;
RegCount = (sizeof(asT3_DDRSetting100MHz)/
sizeof(DDR_SETTING));
break;
case DDR_133_MHZ:
psDDRSetting = asT3_DDRSetting133MHz;
RegCount = (sizeof(asT3_DDRSetting133MHz)/
sizeof(DDR_SETTING));
break;
default:
return -EINVAL;
}
case 0xbece0310:
{
switch (DDRSetting)
{
case DDR_80_MHZ:
psDDRSetting = asT3B_DDRSetting80MHz;
RegCount=(sizeof(asT3B_DDRSetting80MHz)/
sizeof(DDR_SETTING));
break;
case DDR_100_MHZ:
psDDRSetting=asT3B_DDRSetting100MHz;
RegCount=(sizeof(asT3B_DDRSetting100MHz)/
sizeof(DDR_SETTING));
break;
case DDR_133_MHZ:
if(PLLConfig == PLL_266_MHZ)//266Mhz PLL selected.
{
memcpy(asT3B_DDRSetting133MHz, asDPLL_266MHZ,
sizeof(asDPLL_266MHZ));
psDDRSetting = asT3B_DDRSetting133MHz;
RegCount=(sizeof(asT3B_DDRSetting133MHz)/
sizeof(DDR_SETTING));
}
else
{
psDDRSetting = asT3B_DDRSetting133MHz;
RegCount=(sizeof(asT3B_DDRSetting133MHz)/
sizeof(DDR_SETTING));
if(MipsConfig == MIPS_200_MHZ)
{
uiClockSetting = 0x07F13652;
}
else
{
uiClockSetting = 0x07F1365B;
}
}
break;
default:
return -EINVAL;
}
break;
}
default:
return -EINVAL;
}
value=0;
TRACE("Debug: Register count is %lu\n", RegCount);
while(RegCount && !retval)
{
if(uiClockSetting && psDDRSetting->ulRegAddress == MIPS_CLOCK_REG)
{
value = uiClockSetting;
}
else
{
value = psDDRSetting->ulRegValue;
}
retval = BizarroWriteRegister(psDDRSetting->ulRegAddress,
sizeof(value), (unsigned int*)&value);
if(B_OK != retval) {
TRACE_ALWAYS(
"%s:%d BizarroWriteRegister failed at 0x%x on Register #%d.\n",
__FUNCTION__, __LINE__, psDDRSetting->ulRegAddress, RegCount);
break;
}
RegCount--;
psDDRSetting++;
}
if(ChipID >= 0xbece3300 )
{
snooze(3);
if( (ChipID != BCS220_2)&&
(ChipID != BCS220_2BC)&&
(ChipID != BCS220_3))
{
/* drive MDDR to half in case of UMA-B: */
uiResetValue = 0x01010001;
retval = BizarroWriteRegister((unsigned int)0x0F007018,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue = 0x00040020;
retval = BizarroWriteRegister((unsigned int)0x0F007094,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue = 0x01020101;
retval = BizarroWriteRegister((unsigned int)0x0F00701c,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue = 0x01010000;
retval = BizarroWriteRegister((unsigned int)0x0F007018,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
}
snooze(3);
/* DC/DC standby change...
* This is to be done only for Hybrid PMU mode.
* with the current h/w there is no way to detect this.
* and since we dont have internal PMU lets do it under
* UMA-B chip id. we will change this when we will have an
* internal PMU.
*/
if(PmuMode == HYBRID_MODE_7C)
{
TRACE("Debug: Hybrid Power Mode 7C\n");
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue = 0x1322a8;
retval = BizarroWriteRegister((unsigned int)0x0f000d1c,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue = 0x132296;
retval = BizarroWriteRegister((unsigned int)0x0f000d14,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
}
else if(PmuMode == HYBRID_MODE_6 )
{
TRACE("Debug: Hybrid Power Mode 6\n");
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue = 0x6003229a;
retval = BizarroWriteRegister((unsigned int)0x0f000d14,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
retval = BizarroReadRegister((unsigned int)0x0f000c00,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroReadRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
uiResetValue = 0x1322a8;
retval = BizarroWriteRegister((unsigned int)0x0f000d1c,
sizeof(uiResetValue), &uiResetValue);
if(retval < 0) {
TRACE_ALWAYS("%s:%d BizarroWriteRegister failed\n",
__FUNCTION__, __LINE__);
return retval;
}
}
}
return retval;
}
@@ -0,0 +1,852 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <[email protected]>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*
* Description: Wrangle Beceem volatile DDR memory.
*/
#ifndef _USB_BECEEM_DDR_H_
#define _USB_BECEEM_DDR_H_
#include <ByteOrder.h>
#include "DeviceStruct.h"
#define DDR_DUMP_INTERNAL_DEVICE_MEMORY 0xBFC02B00
#define MIPS_CLOCK_REG 0x0f000820
#define MIPS_200_MHZ 0
#define MIPS_160_MHZ 1
#define PLL_800_MHZ 0
#define PLL_266_MHZ 1
#define DDR_80_MHZ 0
#define DDR_100_MHZ 1
#define DDR_120_MHZ 2 // Additional Frequency for T3LP
#define DDR_133_MHZ 3
#define DDR_140_MHZ 4 // Not Used (Reserved for future)
#define DDR_160_MHZ 5 // Additional Frequency for T3LP
#define DDR_180_MHZ 6 // Not Used (Reserved for future)
#define DDR_200_MHZ 7 // Not Used (Reserved for future)
class BeceemDDR
{
public:
WIMAX_DEVICE* pwmxdevice;
BeceemDDR();
status_t DDRInit(WIMAX_DEVICE* swmxdevice);
// yuck. These are in a child class class
virtual status_t ReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t WriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroWriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
};
/*
* DDR Power modes
*/
typedef enum ePMU_MODES
{
HYBRID_MODE_7C = 0,
INTERNAL_MODE_6 = 1,
HYBRID_MODE_6 = 2
}PMU_MODE;
/*
* DDR Init maps, taken from Beceem GPL Linux Driver
*/
typedef struct _DDR_SETTING
{
unsigned long ulRegAddress;
unsigned long ulRegValue;
}DDR_SETTING, *PDDR_SETTING;
typedef DDR_SETTING DDR_SET_NODE, *PDDR_SET_NODE;
//DDR INIT-133Mhz
#define T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 12 //index for 0x0F007000
static DDR_SET_NODE asT3_DDRSetting133MHz[]= {// # DPLL Clock Setting
{0x0F000800,0x00007212},
{0x0f000820,0x07F13FFF},
{0x0f000810,0x00000F95},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
// Changed source for X-bar and MIPS clock to APLL
{0x0f000840,0x0FFF1B00},
{0x0f000870,0x00000002},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
{0x0F00a04C,0x0000000C},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001
{0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x02000007},
{0x0F007028,0x02020202},
{0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a
{0x0F007030,0x05000000},
{0x0F007034,0x00000003},
{0x0F007038,0x110a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200
{0x0F00703C,0x02101010},//ROB - 0x02101010,//0x02101018},
{0x0F007040,0x45751200},//ROB - 0x45751200,//0x450f1200},
{0x0F007044,0x110a0d00},//ROB - 0x110a0d00//0x111f0d00
{0x0F007048,0x081b0306},
{0x0F00704c,0x00000000},
{0x0F007050,0x0000001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x0010246c},
{0x0F007064,0x00000010},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00007000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
//# Enable BW improvement within memory controller
{0x0F007094,0x00000104},
//# Enable 2 ports within X-bar
{0x0F00A000,0x00000016},
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
//80Mhz
#define T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 10 //index for 0x0F007000
static DDR_SET_NODE asT3_DDRSetting80MHz[]= {// # DPLL Clock Setting
{0x0f000810,0x00000F95},
{0x0f000820,0x07f1ffff},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
{0x0F00a000,0x00000016},
{0x0F00a04C,0x0000000C},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01000000},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020000},
{0x0F007020,0x04020107},
{0x0F007024,0x00000007},
{0x0F007028,0x02020201},
{0x0F00702c,0x0204040a},
{0x0F007030,0x04000000},
{0x0F007034,0x00000002},
{0x0F007038,0x1F060200},
{0x0F00703C,0x1C22221F},
{0x0F007040,0x8A006600},
{0x0F007044,0x221a0800},
{0x0F007048,0x02690204},
{0x0F00704c,0x00000000},
{0x0F007050,0x0000001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x000A15D6},
{0x0F007064,0x0000000A},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00004000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
{0x0F007094,0x00000104},
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
//100Mhz
#define T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 13 //index for 0x0F007000
static DDR_SET_NODE asT3_DDRSetting100MHz[]= {// # DPLL Clock Setting
{0x0F000800,0x00007008},
{0x0f000810,0x00000F95},
{0x0f000820,0x07F13E3F},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
// Changed source for X-bar and MIPS clock to APLL
//0x0f000840,0x0FFF1800,
{0x0f000840,0x0FFF1B00},
{0x0f000870,0x00000002},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
{0x0F00a04C,0x0000000C},
//# Enable 2 ports within X-bar
{0x0F00A000,0x00000016},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020001}, // POP - 0x00020000 Normal 0x01020000
{0x0F007020,0x04020107},//Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x00000007},
{0x0F007028,0x01020201},
{0x0F00702c,0x0204040A},
{0x0F007030,0x06000000},
{0x0F007034,0x00000004},
{0x0F007038,0x20080200},
{0x0F00703C,0x02030320},
{0x0F007040,0x6E7F1200},
{0x0F007044,0x01190A00},
{0x0F007048,0x06120305},//0x02690204 // 0x06120305
{0x0F00704c,0x00000000},
{0x0F007050,0x0000001C},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x00082ED6},
{0x0F007064,0x0000000A},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00005000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
//# Enable BW improvement within memory controller
{0x0F007094,0x00000104},
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
//Net T3B DDR Settings
//DDR INIT-133Mhz
static DDR_SET_NODE asDPLL_266MHZ[] = {
{0x0F000800,0x00007212},
{0x0f000820,0x07F13FFF},
{0x0f000810,0x00000F95},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
// Changed source for X-bar and MIPS clock to APLL
{0x0f000840,0x0FFF1B00},
{0x0f000870,0x00000002}
};
#if 0
static DDR_SET_NODE asDPLL_800MHZ[] = {
{0x0f000810,0x00000F95},
{0x0f000810,0x00000F95},
{0x0f000810,0x00000F95},
{0x0f000820,0x03F1365B},
{0x0f000840,0x0FFF0000},
{0x0f000880,0x000003DD},
{0x0f000860,0x00000000}
};
#endif
#define T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 11 //index for 0x0F007000
static DDR_SET_NODE asT3B_DDRSetting133MHz[] = {// # DPLL Clock Setting
{0x0f000810,0x00000F95},
{0x0f000810,0x00000F95},
{0x0f000810,0x00000F95},
{0x0f000820,0x07F13652},
{0x0f000840,0x0FFF0800},
// Changed source for X-bar and MIPS clock to APLL
{0x0f000880,0x000003DD},
{0x0f000860,0x00000000},
// Changed source for X-bar and MIPS clock to APLL
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
//# Enable 2 ports within X-bar
{0x0F00A000,0x00000016},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001
{0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x02000007},
{0x0F007028,0x02020202},
{0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a
{0x0F007030,0x05000000},
{0x0F007034,0x00000003},
{0x0F007038,0x130a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200
{0x0F00703C,0x02101012},//ROB - 0x02101010,//0x02101018},
{0x0F007040,0x457D1200},//ROB - 0x45751200,//0x450f1200},
{0x0F007044,0x11130d00},//ROB - 0x110a0d00//0x111f0d00
{0x0F007048,0x040D0306},
{0x0F00704c,0x00000000},
{0x0F007050,0x0000001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x0010246c},
{0x0F007064,0x00000012},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00007000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
//# Enable BW improvement within memory controller
{0x0F007094,0x00000104},
//# Enable start bit within memory controller
{0x0F007018,0x01010000},
};
#define T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000
static DDR_SET_NODE asT3B_DDRSetting80MHz[] = {// # DPLL Clock Setting
{0x0f000810,0x00000F95},
{0x0f000820,0x07F13FFF},
{0x0f000840,0x0FFF1F00},
{0x0f000880,0x000003DD},
{0x0f000860,0x00000000},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
{0x0F00a000,0x00000016},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01000000},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020000},
{0x0F007020,0x04020107},
{0x0F007024,0x00000007},
{0x0F007028,0x02020201},
{0x0F00702c,0x0204040a},
{0x0F007030,0x04000000},
{0x0F007034,0x02000002},
{0x0F007038,0x1F060202},
{0x0F00703C,0x1C22221F},
{0x0F007040,0x8A006600},
{0x0F007044,0x221a0800},
{0x0F007048,0x02690204},
{0x0F00704c,0x00000000},
{0x0F007050,0x0100001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x000A15D6},
{0x0F007064,0x0000000A},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00004000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
{0x0F007094,0x00000104},
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
//100Mhz
#define T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 9 //index for 0x0F007000
static DDR_SET_NODE asT3B_DDRSetting100MHz[] = {// # DPLL Clock Setting
{0x0f000810,0x00000F95},
{0x0f000820,0x07F1369B},
{0x0f000840,0x0FFF0800},
{0x0f000880,0x000003DD},
{0x0f000860,0x00000000},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
//# Enable 2 ports within X-bar
{0x0F00A000,0x00000016},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020000}, // POP - 0x00020000 Normal 0x01020000
{0x0F007020,0x04020107},//Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x00000007},
{0x0F007028,0x01020201},
{0x0F00702c,0x0204040A},
{0x0F007030,0x06000000},
{0x0F007034,0x02000004},
{0x0F007038,0x20080200},
{0x0F00703C,0x02030320},
{0x0F007040,0x6E7F1200},
{0x0F007044,0x01190A00},
{0x0F007048,0x06120305},//0x02690204 // 0x06120305
{0x0F00704c,0x00000000},
{0x0F007050,0x0100001C},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x00082ED6},
{0x0F007064,0x0000000A},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00005000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
//# Enable BW improvement within memory controller
{0x0F007094,0x00000104},
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 9 //index for 0x0F007000
static DDR_SET_NODE asT3LP_DDRSetting133MHz[]= {// # DPLL Clock Setting
{0x0f000820,0x03F1365B},
{0x0f000810,0x00002F95},
{0x0f000880,0x000003DD},
// Changed source for X-bar and MIPS clock to APLL
{0x0f000840,0x0FFF0000},
{0x0f000860,0x00000000},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
{0x0F00A000,0x00000016},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001
{0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x02000007},
{0x0F007028,0x02020200},
{0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a
{0x0F007030,0x05000000},
{0x0F007034,0x00000003},
{0x0F007038,0x200a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200
{0x0F00703C,0x02101020},//ROB - 0x02101010,//0x02101018,
{0x0F007040,0x45711200},//ROB - 0x45751200,//0x450f1200,
{0x0F007044,0x110D0D00},//ROB - 0x110a0d00//0x111f0d00
{0x0F007048,0x04080306},
{0x0F00704c,0x00000000},
{0x0F007050,0x0100001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x0010245F},
{0x0F007064,0x00000010},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00007000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
{0x0F007088,0x01000001},
{0x0F00708c,0x00000101},
{0x0F007090,0x00000000},
//# Enable BW improvement within memory controller
{0x0F007094,0x00040000},
{0x0F007098,0x00000000},
{0x0F0070c8,0x00000104},
//# Enable 2 ports within X-bar
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 11 //index for 0x0F007000
static DDR_SET_NODE asT3LP_DDRSetting100MHz[]= {// # DPLL Clock Setting
{0x0f000810,0x00002F95},
{0x0f000820,0x03F1369B},
{0x0f000840,0x0fff0000},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
// Changed source for X-bar and MIPS clock to APLL
{0x0f000840,0x0FFF0000},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020000},// POP - 0x00020001 Normal 0x01020001
{0x0F007020,0x04020107}, //Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x00000007},
{0x0F007028,0x01020200},
{0x0F00702c,0x0204040a},//ROB- 0x0205050a,//0x0206060a
{0x0F007030,0x06000000},
{0x0F007034,0x00000004},
{0x0F007038,0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200
{0x0F00703C,0x0203031F},//ROB - 0x02101010,//0x02101018,
{0x0F007040,0x6e001200},//ROB - 0x45751200,//0x450f1200,
{0x0F007044,0x011a0a00},//ROB - 0x110a0d00//0x111f0d00
{0x0F007048,0x03000305},
{0x0F00704c,0x00000000},
{0x0F007050,0x0100001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x00082ED6},
{0x0F007064,0x0000000A},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00005000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
{0x0F007088,0x01000001},
{0x0F00708c,0x00000101},
{0x0F007090,0x00000000},
{0x0F007094,0x00010000},
{0x0F007098,0x00000000},
{0x0F0070C8,0x00000104},
//# Enable 2 ports within X-bar
{0x0F00A000,0x00000016},
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000
static DDR_SET_NODE asT3LP_DDRSetting80MHz[]= {// # DPLL Clock Setting
{0x0f000820,0x07F13FFF},
{0x0f000810,0x00002F95},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
{0x0f000840,0x0FFF1F00},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0F00a084,0x1Cffffff},
{0x0F00a080,0x1C000000},
{0x0F00A000,0x00000016},
{0x0f007000,0x00010001},
{0x0f007004,0x01000000},
{0x0f007008,0x01000001},
{0x0f00700c,0x00000000},
{0x0f007010,0x01000000},
{0x0f007014,0x01000100},
{0x0f007018,0x01000000},
{0x0f00701c,0x01020000},
{0x0f007020,0x04020107},
{0x0f007024,0x00000007},
{0x0f007028,0x02020200},
{0x0f00702c,0x0204040a},
{0x0f007030,0x04000000},
{0x0f007034,0x00000002},
{0x0f007038,0x1d060200},
{0x0f00703c,0x1c22221d},
{0x0f007040,0x8A116600},
{0x0f007044,0x222d0800},
{0x0f007048,0x02690204},
{0x0f00704c,0x00000000},
{0x0f007050,0x0100001c},
{0x0f007054,0x00000000},
{0x0f007058,0x00000000},
{0x0f00705c,0x00000000},
{0x0f007060,0x000A15D6},
{0x0f007064,0x0000000A},
{0x0f007068,0x00000000},
{0x0f00706c,0x00000001},
{0x0f007070,0x00004000},
{0x0f007074,0x00000000},
{0x0f007078,0x00000000},
{0x0f00707c,0x00000000},
{0x0f007080,0x00000000},
{0x0f007084,0x00000000},
{0x0f007088,0x01000001},
{0x0f00708c,0x00000101},
{0x0f007090,0x00000000},
{0x0f007094,0x00010000},
{0x0f007098,0x00000000},
{0x0F0070C8,0x00000104},
{0x0F007018,0x01010000}
};
///T3 LP-B (UMA-B)
#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ 7 //index for 0x0F007000
static DDR_SET_NODE asT3LPB_DDRSetting160MHz[]= {// # DPLL Clock Setting
{0x0f000820,0x03F137DB},
{0x0f000810,0x01842795},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
{0x0f000840,0x0FFF0400},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0f003050,0x00000021},//this is flash/eeprom clock divisor which set the flash clock to 20 MHz
{0x0F00a084,0x1Cffffff},//Now dump from her in internal memory
{0x0F00a080,0x1C000000},
{0x0F00A000,0x00000016},
{0x0f007000,0x00010001},
{0x0f007004,0x01000001},
{0x0f007008,0x01000101},
{0x0f00700c,0x00000000},
{0x0f007010,0x01000100},
{0x0f007014,0x01000100},
{0x0f007018,0x01000000},
{0x0f00701c,0x01020000},
{0x0f007020,0x04030107},
{0x0f007024,0x02000007},
{0x0f007028,0x02020200},
{0x0f00702c,0x0206060a},
{0x0f007030,0x050d0d00},
{0x0f007034,0x00000003},
{0x0f007038,0x170a0200},
{0x0f00703c,0x02101012},
{0x0f007040,0x45161200},
{0x0f007044,0x11250c00},
{0x0f007048,0x04da0307},
{0x0f00704c,0x00000000},
{0x0f007050,0x0000001c},
{0x0f007054,0x00000000},
{0x0f007058,0x00000000},
{0x0f00705c,0x00000000},
{0x0f007060,0x00142bb6},
{0x0f007064,0x20430014},
{0x0f007068,0x00000000},
{0x0f00706c,0x00000001},
{0x0f007070,0x00009000},
{0x0f007074,0x00000000},
{0x0f007078,0x00000000},
{0x0f00707c,0x00000000},
{0x0f007080,0x00000000},
{0x0f007084,0x00000000},
{0x0f007088,0x01000001},
{0x0f00708c,0x00000101},
{0x0f007090,0x00000000},
{0x0f007094,0x00040000},
{0x0f007098,0x00000000},
{0x0F0070C8,0x00000104},
{0x0F007018,0x01010000}
};
#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 7 //index for 0x0F007000
static DDR_SET_NODE asT3LPB_DDRSetting133MHz[]= {// # DPLL Clock Setting
{0x0f000820,0x03F1365B},
{0x0f000810,0x00002F95},
{0x0f000880,0x000003DD},
// Changed source for X-bar and MIPS clock to APLL
{0x0f000840,0x0FFF0000},
{0x0f000860,0x00000000},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz
{0x0F00a084,0x1Cffffff},//dump from here in internal memory
{0x0F00a080,0x1C000000},
{0x0F00A000,0x00000016},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001
{0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x02000007},
{0x0F007028,0x02020200},
{0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a
{0x0F007030,0x05000000},
{0x0F007034,0x00000003},
{0x0F007038,0x190a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200
{0x0F00703C,0x02101017},//ROB - 0x02101010,//0x02101018,
{0x0F007040,0x45171200},//ROB - 0x45751200,//0x450f1200,
{0x0F007044,0x11290D00},//ROB - 0x110a0d00//0x111f0d00
{0x0F007048,0x04080306},
{0x0F00704c,0x00000000},
{0x0F007050,0x0100001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x0010245F},
{0x0F007064,0x00000010},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00007000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
{0x0F007088,0x01000001},
{0x0F00708c,0x00000101},
{0x0F007090,0x00000000},
//# Enable BW improvement within memory controller
{0x0F007094,0x00040000},
{0x0F007098,0x00000000},
{0x0F0070c8,0x00000104},
//# Enable 2 ports within X-bar
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 8 //index for 0x0F007000
static DDR_SET_NODE asT3LPB_DDRSetting100MHz[]= {// # DPLL Clock Setting
{0x0f000810,0x00002F95},
{0x0f000820,0x03F1369B},
{0x0f000840,0x0fff0000},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
// Changed source for X-bar and MIPS clock to APLL
{0x0f000840,0x0FFF0000},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz
{0x0F00a084,0x1Cffffff}, //dump from here in internal memory
{0x0F00a080,0x1C000000},
//Memcontroller Default values
{0x0F007000,0x00010001},
{0x0F007004,0x01010100},
{0x0F007008,0x01000001},
{0x0F00700c,0x00000000},
{0x0F007010,0x01000000},
{0x0F007014,0x01000100},
{0x0F007018,0x01000000},
{0x0F00701c,0x01020000},// POP - 0x00020001 Normal 0x01020001
{0x0F007020,0x04020107}, //Normal - 0x04030107 POP - 0x05030107
{0x0F007024,0x00000007},
{0x0F007028,0x01020200},
{0x0F00702c,0x0204040a},//ROB- 0x0205050a,//0x0206060a
{0x0F007030,0x06000000},
{0x0F007034,0x00000004},
{0x0F007038,0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200
{0x0F00703C,0x0203031F},//ROB - 0x02101010,//0x02101018,
{0x0F007040,0x6e001200},//ROB - 0x45751200,//0x450f1200,
{0x0F007044,0x011a0a00},//ROB - 0x110a0d00//0x111f0d00
{0x0F007048,0x03000305},
{0x0F00704c,0x00000000},
{0x0F007050,0x0100001c},
{0x0F007054,0x00000000},
{0x0F007058,0x00000000},
{0x0F00705c,0x00000000},
{0x0F007060,0x00082ED6},
{0x0F007064,0x0000000A},
{0x0F007068,0x00000000},
{0x0F00706c,0x00000001},
{0x0F007070,0x00005000},
{0x0F007074,0x00000000},
{0x0F007078,0x00000000},
{0x0F00707C,0x00000000},
{0x0F007080,0x00000000},
{0x0F007084,0x00000000},
{0x0F007088,0x01000001},
{0x0F00708c,0x00000101},
{0x0F007090,0x00000000},
{0x0F007094,0x00010000},
{0x0F007098,0x00000000},
{0x0F0070C8,0x00000104},
//# Enable 2 ports within X-bar
{0x0F00A000,0x00000016},
//# Enable start bit within memory controller
{0x0F007018,0x01010000}
};
#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 7 //index for 0x0F007000
static DDR_SET_NODE asT3LPB_DDRSetting80MHz[]= {// # DPLL Clock Setting
{0x0f000820,0x07F13FFF},
{0x0f000810,0x00002F95},
{0x0f000860,0x00000000},
{0x0f000880,0x000003DD},
{0x0f000840,0x0FFF1F00},
{0x0F00a044,0x1fffffff},
{0x0F00a040,0x1f000000},
{0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz
{0x0F00a084,0x1Cffffff},// dump from here in internal memory
{0x0F00a080,0x1C000000},
{0x0F00A000,0x00000016},
{0x0f007000,0x00010001},
{0x0f007004,0x01000000},
{0x0f007008,0x01000001},
{0x0f00700c,0x00000000},
{0x0f007010,0x01000000},
{0x0f007014,0x01000100},
{0x0f007018,0x01000000},
{0x0f00701c,0x01020000},
{0x0f007020,0x04020107},
{0x0f007024,0x00000007},
{0x0f007028,0x02020200},
{0x0f00702c,0x0204040a},
{0x0f007030,0x04000000},
{0x0f007034,0x00000002},
{0x0f007038,0x1d060200},
{0x0f00703c,0x1c22221d},
{0x0f007040,0x8A116600},
{0x0f007044,0x222d0800},
{0x0f007048,0x02690204},
{0x0f00704c,0x00000000},
{0x0f007050,0x0100001c},
{0x0f007054,0x00000000},
{0x0f007058,0x00000000},
{0x0f00705c,0x00000000},
{0x0f007060,0x000A15D6},
{0x0f007064,0x0000000A},
{0x0f007068,0x00000000},
{0x0f00706c,0x00000001},
{0x0f007070,0x00004000},
{0x0f007074,0x00000000},
{0x0f007078,0x00000000},
{0x0f00707c,0x00000000},
{0x0f007080,0x00000000},
{0x0f007084,0x00000000},
{0x0f007088,0x01000001},
{0x0f00708c,0x00000101},
{0x0f007090,0x00000000},
{0x0f007094,0x00010000},
{0x0f007098,0x00000000},
{0x0F0070C8,0x00000104},
{0x0F007018,0x01010000}
};
#endif // _USB_BECEEM_DDR_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,132 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*
* Description: Wrangle Beceem wimax usb device
*/
#ifndef _USB_BECEEM_DEVICE_H_
#define _USB_BECEEM_DEVICE_H_
#include <net/if_media.h>
#include <sys/ioctl.h>
#include "BeceemNVM.h"
#include "BeceemDDR.h"
#include "BeceemCPU.h"
#include "BeceemLED.h"
#include "Driver.h"
#include "DeviceStruct.h"
#define MAX_USB_IO_RETRIES 1
#define MAX_USB_TRANSFER 255
class BeceemDevice
:
public BeceemNVM,
public BeceemDDR,
public BeceemCPU,
public BeceemLED
{
public:
BeceemDevice(usb_device device, const char *description);
virtual ~BeceemDevice();
status_t InitCheck() { return fStatus; };
status_t Open(uint32 flags);
bool IsOpen() { return fOpen; };
status_t Close();
status_t Free();
status_t Read(uint8 *buffer, size_t *numBytes);
status_t Write(const uint8 *buffer, size_t *numBytes);
status_t Control(uint32 op, void *buffer, size_t length);
status_t LoadConfig();
status_t PushConfig(unsigned int loc);
status_t PushFirmware(unsigned int loc);
void Removed();
status_t CompareAndReattach(usb_device device);
virtual status_t SetupDevice(bool deviceReplugged);
status_t ReadRegister(unsigned int reg, size_t size, uint32_t* buffer);
status_t WriteRegister(unsigned int reg, size_t size, uint32_t* buffer);
status_t BizarroReadRegister(unsigned int reg, size_t size, uint32_t* buffer);
status_t BizarroWriteRegister(unsigned int reg, size_t size, uint32_t* buffer);
private:
static void _ReadCallback(void *cookie, int32 status,
void *data, uint32 actualLength);
static void _WriteCallback(void *cookie, int32 status,
void *data, uint32 actualLength);
static void _NotifyCallback(void *cookie, int32 status,
void *data, uint32 actualLength);
status_t _SetupEndpoints();
status_t IdentifyChipset();
static const int kFrameSize = 1518;
static const uint8 kRXHeaderSize = 3;
static const uint8 kTXHeaderSize = 2;
protected:
/* overrides */
virtual status_t StartDevice() ;
virtual status_t StopDevice();
virtual status_t OnNotify(uint32 actualLength) ;
virtual status_t GetLinkState(ether_link_state *state) ;
virtual status_t SetPromiscuousMode(bool bOn);
virtual status_t ModifyMulticastTable(bool add, uint8 address);
// state tracking
status_t fStatus;
bool fOpen;
vint32 fInsideNotify;
usb_device fDevice;
uint16 fVendorID;
uint16 fProductID;
const char * fDescription;
bool fNonBlocking;
// Our driver device struct
struct WIMAX_DEVICE *pwmxdevice;
// pipes for notifications and data io
usb_pipe fNotifyEndpoint;
usb_pipe fReadEndpoint;
usb_pipe fWriteEndpoint;
// data stores for async usb transfers
uint32 fActualLengthRead;
uint32 fActualLengthWrite;
int32 fStatusRead;
int32 fStatusWrite;
sem_id fNotifyReadSem;
sem_id fNotifyWriteSem;
uint8 * fNotifyBuffer;
uint32 fNotifyBufferLength;
// connection data
sem_id fLinkStateChangeSem;
ether_address_t fMACAddress;
bool fHasConnection;
bool fTXBufferFull;
};
#endif //_USB_BECEEM_DEVICE_H_
@@ -0,0 +1,344 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*
* Beceem devices use fairly complex GPIO registers to control the
* device LED(s). As each implimentation uses the LEDs differently,
* each vendor provides a binary target configuration telling the
* driver what GPIO led register is used for what device state.
*/
#include "Settings.h"
#include "BeceemLED.h"
BeceemLED::BeceemLED()
{
TRACE("Debug: Load LED handler\n");
}
status_t
BeceemLED::LEDInit(WIMAX_DEVICE* wmxdevice)
{
pwmxdevice = wmxdevice;
uint8_t GPIO_Array[NUM_OF_LEDS+1];
unsigned char ucIndex = 0;
uint32_t uiIndex = 0;
unsigned char* puCFGData = NULL;
unsigned char bData = 0;
memset(GPIO_Array, GPIO_DISABLE_VAL, NUM_OF_LEDS+1);
TRACE("Debug: Raw GPIO information: 0x%x\n", pwmxdevice->gpioInfo);
snooze(500000);
if (pwmxdevice->deviceChipID == 0xbece0120
|| pwmxdevice->deviceChipID == 0xbece0121)
{
/*Hardcode the values of GPIO numbers for ASIC board.*/
GPIO_Array[RED_LED] = 2;
GPIO_Array[BLUE_LED] = 3;
GPIO_Array[YELLOW_LED] = GPIO_DISABLE_VAL;
GPIO_Array[GREEN_LED] = 4;
} else {
// for all possible GPIO pins...
for (ucIndex = 0; ucIndex < 32; ucIndex++)
{
switch(pwmxdevice->gpioInfo[ucIndex])
{
case RED_LED:
TRACE("Debug: GPIO: %d found RED_LED!\n", ucIndex);
GPIO_Array[RED_LED] = ucIndex;
pwmxdevice->gpioBitMap |= (1<<ucIndex);
break;
case BLUE_LED:
TRACE("Debug: GPIO: %d found BLUE_LED!\n", ucIndex);
GPIO_Array[BLUE_LED] = ucIndex;
pwmxdevice->gpioBitMap |= (1<<ucIndex);
break;
case YELLOW_LED:
TRACE("Debug: GPIO: %d found YELLOW_LED!\n", ucIndex);
GPIO_Array[YELLOW_LED] = ucIndex;
pwmxdevice->gpioBitMap |= (1<<ucIndex);
break;
case GREEN_LED:
TRACE("Debug: GPIO: %d found GREEN_LED!\n", ucIndex);
GPIO_Array[GREEN_LED] = ucIndex;
pwmxdevice->gpioBitMap |= (1<<ucIndex);
break;
default:
// TRACE("Debug: GPIO: %d found NO_LED!\n", ucIndex);
break;
}
}
}
TRACE("Debug: GPIO's bitmap correspond to LED :0x%X\n",
pwmxdevice->gpioBitMap);
// Load GPIO configuration data from vendor config
puCFGData = (unsigned char *)&pwmxdevice->vendorcfg.HostDrvrConfig1;
for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
{
bData = *puCFGData;
// Check Bit 8 for polarity. If it is set, polarity is reverse
if (bData & 0x80)
{
pwmxdevice->LEDMap.LEDState[uiIndex].BitPolarity = 0;
// unset bit 8
bData = bData & 0x7f;
} else {
// If polarity is not reverse, set to normal state.
pwmxdevice->LEDMap.LEDState[uiIndex].BitPolarity = 1;
}
pwmxdevice->LEDMap.LEDState[uiIndex].LED_Type = ( bData );
if (bData <= NUM_OF_LEDS)
pwmxdevice->LEDMap.LEDState[uiIndex].GPIO_Num = GPIO_Array[bData];
else
pwmxdevice->LEDMap.LEDState[uiIndex].GPIO_Num = GPIO_DISABLE_VAL;
puCFGData++;
bData = *puCFGData;
pwmxdevice->LEDMap.LEDState[uiIndex].LED_On_State = bData;
puCFGData++;
bData = *puCFGData;
pwmxdevice->LEDMap.LEDState[uiIndex].LED_Blink_State = bData;
puCFGData++;
}
GPIOReset(); // Set all GPIO pins to off
for (uiIndex = 0; uiIndex<NUM_OF_LEDS; uiIndex++)
{
if (pwmxdevice->LEDMap.LEDState[uiIndex].GPIO_Num != GPIO_DISABLE_VAL) {
LEDOn(uiIndex);
TRACE("Debug: LED[%d].LED_Type = %x\n",
uiIndex, pwmxdevice->LEDMap.LEDState[uiIndex].LED_Type);
TRACE("Debug: LED[%d].LED_On_State = %x\n",
uiIndex, pwmxdevice->LEDMap.LEDState[uiIndex].LED_On_State);
TRACE("Debug: LED[%d].LED_Blink_State = %x\n",
uiIndex, pwmxdevice->LEDMap.LEDState[uiIndex].LED_Blink_State);
TRACE("Debug: LED[%d].GPIO_Num = %i\n",
uiIndex, pwmxdevice->LEDMap.LEDState[uiIndex].GPIO_Num);
TRACE("Debug: LED[%d].Polarity = %d\n",
uiIndex, pwmxdevice->LEDMap.LEDState[uiIndex].BitPolarity);
snooze(500000);
LEDOff(uiIndex);
}
}
// Spawn LED monitor / blink thread
pwmxdevice->LEDThreadID = spawn_kernel_thread(LEDThread,
"usb_beceemwmx GPIO:LED",
B_NORMAL_PRIORITY, this);
if (pwmxdevice->LEDThreadID < 1) {
TRACE("Error: Problem spawning LED Thread: %i\n", pwmxdevice->LEDThreadID);
return B_ERROR;
}
resume_thread(pwmxdevice->LEDThreadID);
TRACE("Debug: LED Thread spawned: %i\n", pwmxdevice->LEDThreadID);
return B_OK;
}
status_t
BeceemLED::GPIOReset()
{
int index = 0;
TRACE("Debug: GPIO reset called\n");
for (index = 0; index < NUM_OF_LEDS; index++) {
if (pwmxdevice->LEDMap.LEDState[index].GPIO_Num != GPIO_DISABLE_VAL)
LEDOff(index);
}
return B_OK;
}
status_t
BeceemLED::LEDThreadTerminate()
{
status_t thread_return_value;
TRACE("Debug: Terminating LED thread PID %i\n", pwmxdevice->LEDThreadID);
// Lets make sure driverHalt is true... if it is false this will
// wait forever.
if (!pwmxdevice->driverHalt) {
TRACE_ALWAYS("Wierd... driver is not halted. Halting\n");
pwmxdevice->driverHalt = true;
}
return wait_for_thread(pwmxdevice->LEDThreadID, &thread_return_value);
}
status_t
BeceemLED::LightsOut()
{
unsigned int uiIndex = 0;
for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
{
if (pwmxdevice->LEDMap.LEDState[uiIndex].GPIO_Num != GPIO_DISABLE_VAL) {
LEDOff(uiIndex);
}
}
return B_OK;
}
status_t
BeceemLED::LEDOn(unsigned int index)
{
status_t result;
uint32_t gpio_towrite = 0;
uint32_t uiResetValue = 0;
gpio_towrite = 1<<pwmxdevice->LEDMap.LEDState[index].GPIO_Num;
if (pwmxdevice->LEDMap.LEDState[index].BitPolarity == 0)
result = BizarroWriteRegister(GPIO_OUTPUT_SET_REG,
sizeof(gpio_towrite), &gpio_towrite);
else
result = BizarroWriteRegister(GPIO_OUTPUT_CLR_REG,
sizeof(gpio_towrite), &gpio_towrite);
if (result != B_OK) {
TRACE_ALWAYS("Error: Problem setting LED(%d) at GPIO 0x%x (bit %d)\n",
index, gpio_towrite, pwmxdevice->LEDMap.LEDState[index].GPIO_Num);
}
uiResetValue = BizarroReadRegister(GPIO_MODE_REGISTER,
sizeof(uiResetValue), &uiResetValue);
uiResetValue |= gpio_towrite;
BizarroWriteRegister(GPIO_MODE_REGISTER, sizeof(uiResetValue), &uiResetValue);
return B_OK;
}
status_t
BeceemLED::LEDOff(unsigned int index)
{
status_t result;
uint32_t gpio_towrite = 0;
uint32_t uiResetValue = 0;
gpio_towrite = 1<<pwmxdevice->LEDMap.LEDState[index].GPIO_Num;
if (pwmxdevice->LEDMap.LEDState[index].BitPolarity == 0)
result = BizarroWriteRegister(GPIO_OUTPUT_CLR_REG,
sizeof(gpio_towrite), &gpio_towrite);
else
result = BizarroWriteRegister(GPIO_OUTPUT_SET_REG,
sizeof(gpio_towrite), &gpio_towrite);
if (result != B_OK) {
TRACE_ALWAYS("Error: Problem setting LED(%d) at GPIO 0x%x (bit %d)\n",
index, gpio_towrite, pwmxdevice->LEDMap.LEDState[index].GPIO_Num);
}
uiResetValue = BizarroReadRegister(GPIO_MODE_REGISTER,
sizeof(uiResetValue), &uiResetValue);
uiResetValue |= gpio_towrite;
BizarroWriteRegister(GPIO_MODE_REGISTER,
sizeof(uiResetValue), &uiResetValue);
return B_OK;
}
status_t
BeceemLED::LEDThread(void *cookie)
{
bool LEDisON = false;
BeceemLED *led = (BeceemLED *)cookie;
// While the driver is active
while (!led->pwmxdevice->driverHalt)
{
unsigned int uiIndex = 0;
unsigned int uiLedIndex = 0;
bool blink = false;
// LED state changes will be at least 500ms apart
snooze(500000);
// determine what the LED is doing in each state
switch(led->pwmxdevice->driverState)
{
case STATE_FWPUSH:
for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
{
if (led->pwmxdevice->LEDMap.LEDState[uiIndex].LED_Blink_State
& STATE_FWPUSH)
{
if (led->pwmxdevice->LEDMap.LEDState[uiIndex].GPIO_Num
!= GPIO_DISABLE_VAL) {
uiLedIndex = uiIndex;
}
}
}
blink = true;
break;
case STATE_NONET:
for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
{
if (led->pwmxdevice->LEDMap.LEDState[uiIndex].LED_On_State
& STATE_NONET)
{
if (led->pwmxdevice->LEDMap.LEDState[uiIndex].GPIO_Num
!= GPIO_DISABLE_VAL) {
uiLedIndex = uiIndex;
}
}
}
blink = false;
break;
default:
blink = false;
break;
}
TRACE("Debug: Detected to use LedIndex: 0x%x for driver state 0x%x\n",
uiLedIndex, led->pwmxdevice->driverState);
if (blink == true) {
led->LEDOff(uiLedIndex);
LEDisON = false;
snooze(500000);
led->LEDOn(uiLedIndex);
LEDisON = true;
} else {
// else we just flip on the color it needs to be.
led->LEDOn(uiLedIndex);
LEDisON = true;
snooze(500000);
}
}
return(B_OK);
}
@@ -0,0 +1,48 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*/
#ifndef _USB_BECEEM_LED_H_
#define _USB_BECEEM_LED_H_
#include <ByteOrder.h>
#include "DeviceStruct.h"
class BeceemLED
{
public:
BeceemLED();
status_t LEDInit(WIMAX_DEVICE* wmxdevice);
status_t LEDThreadTerminate();
status_t LEDOff(unsigned int index);
status_t LEDOn(unsigned int index);
status_t LightsOut();
static status_t LEDThread(void *cookie);
WIMAX_DEVICE* pwmxdevice;
// yuck. These are in a parent class
virtual status_t ReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t WriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroWriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
private:
status_t GPIOReset();
};
typedef enum _LEDColors{
RED_LED = 1,
BLUE_LED = 2,
YELLOW_LED = 3,
GREEN_LED = 4
} LEDColors; /*Enumerated values of different LED types*/
#endif // _USB_BECEEM_LED_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,119 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*/
#ifndef _USB_BECEEM_NVM_H_
#define _USB_BECEEM_NVM_H_
#include <ByteOrder.h>
#include <ether_driver.h>
#include "util.h"
#include "DeviceStruct.h"
#define BECM ntohl(0x4245434d)
#define MAC_ADDR_OFFSET 0x200
#define SPI_FLUSH_REG 0x0F00304C
// Our Flash addresses
#define FLASH_PART_SIZE (16 * 1024 * 1024)
#define FLASH_CONFIG_REG 0xAF003050
#define FLASH_GPIO_CONFIG_REG 0xAF000030
#define FLASH_CS_INFO_START_ADDR 0xFF0000 // Location for Flash calibration info
#define FLASH_AUTO_INIT_BASE_ADDR 0xF00000
#define FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT 0x1F000000 // Flash base before DDR Init
#define FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT 0x1C000000 // Flash base after DDR Init
#define FLASH_SPI_CMDQ_REG 0xAF003040
#define FLASH_SPI_WRITEQ_REG 0xAF003044
#define FLASH_SPI_READQ_REG 0xAF003048
#define FLASH_SIZE_ADDR 0xFFFFEC // Location of Flash memory size
#define FLASH_CMD_STATUS_REG_WRITE 0x01
#define FLASH_CMD_STATUS_REG_READ 0x05
#define FLASH_CMD_WRITE_ENABLE 0x06
#define FLASH_CMD_READ_ID 0x9F // Command to read the flash chip ID
#define FLASH_CS_SIGNATURE 0xBECEF1A5 // Beceem FLAS(H) (get it?)
// Our EEPROM addresses
#define EEPROM_SPI_Q_STATUS_REG 0x0F003008
#define EEPROM_CMDQ_SPI_REG 0x0F003018
#define EEPROM_READ_DATAQ_REG 0x0F003020
#define RESET_CHIP_SELECT -1
#define MAX_RW_SIZE 0x10 // bytes
#define MAX_NVM_SIZE (8*1024)
// Different models have different storage devices (sigh)
#define NVM_UNKNOWN 0
#define NVM_EEPROM 1
#define NVM_FLASH 2
#define NVM_VERSION_OFFSET 0x020E
#define NVM_SECTOR_SIZE 0x10000
#define NVM_READ_DATA_AVAIL 0x00000020 // was EEPROM_READ_DATA_AVAIL
#define NVM_SPI_Q_STATUS1_REG 0x0F003004 // was EEPROM_SPI_Q_STATUS1_REG
#define NVM_ALL_QUEUE_FLUSH 0x0000000f // was EEPROM_ALL_QUEUE_FLUSH
#define SCSI_FIRMWARE_MINOR_VERSION 0x5
#ifndef MIN
#define MIN(_a, _b) ((_a) < (_b)? (_a): (_b))
#endif
#define MAJOR_VERSION(x) (x & 0xFFFF)
#define MINOR_VERSION(x) ((x >>16) & 0xFFFF)
class BeceemNVM
{
int bSelectedChip; // selected chip
public:
BeceemNVM();
status_t NVMInit(WIMAX_DEVICE* swmxdevice);
status_t ReadMACFromNVM(ether_address *address);
status_t ValidateDSD(unsigned long hwParam);
int NVMRead(unsigned int offset, unsigned int size, unsigned int* buffer);
int NVMWrite(unsigned int offset, unsigned int size, unsigned int* buffer);
// yuck. These are in a child class class
virtual status_t ReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t WriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroReadRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
virtual status_t BizarroWriteRegister(unsigned int reg, size_t size, uint32_t* buffer){ return NULL; };
private:
WIMAX_DEVICE* pwmxdevice;
status_t NVMDetect();
status_t NVMFlush();
status_t NVMChipSelect(unsigned int offset);
status_t RestoreBlockProtect(unsigned long writestatus);
unsigned long DisableBlockProtect(unsigned int offset, size_t size);
int FlashGetBaseAddr();
unsigned long FlashReadID();
status_t FlashReadCS();
status_t FlashSectorErase(unsigned int addr, unsigned int numOfSectors);
status_t FlashBulkRead(unsigned int offset, unsigned int size, unsigned int* buffer);
status_t FlashBulkWrite(unsigned int offset, unsigned int size, unsigned int* buffer);
status_t FlashCSFlip(PFLASH_CS_INFO FlashCSInfo);
status_t FlashCSDump(PFLASH_CS_INFO FlashCSInfo);
unsigned int EEPROMGetSize();
unsigned int FlashGetSize();
status_t EEPROMRead(unsigned int offset, unsigned int *pdwData);
status_t EEPROMBulkRead( unsigned int offset, size_t numBytes, unsigned int* buffer);
};
#endif // _USB_BECEEM_NVM_H
@@ -0,0 +1,517 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Based on GPL code developed by: Beceem Communications Pvt. Ltd
*/
#ifndef _USB_BECEEM_DEVICE_STRUCT_
#define _USB_BECEEM_DEVICE_STRUCT_
#include "Driver.h"
typedef struct FirmwareInfo
{
void* pvMappedFirmwareAddress;
unsigned long u32FirmwareLength;
unsigned long u32StartingAddress;
}__attribute__((packed)) FIRMWARE_INFO, *PFIRMWARE_INFO;
/* WARNING: DO NOT edit this struct
* This struct is size / location dependant to vendor conf
*/
typedef struct _VENDORCFG
{
/*
Vendor Configuration Versions -- Beceem Internal
Clear drivers use version 26
# Version 1 - Creation
# Version 2 - Major revision - Created the current structure
# Version 3 - Renaming to HARQ structure to 'General'. HARQ will be
# reintroduced later.
# Version 4 - Added enabling of Tx Power Report from config file
# Version 5 - Added enabling of Random FA selection
# Version 7 - Added the firmware config option
# Version 8 - Added the config option for 8.75 or 10 MHz bandwidth
# Version 9 - Added the config option for ShutDown Timer
# - Removed changes in Version 8
# Version 10 - Merged versions 8 and 9
# Version 11 - EncrSupport & NumOfSAId added
# Version 12 - Radio and PHY Parameters added
# Version 13 - options for testing cqich, rang etc
# Version 14 - NA
# Version 15 - Added Max MAC Data per Frame to be sent in REG-REQ
# Version 16 - Added flags to enable Corrigendum 2
# Version 17 - IDLE Reserved1 field is changed to idle mode option.
# 0 means normal, 1 for CPE special Idle mode
# Version 18 - Changes to Radio Parameter, high band support added
# Version 19 - Changed Idlemode Enable to powersaving modes enable for Sleep
# - Changed Idlemode options to powersaving mode enable for Sleep
# Version 20 - Changed Rtps Enable to Minimum Grant size, nRtps Enable to
# Maximum Grant size, PC reserved 4 to MimoEnabled
# Version 21 - Changed eRtps Enable to PHS Enabled
# Version 22 - Removed PC related cfg options (made them unused).
# - Added a test option for connect-disconnect testing
# Version 23 - Removed the unused parameter from the config file
# version 24 - change config file as the latest config file not consistent
# version 25 - Added Segmented PUSC config option
# version 26 - Updated customize field for Wibro Nw
# version 27 - Added Shutdown Related Params
# version 28 - Added Band AMC Related Params
# version 29 - Updated HostDrvrConfig6 for DDR Memory Clock Frequency
# selection & Power Save Mode Selection.
# version 30 - Changed the "MAX MAC Data per frame" from 15:4 to 75:0
# (to reflect T3 capability - for T2 its still 15:4 this is
# handled in MS firmware)
# Version 31 - Added CFG option for HARQ channel mapping
# Version 32 - Added CFG options for ERTPS
# - Removed CFG option for HARQ channel mapping
# Version 33 - Sync 4.x and 5.x CFG file
# Version 34 - Updated the comments for HostDrvrConfig6.
# - Added Cfg options for Enabled Action Trigger and TTWF
# values for Sleepmode
# Version 35 - Added support for IP retention (bit 1 of customize field)
# Version 36 - Renamed the PHS Enable field to CS options. This has now been
# made a bit field
# Version 37 - Updated HostDrvrConfig4(31:30) and HostDrvrConfig5(31:0) for
# WiMAX trigger type and threshold
# Version 39 - Using the handoff enable flags to enable/disable HO on signal
# fade (Active State Retention feature).
# Version 40 - Clean up and add support for MIMO B enable/disable, and
# Encryption enable/disable
# Version 41 - Added bitwise support for Eth CS
# Version 42 - Added support for CFG based purge timer setting for real time
# HARQ connections
# Version 43 - Added config for out of HARQ order delivery feature
# Version 44 - Added config for enabling RPD 124 changes related to Tx power
# report
# Version 45 - Added flag in Wimax options to enable/disable GPIO 2
# signaling of Out of Wimax Coverage.
# Version 46 - Added flag to enable inclusion of Idlemode MAC Hash Skip
# Threshold TLV
# Version 47 - Added DP options
# Version 48 - Added flag in Wimax options to enable/disable GPIO 14 based
# low power mode (LPM) entry
# Version 49 - Added flag under ARQ ENable for disabling ARQ Cut Thru for
# Ack generation
# Version 50 - Added flag for handling partial nacking of PDUs, and retxing
# only nacked blocks */
unsigned int m_u32CfgVersion;
/*
Scanning Parameters
Make center frequency as 0 to enable scanning
Or use: 2336, 2345, 2354, 2367.5, 2385.5
Choosing the center frequency non-zero will
disable scanning! */
unsigned int m_u32CenterFrequency;
unsigned int m_u32BandAScan;
unsigned int m_u32BandBScan;
unsigned int m_u32BandCScan;
// QoS Params
unsigned int m_u32minGrantsize; // size of minimum grant is 0 or 6
unsigned int m_u32PHSEnable;
// HO Params
unsigned int m_u32HoEnable;
unsigned int m_u32HoReserved1;
unsigned int m_u32HoReserved2;
/*
MIMO Enable ==> 0xddccbbaa
aa = 0x01 Enables DL MIMO,
bb = 0x01 Enabled UL CSM ;
cc = 0x01 to disable MIMO B support
0xdd Reserved
0x0101 => Enables DL MIMO and UL CSM
0x010101 =? Enable DL MIMO, UL CSM, and disable MIMO B in DL */
unsigned int m_u32MimoEnable;
/*
Security Parameters
bit 0 = Enable PKMV2 support (Auth support)
bit 1 = Enable index based SFID mapping for MS init SFs
bit 2 = Enable domain restriction for security
bit 3 = Disable encryption support
bit[31:4] = Unused. */
unsigned int m_u32SecurityEnable;
/*
PowerSaving enable
bit 1 = 1 Idlemode enable
bit 2 = 1 Sleepmode Enable */
unsigned int m_u32PowerSavingModesEnable;
/*
PowerSaving Mode Options
bit 0 = 1: CPE mode - to keep pcmcia if alive;
bit 1 = 1: CINR reporing in Idlemode Msg
bit 2 = 1: Default PSC Enable in sleepmode */
unsigned int m_u32PowerSavingModeOptions;
/*
ARQ Enable ==> 0xddccbbaa
aa => 0x01 Enables ARQ
bb => 0x01 Disables the ARQ feature where MS combines ARQ FB and tranport
CID Bw Requests:
cc => 0x01 Enable ARQ FB BW req enh
dd => 0th bit Disable ARQ Cut thru for Ack Generation
dd => 1st bit enables handling of partial nacking of PDUs, and retxing */
unsigned int m_u32ArqEnable;
/*
HARQ Enable ==> 0xddccbbaa
aa => 0x01 Enables HARQ on Transport;
bb => 0 bit Enables HARQ on Management
bb => 1 bit Enables Out of order delivery on non-ARQ Rx ERTPS HARQ connections
bb => 2 bit Enables Out of order delivery on all non-ARQ RX HARQ connections
dd => If set, used as the PDU purge timer on the non-ARQ Rx HARQ RT connections
ERTPS, RTPS, UGS
HARQ on Management only is NOT Permitted.
Eg. 0x0101 => Enables HARQ on Management and HARQ on Transport Connections
Eg. 0x0301 => Enables HARQ on Management and HARQ on Transport Connections
Enables out of deliver on the non-ARQ rx ERTPS HARQ connections
Eg. 0x0501 => Enables HARQ on Management and HARQ on Transport Connections
Enables out of deliver on the non-ARQ RX HARQ connections */
unsigned int m_u32HarqEnable;
// EEPROM Param Location
unsigned int m_u32EEPROMFlag;
/*
Customize
Normal Mode should be set to (0x00000100)
Set bit 0 for using D5 CQICH IE (WiBro NW)
Bit 26 should be set to disable the BEU */
unsigned int m_u32Customize;
/*
Config Bandwidth
Should be in Hz i.e. 8750000, 10000000 */
unsigned int m_u32ConfigBW;
/*
Shutdown Timer
number of frames (5 ms)
ShutDown Timer Value = 0x7fffffff */
unsigned int m_u32ShutDownTimer;
/*
Radio Parameter
e.g. 0x000dccba
d = [19:16] Second/High Band Select
{ 2->2.3 to 2.4G; 3->2.5 to 2.7G; 4->3.4 to 3.6G,
F-> Select from EEPROM if info available }
Do not fill for single band unit
cc = [15:8] Board Type, set to 0
b = [7:4] Primary/Low Band Select
{ 2->2.3 to 2.4G; 3->2.5 to 2.7G; 4->3.4 to 3.6G,
F-> Select from EEPROM if info available }
a = [3:0] Set to 2
Examples:
# 2.3GHz MS120 single band unit needs 0x22
# 2.5GHz MS120 single band unit needs 0x32
# 3.5GHz MS120 single band unit needs 0x42
# 2.3G and/or 3.5G BCS200 unit needs 0x40022
# 2.5G and/or 3.5G BCS200 unit needs 0x40032 */
unsigned int m_u32RadioParameter;
/*
PhyParameter1 e.g. 0xccccbbaa
cccc = [31:16] 80 * Value of TTG in us
bb = [15:8] Number of DL symbols
aa = [7:0] Number of UL symbols
Special value of 0xFFFFFFFF indicates use of embedded logic
PhyParameter1 = 0xFFFFFFFF */
unsigned int m_u32PhyParameter1;
/*
PhyParameter2
[16] Set to 1 for accurate CINR measurement on noise limited scenarios
If set to 1, note the BTS Link Adaptation tables may need change
[15:8] Backoff in 0.25dBm steps in Transmit power to be
applied for an uncalibrated unit */
unsigned int m_u32PhyParameter2;
/*
PhyParameter3 = 0x0 */
unsigned int m_u32PhyParameter3;
/*
TestOptions
in eval mode only;
-lower 16bits = basic cid for testing;
-then bit 16 is test cqich,
-bit 17 test init rang;
-bit 18 test periodic rang
-bit 19 is test harq ack/nack
in normal mode;
-#define ENABLE_RNG_REQ_RPD_R4 0x1
-#define ENABLE_RNG_REQ_RPD_R3 0x2
-#define TEST_HOCODE_IN_IM_REENTRY_RPD 0x4
-#define ENABLE_PHY_PARAMETERS_RPD 0x8
-#define ENABLE_INDEP_CONTROL_DATA_POW_SCALLING 0x10
-#define ENABLE_PTXIRMAX_FOR_ALL_CDMA_CODES 0x20
-#define ENABLE_EXT_BS_INITIATED_IDLE_MODE 0x40
-#define DISABLE_RNG_REQ_ANOMALY 0x100
-#define ENABLE_HARQ_TLVS_IN_DSA_RSP_IOPR 0x200
-#define ENABLE_TX_PWR_RPT_RPD_124 0x400
-#define INCLUDE_IM_MAC_HASH_SKIP_THRESH_TLV 0x800
-#define ENABLE_POLL_ME_BIT_USING_UGS 0x8000
-#define NW_ENTRY_DREG 0x100000
-#define TEST_DISABLE_DSX_FLOW_CONTROL_TLV 0x200000
-#define TEST_SBC_OPTIMIZATION 0x400000
-#define TEST_DISABLE_EARLY_TX_POWER_GEN 0x1000000
-#define LA_DISABLE_ECINR_SUPPORT 0x2000000
-#define ENABLE_NSP_SBC_DISCOVERY_METHOD 0x8000000
-#define ENABLE__BF_WA 0x20000000
-#define ENABLE_BR_PWR_INCR_AND_IGNORE_PC_IE_OUT_DYNAMIC_RNG 0x40000000
-#define ENABLE_BR_CODE_TIMEOUT_PWR_ADJ_PDUS 0x80000000*/
unsigned int m_u32TestOptions;
/*
Max MAC Data per Frame to be sent in REG-REQ */
unsigned int m_u32MaxMACDataperDLFrame;
unsigned int m_u32MaxMACDataperULFrame;
unsigned int m_u32Corr2MacFlags;
/*
HostDrvrConfig1/HostDrvrConfig2/HostDrvrConfig3
12 Bytes are required for setting the LED Configurations.
LED Type (This can be either RED/YELLOW/GREEN/FLUORESCENT)
ON State (This makes sure that the LED is ON till a state is achieved)
Blink State (This makes sure that the LED Keeps Blinking till a state is
achieved e.g. firmware download state)*/
unsigned int HostDrvrConfig1;
unsigned int HostDrvrConfig2;
unsigned int HostDrvrConfig3;
/*
HostDrvrConfig4/HostDrvrConfig5
Used for "WiMAX Trigger" for out of WiMAX Coverage.
HostDrvrConfig4 [31:30]
To set WiMAX Trigger Type:
00 -"Not Defined", 01 -"RSSI", 10 -"CINR", 11 -"Reserved"
HostDrvrConfig5 [31:0]
To set WiMAX Trigger Threshold for the type
selected in HostDrvrConfig4 */
unsigned int HostDrvrConfig4;
unsigned int HostDrvrConfig5;
/*
HostDrvrConfig6:
Important device configuration data
Bit[3..0] Control Flags
Bit 0: Automatic Firmware Download 1: Enable, 0: Disable
Bit 1: Auto Linkup 1: Enable, 0: Disable
Bit 2: Reserved.
Bit 3: Reserved.
Bit[7..4] RESERVED
Bit[11..8] DDR Memory Clock Configuration
MEM_080_MHZ = 0x0
MEM_133_MHZ = 0x3
MEM_160_MHZ = 0x5
Bit[14..12] PowerSaveMethod
DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING = 0x0
DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING = 0x1
DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN = 0x2
Bit[15] Idlemode Auto correct mode.
0-Enable, 1- Disable. */
unsigned int HostDrvrConfig6;
/*
Segmented PSUC
Option to enable support of Segmented PUSC.
If set to 0, only full reuse profiles are supported */
unsigned int m_u32SegmentedPUSCenable;
/*
BAMC Related Parameters
4.x does not support this feature
This is added just to sync 4.x and 5.x CFGs
Bit[0..15] Band AMC signaling configuration:
Bit 0 = 1 Enable Band AMC signaling.
Bit[16..31] Band AMC Data configuration:
Bit 16 = 1 Band AMC 2x3 support.
Bit 0 is effective only if bit 16 is set. */
unsigned int m_u32BandAMCEnable;
} VENDORCFG, *PSVENDORCFG;
/*Structure which stores the information of different LED types
* and corresponding LED state information of driver states*/
typedef struct _GPIO_LED_STATE
{
uint8_t LED_Type;
// specify GPIO number - use 0xFF if not used
uint8_t LED_On_State;
// Bits set or reset for different states
uint8_t LED_Blink_State;
// Bits set or reset for blinking LEDs for different states
uint8_t GPIO_Num;
// GPIO number (this is the bit offset and is 1<<n'ed)
uint8_t BitPolarity;
// Is hardware normal polarity or reverse polarity
} GPIO_LED_STATE, *PSGPIO_LED_STATE;
typedef struct _GPIO_LED_MAP
{
GPIO_LED_STATE LEDState[NUM_OF_LEDS];
// struct stores the state of the LED's
bool bIdleMode_tx_from_host;
// Store notification if driver came out of idle mode
// due to Host or target
bool bIdle_led_off;
// TODO : figure out how to handle these linux wait typedefs
// wait_queue_head_t notify_led_event;
// wait_queue_head_t idleModeSyncEvent;
bool notify_led_event;
bool idleModeSyncEvent;
// TODO END : figure out how to handle these linux wait typedefs
struct task_struct *led_cntrl_threadid;
int led_thread_running;
bool bLedInitDone;
}GPIO_LED_MAP, *PSGPIO_LED_MAP;
typedef struct _FLASH_CS_INFO
{
uint32_t MagicNumber;
// 0xBECE - F1A5 for FLAS(H)
uint32_t FlashLayoutVersion;
// Flash layout version
uint32_t ISOImageVersion;
// ISO Image / Format / Eng version
uint32_t SCSIFirmwareVersion;
// SCSI Firmware Version
uint32_t OffsetFromZeroForPart1ISOImage;
// Normally 0
uint32_t OffsetFromZeroForScsiFirmware;
// Normally 12MB
uint32_t SizeOfScsiFirmware;
// Size of firmware, varies
uint32_t OffsetFromZeroForPart2ISOImage;
// 1st word offset 12MB + sizeofScsiFirmware
uint32_t OffsetFromZeroForCalibrationStart;
uint32_t OffsetFromZeroForCalibrationEnd;
uint32_t OffsetFromZeroForVSAStart;
uint32_t OffsetFromZeroForVSAEnd;
// VSA0 offsets
uint32_t OffsetFromZeroForControlSectionStart;
uint32_t OffsetFromZeroForControlSectionData;
// Control Section offsets
uint32_t CDLessInactivityTimeout;
// NO Data Activity timeout to switch from MSC to NW Mode
uint32_t NewImageSignature;
// New ISO Image Signature
uint32_t FlashSectorSizeSig;
// Signature to validate the sector size.
uint32_t FlashSectorSize;
// Sector Size
uint32_t FlashWriteSupportSize;
// Write Size Support
uint32_t TotalFlashSize;
// Total Flash Size
uint32_t FlashBaseAddr;
// Flash Base Address for offset specified
uint32_t FlashPartMaxSize;
// Flash Part Max Size
uint32_t IsCDLessDeviceBootSig;
// Is CDLess or Flash Bootloader
uint32_t MassStorageTimeout;
// MSC Timeout after reset to switch from MSC to NW Mode
} FLASH_CS_INFO, *PFLASH_CS_INFO;
struct WIMAX_DEVICE
{
VENDORCFG vendorcfg;
// we memcpy the vendor cfg here
unsigned int syscfgBefFw;
// SYS_CFG before firmware
bool CPUFlashBoot;
// Reverse MIPS
unsigned int deviceChipID;
// Beceem interface chip model
volatile bool driverHalt;
// gets set to true when driver is being shutdown
volatile unsigned int driverState;
// Driver state, defined in Driver.h
volatile bool driverDDRinit;
// has the DDR memory been initialized?
volatile bool driverFwPushed;
// has the firmware been pushed to the device?
GPIO_LED_MAP LEDMap;
// Map of LED's in GPIO
thread_id LEDThreadID;
// Thread ID of LED state handler
unsigned int nvmType;
// NVM Type (FLASH|EEPROM|UNKNOWN)
unsigned int nvmDSDSize;
// NVM DSD Size
unsigned int nvmVerMajor;
// NVM Major
unsigned int nvmVerMinor;
// NVM Minor
volatile uint32_t nvmFlashBaseAddr;
// NVM Flash base address
unsigned long nvmFlashCalStart;
// NVM Flash calibrated start
unsigned long nvmFlashCSStart;
// NVM Flash CS start
PFLASH_CS_INFO nvmFlashCSInfo;
// NVM Flash CS info
unsigned long int nvmFlashID;
// ID of Flash chip
volatile bool nvmFlashCSDone;
// Has CS been read yet?
volatile bool nvmFlashRaw;
// Do we need raw access at the moment?
unsigned int nvmFlashMajor;
// NVM Flash layout major version
unsigned int nvmFlashMinor;
// NVM Flash layout major version
unsigned int hwParamPtr;
// Pointer to the NVM Param section address
unsigned char gpioInfo[32];
// Stored GPIO information
unsigned int gpioBitMap;
// GPIO LED bitmap
};
#endif // _USB_BECEEM_DEVICE_STRUCT_
@@ -0,0 +1,358 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of :
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*
* The Beceem chipset can be used via multiple interfaces
* such as PCMCIA, MII, PCI, SDIO, and Serial. However I have
* only found it implemented commercially for PC use as USB.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
#include <lock.h> // for mutex
#else
#include "BeOSCompatibility.h" // for pseudo mutex
#endif
#include "BeceemDevice.h"
#include "Driver.h"
#include "Settings.h"
int32 api_version = B_CUR_DRIVER_API_VERSION;
static const char *sDeviceBaseName = "net/usb_beceemwmx/";
BeceemDevice *gBeceemDevices[MAX_DEVICES];
char *gDeviceNames[MAX_DEVICES + 1];
usb_module_info *gUSBModule = NULL;
usb_support_descriptor gSupportedDevices[] = {
{ 0, 0, 0, 0x0489, 0xe016},
// "Ubee WiMAX Mobile USB - PXU1900 (Clear)"
{ 0, 0, 0, 0x0489, 0xe017},
// "Ubee WiMAX Mobile USB - PXU1901 (Sprint)"
{ 0, 0, 0, 0x198f, 0x0210},
// "Motorola USBw 100 WiMAX CPE"
{ 0, 0, 0, 0x198f, 0x0220},
// "Huawei Mobile USB, Sierra 250U Dual 3G/WiMAX, Sprint U301 WiMAX"
{ 0, 0, 0, 0x19d2, 0x0007}
// "ZTE TU25 WiMAX Adapter [Beceem BCS200]"
};
mutex gDriverLock;
// auto-release helper class
class DriverSmartLock {
public:
DriverSmartLock() { mutex_lock(&gDriverLock); }
~DriverSmartLock() { mutex_unlock(&gDriverLock); }
};
BeceemDevice *
create_beceem_device(usb_device device)
{
const usb_device_descriptor *deviceDescriptor
= gUSBModule->get_device_descriptor(device);
if (deviceDescriptor == NULL) {
TRACE_ALWAYS("Error: Problem getting USB device descriptor.\n");
return NULL;
}
#define IDS(__vendor, __product) (((__vendor) << 16) | (__product))
switch(IDS(deviceDescriptor->vendor_id, deviceDescriptor->product_id)) {
case IDS(0x0489, 0xe016):
return new BeceemDevice(device, "Ubee WiMAX Mobile USB - PXU1900 (Clear)");
case IDS(0x0489, 0xe017):
return new BeceemDevice(device, "Ubee WiMAX Mobile USB - PXU1901 (Sprint)");
case IDS(0x198f, 0x0210):
return new BeceemDevice(device, "Motorola USBw 100 WiMAX CPE");
case IDS(0x198f, 0x0220):
return new BeceemDevice(device, "Beceem Mobile USB WiMAX CPE");
case IDS(0x19d2, 0x0007):
return new BeceemDevice(device, "ZTE TU25 WiMAX Adapter [Beceem BCS200]");
}
return NULL;
}
status_t
usb_beceem_device_added(usb_device device, void **cookie)
{
*cookie = NULL;
DriverSmartLock driverLock; // released on exit
// check if this is a replug of an existing device first
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gBeceemDevices[i] == NULL)
continue;
if (gBeceemDevices[i]->CompareAndReattach(device) != B_OK)
continue;
TRACE("Debug: The device is plugged back. Use entry at %ld.\n", i);
*cookie = gBeceemDevices[i];
return B_OK;
}
// no such device yet, create a new one
BeceemDevice *beceemDevice = create_beceem_device(device);
if (beceemDevice == 0) {
return ENODEV;
}
status_t status = beceemDevice->InitCheck();
if (status < B_OK) {
delete beceemDevice;
return status;
}
status = beceemDevice->SetupDevice(false);
if (status < B_OK) {
delete beceemDevice;
return status;
}
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gBeceemDevices[i] != NULL)
continue;
gBeceemDevices[i] = beceemDevice;
*cookie = beceemDevice;
TRACE("Debug: New device is added at %ld.\n", i);
return B_OK;
}
// no space for the device
TRACE_ALWAYS("Error: no more device entries availble.\n");
delete beceemDevice;
return B_ERROR;
}
status_t
usb_beceem_device_removed(void *cookie)
{
TRACE("Debug: device was removed.\n");
DriverSmartLock driverLock; // released on exit
BeceemDevice *device = (BeceemDevice *)cookie;
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gBeceemDevices[i] == device) {
if (device->IsOpen()) {
// the device will be deleted upon being freed
TRACE("Debug: Device %ld will be deleted upon being freed.\n", i);
device->Removed();
} else {
TRACE("Debug: Device at %ld will be deleted.\n", i);
gBeceemDevices[i] = NULL;
delete device;
TRACE("Debug: Device at %ld deleted.\n", i);
}
break;
}
}
return B_OK;
}
//#pragma mark -
status_t
init_hardware()
{
return B_OK;
}
status_t
init_driver()
{
status_t status = get_module(B_USB_MODULE_NAME,
(module_info **)&gUSBModule);
if (status < B_OK)
return status;
load_settings();
TRACE_ALWAYS("%s\n", kVersion);
for (int32 i = 0; i < MAX_DEVICES; i++)
gBeceemDevices[i] = NULL;
gDeviceNames[0] = NULL;
mutex_init(&gDriverLock, DRIVER_NAME"_devices");
static usb_notify_hooks notifyHooks = {
&usb_beceem_device_added,
&usb_beceem_device_removed
};
gUSBModule->register_driver(DRIVER_NAME, gSupportedDevices,
sizeof(gSupportedDevices) / sizeof(usb_support_descriptor), NULL);
gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
return B_OK;
}
void
uninit_driver()
{
gUSBModule->uninstall_notify(DRIVER_NAME);
mutex_lock(&gDriverLock);
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gBeceemDevices[i]) {
delete gBeceemDevices[i];
gBeceemDevices[i] = NULL;
}
}
for (int32 i = 0; gDeviceNames[i]; i++) {
free(gDeviceNames[i]);
gDeviceNames[i] = NULL;
}
mutex_destroy(&gDriverLock);
put_module(B_USB_MODULE_NAME);
release_settings();
}
static status_t
usb_beceem_open(const char *name, uint32 flags, void **cookie)
{
DriverSmartLock driverLock; // released on exit
*cookie = NULL;
status_t status = ENODEV;
int32 index = strtol(name + strlen(sDeviceBaseName), NULL, 10);
if (index >= 0 && index < MAX_DEVICES && gBeceemDevices[index]) {
status = gBeceemDevices[index]->Open(flags);
*cookie = gBeceemDevices[index];
}
return status;
}
static status_t
usb_beceem_read(void *cookie, off_t position, void *buffer, size_t *numBytes)
{
BeceemDevice *device = (BeceemDevice *)cookie;
return device->Read((uint8 *)buffer, numBytes);
}
static status_t
usb_beceem_write(void *cookie, off_t position, const void *buffer,
size_t *numBytes)
{
BeceemDevice *device = (BeceemDevice *)cookie;
return device->Write((const uint8 *)buffer, numBytes);
}
static status_t
usb_beceem_control(void *cookie, uint32 op, void *buffer, size_t length)
{
BeceemDevice *device = (BeceemDevice *)cookie;
return device->Control(op, buffer, length);
}
static status_t
usb_beceem_close(void *cookie)
{
BeceemDevice *device = (BeceemDevice *)cookie;
return device->Close();
}
static status_t
usb_beceem_free(void *cookie)
{
TRACE("Debug: Device to be freed\n");
BeceemDevice *device = (BeceemDevice *)cookie;
DriverSmartLock driverLock; // released on exit
status_t status = device->Free();
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gBeceemDevices[i] == device) {
// the device is removed already but as it was open the
// removed hook has not deleted the object
TRACE("Debug: Device was removed, but it was open.\n");
gBeceemDevices[i] = NULL;
delete device;
TRACE("Debug: Device at %ld deleted.\n", i);
break;
}
}
return status;
}
const char **
publish_devices()
{
for (int32 i = 0; gDeviceNames[i]; i++) {
free(gDeviceNames[i]);
gDeviceNames[i] = NULL;
}
DriverSmartLock driverLock; // released on exit
int32 deviceCount = 0;
for (int32 i = 0; i < MAX_DEVICES; i++) {
if (gBeceemDevices[i] == NULL)
continue;
gDeviceNames[deviceCount] = (char *)malloc(strlen(sDeviceBaseName) + 4);
if (gDeviceNames[deviceCount]) {
sprintf(gDeviceNames[deviceCount], "%s%ld", sDeviceBaseName, i);
TRACE("Debug: publishing %s\n", gDeviceNames[deviceCount]);
deviceCount++;
} else
TRACE_ALWAYS("Error: out of memory during allocating device name.\n");
}
gDeviceNames[deviceCount] = NULL;
return (const char **)&gDeviceNames[0];
}
device_hooks *
find_device(const char *name)
{
static device_hooks deviceHooks = {
usb_beceem_open,
usb_beceem_close,
usb_beceem_free,
usb_beceem_control,
usb_beceem_read,
usb_beceem_write,
NULL, /* select */
NULL /* deselect */
};
return &deviceHooks;
}
@@ -0,0 +1,116 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of :
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*
*/
#ifndef _USB_BECEEM_DRIVER_H_
#define _USB_BECEEM_DRIVER_H_
#include <OS.h>
#include <KernelExport.h>
#include <Drivers.h>
#include <USB3.h>
#include <ether_driver.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <util/kernel_cpp.h>
#define DRIVER_NAME "usb_beceemwmx"
#define MAX_DEVICES 8
#define FIRM_BIN "/boot/system/data/firmware/macxvi200/macxvi200.bin"
// location on file system of device firmware
#define FIRM_CFG "/boot/system/data/firmware/macxvi200/macxvi.cfg"
// location on file system of vendor configuration
#define SYS_CFG 0x0F000C00
#define FIRM_BEGIN_ADDR 0xBFC00000
// register we push firmware to
#define CONF_BEGIN_ADDR 0xBF60B004
// register we push vendor configuration to
#define EEPROM_COMMAND_Q_REG 0x0F003018
#define EEPROM_READ_DATA_Q_REG 0x0F003020
#define EEPROM_CAL_DATA_INTERNAL_LOC 0x1FB00008
#define DSD_START_OFFSET 0x200
// DSD start offset
#define GPIO_START_OFFSET 0x3
// offset of GPIO start
#define GPIO_PARAM_POINTER 0x0218
// offset on DSD containing GPIO paramaters (flash map <5)
#define GPIO_PARAM_POINTER_MAP5 0x0220
// offset on DSD containing GPIO paramaters (flash map 5>)
#define GPIO_MODE_REGISTER 0x0F000034
// register to set GPIO mode (input or output)
#define GPIO_OUTPUT_SET_REG 0x0F000040
// register to set active GPIO pin, 1 enables, 0 does nothing
#define GPIO_OUTPUT_CLR_REG 0x0F000044
// register to clear active GPIO pin, 1 enables, 0 does nothing
#define GPIO_DISABLE_VAL 0xFF
// value of a disabled GPIO pin
#define NUM_OF_LEDS 4
// number of possible GPIO leds
#define CLOCK_RESET_CNTRL_REG_1 0x0F00000C
#define HPM_CONFIG_LDO145 0x0F000D54
#define CHIP_ID_REG 0x0F000000
// register containing chipset ID
//Beceem chip models |Chip_ID |NVM type
//UNKNOWN 0xbece0110
//UNKNOWN 0xbece0120
//UNKNOWN 0xbece0121
//UNKNOWN 0xbece0130
#define T3 0xbece0300 // EEPROM
#define T3B 0xbece0310
//UNKNOWN 0xbece3200
#define T3LPB 0xbece3300
#define BCS250_BC 0xbece3301 // FLASH
#define BCS220_2 0xbece3311
#define BCS220_2BC 0xbece3310
#define BCS220_3 0xbece3321
// Driver states for pwmxdevice->driverState
#define STATE_INIT 0x1 // DRIVER_INIT
#define STATE_FWPUSH 0x2 // FW_DOWNLOAD
#define STATE_FWPUSH_OK 0x4 // FW_DOWNLOAD_DONE
#define STATE_NONET 0x8 // NO_NETWORK_ENTRY
#define STATE_NORMAL 0x10 // NORMAL_OPERATION
#define STATE_IDLEENTER 0x20 // IDLEMODE_ENTER
#define STATE_IDLECONT 0x40 // IDLEMODE_CONTINUE
#define STATE_IDLEEXIT 0x80 // IDLEMODE_EXIT
#define STATE_HALT 0x00 // SHUTDOWN_EXIT
const uint8 kInvalidRequest = 0xff;
// version of bcm driver this was based upon + end .1
const char* const kVersion = "ver.5.2.45.1";
extern usb_module_info *gUSBModule;
extern "C" {
status_t usb_beceem_device_added(usb_device device, void **cookie);
status_t usb_beceem_device_removed(void *cookie);
status_t init_hardware();
void uninit_driver();
const char **publish_devices();
device_hooks *find_device(const char *name);
}
#endif //_USB_BECEEM_DRIVER_H_
@@ -0,0 +1,16 @@
SubDir HAIKU_TOP src add-ons kernel drivers network wimax usb_beceemwmx ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders kernel net ;
KernelAddon usb_beceemwmx :
Driver.cpp
BeceemDevice.cpp
Settings.cpp
util.cpp
BeceemNVM.cpp
BeceemDDR.cpp
BeceemLED.cpp
BeceemCPU.cpp
;
@@ -0,0 +1,29 @@
USB Driver for Beceem WiMAX devices
====================================================
Realeased under the MIT license for Haiku
2010 Alexander von Gluck
This driver requires a Beceem firmware/vendor configuration
The firmware is binary code pushed to the device and is
a requirement to operate.
The vendor config is a binary configuration file provided
by the device vendor (Ubee, ZTE, Sierra,etc) to tell the
device about it's internal configuration.
Obtaining the Firmware / Vendor configuration
=========================================================
The driver will gracefully search the following directory
for it's needed binary files:
/boot/system/data/firmware/macxvi200/
macxvi200.bin
macvi.cfg
These needed files can be obtained by installing the vendor
provided drivers onto a windows system and checking in
system32/drivers
*Warning*
The license of the binary files is currently unknown.
@@ -0,0 +1,111 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of :
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*
*/
#include <lock.h> // for mutex
#include "Settings.h"
bool gTraceOn = false;
bool gTruncateLogFile = false;
bool gAddTimeStamp = true;
bool gTraceFlow = false;
static char *gLogFilePath = NULL;
mutex gLogLock;
static
void create_log()
{
if(gLogFilePath == NULL)
return;
int flags = O_WRONLY | O_CREAT | ((gTruncateLogFile) ? O_TRUNC : 0);
close(open(gLogFilePath, flags, 0666));
mutex_init(&gLogLock, DRIVER_NAME"-logging");
}
void load_settings()
{
void *handle = load_driver_settings(DRIVER_NAME);
if(handle == 0)
return;
gTraceOn = get_driver_boolean_parameter(handle, "trace", gTraceOn, true);
gTraceFlow = get_driver_boolean_parameter(handle, "trace_flow", gTraceFlow, true);
gTruncateLogFile = get_driver_boolean_parameter(handle, "truncate_logfile",
gTruncateLogFile, true);
gAddTimeStamp = get_driver_boolean_parameter(handle, "add_timestamp",
gAddTimeStamp, true);
const char * logFilePath = get_driver_parameter(handle, "logfile",
NULL, "/var/log/"DRIVER_NAME".log");
if(logFilePath != NULL) {
gLogFilePath = strdup(logFilePath);
}
unload_driver_settings(handle);
create_log();
}
void release_settings()
{
if(gLogFilePath != NULL) {
mutex_destroy(&gLogLock);
free(gLogFilePath);
}
}
void usb_beceem_trace(bool force, const char* func, const char *fmt, ...)
{
if(!(force || gTraceOn)) {
// return;
}
va_list arg_list;
static const char *prefix = "\33[33m"DRIVER_NAME":\33[0m";
static char buffer[1024];
char *buf_ptr = buffer;
if(gLogFilePath == NULL){
strcpy(buffer, prefix);
buf_ptr += strlen(prefix);
}
if(gAddTimeStamp) {
bigtime_t time = system_time();
uint32 msec = time / 1000;
uint32 sec = msec / 1000;
sprintf(buf_ptr, "%02ld.%02ld.%03ld:",
sec / 60, sec % 60, msec % 1000);
buf_ptr += strlen(buf_ptr);
}
if(func != NULL) {
sprintf(buf_ptr, "%s::", func);
buf_ptr += strlen(buf_ptr);
}
va_start(arg_list, fmt);
vsprintf(buf_ptr, fmt, arg_list);
va_end(arg_list);
if(gLogFilePath == NULL) {
dprintf(buffer);
return;
}
mutex_lock(&gLogLock);
int fd = open(gLogFilePath, O_WRONLY | O_APPEND);
write(fd, buffer, strlen(buffer));
close(fd);
mutex_unlock(&gLogLock);
}
@@ -0,0 +1,35 @@
/*
* Ubee WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of :
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
*
*/
#ifndef _USB_BECEEM_SETTINGS_H_
#define _USB_BECEEM_SETTINGS_H_
#include <driver_settings.h>
#include "Driver.h"
void load_settings();
void release_settings();
void usb_beceem_trace(bool force, const char *func, const char *fmt, ...);
#define TRACE(x...) usb_beceem_trace(false, __func__, x)
#define TRACE_ALWAYS(x...) usb_beceem_trace(true, __func__, x)
extern bool gTraceFlow;
#define TRACE_FLOW(x...) usb_beceem_trace(gTraceFlow, NULL, x)
#define TRACE_RET(result) usb_beceem_trace(false, __func__, \
"Returns:%#010x\n", result);
#endif /*_USB_BECEEM_SETTINGS_H_*/
@@ -0,0 +1,33 @@
##
## USB Beceem driver
## Distributed under the terms of the MIT license.
##
## trace [on|off] - activate additional tracing.
## default value: off
trace on
## logfile [full path to private log file]
## default path value: /var/log/usb_beceem.log
## if disabled - all output goes to syslog
logfile /var/log/usb_beceem.log
## reset_logfile [on|off] - truncate private log file on driver/system restart
## default value: off
##
reset_logfile on
## add_timestamp [on|off] - add time of writing the string in private log file.
## default value: on
##
# add_timestamp off
## trace_flow [on|off] - activate data flow tracing. Statistic about of
## transferred data amount and media state.
## default value: off
# trace_flow on
@@ -0,0 +1,38 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
*/
#include <ByteOrder.h>
#include "util.h"
void
convertEndian(bool write, unsigned int uiByteCount, unsigned int* buffer)
{
unsigned int uiIndex = 0;
if( write == true ) {
for(uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++) {
buffer[uiIndex] = htonl(buffer[uiIndex]);
}
} else {
for(uiIndex = 0; uiIndex < (uiByteCount/sizeof(unsigned int)); uiIndex++) {
buffer[uiIndex] = ntohl(buffer[uiIndex]);
}
}
}
uint16_t
CalculateHWChecksum(uint8_t* pu8Buffer, uint32_t u32Size)
{
uint16_t u16CheckSum=0;
while(u32Size--) {
u16CheckSum += (uint8_t)~(*pu8Buffer);
pu8Buffer++;
}
return u16CheckSum;
}
@@ -0,0 +1,12 @@
/*
* Beceem WiMax USB Driver.
* Copyright (c) 2010 Alexander von Gluck <kallisti5@unixzen.com>
* Distributed under the terms of the MIT license.
*
*/
#include "Driver.h"
void convertEndian(bool write, unsigned int uiByteCount, unsigned int* buffer);
uint16_t CalculateHWChecksum(uint8_t* pu8Buffer, uint32_t u32Size);