瑞芯微Rockchip开发者社区
直播中

杨福林

7年用户 1555经验值
私信 关注
[问答]

怎样去调用rk3288 android7.1.2 u-boot i2c呢

怎样去调用rk3288 android7.1.2 u-boot i2c呢?有哪些基本步骤?

回帖(5)

张翔

2022-3-3 17:06:06
一 . 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 = %dn", i2c_rate, scl_rate);
        i2c_info("set i2c clk div = %d, divh = %d, divl = %dn", 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 = %dn", 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%08xn", i2c_readl(i2c->regs + I2C_CON));
        i2c_info("I2C_CLKDIV: 0x%08xn", i2c_readl(i2c->regs + I2C_CLKDIV));
        i2c_info("I2C_MRXADDR: 0x%08xn", i2c_readl(i2c->regs + I2C_MRXADDR));
        i2c_info("I2C_MRXRADDR: 0x%08xn", i2c_readl(i2c->regs + I2C_MRXRADDR));
        i2c_info("I2C_MTXCNT: 0x%08xn", i2c_readl(i2c->regs + I2C_MTXCNT));
        i2c_info("I2C_MRXCNT: 0x%08xn", i2c_readl(i2c->regs + I2C_MRXCNT));
        i2c_info("I2C_IEN: 0x%08xn", i2c_readl(i2c->regs + I2C_IEN));
        i2c_info("I2C_IPD: 0x%08xn", i2c_readl(i2c->regs + I2C_IPD));
        i2c_info("I2C_FCNT: 0x%08xn", i2c_readl(i2c->regs + I2C_FCNT));
        for (i = 0; i < 8; i ++) {
                i2c_info("I2C_TXDATA%d: 0x%08xn", i, i2c_readl(i2c->regs + I2C_TXDATA_BASE + i * 4));
        }
        for (i = 0; i < 8; i ++) {
                i2c_info("I2C_RXDATA%d: 0x%08xn", 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 Timeoutn");
                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 Timeoutn");
                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 = %dn", 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 supportedn", 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 Timeoutn");
                        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%xn", 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 %dn", 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 = %dn", 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%xn", (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%xn", i, txdata);
                        printf("I2c Write TXDATA[%d] = 0x%xn", 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 Timeoutn");
                        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 %dn", 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 = %dn", 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
举报

崔映芬

2022-3-3 17:06:44
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 = %dn", 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 supportedn", 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 supportedn", 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 Timeoutn");
                        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%xn", 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 %dn", 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 = %dn", 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 supportedn", 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%xn", txdata);
                                } else if (i == 0 && j <= r_len) {
                                        txdata |= (reg & (0xff << ((j - 1) * 8))) << 8;
                                        i2c_info("I2c Write1 txdata = 0x%xn", txdata);
                                } else {
                                        txdata |= (*pbuf++)<<(j * 8);
                                        i2c_info("I2c Write1 txdata = 0x%xn", txdata);
                                }
                                i2c_writel(txdata, i2c->regs + I2C_TXDATA_BASE + i * 4);                              
                        }      
                       
                        i2c_info("I2c Write1 TXDATA[%d] = 0x%xn", 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 Timeoutn");
                        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 %dn", 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 == NULLn");
                return -2;
        }

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

刘琨

2022-3-3 17:07:47
/*
* 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 == NULLn");
                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 == NULLn");
                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 == NULLn");
                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_proben");

        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_initn");
        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_speedn");

        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.regs)
                        return i;
        }

        printf("%s: Can't find any matched I2C busn", __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 supportedn", 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 supportedn", 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("nni2c_probe = %dnn", tmp);

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

        tmp = a[0] << 8;

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

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

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

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

      
        mdelay(10);
        a[0] = 0x33;
        i2c_write_x(0x24, 0x80, 1, a, 1);
        printf("nnt613_init = 0x%02xnn", 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, <
superpeter.cai@gmail.com>.
*
* 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;
}
举报

云静京

2022-3-3 17:08:34
/*****************************************
* 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 Boardn");
#ifdef CONFIG_SECOND_LEVEL_BOOTLOADER
        printf("Uboot as second level loadern");
#endif
        return 0;
}
#endif


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

         /* 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"
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 = %lun", bootdelay);
#if (CONFIG_BOOTDELAY <= 0)
                if (bootdelay > 0) {
                        setenv("bootdelay", simple_itoa(0));
                        change = true;
                        debug("setenv: bootdelay = 0n");
                }
#else
                if (bootdelay != CONFIG_BOOTDELAY) {
                        setenv("bootdelay", simple_itoa(CONFIG_BOOTDELAY));
                        change = true;
                        debug("setenv: bootdelay = %dn", CONFIG_BOOTDELAY);
                }
#endif
        }

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

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

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

void u***_current_limit_ctrl(bool unlock_current)
{
        printf("%s: unlock_current = %dn", __func__, unlock_current);

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

举报

丁滢

2022-3-3 17:08:37
/*
*
* eMMC maskrom mode : GPIO6_A7 (H:disable maskrom, L:enable maskrom)
*
*/
void rk3288_maskrom_ctrl(bool enable_emmc)
{
        printf("%s: enable_emmc = %dn", __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%xn", gpio_get_value(GPIO_BANK6|GPIO_A5));
                if(gpio_get_value(GPIO_BANK6|GPIO_A5) == 1){
                        // SDP detected, enable EMMC and unlock u*** current limit
                        printf("u*** connected to SDP, force enter ums moden");
                        force_ums = true;
                        // unlock u*** current limit and re-enable EMMC
                        u***_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("nni2c_probe = %dnn", tmp);

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

        tmp = a[0] << 8;

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

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

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

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

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

               
        return (0);
}


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

        board_init_adjust_env();

        load_disk_partitions();

        debug("rkimage_prepare_fdtn");
        rkimage_prepare_fdt();

#ifdef CONFIG_RK_KEY
        debug("key_initn");
        key_init();
#endif

#ifdef CONFIG_RK_POWER
        debug("fixed_initn");
        fixed_regulator_init();
        debug("pmic_initn");
        pmic_init(0);
#if defined(CONFIG_POWER_PWM_REGULATOR)
        debug("pwm_regulator_initn");
        pwm_regulator_init();
#endif
        debug("fg_initn");
        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 initn");
        //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: %sn", 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 prebootn");
        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: %dn", 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_initn");

#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: %sn", 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: %sn", ethaddr);
                        setenv ((char *)"ethaddr", (char *)ethaddr);
                } else {
                        printf("mac address: %sn", env_str);
                }
        }

        rc = rk_gmac_initialize(bis);
        if (rc < 0) {
                printf("rockchip: failed to initialize gmacn");
                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 档(该工具在源码目录下 RKToolswindows)

echo 打开Win32diskImager.exe 将bin 档烧写到SD卡中,然后上电启动RK3288
重新上电后,就会对slave device 进行init 操作。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分