1. 程式人生 > >bootloader中使用2C功能實現

bootloader中使用2C功能實現

包含需要修改及用到得子函式內容

//在 lk/platform/msm8226/include/platform/aboot.h 中新增 判斷 判斷pad與pad連結得引腳定義

     #define P03_PLUG_IN                          15             //GPIO表中查詢
          
 //在 lk/platform/msm8226/include/platform/iomap.h中修改
     #define RESTART_REASON_ADDR         (SYSTEM_IMEM_BASE + 0x565C)
     
 //在lk/platform/msm8226/gpio.c中新增如下:
 int gpio_get(uint32_t gpio)
{
        unsigned int *addr = (unsigned int *)GPIO_IN_OUT_ADDR(gpio);
        return (readl(addr) & 0x1);  
}
 //同時修改 gpio_config_blsp_i2c 函式內容 新增case  QUP_ID_3  在target_init-> qup_blsp_i2c_init 中用到初始化i2用到
 
void gpio_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id)
{
     /* ...*/
   case QUP_ID_3:
        dprintf(CRITICAL, "[I2C] gpio_config_blsp1_i2c: qup3 , i2c_4 \n");
           gpio_tlmm_config(10, 3, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_6MA, GPIO_DISABLE);
           gpio_tlmm_config(11, 3, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_6MA, GPIO_DISABLE);
      /* ...*/
}
 //在lk/inlcude/gpio.h中新增如下
int gpio_get(unsigned nr);


 
 ///////////////////////////////////////////////////////////////////////init.c+++    
 //在lk/target/msms8226/init.c  中新增如下          
     #include <i2c_qup.h>     
     static struct qup_i2c_dev *dev = NULL;
#define SOFTWARE_RESET                        0x73727374    
#define ADB_REBOOT                            0x77665501
#define RECOVERY_MODE                        0x77665502
#define UARTLOG_MODE                        0x77665503
#define NORMAL_BOOT                        0x77665504
#define MICROP_CABLE_IN_TRIGGER            0x02
#define MICROP_POWER_KEY_TRIGGER            0x03     
#define SCALER_I2C_ADDRESS                    (0x37)
#define SCALER_IMAGE_I2C_ADDRESS            (0xE8)
#define MICROP_I2C_ADDRESS                    (0x15)
#define MICROP_ID_I2C_ADDRESS                (0x00)
#define MICROP_FW_ADDRESS                    (0x01)
#define MICROP_POWER_ON_REASON_ADDRESS    (0x07)
#define MICROP_VBUS_OFF_ADDRESS            (0x23)
#define MICROP_POWER_OFF_ADDRESS            (0x55)
#define MICROP_A68_READY_ADDRESS            (0x05
     
     
     
uint8_t read_microp_hwid(uint8_t addr)
{
    int ret = 0;
    uint8_t data[4];
    /* Create a i2c_msg buffer, that is used to put the controller into read
    mode and then to read some data. */
    struct i2c_msg msg_buf[] = {
        {MICROP_I2C_ADDRESS, I2C_M_WR, 1, &addr},
        {MICROP_I2C_ADDRESS, I2C_M_RD, 4, &data}
    };
dprintf(CRITICAL, "lion->init.c->read_microp_hwid::addr = 0x%d \r\n",addr);
    ret = qup_i2c_xfer(dev, msg_buf, 2);
    if ( ret < 0 )
        return ret;

    dprintf(INFO, "[BL]  ret[0] = 0x%x \n", data[0]);
    dprintf(INFO, "[BL]  ret[1] = 0x%x \n", data[1]);
    dprintf(INFO, "[BL]  ret[2] = 0x%x \n", data[2]);
    dprintf(INFO, "[BL]  ret[3] = 0x%x \n", data[3]);

    return data[1];
}

