RK3288 android7.1.2 uboot i2c read/write (1byte/2bytes register addr) 以及调用(进阶篇三)

一 . rk3288 android7.1.2 u-boot i2c

1.1byte register addr

1)写时序 slave addr(1byte) +  register addr(1byte)+  Wvlaue(1byte)

2)读时序 slave addr(1byte) +  register addr(1byte)+  (slave addr(1byte)+1)+ Rvlaue(1byte)

2.2byte register addr

1)写时序 slave addr(1byte) +  register addr(H8+L8 2byte)+  Wvlaue(1byte)

2)读时序 slave addr(1byte) +  register addr(H8+L8 2byte)+  (slave addr(1byte)+1)+ Rvlaue(1byte)

注意:start 以及ACK 并未标出,而且读时序有restart

3.在根目录u-boot/drivers/i2c/rk_i2c.c ,为了根据时序的不同改写code 而不影响原本code 的调用,建议重写读写函数如下:

static int rk_i2c_read1(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len);
static int rk_i2c_write1(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len);
int i2c_read_x(uchar chip, uint addr, int alen, uchar *buf, int len);
int i2c_write_x(uchar chip, uint addr, int alen, uchar *buf, int len);

4.整个rk_i2c.c 如下:

/*
 * (C) Copyright 2008-2016 Fuzhou Rockchip Electronics Co., Ltd
 * Peter, Software Engineering, .
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#include 
#include 
#include 
#include 
#include 


#define RKI2C_VERSION		"1.3"

/* i2c debug information config */
#define RKI2C_DEBUG_INFO

#ifdef RKI2C_DEBUG_INFO
#define i2c_info(format, arg...)	printf(format, ##arg)
#else
#define i2c_info(format, arg...)
#endif


/* register io */
#define i2c_writel(val, addr)		writel(val, addr)
#define i2c_readl(addr)			readl(addr)

/* i2c timerout */
#define I2C_TIMEOUT_US		100000  // 100000us = 100ms
#define I2C_RETRY_COUNT		3

/* i2c error return code */
#define I2C_OK			0
#define I2C_ERROR_TIMEOUT	-1
#define I2C_ERROR_NOACK		-2
#define I2C_ERROR_IO		-3

/* rk i2c fifo max transfer bytes */
#define RK_I2C_FIFO_SIZE	32

/* rk i2c device register size */
#define RK_I2C_REGISTER_SIZE	3

#define RK_CEIL(x, y) \
	({ unsigned long __x = (x), __y = (y); (__x + __y - 1) / __y; })


#define I2C_ADAP_SEL_BIT(nr)	((nr) + 11)
#define I2C_ADAP_SEL_MASK(nr)	((nr) + 27)


/* Control register */
#define I2C_CON			0x000
#define I2C_CON_EN		(1 << 0)
#define I2C_CON_MOD(mod)	((mod) << 1)
#define I2C_MODE_TX		0x00
#define I2C_MODE_TRX		0x01
#define I2C_MODE_RX		0x02
#define I2C_MODE_RRX		0x03
#define I2C_CON_MASK		(3 << 1)

#define I2C_CON_START		(1 << 3)
#define I2C_CON_STOP		(1 << 4)
#define I2C_CON_LASTACK		(1 << 5)
#define I2C_CON_ACTACK		(1 << 6)


/* Clock dividor register */
#define I2C_CLKDIV		0x004
#define I2C_CLKDIV_VAL(divl, divh)	(((divl) & 0xffff) | (((divh) << 16) & 0xffff0000))

/* the slave address accessed  for master rx mode */
#define I2C_MRXADDR		0x008
#define I2C_MRXADDR_SET(vld, addr)	(((vld) << 24) | (addr))


/* the slave register address accessed  for master rx mode */
#define I2C_MRXRADDR		0x00c
#define I2C_MRXRADDR_SET(vld, raddr)	(((vld) << 24) | (raddr))

/* master tx count */
#define I2C_MTXCNT		0x010

/* master rx count */
#define I2C_MRXCNT		0x014

/* interrupt enable register */
#define I2C_IEN			0x018
#define I2C_BTFIEN		(1 << 0)
#define I2C_BRFIEN		(1 << 1)
#define I2C_MBTFIEN		(1 << 2)
#define I2C_MBRFIEN		(1 << 3)
#define I2C_STARTIEN		(1 << 4)
#define I2C_STOPIEN		(1 << 5)
#define I2C_NAKRCVIEN		(1 << 6)

/* interrupt pending register */
#define I2C_IPD                 0x01c
#define I2C_BTFIPD              (1 << 0)
#define I2C_BRFIPD              (1 << 1)
#define I2C_MBTFIPD             (1 << 2)
#define I2C_MBRFIPD             (1 << 3)
#define I2C_STARTIPD            (1 << 4)
#define I2C_STOPIPD             (1 << 5)
#define I2C_NAKRCVIPD           (1 << 6)
#define I2C_IPD_ALL_CLEAN       0x7f

/* finished count */
#define I2C_FCNT                0x020

/* I2C tx data register */
#define I2C_TXDATA_BASE         0X100

/* I2C rx data register */
#define I2C_RXDATA_BASE         0x200


struct rk_i2c {
	uint32_t		regs;
	unsigned int		speed;
};


#ifdef CONFIG_I2C_MULTI_BUS
static struct rk_i2c rki2c_base[I2C_BUS_MAX] = {
	{ .regs = (uint32_t)RKIO_I2C0_BASE, 0 },
	{ .regs = (uint32_t)RKIO_I2C1_BASE, 0 },
	{ .regs = (uint32_t)RKIO_I2C2_BASE, 0 },
	{ .regs = (uint32_t)RKIO_I2C3_BASE, 0 },
	{ .regs = (uint32_t)RKIO_I2C4_BASE, 0 },
	{ .regs = (uint32_t)RKIO_I2C5_BASE, 0 },
	{ .regs = (uint32_t)RKIO_I2C6_BASE, 0 },
	{ .regs = (uint32_t)RKIO_I2C7_BASE, 0 }
};
#endif

static uint g_i2c_online_bus = I2C_BUS_MAX;


