RK3288 android7.1.2 uboot i2c read/write (1byte/2bytes register addr) 以及调用(进阶篇三)_i2c_write_Chhjnavy的博客-程序员秘密

技术标签: android  I2C  RK3288  U-BOOT  android7.1.2  

一 . 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, <[email protected]>.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#include <common.h>
#include <asm/io.h>
#include <linux/sizes.h>
#include <i2c.h>
#include <asm/arch/rkplat.h>


#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 无法使用(个人认为有误,需要修正):

根据手册可知:

/* 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);
}

调用顺序:

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

/*
 * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
 * Peter, Software Engineering, <[email protected]>.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#include <common.h>
#include <version.h>
#include <errno.h>
#include <fastboot.h>
#include <fdtdec.h>
#include <fdt_support.h>
#include <power/pmic.h>

#include <rk_i2c.h>

//#include <rk_spi.h>
#include <spi.h>

#include <asm/io.h>
#include <asm/arch/rkplat.h>

#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] 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Chhjnavy/article/details/98652758

智能推荐

在没有前端Web HTML,CSS,JavaScript技术知识情况下使用Delphi / C ++ Builder快速开发构建Web前端B/S应用_cbuilder web mvc_xyzhan的博客-程序员秘密

对标题感到惊讶?是的,如果您不了解HTML,CSS,JavaScript,则可以使用某些Client / Server(FullStack)或Client-Focused第三方Web框架从Delphi / C ++ Builder构建Web前端。想知道这些框架是如何做到的?这篇文章将帮助您理解。Delphi intraweb结合Cesium开发WEBGIS前端Web前端框架的功能是什么:视觉布局在IDE中设计,可以在浏览器中使用HTML,Javascript和CSS进行呈现。使用Delphi或

消息模式 之 消息100%投递、幂等性、Confirm确认消息、Return返回消息、自定义消费者_消息投递模式_一只媛球球的博客-程序员秘密

消息模式消息100%的投递幂等性概念Confirm确认消息Return返回消息自定义消费者本章知识:1、消息如何保证100%的投递?2、幂等性概念3、Confirm 确认消息4、Return 返回消息5、自定义消费者消息100%的投递可参考 -------- RabbitMQ 快速入门:https://blog.csdn.net/qq_44641053/article/detail...

使用HBuilder软件浏览HTML页面,显示127.0.0.1 拒绝了我们的连接请求。_hbuider浏览器运行打不开127.0.0.1:8848/_小驼背十三的博客-程序员秘密

第一步:配置web服务器第二,如果第一步未解决进行该步骤控制面板—》程序—》打开或关闭windows功能

算法实习准备之五:算法岗面试整理_雾容的博客-程序员秘密

算法实习准备之五算法岗面试整理CVFaster-RCNNCNN卷积池化全连接层反向传播LSTMAttentionTranformer机器学习算法线性回归LRSVM优化方法梯度下降法正则化NLPword2vecBert算法岗面试整理CVFaster-RCNNCNN卷积解释卷积层的最佳方法是想象有一束手电筒光正从图像的左上角照过。假设手电筒光可以覆盖 5 x 5 的区域,想象一下手电筒光照过输入图像的所有区域。在机器学习术语中,这束手电筒被叫做过滤器(filter,有时候也被称为神经元(neuron

VB仿大漠GDI模式后台找图找色-揭秘后台图色窗口不黑的原理_vb 找图_sdgaojian的博客-程序员秘密

记得老版的梦工厂论坛曾经有人讨论过,为什么youxi使用PrintWindow有时能截图有时却不能(有的youxi压根没成功过),其实大漠的GDI模式的图色,截图同样使用的是这个函数,只不过它在printwindow前对窗口做了处理(为什么窗口要部分移出屏幕,为什么会有绑定窗口这一步),关键函数 SetWindowLong   GetWindowLong[Visual Basic] 纯

乘法算法-Karatsuba算法_jiyanfeng1的博客-程序员秘密

考虑两个n位整数x和y的乘法。基本的算法是O(n^2)的。以10进制为例,用bigint表示大整数类型,s[1]表示个位,len为位数。按照小学数学多位数乘法法则,程序如下:bigint mult(bigint a, bigint b){ bigint c; c.len = a.len + b.len ; for(int i=1; i <= c.len; i++) c.s[i]

随便推点

实现多个大文件拖拽上传+大文件分片上传+断点续传+文件预览_小琳同学的博客-程序员秘密

前言之前看了掘友写了一个单文件分片上传和断点续传的文章,对此充满了兴趣,因此开始自研学习。经过一段时间的学习,自己动手写了一个小demo。这篇文章将记录自己coding遇见的问题和总结自己小demo的思路。技术关键词前端:@vue/cli-service+element-ui+axios后端:node.js+koacoding思路分析拖拽上传拖拽上传是利用HTML5新特性实现拖拽上传,详细用法可阅读MDN-drag利用dragover事件(当某物被拖动的对象在另一对象容器范围内拖动时触发此事

从区块技术的发展历史看区块链是什么?_区块链是技术的心血_共识区块链技术社区的博客-程序员秘密

哲学的终极三问:“我是谁?我从哪里来?我要到哪里去?” 耗费古今中外多少人的心血。作为区块链的从业者,也面临有三个根本性问题:区块链是什么?区块链怎么产生的?区块链有什么用?追根溯源,本文尝试从区块链技术的产生背景和技术演进过程来回答:区块链是什么呢?希望对大家理解区块链有所帮助。区块链前传之密码朋克任何事情的兴起都有量变到质变的过程,看似横空出世,其实背后都有发...

服务器64位还是32位系统好,云服务器64位还是32位_weixin_39731586的博客-程序员秘密

云服务器64位还是32位 内容精选换一换Windows操作系统与Linux操作系统没有好坏之分,只有适合不适合。请根据业务需求选择Windows或Linux的操作系统。华为云提供了5个版本,且每个版本还有32位、64位,以及中英文的区分。微软已停止对Windows2003、Windows2008操作系统的维护支持,华为云已下线Windows Server 2008操作系统公共镜华为云弹性云服务器(...

Jsoncpp编译与使用基础_SyGoing的博客-程序员秘密

                                   Jsoncpp编译与使用基础                                                                          ---唠叨一句:不积跬步无以至千里1、Json编译1.1   库准备Jsoncpp库(jsoncpp-src-0.5.0.tar.gz)下...

统计学——基于R(第3版)(基于R应用的统计学丛书)作者:贾俊平 习题答案 第四章_统计学导论基于r语言第四章答案_禾了了的博客-程序员秘密

load("C:/exercise/ch4/exercise4_1.RData")exercise4_1#4.1sum(0.209,0.223,0.178,0.114)sum(0.041,0.130)sum(0.061,0.028,0.011,0.004,0.001)#4.2#(1)dbinom(2,4,0.1)#(2)pbinom(1,4,0.1)#4.3...

PCL高斯滤波两种方法:pcl::filters::GaussianKernel和pcl::filter::Convolution使用的报错问题_pcl/filters/gaussian.h_么么儿panda的博客-程序员秘密

想调用pcl高斯滤波函数进行点云处理中,先参考了两种网上的pcl高斯滤波程序,在VS2013中运行报错,一直未能解决,求助!!!方法1:(参考文章:https://blog.csdn.net/fandq1223/article/details/53183489)#include &amp;lt;iostream&amp;gt;#include &amp;lt;pcl/io/pcd_io.h&amp;gt;#incl...

推荐文章

热门文章

相关标签