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