static inline void *rk_i2c_get_base(void)
{
	if (g_i2c_online_bus >= I2C_BUS_MAX) {
		printf("I2C bus error, PLS set i2c bus first!\n");
		return (void *)NULL;
	}

	if (rki2c_base[g_i2c_online_bus].regs == 0) {
		printf("I2C base register error, PLS check i2c config!\n");
		return (void *)NULL;	
	}

	return (void *)&rki2c_base[g_i2c_online_bus];
}


static inline void rk_i2c_iomux(eI2C_ch_t bus_id)
{
	rk_iomux_config(RK_I2C0_IOMUX + bus_id);
}


static inline void rk_i2c_get_div(int div, int *divh, int *divl)
{
	if (div % 2 == 0) {
		*divh = div / 2;
		*divl = div / 2;
	} else {
		*divh = RK_CEIL(div, 2);
		*divl = div / 2;
	}
}


/* SCL Divisor = 8 * (CLKDIVL+1 + CLKDIVH+1)
 * SCL = PCLK / SCLK Divisor
 * i2c_rate = PCLK
*/
static void rk_i2c_set_clk(struct rk_i2c *i2c, uint32 scl_rate)
{
	uint32 i2c_rate;
	int div, divl, divh;

	if (i2c->speed == scl_rate) {
		return ;
	}
	/* First get i2c rate from pclk */
	i2c_rate = rkclk_get_i2c_clk(g_i2c_online_bus);

	div = RK_CEIL(i2c_rate, scl_rate * 8) - 2;
	if (div < 0) {
		divh = divl = 0;
	} else {
		rk_i2c_get_div(div, &divh, &divl);
	}
	i2c_writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV);

	i2c->speed = scl_rate;

	i2c_info("rk_i2c_set_clk: i2c rate = %d, scl rate = %d\n", i2c_rate, scl_rate);
	i2c_info("set i2c clk div = %d, divh = %d, divl = %d\n", div, divh, divl);
	i2c_info("set clk(I2C_CLKDIV: 0x%08x)\n", i2c_readl(i2c->regs + I2C_CLKDIV));
}


static int rk_i2c_init(int speed)
{
	struct rk_i2c *i2c = (struct rk_i2c *)rk_i2c_get_base();

	if (i2c == NULL) {
		return -1;
	}

	i2c_info("rk_i2c_init: I2C bus = %d\n", g_i2c_online_bus);

	rk_i2c_iomux(g_i2c_online_bus);
	rk_i2c_set_clk(i2c, speed);

	return 0;
}


static void rk_i2c_show_regs(struct rk_i2c *i2c)
{
#ifdef RKI2C_DEBUG_INFO
	uint i;

	i2c_info("I2C_CON: 0x%08x\n", i2c_readl(i2c->regs + I2C_CON));
	i2c_info("I2C_CLKDIV: 0x%08x\n", i2c_readl(i2c->regs + I2C_CLKDIV));
	i2c_info("I2C_MRXADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXADDR));
	i2c_info("I2C_MRXRADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXRADDR));
	i2c_info("I2C_MTXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MTXCNT));
	i2c_info("I2C_MRXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXCNT));
	i2c_info("I2C_IEN: 0x%08x\n", i2c_readl(i2c->regs + I2C_IEN));
	i2c_info("I2C_IPD: 0x%08x\n", i2c_readl(i2c->regs + I2C_IPD));
	i2c_info("I2C_FCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_FCNT));
	for (i = 0; i < 8; i ++) {
		i2c_info("I2C_TXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_TXDATA_BASE + i * 4));
	}
	for (i = 0; i < 8; i ++) {
		i2c_info("I2C_RXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_RXDATA_BASE + i * 4));
	}
#endif
}


static int rk_i2c_send_start_bit(struct rk_i2c *i2c)
{
	int TimeOut = I2C_TIMEOUT_US;

	i2c_info("I2c Send Start bit.\n");
	i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);

	i2c_writel(I2C_CON_EN | I2C_CON_START, i2c->regs + I2C_CON);
	i2c_writel(I2C_STARTIEN, i2c->regs + I2C_IEN);

	while (TimeOut--) {
		if (i2c_readl(i2c->regs + I2C_IPD) & I2C_STARTIPD) {
			i2c_writel(I2C_STARTIPD, i2c->regs + I2C_IPD);
			break;
		}
		udelay(1);
	}
	if (TimeOut <= 0) {
		printf("I2C Send Start Bit Timeout\n");
		rk_i2c_show_regs(i2c);
		return I2C_ERROR_TIMEOUT;
	}

	return I2C_OK;
}


static int rk_i2c_send_stop_bit(struct rk_i2c *i2c)
{
	int TimeOut = I2C_TIMEOUT_US;

	i2c_info("I2c Send Stop bit.\n");
	i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);

	i2c_writel(I2C_CON_EN | I2C_CON_STOP, i2c->regs + I2C_CON);
	i2c_writel(I2C_CON_STOP, i2c->regs + I2C_IEN);

	while (TimeOut--) {
		if (i2c_readl(i2c->regs + I2C_IPD) & I2C_STOPIPD) {
			i2c_writel(I2C_STOPIPD, i2c->regs + I2C_IPD);
			break;
		}
		udelay(1);
	}
	if (TimeOut <= 0) {
		printf("I2C Send Stop Bit Timeout\n");
		rk_i2c_show_regs(i2c);
		return I2C_ERROR_TIMEOUT;
	}

	return I2C_OK;
}


static inline void rk_i2c_disable(struct rk_i2c *i2c)
{
	i2c_writel(0, i2c->regs + I2C_CON);
}


static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len)
{
	int err = I2C_OK;
	int TimeOut = I2C_TIMEOUT_US;
	uchar *pbuf = buf;
	uint bytes_remain_len = b_len;
	uint bytes_tranfered_len = 0;
	uint words_tranfered_len = 0;
	uint con = 0;
	uint rxdata;
	uint i, j;

	i2c_info("rk_i2c_read: chip = %x, reg = %x, r_len = %d, b_len = %d\n", chip, reg, r_len, b_len);

	err = rk_i2c_send_start_bit(i2c);
	if (err != I2C_OK) {
		return err;
	}

	i2c_writel(I2C_MRXADDR_SET(1, chip << 1 | 1), i2c->regs + I2C_MRXADDR);
	if (r_len == 0) {
		i2c_writel(0, i2c->regs + I2C_MRXRADDR);
	} else if (r_len < 4) {
		i2c_writel(I2C_MRXRADDR_SET(r_len, reg), i2c->regs + I2C_MRXRADDR);
	} else {
		printf("I2C Read: addr len %d not supported\n", r_len);
		return I2C_ERROR_IO;
	}

	while (bytes_remain_len) {
		if (bytes_remain_len > RK_I2C_FIFO_SIZE) {
			con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX);
			bytes_tranfered_len = 32;
		} else {
			con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX) | I2C_CON_LASTACK;
			bytes_tranfered_len = bytes_remain_len;
		}
		words_tranfered_len = RK_CEIL(bytes_tranfered_len, 4);

		i2c_writel(con, i2c->regs + I2C_CON);
		i2c_writel(bytes_tranfered_len, i2c->regs + I2C_MRXCNT);
		i2c_writel(I2C_MBRFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN);

		TimeOut = I2C_TIMEOUT_US;
		while (TimeOut--) {
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_NAKRCVIPD) {
				i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
				err = I2C_ERROR_NOACK;
			}
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_MBRFIPD) {
				i2c_writel(I2C_MBRFIPD, i2c->regs + I2C_IPD);
				break;
			}
			udelay(1);
		}

		if (TimeOut <= 0) {
			printf("I2C Read Data Timeout\n");
			err =  I2C_ERROR_TIMEOUT;
			rk_i2c_show_regs(i2c);
			goto i2c_exit;
		}

		for (i = 0; i < words_tranfered_len; i++) {
			rxdata = i2c_readl(i2c->regs + I2C_RXDATA_BASE + i * 4);
			i2c_info("I2c Read RXDATA[%d] = 0x%x\n", i, rxdata);
			for (j = 0; j < 4; j++) {
				if ((i * 4 + j) == bytes_tranfered_len) {
					break;
				}
				*pbuf++ = (rxdata >> (j * 8)) & 0xff;
			}
		}
		bytes_remain_len -= bytes_tranfered_len;
		i2c_info("I2C Read bytes_remain_len %d\n", bytes_remain_len);
	}

i2c_exit:
	// Send stop bit
	rk_i2c_send_stop_bit(i2c);
	// Disable Controller
	rk_i2c_disable(i2c);

	return err;
}

