2 * Bootloader version of the i2c driver for the MV64x60.
4 * Author: Dale Farnsworth <dfarnsworth@mvista.com>
5 * Maintained by: Mark A. Greer <mgreer@mvista.com>
7 * 2003, 2007 (c) MontaVista, Software, Inc. This file is licensed under
8 * the terms of the GNU General Public License version 2. This program is
9 * licensed "as is" without any warranty of any kind, whether express or
24 /* Register defines */
25 #define MV64x60_I2C_REG_SLAVE_ADDR 0x00
26 #define MV64x60_I2C_REG_DATA 0x04
27 #define MV64x60_I2C_REG_CONTROL 0x08
28 #define MV64x60_I2C_REG_STATUS 0x0c
29 #define MV64x60_I2C_REG_BAUD 0x0c
30 #define MV64x60_I2C_REG_EXT_SLAVE_ADDR 0x10
31 #define MV64x60_I2C_REG_SOFT_RESET 0x1c
33 #define MV64x60_I2C_CONTROL_ACK 0x04
34 #define MV64x60_I2C_CONTROL_IFLG 0x08
35 #define MV64x60_I2C_CONTROL_STOP 0x10
36 #define MV64x60_I2C_CONTROL_START 0x20
37 #define MV64x60_I2C_CONTROL_TWSIEN 0x40
38 #define MV64x60_I2C_CONTROL_INTEN 0x80
40 #define MV64x60_I2C_STATUS_BUS_ERR 0x00
41 #define MV64x60_I2C_STATUS_MAST_START 0x08
42 #define MV64x60_I2C_STATUS_MAST_REPEAT_START 0x10
43 #define MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK 0x18
44 #define MV64x60_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20
45 #define MV64x60_I2C_STATUS_MAST_WR_ACK 0x28
46 #define MV64x60_I2C_STATUS_MAST_WR_NO_ACK 0x30
47 #define MV64x60_I2C_STATUS_MAST_LOST_ARB 0x38
48 #define MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK 0x40
49 #define MV64x60_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48
50 #define MV64x60_I2C_STATUS_MAST_RD_DATA_ACK 0x50
51 #define MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58
52 #define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0
53 #define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8
54 #define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0
55 #define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8
56 #define MV64x60_I2C_STATUS_NO_STATUS 0xf8
60 static int mv64x60_i2c_wait_for_status(int wanted
)
65 for (i
=0; i
<1000; i
++) {
67 status
= in_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_STATUS
))
75 static int mv64x60_i2c_control(int control
, int status
)
77 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_CONTROL
), control
& 0xff);
78 return mv64x60_i2c_wait_for_status(status
);
81 static int mv64x60_i2c_read_byte(int control
, int status
)
83 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_CONTROL
), control
& 0xff);
84 if (mv64x60_i2c_wait_for_status(status
) < 0)
86 return in_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_DATA
)) & 0xff;
89 static int mv64x60_i2c_write_byte(int data
, int control
, int status
)
91 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_DATA
), data
& 0xff);
92 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_CONTROL
), control
& 0xff);
93 return mv64x60_i2c_wait_for_status(status
);
96 int mv64x60_i2c_read(u32 devaddr
, u8
*buf
, u32 offset
, u32 offset_size
,
104 if (ctlr_base
== NULL
)
108 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_SOFT_RESET
), 0);
109 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_SLAVE_ADDR
), 0);
110 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_EXT_SLAVE_ADDR
), 0);
111 out_le32((u32
*)(ctlr_base
+ MV64x60_I2C_REG_BAUD
), (4 << 3) | 0x4);
113 if (mv64x60_i2c_control(MV64x60_I2C_CONTROL_TWSIEN
,
114 MV64x60_I2C_STATUS_NO_STATUS
) < 0)
118 control
= MV64x60_I2C_CONTROL_START
| MV64x60_I2C_CONTROL_TWSIEN
;
119 status
= MV64x60_I2C_STATUS_MAST_START
;
120 if (mv64x60_i2c_control(control
, status
) < 0)
123 /* select device for writing */
124 data
= devaddr
& ~0x1;
125 control
= MV64x60_I2C_CONTROL_TWSIEN
;
126 status
= MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK
;
127 if (mv64x60_i2c_write_byte(data
, control
, status
) < 0)
130 /* send offset of data */
131 control
= MV64x60_I2C_CONTROL_TWSIEN
;
132 status
= MV64x60_I2C_STATUS_MAST_WR_ACK
;
133 if (offset_size
> 1) {
134 if (mv64x60_i2c_write_byte(offset
>> 8, control
, status
) < 0)
137 if (mv64x60_i2c_write_byte(offset
, control
, status
) < 0)
141 control
= MV64x60_I2C_CONTROL_START
| MV64x60_I2C_CONTROL_TWSIEN
;
142 status
= MV64x60_I2C_STATUS_MAST_REPEAT_START
;
143 if (mv64x60_i2c_control(control
, status
) < 0)
146 /* select device for reading */
147 data
= devaddr
| 0x1;
148 control
= MV64x60_I2C_CONTROL_TWSIEN
;
149 status
= MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK
;
150 if (mv64x60_i2c_write_byte(data
, control
, status
) < 0)
153 /* read all but last byte of data */
154 control
= MV64x60_I2C_CONTROL_ACK
| MV64x60_I2C_CONTROL_TWSIEN
;
155 status
= MV64x60_I2C_STATUS_MAST_RD_DATA_ACK
;
157 for (i
=1; i
<count
; i
++) {
158 data
= mv64x60_i2c_read_byte(control
, status
);
160 printf("errors on iteration %d\n", i
);
166 /* read last byte of data */
167 control
= MV64x60_I2C_CONTROL_TWSIEN
;
168 status
= MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK
;
169 data
= mv64x60_i2c_read_byte(control
, status
);
175 control
= MV64x60_I2C_CONTROL_STOP
| MV64x60_I2C_CONTROL_TWSIEN
;
176 status
= MV64x60_I2C_STATUS_NO_STATUS
;
177 if (mv64x60_i2c_control(control
, status
) < 0)
183 int mv64x60_i2c_open(void)
188 devp
= finddevice("/mv64x60/i2c");
191 if (getprop(devp
, "virtual-reg", &v
, sizeof(v
)) != sizeof(v
))
201 void mv64x60_i2c_close(void)