芯片序列号

Allwinner Rockchip

Posted by LXG on April 19, 2023

全志

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 的调用方式。关系如下图:

allwinner_sid

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);
                //-------------------------------------------------------------------------------------------
}