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.
26 #define BASE_ADDR_I2C 0xfffe2800
27 #define I2C_REG(x) (BASE_ADDR_I2C+(x))
42 #define I2C_CMD_SOFT_RESET (1 << 0)
43 #define I2C_CMD_EN_CLK (1 << 1)
44 #define I2C_CMD_START (1 << 2)
45 #define I2C_CMD_RW_READ (1 << 3)
46 #define I2C_CMD_COMP_READ (1 << 4)
47 #define I2C_CMD_IRQ_ENABLE (1 << 5)
49 #define I2C_STATUS_ERROR_DATA (1 << 0)
50 #define I2C_STATUS_ERROR_DEV (1 << 1)
51 #define I2C_STATUS_IDLE (1 << 2) // 1: not idle, 0: idle
52 #define I2C_STATUS_INTERRUPT (1 << 3)
54 int i2c_write(uint8_t chip
, uint32_t addr
, int alen
, const uint8_t *buffer
, int len
)
58 /* Calypso I2C controller doesn't support fancy addressing */
62 /* FIXME: implement writes longer than fifo size */
66 printd("i2c_write(chip=0x%02u, addr=0x%02u): ", chip
, addr
);
68 writeb(chip
& 0x7f, I2C_REG(DEVICE_REG
));
69 writeb(addr
& 0xff, I2C_REG(ADDRESS_REG
));
71 /* we have to tell the controller how many bits we'll put into the fifo ?!? */
72 writeb(len
-1, I2C_REG(CONF_FIFO_REG
));
76 uint8_t byte
= *buffer
++;
77 writeb(byte
, I2C_REG(DATA_WR_REG
));
78 printd("%02X ", byte
);
82 /* start the transfer */
83 cmd
= readb(I2C_REG(CMD_REG
));
85 writeb(cmd
, I2C_REG(CMD_REG
));
87 /* wait until transfer completes */
89 uint8_t reg
= readb(I2C_REG(STATUS_ACTIVITY_REG
));
90 printd("I2C Status: 0x%02x\n", reg
& 0xf);
91 if (!(reg
& I2C_STATUS_IDLE
)) // 0: idle 1: not idle
94 dputs("I2C transfer completed\n");
99 void i2c_init(int speed
, int slaveadd
)
101 /* scl_out = clk_func_ref / 3,
102 clk_func_ref = master_clock_freq / (divisor_2 + 1)
103 master_clock_freq = ext_clock_freq / divisor_1 */
104 /* clk_func_ref = scl_out * 3,
105 divisor_2 = (master_clock_freq / clk_func_ref) - 1
106 divisor_1 = ext_clock_freq / master_clock_freq */
107 /* for a target freq of 200kHz:
108 ext_clock_freq = 13MHz
109 clk_func_ref = 3 * 300kHZ = 600kHz
110 divisor_1 = 1 => master_clock_freq = ext_clock_freq = 13MHz
111 divisor_2 = 21 => clk_func_ref = 13MHz / (21+2) = 590.91 kHz
112 scl_out = clk_func_ref / 3 = 509.91 kHz / 3 = 196.97kHz */
113 writeb(I2C_CMD_SOFT_RESET
, I2C_REG(CMD_REG
));
115 writeb(0x00, I2C_REG(CONF_CLK_REG
));
116 writeb(21, I2C_REG(CONF_CLK_FUNC_REF
));
118 writeb(I2C_CMD_EN_CLK
, I2C_REG(CMD_REG
));