FreeBSD kernel IICBUS device code
max44009.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) Andriy Gapon
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include "opt_platform.h"
33
34#include <sys/param.h>
35#include <sys/bus.h>
36#include <sys/kernel.h>
37#include <sys/module.h>
38#include <sys/sysctl.h>
39#include <sys/systm.h>
40
41#include <machine/bus.h>
42
43#include <dev/iicbus/iicbus.h>
44#include <dev/iicbus/iiconf.h>
45
46#ifdef FDT
47#include <dev/ofw/ofw_bus.h>
48#include <dev/ofw/ofw_bus_subr.h>
49#endif
50
51/*
52 * Driver for MAX44009 Ambient Light Sensor with ADC.
53 */
54#define REG_LUX_HIGH 0x03
55#define REG_LUX_LOW 0x04
56
58 device_t sc_dev;
59 uint8_t sc_addr;
60};
61
62#ifdef FDT
63static const struct ofw_compat_data compat_data[] = {
64 { "maxim,max44009", true },
65 { NULL, false },
66};
67#endif
68
69static int
70max44009_get_reading(device_t dev, u_int *reading)
71{
72 struct iic_msg msgs[4];
73 struct max44009_softc *sc;
74 u_int val;
75 uint8_t reghi, reglo, valhi, vallo;
76 int error;
77
78 sc = device_get_softc(dev);
79
80 reghi = REG_LUX_HIGH;
81 reglo = REG_LUX_LOW;
82 msgs[0].slave = sc->sc_addr;
84 msgs[0].len = 1;
85 msgs[0].buf = &reghi;
86 msgs[1].slave = sc->sc_addr;
88 msgs[1].len = 1;
89 msgs[1].buf = &valhi;
90 msgs[2].slave = sc->sc_addr;
92 msgs[2].len = 1;
93 msgs[2].buf = &reglo;
94 msgs[3].slave = sc->sc_addr;
95 msgs[3].flags = IIC_M_RD;
96 msgs[3].len = 1;
97 msgs[3].buf = &vallo;
98
99 error = iicbus_transfer_excl(dev, msgs, nitems(msgs), IIC_INTRWAIT);
100 if (error != 0)
101 return (error);
102
103 val = ((valhi & 0x0f) << 4) | (vallo & 0x0f);
104 val <<= (valhi & 0xf0) >> 4;
105 val = val * 72 / 100;
106 *reading = val;
107 return (0);
108}
109
110static int
111max44009_lux_sysctl(SYSCTL_HANDLER_ARGS)
112{
113 device_t dev;
114 u_int reading;
115 int error, val;
116
117 if (req->oldptr != NULL) {
118 dev = arg1;
119 error = max44009_get_reading(dev, &reading);
120 if (error != 0)
121 return (EIO);
122 val = reading;
123 }
124 error = sysctl_handle_int(oidp, &val, 0, req);
125 return (error);
126}
127
128static int
130{
131 int rc;
132
133#ifdef FDT
134 if (!ofw_bus_status_okay(dev))
135 return (ENXIO);
136 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
137 rc = BUS_PROBE_GENERIC;
138 else
139#endif
140 rc = BUS_PROBE_NOWILDCARD;
141 device_set_desc(dev, "MAX44009 light intensity sensor");
142 return (rc);
143}
144
145static int
147{
148 struct max44009_softc *sc;
149 struct sysctl_ctx_list *ctx;
150 struct sysctl_oid *tree_node;
151 struct sysctl_oid_list *tree;
152
153 sc = device_get_softc(dev);
154 sc->sc_dev = dev;
155 sc->sc_addr = iicbus_get_addr(dev);
156
157 ctx = device_get_sysctl_ctx(dev);
158 tree_node = device_get_sysctl_tree(dev);
159 tree = SYSCTL_CHILDREN(tree_node);
160
161 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "illuminance",
162 CTLTYPE_INT | CTLFLAG_RD, dev, 0,
163 max44009_lux_sysctl, "I", "Light intensity, lux");
164 return (0);
165}
166
167static int
169{
170 return (0);
171}
172
173static device_method_t max44009_methods[] = {
174 /* Device interface */
175 DEVMETHOD(device_probe, max44009_probe),
176 DEVMETHOD(device_attach, max44009_attach),
177 DEVMETHOD(device_detach, max44009_detach),
178
179 DEVMETHOD_END
180};
181
182static driver_t max44009_driver = {
183 "max44009",
185 sizeof(struct max44009_softc)
186};
187
188static devclass_t max44009_devclass;
189
192MODULE_VERSION(max44009, 1);
#define IIC_M_WR
Definition: ad7418.c:45
static ds13_compat_data compat_data[]
Definition: ds13rtc.c:187
#define IIC_M_RD
Definition: iic.h:42
#define IIC_M_NOSTOP
Definition: iic.h:43
int val
Definition: iicbb_if.m:83
struct iic_msg * msgs
Definition: iicbus_if.m:134
INTERFACE iicbus
Definition: iicbus_if.m:32
int iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs, int how)
Definition: iiconf.c:449
#define IICBUS_MINVER
Definition: iiconf.h:171
#define IIC_INTRWAIT
Definition: iiconf.h:48
#define IICBUS_MAXVER
Definition: iiconf.h:172
#define IICBUS_PREFVER
Definition: iiconf.h:173
MODULE_VERSION(max44009, 1)
MODULE_DEPEND(max44009, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER)
static int max44009_get_reading(device_t dev, u_int *reading)
Definition: max44009.c:70
static int max44009_attach(device_t dev)
Definition: max44009.c:146
static device_method_t max44009_methods[]
Definition: max44009.c:173
static devclass_t max44009_devclass
Definition: max44009.c:188
static int max44009_detach(device_t dev)
Definition: max44009.c:168
__FBSDID("$FreeBSD$")
#define REG_LUX_LOW
Definition: max44009.c:55
IICBUS_FDT_PNP_INFO(compat_data)
static int max44009_probe(device_t dev)
Definition: max44009.c:129
static driver_t max44009_driver
Definition: max44009.c:182
#define REG_LUX_HIGH
Definition: max44009.c:54
DRIVER_MODULE(max44009, iicbus, max44009_driver, max44009_devclass, 0, 0)
static int max44009_lux_sysctl(SYSCTL_HANDLER_ARGS)
Definition: max44009.c:111
device_t dev
Definition: ofw_iicbus_if.m:38
Definition: iic.h:38
uint16_t slave
Definition: iic.h:39
uint16_t len
Definition: iic.h:45
uint8_t * buf
Definition: iic.h:46
uint16_t flags
Definition: iic.h:40
device_t sc_dev
Definition: max44009.c:58
uint8_t sc_addr
Definition: max44009.c:59