全志
D1_Linux_SID_开发指南.pdf
对于全志的 SoC 来说,ChipID 用于该 SoC 的唯一标识。
ChipID 由 4 个 word(16 个 byte)组成,共 128bit,通常放在 Efuse(见 2.1.3 节)的起始 4 个 word。
SID 是一个比较独立的模块,在 Linux 内核中没有依赖其他子系统,存放在 drivers/soc/sunxi 目录中。SID 为其他模块提供 API 的调用方式。关系如下图:
1)Thermal、GMAC 的校准参数保存在 SID 中; 2)CE 会用到 SID 中的一些 Key; 3)Sysinfo 比较特殊,为了方便用户空间获取、调试 SID 信息,专门设计的一个字符型设备驱动
A133 ChipID 查看
ceres-c3:/ $ cat sys/class/sunxi_info/sys_info
sunxi_platform : sun50iw10
sunxi_secure : normal
sunxi_chipid : 538014008c0048140144c880407d2190
sunxi_serial : 407d21900144c88000008c0000000000
sunxi_chiptype : 00001400
sunxi_batchno : 0x18550004
DTS
sun50iw10p1.dtsi
/ {
model = "sun50iw10";
compatible = "arm,sun50iw10p1";
interrupt-parent = <&wakeupgen>;
#address-cells = <2>;
#size-cells = <2>;
sid: sunxi-sid@03006000 {
compatible = "allwinner,sunxi-sid";
device_type = "sid";
reg = <0x0 0x03006000 0 0x1000>;
};
sunxi-sid-ng@03006000 {
compatible = "allwinner,sun50iw10p1-sid";
reg = <0x0 0x03006000 0 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
speedbin_efuse: speed@00 {
reg = <0x0 2>;
};
ths_calib: calib@14 {
reg = <0x14 8>;
};
cpubin_efuse: calib@1c {
reg = <0x1c 2>;
};
cpubin_extend: calib@28 {
reg = <0x28 4>;
};
};
chipid: sunxi-chipid@03006200 {
compatible = "allwinner,sunxi-chipid";
device_type = "chipid";
reg = <0x0 0x03006200 0 0x0200>;
};
}
驱动
longan/kernel/linux-4.9/drivers/soc/sunxi/sunxi-sid.c
static unsigned int sunxi_soc_chipid[4];
/**
* soc chipid:
*/
int sunxi_get_soc_chipid(u8 *chipid)
{
sid_chipid_init();
// 53801400-8c004814-0144c880-407d2190 // 10 进制 -------16进制
SID_ERR("sunxi_soc_chipid[0] = %u\n", sunxi_soc_chipid[0]); // 1400902656-----53801400
SID_ERR("sunxi_soc_chipid[1] = %u\n", sunxi_soc_chipid[1]); // 2348828692-----8c004814
SID_ERR("sunxi_soc_chipid[2] = %u\n", sunxi_soc_chipid[2]); // 21284992-------0144c880
SID_ERR("sunxi_soc_chipid[3] = %u\n", sunxi_soc_chipid[3]); // 1081942416-----407d2190
memcpy(chipid, sunxi_soc_chipid, 16);
return 0;
}
EXPORT_SYMBOL(sunxi_get_soc_chipid);
drivers/char/sunxi-sysinfo/sunxi-sysinfo.c
static ssize_t sys_info_show(struct class *class,
struct class_attribute *attr, char *buf)
{
int i;
int databuf[4] = {0};
char tmpbuf[129] = {0};
size_t size = 0;
// ------------------------------------------------------------
/* chipid */
sunxi_get_soc_chipid((u8 *)databuf);
for (i = 0; i < 4; i++)
sprintf(tmpbuf + i*8, "%08x", databuf[i]);
tmpbuf[128] = 0;
size += sprintf(buf + size, "sunxi_chipid : %s\n", tmpbuf);
//--------------------------------------------------------------
return size;
}
内核读取文件节点方式
usb_hw_scan.c
static int get_usb_gadget_functions(void)
{
struct file *filep;
loff_t pos;
char buf[32] = {0};
filep = filp_open("/sys/class/android_usb/android0/functions",
O_RDONLY, 0);
if (IS_ERR(filep))
return 0;
pos = 0;
vfs_read(filep, (char __user *)buf, 32, &pos);
filp_close(filep, NULL);
if (strlen(buf) == 0)
return 0;
else
return 1;
}
以太网固定mac地址
根据ChipId生成mac地址
drivers/net/usb/r8152.c
//lixiaogang add start
static u8 hex_to_int(char hex) {
switch(hex) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'a':
return 10;
case 'b':
return 11;
case 'c':
return 12;
case 'd':
return 13;
case 'e':
return 14;
case 'f':
return 15;
}
}
//lixiaogang add end
static int set_ethernet_addr(struct r8152 *tp)
{
//lixiaogang modify FAQ259 start
u32 databuf[4] = {0};
sunxi_get_soc_chipid((u8 *)databuf);
netif_info(tp, probe, dev, "databuf[0] = %u\n", databuf[0]); // 1400902656
netif_info(tp, probe, dev, "databuf[1] = %u\n", databuf[1]); // 2348828692
netif_info(tp, probe, dev, "databuf[2] = %u\n", databuf[2]); // 21284992
netif_info(tp, probe, dev, "databuf[3] = %u\n", databuf[3]); // 1081942416
int i;
char tmpbuf[129] = {0};
for (i = 0; i < 4; i++) {
sprintf(tmpbuf + i*8, "%08x", databuf[i]);
}
tmpbuf[128] = 0;
netif_info(tp, probe, dev, "sunxi_chipid = %s\n", (char *)tmpbuf); // 538014008c0048140144c880407d2190
u8 *macaddr = dev->dev_addr;
macaddr[0] = (((databuf[1] >> 28) & 0x0f) | ((databuf[2] & 0x0f) << 4)) & 0xff;
macaddr[1] = (databuf[2] >> 4) & 0xff;
macaddr[2] = (databuf[2] >> 12) & 0xff;
macaddr[3] = (databuf[3] >> 6) & 0xff;
macaddr[4] = (databuf[3] >> 16) & 0xff;
macaddr[5] = (databuf[3] >> 26) & 0xff;
macaddr[0] &= 0xfe;
macaddr[0] |= 0x02;
netif_info(tp, probe, dev, "macaddr[0] = %u\n", macaddr[0]); // 10 --- a
netif_info(tp, probe, dev, "macaddr[1] = %u\n", macaddr[1]); // 136 --- 88
netif_info(tp, probe, dev, "macaddr[2] = %u\n", macaddr[2]); // 76 --- 4c
netif_info(tp, probe, dev, "macaddr[3] = %u\n", macaddr[3]); // 134 --- 86
netif_info(tp, probe, dev, "macaddr[4] = %u\n", macaddr[4]); // 125 --- 7d
netif_info(tp, probe, dev, "macaddr[5] = %u\n", macaddr[5]); // 16 --- 10
netif_info(tp, probe, dev, "macaddr[0] = %x\n", macaddr[0]); // a
netif_info(tp, probe, dev, "macaddr[1] = %x\n", macaddr[1]); // 88
netif_info(tp, probe, dev, "macaddr[2] = %x\n", macaddr[2]); // 4c
netif_info(tp, probe, dev, "macaddr[3] = %x\n", macaddr[3]); // 86
netif_info(tp, probe, dev, "macaddr[4] = %x\n", macaddr[4]); // 7d
netif_info(tp, probe, dev, "macaddr[5] = %x\n", macaddr[5]); // 10
if (is_valid_ether_addr(macaddr)) {
netif_info(tp, probe, dev, "Cpu chipid ether addr %pM\n", macaddr);
} else {
eth_hw_addr_random(dev);
netif_info(tp, probe, dev, "Random ether addr %pM\n", macaddr);
}
ether_addr_copy(sa.sa_data, dev->dev_addr);
ret = rtl8152_set_mac_address(dev, &sa);
netif_info(tp, probe, dev, "Final ether addr %pM\n", sa.sa_data);
}
从EEPROM中读取MAC地址
static int set_ethernet_addr(struct r8152 *tp)
{
//----------------------------------------------------------------------------------------------
//add by lixiaogang start
u8 *macaddr = dev->dev_addr;
int j = 0;
for(j = 0; j < 5; j++) {
netif_err(tp, probe, dev, "sleep 100ms\n");
msleep(100);
struct file *filep;
filep = filp_open("/sys/bus/i2c/devices/3-0050/eeprom", O_RDONLY, 0);
if (IS_ERR(filep)) {
netif_err(tp, probe, dev, "eeprom open error\n");
continue;
} else {
loff_t pos = 32;
int i;
int temp;
char buf[17] = {0};
vfs_read(filep, (char __user *)buf, 17, &pos);
for (i = 0; i < 6; i++) {
temp = i * 3;
macaddr[i] = hex_to_int(buf[temp]) * 16 + hex_to_int(buf[temp + 1]);
}
filp_close(filep, NULL);
break;
}
}
netif_info(tp, probe, dev, "eeprom macaddr %pM\n", macaddr);
//add by lixiaogang end
if (!is_valid_ether_addr(macaddr)) {
//lixiaogang modify FAQ259 start
u32 databuf[4] = {0};
sunxi_get_soc_chipid((u8 *)databuf);
macaddr[0] = (((databuf[1] >> 28) & 0x0f) | ((databuf[2] & 0x0f) << 4)) & 0xff;
macaddr[1] = (databuf[2] >> 4) & 0xff;
macaddr[2] = (databuf[2] >> 12) & 0xff;
macaddr[3] = (databuf[3] >> 6) & 0xff;
macaddr[4] = (databuf[3] >> 16) & 0xff;
macaddr[5] = (databuf[3] >> 26) & 0xff;
macaddr[0] &= 0xfe;
macaddr[0] |= 0x02;
if (is_valid_ether_addr(macaddr)) {
netif_info(tp, probe, dev, "Cpu chipid ether addr %pM\n", macaddr);
} else {
eth_hw_addr_random(dev);
netif_info(tp, probe, dev, "Random ether addr %pM\n", macaddr);
}
//lixiaogang modify end
}
ether_addr_copy(sa.sa_data, dev->dev_addr);
ret = rtl8152_set_mac_address(dev, &sa);
netif_info(tp, probe, dev, "Final ether addr %pM\n",
sa.sa_data);
//-------------------------------------------------------------------------------------------
}