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 无法使用(个人认为有误,需要修正):
根据手册可知:
/* 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, .
*
* 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 操作。
请认真阅读每个步骤上的提示,以及文件放置的相应路径。如果错误,欢迎批评指正,谢谢!