Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/powerpc/mpc85xx/i2c.c
39563 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (C) 2008-2009 Semihalf, Michal Hajduk
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/param.h>
30
#include <sys/systm.h>
31
#include <sys/bus.h>
32
#include <sys/kernel.h>
33
#include <sys/module.h>
34
#include <sys/resource.h>
35
36
#include <machine/bus.h>
37
#include <machine/resource.h>
38
#include <sys/rman.h>
39
40
#include <sys/lock.h>
41
#include <sys/mutex.h>
42
43
#include <dev/iicbus/iiconf.h>
44
#include <dev/iicbus/iicbus.h>
45
#include "iicbus_if.h"
46
47
#include <dev/ofw/ofw_bus.h>
48
#include <dev/ofw/ofw_bus_subr.h>
49
50
#define I2C_ADDR_REG 0x00 /* I2C slave address register */
51
#define I2C_FDR_REG 0x04 /* I2C frequency divider register */
52
#define I2C_CONTROL_REG 0x08 /* I2C control register */
53
#define I2C_STATUS_REG 0x0C /* I2C status register */
54
#define I2C_DATA_REG 0x10 /* I2C data register */
55
#define I2C_DFSRR_REG 0x14 /* I2C Digital Filter Sampling rate */
56
#define I2C_ENABLE 0x80 /* Module enable - interrupt disable */
57
#define I2CSR_RXAK 0x01 /* Received acknowledge */
58
#define I2CSR_MCF (1<<7) /* Data transfer */
59
#define I2CSR_MASS (1<<6) /* Addressed as a slave */
60
#define I2CSR_MBB (1<<5) /* Bus busy */
61
#define I2CSR_MAL (1<<4) /* Arbitration lost */
62
#define I2CSR_SRW (1<<2) /* Slave read/write */
63
#define I2CSR_MIF (1<<1) /* Module interrupt */
64
#define I2CCR_MEN (1<<7) /* Module enable */
65
#define I2CCR_MSTA (1<<5) /* Master/slave mode */
66
#define I2CCR_MTX (1<<4) /* Transmit/receive mode */
67
#define I2CCR_TXAK (1<<3) /* Transfer acknowledge */
68
#define I2CCR_RSTA (1<<2) /* Repeated START */
69
70
#define I2C_BAUD_RATE_FAST 0x31
71
#define I2C_BAUD_RATE_DEF 0x3F
72
#define I2C_DFSSR_DIV 0x10
73
74
#ifdef DEBUG
75
#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
76
#else
77
#define debugf(fmt, args...)
78
#endif
79
80
struct i2c_softc {
81
device_t dev;
82
device_t iicbus;
83
struct resource *res;
84
struct mtx mutex;
85
int rid;
86
bus_space_handle_t bsh;
87
bus_space_tag_t bst;
88
};
89
90
static int i2c_probe(device_t);
91
static int i2c_attach(device_t);
92
93
static int i2c_repeated_start(device_t dev, u_char slave, int timeout);
94
static int i2c_start(device_t dev, u_char slave, int timeout);
95
static int i2c_stop(device_t dev);
96
static int i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
97
static int i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay);
98
static int i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout);
99
static phandle_t i2c_get_node(device_t bus, device_t dev);
100
101
static device_method_t i2c_methods[] = {
102
DEVMETHOD(device_probe, i2c_probe),
103
DEVMETHOD(device_attach, i2c_attach),
104
105
DEVMETHOD(iicbus_callback, iicbus_null_callback),
106
DEVMETHOD(iicbus_repeated_start, i2c_repeated_start),
107
DEVMETHOD(iicbus_start, i2c_start),
108
DEVMETHOD(iicbus_stop, i2c_stop),
109
DEVMETHOD(iicbus_reset, i2c_reset),
110
DEVMETHOD(iicbus_read, i2c_read),
111
DEVMETHOD(iicbus_write, i2c_write),
112
DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
113
DEVMETHOD(ofw_bus_get_node, i2c_get_node),
114
{ 0, 0 }
115
};
116
117
static driver_t i2c_driver = {
118
"iichb",
119
i2c_methods,
120
sizeof(struct i2c_softc),
121
};
122
123
DRIVER_MODULE(i2c, simplebus, i2c_driver, 0, 0);
124
DRIVER_MODULE(iicbus, i2c, iicbus_driver, 0, 0);
125
126
static __inline void
127
i2c_write_reg(struct i2c_softc *sc, bus_size_t off, uint8_t val)
128
{
129
130
bus_space_write_1(sc->bst, sc->bsh, off, val);
131
}
132
133
static __inline uint8_t
134
i2c_read_reg(struct i2c_softc *sc, bus_size_t off)
135
{
136
137
return (bus_space_read_1(sc->bst, sc->bsh, off));
138
}
139
140
static __inline void
141
i2c_flag_set(struct i2c_softc *sc, bus_size_t off, uint8_t mask)
142
{
143
uint8_t status;
144
145
status = i2c_read_reg(sc, off);
146
status |= mask;
147
i2c_write_reg(sc, off, status);
148
}
149
150
static int
151
i2c_do_wait(device_t dev, struct i2c_softc *sc, int write, int start)
152
{
153
int err;
154
uint8_t status;
155
156
status = i2c_read_reg(sc, I2C_STATUS_REG);
157
if (status & I2CSR_MIF) {
158
if (write && start && (status & I2CSR_RXAK)) {
159
debugf("no ack %s", start ?
160
"after sending slave address" : "");
161
err = IIC_ENOACK;
162
goto error;
163
}
164
if (status & I2CSR_MAL) {
165
debugf("arbitration lost");
166
err = IIC_EBUSERR;
167
goto error;
168
}
169
if (!write && !(status & I2CSR_MCF)) {
170
debugf("transfer unfinished");
171
err = IIC_EBUSERR;
172
goto error;
173
}
174
}
175
176
return (IIC_NOERR);
177
178
error:
179
i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
180
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
181
return (err);
182
}
183
184
static int
185
i2c_probe(device_t dev)
186
{
187
struct i2c_softc *sc;
188
189
if (!ofw_bus_is_compatible(dev, "fsl-i2c"))
190
return (ENXIO);
191
192
sc = device_get_softc(dev);
193
sc->rid = 0;
194
195
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
196
RF_ACTIVE);
197
if (sc->res == NULL) {
198
device_printf(dev, "could not allocate resources\n");
199
return (ENXIO);
200
}
201
202
sc->bst = rman_get_bustag(sc->res);
203
sc->bsh = rman_get_bushandle(sc->res);
204
205
/* Enable I2C */
206
i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
207
bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
208
device_set_desc(dev, "I2C bus controller");
209
210
return (BUS_PROBE_DEFAULT);
211
}
212
213
static int
214
i2c_attach(device_t dev)
215
{
216
struct i2c_softc *sc;
217
sc = device_get_softc(dev);
218
219
sc->dev = dev;
220
sc->rid = 0;
221
222
mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
223
224
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
225
RF_ACTIVE);
226
if (sc->res == NULL) {
227
device_printf(dev, "could not allocate resources");
228
mtx_destroy(&sc->mutex);
229
return (ENXIO);
230
}
231
232
sc->bst = rman_get_bustag(sc->res);
233
sc->bsh = rman_get_bushandle(sc->res);
234
235
sc->iicbus = device_add_child(dev, "iicbus", DEVICE_UNIT_ANY);
236
if (sc->iicbus == NULL) {
237
device_printf(dev, "could not add iicbus child");
238
mtx_destroy(&sc->mutex);
239
return (ENXIO);
240
}
241
242
bus_attach_children(dev);
243
return (IIC_NOERR);
244
}
245
static int
246
i2c_repeated_start(device_t dev, u_char slave, int timeout)
247
{
248
struct i2c_softc *sc;
249
int error;
250
251
sc = device_get_softc(dev);
252
253
mtx_lock(&sc->mutex);
254
/* Set repeated start condition */
255
i2c_flag_set(sc, I2C_CONTROL_REG ,I2CCR_RSTA);
256
/* Write target address - LSB is R/W bit */
257
i2c_write_reg(sc, I2C_DATA_REG, slave);
258
DELAY(1250);
259
260
error = i2c_do_wait(dev, sc, 1, 1);
261
mtx_unlock(&sc->mutex);
262
263
if (error)
264
return (error);
265
266
return (IIC_NOERR);
267
}
268
269
static int
270
i2c_start(device_t dev, u_char slave, int timeout)
271
{
272
struct i2c_softc *sc;
273
uint8_t status;
274
int error;
275
276
sc = device_get_softc(dev);
277
DELAY(1000);
278
279
mtx_lock(&sc->mutex);
280
status = i2c_read_reg(sc, I2C_STATUS_REG);
281
/* Check if bus is idle or busy */
282
if (status & I2CSR_MBB) {
283
debugf("bus busy");
284
mtx_unlock(&sc->mutex);
285
i2c_stop(dev);
286
return (IIC_EBUSERR);
287
}
288
289
/* Set start condition */
290
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX);
291
/* Write target address - LSB is R/W bit */
292
i2c_write_reg(sc, I2C_DATA_REG, slave);
293
DELAY(1250);
294
295
error = i2c_do_wait(dev, sc, 1, 1);
296
297
mtx_unlock(&sc->mutex);
298
if (error)
299
return (error);
300
301
return (IIC_NOERR);
302
}
303
304
static int
305
i2c_stop(device_t dev)
306
{
307
struct i2c_softc *sc;
308
309
sc = device_get_softc(dev);
310
mtx_lock(&sc->mutex);
311
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
312
DELAY(1000);
313
mtx_unlock(&sc->mutex);
314
315
return (IIC_NOERR);
316
}
317
318
static int
319
i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
320
{
321
struct i2c_softc *sc;
322
uint8_t baud_rate;
323
324
sc = device_get_softc(dev);
325
326
switch (speed) {
327
case IIC_FAST:
328
baud_rate = I2C_BAUD_RATE_FAST;
329
break;
330
case IIC_SLOW:
331
case IIC_UNKNOWN:
332
case IIC_FASTEST:
333
default:
334
baud_rate = I2C_BAUD_RATE_DEF;
335
break;
336
}
337
338
mtx_lock(&sc->mutex);
339
i2c_write_reg(sc, I2C_CONTROL_REG, 0x0);
340
i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
341
DELAY(1000);
342
i2c_write_reg(sc, I2C_FDR_REG, baud_rate);
343
i2c_write_reg(sc, I2C_DFSRR_REG, I2C_DFSSR_DIV);
344
i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
345
DELAY(1000);
346
mtx_unlock(&sc->mutex);
347
348
return (IIC_NOERR);
349
}
350
351
static int
352
i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
353
{
354
struct i2c_softc *sc;
355
int error;
356
357
sc = device_get_softc(dev);
358
*read = 0;
359
360
mtx_lock(&sc->mutex);
361
if (len) {
362
if (len == 1)
363
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
364
I2CCR_MSTA | I2CCR_TXAK);
365
366
else
367
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
368
I2CCR_MSTA);
369
370
/* dummy read */
371
i2c_read_reg(sc, I2C_DATA_REG);
372
DELAY(1000);
373
}
374
375
while (*read < len) {
376
DELAY(1000);
377
error = i2c_do_wait(dev, sc, 0, 0);
378
if (error) {
379
mtx_unlock(&sc->mutex);
380
return (error);
381
}
382
if ((*read == len - 2) && last) {
383
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
384
I2CCR_MSTA | I2CCR_TXAK);
385
}
386
387
if ((*read == len - 1) && last) {
388
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
389
I2CCR_TXAK);
390
}
391
392
*buf++ = i2c_read_reg(sc, I2C_DATA_REG);
393
(*read)++;
394
DELAY(1250);
395
}
396
mtx_unlock(&sc->mutex);
397
398
return (IIC_NOERR);
399
}
400
401
static int
402
i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
403
{
404
struct i2c_softc *sc;
405
int error;
406
407
sc = device_get_softc(dev);
408
*sent = 0;
409
410
mtx_lock(&sc->mutex);
411
while (*sent < len) {
412
i2c_write_reg(sc, I2C_DATA_REG, *buf++);
413
DELAY(1250);
414
415
error = i2c_do_wait(dev, sc, 1, 0);
416
if (error) {
417
mtx_unlock(&sc->mutex);
418
return (error);
419
}
420
421
(*sent)++;
422
}
423
mtx_unlock(&sc->mutex);
424
425
return (IIC_NOERR);
426
}
427
428
static phandle_t
429
i2c_get_node(device_t bus, device_t dev)
430
{
431
432
/* Share controller node with iibus device. */
433
return (ofw_bus_get_node(bus));
434
}
435
436