meson_i2c.c revision 1.5 1 1.5 thorpej /* $NetBSD: meson_i2c.c,v 1.5 2025/09/16 11:55:16 thorpej Exp $ */
2 1.1 rjs
3 1.1 rjs /*-
4 1.1 rjs * Copyright (c) 2025 The NetBSD Foundation, Inc.
5 1.1 rjs * All rights reserved.
6 1.1 rjs *
7 1.1 rjs * Written by Vincent Defert for The NetBSD Foundation, Inc.
8 1.1 rjs *
9 1.1 rjs * Redistribution and use in source and binary forms, with or without
10 1.1 rjs * modification, are permitted provided that the following conditions
11 1.1 rjs * are met:
12 1.1 rjs * 1. Redistributions of source code must retain the above copyright
13 1.1 rjs * notice, this list of conditions and the following disclaimer.
14 1.1 rjs * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 rjs * notice, this list of conditions and the following disclaimer in the
16 1.1 rjs * documentation and/or other materials provided with the distribution.
17 1.1 rjs *
18 1.1 rjs * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 1.1 rjs * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 1.1 rjs * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 1.1 rjs * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 1.1 rjs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 1.1 rjs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 1.1 rjs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 1.1 rjs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 1.1 rjs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 1.1 rjs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 1.1 rjs * POSSIBILITY OF SUCH DAMAGE.
29 1.1 rjs */
30 1.1 rjs
31 1.1 rjs #include <sys/cdefs.h>
32 1.5 thorpej __KERNEL_RCSID(1, "$NetBSD: meson_i2c.c,v 1.5 2025/09/16 11:55:16 thorpej Exp $");
33 1.1 rjs
34 1.1 rjs #include <sys/param.h>
35 1.1 rjs #include <sys/bus.h>
36 1.1 rjs #include <sys/device.h>
37 1.1 rjs #include <sys/intr.h>
38 1.1 rjs #include <sys/systm.h>
39 1.1 rjs #include <sys/time.h>
40 1.1 rjs #include <sys/kmem.h>
41 1.1 rjs #include <sys/mutex.h>
42 1.1 rjs #include <sys/condvar.h>
43 1.1 rjs #include <dev/i2c/i2cvar.h>
44 1.1 rjs #include <dev/fdt/fdtvar.h>
45 1.1 rjs
46 1.1 rjs #define MESONI2C_CTRL_REG 0x00
47 1.1 rjs #define MESONI2C_CTRL_START __BIT(0)
48 1.1 rjs #define MESONI2C_CTRL_ACK_IGNORE __BIT(1)
49 1.1 rjs #define MESONI2C_CTRL_STATUS __BIT(2)
50 1.1 rjs #define MESONI2C_CTRL_ERROR __BIT(3)
51 1.1 rjs #define MESONI2C_CTRL_READ_DATA_SHIFT 8
52 1.1 rjs #define MESONI2C_CTRL_READ_DATA_MASK __BITS(11, MESONI2C_CTRL_READ_DATA_SHIFT)
53 1.1 rjs #define MESONI2C_CTRL_CLKDIV_SHIFT 12
54 1.1 rjs #define MESONI2C_CTRL_CLKDIV_MASK __BITS(21, MESONI2C_CTRL_CLKDIV_SHIFT)
55 1.1 rjs #define MESONI2C_CTRL_CLKDIVEXT_SHIFT 28
56 1.1 rjs #define MESONI2C_CTRL_CLKDIVEXT_MASK __BITS(29, MESONI2C_CTRL_CLKDIVEXT_SHIFT)
57 1.1 rjs
58 1.1 rjs #define MESONI2C_SLAVE_ADDR_REG 0x04
59 1.1 rjs #define MESONI2C_SLAVE_ADDR_MASK __BITS(7, 0)
60 1.1 rjs #define MESONI2C_SLAVE_SDA_FILTER_MASK __BITS(10, 8)
61 1.1 rjs #define MESONI2C_SLAVE_SCL_FILTER_MASK __BITS(13, 11)
62 1.1 rjs #define MESONI2C_SLAVE_SCL_LOW_SHIFT 16
63 1.1 rjs #define MESONI2C_SLAVE_SCL_LOW_MASK __BITS(27, MESONI2C_SLAVE_SCL_LOW_SHIFT)
64 1.1 rjs #define MESONI2C_SLAVE_SCL_LOW_EN __BIT(28)
65 1.1 rjs
66 1.1 rjs #define MESONI2C_TOKEN_LIST_REG0 0x08
67 1.1 rjs #define MESONI2C_TOKEN_LIST_REG1 0x0c
68 1.1 rjs #define MESONI2C_TOKEN_WDATA_REG0 0x10
69 1.1 rjs #define MESONI2C_TOKEN_WDATA_REG1 0x14
70 1.1 rjs #define MESONI2C_TOKEN_RDATA_REG0 0x18
71 1.1 rjs #define MESONI2C_TOKEN_RDATA_REG1 0x1c
72 1.1 rjs
73 1.1 rjs #define MESONI2C_TOKEN_BITS 4
74 1.1 rjs #define MESONI2C_TOKEN_MASK ((1 << MESONI2C_TOKEN_BITS) - 1)
75 1.1 rjs #define MESONI2C_TOKEN_REG_HALF (32 / MESONI2C_TOKEN_BITS)
76 1.1 rjs #define MESONI2C_TOKEN_REG_FULL (64 / MESONI2C_TOKEN_BITS)
77 1.1 rjs
78 1.1 rjs #define MESONI2C_DATA_BITS 8
79 1.1 rjs #define MESONI2C_DATA_MASK ((1 << MESONI2C_DATA_BITS) - 1)
80 1.1 rjs #define MESONI2C_DATA_REG_HALF (32 / MESONI2C_DATA_BITS)
81 1.1 rjs #define MESONI2C_DATA_REG_FULL (64 / MESONI2C_DATA_BITS)
82 1.1 rjs
83 1.1 rjs #define I2C_TIMEOUT_MS 1000
84 1.1 rjs #define FILTER_DELAY 15
85 1.1 rjs
86 1.1 rjs enum mesoni2c_token {
87 1.1 rjs TOKEN_END = 0,
88 1.1 rjs TOKEN_START,
89 1.1 rjs TOKEN_SLAVE_ADDR_WRITE,
90 1.1 rjs TOKEN_SLAVE_ADDR_READ,
91 1.1 rjs TOKEN_DATA,
92 1.1 rjs TOKEN_DATA_LAST,
93 1.1 rjs TOKEN_STOP,
94 1.1 rjs };
95 1.1 rjs
96 1.1 rjs enum mesoni2c_type {
97 1.1 rjs TYPE_MESON6,
98 1.1 rjs TYPE_GXBB,
99 1.1 rjs TYPE_AXG,
100 1.1 rjs };
101 1.1 rjs
102 1.1 rjs struct mesoni2c_softc {
103 1.1 rjs device_t sc_dev;
104 1.1 rjs bus_space_tag_t sc_bst;
105 1.1 rjs bus_space_handle_t sc_bsh;
106 1.1 rjs struct clk *sc_clk;
107 1.1 rjs u_int sc_clkfreq;
108 1.1 rjs struct i2c_controller sc_ic;
109 1.1 rjs kcondvar_t sc_cv;
110 1.1 rjs kmutex_t sc_mtx;
111 1.1 rjs void *sc_ih;
112 1.1 rjs
113 1.1 rjs u_int sc_token_index;
114 1.1 rjs u_int sc_wdata_index;
115 1.1 rjs u_int sc_rdata_index;
116 1.1 rjs
117 1.1 rjs const uint8_t *sc_cmdbuf;
118 1.1 rjs size_t sc_cmdlen;
119 1.1 rjs uint8_t *sc_databuf;
120 1.1 rjs size_t sc_datalen;
121 1.1 rjs i2c_op_t sc_op;
122 1.1 rjs
123 1.1 rjs size_t sc_curlen;
124 1.1 rjs i2c_op_t sc_curop;
125 1.1 rjs int sc_sendingCmd;
126 1.1 rjs int sc_error;
127 1.1 rjs };
128 1.1 rjs
129 1.1 rjs static void mesoni2c_set_mask(struct mesoni2c_softc *sc, bus_size_t reg, uint32_t mask, uint32_t value);
130 1.1 rjs static void mesoni2c_reset_state(struct mesoni2c_softc *sc);
131 1.1 rjs static int mesoni2c_push_token(struct mesoni2c_softc *sc, enum mesoni2c_token token);
132 1.1 rjs static void mesoni2c_write_byte(struct mesoni2c_softc *sc, uint8_t data);
133 1.1 rjs static uint8_t mesoni2c_get_byte(struct mesoni2c_softc *sc);
134 1.1 rjs static void mesoni2c_prepare_xfer(struct mesoni2c_softc *sc, i2c_op_t op);
135 1.1 rjs static void mesoni2c_partial_xfer(struct mesoni2c_softc *sc);
136 1.1 rjs static int mesoni2c_exec(void *priv, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, size_t cmdlen, void *buf, size_t buflen, int flags);
137 1.1 rjs static int mesoni2c_intr(void *arg);
138 1.1 rjs static void mesoni2c_set_clock_div_meson6(struct mesoni2c_softc *sc);
139 1.1 rjs static void mesoni2c_set_clock_div_gxbb_axg(struct mesoni2c_softc *sc);
140 1.1 rjs static int mesoni2c_match(device_t parent, cfdata_t cf, void *aux);
141 1.1 rjs static void mesoni2c_attach(device_t parent, device_t self, void *aux);
142 1.1 rjs
143 1.1 rjs CFATTACH_DECL_NEW(meson_i2c, sizeof(struct mesoni2c_softc),
144 1.1 rjs mesoni2c_match, mesoni2c_attach, NULL, NULL);
145 1.1 rjs
146 1.1 rjs static const struct device_compatible_entry compat_data[] = {
147 1.1 rjs { .compat = "amlogic,meson6-i2c", .value = TYPE_MESON6 },
148 1.1 rjs { .compat = "amlogic,meson-gxbb-i2c", .value = TYPE_GXBB },
149 1.1 rjs { .compat = "amlogic,meson-axg-i2c", .value = TYPE_AXG },
150 1.1 rjs DEVICE_COMPAT_EOL
151 1.1 rjs };
152 1.1 rjs
153 1.1 rjs #define RD4(sc, reg) \
154 1.1 rjs bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
155 1.1 rjs
156 1.1 rjs #define WR4(sc, reg, val) \
157 1.1 rjs bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
158 1.1 rjs
159 1.1 rjs static void
160 1.1 rjs mesoni2c_set_mask(struct mesoni2c_softc *sc, bus_size_t reg, uint32_t mask,
161 1.1 rjs uint32_t value)
162 1.1 rjs {
163 1.1 rjs uint32_t data = RD4(sc, reg);
164 1.1 rjs data &= ~mask;
165 1.1 rjs data |= value & mask;
166 1.1 rjs WR4(sc, reg, data);
167 1.1 rjs }
168 1.1 rjs
169 1.1 rjs static void
170 1.1 rjs mesoni2c_reset_state(struct mesoni2c_softc *sc)
171 1.1 rjs {
172 1.1 rjs sc->sc_token_index = 0;
173 1.1 rjs sc->sc_wdata_index = 0;
174 1.1 rjs sc->sc_rdata_index = 0;
175 1.1 rjs }
176 1.1 rjs
177 1.1 rjs static int
178 1.1 rjs mesoni2c_push_token(struct mesoni2c_softc *sc, enum mesoni2c_token token)
179 1.1 rjs {
180 1.1 rjs bus_size_t reg;
181 1.1 rjs u_int pos;
182 1.1 rjs
183 1.1 rjs if (sc->sc_token_index >= MESONI2C_TOKEN_REG_HALF) {
184 1.1 rjs reg = MESONI2C_TOKEN_LIST_REG1;
185 1.1 rjs pos = sc->sc_token_index - MESONI2C_TOKEN_REG_HALF;
186 1.1 rjs } else {
187 1.1 rjs reg = MESONI2C_TOKEN_LIST_REG0;
188 1.1 rjs pos = sc->sc_token_index;
189 1.1 rjs }
190 1.1 rjs
191 1.1 rjs sc->sc_token_index++;
192 1.1 rjs pos *= MESONI2C_TOKEN_BITS;
193 1.1 rjs mesoni2c_set_mask(sc, reg, MESONI2C_TOKEN_MASK << pos, token << pos);
194 1.1 rjs
195 1.1 rjs return sc->sc_token_index == MESONI2C_TOKEN_REG_FULL;
196 1.1 rjs }
197 1.1 rjs
198 1.1 rjs static void
199 1.1 rjs mesoni2c_write_byte(struct mesoni2c_softc *sc, uint8_t data)
200 1.1 rjs {
201 1.1 rjs bus_size_t reg;
202 1.1 rjs u_int pos;
203 1.1 rjs
204 1.1 rjs if (sc->sc_wdata_index >= MESONI2C_DATA_REG_HALF) {
205 1.1 rjs reg = MESONI2C_TOKEN_WDATA_REG1;
206 1.1 rjs pos = sc->sc_wdata_index - MESONI2C_DATA_REG_HALF;
207 1.1 rjs } else {
208 1.1 rjs reg = MESONI2C_TOKEN_WDATA_REG0;
209 1.1 rjs pos = sc->sc_wdata_index;
210 1.1 rjs }
211 1.1 rjs
212 1.1 rjs sc->sc_wdata_index++;
213 1.1 rjs pos *= MESONI2C_DATA_BITS;
214 1.1 rjs mesoni2c_set_mask(sc, reg, MESONI2C_DATA_MASK << pos, ((uint32_t) data) << pos);
215 1.1 rjs mesoni2c_push_token(sc, TOKEN_DATA);
216 1.1 rjs }
217 1.1 rjs
218 1.1 rjs static uint8_t
219 1.1 rjs mesoni2c_get_byte(struct mesoni2c_softc *sc)
220 1.1 rjs {
221 1.1 rjs bus_size_t reg;
222 1.1 rjs u_int pos;
223 1.1 rjs
224 1.1 rjs if (sc->sc_rdata_index >= MESONI2C_DATA_REG_HALF) {
225 1.1 rjs reg = MESONI2C_TOKEN_RDATA_REG1;
226 1.1 rjs pos = sc->sc_rdata_index - MESONI2C_DATA_REG_HALF;
227 1.1 rjs } else {
228 1.1 rjs reg = MESONI2C_TOKEN_RDATA_REG0;
229 1.1 rjs pos = sc->sc_rdata_index;
230 1.1 rjs }
231 1.1 rjs
232 1.1 rjs sc->sc_rdata_index++;
233 1.1 rjs pos *= MESONI2C_DATA_BITS;
234 1.1 rjs
235 1.1 rjs return (RD4(sc, reg) >> pos) & MESONI2C_DATA_MASK;
236 1.1 rjs }
237 1.1 rjs
238 1.1 rjs static void
239 1.1 rjs mesoni2c_prepare_xfer(struct mesoni2c_softc *sc, i2c_op_t op)
240 1.1 rjs {
241 1.1 rjs mesoni2c_reset_state(sc);
242 1.1 rjs mesoni2c_push_token(sc, TOKEN_START);
243 1.1 rjs mesoni2c_push_token(sc, I2C_OP_WRITE_P(op) ? TOKEN_SLAVE_ADDR_WRITE : TOKEN_SLAVE_ADDR_READ);
244 1.1 rjs }
245 1.1 rjs
246 1.1 rjs static void
247 1.1 rjs mesoni2c_partial_xfer(struct mesoni2c_softc *sc)
248 1.1 rjs {
249 1.1 rjs int dataBufferFree = MESONI2C_DATA_REG_FULL;
250 1.1 rjs
251 1.1 rjs while (sc->sc_curlen && dataBufferFree) {
252 1.1 rjs sc->sc_curlen--;
253 1.1 rjs dataBufferFree--;
254 1.1 rjs
255 1.1 rjs if (I2C_OP_WRITE_P(sc->sc_curop)) {
256 1.1 rjs if (sc->sc_sendingCmd) {
257 1.1 rjs uint8_t c = *(sc->sc_cmdbuf++);
258 1.1 rjs mesoni2c_write_byte(sc, c);
259 1.1 rjs } else {
260 1.1 rjs mesoni2c_write_byte(sc, *(sc->sc_databuf++));
261 1.1 rjs }
262 1.1 rjs } else {
263 1.1 rjs mesoni2c_push_token(sc, sc->sc_curlen ? TOKEN_DATA : TOKEN_DATA_LAST);
264 1.1 rjs }
265 1.1 rjs }
266 1.1 rjs
267 1.1 rjs if (sc->sc_curlen == 0 && I2C_OP_STOP_P(sc->sc_curop)) {
268 1.1 rjs mesoni2c_push_token(sc, TOKEN_STOP);
269 1.1 rjs }
270 1.1 rjs
271 1.1 rjs mesoni2c_push_token(sc, TOKEN_END);
272 1.1 rjs
273 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_CTRL_REG, MESONI2C_CTRL_START, 0);
274 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_CTRL_REG, MESONI2C_CTRL_START, 1);
275 1.1 rjs }
276 1.1 rjs
277 1.1 rjs static int
278 1.1 rjs mesoni2c_exec(void *priv, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf,
279 1.1 rjs size_t cmdlen, void *databuf, size_t datalen, int flags)
280 1.1 rjs {
281 1.1 rjs struct mesoni2c_softc * const sc = priv;
282 1.1 rjs
283 1.1 rjs mutex_enter(&sc->sc_mtx);
284 1.1 rjs
285 1.1 rjs sc->sc_cmdbuf = cmdbuf;
286 1.1 rjs sc->sc_cmdlen = cmdlen;
287 1.1 rjs sc->sc_databuf = databuf;
288 1.1 rjs sc->sc_datalen = datalen;
289 1.1 rjs sc->sc_op = op;
290 1.1 rjs sc->sc_error = 0;
291 1.1 rjs
292 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_SLAVE_ADDR_REG, MESONI2C_SLAVE_ADDR_MASK, addr << 1);
293 1.2 skrll
294 1.1 rjs if (cmdlen) {
295 1.1 rjs sc->sc_curlen = cmdlen;
296 1.1 rjs sc->sc_curop = datalen ? I2C_OP_WRITE : op;
297 1.1 rjs sc->sc_sendingCmd = 1;
298 1.1 rjs } else {
299 1.1 rjs sc->sc_curlen = datalen;
300 1.1 rjs sc->sc_curop = op;
301 1.1 rjs sc->sc_sendingCmd = 0;
302 1.1 rjs }
303 1.1 rjs
304 1.1 rjs mesoni2c_prepare_xfer(sc, sc->sc_curop);
305 1.1 rjs mesoni2c_partial_xfer(sc);
306 1.1 rjs
307 1.1 rjs if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, mstohz(I2C_TIMEOUT_MS)) == EWOULDBLOCK) {
308 1.1 rjs sc->sc_error = EIO;
309 1.1 rjs }
310 1.1 rjs
311 1.1 rjs mutex_exit(&sc->sc_mtx);
312 1.1 rjs
313 1.1 rjs return sc->sc_error;
314 1.1 rjs }
315 1.1 rjs
316 1.1 rjs static int
317 1.1 rjs mesoni2c_intr(void *arg)
318 1.1 rjs {
319 1.1 rjs struct mesoni2c_softc *sc = arg;
320 1.1 rjs int done = 0;
321 1.1 rjs
322 1.1 rjs mutex_enter(&sc->sc_mtx);
323 1.1 rjs
324 1.1 rjs if (RD4(sc, MESONI2C_CTRL_REG) & MESONI2C_CTRL_ERROR) {
325 1.1 rjs /*
326 1.1 rjs * The ERROR bit is set when the ACK_IGNORE bit is cleared
327 1.1 rjs * in MESONI2C_CTRL_REG and the device didn't respond with
328 1.1 rjs * an ACK. In this case, the I2C controller automatically
329 1.1 rjs * generates a STOP condition.
330 1.1 rjs */
331 1.1 rjs sc->sc_error = EIO;
332 1.1 rjs done = 1;
333 1.1 rjs } else {
334 1.1 rjs if (I2C_OP_READ_P(sc->sc_curop)) {
335 1.1 rjs /* Read data bytes */
336 1.1 rjs u_int count = (RD4(sc, MESONI2C_CTRL_REG) & MESONI2C_CTRL_READ_DATA_MASK)
337 1.1 rjs >> MESONI2C_CTRL_READ_DATA_SHIFT;
338 1.2 skrll
339 1.1 rjs while (count--) {
340 1.1 rjs *(sc->sc_databuf++) = mesoni2c_get_byte(sc);
341 1.1 rjs }
342 1.1 rjs }
343 1.1 rjs
344 1.1 rjs if (sc->sc_curlen) {
345 1.1 rjs /* Continue transfer */
346 1.1 rjs mesoni2c_reset_state(sc);
347 1.1 rjs mesoni2c_partial_xfer(sc);
348 1.1 rjs } else {
349 1.1 rjs if (sc->sc_sendingCmd && sc->sc_datalen) {
350 1.1 rjs /*
351 1.1 rjs * We've just finished transfering the command
352 1.3 andvar * bytes, we must now transfer the data.
353 1.1 rjs */
354 1.1 rjs sc->sc_curlen = sc->sc_datalen;
355 1.1 rjs sc->sc_curop = sc->sc_op;
356 1.1 rjs sc->sc_sendingCmd = 0;
357 1.1 rjs
358 1.1 rjs if (I2C_OP_READ_P(sc->sc_curop)) {
359 1.1 rjs mesoni2c_prepare_xfer(sc, sc->sc_curop);
360 1.1 rjs } else {
361 1.1 rjs mesoni2c_reset_state(sc);
362 1.1 rjs }
363 1.1 rjs
364 1.1 rjs mesoni2c_partial_xfer(sc);
365 1.1 rjs } else {
366 1.1 rjs done = 1;
367 1.1 rjs }
368 1.1 rjs }
369 1.1 rjs }
370 1.1 rjs
371 1.1 rjs if (done) {
372 1.1 rjs /* Tell mesoni2c_exec() we're done. */
373 1.1 rjs cv_broadcast(&sc->sc_cv);
374 1.1 rjs }
375 1.1 rjs
376 1.1 rjs mutex_exit(&sc->sc_mtx);
377 1.1 rjs
378 1.1 rjs return 1;
379 1.1 rjs }
380 1.1 rjs
381 1.1 rjs static void
382 1.1 rjs mesoni2c_set_clock_div_meson6(struct mesoni2c_softc *sc)
383 1.1 rjs {
384 1.1 rjs u_int rate = clk_get_rate(sc->sc_clk);
385 1.1 rjs u_int div = howmany(rate, sc->sc_clkfreq) - FILTER_DELAY;
386 1.1 rjs div = howmany(div, 4);
387 1.1 rjs
388 1.1 rjs /* Set prescaler */
389 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_CTRL_REG, MESONI2C_CTRL_CLKDIV_MASK, (div & __BITS(9, 0)) << MESONI2C_CTRL_CLKDIV_SHIFT);
390 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_CTRL_REG, MESONI2C_CTRL_CLKDIVEXT_MASK, (div >> 10) << MESONI2C_CTRL_CLKDIVEXT_SHIFT);
391 1.1 rjs
392 1.1 rjs /* Disable HIGH/LOW mode */
393 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_SLAVE_ADDR_REG, MESONI2C_SLAVE_SCL_LOW_EN, 0);
394 1.1 rjs }
395 1.1 rjs
396 1.1 rjs static void
397 1.1 rjs mesoni2c_set_clock_div_gxbb_axg(struct mesoni2c_softc *sc)
398 1.1 rjs {
399 1.1 rjs u_int rate = clk_get_rate(sc->sc_clk);
400 1.1 rjs u_int divh, divl;
401 1.1 rjs
402 1.1 rjs /*
403 1.1 rjs * According to I2C-BUS Spec 2.1, in FAST-MODE, the minimum
404 1.1 rjs * LOW period is 1.3uS, and minimum HIGH is least 0.6us.
405 1.1 rjs * For
406 1.1 rjs * 400000 freq, the period is 2.5us. To keep within the specs,
407 1.1 rjs * give 40% of period to HIGH and 60% to LOW. This means HIGH
408 1.1 rjs * at 1.0us and LOW 1.5us.
409 1.1 rjs * The same applies for Fast-mode plus, where LOW is 0.5us and
410 1.1 rjs * HIGH is 0.26us.
411 1.1 rjs * Duty = H/(H + L) = 2/5
412 1.1 rjs */
413 1.1 rjs if (sc->sc_clkfreq <= 100000) {
414 1.1 rjs divh = howmany(rate, sc->sc_clkfreq);
415 1.1 rjs divl = howmany(divh, 4);
416 1.1 rjs divh = howmany(divh, 2) - FILTER_DELAY;
417 1.1 rjs } else {
418 1.1 rjs divh = howmany(rate * 2, sc->sc_clkfreq * 5) - FILTER_DELAY;
419 1.1 rjs divl = howmany(rate * 3, sc->sc_clkfreq * 5 * 2);
420 1.1 rjs }
421 1.1 rjs
422 1.1 rjs /* Set prescaler */
423 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_CTRL_REG, MESONI2C_CTRL_CLKDIV_MASK, (divh & __BITS(9, 0)) << MESONI2C_CTRL_CLKDIV_SHIFT);
424 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_CTRL_REG, MESONI2C_CTRL_CLKDIVEXT_MASK, (divh >> 10) << MESONI2C_CTRL_CLKDIVEXT_SHIFT);
425 1.1 rjs
426 1.1 rjs /* Set SCL low delay */
427 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_SLAVE_ADDR_REG, MESONI2C_SLAVE_SCL_LOW_MASK, divl << MESONI2C_SLAVE_SCL_LOW_SHIFT);
428 1.1 rjs
429 1.1 rjs /* Enable HIGH/LOW mode */
430 1.1 rjs mesoni2c_set_mask(sc, MESONI2C_SLAVE_ADDR_REG, MESONI2C_SLAVE_SCL_LOW_EN, MESONI2C_SLAVE_SCL_LOW_EN);
431 1.1 rjs }
432 1.1 rjs
433 1.1 rjs static int
434 1.1 rjs mesoni2c_match(device_t parent, cfdata_t cf, void *aux)
435 1.1 rjs {
436 1.1 rjs struct fdt_attach_args * const faa = aux;
437 1.1 rjs
438 1.1 rjs return of_compatible_match(faa->faa_phandle, compat_data);
439 1.1 rjs }
440 1.1 rjs
441 1.1 rjs static void
442 1.1 rjs mesoni2c_attach(device_t parent, device_t self, void *aux)
443 1.1 rjs {
444 1.1 rjs struct mesoni2c_softc * const sc = device_private(self);
445 1.1 rjs struct fdt_attach_args * const faa = aux;
446 1.1 rjs const int phandle = faa->faa_phandle;
447 1.1 rjs bus_addr_t addr;
448 1.1 rjs bus_size_t size;
449 1.1 rjs char intrstr[128];
450 1.1 rjs
451 1.1 rjs if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
452 1.1 rjs aprint_error_dev(self, "couldn't get registers\n");
453 1.1 rjs return;
454 1.1 rjs }
455 1.1 rjs
456 1.1 rjs sc->sc_clk = fdtbus_clock_get_index(phandle, 0);
457 1.2 skrll
458 1.1 rjs if (sc->sc_clk == NULL || clk_enable(sc->sc_clk) != 0) {
459 1.1 rjs aprint_error_dev(self, "couldn't enable clock\n");
460 1.1 rjs return;
461 1.1 rjs }
462 1.1 rjs
463 1.1 rjs sc->sc_dev = self;
464 1.1 rjs sc->sc_bst = faa->faa_bst;
465 1.1 rjs
466 1.1 rjs if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
467 1.1 rjs aprint_error_dev(self, "couldn't map registers\n");
468 1.1 rjs return;
469 1.1 rjs }
470 1.1 rjs
471 1.1 rjs fdtbus_clock_assign(phandle);
472 1.1 rjs
473 1.1 rjs if (of_getprop_uint32(phandle, "clock-frequency", &sc->sc_clkfreq)) {
474 1.1 rjs sc->sc_clkfreq = 100000;
475 1.1 rjs } else {
476 1.1 rjs if (sc->sc_clkfreq < 100000) {
477 1.1 rjs sc->sc_clkfreq = 100000;
478 1.1 rjs } else if (sc->sc_clkfreq > 400000) {
479 1.1 rjs sc->sc_clkfreq = 400000;
480 1.1 rjs }
481 1.1 rjs }
482 1.1 rjs
483 1.1 rjs aprint_naive("\n");
484 1.1 rjs aprint_normal(": Meson I2C (%u Hz)\n", sc->sc_clkfreq);
485 1.1 rjs
486 1.1 rjs enum mesoni2c_type type = of_compatible_lookup(phandle, compat_data)->value;
487 1.2 skrll
488 1.1 rjs switch (type) {
489 1.1 rjs case TYPE_MESON6:
490 1.1 rjs mesoni2c_set_clock_div_meson6(sc);
491 1.1 rjs break;
492 1.1 rjs
493 1.1 rjs case TYPE_GXBB:
494 1.1 rjs case TYPE_AXG:
495 1.1 rjs mesoni2c_set_clock_div_gxbb_axg(sc);
496 1.1 rjs break;
497 1.1 rjs }
498 1.1 rjs
499 1.1 rjs mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM);
500 1.1 rjs cv_init(&sc->sc_cv, "mesoniic");
501 1.1 rjs
502 1.1 rjs if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
503 1.1 rjs aprint_error_dev(self, "failed to decode interrupt\n");
504 1.1 rjs return;
505 1.1 rjs }
506 1.1 rjs
507 1.1 rjs sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_VM, 0,
508 1.1 rjs mesoni2c_intr, sc, device_xname(self));
509 1.1 rjs
510 1.1 rjs if (sc->sc_ih == NULL) {
511 1.1 rjs aprint_error_dev(self, "couldn't establish interrupt\n");
512 1.1 rjs return;
513 1.1 rjs }
514 1.1 rjs
515 1.1 rjs aprint_normal_dev(self, "interrupting on %s\n", intrstr);
516 1.1 rjs
517 1.1 rjs iic_tag_init(&sc->sc_ic);
518 1.1 rjs sc->sc_ic.ic_cookie = sc;
519 1.1 rjs sc->sc_ic.ic_exec = mesoni2c_exec;
520 1.1 rjs
521 1.4 thorpej iicbus_attach(self, &sc->sc_ic);
522 1.1 rjs }
523