123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843 |
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <rthw.h>
- #include "board.h"
- #include "drv_clock.h"
- #include "drv_gpio.h"
- #define I2C_DEBUG 0
- #if I2C_DEBUG
- #define I2C_DBG(...) rt_kprintf("[I2C]"),rt_kprintf(__VA_ARGS__)
- #else
- #define I2C_DBG(...)
- #endif
- #define I2C_CTRL (0x00)
- #define I2C_TAR (0x04)
- #define I2C_SAR (0x08)
- #define I2C_DC (0x10)
- #define I2C_SHCNT (0x14)
- #define I2C_SLCNT (0x18)
- #define I2C_FHCNT (0x1C)
- #define I2C_FLCNT (0x20)
- #define I2C_INTST (0x2C)
- #define I2C_INTM (0x30)
- #define I2C_RXTL (0x38)
- #define I2C_TXTL (0x3c)
- #define I2C_CINTR (0x40)
- #define I2C_CRXUF (0x44)
- #define I2C_CRXOF (0x48)
- #define I2C_CTXOF (0x4C)
- #define I2C_CRXREQ (0x50)
- #define I2C_CTXABRT (0x54)
- #define I2C_CRXDONE (0x58)
- #define I2C_CACT (0x5C)
- #define I2C_CSTP (0x60)
- #define I2C_CSTT (0x64)
- #define I2C_CGC (0x68)
- #define I2C_ENB (0x6C)
- #define I2C_STA (0x70)
- #define I2C_TXFLR (0x74)
- #define I2C_RXFLR (0x78)
- #define I2C_SDAHD (0x7C)
- #define I2C_TXABRT (0x80)
- #define I2C_DMACR (0x88)
- #define I2C_DMATDLR (0x8c)
- #define I2C_DMARDLR (0x90)
- #define I2C_SDASU (0x94)
- #define I2C_ACKGC (0x98)
- #define I2C_ENSTA (0x9C)
- #define I2C_FLT (0xA0)
- /* I2C Control Register (I2C_CTRL) */
- #define I2C_CTRL_SLVDIS (1 << 6) /* after reset slave is disabled */
- #define I2C_CTRL_REST (1 << 5)
- #define I2C_CTRL_MATP (1 << 4) /* 1: 10bit address 0: 7bit addressing */
- #define I2C_CTRL_SATP (1 << 3) /* 1: 10bit address 0: 7bit address */
- #define I2C_CTRL_SPDF (2 << 1) /* fast mode 400kbps */
- #define I2C_CTRL_SPDS (1 << 1) /* standard mode 100kbps */
- #define I2C_CTRL_MD (1 << 0) /* master enabled */
- /* I2C Status Register (I2C_STA) */
- #define I2C_STA_SLVACT (1 << 6) /* Slave FSM is not in IDLE state */
- #define I2C_STA_MSTACT (1 << 5) /* Master FSM is not in IDLE state */
- #define I2C_STA_RFF (1 << 4) /* RFIFO if full */
- #define I2C_STA_RFNE (1 << 3) /* RFIFO is not empty */
- #define I2C_STA_TFE (1 << 2) /* TFIFO is empty */
- #define I2C_STA_TFNF (1 << 1) /* TFIFO is not full */
- #define I2C_STA_ACT (1 << 0) /* I2C Activity Status */
- /* i2c interrupt status (I2C_INTST) */
- #define I2C_INTST_IGC (1 << 11)
- #define I2C_INTST_ISTT (1 << 10)
- #define I2C_INTST_ISTP (1 << 9)
- #define I2C_INTST_IACT (1 << 8)
- #define I2C_INTST_RXDN (1 << 7)
- #define I2C_INTST_TXABT (1 << 6)
- #define I2C_INTST_RDREQ (1 << 5)
- #define I2C_INTST_TXEMP (1 << 4)
- #define I2C_INTST_TXOF (1 << 3)
- #define I2C_INTST_RXFL (1 << 2)
- #define I2C_INTST_RXOF (1 << 1)
- #define I2C_INTST_RXUF (1 << 0)
- /* i2c interrupt mask status (I2C_INTM) */
- #define I2C_INTM_MIGC (1 << 11)
- #define I2C_INTM_MISTT (1 << 10)
- #define I2C_INTM_MISTP (1 << 9)
- #define I2C_INTM_MIACT (1 << 8)
- #define I2C_INTM_MRXDN (1 << 7)
- #define I2C_INTM_MTXABT (1 << 6)
- #define I2C_INTM_MRDREQ (1 << 5)
- #define I2C_INTM_MTXEMP (1 << 4)
- #define I2C_INTM_MTXOF (1 << 3)
- #define I2C_INTM_MRXFL (1 << 2)
- #define I2C_INTM_MRXOF (1 << 1)
- #define I2C_INTM_MRXUF (1 << 0)
- #define I2C_DC_REST (1 << 10)
- #define I2C_DC_STP (1 << 9)
- #define I2C_DC_READ (1 << 8)
- #define I2C_ENB_I2CENB (1 << 0) /* Enable the i2c */
- #define CONFIG_I2C_FIFO_LEN 64
- #define I2C_FIFO_LEN (CONFIG_I2C_FIFO_LEN)
- #define TX_LEVEL (I2C_FIFO_LEN / 2)
- #define RX_LEVEL (I2C_FIFO_LEN / 2 - 1)
- #define TIMEOUT 0xff
- /*
- * msg_end_type: The bus control which need to be send at end of transfer.
- * @MSG_END_STOP: Send stop pulse at end of transfer.
- * @MSG_END_REPEAT_START: Send repeat start at end of transfer.
- */
- enum msg_end_type
- {
- MSG_END_STOP,
- MSG_END_CONTINUE,
- MSG_END_REPEAT_START,
- };
- /* I2C standard mode high count register(I2CSHCNT) */
- #define I2CSHCNT_ADJUST(n) (((n) - 8) < 6 ? 6 : ((n) - 8))
- /* I2C standard mode low count register(I2CSLCNT) */
- #define I2CSLCNT_ADJUST(n) (((n) - 1) < 8 ? 8 : ((n) - 1))
- /* I2C fast mode high count register(I2CFHCNT) */
- #define I2CFHCNT_ADJUST(n) (((n) - 8) < 6 ? 6 : ((n) - 8))
- /* I2C fast mode low count register(I2CFLCNT) */
- #define I2CFLCNT_ADJUST(n) (((n) - 1) < 8 ? 8 : ((n) - 1))
- /* I2C Transmit Abort Status Register (I2C_TXABRT) */
- static const char *abrt_src[] =
- {
- "I2C_TXABRT_ABRT_7B_ADDR_NOACK",
- "I2C_TXABRT_ABRT_10ADDR1_NOACK",
- "I2C_TXABRT_ABRT_10ADDR2_NOACK",
- "I2C_TXABRT_ABRT_XDATA_NOACK",
- "I2C_TXABRT_ABRT_GCALL_NOACK",
- "I2C_TXABRT_ABRT_GCALL_READ",
- "I2C_TXABRT_ABRT_HS_ACKD",
- "I2C_TXABRT_SBYTE_ACKDET",
- "I2C_TXABRT_ABRT_HS_NORSTRT",
- "I2C_TXABRT_SBYTE_NORSTRT",
- "I2C_TXABRT_ABRT_10B_RD_NORSTRT",
- "I2C_TXABRT_ABRT_MASTER_DIS",
- "I2C_TXABRT_ARB_LOST",
- "I2C_TXABRT_SLVFLUSH_TXFIFO",
- "I2C_TXABRT_SLV_ARBLOST",
- "I2C_TXABRT_SLVRD_INTX",
- };
- struct ingenic_i2c_bus
- {
- struct rt_i2c_bus_device parent;
- rt_uint32_t hwaddr;
- rt_uint32_t irqno;
- struct clk *clk;
- enum msg_end_type w_end_type;
- enum msg_end_type r_end_type;
- unsigned char *rbuf;
- unsigned char *wbuf;
- unsigned int rd_len;
- int len;
- unsigned int rate;
- struct rt_completion completion;
- };
- #ifdef RT_USING_I2C0
- static struct ingenic_i2c_bus ingenic_i2c0;
- #endif
- #ifdef RT_USING_I2C1
- static struct ingenic_i2c_bus ingenic_i2c1;
- #endif
- #ifdef RT_USING_I2C2
- static struct ingenic_i2c_bus ingenic_i2c2;
- #endif
- static inline unsigned short i2c_readl(struct ingenic_i2c_bus *i2c,
- unsigned short offset)
- {
- return readl(i2c->hwaddr + offset);
- }
- static inline void i2c_writel(struct ingenic_i2c_bus *i2c, unsigned short offset,
- unsigned short value)
- {
- writel(value, i2c->hwaddr + offset);
- }
- static int ingenic_i2c_disable(struct ingenic_i2c_bus *i2c)
- {
- int timeout = TIMEOUT;
- i2c_writel(i2c, I2C_ENB, 0);
- while ((i2c_readl(i2c, I2C_ENSTA) & I2C_ENB_I2CENB) && (--timeout > 0))
- rt_thread_delay(1);
- if (timeout) return 0;
- I2C_DBG("disable i2c failed!\n");
- return -RT_ETIMEOUT;
- }
- static int ingenic_i2c_enable(struct ingenic_i2c_bus *i2c)
- {
- int timeout = TIMEOUT;
- i2c_writel(i2c, I2C_ENB, 1);
- while (!(i2c_readl(i2c, I2C_ENSTA) & I2C_ENB_I2CENB) && (--timeout > 0))
- rt_thread_delay(1);
- if (timeout) return 0;
- I2C_DBG("enable i2c failed\n");
- return -RT_ETIMEOUT;
- }
- static void ingenic_i2c_reset(struct ingenic_i2c_bus *i2c)
- {
- i2c_readl(i2c, I2C_CTXABRT);
- i2c_readl(i2c, I2C_INTST);
- ingenic_i2c_disable(i2c);
- rt_thread_delay(1);
- ingenic_i2c_enable(i2c);
- }
- static int ingenic_i2c_set_speed(struct ingenic_i2c_bus *i2c, int rate)
- {
- /*ns */
- long dev_clk = clk_get_rate(i2c->clk);
- long cnt_high = 0; /* HIGH period count of the SCL clock */
- long cnt_low = 0; /* LOW period count of the SCL clock */
- long setup_time = 0;
- long hold_time = 0;
- unsigned short tmp;
- i2c->rate = rate;
- if (ingenic_i2c_disable(i2c))I2C_DBG("i2c not disable\n");
- if (rate <= 100000)
- {
- tmp = 0x43 | (1 << 5); /* standard speed mode */
- i2c_writel(i2c, I2C_CTRL, tmp);
- }
- else
- {
- tmp = 0x45 | (1 << 5); /* fast speed mode */
- i2c_writel(i2c, I2C_CTRL, tmp);
- }
- /* high
- * ____ ____ ____ ____
- * clk __| | |___| |____| |____| |___
- * | | |
- * | | |
- * |_|_| _________ ____
- * data __/ | |\___/ \____/ \____
- * setup->| |<|
- * ->| |<-hold
- */
- //setup_time = (10 000 000/(rate*4)) + 1;
- setup_time = (dev_clk / (rate * 4));
- if (setup_time > 1) setup_time -= 1;
- //hold_time = (10000000/(rate*4)) - 1;
- hold_time = (dev_clk / (rate * 4));
- /* high
- * ____ ____
- * clk __| |___| |____
- * low
- * |<--period--->|
- *
- */
- cnt_high = dev_clk / (rate * 2);
- cnt_low = dev_clk / (rate * 2);
- if (setup_time > 255) setup_time = 255;
- if (setup_time <= 0) setup_time = 1;
- if (hold_time > 0xFFFF) hold_time = 0xFFFF;
- if (rate <= 100000)
- {
- i2c_writel(i2c, I2C_SHCNT, I2CSHCNT_ADJUST(cnt_high));
- i2c_writel(i2c, I2C_SLCNT, I2CSLCNT_ADJUST(cnt_low));
- }
- else
- {
- i2c_writel(i2c, I2C_FHCNT, I2CFHCNT_ADJUST(cnt_high));
- i2c_writel(i2c, I2C_FLCNT, I2CFLCNT_ADJUST(cnt_low));
- }
- i2c_writel(i2c, I2C_SDASU, setup_time & 0xff);
- i2c_writel(i2c, I2C_SDAHD, hold_time);
- return 0;
- }
- /* function: send read command
- * return: 0, successful
- * 1, txfifo valid entry is more than receive fifo, before send read command,
- * must be read.
- * 2, txfifo count is 0 or rxfifo count is 0.
- * */
- static inline unsigned int i2c_send_rcmd(struct ingenic_i2c_bus *i2c)
- {
- unsigned int tx_count, rx_count, count, tx_valid, rx_valid;
- tx_valid = i2c_readl(i2c, I2C_TXFLR);
- rx_valid = i2c_readl(i2c, I2C_RXFLR);
- tx_count = I2C_FIFO_LEN - tx_valid;
- rx_count = I2C_FIFO_LEN - rx_valid;
- if (tx_valid > rx_count)
- {
- I2C_DBG("###Warning: I2C transfer fifo valid entry is more receive fifo, "
- "before send read cmd, please read data from "
- "the read fifo.\n");
- return 1;
- }
- if (!tx_count || !rx_count)
- {
- I2C_DBG("###Warning: I2C receive fifo or transfer fifo is full, "
- "before send read cmd, please read data from "
- "the read fifo or wait some time.\n\n");
- return 2;
- }
- count = (i2c->rd_len < tx_count)? i2c->rd_len : tx_count;
- count = (count < rx_count)? count : rx_count;
- i2c->rd_len -= count;
- if (!i2c->rd_len)
- {
- while (count > 1)
- {
- i2c_writel(i2c, I2C_DC, I2C_DC_READ);
- count--;
- }
- if (i2c->r_end_type == MSG_END_STOP)
- {
- i2c_writel(i2c, I2C_DC, I2C_DC_READ | I2C_DC_STP);
- }
- else
- {
- i2c_writel(i2c, I2C_DC, I2C_DC_READ);
- }
- }
- else
- {
- while (count > 0)
- {
- i2c_writel(i2c, I2C_DC, I2C_DC_READ);
- count--;
- }
- }
- return 0;
- }
- static void txabrt(struct ingenic_i2c_bus *i2c, int src)
- {
- int i;
- I2C_DBG("--I2C txabrt:\n");
- for (i = 0; i < 16; i++)
- {
- if (src & (0x1 << i))
- I2C_DBG("--I2C TXABRT[%d]=%s\n", i, abrt_src[i]);
- }
- }
- static int i2c_disable_clk(struct ingenic_i2c_bus *i2c)
- {
- int timeout = 10;
- int tmp = i2c_readl(i2c, I2C_STA);
- while ((tmp & I2C_STA_MSTACT) && (--timeout > 0))
- {
- rt_thread_delay(2);
- tmp = i2c_readl(i2c, I2C_STA);
- }
- if (timeout > 0)
- {
- clk_disable(i2c->clk);
- return 0;
- }
- else
- {
- I2C_DBG("--I2C disable clk timeout, I2C_STA = 0x%x\n", tmp);
- ingenic_i2c_reset(i2c);
- clk_disable(i2c->clk);
- return -RT_ETIMEOUT;
- }
- }
- static inline int xfer_read(struct ingenic_i2c_bus *i2c, unsigned char *buf, int len, enum msg_end_type end_type)
- {
- int ret = 0;
- long timeout;
- unsigned short tmp;
- rt_memset(buf, 0, len);
- i2c->rd_len = len;
- i2c->len = len;
- i2c->rbuf = buf;
- i2c->r_end_type = end_type;
- i2c_readl(i2c, I2C_CSTP); /* clear STP bit */
- i2c_readl(i2c, I2C_CTXOF); /* clear TXOF bit */
- i2c_readl(i2c, I2C_CTXABRT); /* clear TXABRT bit */
- I2C_DBG("i2c: read %d len data\n", len);
- if (len <= I2C_FIFO_LEN)
- {
- i2c_writel(i2c, I2C_RXTL, len - 1);
- }
- else
- {
- i2c_writel(i2c, I2C_RXTL, RX_LEVEL);
- }
- // I2C_DBG("RXTL: %x\n", i2c_readl(i2c, I2C_RXTL));
- I2C_DBG("read len: %d\n", i2c_readl(i2c, I2C_RXFLR));
- while (i2c_readl(i2c, I2C_STA) & I2C_STA_RFNE)
- {
- i2c_readl(i2c, I2C_DC);
- }
- if (i2c_send_rcmd(i2c))
- {
- I2C_DBG("i2c: send read command failed!\n");
- }
- else
- {
- I2C_DBG("i2c: send read command OK!\n");
- }
- tmp = I2C_INTM_MRXFL | I2C_INTM_MTXABT;
- if (end_type == MSG_END_STOP) tmp |= I2C_INTM_MISTP;
- i2c_writel(i2c, I2C_INTM, tmp);
- /* wait for finish */
- while(rt_completion_wait(&(i2c->completion), RT_TICK_PER_SECOND) == -RT_ETIMEOUT)
- I2C_DBG("fifo len: %d\n", i2c_readl(i2c, I2C_RXFLR));
- tmp = i2c_readl(i2c, I2C_TXABRT);
- if (tmp)
- {
- txabrt(i2c, tmp);
- if (tmp > 0x1 && tmp < 0x10)
- ret = -RT_EIO;
- else
- ret = -RT_EIO;
- /* abort read */
- if (tmp & (1 << 5)) {
- ret = -RT_ERROR;
- }
- i2c_readl(i2c, I2C_CTXABRT);
- }
- if (ret < 0) ingenic_i2c_reset(i2c);
- return ret;
- }
- static inline int xfer_write(struct ingenic_i2c_bus *i2c, unsigned char *buf, int len, enum msg_end_type end_type)
- {
- int ret = 0;
- long timeout = TIMEOUT;
- unsigned short reg_tmp;
- i2c->wbuf = buf;
- i2c->len = len;
- i2c_writel(i2c, I2C_TXTL, TX_LEVEL);
- i2c_readl(i2c, I2C_CSTP); /* clear STP bit */
- i2c_readl(i2c, I2C_CTXOF); /* clear TXOF bit */
- i2c_readl(i2c, I2C_CTXABRT); /* clear TXABRT bit */
- I2C_DBG("i2c: write %d len data\n", len);
- i2c->w_end_type = end_type;
- while ((i2c_readl(i2c, I2C_STA) & I2C_STA_TFNF) && (i2c->len > 0))
- {
- reg_tmp = *i2c->wbuf++;
- if (i2c->len == 1)
- {
- if (end_type == MSG_END_STOP)
- {
- reg_tmp |= I2C_DC_STP;
- }
- }
- i2c_writel(i2c, I2C_DC, reg_tmp);
- i2c->len -= 1;
- }
- if (i2c->len == 0)
- {
- i2c_writel(i2c, I2C_TXTL, 0);
- }
- reg_tmp = I2C_INTM_MTXEMP | I2C_INTM_MTXABT | I2C_INTM_MTXOF;
- if (end_type == MSG_END_STOP) reg_tmp |= I2C_INTM_MISTP;
- i2c_writel(i2c, I2C_INTM, reg_tmp);
- /* wait for finish */
- rt_completion_wait(&(i2c->completion), rt_tick_from_millisecond(2000));
- reg_tmp = i2c_readl(i2c, I2C_TXABRT);
- if (reg_tmp)
- {
- txabrt(i2c, reg_tmp);
- if (reg_tmp > 0x1 && reg_tmp < 0x10)
- ret = -RT_EIO;
- else
- ret = -RT_EIO;
- //after I2C_TXABRT_ABRT_XDATA_NOACK error,this required core to resend
- if (reg_tmp & 8)
- {
- ret = -RT_ERROR;
- }
- i2c_readl(i2c, I2C_CTXABRT);
- }
- if (ret < 0) ingenic_i2c_reset(i2c);
- return ret;
- }
- static rt_size_t ingenic_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
- {
- int i;
- int ret = RT_EOK;
- struct ingenic_i2c_bus *i2c;
- i2c = (struct ingenic_i2c_bus*)bus;
- clk_enable(i2c->clk);
- i2c_writel(i2c, I2C_TAR, msgs[0].addr);
- for (i = 0; i < num; i++)
- {
- enum msg_end_type end_type = MSG_END_STOP;
- if (i < (num - 1))
- {
- if (msgs[i + 1].flags & RT_I2C_NO_START)
- {
- end_type = MSG_END_CONTINUE; /* have no STOP and START */
- }
- else
- {
- end_type = MSG_END_REPEAT_START; /* have no STOP but have RESTART */
- }
- }
- /* initialize completion */
- rt_completion_init(&(i2c->completion));
- if (msgs[i].flags & RT_I2C_RD)
- {
- ret = xfer_read(i2c, msgs[i].buf, msgs[i].len, end_type);
- }
- else
- {
- ret = xfer_write(i2c, msgs[i].buf, msgs[i].len, end_type);
- }
- if (ret < 0)
- {
- clk_disable(i2c->clk);
- goto _ERR;
- }
- }
- ret = i2c_disable_clk(i2c);
- _ERR:
- return ret < 0? ret : i;
- }
- static const struct rt_i2c_bus_device_ops i2c_ops =
- {
- ingenic_i2c_xfer,
- RT_NULL,
- RT_NULL
- };
- static void i2c_irq_handler(int irqno, void *param)
- {
- unsigned short tmp, intst, intmsk;
- struct ingenic_i2c_bus *i2c;
- i2c = (struct ingenic_i2c_bus*)param;
- intst = i2c_readl(i2c, I2C_INTST);
- intmsk = i2c_readl(i2c, I2C_INTM);
- I2C_DBG("i2c irq!!\n");
- if ((intst & I2C_INTST_TXABT) && (intmsk & I2C_INTM_MTXABT))
- {
- I2C_DBG("%s %d, I2C transfer error, ABORT interrupt\n", __func__, __LINE__);
- goto END_TRSF_IRQ_HND;
- }
- if ((intst & I2C_INTST_ISTP) && (intmsk & I2C_INTM_MISTP))
- {
- i2c_readl(i2c, I2C_CSTP); /* clear STP bit */
- if (i2c->len == 0)
- goto END_TRSF_IRQ_HND;
- }
- if ((intmsk & I2C_INTM_MTXEMP) && (intst & I2C_INTST_TXEMP))
- {
- if (!i2c->len)
- {
- if (i2c->w_end_type == MSG_END_REPEAT_START)
- {
- goto END_TRSF_IRQ_HND;
- }
- else
- {
- tmp = i2c_readl(i2c, I2C_INTM);
- tmp &= ~I2C_INTM_MTXEMP;
- i2c_writel(i2c, I2C_INTM, tmp);
- }
- }
- else
- {
- while ((i2c->len > 0) && (i2c_readl(i2c, I2C_STA) & I2C_STA_TFNF))
- {
- tmp = *i2c->wbuf++;
- if (i2c->len == 1)
- {
- if (i2c->w_end_type == MSG_END_STOP)
- tmp |= I2C_DC_STP;
- }
- i2c_writel(i2c, I2C_DC, tmp);
- i2c->len -= 1;
- }
- if (i2c->len == 0)
- {
- i2c_writel(i2c, I2C_TXTL, 0);
- }
- }
- }
- if ((intst & I2C_INTST_RXFL) && (intmsk & I2C_INTM_MRXFL))
- {
- I2C_DBG("I2C RXFL\n");
- while ((i2c_readl(i2c, I2C_STA) & I2C_STA_RFNE) && (i2c->len > 0))
- {
- tmp = i2c_readl(i2c, I2C_DC) & 0xff;
- *i2c->rbuf++ = tmp;
- i2c->len--;
- }
- if (i2c->len == 0)
- {
- goto END_RECE_IRQ_HND;
- }
- if (i2c->len <= I2C_FIFO_LEN)
- {
- i2c_writel(i2c, I2C_RXTL, i2c->len - 1);
- }
- if (i2c_send_rcmd(i2c))
- {
- I2C_DBG("%s %d, I2C controller has BUG, RXFLR or TXFLR can not clear\n", __func__, __LINE__);
- }
- }
- if ((intst & I2C_INTST_RXOF) && (intmsk & I2C_INTM_MRXOF))
- {
- I2C_DBG("%s %d, I2C transfer error, RXFIFO over full\n", __func__, __LINE__);
- i2c_readl(i2c, I2C_CRXOF); /* clear RXOF bit */
- }
- if ((intst & I2C_INTST_TXOF) && (intmsk & I2C_INTM_MTXOF))
- {
- I2C_DBG("%s %d, I2C transfer error, TXFIFO over full\n", __func__, __LINE__);
- i2c_readl(i2c, I2C_CTXOF); /* clear TXOF bit */
- goto END_TRSF_IRQ_HND;
- }
- return ;
- END_RECE_IRQ_HND:
- END_TRSF_IRQ_HND:
- i2c_writel(i2c, I2C_INTM, 0);
- rt_completion_done(&i2c->completion);
- }
- int rt_hw_i2c_init(void)
- {
- struct ingenic_i2c_bus *i2c;
- struct rt_i2c_bus_device *i2c_bus;
- #ifdef RT_USING_I2C0
- {
- i2c = &ingenic_i2c0;
- rt_memset((void *)i2c, 0, sizeof(struct ingenic_i2c_bus));
- i2c->hwaddr = I2C0_BASE;
- i2c->irqno = IRQ_I2C0;
- /* Set PB23 PB24 in func0 (I2C0) */
- gpio_set_func(GPIO_PORT_B, GPIO_Pin_24, GPIO_FUNC_0);
- gpio_set_func(GPIO_PORT_B, GPIO_Pin_23, GPIO_FUNC_0);
- /* enable clock */
- i2c->clk = clk_get("i2c0");
- clk_enable(i2c->clk);
- i2c_bus = &i2c->parent;
- i2c_bus->ops = &i2c_ops;
- rt_i2c_bus_device_register(i2c_bus, "i2c0");
- ingenic_i2c_set_speed(i2c, 400 * 1000);
- /* reset I2C */
- i2c_writel(i2c, I2C_CTRL, i2c_readl(i2c, I2C_CTRL) | I2C_CTRL_REST);
- i2c_writel(i2c, I2C_INTM, 0x0);
- ingenic_i2c_enable(i2c);
- clk_disable(i2c->clk);
- /* install interrupt */
- rt_hw_interrupt_install(i2c->irqno, i2c_irq_handler, i2c, "i2c0");
- rt_hw_interrupt_umask(i2c->irqno);
- }
- #endif
- #ifdef RT_USING_I2C1
- {
- i2c = &ingenic_i2c1;
- rt_memset((void *)i2c, 0, sizeof(struct ingenic_i2c_bus));
- i2c->hwaddr = I2C1_BASE;
- i2c->irqno = IRQ_I2C1;
- /* Set PC26 PC27 in func0 (I2C1) */
- gpio_set_func(GPIO_PORT_C, GPIO_Pin_26, GPIO_FUNC_0);
- gpio_set_func(GPIO_PORT_C, GPIO_Pin_27, GPIO_FUNC_0);
- /* enable clock */
- i2c->clk = clk_get("i2c1");
- clk_enable(i2c->clk);
- i2c_bus = &i2c->parent;
- i2c_bus->ops = &i2c_ops;
- rt_i2c_bus_device_register(i2c_bus, "i2c1");
- ingenic_i2c_set_speed(i2c, 400 * 1000);
- /* reset I2C */
- i2c_writel(i2c, I2C_CTRL, i2c_readl(i2c, I2C_CTRL) | I2C_CTRL_REST);
- i2c_writel(i2c, I2C_INTM, 0x0);
- ingenic_i2c_enable(i2c);
- clk_disable(i2c->clk);
- /* install interrupt */
- rt_hw_interrupt_install(i2c->irqno, i2c_irq_handler, i2c, "i2c1");
- rt_hw_interrupt_umask(i2c->irqno);
- }
- #endif
- #ifdef RT_USING_I2C2
- {
- i2c = &ingenic_i2c2;
- rt_memset((void *)i2c, 0, sizeof(struct ingenic_i2c_bus));
- i2c->hwaddr = I2C2_BASE;
- i2c->irqno = IRQ_I2C2;
- /* Set PC26 PC27 in func0 (I2C1) */
- gpio_set_func(GPIO_PORT_D, GPIO_Pin_0, GPIO_FUNC_1);
- gpio_set_func(GPIO_PORT_D, GPIO_Pin_1, GPIO_FUNC_1);
- /* enable clock */
- i2c->clk = clk_get("i2c2");
- clk_enable(i2c->clk);
- i2c_bus = &i2c->parent;
- i2c_bus->ops = &i2c_ops;
- rt_i2c_bus_device_register(i2c_bus, "i2c2");
- ingenic_i2c_set_speed(i2c, 400 * 1000);
- /* reset I2C */
- i2c_writel(i2c, I2C_CTRL, i2c_readl(i2c, I2C_CTRL) | I2C_CTRL_REST);
- i2c_writel(i2c, I2C_INTM, 0x0);
- ingenic_i2c_enable(i2c);
- clk_disable(i2c->clk);
- /* install interrupt */
- rt_hw_interrupt_install(i2c->irqno, i2c_irq_handler, i2c, "i2c2");
- rt_hw_interrupt_umask(i2c->irqno);
- }
- #endif
- return 0;
- }
- INIT_BOARD_EXPORT(rt_hw_i2c_init);
|