static int rk_i2c_write(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len)
{
	int err = I2C_OK;
	int TimeOut = I2C_TIMEOUT_US;
	uchar *pbuf = buf;
	uint bytes_remain_len = b_len + r_len + 1;
	uint bytes_tranfered_len = 0;
	uint words_tranfered_len = 0;
	uint txdata;
	uint i, j;

	i2c_info("rk_i2c_write: chip = %x, reg = %x, r_len = %d, b_len = %d\n", chip, reg, r_len, b_len);
	
	err = rk_i2c_send_start_bit(i2c);
	if (err != I2C_OK) {
		return err;
	}

	while (bytes_remain_len) {
		if (bytes_remain_len > RK_I2C_FIFO_SIZE) {
			bytes_tranfered_len = 32;
		} else {
			bytes_tranfered_len = bytes_remain_len;
		}
		words_tranfered_len = RK_CEIL(bytes_tranfered_len, 4);

		for (i = 0; i < words_tranfered_len; i++) {
			txdata = 0;
			for (j = 0; j < 4; j++) {
				if ((i * 4 + j) == bytes_tranfered_len) {
					break;
				}

				if (i == 0 && j == 0) {
					txdata |= (chip << 1);
				} else if (i == 0 && j <= r_len) {
					txdata |= (reg & (0xff << ((j - 1) * 8))) << 8;
					printf("I2c Write reg = 0x%x\n", (reg & (0xff << ((j - 1) * 8))) << 8);
				} else {
					txdata |= (*pbuf++)<<(j * 8);
				}
				i2c_writel(txdata, i2c->regs + I2C_TXDATA_BASE + i * 4);
			}
			i2c_info("I2c Write TXDATA[%d] = 0x%x\n", i, txdata);
			printf("I2c Write TXDATA[%d] = 0x%x\n", i, txdata);
		}
		
		i2c_writel(I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TX), i2c->regs + I2C_CON);
		i2c_writel(bytes_tranfered_len, i2c->regs + I2C_MTXCNT);
		i2c_writel(I2C_MBTFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN);

		TimeOut = I2C_TIMEOUT_US;
		while (TimeOut--) {
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_NAKRCVIPD) {
				i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
				err = I2C_ERROR_NOACK;
			}
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_MBTFIPD) {
				i2c_writel(I2C_MBTFIPD, i2c->regs + I2C_IPD);
				break;
			}
			udelay(1);
		}

		if (TimeOut <= 0) {
			printf("I2C Write Data Timeout\n");
			err =  I2C_ERROR_TIMEOUT;
			rk_i2c_show_regs(i2c);
			goto i2c_exit;
		}

		bytes_remain_len -= bytes_tranfered_len;
		i2c_info("I2C Write bytes_remain_len %d\n", bytes_remain_len);
	}

i2c_exit:
	// Send stop bit
	rk_i2c_send_stop_bit(i2c);
	// Disable Controller
	rk_i2c_disable(i2c);

	return err;
}


#ifdef CONFIG_I2C_MULTI_BUS
unsigned int i2c_get_bus_num(void)
{
	return g_i2c_online_bus;
}


int i2c_set_bus_num(unsigned bus_idx)
{
	i2c_info("i2c_set_bus_num: I2C bus = %d\n", bus_idx);

	if (bus_idx >= I2C_BUS_MAX) {
		printf("i2c_set_bus_num: I2C bus error!\n");
		return -1;
	}

	g_i2c_online_bus = bus_idx;

	return 0;
}
#endif


