xref: /netbsd-src/sys/dev/i2c/lm_i2c.c (revision 77c8c4e6710b7b5cba3f6a8d733c76c3b5f9809b)
1*77c8c4e6Smlelstv /*	$NetBSD: lm_i2c.c,v 1.7 2021/06/13 09:48:44 mlelstv Exp $	*/
2eacec974Spgoyette 
3eacec974Spgoyette /*-
4eacec974Spgoyette  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5eacec974Spgoyette  * All rights reserved.
6eacec974Spgoyette  *
7eacec974Spgoyette  * This code is derived from software contributed to The NetBSD Foundation
8eacec974Spgoyette  * by Bill Squier.
9eacec974Spgoyette  *
10eacec974Spgoyette  * Redistribution and use in source and binary forms, with or without
11eacec974Spgoyette  * modification, are permitted provided that the following conditions
12eacec974Spgoyette  * are met:
13eacec974Spgoyette  * 1. Redistributions of source code must retain the above copyright
14eacec974Spgoyette  *    notice, this list of conditions and the following disclaimer.
15eacec974Spgoyette  * 2. Redistributions in binary form must reproduce the above copyright
16eacec974Spgoyette  *    notice, this list of conditions and the following disclaimer in the
17eacec974Spgoyette  *    documentation and/or other materials provided with the distribution.
18eacec974Spgoyette  *
19eacec974Spgoyette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20eacec974Spgoyette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21eacec974Spgoyette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22eacec974Spgoyette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23eacec974Spgoyette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24eacec974Spgoyette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25eacec974Spgoyette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26eacec974Spgoyette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27eacec974Spgoyette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28eacec974Spgoyette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29eacec974Spgoyette  * POSSIBILITY OF SUCH DAMAGE.
30eacec974Spgoyette  */
31eacec974Spgoyette 
32eacec974Spgoyette #include <sys/cdefs.h>
33*77c8c4e6Smlelstv __KERNEL_RCSID(0, "$NetBSD: lm_i2c.c,v 1.7 2021/06/13 09:48:44 mlelstv Exp $");
34eacec974Spgoyette 
35eacec974Spgoyette #include <sys/param.h>
36eacec974Spgoyette #include <sys/systm.h>
37eacec974Spgoyette #include <sys/kernel.h>
38eacec974Spgoyette #include <sys/device.h>
39eacec974Spgoyette #include <sys/conf.h>
40f1e1c62dSjdolecek #include <sys/kmem.h>
41eacec974Spgoyette 
42eacec974Spgoyette #include <dev/i2c/i2cvar.h>
43eacec974Spgoyette 
44eacec974Spgoyette #include <dev/sysmon/sysmonvar.h>
45eacec974Spgoyette 
46eacec974Spgoyette #include <dev/ic/nslm7xvar.h>
47eacec974Spgoyette 
48eacec974Spgoyette int 	lm_i2c_match(device_t, cfdata_t, void *);
49eacec974Spgoyette void 	lm_i2c_attach(device_t, device_t, void *);
50eacec974Spgoyette int 	lm_i2c_detach(device_t, int);
51eacec974Spgoyette 
52eacec974Spgoyette uint8_t lm_i2c_readreg(struct lm_softc *, int);
533ad4b272Smsaitoh void 	lm_i2c_writereg(struct lm_softc *, int, uint8_t);
54eacec974Spgoyette 
55eacec974Spgoyette struct lm_i2c_softc {
56eacec974Spgoyette 	struct lm_softc sc_lmsc;
57eacec974Spgoyette 	i2c_tag_t sc_tag;
58eacec974Spgoyette 	i2c_addr_t sc_addr;
59eacec974Spgoyette };
60eacec974Spgoyette 
61eacec974Spgoyette CFATTACH_DECL_NEW(lm_iic, sizeof(struct lm_i2c_softc),
62eacec974Spgoyette     lm_i2c_match, lm_i2c_attach, lm_i2c_detach, NULL);
63eacec974Spgoyette 
64eacec974Spgoyette int
lm_i2c_match(device_t parent,cfdata_t match,void * aux)65eacec974Spgoyette lm_i2c_match(device_t parent, cfdata_t match, void *aux)
66eacec974Spgoyette {
67eacec974Spgoyette 	struct i2c_attach_args *ia = aux;
68eacec974Spgoyette 	int rv = 0;
69f1e1c62dSjdolecek 	struct lm_i2c_softc *sc;
70eacec974Spgoyette 
71eacec974Spgoyette 	/* Must supply an address */
72eacec974Spgoyette 	if (ia->ia_addr < 1)
73eacec974Spgoyette 		return 0;
74eacec974Spgoyette 
75aa41e992Sthorpej 	/* XXXJRT filter addresses //at all// please? */
76aa41e992Sthorpej 
77eacec974Spgoyette 	/* Bus independent probe */
78f1e1c62dSjdolecek 	sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
79f1e1c62dSjdolecek 	sc->sc_lmsc.lm_writereg = lm_i2c_writereg;
80f1e1c62dSjdolecek 	sc->sc_lmsc.lm_readreg = lm_i2c_readreg;
81f1e1c62dSjdolecek 	sc->sc_tag = ia->ia_tag;
82f1e1c62dSjdolecek 	sc->sc_addr = ia->ia_addr;
83f1e1c62dSjdolecek 	rv = lm_match(&sc->sc_lmsc);
84f1e1c62dSjdolecek 	kmem_free(sc, sizeof(*sc));
85eacec974Spgoyette 
86aa41e992Sthorpej 	return rv ? I2C_MATCH_ADDRESS_AND_PROBE : 0;
87eacec974Spgoyette }
88eacec974Spgoyette 
89eacec974Spgoyette 
90eacec974Spgoyette void
lm_i2c_attach(device_t parent,device_t self,void * aux)91eacec974Spgoyette lm_i2c_attach(device_t parent, device_t self, void *aux)
92eacec974Spgoyette {
93eacec974Spgoyette 	struct lm_i2c_softc *sc = device_private(self);
94eacec974Spgoyette 	struct i2c_attach_args *ia = aux;
95eacec974Spgoyette 
96eacec974Spgoyette 	sc->sc_tag = ia->ia_tag;
97eacec974Spgoyette 	sc->sc_addr = ia->ia_addr;
98eacec974Spgoyette 
99eacec974Spgoyette 	/* Bus-independent attachment */
100eacec974Spgoyette 	sc->sc_lmsc.sc_dev = self;
101eacec974Spgoyette 	sc->sc_lmsc.lm_writereg = lm_i2c_writereg;
102eacec974Spgoyette 	sc->sc_lmsc.lm_readreg = lm_i2c_readreg;
103eacec974Spgoyette 
104eacec974Spgoyette 	lm_attach(&sc->sc_lmsc);
105eacec974Spgoyette }
106eacec974Spgoyette 
107eacec974Spgoyette int
lm_i2c_detach(device_t self,int flags)108eacec974Spgoyette lm_i2c_detach(device_t self, int flags)
109eacec974Spgoyette {
110eacec974Spgoyette 	struct lm_i2c_softc *sc = device_private(self);
111eacec974Spgoyette 
112eacec974Spgoyette 	lm_detach(&sc->sc_lmsc);
113eacec974Spgoyette 	return 0;
114eacec974Spgoyette }
115eacec974Spgoyette 
116eacec974Spgoyette uint8_t
lm_i2c_readreg(struct lm_softc * lmsc,int reg)117eacec974Spgoyette lm_i2c_readreg(struct lm_softc *lmsc, int reg)
118eacec974Spgoyette {
119eacec974Spgoyette 	struct lm_i2c_softc *sc = (struct lm_i2c_softc *)lmsc;
120eacec974Spgoyette 	uint8_t cmd, data;
121eacec974Spgoyette 
122*77c8c4e6Smlelstv 	if (iic_acquire_bus(sc->sc_tag, 0))
123*77c8c4e6Smlelstv 		return 0;
124eacec974Spgoyette 
125eacec974Spgoyette 	cmd = reg;
126eacec974Spgoyette 	iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
127eacec974Spgoyette 		 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0);
128eacec974Spgoyette 
129eacec974Spgoyette 	iic_release_bus(sc->sc_tag, 0);
130eacec974Spgoyette 
131eacec974Spgoyette 	return data;
132eacec974Spgoyette }
133eacec974Spgoyette 
134eacec974Spgoyette 
135eacec974Spgoyette void
lm_i2c_writereg(struct lm_softc * lmsc,int reg,uint8_t val)1363ad4b272Smsaitoh lm_i2c_writereg(struct lm_softc *lmsc, int reg, uint8_t val)
137eacec974Spgoyette {
138eacec974Spgoyette 	struct lm_i2c_softc *sc = (struct lm_i2c_softc *)lmsc;
139eacec974Spgoyette 	uint8_t cmd, data;
140eacec974Spgoyette 
141*77c8c4e6Smlelstv 	if (iic_acquire_bus(sc->sc_tag, 0))
142*77c8c4e6Smlelstv 		return;
143eacec974Spgoyette 
144eacec974Spgoyette 	cmd = reg;
145eacec974Spgoyette 	data = val;
146eacec974Spgoyette 	iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
147eacec974Spgoyette 		 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0);
148eacec974Spgoyette 
149eacec974Spgoyette 	iic_release_bus(sc->sc_tag, 0);
150eacec974Spgoyette }
151