1.继续往下执行
config_ht_link 在 ls3a7a_setup_ht_link.S 文件的前半部分:
1.1 先看这个文件的注释吧
//************************************
// setup_ht_link
// author: chenxk
// date: 2017.11.14
// set up the link between CPU and PCH include two steps: 设置这个连接包括两个步骤
// 1. config_ht_link(set link parameters) 1.配置ht的连接参数
// 2. reset_ht_link(reset to make new configure effect) 2.重启ht的连接
//
// for CPU: LS3A2000/LS3A3000
// for PCH: LS7A1000
//************************************
#include "ht.h".global config_ht_link
.ent config_ht_link
.set noreorder
.set mips3
//input:
//a0: HT address base(full address base, like: 0x90001e0000000000) ht的基地址
//a1: HT bus and hard freq mode related setting: 总线频率关系如下
//[15:12]: 7A freq-0: 200M; 2: 400M; 5: 800M; 9: 1600M; 传入参数是9
//[11: 8]: 3A freq-0: 200M; 2: 400M; 5: 800M; 9: 1600M; 传入参数是9
//[ 7: 4]: GENx-1/3; 传入参数是3
//[ 1]: width-0: 8bit; 1: 16bits; 传入参数是1,16位宽度
//[ 0]: reconnect, 0: not reconnect; 1: reconnect 传入参数是1,重新连接
//a2: HT soft configure pll setting:
//[63:32]: 7A side ht_pllcfg[31:0] //高32位表示7A的PLL设置
//[31: 0]: 3A side ht_pllcfg[31:0] //低32位表示3A的PLL设置//register usage:
//t0: 3A HT cntl register base address //t0表示3A的ht控制器基地址
//t1: 7A HT cntl register base address //t1表示7A的ht控制器基地址
//t5, t6: tmp variable //临时变量
//t2: store a1 //t2保存传入参数2
//t3: store a2 //t2保存传入参数3
//s1: store ra //s1保存返回地址。有可能中间有调用其他函数
1.2 进入代码,分成几段吧,比较长。
config_ht_link:
move s1, ra /* 函数返回在483行 */
dli t0, 0xfdfb000000 //3A
dli t1, 0xfdfe000000 //7A
daddu t0, t0, a0 //a0 = 0x90000e0000000000
daddu t1, t1, a0
move t2, a1
move t3, a2
//中间有些宏定义控制,没有定义的部分,就省略了。
#ifdef CHECK_HT_PLL_LOCK //宏定义有效
//check HT PLL lock
move t5, $0
lw a0, LS3A_HT_PLL_CONF(t0)
srl a0, a0, 3
and a0, a0, 0x1
bnez a0, 2f
nop
PRINTSTR("\r\nError: After reconfigure, 3A HT PLL not locked!!!")
add t5, t5, 1
2:
#ifdef CHECK_7A_HT_PLL_LOCK //宏定义有效
lw a0, 0x1F4(t1)
srl a0, a0, 3
and a0, a0, 0x1
bnez a0, 2f
nop
PRINTSTR("\r\nError: After reconfigure, 7A HT PLL not locked!!!")
add t5, t5, 1
2:
#endif
bnez t5, 2b
nop
TTYDBG("\r\nPLL check success.") //执行这句
#endif
1.2.1 代码最前面的7行。
1)保存ra到s1
2)t0为3A的ht控制器的基地址,t1为7A的HT控制器的基地址
3)参数2,参数3分别保存到 t2和t3中。
1.2.2 接下来
1)t5 的寄存器被清零。$0寄存器的值只有0,复制给t5
2)读3A的HT寄存器(0x9000,0efd,fb00,0178),判断位[3]是否为0,为0则出错,否则跳转继续执行
文档显示第3位是保留,????0x178就是这个寄存器。参考7A的寄存器,两个有点像。
3)读7A的HT寄存器(0x9000,0efd,fb00,01f4),判断位[3]是否为0,为0则出错,否则跳转继续执行
这个寄存器与上面那个寄存器的分区很像,可能是上个寄存器的手册不完整。
4)不为0,是不是表示PLL锁定了?唉,反正就是靠猜。。。
1.2.3 接下来
t5 不等于0,则表示刚刚执行的出错了,死循环。
等于0,则继续向下执行。打印成功的提示
1.3 继续看代码
//wait until HT link up
TTYDBG("\r\nWait HT bus up.")
li t5, 0x1f
1:
lw a0, 0x44(t0)
bal hexserial //打印寄存器的值
nop
TTYDBG(">")
addi t5, t5, -1
bnez t5, 2f
nop
TTYDBG("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b=")
li t5, 0x1f
2:
lw a0, 0x44(t0)
li a1, 0x20 //[5] InitComplete 置1,表示初始化完成。
and a0, a0, a1 //与操作
beqz a0, 1b //等于0,则往会跳,否则继续向下执行
nop
TTYDBG("\r\n")
lw a0, 0x44(t0)
bal hexserial //打印寄存器的值
nop
TTYDBG("\r\n")
3A的HT寄存器(偏移地址0x44):
1.4 继续看代码
#if HT1_RECONNECT
and a0, t2, 0x1 //t2最低位是1
beqz a0, 8f //8f 479行,程序结束返回
nop
TTYDBG("Set 7A side HT:\r\n") //7A1000 手册.pdf
TTYDBG("Set width\r\n")
lw a0, 0x44(t1)
li a1, (0xff<<24) //注意是文档中46-47H寄存器的值
not a1, a1 //a1 = 00ff,ffff
and a0, a0, a1 //[31:24]被清零
li a1, HT_WIDTH_CTRL_8 //a1 = 0
srl t5, t2, 1 //t5 = t2 >> 1
and t5, t5, 0x1 //t2[1] = 1
beqz t5, 1f //不等于0,不跳
nop
li a1, HT_WIDTH_CTRL_16 //a1 = 0x11
1:
sll a1, a1, 24 //a1 = 0x1100,0000
or a0, a0, a1 //a0 的[28] [24] 置1 发送端和接收端 16位宽度设置
sw a0, 0x44(t1) //写入寄存器
lw a0, 0x44(t1) //信息打印,
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Set Freq\r\n")
lw a0, 0x4c(t1) //链路频率配置寄存器 ,只有8-11位可写
li a1, (0xf<<8)
not a1, a1 //a1 = 0xffff,f0ff
and a0, a0, a1 //[11:8] 清零
srl a1, t2, 12 //右移12位
and a1, a1, 0xf //剩下 9 HT总线工作频率配置
sll a1, a1, 8 //左移8位
or a0, a0, a1 //9 写入到[11:8]
sw a0, 0x4c(t1) //偏移为4c的寄存器
lw a0, 0x4c(t1) //打印出来[11:8] = 0; 打印值:0x82250060
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Set soft config\r\n")
dsrl a1, t3, 32 //右移32,取高32位
sw a1, 0x1F4(t1)
lw a0, 0x1F4(t1) //HT PLL控制寄存器,配置时钟 频率的。
bal hexserial
nop
TTYDBG("\r\n")
srl a1, t2, 4 //右移4
and a1, a1, 0xf
li a0, 3
bne a0, a1, 4f //相等,不跳转
nop
TTYDBG("Set Gen3 mode\r\n")
lw a0, 0x6c(t1) //
li a1, (0xff<<16)
not a1, a1 //a1 = 0xff00,ffff
and a0, a0, a1 //清零[23:16]
li a1, (0x60<<16)
or a0, a0, a1 //[23:16]= 0x60
sw a0, 0x6c(t1) //文档说明没找到!!!!!!!
lw a0, 0x6c(t1)
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Set retry mode\r\n")
lw a0, 0x64(t1)
li a1, (0xc1<<0)
not a1, a1
and a0, a0, a1 //清零[7:6],[0]
li a1, (0x81<<0)
or a0, a0, a1
sw a0, 0x64(t1) //文档说明没找到!!!!!!!
lw a0, 0x64(t1)
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Enable scrambling\r\n")
lw a0, 0xd0(t1)
li a1, (0x78<<0)
not a1, a1
and a0, a0, a1 //清零[6:4],[3]
li a1, (0x78<<0)
or a0, a0, a1 //[6:4] = 7 [3] = 1
sw a0, 0xd0(t1)
lw a0, 0xd0(t1)
bal hexserial
nop
TTYDBG("\r\n")
4:
TTYDBG("set buffer num\r\n")
lw a0, 0x1dc(t1)
li a1, 0xfffffff
or a0, a0, a1
sw a0, 0x1dc(t1)
lw a0, 0x1dc(t1)
bal hexserial
nop
TTYDBG("\r\n")
//Set CPU side HT
TTYDBG("Set CPU side HT:\r\n") //执行,3A文档部分。
//HT bus width
TTYDBG("Set width\r\n")
li a1, HT_WIDTH_CTRL_8
srl t5, t2, 1
and t5, t5, 0x1
beqz t5, 1f //等于0跳转,实际不跳转
nop
li a1, HT_WIDTH_CTRL_16 //0x11
1:
sb a1, 0x47(t0) //0x44 [31:24] 高8位,使能相位选择,接收发送16位模式
lw a0, 0x44(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
//Set HT bus frequency
TTYDBG("Set Freq\r\n")
srl a1, t2, 8 //9
and a1, a1, 0xf //a1= 9
sb a1, (LS3A_HT_FREQ+1)(t0) //0x4d这个字节 [11:8] = 9 文档中意义不明确
lw a0, LS3A_HT_FREQ (t0) //0x4c ,信息打印
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Set soft config\r\n")
move a1, t3
sw a1, LS3A_HT_PLL_CONF(t0) //0x178 ,100页,软件频率配置
lw a0, LS3A_HT_PLL_CONF(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
srl a1, t2, 4 //逻辑右移
and a1, a1, 0xf //3
li a0, 3
bne a0, a1, 4f //相等,不跳转
nop
TTYDBG("Set GEN3 mode\r\n")
li a1, 0x88600000
sw a1, LS3A_HT_REVISION(t0) //0x110 [23:16] = 0x60 表示HT3.0 其他位只读
lw a0, LS3A_HT_REVISION(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Set retry mode\r\n")
li a1, 0x81
sb a1, LS3A_HT_RETRY_CONTROL(t0) //0x118 错误重传使能 [7:6]=2, 运行重传次数,[0]可能是使能位,文档中未给出
lw a0, LS3A_HT_RETRY_CONTROL(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Enable scrambling\r\n")
li a1, 0x78
sb a1, LS3A_HT_LINK_TRAIN(t0) //0x130 文档97页。 注意设置的低8位0111,1000每一位的含义 使能scrambling(抢占)
lw a0, LS3A_HT_LINK_TRAIN(t0) //信息打印 ,函数准备返回了,482行
bal hexserial
nop
TTYDBG("\r\n")
4:
//中间删掉了一些没有宏定义的代码
8:
#endif
move ra, s1 /* 函数返回 */
jr ra
nop
1.4.1 t2(t2 = 9<<12 | 9<<8 | 3<<4 | 1<<1 | 1<<0;)是保存的传入的参数,最低位是1,不结束。继续执行
1.4.2 到“TTYDBG("Set Freq\r\n")”的前面,7A这边0x44-0x47寄存器,高31-24位(应该是0x47地址)被清零,[28],[24] 被置1,其他位保持不变
1.4.3 到“TTYDBG("Set soft config\r\n")”代码前,配置0x4c寄存器,设置位[11-8]为9,1600MHz
1.4.4 接下来7句,到回车换行结束。
设置7A的HTPLL寄存器 值为 2<<22 | 2<<18 | 2<<16 | 32*2<<9 | 8<<5 | 1<<1;
不知道它这个计算公式在哪?看下图,似乎是HT PHY自己产生时钟,跟5个PLL没什么关系????
1.4.5 到“TTYDBG("Set retry mode\r\n")”代码前 ,这一段注释说明是配置GEN3.0 但是0x6c的寄存器并没有找到文档说明!!
跳过吧,这也猜不出来啊!!!!
1.4.6 到“TTYDBG("Enable scrambling\r\n")”代码前,0x64的寄存器并没有找到文档说明!!
跳过吧,这也猜不出来啊!!!!
1.4.7 到“TTYDBG("set buffer num\r\n")”代码前,0xd0的寄存器并没有找到文档说明!!
跳过吧,这也猜不出来啊!!!!
1.4.8 到“TTYDBG("Set CPU side HT:\r\n")”代码前,0x1dc的寄存器并没有找到文档说明!!
跳过吧,这也猜不出来啊!!!!
1.5 截取其中cpu HT的代码下来,(跟1.4中后半截相同)
//Set CPU side HT
TTYDBG("Set CPU side HT:\r\n") //执行,3A文档部分。
//HT bus width
TTYDBG("Set width\r\n")
li a1, HT_WIDTH_CTRL_8
srl t5, t2, 1
and t5, t5, 0x1
beqz t5, 1f //等于0跳转,实际不跳转
nop
li a1, HT_WIDTH_CTRL_16 //0x11
1:
sb a1, 0x47(t0) //0x44 [31:24] 高8位,使能相位选择,接收发送16位模式
lw a0, 0x44(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
//Set HT bus frequency
TTYDBG("Set Freq\r\n")
srl a1, t2, 8 //9
and a1, a1, 0xf //a1= 9
sb a1, (LS3A_HT_FREQ+1)(t0) //0x49这个字节 [11:8] = 9 文档中意义不明确
lw a0, LS3A_HT_FREQ (t0) //0x48 ,信息打印
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Set soft config\r\n")
move a1, t3
sw a1, LS3A_HT_PLL_CONF(t0) //0x178 ,100页,软件频率配置
lw a0, LS3A_HT_PLL_CONF(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
srl a1, t2, 4 //逻辑右移
and a1, a1, 0xf //3
li a0, 3
bne a0, a1, 4f //相等,不跳转
nop
TTYDBG("Set GEN3 mode\r\n")
li a1, 0x88600000
sw a1, LS3A_HT_REVISION(t0) //0x110 [23:16] = 0x60 表示HT3.0 其他位只读
lw a0, LS3A_HT_REVISION(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Set retry mode\r\n")
li a1, 0x81
sb a1, LS3A_HT_RETRY_CONTROL(t0) //0x118 错误重传使能 [7:6]=2, 运行重传次数,[0]可能是使能位,文档中未给出
lw a0, LS3A_HT_RETRY_CONTROL(t0) //信息打印
bal hexserial
nop
TTYDBG("\r\n")
TTYDBG("Enable scrambling\r\n")
li a1, 0x78
sb a1, LS3A_HT_LINK_TRAIN(t0) //0x130 文档97页。 注意设置的低8位0111,1000每一位的含义 使能scrambling(抢占)
lw a0, LS3A_HT_LINK_TRAIN(t0) //信息打印 ,函数准备返回了,482行
bal hexserial
nop
TTYDBG("\r\n")
1.5.1 前面几句 a1 = 0x11
1.5.2 接着 赋值0x47字节0x11(即0x44的[31-24]),设置宽度为16位。
1.5.3 对0x49寄存器进行字节操作,写入数字9
1.5.4 到“TTYDBG("Set soft config\r\n")”开始的7个语句,寄存器0x178
设置HT的PLL频率
怎么感觉算出来不是1600M呢????
1.5.5 配置0x110寄存器
1.5.6 配置0x118寄存器,配置为0x81,文档说明不全!!
1.5.7 配置0x130寄存器,配置为0x78,只有[7-0]位有效
然后函数就返回了。
2.总结:
1.这部分主要是HT的时钟配置1600MHz,16bits模式,HT3.0,使能scrambling(抢占),最大重试次数为2
2.配置之后并不能立马生效,还得重启HT控制器,这是下一步要干的事情。
3.文档的说明真的是很不详细,可能需要结合3A和7A的文档一起看才行,顺便也猜一猜吧。唉。。。。