在Aboot中添加i2c使用得方法二

本文介绍如何在 MSM8226 平台上配置 PAD 启动功能,包括 GPIO 引脚设置、I2C 接口初始化、时钟控制等关键步骤。通过读取 Microp 芯片 ID 和固件版本,根据不同的启动模式执行相应的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//在 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--


<think>好的,我现在需要帮助用户解决在RK3588的U-Boot中配置和使用PCA9555 I2C扩展GPIO的问题。首先,我得回忆一下相关的知识,特别是关于Rockchip平台和U-Boot的设备树配置。 用户提到了PCA9555芯片,这是一种I2C GPIO扩展器,常用于扩展系统的GPIO数量。在U-Boot中配置这样的设备,通常需要修改设备树,并在代码中进行相应的初始化。根据用户提供的引用,特别是引用[1]中的示例,看起来配置涉及到I2C控制器的启用和PCA9555节点的添加。 首先,我需要确认U-Boot的设备树结构和内核设备树的区别。U-Boot有自己的设备树,但通常会和内核的设备树保持一致,尤其是在硬件描述部分。所以在U-Boot中添加I2C设备的方法应该类似于内核中的配置,但需要注意U-Boot的驱动支持情况。 接下来,用户需要知道如何在U-Boot的设备树中添加PCA9555节点。根据引用[1],示例中配置了i2c1控制器,并在其下添加了pca9555的节点,指定了寄存器地址、兼容性字符串以及GPIO相关的属性。在U-Boot中,这个过程应该类似,但可能需要检查U-Boot是否支持PCA9555的驱动。需要确认U-Boot的版本是否包含PCA9555的驱动程序,或者是否有必要自行添加。 另外,用户可能需要了解如何在U-Boot中使用这些扩展的GPIO。例如,通过gpio命令来读取或设置GPIO的状态。这需要U-Boot中的驱动正确注册这些GPIO,并且用户空间工具能够访问它们。 可能的步骤包括:修改U-Boot的设备树文件,启用对应的I2C控制器,添加PCA9555节点,编译并烧写新的U-Boot镜像,然后在U-Boot命令行中测试GPIO的功能。此外,用户可能需要检查U-Boot的日志信息,确认设备是否被正确识别和初始化。 需要注意的是,不同的开发板可能硬件连接不同,比如I2C总线的编号和设备的地址可能有所差异,用户需要根据实际硬件调整设备树中的reg属性。例如,引用[1]中的reg = <0x22>,而其他情况可能是不同的地址。 还有,GPIO的编号分配也很重要,尤其是在系统中已经有多个GPIO控制器的情况下。需要确保gpio-group-num不与已有的GPIO范围冲突,如引用[1]中提到必须大于RK3568 GPIO的最大引脚编号。 最后,用户可能需要示例代码来验证配置是否正确。例如,在U-Boot中使用i2c命令扫描I2C总线,确认PCA9555设备是否存在,然后使用gpio命令设置或读取引脚状态。如果驱动正确,这些命令应该能够正常工作。</think>在RK3588平台的U-Boot中使用PCA9555 I2C扩展GPIO,需按照以下步骤操作: ### 一、设备树配置 1. **启用I2C控制器**,在U-Boot设备树文件`*-u-boot.dtsi`中添加: ```dts &i2c1 { status = "okay"; clock-frequency = <100000>; // 标准模式 pca9555: gpio@22 { compatible = "nxp,pca9555"; reg = <0x22>; // I2C设备地址 gpio-controller; #gpio-cells = <2>; gpio-group-num = <300>; // 起始编号需大于主控已有GPIO最大值 }; }; ``` ### 、U-Boot驱动验证 1. 确保`CONFIG_DM_GPIO`和`CONFIG_GPIO_PCA953X`配置已启用 2. 检查U-Boot启动日志: ``` gpio@22: gpio@22 ready ``` ### 三、GPIO操作示例 ```bash # U-Boot命令行操作 => i2c dev 1 # 选择i2c1总线 => i2c probe # 扫描设备应显示0x22地址 => gpio status -a => gpio set 300 # 设置GPIO300为高电平 => gpio input 301 # 读取GPIO301状态 ``` ### 四、硬件注意事项 1. 确认物理连接:SCL/SDA信号需上拉至3.3V 2. 地址匹配:芯片A0/A1/A2引脚决定设备地址,0x22对应全接地状态[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值