dw_iic.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /******************************************************************************
  17. * @file dw_iic.c
  18. * @brief CSI Source File for IIC Driver
  19. * @version V1.0
  20. * @date 02. June 2017
  21. ******************************************************************************/
  22. #include "csi_core.h"
  23. #include "drv_iic.h"
  24. #include "dw_iic.h"
  25. #include "soc.h"
  26. #include "string.h"
  27. #define ERR_IIC(errno) (CSI_DRV_ERRNO_I2C_BASE | errno)
  28. #define IIC_NULL_PARAM_CHK(para) \
  29. do { \
  30. if (para == NULL) { \
  31. return ERR_IIC(EDRV_PARAMETER); \
  32. } \
  33. } while (0)
  34. typedef struct {
  35. uint32_t base;
  36. uint32_t irq;
  37. iic_event_cb_t cb_event;
  38. void *cb_arg;
  39. uint32_t rx_total_num;
  40. uint32_t tx_total_num;
  41. void *rx_buf;
  42. void *tx_buf;
  43. volatile uint32_t rx_cnt;
  44. volatile uint32_t tx_cnt;
  45. uint32_t status; ///< status of iic transfer
  46. } dw_iic_priv_t;
  47. static dw_iic_priv_t iic_instance[CONFIG_IIC_NUM];
  48. static const iic_capabilities_t iic_capabilities = {
  49. .address_10_bit = 0 /* supports 10-bit addressing */
  50. };
  51. static inline void dw_iic_disable(dw_iic_reg_t *addr)
  52. {
  53. /* First clear ACTIVITY, then Disable IIC */
  54. addr->IC_CLR_ACTIVITY;
  55. addr->IC_ENABLE = DW_IIC_DISABLE;
  56. }
  57. static inline void dw_iic_enable(dw_iic_reg_t *addr)
  58. {
  59. addr->IC_ENABLE = DW_IIC_ENABLE;
  60. }
  61. static inline void dw_iic_set_transfer_speed(dw_iic_reg_t *addr, DWENUM_IIC_SPEED speed)
  62. {
  63. uint16_t temp = addr->IC_CON;
  64. temp &= ~((1 << 1) + (1 << 2));
  65. temp |= speed << 1;
  66. addr->IC_CON = temp;
  67. }
  68. static inline void dw_iic_set_target_address(dw_iic_reg_t *addr, uint16_t address)
  69. {
  70. uint16_t temp = addr->IC_TAR;
  71. temp &= 0xfc00;
  72. temp |= address;
  73. addr->IC_TAR = temp;
  74. }
  75. static inline void dw_iic_set_addr_mode(dw_iic_reg_t *addr, iic_address_mode_e addr_mode)
  76. {
  77. uint16_t temp = addr->IC_TAR;
  78. temp &= 0xefff;
  79. temp |= addr_mode << 12;
  80. addr->IC_TAR = temp;
  81. }
  82. static void dw_i2c_int_clear(dw_iic_reg_t *addr, DWENUM_IIC_INTERRUPT_TYPE type)
  83. {
  84. uint32_t temp = 0;
  85. switch (type) {
  86. case DW_IIC_RX_UNDER:
  87. temp = addr->IC_CLR_RX_UNDER;
  88. break;
  89. case DW_IIC_RX_OVER:
  90. temp = addr->IC_CLR_RX_OVER;
  91. break;
  92. case DW_IIC_TX_OVER:
  93. temp = addr->IC_CLR_TX_OVER;
  94. break;
  95. case DW_IIC_RD_REQ:
  96. temp = addr->IC_CLR_RD_REQ;
  97. break;
  98. case DW_IIC_TX_ABRT:
  99. temp = addr->IC_CLR_TX_ABRT;
  100. break;
  101. case DW_IIC_RX_DONE:
  102. temp = addr->IC_CLR_RX_DONE;
  103. break;
  104. case DW_IIC_ACTIVITY:
  105. temp = addr->IC_CLR_ACTIVITY;
  106. break;
  107. case DW_IIC_STOP_DET:
  108. temp = addr->IC_CLR_STOP_DET;
  109. break;
  110. case DW_IIC_START_DET:
  111. temp = addr->IC_CLR_START_DET;
  112. break;
  113. case DW_IIC_GEN_CALL:
  114. temp = addr->IC_CLR_GEN_CALL;
  115. break;
  116. default:
  117. temp = addr->IC_CLR_INTR;
  118. }
  119. }
  120. /**
  121. \brief interrupt service function for transmit FIFO empty interrupt.
  122. \param[in] iic_priv pointer to iic private.
  123. */
  124. static void dw_iic_intr_tx_empty(dw_iic_priv_t *iic_priv)
  125. {
  126. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  127. if (addr->IC_INTR_STAT & (1 << DW_IIC_TX_EMPTY)) {
  128. uint32_t remain_txfifo = iic_priv->tx_total_num - iic_priv->tx_cnt;
  129. uint8_t emptyfifo = (remain_txfifo > (DW_IIC_FIFO_MAX_LV - addr->IC_TXFLR)) ? DW_IIC_FIFO_MAX_LV - addr->IC_TXFLR : remain_txfifo;
  130. uint32_t i = 0u;
  131. for (i = 0; i < emptyfifo; i++) {
  132. addr->IC_DATA_CMD = *((uint8_t *)(iic_priv->tx_buf)++);
  133. }
  134. iic_priv->tx_cnt += emptyfifo;
  135. if (iic_priv->tx_cnt == iic_priv->tx_total_num) {
  136. addr->IC_INTR_MASK &= ~(1 << DW_IIC_TX_EMPTY);
  137. }
  138. }
  139. if (addr->IC_INTR_STAT & (1 << DW_IIC_TX_OVER)) {
  140. dw_i2c_int_clear(addr, DW_IIC_TX_OVER);
  141. iic_priv->status = IIC_STATE_ERROR;
  142. dw_iic_disable(addr);
  143. if (iic_priv->cb_event) {
  144. iic_priv->cb_event(I2C_EVENT_BUS_ERROR, iic_priv->cb_arg);
  145. }
  146. }
  147. if (addr->IC_INTR_STAT & (1 << DW_IIC_TX_ABRT)) {
  148. dw_i2c_int_clear(addr, DW_IIC_TX_ABRT);
  149. iic_priv->status = IIC_STATE_ERROR;
  150. dw_iic_disable(addr);
  151. if (iic_priv->cb_event) {
  152. iic_priv->cb_event(I2C_EVENT_BUS_ERROR, iic_priv->cb_arg);
  153. }
  154. }
  155. if (addr->IC_INTR_STAT & (1 << DW_IIC_STOP_DET)) {
  156. iic_priv->status = IIC_STATE_DONE;
  157. dw_i2c_int_clear(addr, DW_IIC_STOP_DET);
  158. if (iic_priv->cb_event) {
  159. dw_iic_disable(addr);
  160. addr->IC_CLR_INTR;
  161. iic_priv->cb_event(I2C_EVENT_TRANSFER_DONE, iic_priv->cb_arg);
  162. }
  163. }
  164. }
  165. /**
  166. \brief interrupt service function for receive FIFO full interrupt .
  167. \param[in] iic_priv pointer to iic private.
  168. */
  169. static void dw_iic_intr_rx_full(dw_iic_priv_t *iic_priv)
  170. {
  171. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  172. if (addr->IC_INTR_STAT & (1 << DW_IIC_RX_FULL)) {
  173. uint8_t emptyfifo = addr->IC_RXFLR;
  174. uint32_t i = 0u;
  175. for (i = 0; i < emptyfifo ; i++) {
  176. *((uint8_t *)(iic_priv->rx_buf++)) = ((addr->IC_DATA_CMD) & 0xff);
  177. }
  178. iic_priv->rx_cnt += emptyfifo;
  179. if (iic_priv->rx_cnt != iic_priv->rx_total_num) {
  180. addr->IC_DATA_CMD = 1 << 8;
  181. }
  182. }
  183. if (addr->IC_INTR_STAT & (1 << DW_IIC_RX_OVER)) {
  184. dw_i2c_int_clear(addr, DW_IIC_RX_OVER);
  185. iic_priv->status = IIC_STATE_ERROR;
  186. dw_iic_disable(addr);
  187. if (iic_priv->cb_event) {
  188. iic_priv->cb_event(I2C_EVENT_BUS_ERROR, iic_priv->cb_arg);
  189. }
  190. }
  191. if (addr->IC_INTR_STAT & (1 << DW_IIC_RX_FULL)) {
  192. dw_i2c_int_clear(addr, DW_IIC_RX_FULL);
  193. iic_priv->status = IIC_STATE_ERROR;
  194. dw_iic_disable(addr);
  195. if (iic_priv->cb_event) {
  196. iic_priv->cb_event(I2C_EVENT_BUS_ERROR, iic_priv->cb_arg);
  197. }
  198. }
  199. if (addr->IC_INTR_STAT & (1 << DW_IIC_STOP_DET)) {
  200. dw_i2c_int_clear(addr, DW_IIC_STOP_DET);
  201. if (iic_priv->rx_cnt == iic_priv->rx_total_num) {
  202. iic_priv->status = IIC_STATE_DONE;
  203. dw_iic_disable(addr);
  204. addr->IC_CLR_INTR;
  205. if (iic_priv->cb_event) {
  206. iic_priv->cb_event(I2C_EVENT_TRANSFER_DONE, iic_priv->cb_arg);
  207. }
  208. }
  209. }
  210. }
  211. void dw_iic_irqhandler(int32_t idx)
  212. {
  213. dw_iic_priv_t *iic_priv = &iic_instance[idx];
  214. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  215. if (addr->IC_INTR_STAT & (1 << DW_IIC_TX_ABRT)) {
  216. /* If arbitration fault, it indicates either a slave device not
  217. * responding as expected, or other master which is not supported
  218. * by this SW.
  219. */
  220. dw_i2c_int_clear(addr, DW_IIC_TX_ABRT);
  221. iic_priv->status = IIC_STATE_DONE;
  222. if (iic_priv->cb_event) {
  223. dw_iic_disable(addr);
  224. iic_priv->cb_event(I2C_EVENT_BUS_ERROR, iic_priv->cb_arg);
  225. return;
  226. }
  227. }
  228. switch (iic_priv->status) {
  229. /* send data to slave */
  230. case IIC_STATE_DATASEND: {
  231. dw_iic_intr_tx_empty(iic_priv);
  232. break;
  233. }
  234. /* wait for data from slave */
  235. case IIC_STATE_WFDATA: {
  236. dw_iic_intr_rx_full(iic_priv);
  237. break;
  238. }
  239. /* unexpected state,SW fault */
  240. default: {
  241. dw_iic_disable(addr);
  242. if (iic_priv->cb_event) {
  243. iic_priv->cb_event(I2C_EVENT_BUS_ERROR, iic_priv->cb_arg);
  244. }
  245. }
  246. }
  247. }
  248. int32_t __attribute__((weak)) target_iic_init(pin_t scl, pin_t sda, uint32_t *base, uint32_t *irq)
  249. {
  250. return -1;
  251. }
  252. /**
  253. \brief Initialize IIC Interface. 1. Initializes the resources needed for the IIC interface 2.registers event callback function
  254. \param[in] handle iic handle to operate.
  255. \param[in] cb_event Pointer to \ref iic_event_cb_t
  256. \return error code
  257. */
  258. iic_handle_t csi_iic_initialize(pin_t scl, pin_t sda, iic_event_cb_t cb_event, void *cb_arg)
  259. {
  260. uint32_t base = 0u;
  261. uint32_t irq = 0u;
  262. int32_t idx = target_iic_init(scl, sda, &base, &irq);
  263. if (idx < 0 || idx >= CONFIG_IIC_NUM) {
  264. return NULL;
  265. }
  266. dw_iic_priv_t *iic_priv = &iic_instance[idx];
  267. iic_priv->base = base;
  268. iic_priv->irq = irq;
  269. iic_priv->cb_event = cb_event;
  270. iic_priv->cb_arg = cb_arg;
  271. iic_priv->rx_total_num = 0;
  272. iic_priv->tx_total_num = 0;
  273. iic_priv->rx_buf = NULL;
  274. iic_priv->tx_buf = NULL;
  275. iic_priv->rx_cnt = 0;
  276. iic_priv->tx_cnt = 0;
  277. iic_priv->status = 0;
  278. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  279. /* mask all interrupts */
  280. addr->IC_INTR_MASK = 0x00;
  281. addr->IC_CON = DW_IIC_CON_DEFAUL;
  282. addr->IC_INTR_MASK |= 1 << DW_IIC_TX_ABRT;
  283. addr->IC_INTR_MASK |= 1 << DW_IIC_TX_OVER;
  284. addr->IC_INTR_MASK |= 1 << DW_IIC_RX_OVER;
  285. addr->IC_INTR_MASK |= 1 << DW_IIC_RX_FULL;
  286. addr->IC_INTR_MASK |= 1 << DW_IIC_STOP_DET;
  287. drv_nvic_enable_irq(iic_priv->irq);
  288. return iic_priv;
  289. }
  290. /**
  291. \brief De-initialize IIC Interface. stops operation and releases the software resources used by the interface
  292. \param[in] handle iic handle to operate.
  293. \return error code
  294. */
  295. int32_t csi_iic_uninitialize(iic_handle_t handle)
  296. {
  297. IIC_NULL_PARAM_CHK(handle);
  298. /* First clear ACTIVITY, then Disable IIC */
  299. dw_iic_priv_t *iic_priv = handle;
  300. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  301. addr->IC_CLR_ACTIVITY;
  302. addr->IC_INTR_MASK = 0x00;
  303. addr->IC_ENABLE = DW_IIC_DISABLE;
  304. iic_priv->cb_event = NULL;
  305. iic_priv->rx_total_num = 0;
  306. iic_priv->tx_total_num = 0;
  307. iic_priv->rx_buf = NULL;
  308. iic_priv->tx_buf = NULL;
  309. iic_priv->rx_cnt = 0;
  310. iic_priv->tx_cnt = 0;
  311. iic_priv->status = 0;
  312. drv_nvic_disable_irq(iic_priv->irq);
  313. return 0;
  314. }
  315. /**
  316. \brief Get driver capabilities.
  317. \return \ref iic_capabilities_t
  318. */
  319. iic_capabilities_t csi_iic_get_capabilities(iic_handle_t handle)
  320. {
  321. return iic_capabilities;
  322. }
  323. /**
  324. \brief config iic.
  325. \param[in] handle iic handle to operate.
  326. \param[in] mode \ref iic_mode_e.if negative, then this attribute not changed
  327. \param[in] speed \ref iic_speed_e.if negative, then this attribute not changed
  328. \param[in] addr_mode \ref iic_address_mode_e.if negative, then this attribute not changed
  329. \param[in] slave_addr slave address.if negative, then this attribute not changed
  330. \return error code
  331. */
  332. int32_t csi_iic_config(iic_handle_t handle,
  333. iic_mode_e mode,
  334. iic_speed_e speed,
  335. iic_address_mode_e addr_mode,
  336. int32_t slave_addr)
  337. {
  338. IIC_NULL_PARAM_CHK(handle);
  339. if (mode >= 0) {
  340. switch (mode) {
  341. case IIC_MODE_MASTER:
  342. break;
  343. case IIC_MODE_SLAVE:
  344. return ERR_IIC(EDRV_UNSUPPORTED);
  345. break;
  346. default:
  347. return ERR_IIC(EDRV_PARAMETER);
  348. }
  349. }
  350. dw_iic_reg_t *addr = (dw_iic_reg_t *)(((dw_iic_priv_t *)handle)->base);
  351. if (speed >= 0) {
  352. switch (speed) {
  353. case I2C_BUS_SPEED_STANDARD:
  354. dw_iic_set_transfer_speed(addr, DW_IIC_STANDARDSPEED);
  355. break;
  356. case I2C_BUS_SPEED_FAST:
  357. dw_iic_set_transfer_speed(addr, DW_IIC_FASTSPEED);
  358. break;
  359. case I2C_BUS_SPEED_FAST_PLUS:
  360. return ERR_IIC(EDRV_UNSUPPORTED);
  361. case I2C_BUS_SPEED_HIGH:
  362. dw_iic_set_transfer_speed(addr, DW_IIC_HIGHSPEED);
  363. break;
  364. default:
  365. return ERR_IIC(EDRV_PARAMETER);
  366. }
  367. }
  368. if (addr_mode >= 0) {
  369. switch (addr_mode) {
  370. case I2C_ADDRESS_10BIT:
  371. case I2C_ADDRESS_7BIT:
  372. dw_iic_set_addr_mode(addr, addr_mode);
  373. break;
  374. default:
  375. return ERR_IIC(EDRV_PARAMETER);
  376. }
  377. }
  378. if (slave_addr >= 0) {
  379. dw_iic_set_target_address(addr, slave_addr);
  380. }
  381. return 0;
  382. }
  383. /**
  384. \brief Start transmitting data as I2C Master.
  385. \param[in] handle iic handle to operate.
  386. \param[in] data Pointer to buffer with data to transmit to I2C Slave
  387. \param[in] num Number of data items to send
  388. \param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
  389. \return error code
  390. */
  391. int32_t csi_iic_master_send(iic_handle_t handle, const void *data, uint32_t num, bool xfer_pending)
  392. {
  393. IIC_NULL_PARAM_CHK(handle);
  394. if (data == NULL || num == 0) {
  395. return ERR_IIC(EDRV_PARAMETER);
  396. }
  397. dw_iic_priv_t *iic_priv = handle;
  398. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  399. iic_priv->tx_buf = (uint8_t *)data;
  400. iic_priv->tx_total_num = num;
  401. iic_priv->tx_cnt = 0;
  402. iic_priv->status = IIC_STATE_DATASEND;
  403. dw_iic_disable(addr);
  404. addr->IC_CLR_INTR;
  405. uint32_t length = (num > DW_IIC_FIFO_MAX_LV) ? DW_IIC_FIFO_MAX_LV : num;
  406. addr->IC_TX_TL = DW_IIC_TXFIFO_LV;
  407. dw_iic_enable(addr);
  408. uint32_t i = 0u;
  409. for (i = 0; i < length; i++) {
  410. addr->IC_DATA_CMD = *((uint8_t *)(iic_priv->tx_buf)++);
  411. }
  412. iic_priv->tx_cnt += length;
  413. /* open corresponding interrupts */
  414. addr->IC_INTR_MASK |= 1 << DW_IIC_TX_EMPTY;
  415. return 0;
  416. }
  417. /**
  418. \fn int32_t csi_iic_master_receive (iic_handle_t handle,const void *data, uint32_t num, bool xfer_pending)
  419. \brief Start receiving data as I2C Master.
  420. \param[in] handle iic handle to operate.
  421. \param[out] data Pointer to buffer for data to receive from IIC receiver
  422. \param[in] num Number of data items to receive
  423. \param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
  424. \return error code
  425. */
  426. int32_t csi_iic_master_receive(iic_handle_t handle, const void *data, uint32_t num, bool xfer_pending)
  427. {
  428. IIC_NULL_PARAM_CHK(handle);
  429. if (data == NULL || num == 0) {
  430. return ERR_IIC(EDRV_PARAMETER);
  431. }
  432. dw_iic_priv_t *iic_priv = handle;
  433. iic_priv->rx_buf = (uint8_t *)data;
  434. iic_priv->rx_total_num = num;
  435. iic_priv->rx_cnt = 0;
  436. iic_priv->status = IIC_STATE_WFDATA;
  437. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  438. dw_iic_disable(addr);
  439. int32_t tmp = addr->IC_CLR_INTR;
  440. addr->IC_RX_TL = DW_IIC_FIFO_MAX_LV; /* Sets receive FIFO threshold */
  441. tmp = addr->IC_CLR_INTR;
  442. addr->IC_RX_TL = DW_IIC_RXFIFO_LV; /* Sets receive FIFO threshold */
  443. dw_iic_enable(addr);
  444. addr->IC_DATA_CMD = 1 << 8;
  445. return 0;
  446. }
  447. /**
  448. \brief Start transmitting data as I2C Slave.
  449. \param[in] handle iic handle to operate.
  450. \param[in] data Pointer to buffer with data to transmit to I2C Master
  451. \param[in] num Number of data items to send
  452. \return error code
  453. */
  454. int32_t csi_iic_slave_send(iic_handle_t handle, const void *data, uint32_t num)
  455. {
  456. return ERR_IIC(EDRV_UNSUPPORTED);
  457. }
  458. /**
  459. \fn int32_t csi_iic_slave_receive (iic_handle_t handle, const void *data, uint32_t num)
  460. \brief Start receiving data as I2C Slave.
  461. \param[in] handle iic handle to operate.
  462. \param[out] data Pointer to buffer for data to receive from I2C Master
  463. \param[in] num Number of data items to receive
  464. \return error code
  465. */
  466. int32_t csi_iic_slave_receive(iic_handle_t handle, const void *data, uint32_t num)
  467. {
  468. return ERR_IIC(EDRV_UNSUPPORTED);
  469. }
  470. /**
  471. \brief abort transfer.
  472. \param[in] handle iic handle to operate.
  473. \return error code
  474. */
  475. int32_t csi_iic_abort_transfer(iic_handle_t handle)
  476. {
  477. IIC_NULL_PARAM_CHK(handle);
  478. dw_iic_priv_t *iic_priv = handle;
  479. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  480. dw_iic_disable(addr);
  481. iic_priv->rx_cnt = 0;
  482. iic_priv->tx_cnt = 0;
  483. iic_priv->rx_buf = NULL;
  484. iic_priv->tx_buf = NULL;
  485. return 0;
  486. }
  487. /**
  488. \brief Get IIC status.
  489. \param[in] handle iic handle to operate.
  490. \return IIC status \ref iic_status_t
  491. */
  492. iic_status_t csi_iic_get_status(iic_handle_t handle)
  493. {
  494. iic_status_t iic_status = {0};
  495. if (handle == NULL) {
  496. return iic_status;
  497. }
  498. dw_iic_priv_t *iic_priv = handle;
  499. dw_iic_reg_t *addr = (dw_iic_reg_t *)(iic_priv->base);
  500. int32_t tmp = addr->IC_STATUS;
  501. if (tmp & 0x1) {
  502. iic_status.busy = 1;
  503. if (tmp & 0x40) {
  504. iic_status.mode = 0;
  505. } else {
  506. iic_status.mode = 1;
  507. }
  508. }
  509. if (iic_priv->status == IIC_STATE_WFDATA) {
  510. iic_status.direction = 1;
  511. }
  512. if (addr->IC_RAW_INTR_STAT & 0x800) {
  513. iic_status.general_call = 1;
  514. }
  515. if (iic_priv->status == IIC_STATE_ERROR) {
  516. iic_status.bus_error = 1;
  517. }
  518. return iic_status;
  519. }