在boot中添加i2c使用得方法

//在 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);  
}
 //在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_i2c_init( GSBI_ID_4 , 100000, 24000000);
		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---



 ///qup_i2c_init+++
//  修改 lk/platform/msm_shared/i2c_qup.c 中得函数qup_i2c_init 
struct qup_i2c_dev *qup_i2c_init(uint8_t gsbi_id, unsigned clk_freq,
				 unsigned src_clk_freq)
{ 
	/*   ....*/ 
	//添加如下判断 
	switch (gsbi_id) 
	{  
		case GSBI_ID_4:
			dev->gsbi_base = 0x16300000;
			dev->qup_base = 0x16300000 + 0x80000;
			/* Initialize the GPIO_10 and GPIO_11 for GSBI4 as i2c */
			gpio_tlmm_config(10, 0x9, GPIO_OUTPUT, GPIO_NO_PULL,
				GPIO_2MA, GPIO_DISABLE);
			gpio_tlmm_config(11, 0xa, GPIO_OUTPUT, GPIO_NO_PULL,
				GPIO_2MA, GPIO_DISABLE);
			dprintf(CRITICAL, "[GSBI_4] GPIO_10 and GPIO_11 ok\n"); 			
			/* Setting i2c_mux_rw */ 
			val = readl(0x008003E0);
			dprintf(CRITICAL, "[GSBI_4] rw_base value  0x%x ->", val);
			writel((val | 0x200), 0x008003E0);
			val = readl(0x008003E0);
			dprintf(CRITICAL, " 0x%x\n", val);

			/* Setting i2c_mux_ctl */
			val = readl(0x008020B8);
			dprintf(CRITICAL, "[GSBI_4] ctl_base value  0x%x ->", val);
			writel(((val | 0x2) & ~(0x1)), 0x008020B8);
			val = readl(0x008020B8);
			dprintf(CRITICAL, " 0x%x\n", val);
			dprintf(CRITICAL, "[GSBI_4] initial complete !\n");
			break;
		 
		default:
			ASSERT(0);
	}  
	/* This must be done for qup_i2c_interrupt to work. */
	dev_addr = dev; 
	/* Configure the GSBI Protocol Code for i2c */
	writel((GSBI_PROTOCOL_CODE_I2C <<GSBI_CTRL_REG_PROTOCOL_CODE_S), GSBI_CTRL_REG(dev->gsbi_base));

	/* Set clk_freq and src_clk_freq for i2c. */
	dev->clk_freq = clk_freq;
	dev->src_clk_freq = src_clk_freq; 
	dev->num_irqs = 1; 
	dev->one_bit_t = USEC_PER_SEC / dev->clk_freq;
	dev->clk_ctl = 0; 
	/* Register the GSBIn QUP IRQ */
	register_int_handler(dev->qup_irq, (int_handler) qup_i2c_interrupt, 0); 
	/* Then disable it */
	mask_interrupt(dev->qup_irq); 
	return dev;
}
///qup_i2c_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--


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值