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