4 * (C) Copyright 2016 Songjun Wu <songjun.wu@atmel.com>
6 * SPDX-License-Identifier: GPL-2.0+
16 #include <linux/bitops.h>
21 DECLARE_GLOBAL_DATA_PTR
;
23 #define I2C_TIMEOUT_MS 100
25 static int at91_wait_for_xfer(struct at91_i2c_bus
*bus
, u32 status
)
27 struct at91_i2c_regs
*reg
= bus
->regs
;
28 ulong start_time
= get_timer(0);
41 } while (get_timer(start_time
) < I2C_TIMEOUT_MS
);
46 static int at91_i2c_xfer_msg(struct at91_i2c_bus
*bus
, struct i2c_msg
*msg
)
48 struct at91_i2c_regs
*reg
= bus
->regs
;
49 bool is_read
= msg
->flags
& I2C_M_RD
;
55 writel(TWI_CR_START
, ®
->cr
);
57 for (i
= 0; !ret
&& i
< (msg
->len
- 1); i
++) {
58 ret
= at91_wait_for_xfer(bus
, TWI_SR_RXRDY
);
59 msg
->buf
[i
] = readl(®
->rhr
);
65 writel(TWI_CR_STOP
, ®
->cr
);
67 ret
= at91_wait_for_xfer(bus
, TWI_SR_RXRDY
);
71 msg
->buf
[i
] = readl(®
->rhr
);
74 writel(msg
->buf
[0], ®
->thr
);
75 ret
= at91_wait_for_xfer(bus
, TWI_SR_TXRDY
);
77 for (i
= 1; !ret
&& (i
< msg
->len
); i
++) {
78 writel(msg
->buf
[i
], ®
->thr
);
79 ret
= at91_wait_for_xfer(bus
, TWI_SR_TXRDY
);
85 writel(TWI_CR_STOP
, ®
->cr
);
89 ret
= at91_wait_for_xfer(bus
, TWI_SR_TXCOMP
);
94 if (bus
->status
& (TWI_SR_OVRE
| TWI_SR_UNRE
| TWI_SR_LOCK
)) {
102 if (bus
->status
& TWI_SR_LOCK
)
103 writel(TWI_CR_LOCKCLR
, ®
->cr
);
108 static int at91_i2c_xfer(struct udevice
*dev
, struct i2c_msg
*msg
, int nmsgs
)
110 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
111 struct at91_i2c_regs
*reg
= bus
->regs
;
112 struct i2c_msg
*m_start
= msg
;
114 u32 int_addr_flag
= 0;
118 int internal_address
= 0;
121 /* 1st msg is put into the internal address, start with 2nd */
124 /* the max length of internal address is 3 bytes */
128 for (i
= 0; i
< msg
->len
; ++i
) {
129 const unsigned addr
= msg
->buf
[msg
->len
- 1 - i
];
131 internal_address
|= addr
<< (8 * i
);
132 int_addr_flag
+= TWI_MMR_IADRSZ_1
;
135 writel(internal_address
, ®
->iadr
);
138 is_read
= m_start
->flags
& I2C_M_RD
;
140 writel((m_start
->addr
<< 16) | int_addr_flag
|
141 (is_read
? TWI_MMR_MREAD
: 0), ®
->mmr
);
143 ret
= at91_i2c_xfer_msg(bus
, m_start
);
149 * Calculate symmetric clock as stated in datasheet:
150 * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
152 static void at91_calc_i2c_clock(struct udevice
*dev
, int i2c_clk
)
154 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
155 const struct at91_i2c_pdata
*pdata
= bus
->pdata
;
156 int offset
= pdata
->clk_offset
;
157 int max_ckdiv
= pdata
->clk_max_div
;
158 int ckdiv
, cdiv
, div
;
159 unsigned long src_rate
;
161 src_rate
= bus
->bus_clk_rate
;
163 div
= max(0, (int)DIV_ROUND_UP(src_rate
, 2 * i2c_clk
) - offset
);
164 ckdiv
= fls(div
>> 8);
167 if (ckdiv
> max_ckdiv
) {
172 bus
->speed
= DIV_ROUND_UP(src_rate
,
173 (cdiv
* (1 << ckdiv
) + offset
) * 2);
175 bus
->cwgr_val
= (ckdiv
<< 16) | (cdiv
<< 8) | cdiv
;
178 static int at91_i2c_enable_clk(struct udevice
*dev
)
180 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
185 ret
= clk_get_by_index(dev
, 0, &clk
);
189 ret
= clk_enable(&clk
);
193 clk_rate
= clk_get_rate(&clk
);
197 bus
->bus_clk_rate
= clk_rate
;
204 static int at91_i2c_set_bus_speed(struct udevice
*dev
, unsigned int speed
)
206 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
208 at91_calc_i2c_clock(dev
, speed
);
210 writel(bus
->cwgr_val
, &bus
->regs
->cwgr
);
215 int at91_i2c_get_bus_speed(struct udevice
*dev
)
217 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
222 static int at91_i2c_ofdata_to_platdata(struct udevice
*dev
)
224 const void *blob
= gd
->fdt_blob
;
225 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
226 int node
= dev_of_offset(dev
);
228 bus
->regs
= (struct at91_i2c_regs
*)devfdt_get_addr(dev
);
229 bus
->pdata
= (struct at91_i2c_pdata
*)dev_get_driver_data(dev
);
230 bus
->clock_frequency
= fdtdec_get_int(blob
, node
,
231 "clock-frequency", 100000);
236 static const struct dm_i2c_ops at91_i2c_ops
= {
237 .xfer
= at91_i2c_xfer
,
238 .set_bus_speed
= at91_i2c_set_bus_speed
,
239 .get_bus_speed
= at91_i2c_get_bus_speed
,
242 static int at91_i2c_probe(struct udevice
*dev
)
244 struct at91_i2c_bus
*bus
= dev_get_priv(dev
);
245 struct at91_i2c_regs
*reg
= bus
->regs
;
248 ret
= at91_i2c_enable_clk(dev
);
252 writel(TWI_CR_SWRST
, ®
->cr
);
254 at91_calc_i2c_clock(dev
, bus
->clock_frequency
);
256 writel(bus
->cwgr_val
, ®
->cwgr
);
257 writel(TWI_CR_MSEN
, ®
->cr
);
258 writel(TWI_CR_SVDIS
, ®
->cr
);
263 static const struct at91_i2c_pdata at91rm9200_config
= {
268 static const struct at91_i2c_pdata at91sam9261_config
= {
273 static const struct at91_i2c_pdata at91sam9260_config
= {
278 static const struct at91_i2c_pdata at91sam9g20_config
= {
283 static const struct at91_i2c_pdata at91sam9g10_config
= {
288 static const struct at91_i2c_pdata at91sam9x5_config
= {
293 static const struct at91_i2c_pdata sama5d4_config
= {
298 static const struct at91_i2c_pdata sama5d2_config
= {
303 static const struct udevice_id at91_i2c_ids
[] = {
304 { .compatible
= "atmel,at91rm9200-i2c", .data
= (long)&at91rm9200_config
},
305 { .compatible
= "atmel,at91sam9260-i2c", .data
= (long)&at91sam9260_config
},
306 { .compatible
= "atmel,at91sam9261-i2c", .data
= (long)&at91sam9261_config
},
307 { .compatible
= "atmel,at91sam9g20-i2c", .data
= (long)&at91sam9g20_config
},
308 { .compatible
= "atmel,at91sam9g10-i2c", .data
= (long)&at91sam9g10_config
},
309 { .compatible
= "atmel,at91sam9x5-i2c", .data
= (long)&at91sam9x5_config
},
310 { .compatible
= "atmel,sama5d4-i2c", .data
= (long)&sama5d4_config
},
311 { .compatible
= "atmel,sama5d2-i2c", .data
= (long)&sama5d2_config
},
315 U_BOOT_DRIVER(i2c_at91
) = {
318 .of_match
= at91_i2c_ids
,
319 .probe
= at91_i2c_probe
,
320 .ofdata_to_platdata
= at91_i2c_ofdata_to_platdata
,
321 .per_child_auto_alloc_size
= sizeof(struct dm_i2c_chip
),
322 .priv_auto_alloc_size
= sizeof(struct at91_i2c_bus
),
323 .ops
= &at91_i2c_ops
,