xref: /illumos-gate/usr/src/uts/common/io/i2c/sensor/tmp43x/tmp43x.c (revision 2042f022d202609e92f891e343803ac28419cace)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2025 Oxide Computer Company
14  */
15 
16 /*
17  * TI TMP401, TMP411, TMP431, TMP432, and TMP435 driver.
18  *
19  * This driver supports a variety of TI TMP4xx devices that have relatively
20  * similar programming semantics and register layouts. They all share one
21  * critical piece, that the various devices can be identified by a combination
22  * of the manufacturer and device id registers in 0xfe and 0xff respectively.
23  *
24  * The temperature data is stored as a 12-bit unsigned value that is offset from
25  * one of two modes depending on the device temperature range and measure in
26  * units of 0.0625 C. The temperature registers are split between a high and a
27  * low byte. The hardware allows you to either perform a two byte read of the
28  * high byte to get a coherent read or otherwise it will latch the low byte on
29  * the read of a high byte. The temperature data comes in two forms, a standard
30  * form in the range 0 to 127 C. However, the extended range operates from -55
31  * to 150 C. The main difference is that in extended mode, there is a -64 C
32  * offset applied to the read value.
33  *
34  * We use our normal register interface to take care of the 2-byte endian reads.
35  * The rest use a normal SMBus register interface. Like other devices, this
36  * hardware has a shutdown mode that we will take the device out of if we find
37  * it in it.
38  *
39  * Here are the major differences between device generations:
40  *
41  * DEV     LOCAL  REMOTE  NFACTOR   BETA    MIN/MAX  LRES
42  * TMP401  1      1       No        No      No       YES
43  * TMP411  1      1       Yes       No      Yes      YES
44  * TMP431  1      1       Yes       Yes     No       No
45  * TMP432  1      2       Yes       Yes     No       No
46  * TMP435  1      1       Yes       Yes     No       No
47  *
48  * These devices have evolved a bit over time. The TMP401 does not have n-factor
49  * correction or beta compensation support. n-factor supported was added in the
50  * TMP411 devices and BETA compensation TMP43x devices. The TMP401 and TMP411
51  * have a programmable resolution for the local measurement. TMP411 is the only
52  * device with a maximum and minimum register values. Those are not plumbed
53  * through in the driver right now.
54  *
55  * These devices also support programmable alert thresholds, which are not
56  * exposed in the sensor framework today.
57  */
58 
59 #include <sys/modctl.h>
60 #include <sys/conf.h>
61 #include <sys/devops.h>
62 #include <sys/ddi.h>
63 #include <sys/sunddi.h>
64 #include <sys/bitext.h>
65 #include <sys/debug.h>
66 #include <sys/sysmacros.h>
67 #include <sys/i2c/client.h>
68 #include <sys/sensors.h>
69 
70 
71 /*
72  * The device registers across these families are a bit of a mess. Some
73  * registers, but not all have different addresses for read and for write. These
74  * are all in slightly different places. All devices support a manufacturer and
75  * device ID in the same spot here. We use logical registers to identify things
76  * here and then use device-specific information to know how to dispatch it.
77  * Only a subset of the registers that we use are listed here. While we don't
78  * use them today, the registers related to device-tree based configuration, the
79  * n-factor and beta compensation are also included here. They are only
80  * supported by the TMP43x devices.
81  */
82 typedef enum {
83 	TMP43X_R_TEMP_LOCAL	= 0,
84 	TMP43X_R_TEMP_REM1,
85 	TMP43X_R_TEMP_REM2,
86 	TMP43X_R_CFG1,
87 	TMP43X_R_NFACTOR1,
88 	TMP43X_R_NFACTOR2,
89 	TMP43X_R_BETA1,
90 	TMP43X_R_BETA2,
91 	TMP43X_R_RES
92 } tmp43x_reg_t;
93 
94 #define	TMP43X_NSESNORS	3
95 
96 typedef enum {
97 	TMP43X_REG_TYPE_TEMP,
98 	TMP43X_REG_TYPE_1B
99 } tmp43x_reg_type_t;
100 
101 typedef struct tmp43x_reg_info {
102 	tmp43x_reg_t tri_reg;
103 	bool tri_ro;
104 	uint8_t tri_read;
105 	uint8_t tri_write;
106 } tmp43x_reg_info_t;
107 
108 static const tmp43x_reg_info_t tmp43x_regs_401[] = {
109 	{ TMP43X_R_TEMP_LOCAL, true, 0x0, 0x0 },
110 	{ TMP43X_R_TEMP_REM1, true, 0x1, 0x1 },
111 	{ TMP43X_R_CFG1, false, 0x3, 0x9 },
112 	{ TMP43X_R_RES, false, 0x1a, 0x1a }
113 };
114 
115 static const tmp43x_reg_info_t tmp43x_regs_411[] = {
116 	{ TMP43X_R_TEMP_LOCAL, true, 0x0, 0x0 },
117 	{ TMP43X_R_TEMP_REM1, true, 0x1, 0x1 },
118 	{ TMP43X_R_CFG1, false, 0x3, 0x9 },
119 	{ TMP43X_R_RES, false, 0x1a, 0x1a },
120 	{ TMP43X_R_NFACTOR1, false, 0x18, 0x18 }
121 };
122 
123 static const tmp43x_reg_info_t tmp43x_regs_431_435[] = {
124 	{ TMP43X_R_TEMP_LOCAL, true, 0x0, 0x0 },
125 	{ TMP43X_R_TEMP_REM1, true, 0x1, 0x1 },
126 	{ TMP43X_R_CFG1, false, 0x3, 0x9 },
127 	{ TMP43X_R_NFACTOR1, false, 0x18, 0x18 },
128 	{ TMP43X_R_BETA1, false, 0x25, 0x25 },
129 };
130 
131 static const tmp43x_reg_info_t tmp43x_regs_432[] = {
132 	{ TMP43X_R_TEMP_LOCAL, true, 0x0, 0x0 },
133 	{ TMP43X_R_TEMP_REM1, true, 0x1, 0x1 },
134 	{ TMP43X_R_TEMP_REM2, true, 0x23, 0x23 },
135 	{ TMP43X_R_CFG1, false, 0x3, 0x9 },
136 	{ TMP43X_R_NFACTOR1, false, 0x27, 0x27 },
137 	{ TMP43X_R_NFACTOR2, false, 0x28, 0x28 },
138 	{ TMP43X_R_BETA1, false, 0x25, 0x25 },
139 	{ TMP43X_R_BETA2, false, 0x26, 0x26 },
140 };
141 
142 /*
143  * Fixed location registers that each device doesn't have to define. These
144  * define the vendor and device IDs.
145  */
146 #define	TMP43X_R_MFGID	0xfe
147 #define	TMP43X_MFG_TI	0x55
148 #define	TMP43X_R_DEVID	0xff
149 
150 typedef enum {
151 	TMP43X_DEV_401	= 0x11,
152 	/* The 411E/411DE use the same code */
153 	TMP43X_DEV_411A	= 0x12,
154 	TMP43X_DEV_411B	= 0x13,
155 	TMP43X_DEV_411C	= 0x10,
156 	TMP43X_DEV_431	= 0x31,
157 	TMP43X_DEV_432	= 0x32,
158 	TMP43X_DEV_435	= 0x35
159 } tmp43x_dev_t;
160 
161 /*
162  * The temperature is a 12 bit value in temp[15, 4]. The granularity is 16 as we
163  * have 4 bits of data here.
164  */
165 #define	TMP43X_TEMP_GRAN	16
166 #define	TMP43X_TEMP_GET_VAL(r)	bitx16(r, 15, 4)
167 #define	TMP43X_TEMP_EXTD_ADJ	(-65 * TMP43X_TEMP_GRAN)
168 #define	TMP43X_TEMP_PREC	(TMP43X_TEMP_GRAN * 1)
169 
170 /*
171  * Common configuration register bits.
172  */
173 #define	TMP43X_CFG1_GET_SD(r)		bitx8(r, 6, 6)
174 #define	TMP43X_CFG1_SET_SD(r, v)	bitset8(r, 6, 6, v)
175 #define	TMP43X_CFG1_SD_RUN	0
176 #define	TMP43X_CFG1_SD_STOP	1
177 #define	TMP43X_CFG1_GET_RANGE(r)	bitx8(r, 2, 2)
178 #define	TMP43X_CFG1_RANGE_STD	0
179 #define	TMP43X_CFG1_RANGE_EXT	1
180 
181 /*
182  * Resolution register.
183  */
184 #define	TMP43X_RES_SET_RES(r, v)	bitset8(r, 1, 0, v)
185 #define	TMP43X_RES_RES_9B	0
186 #define	TMP43X_RES_RES_10B	1
187 #define	TMP43X_RES_RES_11B	2
188 #define	TMP43X_RES_RES_12B	3
189 
190 /*
191  * BETA register controls.
192  */
193 #define	TMP43X_BETA_GET_RANGE(r)	bitx8(r, 3, 0)
194 #define	TMP43X_BETA_SET_RANGE(r, v)	bitset8(r, 3, 0, v)
195 
196 /*
197  * Flags used to indicate which device-specific behaviors needs to be set.
198  */
199 typedef enum {
200 	TMP43X_F_NFACTOR	= 1 << 0,
201 	TMP43X_F_BETA		= 1 << 1,
202 	TMP43X_F_LRES		= 1 << 2,
203 	TMP43X_F_MINMAX		= 1 << 3,
204 	TMP43X_F_REM2		= 1 << 4,
205 	/*
206 	 * This is a run-time flag to indicate if extended measurements are in
207 	 * effect.
208 	 */
209 	TMP43X_F_EXT_TEMP	= 1 << 5
210 } tmp43x_flags_t;
211 
212 typedef struct tmp43x {
213 	dev_info_t *tmp_dip;
214 	i2c_client_t *tmp_client;
215 	i2c_reg_hdl_t *tmp_regs;
216 	tmp43x_dev_t tmp_dev;
217 	tmp43x_flags_t tmp_flags;
218 	uint8_t tmp_nrem;
219 	const tmp43x_reg_info_t *tmp_rinfo;
220 	size_t tmp_nrinfo;
221 	id_t tmp_ksensor[TMP43X_NSESNORS];
222 	kmutex_t tmp_mutex;
223 	uint16_t tmp_raw[TMP43X_NSESNORS];
224 	int64_t tmp_temp[TMP43X_NSESNORS];
225 } tmp43x_t;
226 
227 static tmp43x_reg_type_t
tmp43x_reg_type(tmp43x_reg_t reg)228 tmp43x_reg_type(tmp43x_reg_t reg)
229 {
230 	switch (reg) {
231 	case TMP43X_R_TEMP_LOCAL:
232 	case TMP43X_R_TEMP_REM1:
233 	case TMP43X_R_TEMP_REM2:
234 		return (TMP43X_REG_TYPE_TEMP);
235 	case TMP43X_R_CFG1:
236 	case TMP43X_R_NFACTOR1:
237 	case TMP43X_R_NFACTOR2:
238 	case TMP43X_R_BETA1:
239 	case TMP43X_R_BETA2:
240 	case TMP43X_R_RES:
241 		return (TMP43X_REG_TYPE_1B);
242 	default:
243 		panic("tmp43x programmer error: unknown register 0x%x", reg);
244 	}
245 }
246 
247 static bool
tmp43x_write_ctl(tmp43x_t * tmp,tmp43x_reg_t reg,uint8_t val)248 tmp43x_write_ctl(tmp43x_t *tmp, tmp43x_reg_t reg, uint8_t val)
249 {
250 	const tmp43x_reg_info_t *info = NULL;
251 	i2c_error_t err;
252 
253 	for (size_t i = 0; i < tmp->tmp_nrinfo; i++) {
254 		if (tmp->tmp_rinfo[i].tri_reg == reg) {
255 			info = &tmp->tmp_rinfo[i];
256 			break;
257 		}
258 	}
259 
260 	VERIFY3P(info, !=, NULL);
261 	VERIFY3B(info->tri_ro, ==, false);
262 	VERIFY3U(tmp43x_reg_type(reg), ==, TMP43X_REG_TYPE_1B);
263 
264 	if (!smbus_client_write_u8(NULL, tmp->tmp_client, info->tri_write, val,
265 	    &err)) {
266 		dev_err(tmp->tmp_dip, CE_WARN, "!failed to write register "
267 		    "0x%x: 0x%x/0x%x", info->tri_read, err.i2c_error,
268 		    err.i2c_ctrl);
269 		return (false);
270 	}
271 
272 	return (true);
273 }
274 
275 static bool
tmp43x_read_ctl(tmp43x_t * tmp,tmp43x_reg_t reg,uint8_t * valp)276 tmp43x_read_ctl(tmp43x_t *tmp, tmp43x_reg_t reg, uint8_t *valp)
277 {
278 	const tmp43x_reg_info_t *info = NULL;
279 	i2c_error_t err;
280 
281 	for (size_t i = 0; i < tmp->tmp_nrinfo; i++) {
282 		if (tmp->tmp_rinfo[i].tri_reg == reg) {
283 			info = &tmp->tmp_rinfo[i];
284 			break;
285 		}
286 	}
287 
288 	VERIFY3P(info, !=, NULL);
289 	VERIFY3U(tmp43x_reg_type(reg), ==, TMP43X_REG_TYPE_1B);
290 
291 	if (!smbus_client_read_u8(NULL, tmp->tmp_client, info->tri_read, valp,
292 	    &err)) {
293 		dev_err(tmp->tmp_dip, CE_WARN, "!failed to read register 0x%x: "
294 		    "0x%x/0x%x", info->tri_read, err.i2c_error, err.i2c_ctrl);
295 		return (false);
296 	}
297 
298 	return (true);
299 }
300 
301 static int
tmp43x_temp_read(tmp43x_t * tmp,tmp43x_reg_t reg,sensor_ioctl_scalar_t * scalar)302 tmp43x_temp_read(tmp43x_t *tmp, tmp43x_reg_t reg, sensor_ioctl_scalar_t *scalar)
303 {
304 	const tmp43x_reg_info_t *info = NULL;
305 	i2c_error_t err;
306 	uint16_t val;
307 
308 	for (size_t i = 0; i < tmp->tmp_nrinfo; i++) {
309 		if (tmp->tmp_rinfo[i].tri_reg == reg) {
310 			info = &tmp->tmp_rinfo[i];
311 			break;
312 		}
313 	}
314 
315 	VERIFY3P(info, !=, NULL);
316 	VERIFY3U(tmp43x_reg_type(reg), ==, TMP43X_REG_TYPE_TEMP);
317 
318 	mutex_enter(&tmp->tmp_mutex);
319 	if (!i2c_reg_get(NULL, tmp->tmp_regs, info->tri_read, &val,
320 	    sizeof (val), &err)) {
321 		dev_err(tmp->tmp_dip, CE_WARN, "!failed to read temperature "
322 		    "register 0x%x: 0x%x/0x%x", info->tri_read, err.i2c_error,
323 		    err.i2c_ctrl);
324 		mutex_exit(&tmp->tmp_mutex);
325 		return (EIO);
326 	}
327 
328 	tmp->tmp_raw[reg] = val;
329 	int64_t temp = TMP43X_TEMP_GET_VAL(val);
330 	if ((tmp->tmp_flags & TMP43X_F_EXT_TEMP) != 0) {
331 		temp += TMP43X_TEMP_EXTD_ADJ;
332 	}
333 	tmp->tmp_temp[reg] = temp;
334 
335 	scalar->sis_value = temp;
336 	scalar->sis_gran = TMP43X_TEMP_GRAN;
337 	scalar->sis_prec = TMP43X_TEMP_PREC;
338 	scalar->sis_unit = SENSOR_UNIT_CELSIUS;
339 	mutex_exit(&tmp->tmp_mutex);
340 
341 	return (0);
342 }
343 
344 static int
tmp43x_temp_read_local(void * arg,sensor_ioctl_scalar_t * scalar)345 tmp43x_temp_read_local(void *arg, sensor_ioctl_scalar_t *scalar)
346 {
347 	tmp43x_t *tmp = arg;
348 
349 	return (tmp43x_temp_read(tmp, TMP43X_R_TEMP_LOCAL, scalar));
350 }
351 
352 static int
tmp43x_temp_read_rem1(void * arg,sensor_ioctl_scalar_t * scalar)353 tmp43x_temp_read_rem1(void *arg, sensor_ioctl_scalar_t *scalar)
354 {
355 	tmp43x_t *tmp = arg;
356 
357 	return (tmp43x_temp_read(tmp, TMP43X_R_TEMP_REM1, scalar));
358 }
359 
360 static int
tmp43x_temp_read_rem2(void * arg,sensor_ioctl_scalar_t * scalar)361 tmp43x_temp_read_rem2(void *arg, sensor_ioctl_scalar_t *scalar)
362 {
363 	tmp43x_t *tmp = arg;
364 
365 	return (tmp43x_temp_read(tmp, TMP43X_R_TEMP_REM2, scalar));
366 }
367 
368 static const ksensor_ops_t tmp43x_local_temp_ops = {
369 	.kso_kind = ksensor_kind_temperature,
370 	.kso_scalar = tmp43x_temp_read_local
371 };
372 
373 static const ksensor_ops_t tmp43x_rem1_temp_ops = {
374 	.kso_kind = ksensor_kind_temperature,
375 	.kso_scalar = tmp43x_temp_read_rem1
376 };
377 
378 static const ksensor_ops_t tmp43x_rem2_temp_ops = {
379 	.kso_kind = ksensor_kind_temperature,
380 	.kso_scalar = tmp43x_temp_read_rem2
381 };
382 
383 
384 static const i2c_reg_acc_attr_t tmp43x_reg_attr = {
385 	.i2cacc_version = I2C_REG_ACC_ATTR_V0,
386 	.i2cacc_addr_len = 1,
387 	.i2cacc_reg_len = 2,
388 	.i2cacc_reg_endian = DDI_STRUCTURE_BE_ACC,
389 	.i2cacc_addr_max = UINT8_MAX
390 };
391 
392 static bool
tmp43x_i2c_init(tmp43x_t * tmp)393 tmp43x_i2c_init(tmp43x_t *tmp)
394 {
395 	i2c_errno_t err;
396 
397 	if ((err = i2c_client_init(tmp->tmp_dip, 0, &tmp->tmp_client)) !=
398 	    I2C_CORE_E_OK) {
399 		dev_err(tmp->tmp_dip, CE_WARN, "failed to create i2c client: "
400 		    "0x%x", err);
401 		return (false);
402 	}
403 
404 	if ((err = i2c_reg_handle_init(tmp->tmp_client, &tmp43x_reg_attr,
405 	    &tmp->tmp_regs)) != I2C_CORE_E_OK) {
406 		dev_err(tmp->tmp_dip, CE_WARN, "failed to create register "
407 		    "handle: %s (0x%x)", i2c_client_errtostr(tmp->tmp_client,
408 		    err), err);
409 		return (false);
410 	}
411 
412 	return (true);
413 }
414 
415 static bool
tmp43x_ident(tmp43x_t * tmp)416 tmp43x_ident(tmp43x_t *tmp)
417 {
418 	uint8_t val;
419 	i2c_error_t err;
420 
421 	if (!smbus_client_read_u8(NULL, tmp->tmp_client, TMP43X_R_MFGID, &val,
422 	    &err)) {
423 		dev_err(tmp->tmp_dip, CE_WARN, "!failed to read mfg register: "
424 		    "0x%x/0x%x", err.i2c_error, err.i2c_ctrl);
425 		return (false);
426 	}
427 
428 	if (val != TMP43X_MFG_TI) {
429 		dev_err(tmp->tmp_dip, CE_WARN, "encountered unsupported vendor "
430 		    "id: 0x%x", val);
431 		return (false);
432 	}
433 
434 	if (!smbus_client_read_u8(NULL, tmp->tmp_client, TMP43X_R_DEVID, &val,
435 	    &err)) {
436 		dev_err(tmp->tmp_dip, CE_WARN, "!failed to read device "
437 		    "id register: 0x%x/0x%x", err.i2c_error, err.i2c_ctrl);
438 		return (false);
439 	}
440 
441 	switch (val) {
442 	case TMP43X_DEV_401:
443 		tmp->tmp_flags = TMP43X_F_LRES;
444 		tmp->tmp_rinfo = tmp43x_regs_401;
445 		tmp->tmp_nrinfo = ARRAY_SIZE(tmp43x_regs_401);
446 		break;
447 	case TMP43X_DEV_411A:
448 	case TMP43X_DEV_411B:
449 	case TMP43X_DEV_411C:
450 		tmp->tmp_flags = TMP43X_F_LRES | TMP43X_F_MINMAX |
451 		    TMP43X_F_NFACTOR;
452 		tmp->tmp_rinfo = tmp43x_regs_411;
453 		tmp->tmp_nrinfo = ARRAY_SIZE(tmp43x_regs_411);
454 		break;
455 	case TMP43X_DEV_431:
456 	case TMP43X_DEV_435:
457 		tmp->tmp_flags = TMP43X_F_NFACTOR | TMP43X_F_BETA;
458 		tmp->tmp_rinfo = tmp43x_regs_431_435;
459 		tmp->tmp_nrinfo = ARRAY_SIZE(tmp43x_regs_431_435);
460 		break;
461 	case TMP43X_DEV_432:
462 		tmp->tmp_flags = TMP43X_F_NFACTOR | TMP43X_F_BETA |
463 		    TMP43X_F_REM2;
464 		tmp->tmp_rinfo = tmp43x_regs_432;
465 		tmp->tmp_nrinfo = ARRAY_SIZE(tmp43x_regs_432);
466 		break;
467 	default:
468 		dev_err(tmp->tmp_dip, CE_WARN, "encountered unsupported device "
469 		    "id: 0x%x", val);
470 		return (false);
471 	}
472 
473 	tmp->tmp_dev = val;
474 	return (true);
475 }
476 
477 /*
478  * Start the device by determining the following:
479  *
480  *  - Which range has been configured on the device.
481  *  - Taking the device out of a shutdown state if its in it.
482  *  - Changing the local resolution for relevant devices.
483  */
484 static bool
tmp43x_start(tmp43x_t * tmp)485 tmp43x_start(tmp43x_t *tmp)
486 {
487 	uint8_t cfg1;
488 
489 	if (!tmp43x_read_ctl(tmp, TMP43X_R_CFG1, &cfg1)) {
490 		return (false);
491 	}
492 
493 	if (TMP43X_CFG1_GET_RANGE(cfg1) == TMP43X_CFG1_RANGE_EXT) {
494 		tmp->tmp_flags |= TMP43X_F_EXT_TEMP;
495 	}
496 
497 	if (TMP43X_CFG1_GET_SD(cfg1) == TMP43X_CFG1_SD_STOP) {
498 		cfg1 = TMP43X_CFG1_SET_SD(cfg1, TMP43X_CFG1_SD_RUN);
499 		if (!tmp43x_write_ctl(tmp, TMP43X_R_CFG1, cfg1)) {
500 			return (false);
501 		}
502 	}
503 
504 	/*
505 	 * Attempt to set the local resolution on hardware that requires it. We
506 	 * always set the device to 12-bit resolution for consistency. On the
507 	 * newer TMP411 parts it is the same cost regardless. On older TMP401 /
508 	 * TMP411 this is a bit more expensive. If this becomes a problem we can
509 	 * add a device property to stop it from occurring.
510 	 */
511 	if ((tmp->tmp_flags & TMP43X_F_LRES) != 0) {
512 		uint8_t res, nres;
513 
514 		if (!tmp43x_read_ctl(tmp, TMP43X_R_RES, &res)) {
515 			return (false);
516 		}
517 
518 		nres = TMP43X_RES_SET_RES(res, TMP43X_RES_RES_12B);
519 		if (res != nres && !tmp43x_write_ctl(tmp, TMP43X_R_RES, nres)) {
520 			return (false);
521 		}
522 	}
523 
524 	return (true);
525 }
526 
527 static bool
tmp43x_ksensor_init(tmp43x_t * tmp)528 tmp43x_ksensor_init(tmp43x_t *tmp)
529 {
530 	int ret;
531 
532 	if ((ret = i2c_client_ksensor_create_scalar(tmp->tmp_client,
533 	    SENSOR_KIND_TEMPERATURE, &tmp43x_local_temp_ops, tmp, "local",
534 	    &tmp->tmp_ksensor[0])) != 0) {
535 		dev_err(tmp->tmp_dip, CE_WARN, "failed to create ksensor: %d",
536 		    ret);
537 		return (false);
538 	}
539 
540 	if ((ret = i2c_client_ksensor_create_scalar(tmp->tmp_client,
541 	    SENSOR_KIND_TEMPERATURE, &tmp43x_rem1_temp_ops, tmp, "remote1",
542 	    &tmp->tmp_ksensor[1])) != 0) {
543 		dev_err(tmp->tmp_dip, CE_WARN, "failed to create ksensor: %d",
544 		    ret);
545 		return (false);
546 	}
547 
548 	if ((tmp->tmp_flags & TMP43X_F_REM2) == 0)
549 		return (true);
550 
551 	if ((ret = i2c_client_ksensor_create_scalar(tmp->tmp_client,
552 	    SENSOR_KIND_TEMPERATURE, &tmp43x_rem2_temp_ops, tmp, "remote2",
553 	    &tmp->tmp_ksensor[2])) != 0) {
554 		dev_err(tmp->tmp_dip, CE_WARN, "failed to create ksensor: %d",
555 		    ret);
556 		return (false);
557 	}
558 	return (true);
559 }
560 
561 static void
tmp43x_cleanup(tmp43x_t * tmp)562 tmp43x_cleanup(tmp43x_t *tmp)
563 {
564 	(void) ksensor_remove(tmp->tmp_dip, KSENSOR_ALL_IDS);
565 	i2c_reg_handle_destroy(tmp->tmp_regs);
566 	i2c_client_destroy(tmp->tmp_client);
567 	mutex_destroy(&tmp->tmp_mutex);
568 	ddi_set_driver_private(tmp->tmp_dip, NULL);
569 	tmp->tmp_dip = NULL;
570 	kmem_free(tmp, sizeof (tmp43x_t));
571 }
572 
573 static int
tmp43x_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)574 tmp43x_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
575 {
576 	tmp43x_t *tmp;
577 
578 	switch (cmd) {
579 	case DDI_ATTACH:
580 		break;
581 	case DDI_RESUME:
582 		return (DDI_SUCCESS);
583 	default:
584 		return (DDI_FAILURE);
585 	}
586 
587 	tmp = kmem_zalloc(sizeof (tmp43x_t), KM_SLEEP);
588 	tmp->tmp_dip = dip;
589 	ddi_set_driver_private(dip, tmp);
590 	mutex_init(&tmp->tmp_mutex, NULL, MUTEX_DRIVER, NULL);
591 
592 	if (!tmp43x_i2c_init(tmp))
593 		goto cleanup;
594 
595 	if (!tmp43x_ident(tmp))
596 		goto cleanup;
597 
598 	if (!tmp43x_start(tmp))
599 		goto cleanup;
600 
601 	if (!tmp43x_ksensor_init(tmp))
602 		goto cleanup;
603 
604 	return (DDI_SUCCESS);
605 
606 cleanup:
607 	tmp43x_cleanup(tmp);
608 	return (DDI_FAILURE);
609 }
610 
611 static int
tmp43x_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)612 tmp43x_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
613 {
614 	tmp43x_t *tmp;
615 
616 	switch (cmd) {
617 	case DDI_DETACH:
618 		break;
619 	case DDI_SUSPEND:
620 		return (DDI_SUCCESS);
621 	default:
622 		return (DDI_FAILURE);
623 	}
624 
625 	tmp = ddi_get_driver_private(dip);
626 	if (tmp == NULL) {
627 		dev_err(dip, CE_WARN, "asked to detach, but missing private "
628 		    "data");
629 		return (DDI_FAILURE);
630 	}
631 	VERIFY3P(tmp->tmp_dip, ==, dip);
632 
633 	tmp43x_cleanup(tmp);
634 	return (DDI_SUCCESS);
635 }
636 
637 static struct dev_ops tmp43x_dev_ops = {
638 	.devo_rev = DEVO_REV,
639 	.devo_refcnt = 0,
640 	.devo_identify = nulldev,
641 	.devo_probe = nulldev,
642 	.devo_attach = tmp43x_attach,
643 	.devo_detach = tmp43x_detach,
644 	.devo_reset = nodev,
645 	.devo_quiesce = ddi_quiesce_not_needed
646 };
647 
648 static struct modldrv tmp43x_modldrv = {
649 	.drv_modops = &mod_driverops,
650 	.drv_linkinfo = "TMP43X driver",
651 	.drv_dev_ops = &tmp43x_dev_ops
652 };
653 
654 static struct modlinkage tmp43x_modlinkage = {
655 	.ml_rev = MODREV_1,
656 	.ml_linkage = { &tmp43x_modldrv, NULL }
657 };
658 
659 int
_init(void)660 _init(void)
661 {
662 	return (mod_install(&tmp43x_modlinkage));
663 }
664 
665 int
_info(struct modinfo * modinfop)666 _info(struct modinfo *modinfop)
667 {
668 	return (mod_info(&tmp43x_modlinkage, modinfop));
669 }
670 
671 int
_fini(void)672 _fini(void)
673 {
674 	return (mod_remove(&tmp43x_modlinkage));
675 }
676