您的位置:首页 > 其它

龙芯软件开发(16)-- 内存参数读取

2007-01-02 12:37 316 查看
前面已经介绍通过读取内存条上的EEPROM来获取内存配置参数的,现在来仔细地分析这段代码是怎么样实现的。
[align=left]li a1, 0x0[/align]
[align=left]1:[/align]
[align=left] li a0,0xa1 [/align]
[align=left] bal i2cread[/align]
nop

上面这段代码,把0设置给a1,然后把0xa1设置给a0,然后就调用I2C的子函数来读取数据。下面去看函数i2cread是怎么样读取I2C数据。

[align=left]/* a0: slave address [/align]
[align=left] a1: reg off[/align]
[align=left]*/[/align]
[align=left]LEAF(i2cread)[/align]
[align=left] /* set device address */[/align]
[align=left] li v0, 0xbfd00000 + SMBUS_HOST_ADDRESS[/align]
[align=left] li a0, 0xa1[/align]
[align=left] sb a0, 0(v0);[/align]
[align=left]上面代码是输出从设备的地址。[/align]
[align=left] [/align]
[align=left] /* store register offset */[/align]
[align=left] li v0, 0xbfd00000 + SMBUS_HOST_COMMAND[/align]
[align=left] sb a1, 0(v0);[/align]
[align=left]上面代码是输出从设备的寄存器偏移量。[/align]
[align=left] [/align]
[align=left] /* read byte data protocol */[/align]
[align=left] li v0, 0x08[/align]
[align=left] li v1, 0xbfd00000 + SMBUS_HOST_CONTROL[/align]
[align=left] sb v0, 0(v1);[/align]
[align=left] [/align]
[align=left] /* make sure SMB host ready to start, important!--zfx */[/align]
[align=left] li v1, 0xbfd00000 + SMBUS_HOST_STATUS[/align]
[align=left] lbu v0, 0(v1)[/align]
[align=left] andi v0,v0, 0x1f[/align]
[align=left] beqz v0,1f[/align]
[align=left] nop[/align]
[align=left] sb v0, 0(v1)[/align]
[align=left] lbu v0, 0(v1) #flush the write[/align]
[align=left]1:[/align]
[align=left]上面代码是查看数据总线是否准备好数据。[/align]
[align=left] [/align]
[align=left] /* start */[/align]
[align=left] li v1, 0xbfd00000 + SMBUS_HOST_CONTROL[/align]
[align=left] lbu v0, 0(v1)[/align]
[align=left] ori v0, v0, 0x40[/align]
[align=left] sb v0, 0(v1);[/align]
[align=left] [/align]
[align=left] /* wait */[/align]
[align=left] li v1, 0xbfd00000 + SMBUS_HOST_STATUS[/align]
[align=left] li a1, 0x1000[/align]
[align=left]1:[/align]
[align=left] [/align]
[align=left]#if 1[/align]
[align=left] /* delay */[/align]
[align=left] li a0, 0x1000 [/align]
[align=left]2: [/align]
[align=left] bnez a0,2b[/align]
[align=left] addiu a0, -1[/align]
[align=left]#endif[/align]
[align=left] addiu a1, -1[/align]
[align=left] beqz a1, 1f[/align]
[align=left] nop[/align]
[align=left] [/align]
[align=left] lbu v0, 0(v1)[/align]
[align=left] andi v0, SMBUS_HOST_STATUS_BUSY[/align]
[align=left] bnez v0, 1b #IDEL ?[/align]
[align=left] nop[/align]
[align=left]上面代码是查看总线是否在忙状态。[/align]
[align=left] [/align]
[align=left]1:[/align]
[align=left] [/align]
[align=left] li v1, 0xbfd00000 + SMBUS_HOST_STATUS[/align]
[align=left] lbu v0, 0(v1)[/align]
[align=left] andi v0,v0, 0x1f[/align]
[align=left] beqz v0,1f[/align]
[align=left] nop[/align]
[align=left] sb v0, 0(v1) #reset[/align]
[align=left] lbu v0, 0(v1) #flush the write[/align]
[align=left]1:[/align]
[align=left] [/align]
[align=left] li v1, 0xbfd00000 + SMBUS_HOST_DATA0[/align]
[align=left] lbu v0, 0(v1)[/align]
[align=left]上面代码是已经把命令成功发送出去,然后成功地读取回来数据,保存在v0寄存里。[/align]
[align=left] [/align]
[align=left] jr ra[/align]
[align=left] nop[/align]
END(i2cread)

