📄 i2c_hw.c
字号:
#include "version.h"#include "config.h"#include "emhwlib_registers.h"#include "hardware.h"#include "em86xxapi.h"#include "io.h"#include "uart.h"#if !defined(CONFIG_ARCH_TANGO15) && !defined(CONFIG_ARCH_TANGO10)#error "Unsupported architecture"#endif#define REG_BASE_I2C (REG_BASE_SYSTEM + SYS_gpio_dir)#if 0int hwi2c_write(unsigned long wr_addr, unsigned char subaddr, unsigned char *ptr, unsigned long n, unsigned long delay);int hwi2c_read(unsigned long rd_addr, unsigned char subaddr, unsigned char *ptr, unsigned long size, unsigned long delay);int hwi2c_write_no_subaddr(unsigned long wr_addr, unsigned char *ptr, unsigned long size, unsigned long delay);int hwi2c_read_no_subaddr(unsigned long rd_addr, unsigned char *ptr, unsigned long size, unsigned long delay);#endifstatic unsigned long hwi2c_wait_status(unsigned long status, unsigned long timeout, unsigned long delay){ unsigned long stat = 0; unsigned long i; for (i = 0; i < timeout; i++) { stat = __raw_readl(REG_BASE_I2C + I2C_MASTER_STATUS); if ((stat & status) != 0) return stat; else em86xx_usleep(delay); } return 0;}static inline int hwi2c_disable(void){ __raw_writel(0x0, REG_BASE_I2C + I2C_MASTER_CONFIG); return 0;}int hwi2c_write(unsigned long wr_addr, unsigned char subaddr, unsigned char *ptr, unsigned long size, unsigned long delay){ unsigned long i; unsigned long stat; /* I2CEnable 8: 1b, REGADRLEN 5-7: 111b, DEVADRLEN 2-4: 110b */ __raw_writel(0x1f8, REG_BASE_I2C + I2C_MASTER_CONFIG); __raw_writel(375 * 4, REG_BASE_I2C + I2C_MASTER_CLK_DIV); __raw_writel(wr_addr >> 1, REG_BASE_I2C + I2C_MASTER_DEV_ADDR); /* Wait until IDLE */ if ((stat = hwi2c_wait_status(0x1, 0x1000, delay)) == 0) { hwi2c_disable(); return -1; } __raw_writel(size - 1, REG_BASE_I2C + I2C_MASTER_BYTE_CNT); for (i = 0; i < size; i++) { __raw_writel(subaddr++, REG_BASE_I2C + I2C_MASTER_ADDR); __raw_writel(*ptr++, REG_BASE_I2C + I2C_MASTER_DATA_OUT); if (i == 0) /* We only toggle the bit the first time */ __raw_writel(0, REG_BASE_I2C + I2C_MASTER_STARTXFER); /* Wait until DATAOUT is empty */ if ((stat = hwi2c_wait_status(0x2, 0x1000, delay)) == 0) break; else if ((stat & 0x8) != 0) /* Check Ack status */ break; }stat = hwi2c_wait_status(0x1, 0x1000, delay);//uart_printf("done: stat=0x%x(3)\n",stat);//ok//uart_printf("0x%x \n",stat);//okuart_printf("0x%x \n",stat);//uart_printf("0x%x \n",stat);//bad <-> ok hwi2c_disable(); return (i < size) ? -1 : 0;}// TODO implement real sequential read, not sequence of single byte transfersint hwi2c_read(unsigned long rd_addr, unsigned char subaddr, unsigned char *ptr, unsigned long size, unsigned long delay){ unsigned long i; unsigned long stat; /* I2CEnable 8: 1b, REGADRLEN 5-7: 111b, DEVADRLEN 2-4: 110b REGADRDIS 1: 1b */ __raw_writel(0x1fa, REG_BASE_I2C + I2C_MASTER_CONFIG); __raw_writel(375 * 4, REG_BASE_I2C + I2C_MASTER_CLK_DIV); /* Wait until IDLE */ if ((stat = hwi2c_wait_status(0x1, 0x1000, delay)) == 0) { hwi2c_disable(); return -1; } for (i = 0; i < size; i++) { __raw_writel(0, REG_BASE_I2C + I2C_MASTER_BYTE_CNT); __raw_writel(rd_addr >> 1, REG_BASE_I2C + I2C_MASTER_DEV_ADDR); __raw_writel(subaddr++, REG_BASE_I2C + I2C_MASTER_DATA_OUT); __raw_writel(4, REG_BASE_I2C + I2C_MASTER_STARTXFER);// __raw_writel(0, REG_BASE_I2C + I2C_MASTER_STARTXFER); if ((stat = hwi2c_wait_status(0x2, 0x1000, delay)) == 0){ break; } //else if ((stat = hwi2c_wait_status(0x1, 0x1000, delay)) == 0) // break; else if ((stat & 0x08) != 0) { break; } __raw_writel(0, REG_BASE_I2C + I2C_MASTER_BYTE_CNT); __raw_writel(rd_addr >> 1, REG_BASE_I2C + I2C_MASTER_DEV_ADDR); __raw_writel(1, REG_BASE_I2C + I2C_MASTER_STARTXFER); if ((stat = hwi2c_wait_status(0x4, 0x1000, delay)) == 0) { break; } //else if ((stat = hwi2c_wait_status(0x1, 0x1000, delay)) == 0) // break; else if ((stat & 0x08) != 0) { break; } *ptr++ = __raw_readl(REG_BASE_I2C + I2C_MASTER_DATA_IN); }stat = hwi2c_wait_status(0x1, 0x1000, delay); hwi2c_disable(); return (i < size) ? -1 : 0;}int hwi2c_write_no_subaddr(unsigned long wr_addr, unsigned char *ptr, unsigned long size, unsigned long delay){ unsigned long i; unsigned long stat; /* I2CEnable 8: 1b, REGADRLEN 5-7: 111b, DEVADRLEN 2-4: 110b, REGADRDIS 1: 1b */ __raw_writel(0x1fa, REG_BASE_I2C + I2C_MASTER_CONFIG); __raw_writel(375 * 4, REG_BASE_I2C + I2C_MASTER_CLK_DIV); __raw_writel(wr_addr >> 1, REG_BASE_I2C + I2C_MASTER_DEV_ADDR); /* Wait until IDLE */ if ((stat = hwi2c_wait_status(0x1, 0x1000, delay)) == 0) { hwi2c_disable(); return -1; } __raw_writel(size - 1, REG_BASE_I2C + I2C_MASTER_BYTE_CNT); for (i = 0; i < size; i++) { __raw_writel(*ptr++, REG_BASE_I2C + I2C_MASTER_DATA_OUT); if (i == 0) __raw_writel(0, REG_BASE_I2C + I2C_MASTER_STARTXFER); /* Wait until DATAOUT is empty */ if ((stat = hwi2c_wait_status(0x2, 0x1000, delay)) == 0) break; else if ((stat & 0x8) != 0) /* Check Ack status */ break; }stat = hwi2c_wait_status(0x1, 0x1000, delay); hwi2c_disable(); return (i < size) ? -1 : 0;}int hwi2c_read_no_subaddr(unsigned long rd_addr, unsigned char *ptr, unsigned long size, unsigned long delay){ unsigned long i; unsigned long stat; if (size < 1) return -1; /* I2CEnable 8: 1b, REGADRLEN 5-7: 111b, DEVADRLEN 2-4: 110b REGADRDIS 1: 1b */ __raw_writel(0x1fa, REG_BASE_I2C + I2C_MASTER_CONFIG); __raw_writel(375 * 4, REG_BASE_I2C + I2C_MASTER_CLK_DIV); if ((stat = hwi2c_wait_status(0x1, 0x1000, delay)) == 0) { hwi2c_disable(); return -1; } __raw_writel(size - 1, REG_BASE_I2C + I2C_MASTER_BYTE_CNT); __raw_writel(rd_addr >> 1, REG_BASE_I2C + I2C_MASTER_DEV_ADDR); __raw_writel(1, REG_BASE_I2C + I2C_MASTER_STARTXFER); for (i = 0; i < size; i++) { if ((stat = hwi2c_wait_status(0x4, 0x1000, delay)) == 0) break;// else if ((stat = hwi2c_wait_status(0x1, 0x1000, delay)) == 0)// break; else if ((stat & 0x08) != 0) break; *ptr++ = __raw_readl(REG_BASE_I2C + I2C_MASTER_DATA_IN); }stat = hwi2c_wait_status(0x1, 0x1000, delay); hwi2c_disable(); return (i < size) ? -1 : 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -