1 /* Driver for I2C Master Controller inside TI Calypso */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #define BASE_ADDR_I2C 0xfffe2800
31 #define I2C_REG(x) (BASE_ADDR_I2C+(x))
46 #define I2C_CMD_SOFT_RESET (1 << 0)
47 #define I2C_CMD_EN_CLK (1 << 1)
48 #define I2C_CMD_START (1 << 2)
49 #define I2C_CMD_RW_READ (1 << 3)
50 #define I2C_CMD_COMP_READ (1 << 4)
51 #define I2C_CMD_IRQ_ENABLE (1 << 5)
53 #define I2C_STATUS_ERROR_DATA (1 << 0)
54 #define I2C_STATUS_ERROR_DEV (1 << 1)
55 #define I2C_STATUS_IDLE (1 << 2) // 1: not idle, 0: idle
56 #define I2C_STATUS_INTERRUPT (1 << 3)
58 int i2c_write(uint8_t chip, uint32_t addr, int alen, const uint8_t *buffer, int len)
62 /* Calypso I2C controller doesn't support fancy addressing */
66 /* FIXME: implement writes longer than fifo size */
70 printd("i2c_write(chip=0x%02u, addr=0x%02u): ", chip, addr)
72 writeb(chip & 0x3f, I2C_REG(DEVICE_REG));
73 writeb(addr & 0xff, I2C_REG(ADDRESS_REG));
75 /* we have to tell the controller how many bits we'll put into the fifo ?!? */
76 writeb(len-1, I2C_REG(CONF_FIFO_REG));
80 uint8_t byte = *buffer++;
81 writeb(byte, I2C_REG(DATA_WR_REG));
82 printd("%02X ", byte);
86 /* start the transfer */
87 cmd = readb(I2C_REG(CMD_REG));
89 writeb(cmd, I2C_REG(CMD_REG));
91 /* wait until transfer completes */
93 uint8_t reg = readb(I2C_REG(STATUS_ACTIVITY_REG));
94 printd("I2C Status: 0x%02x\n", rerg & 0xf);
95 if (!(reg & I2C_STATUS_IDLE)) // 0: idle 1: not idle
98 dputs("I2C transfer completed\n");
103 void i2c_init(int speed, int slaveadd)
105 /* scl_out = clk_func_ref / 3,
106 clk_func_ref = master_clock_freq / (divisor_2 + 1)
107 master_clock_freq = ext_clock_freq / divisor_1 */
108 /* clk_func_ref = scl_out * 3,
109 divisor_2 = (master_clock_freq / clk_func_ref) - 1
110 divisor_1 = ext_clock_freq / master_clock_freq */
111 /* for a target freq of 200kHz:
112 ext_clock_freq = 13MHz
113 clk_func_ref = 3 * 300kHZ = 600kHz
114 divisor_1 = 1 => master_clock_freq = ext_clock_freq = 13MHz
115 divisor_2 = 21 => clk_func_ref = 13MHz / (21+2) = 590.91 kHz
116 scl_out = clk_func_ref / 3 = 509.91 kHz / 3 = 196.97kHz */
117 writeb(I2C_CMD_SOFT_RESET, I2C_REG(CMD_REG));
119 writeb(0x00, I2C_REG(CONF_CLK_REG));
120 writeb(21, I2C_REG(CONF_CLK_FUNC_REF));
122 writeb(I2C_CMD_EN_CLK, I2C_REG(CMD_REG));