static int rk_i2c_read1(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len)
{
	int err = I2C_OK;
	int TimeOut = I2C_TIMEOUT_US;
	uchar *pbuf = buf,tmp[4];
	uint bytes_remain_len = b_len;
	uint bytes_tranfered_len = 0;
	uint words_tranfered_len = 0;
	uint con = 0;
	uint rxdata;
	uint i, j;

	i2c_info("rk_i2c_read1: chip = %x, reg = %x, r_len = %d, b_len = %d\n", chip, reg, r_len, b_len);

	err = rk_i2c_send_start_bit(i2c);
	if (err != I2C_OK) {
		return err;
	}

	tmp[0] = (uchar)(reg & 0xff);
	tmp[1] = (uchar)((reg >> 8) & 0xff);
	tmp[2] = (uchar)((reg >> 16) & 0xff);
	tmp[3] = (uchar)((reg >> 24) & 0xff);

	if(r_len == 2) {
		reg = (tmp[0] << 8) + tmp[1];		
	} else if(r_len == 3){
		reg = (tmp[0] << 16) + (tmp[1] << 8) + tmp[2];
	} else if(r_len == 4){
		reg = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];
	} else if(r_len > 4){
		i2c_info("I2C Read1: addr len %d not supported\n", r_len);
	} else{
		;
	}

	i2c_writel(I2C_MRXADDR_SET(1, chip << 1 | 1), i2c->regs + I2C_MRXADDR);

	if (r_len == 0) {
		i2c_writel(0, i2c->regs + I2C_MRXRADDR);
	} else if (r_len == 1) {		
		i2c_writel(I2C_MRXRADDR_SET(r_len, reg), i2c->regs + I2C_MRXRADDR);
	} else if (r_len == 2) {
		i2c_writel(I2C_MRXRADDR_SET(r_len + 1, reg), i2c->regs + I2C_MRXRADDR);
	} else if (r_len == 3) {
		i2c_writel(I2C_MRXRADDR_SET(r_len + 4, reg), i2c->regs + I2C_MRXRADDR);
	} else {
		i2c_info("I2C Read1: addr len %d not supported\n", r_len);
		return I2C_ERROR_IO;
	}
			
	while (bytes_remain_len) {
		if (bytes_remain_len > RK_I2C_FIFO_SIZE) {
			con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX);
			bytes_tranfered_len = 32;
		} else {
			con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX) | I2C_CON_LASTACK;
			bytes_tranfered_len = bytes_remain_len;
		}
		words_tranfered_len = RK_CEIL(bytes_tranfered_len, 4);

		i2c_writel(con, i2c->regs + I2C_CON);
		i2c_writel(bytes_tranfered_len, i2c->regs + I2C_MRXCNT);
		i2c_writel(I2C_MBRFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN);

		
		TimeOut = I2C_TIMEOUT_US;
		while (TimeOut--) {
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_NAKRCVIPD) {
				i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
				err = I2C_ERROR_NOACK;
			}
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_MBRFIPD) {
				i2c_writel(I2C_MBRFIPD, i2c->regs + I2C_IPD);
				break;
			}
			udelay(1);
		}

		if (TimeOut <= 0) {
			i2c_info("I2C Read1 Data Timeout\n");
			err =  I2C_ERROR_TIMEOUT;
			rk_i2c_show_regs(i2c);
			goto i2c_exit;
		}

		for (i = 0; i < words_tranfered_len; i++) {
			rxdata = i2c_readl(i2c->regs + I2C_RXDATA_BASE + i * 4);
			i2c_info("I2c Read1 RXDATA[%d] = 0x%x\n", i, rxdata);
			for (j = 0; j < 4; j++) {
				if ((i * 4 + j) == bytes_tranfered_len) {
					break;
				}
				*pbuf++ = (rxdata >> (j * 8)) & 0xff;
			}
		}

		bytes_remain_len -= bytes_tranfered_len;
		i2c_info("I2C Read1 bytes_remain_len %d\n", bytes_remain_len);
	}

i2c_exit:
	// Send stop bit
	rk_i2c_send_stop_bit(i2c);
	// Disable Controller
	rk_i2c_disable(i2c);

	return err;
}

static int rk_i2c_write1(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len, uchar *buf, uint b_len)
{
	int err = I2C_OK;
	int TimeOut = I2C_TIMEOUT_US;
	uchar *pbuf = buf,tmp[4];
	uint bytes_remain_len = b_len + r_len + 1;
	uint bytes_tranfered_len = 0;
	uint words_tranfered_len = 0;
	uint txdata;
	uint i, j;

	i2c_info("rk_i2c_write1: chip = %x, reg = %x, r_len = %d, b_len = %d\n", chip, reg, r_len, b_len);

	err = rk_i2c_send_start_bit(i2c);
	if (err != I2C_OK) {
		return err;
	}

	tmp[0] = (uchar)(reg & 0xff);
	tmp[1] = (uchar)((reg >> 8) & 0xff);
	tmp[2] = (uchar)((reg >> 16) & 0xff);
	tmp[3] = (uchar)((reg >> 24) & 0xff);

	if(r_len == 2) {
		reg = (tmp[0] << 8) + tmp[1];		
	} else if(r_len == 3){
		reg = (tmp[0] << 16) + (tmp[1] << 8) + tmp[2];
	} else if(r_len == 4){
		reg = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];
	} else if(r_len > 4){
		i2c_info("I2C Read1: addr len %d not supported\n", r_len);
	} else{
		;
	}

	while (bytes_remain_len) {
		if (bytes_remain_len > RK_I2C_FIFO_SIZE) {
			bytes_tranfered_len = 32;
		} else {
			bytes_tranfered_len = bytes_remain_len;
		}
		words_tranfered_len = RK_CEIL(bytes_tranfered_len, 4);

		for (i = 0; i < words_tranfered_len; i++) {
			txdata = 0;
			for (j = 0; j < 4; j++) {
				if ((i * 4 + j) == bytes_tranfered_len) {
					break;
				}

				if (i == 0 && j == 0) {
					txdata |= (chip << 1);
					i2c_info("I2c Write1 txdata = 0x%x\n", txdata);
				} else if (i == 0 && j <= r_len) {
					txdata |= (reg & (0xff << ((j - 1) * 8))) << 8;
					i2c_info("I2c Write1 txdata = 0x%x\n", txdata);
				} else {
					txdata |= (*pbuf++)<<(j * 8);
					i2c_info("I2c Write1 txdata = 0x%x\n", txdata);
				}
				i2c_writel(txdata, i2c->regs + I2C_TXDATA_BASE + i * 4);				
			}	
			
			i2c_info("I2c Write1 TXDATA[%d] = 0x%x\n", i, txdata);
		}

		i2c_writel(I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TX), i2c->regs + I2C_CON);
		i2c_writel(bytes_tranfered_len, i2c->regs + I2C_MTXCNT);
		i2c_writel(I2C_MBTFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN);

		TimeOut = I2C_TIMEOUT_US;
		while (TimeOut--) {
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_NAKRCVIPD) {
				i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
				err = I2C_ERROR_NOACK;
			}
			if (i2c_readl(i2c->regs + I2C_IPD) & I2C_MBTFIPD) {
				i2c_writel(I2C_MBTFIPD, i2c->regs + I2C_IPD);
				break;
			}
			udelay(1);
		}

		if (TimeOut <= 0) {
			i2c_info("I2C Write1 Data Timeout\n");
			err =  I2C_ERROR_TIMEOUT;
			rk_i2c_show_regs(i2c);
			goto i2c_exit;
		}

		bytes_remain_len -= bytes_tranfered_len;
		i2c_info("I2C Write1 bytes_remain_len %d\n", bytes_remain_len);
	}

i2c_exit:
	// Send stop bit
	rk_i2c_send_stop_bit(i2c);
	// Disable Controller
	rk_i2c_disable(i2c);

	return err;
}

/*
 * i2c_read - Read from i2c memory
 * @chip:	target i2c address
 * @addr:	address to read from
 * @alen:
 * @buffer:	buffer for read data
 * @len:	no of bytes to be read
 *
 * Read from i2c memory.
 */
int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
{

	struct rk_i2c *i2c = (struct rk_i2c *)rk_i2c_get_base();

	if (i2c == NULL) {
		return -1;
	}
	if ((buf == NULL) && (len != 0)) {
		printf("i2c_read: buf == NULL\n");
		return -2;
	}

	return rk_i2c_read(i2c, chip, addr, alen, buf, len);
}


/*
 * i2c_write - Write to i2c memory
 * @chip:	target i2c address
 * @addr:	address to read from
 * @alen:
 * @buffer:	buffer for read data
 * @len:	num of bytes to be read
 *
 * Write to i2c memory.
 */
int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
{

	struct rk_i2c *i2c = (struct rk_i2c *)rk_i2c_get_base();

	if (i2c == NULL) {
		return -1;
	}
	if ((buf == NULL) && (len != 0)) {
		printf("i2c_write: buf == NULL\n");
		return -2;
	}

	return rk_i2c_write(i2c, chip, addr, alen, buf, len);
}

/*
 * i2c_read - Read from i2c memory
 * @chip:	target i2c address
 * @addr:	address to read from
 * @alen:
 * @buffer:	buffer for read data
 * @len:	no of bytes to be read
 *
 * Read from i2c memory.
 */
int i2c_read_x(uchar chip, uint addr, int alen, uchar *buf, int len)
{

	struct rk_i2c *i2c = (struct rk_i2c *)rk_i2c_get_base();

	if (i2c == NULL) {
		return -1;
	}
	if ((buf == NULL) && (len != 0)) {
		printf("i2c_read: buf == NULL\n");
		return -2;
	}

	return rk_i2c_read1(i2c, chip, addr, alen, buf, len);
}


/*
 * i2c_write - Write to i2c memory
 * @chip:	target i2c address
 * @addr:	address to read from
 * @alen:
 * @buffer:	buffer for read data
 * @len:	num of bytes to be read
 *
 * Write to i2c memory.
 */
int i2c_write_x(uchar chip, uint addr, int alen, uchar *buf, int len)
{

	struct rk_i2c *i2c = (struct rk_i2c *)rk_i2c_get_base();

	if (i2c == NULL) {
		return -1;
	}
	if ((buf == NULL) && (len != 0)) {
		printf("i2c_write: buf == NULL\n");
		return -2;
	}

	return rk_i2c_write1(i2c, chip, addr, alen, buf, len);
}


/*
 * Test if a chip at a given address responds (probe the chip)
 */
int i2c_probe(uchar chip)
{
	struct rk_i2c *i2c = (struct rk_i2c *)rk_i2c_get_base();

	i2c_info("i2c_probe\n");

	if (i2c == NULL) {
		return -1;
	}

	return rk_i2c_write(i2c, chip, 0, 0, NULL, 0);
}


/*
 * Init I2C Bus
 */
void i2c_init(int speed, int unused)
{
	i2c_info("i2c_init\n");
	rk_i2c_init(speed);
}

/*
 * Set I2C Speed
 */
int i2c_set_bus_speed(unsigned int speed)
{
	struct rk_i2c *i2c = (struct rk_i2c *)rk_i2c_get_base();

	i2c_info("i2c_set_bus_speed\n");

	if (i2c == NULL) {
		return -1;
	}

	if (g_i2c_online_bus >= I2C_BUS_MAX) {
		return -1;
	}

	rk_i2c_set_clk(i2c, speed);

	return 0;
}

/*
 * Get I2C Speed
 */
unsigned int i2c_get_bus_speed(void)
{
	return 0;
}

int i2c_get_bus_num_fdt(int bus_addr)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(rki2c_base); i++) {
		if ((uint32_t)bus_addr == rki2c_base[i].regs)
			return i;
	}

	printf("%s: Can't find any matched I2C bus\n", __func__);
	return -1;
}

5.重要code 分析:

1)2bytes register addr 读写时,由于原文件是先送低位后送高位,所以reg addr传进函数,先进行高低位置换:

	tmp[0] = (uchar)(reg & 0xff);
	tmp[1] = (uchar)((reg >> 8) & 0xff);
	tmp[2] = (uchar)((reg >> 16) & 0xff);
	tmp[3] = (uchar)((reg >> 24) & 0xff);

	if(r_len == 2) {
		reg = (tmp[0] << 8) + tmp[1];		
	} else if(r_len == 3){
		reg = (tmp[0] << 16) + (tmp[1] << 8) + tmp[2];
	} else if(r_len == 4){
		reg = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];
	} else if(r_len > 4){
		i2c_info("I2C Read1: addr len %d not supported\n", r_len);
	} else{
		;
	}

注意:根据slave device 进行调整,不过一定要注意原code 是先传送的低8位后送高八位!!!

2)2bytes register addr 读时,原code 无法使用(个人认为有误,需要修正):

根据手册可知:

RK3288 android7.1.2 uboot i2c read/write (1byte/2bytes register addr) 以及调用(进阶篇三)_第1张图片

/* the slave register address accessed  for master rx mode */
#define I2C_MRXRADDR        0x00c
#define I2C_MRXRADDR_SET(vld, raddr)    (((vld) << 24) | (raddr))