通过上面的子函数,就可以通过I2C总线去读取内存条上的EEPROM参数,以便后面进行内存初始化。
在这里第一次读取是第一个字节,在SPD规范里定义为使用了EEPROM多少个字节。为了清楚地知道那些参数是什么东西,这里给出一个简单的说明。
第0字节 表示厂商使用的字节数。
第1字节 表示EERPOM存储容量。
第2字节 表示内存类型。
第3字节 表示行地址位数。
第4字节 表示列地址位数。
第5字节 表示排数。
第6字节 表示数据宽度(低字节)。
第7字节 表示数据宽度(高字节)。
第8字节 表示信号电平。
第9字节 表示SDRAM最高时钟频率。
第10字节 表示SDRAM访问时间。
第11字节 表示配置类型。
第12字节 表示刷行率/类型。
第13字节 表示最小SDRAM颗粒数据宽度。
第16字节 表示支持突发传输长度。
第17字节 表示逻辑BANK数。
第18字节 表示CAS延时。
第23字节 表示SDRM时钟。是2的最大指数倍。
第24字节 表示SDRAM访问时间。
第34字节 表示输入数据建立时间。
第35字节 表示输入数据保持时间。
第62字节 表示SPD版本号。
其它的字节,就要参考SPD文档了。后面一大段程序就是实现了读取这些参数,然后根据这些参数来设置龙芯内存的SDRAM寄存器。
/* 蔡军生 2007-1-2 于深圳 */
[align=left]2:[/align]
[align=left] PRINTSTR("DIMM SIZE=")[/align]
[align=left] move a0,msize[/align]
[align=left] bal hexserial[/align]
[align=left] nop[/align]
PRINTSTR("/r/n")

当运行到上面的程序时,已经计算出来有多少内存了。并且也可以用上面的参数去设置内存管理器,如下:

[align=left] li t0, 0xbff00008[/align]
[align=left] sd sdCfg, 0(t0)[/align]
上面代码是设置SDRAM寄存器。
[align=left] [/align]
[align=left] #### gx 2006-03-17: mode ####[/align]
[align=left] #li t1,0x20[/align]
[align=left] li t1,0x28[/align]
[align=left] li t0, 0xbff00000[/align]
[align=left] sd t1,0(t0)[/align]
[align=left] nop[/align]
[align=left] li t1,0x0[/align]
[align=left] li t0, 0xbff00000[/align]
[align=left] sd t1,0x30(t0)[/align]
[align=left] nop[/align]
上面代码是设置内存寄存器的模式。
[align=left] [/align]
[align=left] #### setup high memory window ####[/align]
[align=left] li t1, 0x10000000[/align]
[align=left] blt msize, t1, 1f[/align]
[align=left] nop[/align]
上面代码和下面代码是根据内存大小来配置内存窗口。
[align=left] [/align]
[align=left] lui t1,0x2000[/align]
[align=left] sd t1,0x20(t0)[/align]
[align=left] nop[/align]
[align=left] lui t1,0x1000[/align]
[align=left] sd t1,0x28(t0)[/align]
[align=left] nop[/align]
[align=left] [/align]
[align=left]1:[/align]
[align=left] [/align]
[align=left] PRINTSTR("sdcfg=");[/align]
[align=left] move a0,sdCfg[/align]
[align=left] bal hexserial[/align]
[align=left] nop[/align]
[align=left] PRINTSTR("/r/n");[/align]
[align=left] PRINTSTR("msize=");[/align]
[align=left] move a0,msize[/align]
[align=left] bal hexserial[/align]
[align=left] nop[/align]
[align=left] PRINTSTR("/r/n")[/align]

最后再配置BONITO_PCIMEMBASECFG和BONITO_BONPONCFG寄存器,就可以把内存初始化完成了。下一次开始学习怎么样初始化龙芯的缓存。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: