mstar 平台typec 5450 升级

商显板领域板卡中有许多扩展的端子,且这些端子是带mcu并且包含内置固件程序,为了后续的维护通常
需要有升级功能。5450 就是一款扩展芯片,将手机信号转换成DP 信号,主板上的DP转换芯片再将DP信号
转换HDMI 信号最后输入给主板显示出来。下面我们围绕5450 来分享一下升级的流程。

1. 主体流程

mstar 平台typec 5450 升级_第1张图片
如果是原厂提供的PC 工具端的基本升级流程: 大体就是启动VENDOR_CMD_ENABLE,FLASH_ACCESS_ENABLE,SMBUS_REASE_FLASH,CHECK_BANK,WRITE_BANK,FLASH_ACCESS_DISABLE,SMBUS_ISP_VALIDATION,RESET_TO_FLASH。
其中GET_IC_STATUS 获取芯片状态信息。

详细信息可以查看文档:
https://download.csdn.net/download/kehyuanyu/12629812

  1. 启动mcuSMBUS功能
    mstar 平台typec 5450 升级_第2张图片
    操作码为0x01, 发送三个字节的指令“0xDA,0x0B,0x01”,code 如下:
    int nFd = open(RTL5450_MASTER_DEV, O_RDWR);
    if(nFd < 0)
    {
     
        printf("[%s][%d] open %s failed !\n", __FUNCTION__,__LINE__,RTL5450_MASTER_DEV);
        return FALSE;
    }
    // 1. enable smbus function
    do
    {
     
        MAPI_U8 data[5]   = {
     0x01,0x03,0xDA,0x0B,0x01};

        bRet = sendCmdToRtl5450(nFd, data, 5);
        if(!bRet)
        {
     
            printf("[%s][%d] send cmd <0x01,0x03,0xDA,0x0B,0x01> failed. Count [%d]\n",\
                __FUNCTION__,__LINE__,uCount);
            break;
        }

        uCount = 0;
        while(uCount++ < 350)
        {
     
            usleep(1000);
            bRet = recvFeedbackFromRtl5450Sigle(nFd,&u8FeedBuf);
            if(bRet && u8FeedBuf == 0x01)
            {
     
                bStep1 = MAPI_TRUE;
                break;
            }
            else
            {
     
                continue;
            }
        }
    } while (0);

sendCmdToRtl5450 是发送指令给5450

static MAPI_BOOL sendCmdToRtl5450(int nDevFd, MAPI_U8 u8Cmd[], MAPI_U8 u8Size)
{
     
    int nRet = -1;
    struct i2c_msg msg;
    struct i2c_rdwr_ioctl_data ioctl_data = {
     0};

    msg.addr          = RTL5450_IIC_ADDR;
    msg.flags         = I2C_SMBUS_WRITE; /* write */
    msg.len           = u8Size;
    msg.buf           = u8Cmd;

    ioctl_data.msgs   = &msg;
    ioctl_data.nmsgs  = 1;

    nRet = ioctl(nDevFd, I2C_RDWR, &ioctl_data);
    if( nRet < 0)
    {
     
        printf("[%s][%d] ioctl rtl5450 i2c reg[0x%02x] failed! nRet: = %d, errno: %d, error: %s. \n", \
            __FUNCTION__,__LINE__,u8Cmd[0],nRet, errno,strerror(errno));
        return MAPI_FALSE;
    }

    return MAPI_TRUE;
}

其中 RTL5450_IIC_ADDR 为typec 7位的设备地址,kernel 会根据上层的操作(读/写)来补全最后一位。
recvFeedbackFromRtl5450Sigle 获取指令执行后,5450 发过来的返回值,使用与所有指令执行后的返回值