vld 表示位有效:

vld = 1 表示sraddlvld address low byte valid

vld = 2 表示sraddlvld address middle byte valid

vld = 4 表示sraddlvld address high byte valid

因此1byte vld = 1 ,2bytes vld = 3   3bytes vld = 7

	i2c_writel(I2C_MRXADDR_SET(1, chip << 1 | 1), i2c->regs + I2C_MRXADDR);

	if (r_len == 0) {
		i2c_writel(0, i2c->regs + I2C_MRXRADDR);
	} else if (r_len == 1) {		
		i2c_writel(I2C_MRXRADDR_SET(r_len, reg), i2c->regs + I2C_MRXRADDR);
	} else if (r_len == 2) {
		i2c_writel(I2C_MRXRADDR_SET(r_len + 1, reg), i2c->regs + I2C_MRXRADDR);
	} else if (r_len == 3) {
		i2c_writel(I2C_MRXRADDR_SET(r_len + 4, reg), i2c->regs + I2C_MRXRADDR);
	} else {
		i2c_info("I2C Read1: addr len %d not supported\n", r_len);
		return I2C_ERROR_IO;
	}

 

按照如上改写,测试读正常,使用示波器观察图形正常

 6.读写函数已重写,如何调用上电对slave device 初始化

1)编写头文件rk_i2c.h ,将其放到根目录u-boot/include/ 下

/*opyright (C) ST-Ericsson SA 2009
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifndef _RK_I2C_H_
#define _RK_I2C_H_


int i2c_set_bus_num(unsigned bus_idx);
void i2c_init(int speed, int unused);
int i2c_set_bus_speed(unsigned int speed);
int i2c_probe(uchar chip);
int i2c_read_x(uchar chip, uint addr, int alen, uchar *buf, int len);
int i2c_write_x(uchar chip, uint addr, int alen, uchar *buf, int len);

#endif	/* _RK_I2C_H_ */

2)在根目录u-boot/board/rockchip/ 下,在rk32xx.c 文件中添加rk_i2c.h 头文件以及slave device 的init 函数如下:

