Home | History | Annotate | Line # | Download | only in ic
pca9564.c revision 1.5
      1 /*	$NetBSD: pca9564.c,v 1.5 2021/08/07 16:19:12 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2010 NONAKA Kimihiro <nonaka (at) netbsd.org>
      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 THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: pca9564.c,v 1.5 2021/08/07 16:19:12 thorpej Exp $");
     30 
     31 #include <sys/param.h>
     32 #include <sys/device.h>
     33 #include <sys/mutex.h>
     34 #include <sys/bus.h>
     35 
     36 #include <dev/i2c/i2cvar.h>
     37 
     38 #include <dev/ic/pca9564reg.h>
     39 #include <dev/ic/pca9564var.h>
     40 
     41 #if defined(PCA9564_DEBUG)
     42 int pca9564debug = 0;
     43 #define	DPRINTF(s)	if (pca9564debug) printf s
     44 #else
     45 #define	DPRINTF(s)
     46 #endif
     47 
     48 static int pca9564_acquire_bus(void *, int);
     49 static void pca9564_release_bus(void *, int);
     50 
     51 static int pca9564_send_start(void *, int);
     52 static int pca9564_send_stop(void *, int);
     53 static int pca9564_initiate_xfer(void *, uint16_t, int);
     54 static int pca9564_read_byte(void *, uint8_t *, int);
     55 static int pca9564_write_byte(void *, uint8_t, int);
     56 
     57 static int pca9564_ack(void *, bool, int);
     58 
     59 #define	CSR_READ(sc, r)		(*sc->sc_ios.read_byte)(sc->sc_dev, r)
     60 #define	CSR_WRITE(sc, r, v)	(*sc->sc_ios.write_byte)(sc->sc_dev, r, v)
     61 
     62 void
     63 pca9564_attach(struct pca9564_softc *sc)
     64 {
     65 	struct i2cbus_attach_args iba;
     66 
     67 	aprint_naive("\n");
     68 	aprint_normal(": PCA9564 I2C Controller\n");
     69 
     70 	iic_tag_init(&sc->sc_i2c);
     71 	sc->sc_i2c.ic_cookie = sc;
     72 	sc->sc_i2c.ic_acquire_bus = pca9564_acquire_bus;
     73 	sc->sc_i2c.ic_release_bus = pca9564_release_bus;
     74 	sc->sc_i2c.ic_send_start = pca9564_send_start;
     75 	sc->sc_i2c.ic_send_stop = pca9564_send_stop;
     76 	sc->sc_i2c.ic_initiate_xfer = pca9564_initiate_xfer;
     77 	sc->sc_i2c.ic_read_byte = pca9564_read_byte;
     78 	sc->sc_i2c.ic_write_byte = pca9564_write_byte;
     79 
     80 	/* set serial clock rate */
     81 	switch (sc->sc_i2c_clock) {
     82 	case 330000:	/* 330kHz */
     83 		sc->sc_i2c_clock = I2CCON_CR_330KHZ;
     84 		break;
     85 	case 288000:	/* 288kHz */
     86 		sc->sc_i2c_clock = I2CCON_CR_288KHZ;
     87 		break;
     88 	case 217000:	/* 217kHz */
     89 		sc->sc_i2c_clock = I2CCON_CR_217KHZ;
     90 		break;
     91 	case 146000:	/* 146kHz */
     92 		sc->sc_i2c_clock = I2CCON_CR_146KHZ;
     93 		break;
     94 	case 88000:	/* 88kHz */
     95 		sc->sc_i2c_clock = I2CCON_CR_88KHZ;
     96 		break;
     97 	case 0:		/* default */
     98 	case 59000:	/* 59kHz */
     99 		sc->sc_i2c_clock = I2CCON_CR_59KHZ;
    100 		break;
    101 	case 44000:	/* 44kHz */
    102 		sc->sc_i2c_clock = I2CCON_CR_44KHZ;
    103 		break;
    104 	case 36000:	/* 36kHz */
    105 		sc->sc_i2c_clock = I2CCON_CR_36KHZ;
    106 		break;
    107 	default:
    108 		aprint_error_dev(sc->sc_dev, "unknown i2c clock %dHz\n",
    109 		    sc->sc_i2c_clock);
    110 		sc->sc_i2c_clock = I2CCON_CR_59KHZ;
    111 		break;
    112 	}
    113 
    114 	memset(&iba, 0, sizeof(iba));
    115 	iba.iba_tag = &sc->sc_i2c;
    116 	config_found(sc->sc_dev, &iba, iicbus_print, CFARGS_NONE);
    117 }
    118 
    119 static int
    120 pca9564_acquire_bus(void *cookie, int flags)
    121 {
    122 	struct pca9564_softc *sc = cookie;
    123 	uint8_t control;
    124 
    125 	/* Enable SIO and set clock */
    126 	control = CSR_READ(sc, PCA9564_I2CCON);
    127 	control |= I2CCON_ENSIO;
    128 	control &= ~(I2CCON_STA|I2CCON_STO|I2CCON_SI|I2CCON_AA);
    129 	control &= ~I2CCON_CR_MASK;
    130 	control |= sc->sc_i2c_clock;
    131 	CSR_WRITE(sc, PCA9564_I2CCON, control);
    132 	delay(500);
    133 
    134 	return 0;
    135 }
    136 
    137 static void
    138 pca9564_release_bus(void *cookie, int flags)
    139 {
    140 	struct pca9564_softc *sc = cookie;
    141 	uint8_t control;
    142 
    143 	/* Disable SIO */
    144 	control = CSR_READ(sc, PCA9564_I2CCON);
    145 	control &= ~I2CCON_ENSIO;
    146 	CSR_WRITE(sc, PCA9564_I2CCON, control);
    147 }
    148 
    149 #define	PCA9564_TIMEOUT		100	/* protocol timeout, in uSecs */
    150 
    151 static int
    152 pca9564_wait(struct pca9564_softc *sc, int flags)
    153 {
    154 	int timeout;
    155 
    156 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    157 	for (timeout = PCA9564_TIMEOUT; timeout > 0; timeout--) {
    158 		if (CSR_READ(sc, PCA9564_I2CCON) & I2CCON_SI)
    159 			break;
    160 		delay(1);
    161 	}
    162 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    163 	if (timeout == 0) {
    164 		aprint_error_dev(sc->sc_dev, "timeout\n");
    165 		return ETIMEDOUT;
    166 	}
    167 	return 0;
    168 }
    169 
    170 static int
    171 pca9564_send_start(void *cookie, int flags)
    172 {
    173 	struct pca9564_softc *sc = cookie;
    174 	uint8_t control;
    175 
    176 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    177 	control = CSR_READ(sc, PCA9564_I2CCON);
    178 	control |= I2CCON_STA;
    179 	control &= ~(I2CCON_STO|I2CCON_SI);
    180 	CSR_WRITE(sc, PCA9564_I2CCON, control);
    181 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    182 
    183 	return pca9564_wait(sc, flags);
    184 }
    185 
    186 static int
    187 pca9564_send_stop(void *cookie, int flags)
    188 {
    189 	struct pca9564_softc *sc = cookie;
    190 	uint8_t control;
    191 
    192 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    193 	control = CSR_READ(sc, PCA9564_I2CCON);
    194 	control |= I2CCON_STO;
    195 	control &= ~(I2CCON_STA|I2CCON_SI);
    196 	CSR_WRITE(sc, PCA9564_I2CCON, control);
    197 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    198 
    199 	return 0;
    200 }
    201 
    202 static int
    203 pca9564_initiate_xfer(void *cookie, uint16_t addr, int flags)
    204 {
    205 	struct pca9564_softc *sc = cookie;
    206 	int error, rd_req = (flags & I2C_F_READ) != 0;
    207 	uint8_t data, control;
    208 
    209 	error = pca9564_send_start(sc, flags);
    210 	if (error) {
    211 		aprint_error_dev(sc->sc_dev, "failed to send start %s xfer\n",
    212 		    rd_req ? "read" : "write");
    213 		return error;
    214 	}
    215 
    216 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    217 	control = CSR_READ(sc, PCA9564_I2CCON);
    218 
    219 	data = (addr << 1) | (rd_req ? 1 : 0);
    220 	CSR_WRITE(sc, PCA9564_I2CDAT, data);
    221 
    222 	control &= ~(I2CCON_STO|I2CCON_STA|I2CCON_SI);
    223 	CSR_WRITE(sc, PCA9564_I2CCON, control);
    224 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    225 
    226 	error = pca9564_wait(sc, flags);
    227 	if (error)
    228 		aprint_error_dev(sc->sc_dev, "failed to initiate %s xfer\n",
    229 		    rd_req ? "read" : "write");
    230 	return error;
    231 }
    232 
    233 static int
    234 pca9564_read_byte(void *cookie, uint8_t *bytep, int flags)
    235 {
    236 	struct pca9564_softc *sc = cookie;
    237 	int send_stop = (flags & I2C_F_STOP) != 0;
    238 	int error;
    239 
    240 	error = pca9564_ack(sc, !send_stop, flags);
    241 	if (error) {
    242 		aprint_error_dev(sc->sc_dev, "failed to ack\n");
    243 		return error;
    244 	}
    245 
    246 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    247 	*bytep = CSR_READ(sc, PCA9564_I2CDAT);
    248 	DPRINTF(("%s: status=%#x, byte=%#x\n", __func__,
    249 	    CSR_READ(sc, PCA9564_I2CSTA), *bytep));
    250 
    251 	if (send_stop)
    252 		pca9564_send_stop(sc, flags);
    253 
    254 	return 0;
    255 }
    256 
    257 static int
    258 pca9564_write_byte(void *cookie, uint8_t byte, int flags)
    259 {
    260 	struct pca9564_softc *sc = cookie;
    261 	int send_stop = (flags & I2C_F_STOP) != 0;
    262 	int error;
    263 	uint8_t control;
    264 
    265 	DPRINTF(("%s: status=%#x, byte=%#x\n", __func__,
    266 	    CSR_READ(sc, PCA9564_I2CSTA), byte));
    267 	control = CSR_READ(sc, PCA9564_I2CCON);
    268 
    269 	CSR_WRITE(sc, PCA9564_I2CDAT, byte);
    270 
    271 	control &= ~(I2CCON_STO|I2CCON_STA|I2CCON_SI);
    272 	CSR_WRITE(sc, PCA9564_I2CCON, control);
    273 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    274 
    275 	error = pca9564_wait(sc, flags);
    276 	if (error)
    277 		aprint_error_dev(sc->sc_dev, "write byte failed\n");
    278 
    279 	if (send_stop)
    280 		pca9564_send_stop(sc, flags);
    281 
    282 	return error;
    283 }
    284 
    285 static int
    286 pca9564_ack(void *cookie, bool ack, int flags)
    287 {
    288 	struct pca9564_softc *sc = cookie;
    289 	uint8_t control;
    290 
    291 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    292 	control = CSR_READ(sc, PCA9564_I2CCON);
    293 	control &= ~(I2CCON_STO|I2CCON_STA|I2CCON_SI|I2CCON_AA);
    294 	if (ack)
    295 		control |= I2CCON_AA;
    296 	CSR_WRITE(sc, PCA9564_I2CCON, control);
    297 	DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
    298 
    299 	return pca9564_wait(sc, flags);
    300 }
    301