1 // SPDX-License-Identifier: GPL-2.0+
5 * (C) Copyright 2016 Songjun Wu <songjun.wu@atmel.com>
15 #include <linux/bitops.h>
20 DECLARE_GLOBAL_DATA_PTR
;
22 #define I2C_TIMEOUT_MS 100
24 static int at91_wait_for_xfer(struct at91_i2c_bus
*bus
, u32 status
)
26 struct at91_i2c_regs
*reg
= bus
->regs
;
27 ulong start_time
= get_timer(0);
40 } while (get_timer(start_time
) < I2C_TIMEOUT_MS
);
45 static int at91_i2c_xfer_msg(struct at91_i2c_bus
*bus
, struct i2c_msg
*msg
)
47 struct at91_i2c_regs
*reg
= bus
->regs
;
48 bool is_read
= msg
->flags
& I2C_M_RD
;
54 writel(TWI_CR_START
, ®
->cr
);
56 for (i
= 0; !ret
&& i
< (msg
->len
- 1); i
++) {
57 ret
= at91_wait_for_xfer(bus
, TWI_SR_RXRDY
);
58 msg
->buf
[i
] = readl(®
->rhr
);
64 writel(TWI_CR_STOP
, ®
->cr
);
66 ret
= at91_wait_for_xfer(bus
, TWI_SR_RXRDY
);
70 msg
->buf
[i
] = readl(®
->rhr
);
73 writel(msg
->buf
[0], ®
->thr
);
74 ret
= at91_wait_for_xfer(bus
, TWI_SR_TXRDY
);
76 for (i
= 1; !ret
&& (i
< msg
->len
); i
++) {
77 writel(msg
->buf
[i
], ®
->thr
);
78 ret
= at91_wait_for_xfer(bus
, TWI_SR_TXRDY
);
84 writel(TWI_CR_STOP
, ®
->cr
);
88 ret
= at91_wait_for_xfer(bus
, TWI_SR_TXCOMP
);
93 if (bus
->status
& (TWI_SR_OVRE
| TWI_SR_UNRE
| TWI_SR_LOCK
)) {
101 if (bus
->status
& TWI_SR_LOCK
)
102 writel(TWI_CR_LOCKCLR
, ®
->cr
);
107 static int at91_i2c_xfer(struct udevice
*dev
, struct i2c_msg
*msg
, int nmsgs
)
109 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
110 struct at91_i2c_regs
*reg
= bus
->regs
;
111 struct i2c_msg
*m_start
= msg
;
113 u32 int_addr_flag
= 0;
117 int internal_address
= 0;
120 /* 1st msg is put into the internal address, start with 2nd */
123 /* the max length of internal address is 3 bytes */
127 for (i
= 0; i
< msg
->len
; ++i
) {
128 const unsigned addr
= msg
->buf
[msg
->len
- 1 - i
];
130 internal_address
|= addr
<< (8 * i
);
131 int_addr_flag
+= TWI_MMR_IADRSZ_1
;
134 writel(internal_address
, ®
->iadr
);
137 is_read
= m_start
->flags
& I2C_M_RD
;
139 writel((m_start
->addr
<< 16) | int_addr_flag
|
140 (is_read
? TWI_MMR_MREAD
: 0), ®
->mmr
);
142 ret
= at91_i2c_xfer_msg(bus
, m_start
);
148 * Calculate symmetric clock as stated in datasheet:
149 * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
151 static void at91_calc_i2c_clock(struct udevice
*dev
, int i2c_clk
)
153 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
154 const struct at91_i2c_pdata
*pdata
= bus
->pdata
;
155 int offset
= pdata
->clk_offset
;
156 int max_ckdiv
= pdata
->clk_max_div
;
157 int ckdiv
, cdiv
, div
;
158 unsigned long src_rate
;
160 src_rate
= bus
->bus_clk_rate
;
162 div
= max(0, (int)DIV_ROUND_UP(src_rate
, 2 * i2c_clk
) - offset
);
163 ckdiv
= fls(div
>> 8);
166 if (ckdiv
> max_ckdiv
) {
171 bus
->speed
= DIV_ROUND_UP(src_rate
,
172 (cdiv
* (1 << ckdiv
) + offset
) * 2);
174 bus
->cwgr_val
= (ckdiv
<< 16) | (cdiv
<< 8) | cdiv
;
177 static int at91_i2c_enable_clk(struct udevice
*dev
)
179 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
184 ret
= clk_get_by_index(dev
, 0, &clk
);
188 ret
= clk_enable(&clk
);
192 clk_rate
= clk_get_rate(&clk
);
196 bus
->bus_clk_rate
= clk_rate
;
203 static int at91_i2c_set_bus_speed(struct udevice
*dev
, unsigned int speed
)
205 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
207 at91_calc_i2c_clock(dev
, speed
);
209 writel(bus
->cwgr_val
, &bus
->regs
->cwgr
);
214 int at91_i2c_get_bus_speed(struct udevice
*dev
)
216 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
221 static int at91_i2c_ofdata_to_platdata(struct udevice
*dev
)
223 const void *blob
= gd
->fdt_blob
;
224 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
225 int node
= dev_of_offset(dev
);
227 bus
->regs
= (struct at91_i2c_regs
*)devfdt_get_addr(dev
);
228 bus
->pdata
= (struct at91_i2c_pdata
*)dev_get_driver_data(dev
);
229 bus
->clock_frequency
= fdtdec_get_int(blob
, node
,
230 "clock-frequency", 100000);
235 static const struct dm_i2c_ops at91_i2c_ops
= {
236 .xfer
= at91_i2c_xfer
,
237 .set_bus_speed
= at91_i2c_set_bus_speed
,
238 .get_bus_speed
= at91_i2c_get_bus_speed
,
241 static int at91_i2c_probe(struct udevice
*dev
)
243 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
244 struct at91_i2c_regs
*reg
= bus
->regs
;
247 ret
= at91_i2c_enable_clk(dev
);
251 writel(TWI_CR_SWRST
, ®
->cr
);
253 at91_calc_i2c_clock(dev
, bus
->clock_frequency
);
255 writel(bus
->cwgr_val
, ®
->cwgr
);
256 writel(TWI_CR_MSEN
, ®
->cr
);
257 writel(TWI_CR_SVDIS
, ®
->cr
);
262 static const struct at91_i2c_pdata at91rm9200_config
= {
267 static const struct at91_i2c_pdata at91sam9261_config
= {
272 static const struct at91_i2c_pdata at91sam9260_config
= {
277 static const struct at91_i2c_pdata at91sam9g20_config
= {
282 static const struct at91_i2c_pdata at91sam9g10_config
= {
287 static const struct at91_i2c_pdata at91sam9x5_config
= {
292 static const struct at91_i2c_pdata sama5d4_config
= {
297 static const struct at91_i2c_pdata sama5d2_config
= {
302 static const struct udevice_id at91_i2c_ids
[] = {
303 { .compatible
= "atmel,at91rm9200-i2c", .data
= (long)&at91rm9200_config
},
304 { .compatible
= "atmel,at91sam9260-i2c", .data
= (long)&at91sam9260_config
},
305 { .compatible
= "atmel,at91sam9261-i2c", .data
= (long)&at91sam9261_config
},
306 { .compatible
= "atmel,at91sam9g20-i2c", .data
= (long)&at91sam9g20_config
},
307 { .compatible
= "atmel,at91sam9g10-i2c", .data
= (long)&at91sam9g10_config
},
308 { .compatible
= "atmel,at91sam9x5-i2c", .data
= (long)&at91sam9x5_config
},
309 { .compatible
= "atmel,sama5d4-i2c", .data
= (long)&sama5d4_config
},
310 { .compatible
= "atmel,sama5d2-i2c", .data
= (long)&sama5d2_config
},
314 U_BOOT_DRIVER(i2c_at91
) = {
317 .of_match
= at91_i2c_ids
,
318 .probe
= at91_i2c_probe
,
319 .ofdata_to_platdata
= at91_i2c_ofdata_to_platdata
,
320 .per_child_auto_alloc_size
= sizeof(struct dm_i2c_chip
),
321 .priv_auto_alloc_size
= sizeof(struct at91_i2c_bus
),
322 .ops
= &at91_i2c_ops
,