FreeBSD kernel IICBUS device code
iicoc.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2003-2012 Broadcom Corporation
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 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/bus.h>
37#include <sys/kernel.h>
38#include <sys/lock.h>
39#include <sys/module.h>
40#include <sys/mutex.h>
41#include <sys/rman.h>
42
43#include <machine/bus.h>
44
45#include <dev/iicbus/iicbus.h>
46#include <dev/iicbus/iiconf.h>
47
48#include "iicbus_if.h"
49#include "iicoc.h"
50
51devclass_t iicoc_devclass;
52
54
55static void
56iicoc_dev_write(device_t dev, int reg, int value)
57{
58 struct iicoc_softc *sc;
59
60 sc = device_get_softc(dev);
61 bus_write_1(sc->mem_res, reg<<sc->reg_shift, value);
62}
63
64static int
65iicoc_dev_read(device_t dev, int reg)
66{
67 uint8_t val;
68 struct iicoc_softc *sc;
69
70 sc = device_get_softc(dev);
71 val = bus_read_1(sc->mem_res, reg<<sc->reg_shift);
72 return (val);
73}
74
75static int
76iicoc_wait_on_status(device_t dev, uint8_t bit)
77{
78 int tries = I2C_TIMEOUT;
79 uint8_t status;
80
81 do {
83 } while ((status & bit) != 0 && --tries > 0);
84
85 return (tries == 0 ? -1: 0);
86}
87
88static int
89iicoc_rd_cmd(device_t dev, uint8_t cmd)
90{
91 uint8_t data;
92
95 device_printf(dev, "read: Timeout waiting for TIP clear.\n");
96 return (-1);
97 }
99 return (data);
100}
101
102static int
103iicoc_wr_cmd(device_t dev, uint8_t data, uint8_t cmd)
104{
105
109 device_printf(dev, "write: Timeout waiting for TIP clear.\n");
110 return (-1);
111 }
112 return (0);
113}
114
115static int
116iicoc_wr_ack_cmd(device_t dev, uint8_t data, uint8_t cmd)
117{
118
119 if (iicoc_wr_cmd(dev, data, cmd) < 0)
120 return (-1);
121
123 device_printf(dev, "write: I2C command ACK Error.\n");
124 return (IIC_ENOACK);
125 }
126 return (0);
127}
128
129int
131{
132 struct iicoc_softc *sc;
133 int value;
134
135 sc = device_get_softc(dev);
138 value & ~(OC_CONTROL_EN | OC_CONTROL_IEN));
139 value = (sc->clockfreq/(5 * sc->i2cfreq)) - 1;
144
146 /* return 0 on success, 1 on error */
147 return ((value & OC_CONTROL_EN) == 0);
148}
149
150static int
151iicoc_iicbus_start_common(device_t dev, u_char slave, int timeout, bool repeat)
152{
153 int error = IIC_EBUSERR;
154 struct iicoc_softc *sc;
155
156 sc = device_get_softc(dev);
157 mtx_lock(&sc->sc_mtx);
158 sc->i2cdev_addr = (slave >> 1);
159
160 /* Verify the bus is idle */
161 if (!repeat && iicoc_wait_on_status(dev, OC_STATUS_BUSY) < 0)
162 goto i2c_stx_error;
163
164 /* Write Slave Address */
166 device_printf(dev,
167 "I2C write slave address [0x%x] failed.\n", slave);
168 error = IIC_ENOACK;
169 goto i2c_stx_error;
170 }
171
172 /* Verify Arbitration is not Lost */
174 device_printf(dev, "I2C Bus Arbitration Lost, Aborting.\n");
175 error = IIC_EBUSERR;
176 goto i2c_stx_error;
177 }
178 error = IIC_NOERR;
179 mtx_unlock(&sc->sc_mtx);
180 return (error);
181
182i2c_stx_error:
184 iicoc_wait_on_status(dev, OC_STATUS_BUSY); /* wait for idle */
185 mtx_unlock(&sc->sc_mtx);
186 return (error);
187}
188
189int
190iicoc_iicbus_start(device_t dev, u_char slave, int timeout)
191{
192
193 return (iicoc_iicbus_start_common(dev, slave, timeout, false));
194}
195
196int
198{
199
200 return (iicoc_iicbus_start_common(dev, slave, timeout, true));
201}
202
203int
205{
206 int error = 0;
207 struct iicoc_softc *sc;
208
209 sc = device_get_softc(dev);
210 mtx_lock(&sc->sc_mtx);
212 iicoc_wait_on_status(dev, OC_STATUS_BUSY); /* wait for idle */
213 mtx_unlock(&sc->sc_mtx);
214 return (error);
215}
216
217int
218iicoc_iicbus_write(device_t dev, const char *buf, int len, int *sent,
219 int timeout)
220{
221 uint8_t value;
222 int i;
223
224 value = buf[0];
225 /* Write Slave Offset */
227 device_printf(dev, "I2C write slave offset failed.\n");
228 goto i2c_tx_error;
229 }
230
231 for (i = 1; i < len; i++) {
232 /* Write data byte */
233 value = buf[i];
234 if (iicoc_wr_cmd(dev, value, OC_COMMAND_WRITE)) {
235 device_printf(dev, "I2C write data byte %d failed.\n",
236 i);
237 goto i2c_tx_error;
238 }
239 }
240 *sent = len;
241 return (IIC_NOERR);
242
243i2c_tx_error:
244 return (IIC_EBUSERR);
245}
246
247int
248iicoc_iicbus_read(device_t dev, char *buf, int len, int *read, int last,
249 int delay)
250{
251 int data, i;
252 uint8_t cmd;
253
254 for (i = 0; i < len; i++) {
255 /* Read data byte */
256 cmd = (i == len - 1) ? OC_COMMAND_RDNACK : OC_COMMAND_READ;
257 data = iicoc_rd_cmd(dev, cmd);
258 if (data < 0) {
259 device_printf(dev,
260 "I2C read data byte %d failed.\n", i);
261 goto i2c_rx_error;
262 }
263 buf[i] = (uint8_t)data;
264 }
265
266 *read = len;
267 return (IIC_NOERR);
268
269i2c_rx_error:
270 return (IIC_EBUSERR);
271}
272
273int
274iicoc_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
275{
276 int error;
277 struct iicoc_softc *sc;
278
279 sc = device_get_softc(dev);
280 mtx_lock(&sc->sc_mtx);
281 error = iicoc_init(dev);
282 mtx_unlock(&sc->sc_mtx);
283 return (error);
284}
u_char speed
Definition: iicbb_if.m:115
caddr_t data
Definition: iicbb_if.m:61
int val
Definition: iicbb_if.m:83
u_char addr
Definition: iicbb_if.m:116
devclass_t iicbus_devclass
Definition: iicbus.c:386
driver_t iicbus_driver
Definition: iicbus.c:380
char * buf
Definition: iicbus_if.m:55
int timeout
Definition: iicbus_if.m:77
int delay
Definition: iicbus_if.m:105
int last
Definition: iicbus_if.m:104
METHOD int read
Definition: iicbus_if.m:99
u_char slave
Definition: iicbus_if.m:76
INTERFACE iicbus
Definition: iicbus_if.m:32
int len
Definition: iicbus_if.m:102
devclass_t iicoc_devclass
Definition: iicoc.c:51
static int iicoc_wr_ack_cmd(device_t dev, uint8_t data, uint8_t cmd)
Definition: iicoc.c:116
static int iicoc_iicbus_start_common(device_t dev, u_char slave, int timeout, bool repeat)
Definition: iicoc.c:151
int iicoc_iicbus_write(device_t dev, const char *buf, int len, int *sent, int timeout)
Definition: iicoc.c:218
static int iicoc_rd_cmd(device_t dev, uint8_t cmd)
Definition: iicoc.c:89
static int iicoc_wr_cmd(device_t dev, uint8_t data, uint8_t cmd)
Definition: iicoc.c:103
int iicoc_iicbus_stop(device_t dev)
Definition: iicoc.c:204
int iicoc_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
Definition: iicoc.c:274
static int iicoc_dev_read(device_t dev, int reg)
Definition: iicoc.c:65
int iicoc_iicbus_repeated_start(device_t dev, u_char slave, int timeout)
Definition: iicoc.c:197
__FBSDID("$FreeBSD$")
int iicoc_init(device_t dev)
Definition: iicoc.c:130
DRIVER_MODULE(iicbus, iicoc, iicbus_driver, iicbus_devclass, 0, 0)
static int iicoc_wait_on_status(device_t dev, uint8_t bit)
Definition: iicoc.c:76
int iicoc_iicbus_start(device_t dev, u_char slave, int timeout)
Definition: iicoc.c:190
static void iicoc_dev_write(device_t dev, int reg, int value)
Definition: iicoc.c:56
int iicoc_iicbus_read(device_t dev, char *buf, int len, int *read, int last, int delay)
Definition: iicoc.c:248
#define OC_CONTROL_IEN
Definition: iicoc.h:60
#define OC_STATUS_BUSY
Definition: iicoc.h:75
#define OC_STATUS_NACK
Definition: iicoc.h:74
#define OC_STATUS_TIP
Definition: iicoc.h:77
#define OC_I2C_DATA_REG
Definition: iicoc.h:42
#define OC_COMMAND_START
Definition: iicoc.h:65
#define OC_I2C_PRESCALE_HI_REG
Definition: iicoc.h:38
#define OC_STATUS_AL
Definition: iicoc.h:76
#define OC_COMMAND_WRITE
Definition: iicoc.h:68
#define OC_I2C_PRESCALE_LO_REG
Definition: iicoc.h:37
#define OC_I2C_CMD_REG
Definition: iicoc.h:43
#define OC_CONTROL_EN
Definition: iicoc.h:59
#define OC_I2C_STATUS_REG
Definition: iicoc.h:44
#define OC_COMMAND_STOP
Definition: iicoc.h:66
#define OC_I2C_CTRL_REG
Definition: iicoc.h:39
#define OC_COMMAND_RDNACK
Definition: iicoc.h:70
#define I2C_TIMEOUT
Definition: iicoc.h:48
#define OC_COMMAND_READ
Definition: iicoc.h:67
#define IIC_EBUSERR
Definition: iiconf.h:108
#define IIC_NOERR
Definition: iiconf.h:107
#define IIC_ENOACK
Definition: iiconf.h:109
device_t dev
Definition: ofw_iicbus_if.m:38
struct mtx sc_mtx
Definition: iicoc.h:90
uint8_t i2cdev_addr
Definition: iicoc.h:88
u_int clockfreq
Definition: iicoc.h:83
u_int reg_shift
Definition: iicoc.h:82
struct resource * mem_res
Definition: iicoc.h:85
u_int i2cfreq
Definition: iicoc.h:84