// GET_PING_STATUS
static MAPI_BOOL recvFeedbackFromRtl5450Sigle(int nDevFd, MAPI_U8 *pu8FeedBuf)
{
     
    struct i2c_msg msg;
    struct i2c_rdwr_ioctl_data data_ioctl;
    msg.addr = RTL5450_IIC_ADDR;
    msg.flags = I2C_SMBUS_READ;
    msg.len = 1;
    msg.buf = pu8FeedBuf;

    data_ioctl.msgs = &msg;
    data_ioctl.nmsgs = 1;

    if(ioctl(nDevFd, I2C_RDWR, &data_ioctl) < 0)
    {
     
        printf("[%s][%d] read back value failed! \n", __FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }
    return MAPI_TRUE;
}

通过msg.buf 返回上调指令的执行结果。

2. 获取芯片信息

mstar 平台typec 5450 升级_第3张图片
操作码(亦寄存器)为0x3A,发送三个字节指令"0x00 0x00 0x14"到5450 ,其中主要是操作码,及最后一个0x14(表示将返回0x14 个字节的状态信息)。

    // 2. get ic status
    do
    {
     
        MAPI_U8 data[5]   = {
     0x3A,0x03,0x00,0x00,0x14};
        MAPI_U8 u8CmdCode = 0x00;
        MAPI_BOOL bRet    = MAPI_FALSE;

        bRet = sendCmdToRtl5450(nFd, data, 5);
        if(!bRet)
        {
     
            printf("[%s][%d] send cmd <0x3A,0x03,0x00,0x00,0x14> failed. Count [%d]\n",\
                __FUNCTION__,__LINE__,uCount);
            break;
        }

        uCount = 0;
        while(uCount++ < 350)
        {
     
            usleep(1000);
            u8FeedBuf = 0x00;
            bRet = recvFeedbackFromRtl5450Sigle(nFd,&u8FeedBuf);
            if(bRet && u8FeedBuf == 0x01)
            {
     
                break;
            }
            else
            {
     
                continue;
            }
        }

        uCount = 0;
        u8CmdCode = 0x80;
        while(uCount++ < 350)
        {
     
            usleep(100);
            memset(u8FeedBufs, 0x00, sizeof(u8FeedBufs));
            recvFeedbackFromRtl5450FromReg(nFd, u8CmdCode, u8FeedBufs, sizeof(u8FeedBufs)/sizeof(u8FeedBufs[0]));
            if(bRet && u8FeedBufs[0] == 0x14)
            {
     
                bStep2 = MAPI_TRUE;
                break;
            }
            else
            {
     
                continue;
            }
        }
    }while(0);

recvFeedbackFromRtl5450Sigle 返回值为0x01 ,表示5450 正常收到请求GET_IC_STATUS的指令,接着通过recvFeedbackFromRtl5450FromReg获取0x14 (20)个的信息

static MAPI_BOOL recvFeedbackFromRtl5450FromReg(int nDevFd, MAPI_U8 u8Cmd, MAPI_U8 *pu8FeedBuf, MAPI_U8 u8FeedSize)
{
     
    struct i2c_msg msg[2];
    struct i2c_rdwr_ioctl_data data_ioctl;
    MAPI_U8 ucAddr = u8Cmd;
    msg[0].addr = RTL5450_IIC_ADDR;
    msg[0].flags = I2C_SMBUS_WRITE;
    msg[0].len = 1;
    msg[0].buf = &ucAddr; // cmd  or  reg
    msg[1].addr = RTL5450_IIC_ADDR;
    msg[1].flags = I2C_M_RD;
    msg[1].len = u8FeedSize;
    msg[1].buf = pu8FeedBuf;

    data_ioctl.msgs = msg;
    data_ioctl.nmsgs = 2;

    if(ioctl(nDevFd, I2C_RDWR, &data_ioctl) < 0)
    {
     
        printf("[%s][%d] read back value failed! \n", __FUNCTION__,__LINE__);
        return MAPI_FALSE;
    }

    return MAPI_TRUE;
}

成功之后,解析这个20个bytes,其中byte【1】表示Rom code 还是MCM flash code,而byte【15】为0x10 时表示运行在bank1,其他值则表示运行在bank0,这个会影响写flash的地址。
mstar 平台typec 5450 升级_第4张图片

3. 启动falsh访问权限

操作码0x0a, 发送三个字节0xDA,0x0B,0x03 到5450

    // 3. falsh enable access
    do
    {
     
        MAPI_U8 data[5]   = {
     0x01,0x03,0xDA,0x0B,0x03};
        MAPI_BOOL bRet    = MAPI_FALSE;

        bRet = sendCmdToRtl5450(nFd, data, 5);
        if(!bRet)
        {
     
            printf("[%s][%d] send cmd <0x01,0x03,0xDA,0x0B,0x03> failed. Count [%d]\n",\
                __FUNCTION__,__LINE__,uCount);
            break;
        }

        uCount = 0;
        while(uCount++ < 350)
        {
     
            u8FeedBuf = 0x00;
            bRet = recvFeedbackFromRtl5450Sigle(nFd,&u8FeedBuf);
            if(bRet && u8FeedBuf == 0x01)
            {
     
                bStep3 = MAPI_TRUE;
                break;
            }
            else
            {
     
                continue;
            }
            usleep(1000);
        }
    } while (0);

4. 擦写flash

static MAPI_BOOL writeBinTo5450m(MAPI_U8 u8CodeRun, const char* filename, int nFd)
{
     
    MAPI_U8 u8Step4CmdCode1 = 0x00;
    MAPI_U8 u8Step4CmdCode2 = 0x00;
    char binFile[1024];

    MAPI_U8  u8TmpBin[32]   = {
     0x00};
    MAPI_U8  u8WData[34]    = {
     0x00};
    MAPI_U8  u8RUnitLen     = 0x1D;
    MAPI_BOOL bWRet         = MAPI_FALSE;
    const MAPI_U8  u8RUnitHeadLen  = 5; // cmd, byte count, addr_l, addr_h,wData_count
    const MAPI_U32 nBankHalfSize =  65536; // 64K
    FILE *pFHandle = NULL;
    int nLen  = 0;
    MAPI_U16 uReadCnt   = 0;
    MAPI_U32 uWAddr     = 0x0000;
    MAPI_U16 uWUsdAddr  = 0x0000;
    MAPI_U32 u32RTotal  = 0x0000;
    MAPI_U8 u8RItemSize = 29;
    MAPI_U8 u8RItem     = 1;
    MAPI_U8 u8LoopCnt   = 0;

    if(u8CodeRun == 0x10) // bank1
    {
     
        // bank 0 cmd code
        u8Step4CmdCode1 = 0x04;
        u8Step4CmdCode2 = 0x06;
    }
    else // bank0
    {
     
        // bank 1 cmd code
        u8Step4CmdCode1 = 0x13;
        u8Step4CmdCode2 = 0x14;
    }

    printf("[%s][%d] will upgrade %s \n", __FUNCTION__,__LINE__,u8CodeRun ? "bank0" : "bank1");
    printf("[%s][%d] cmd code1: 0x%02x , cmd: code2 0x%02x .\n", __FUNCTION__,__LINE__,u8Step4CmdCode1,u8Step4CmdCode2);

    memset(binFile,0x00,sizeof(binFile));
    memcpy(binFile,filename,strlen(filename));

    pFHandle = fopen(binFile, "r");
    if(pFHandle == NULL)
    {
     
        printf("[%s][%d] open %s failed! \n",__FUNCTION__,__LINE__,binFile);
        return MAPI_FALSE;
    }

    fseek(pFHandle, 0, SEEK_END);

    nLen = ftell(pFHandle);

    fseek(pFHandle, 0, SEEK_SET);

    printf("[%s][%d] file %s size: %d[0x%05x] \n",__FUNCTION__,__LINE__,binFile,nLen,nLen);

    while(TRUE)
    {
     
        MAPI_BOOL bBackVal = MAPI_FALSE;
        u8RItem = (u8RItem % 10) == 0 ? 1 : (u8RItem % 10) ;
        if(u8RItem % 9 == 0)
        {
     
            u8RItemSize = 24;
        }
        else
        {
     
            u8RItemSize = 29;
        }

        // init buf
        memset(u8TmpBin, 0x00, sizeof(u8TmpBin));
        memset(u8WData, 0x00, sizeof(u8WData));
        u8RUnitLen = fread(u8TmpBin, sizeof(char), u8RItemSize, pFHandle);
        if(u8RUnitLen <= 0)
        {
     
            int nCurPosition = ftell(pFHandle);
            if(nCurPosition >= nLen)
            {
     
                break;
            }
        }

        u32RTotal = u32RTotal + u8RUnitLen;
        if(u32RTotal < nBankHalfSize)
        {
     
            u8WData[0] = u8Step4CmdCode1;
        }
        else
        {
     
            u8RItem    = 1;
            u8WData[0] = u8Step4CmdCode2;
        }

    #if (KERNEL_I2C_DEBUG == 1)
        if(u32RTotal % 1024 == 0)
        {
     
            printf("[%s][%d] read item ( %d KB) from bin, two banks size: %d KB . \n", \
                __FUNCTION__,__LINE__,(u32RTotal/1024),(nLen/1024));
        }
    #endif
        // byte count
        u8WData[1] = u8RUnitLen + (u8RUnitHeadLen - 2); // remove 2 byte(cmd , byte count)

        uWUsdAddr = uWAddr % nBankHalfSize;
        // ADDR_L
        u8WData[2] = (MAPI_U8)uWUsdAddr&0x00FF;
        // ADDR_H
        u8WData[3] = ((MAPI_U8)((uWUsdAddr&0xFF00) >> 8));
        // WData_count
        u8WData[4] = u8RUnitLen;
        // data1 ~ dataN
        memcpy(u8WData + u8RUnitHeadLen, u8TmpBin, u8RUnitLen);

        bWRet = sendCmdToRtl5450(nFd, u8WData, (u8RUnitLen+u8RUnitHeadLen));
        if(!bWRet)
        {
     
            printf("[%s][%d] wirte bin data to 5450 failed\n", __FUNCTION__,__LINE__);
            break;
        }

        u8LoopCnt = 0;
        while(u8LoopCnt++ < 350)
        {
     
            // MAPI_U8   u8CmdCode   = u8WData[0];
            MAPI_BOOL bRetFeedval = MAPI_FALSE;
            MAPI_U8   u8FeedBuf = 0x00;

            usleep(1000);

            bRetFeedval = recvFeedbackFromRtl5450Sigle(nFd,&u8FeedBuf);
            if(bRetFeedval && u8FeedBuf == 0x01)
            {
     
                bBackVal = MAPI_TRUE;
                break;
            }
            else
            {
     
                continue;
            }
        }

        if(!bBackVal)
        {
     
            printf("[%s][%d] get back value failed , when wirte date to 0x%04x\n",\
                __FUNCTION__,__LINE__,uWAddr);
            break;
        }

        uReadCnt++;
        u8RItem++;
        uWAddr = uWAddr + u8RUnitLen;
    }

    if(feof(pFHandle) != 0 || (ftell(pFHandle) == nLen))
    {
     
        printf("[%s][%d] wirte bin file completed .\n", __FUNCTION__,__LINE__);
        fclose(pFHandle);
        return MAPI_TRUE;
    }

    printf("[%s][%d] write %d bytes to dev [addr: 0x%04x], [failed] \n",\
        __FUNCTION__,__LINE__,u8RUnitLen,uWAddr);

    fclose(pFHandle);
    return MAPI_FALSE;
}

mstar 平台typec 5450 升级_第5张图片
bank0 : 0~ 128K, bank1: 128K~256K。 根据GET_IC_STATUS获取信息,如果运行在bank1就写bank0,如果运行在bank0 就写bank1.
根据对应操作码,将从bin文件中读取的数据封装成包,写入mcu 的flash中。一个轮回写8次29bytes,接着写1次24bytes,共计256 bytes,如此反复512次即可烧录完128K数据。

5. 关闭smbus

    do
    {
     
        MAPI_U8 data[5]   = {
     0x01,0x03,0xDA,0x0B,0x01};
        MAPI_BOOL bRet    = MAPI_FALSE;
        memset(u8FeedBufs, 0x00, sizeof(u8FeedBufs));

        bRet = sendCmdToRtl5450(nFd, data, 5);
        if(!bRet)
        {
     
            printf("[%s][%d] send cmd <0x01,0x03,0xDA,0x0B,0x01> failed. Count [%d]\n",\
                __FUNCTION__,__LINE__,uCount);
            break;
        }

        uCount = 0;
        while(uCount++ < 350)
        {
     
            usleep(1000);

            u8FeedBuf = 0x00;
            bRet = recvFeedbackFromRtl5450Sigle(nFd,&u8FeedBuf);
            if(bRet && u8FeedBuf == 0x01)
            {
     
                bStep5_1 = MAPI_TRUE;
                break;
            }
            else
            {
     
                continue;
            }
        }
    } while (0);

6. 校验数据

操作码0x01,发送三字节数据0xDA,0x0B,0x01给mcu

    // 5. smbus isp validation
    do
    {
     
        MAPI_U8 data[3]   = {
     0x16,0x01,0x01};
        MAPI_BOOL bRet    = MAPI_FALSE;

        bRet = sendCmdToRtl5450(nFd, data, 3);
        if(!bRet)
        {
     
            printf("[%s][%d] send cmd <0x16,0x01,0x01> failed. Count [%d]\n",\
                __FUNCTION__,__LINE__,uCount);
            break;
        }

        uCount = 0;
        while(uCount++ < 350)
        {
     
            usleep(1000);
            u8FeedBuf = 0x00;
            bRet = recvFeedbackFromRtl5450Sigle(nFd,&u8FeedBuf);
            if(bRet && u8FeedBuf == 0x01)
            {
     
                bStep5_2 = MAPI_TRUE;
                break;
            }
            else
            {
     
                continue;
            }
        }
    } while (0);

7. 重启flash

    do
    {
     
        MAPI_U8 data[5]   = {
     0x05,0x03,0xDA,0x0B,0x01};
        MAPI_BOOL bRet    = MAPI_FALSE;

        bRet = sendCmdToRtl5450(nFd, data, 5);
        if(!bRet)
        {
     
            printf("[%s][%d] send cmd <0x05,0x03,0xDA,0x0B,0x01> failed. Count [%d]\n",\
                __FUNCTION__,__LINE__,uCount);
            break;
        }

        uCount = 0;
        while(uCount++ < 350)
        {
     
            usleep(1000);
            u8FeedBuf = 0x00;
            bRet = recvFeedbackFromRtl5450Sigle(nFd,&u8FeedBuf);
            if(bRet && u8FeedBuf == 0x01)
            {
     
                bStep6 = MAPI_TRUE;
                break;
            }
            else
            {
     
                continue;
            }
        }
    } while (0);

至此,整个升级流程完成。

你可能感兴趣的:(商显,linux,linux,mstar,商显)