static int xxx_device_i2c(void)
{
	unsigned char a[1]={0x41};
	int tmp;

	i2c_set_bus_num(1);
	i2c_init(100000, 0);
	i2c_set_bus_speed(100000);
	tmp = i2c_probe(0x30);
	printf("\n\ni2c_probe = %d\n\n", tmp);

	
	printf("\n\n*****************read/write reg 16bit******************\n\n"); 
	
	mdelay(10);	
	i2c_read_x(0x30, 0x1404, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

	tmp = a[0] << 8;

	mdelay(10);
	i2c_read_x(0x30, 0x1405, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	tmp = tmp + a[0];
	printf("\n\n========================T613 ID = 0x%x==================\n\n",tmp);

	
	mdelay(10);
	i2c_read_x(0x30, 0x2480, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	i2c_read_x(0x30, 0x2482, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	i2c_read_x(0x30, 0x2484, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

	mdelay(10);
	i2c_read_x(0x30, 0x2485, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	a[0] = 0x33;
	i2c_write_x(0x30, 0x2480, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	a[0] = 0x99;
	i2c_write_x(0x30, 0x2488, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	a[0] = 0x66;
	i2c_write_x(0x30, 0x248A, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	

	printf("\n\n*****************read/write reg 8bit******************\n\n"); 
	
	mdelay(100);
	i2c_read_x(0x24, 0x84, 1, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	i2c_read_x(0x24, 0x85, 1, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

	
	mdelay(10);
	a[0] = 0x33;
	i2c_write_x(0x24, 0x80, 1, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

		
	return (0);
}

调用顺序:

RK3288 android7.1.2 uboot i2c read/write (1byte/2bytes register addr) 以及调用(进阶篇三)_第2张图片

 3)在rk32xx.c 中的int board_late_init(void);函数中调用即可,完整code 如下:

/*
 * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
 * Peter, Software Engineering, .
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

//#include 
#include 

#include 
#include 

#include "../common/config.h"
#ifdef CONFIG_OPTEE_CLIENT
#include "../common/rkloader/attestation_key.h"
#endif
enum project_id {
	TinkerBoardS = 0,
	TinkerBoard  = 7,
};

enum pcb_id {
	SR,
	ER,
	PR,
};

extern bool force_ums;

DECLARE_GLOBAL_DATA_PTR;
static ulong get_sp(void)
{
	ulong ret;

	asm("mov %0, sp" : "=r"(ret) : );
	return ret;
}

void board_lmb_reserve(struct lmb *lmb) {
	ulong sp;
	sp = get_sp();
	debug("## Current stack ends at 0x%08lx ", sp);

	/* adjust sp by 64K to be safe */
	sp -= 64<<10;
	lmb_reserve(lmb, sp,
			gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);

	//reserve 48M for kernel & 8M for nand api.
	lmb_reserve(lmb, gd->bd->bi_dram[0].start, CONFIG_LMB_RESERVE_SIZE);
}

int board_storage_init(void)
{
	int ret = 0;

	if (StorageInit() == 0) {
		printf("storage init OK!\n");
		ret = 0;
	} else {
		printf("storage init fail!\n");
		ret = -1;
	}

	return ret;
}


/*****************************************
 * Routine: board_init
 * Description: Early hardware init.
 *****************************************/
int board_init(void)
{
	/* Set Initial global variables */

	gd->bd->bi_arch_number = MACH_TYPE_RK30XX;
	gd->bd->bi_boot_params = PHYS_SDRAM + 0x88000;

	return 0;
}


#ifdef CONFIG_DISPLAY_BOARDINFO
/**
 * Print board information
 */
int checkboard(void)
{
	puts("Board:\tRockchip platform Board\n");
#ifdef CONFIG_SECOND_LEVEL_BOOTLOADER
	printf("Uboot as second level loader\n");
#endif
	return 0;
}
#endif


#ifdef CONFIG_ARCH_EARLY_INIT_R
int arch_early_init_r(void)
{
	debug("arch_early_init_r\n");

	 /* set up exceptions */
	interrupt_init();
	/* enable exceptions */
	enable_interrupts();

	/* rk pl330 dmac init */
#ifdef CONFIG_RK_PL330_DMAC
	rk_pl330_dmac_init_all();
#endif /* CONFIG_RK_PL330_DMAC */

#ifdef CONFIG_RK_PWM_REMOTE
	RemotectlInit();
#endif

	return 0;
}
#endif


#define RAMDISK_ZERO_COPY_SETTING	"0xffffffff=n\0"
static void board_init_adjust_env(void)
{
	bool change = false;

	char *s = getenv("bootdelay");
	if (s != NULL) {
		unsigned long bootdelay = 0;

		bootdelay = simple_strtoul(s, NULL, 16);
		debug("getenv: bootdelay = %lu\n", bootdelay);
#if (CONFIG_BOOTDELAY <= 0)
		if (bootdelay > 0) {
			setenv("bootdelay", simple_itoa(0));
			change = true;
			debug("setenv: bootdelay = 0\n");
		}
#else
		if (bootdelay != CONFIG_BOOTDELAY) {
			setenv("bootdelay", simple_itoa(CONFIG_BOOTDELAY));
			change = true;
			debug("setenv: bootdelay = %d\n", CONFIG_BOOTDELAY);
		}
#endif
	}

	s = getenv("bootcmd");
	if (s != NULL) {
		debug("getenv: bootcmd = %s\n", s);
		if (strcmp(s, CONFIG_BOOTCOMMAND) != 0) {
			setenv("bootcmd", CONFIG_BOOTCOMMAND);
			change = true;
			debug("setenv: bootcmd = %s\n", CONFIG_BOOTCOMMAND);
		}
	}

	s = getenv("initrd_high");
	if (s != NULL) {
		debug("getenv: initrd_high = %s\n", s);
		if (strcmp(s, RAMDISK_ZERO_COPY_SETTING) != 0) {
			setenv("initrd_high", RAMDISK_ZERO_COPY_SETTING);
			change = true;
			debug("setenv: initrd_high = %s\n", RAMDISK_ZERO_COPY_SETTING);
		}
	}

	if (change) {
#ifdef CONFIG_CMD_SAVEENV
		debug("board init saveenv.\n");
		saveenv();
#endif
	}
}

void usb_current_limit_ctrl(bool unlock_current)
{
	printf("%s: unlock_current = %d\n", __func__, unlock_current);

	if(unlock_current == true)
		gpio_direction_output(GPIO_BANK6|GPIO_A6, 1);
	else
		gpio_direction_output(GPIO_BANK6|GPIO_A6, 0);
}

/*
*
* eMMC maskrom mode : GPIO6_A7 (H:disable maskrom, L:enable maskrom)
*
*/
void rk3288_maskrom_ctrl(bool enable_emmc)
{
	printf("%s: enable_emmc = %d\n", __func__, enable_emmc);

	if(enable_emmc == true)
		gpio_direction_output(GPIO_BANK6|GPIO_A7, 1);
	else
		gpio_direction_output(GPIO_BANK6|GPIO_A7, 0);

	mdelay(10);
}

void check_force_enter_ums_mode(void)
{
	enum pcb_id pcbid;
	enum project_id projectid;

	// enable projectid pull down and set it to input
	gpio_pull_updown(GPIO_BANK2|GPIO_A1, GPIOPullUp);
	gpio_pull_updown(GPIO_BANK2|GPIO_A2, GPIOPullUp);
	gpio_pull_updown(GPIO_BANK2|GPIO_A3, GPIOPullUp);
	gpio_direction_input(GPIO_BANK2|GPIO_A1);
	gpio_direction_input(GPIO_BANK2|GPIO_A2);
	gpio_direction_input(GPIO_BANK2|GPIO_A3);

	// set pcbid to input
	gpio_direction_input(GPIO_BANK2|GPIO_B0);

	// disable SDP pull up/down and set it to input
	gpio_pull_updown(GPIO_BANK6|GPIO_A5, PullDisable);
	gpio_direction_input(GPIO_BANK6|GPIO_A5);

	mdelay(10);

	// read project id
	projectid = gpio_get_value(GPIO_BANK2|GPIO_A1) | gpio_get_value(GPIO_BANK2|GPIO_A2)<<1 | gpio_get_value(GPIO_BANK2|GPIO_A3)<<2;

	// read pcbid
	pcbid = gpio_get_value(GPIO_BANK2|GPIO_B0) | gpio_get_value(GPIO_BANK2|GPIO_B1)<<1 | gpio_get_value(GPIO_BANK2|GPIO_B2)<<2;

	// only Tinker Board S and the PR stage PCB has this function
	if(projectid!=TinkerBoard && pcbid >= ER){
		printf("PC event = 0x%x\n", gpio_get_value(GPIO_BANK6|GPIO_A5));
		if(gpio_get_value(GPIO_BANK6|GPIO_A5) == 1){
			// SDP detected, enable EMMC and unlock usb current limit
			printf("usb connected to SDP, force enter ums mode\n");
			force_ums = true;
			// unlock usb current limit and re-enable EMMC
			usb_current_limit_ctrl(true);
			rk3288_maskrom_ctrl(true);
			mdelay(10);
		}
	}
}

static int xxx_device_i2c(void)
{
	unsigned char a[1]={0x41};
	int tmp;

	i2c_set_bus_num(1);
	i2c_init(100000, 0);
	i2c_set_bus_speed(100000);
	tmp = i2c_probe(0x30);
	printf("\n\ni2c_probe = %d\n\n", tmp);

	
	printf("\n\n*****************read/write reg 16bit******************\n\n"); 
	
	mdelay(10);	
	i2c_read_x(0x30, 0x1404, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

	tmp = a[0] << 8;

	mdelay(10);
	i2c_read_x(0x30, 0x1405, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	tmp = tmp + a[0];
	printf("\n\n========================T613 ID = 0x%x==================\n\n",tmp);

	
	mdelay(10);
	i2c_read_x(0x30, 0x2480, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	i2c_read_x(0x30, 0x2482, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	i2c_read_x(0x30, 0x2484, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

	mdelay(10);
	i2c_read_x(0x30, 0x2485, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	a[0] = 0x33;
	i2c_write_x(0x30, 0x2480, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	a[0] = 0x99;
	i2c_write_x(0x30, 0x2488, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	a[0] = 0x66;
	i2c_write_x(0x30, 0x248A, 2, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	

	printf("\n\n*****************read/write reg 8bit******************\n\n"); 
	
	mdelay(100);
	i2c_read_x(0x24, 0x84, 1, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);
	
	mdelay(10);
	i2c_read_x(0x24, 0x85, 1, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

	
	mdelay(10);
	a[0] = 0x33;
	i2c_write_x(0x24, 0x80, 1, a, 1);
	printf("\n\nt613_init = 0x%02x\n\n", a[0]);

		
	return (0);
}


#ifdef CONFIG_BOARD_LATE_INIT
extern char bootloader_ver[24];
int board_late_init(void)
{
	debug("board_late_init\n");

	board_init_adjust_env();

	load_disk_partitions();

	debug("rkimage_prepare_fdt\n");
	rkimage_prepare_fdt();

#ifdef CONFIG_RK_KEY
	debug("key_init\n");
	key_init();
#endif

#ifdef CONFIG_RK_POWER
	debug("fixed_init\n");
	fixed_regulator_init();
	debug("pmic_init\n");
	pmic_init(0);
#if defined(CONFIG_POWER_PWM_REGULATOR)
	debug("pwm_regulator_init\n");
	pwm_regulator_init();
#endif
	debug("fg_init\n");
	fg_init(0); /*fuel gauge init*/
#endif /* CONFIG_RK_POWER */

#if defined(CONFIG_RK_DCF)
	dram_freq_init();
#endif

#ifdef CONFIG_OPTEE_CLIENT
       load_attestation_key();
#endif

	debug("idb init\n");
	//TODO:set those buffers in a better way, and use malloc?
	rkidb_setup_space(gd->arch.rk_global_buf_addr);

	/* after setup space, get id block data first */
	rkidb_get_idblk_data();

	/* Secure boot check after idb data get */
	SecureBootCheck();

	if (rkidb_get_bootloader_ver() == 0) {
		printf("\n#Boot ver: %s\n", bootloader_ver);
	}

	char tmp_buf[32];
	/* rk sn size 30bytes, zero buff */
	memset(tmp_buf, 0, 32);
	if (rkidb_get_sn(tmp_buf)) {
		setenv("fbt_sn#", tmp_buf);
	}

	debug("fbt preboot\n");
	board_fbt_preboot();
	xxx_device_i2c_i2c();

	return 0;
}
#endif

int board_modify_fdt(void)
{
#if defined(CONFIG_RKCHIP_RK3288) && defined(CONFIG_NORMAL_WORLD)
	int ret;

	/* RK3288W HDMI Revision ID is 0x1A */
	if (readl(RKIO_HDMI_PHYS + 0x4) == 0x1A) {
		ret = fdt_setprop_string((void *)gd->fdt_blob, 0,
					 "compatible", "rockchip,rk3288w");
		if (ret) {
			printf("fdt set compatible failed: %d\n", ret);
			return -1;
		}
	}
#endif
	return 0;
}

#ifdef CONFIG_CMD_NET
/*
 * Initializes on-chip ethernet controllers.
 * to override, implement board_eth_init()
 */
int board_eth_init(bd_t *bis)
{
	__maybe_unused int rc;

	debug("board_eth_init\n");

#ifdef CONFIG_RK_GMAC
	char macaddr[6];
	char ethaddr[20];
	char *env_str = NULL;

	memset(ethaddr, sizeof(ethaddr), 0);
	env_str = getenv("ethaddr");
	if (rkidb_get_mac_address(macaddr) == true) {
		sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
			macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);

		printf("mac address: %s\n", ethaddr);

		if (env_str == NULL)
			setenv ((char *)"ethaddr", (char *)ethaddr);
		else if (strncmp(env_str, ethaddr, strlen(ethaddr)) != 0)
			setenv ((char *)"ethaddr", (char *)ethaddr);
	} else {
		uint16_t v;

		v = (rand() & 0xfeff) | 0x0200;
		macaddr[0] = (v >> 8) & 0xff;
		macaddr[1] = v & 0xff;
		v = rand();
		macaddr[2] = (v >> 8) & 0xff;
		macaddr[3] = v & 0xff;
		v = rand();
		macaddr[4] = (v >> 8) & 0xff;
		macaddr[5] = v & 0xff;

		sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
			macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);

		if (env_str == NULL) {
			printf("mac address: %s\n", ethaddr);
			setenv ((char *)"ethaddr", (char *)ethaddr);
		} else {
			printf("mac address: %s\n", env_str);
		}
	}

	rc = rk_gmac_initialize(bis);
	if (rc < 0) {
		printf("rockchip: failed to initialize gmac\n");
		return rc;
	}
#endif /* CONFIG_RK_GMAC */

	return 0;
}
#endif

#ifdef CONFIG_ROCKCHIP_DISPLAY
extern void rockchip_display_fixup(void *blob);
#endif

#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
void ft_board_setup(void *blob, bd_t * bd)
{
#ifdef CONFIG_ROCKCHIP_DISPLAY
        rockchip_display_fixup(blob);
#endif
#ifdef CONFIG_ROCKCHIP
#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
        u64 start, size;
        int offset;

        if (!gd->uboot_logo)
                return;

        start = gd->fb_base;
        offset = gd->fb_offset;
        if (offset > 0)
                size = CONFIG_RK_LCD_SIZE;
        else
                size = CONFIG_RK_FB_SIZE;

        fdt_update_reserved_memory(blob, "rockchip,fb-logo", start, size);
#endif
#endif
}
#endif

 7.改写完成后重新进行如下操作:

echo 对u-boot 进行重新编译,生成新的update.img

cd u-boot

make

cd ..

./mkimage.sh

cd RKTools/linux/Linux_Pack_Firmware/rockdev

./collectImages.sh && ./mkupdate.sh

echo 在windows 下打开 SpiImageTools.exe 加在update.img,会在当前文件夹下产生bin 档(该工具在源码目录下 RKTools\windows)
 
echo 打开Win32diskImager.exe 将bin 档烧写到SD卡中,然后上电启动RK3288

重新上电后,就会对slave device 进行init 操作。

请认真阅读每个步骤上的提示,以及文件放置的相应路径。如果错误,欢迎批评指正,谢谢!

QQ:[email protected] 

你可能感兴趣的:(RK3288,U-BOOT,I2C,android7.1.2,RK3288,android)