bootloader中使用2C功能實現
阿新 • • 發佈:2019-02-05
包含需要修改及用到得子函式內容
//在 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--