uint8_t read_microp_fw(uint8_t addr)
{
    uint8_t data[4];
    
    struct i2c_msg msg_buf[] =
    {
        {MICROP_I2C_ADDRESS, I2C_M_WR, 1, &addr},
        {MICROP_I2C_ADDRESS, I2C_M_RD, 4, &data}
    };
dprintf(CRITICAL, "lion->init.c->read_microp_fw::addr = 0x%d \r\n",addr);
    qup_i2c_xfer(dev, msg_buf, 2);

    dprintf(INFO, "[BL]  ret[0] = 0x%x \n", data[0]);
    dprintf(INFO, "[BL]  ret[1] = 0x%x \n", data[1]);
    dprintf(INFO, "[BL]  ret[2] = 0x%x \n", data[2]);
    dprintf(INFO, "[BL]  ret[3] = 0x%x \n", data[3]);

    return data[0];
}

uint8_t read_microp_power_on_reason(uint8_t addr)
{
    uint8_t ret[4];
 
    struct i2c_msg msg_buf[] =
     {
        {MICROP_I2C_ADDRESS, I2C_M_WR, 1, &addr},
        {MICROP_I2C_ADDRESS, I2C_M_RD, 4, &ret}
    };
dprintf(CRITICAL, "lion->init.c->read_microp_power_on_reason::addr = 0x%d \r\n",addr);
    qup_i2c_xfer(dev, msg_buf, 2);

    dprintf(INFO, "[BL]  ret[0] = 0x%x \n", ret[0]);
    dprintf(INFO, "[BL]  ret[1] = 0x%x \n", ret[1]);
    dprintf(INFO, "[BL]  ret[2] = 0x%x \n", ret[2]);
    dprintf(INFO, "[BL]  ret[3] = 0x%x \n", ret[3]);

    return ret[1];
}

uint8_t write_microp_a68_ready(uint8_t addr)
{
    int ret;
    uint8_t buf[2];
    buf[0] = addr;
    buf[1] = 0x96;        

    struct i2c_msg msg_buf[] = {
        {MICROP_I2C_ADDRESS, I2C_M_WR, 2, &buf}
    };
dprintf(CRITICAL, "lion->init.c->write_microp_a68_ready::addr = 0x%d \r\n",addr);
    ret = qup_i2c_xfer(dev, msg_buf, 1);

    return ret;
}
uint8_t write_microp_power_off(uint8_t addr)
{
    int ret;
    uint8_t buf[2];
    buf[0] = addr;
    buf[1] = 0xAA;        

    struct i2c_msg msg_buf[] = {
        {MICROP_I2C_ADDRESS, I2C_M_WR, 2, &buf}
    };
dprintf(CRITICAL, "lion->init.c->write_microp_power_off::addr = 0x%d \r\n",addr);
    ret = qup_i2c_xfer(dev, msg_buf, 1);

    return ret;
}
void shutdown_device(void)
{
    dprintf(CRITICAL, "Shutdown system.\n");
    //  lk/dev/pmi/pm8921/pm8921.c中實現
    pm8921_config_reset_pwr_off(0);

    /* Actually reset the chip */
    writel(0, MSM_PSHOLD_CTL_SU);
    mdelay(5000);

    dprintf(CRITICAL, "Shutdown failed.\n");
}
 ///////////////////////////////////////////////////////////////////////init.c---

 ///////////////////////////////////////////////////////////////////////////////////////////////////////////target_init+++
 //在void target_init(void)   函式中新增如下判斷     
     void target_init(void)
     {
    /*判斷是帶PAD啟動           */
     if ( gpio_get(P03_PLUG_IN) )    
    {
        uint8_t whoamI = 0;
        unsigned reboot_mode = 0;
        dprintf(CRITICAL, "lion->tartget_init->[GSBI]  qup_i2c_init++\n");
           dev = qup_blsp_i2c_init( BLSP_ID_1, QUP_ID_3, 100000, 19200000);
        dprintf(CRITICAL, "lion->tartget_init->[GSBI]  qup_i2c_init--\n");
        /* Make sure dev is created and initialized properly */
        if (!dev)
        {
             dprintf(CRITICAL, "[GSBI]  i2c GSBI init dev fail \n" );        
         }
        else
        {  
            /*Microp issue*/
            whoamI = read_microp_hwid( MICROP_ID_I2C_ADDRESS );
            dprintf(CRITICAL, "lion->tartget_init[Microp]  MicropID = 0x%x \n", whoamI);
            if ( !(whoamI < 0) )    
            {
                //0x01
                 whoamI = read_microp_fw(MICROP_FW_ADDRESS);
                 dprintf(CRITICAL, "lion->tartget_init[Microp]  Microp FW = 0x3%x \n", whoamI);
                //0x07
                whoamI = read_microp_power_on_reason(MICROP_POWER_ON_REASON_ADDRESS);
                dprintf(CRITICAL, "lion->tartget_init[Microp]  Microp power on reason = 0x%x \n", whoamI);
                /*If sw reset or recovery reset, don't shut down */                
                reboot_mode = readl(RESTART_REASON_ADDR);
                dprintf(CRITICAL,"lion->tartget_init::reboot_mode : 0x%02x \n", reboot_mode);                
                if ( reboot_mode == SOFTWARE_RESET  || reboot_mode == ADB_REBOOT ||
                    reboot_mode == UARTLOG_MODE || reboot_mode == NORMAL_BOOT ||
                    reboot_mode == RECOVERY_MODE ||
                    whoamI == MICROP_CABLE_IN_TRIGGER || whoamI == MICROP_POWER_KEY_TRIGGER )    
                {
                    dprintf(CRITICAL, "lion->tartget_init[Microp]  Write a68 ready \n");
                    //0x05
                   write_microp_a68_ready(MICROP_A68_READY_ADDRESS);                 
                    //    vibration_enable();  震動 暫時沒開                    
                    dprintf(INFO,"lion->tartget_init::reboot_mode : 0x%02x \n", readl(RESTART_REASON_ADDR));
                }
                //NO
                else    
                {
                    /*If Cable in or long press P03 power_key*/
                    if ( whoamI == 0x01 || whoamI <= 0 )    
                    {  
                        dprintf(CRITICAL, "[Microp]  Power off microp \n");
                        //write_microp_vbus_off(MICROP_VBUS_OFF_ADDRESS);
                        write_microp_power_off(MICROP_POWER_OFF_ADDRESS);
                        dprintf(CRITICAL, "[Microp]  Power off device \n");
                        shutdown_device();
                    }
                }
            }//end of   if ( !(whoamI < 0) )    
        }//end of    else   (!dev)
    }     //end of  if ( gpio_get(P03_PLUG_IN) )    
}
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////target_init---





///////////////////////////////////////////////////////////////////////////////// clk++  
//使能microp 使用得i2c得時鐘 0xF9925000 QUP3
//在lk/platform/msm8226/include/platform/iomap.h 中新增  巨集定義 allows SW control of CBC soft macro
////  CLK_CTL_BASE 為0xFC400000           QUP3  0xFC400748  
#define BLSP1_QUP3_I2C_APPS_CBCR    (CLK_CTL_BASE + 0x748)
//在/lk/platform/msm8226/msm8226-clock.c中新增如下變數:
struct branch_clk gcc_blsp1_qup3_i2c_apps_clk =
{
          .cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
         .parent   = &cxo_clk_src.c,    
      .c = {
          .dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
          .ops      = &clk_ops_branch,
          },
//在msm_clocks_8226結構提中新增
static struct clk_lookup msm_clocks_8226[] =
{
    /* ...*/
  CLK_LOOKUP("blsp1_qup3_i2c_apps_clk", gcc_blsp1_qup3_i2c_apps_clk.c),
  /* ....*/
}
///////////////////////////////////////////////////////////////////////////////// clk--