xref: /titanic_51/usr/src/uts/sun4u/montecarlo/io/pcf8591_nct.c (revision 3d5869cc80c26887ee2c78b0f35e58f574e97192)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * I2C leaf driver for the PCF8591
28  */
29 
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/signal.h>
33 #include <sys/errno.h>
34 #include <sys/file.h>
35 #include <sys/termio.h>
36 #include <sys/termios.h>
37 #include <sys/cmn_err.h>
38 #include <sys/stream.h>
39 #include <sys/strsun.h>
40 #include <sys/stropts.h>
41 #include <sys/strtty.h>
42 #include <sys/debug.h>
43 #include <sys/eucioctl.h>
44 #include <sys/cred.h>
45 #include <sys/uio.h>
46 #include <sys/stat.h>
47 #include <sys/kmem.h>
48 
49 #include <sys/ddi.h>
50 #include <sys/sunddi.h>
51 #include <sys/obpdefs.h>
52 #include <sys/conf.h>
53 #include <sys/modctl.h>
54 #include <sys/stat.h>
55 #include <sys/open.h>
56 #include <sys/uio.h>
57 
58 #include <sys/i2c/misc/i2c_svc.h>
59 #include <sys/envctrl_gen.h>
60 #include <sys/netract_gen.h>
61 #include <sys/pcf8591_nct.h>
62 
63 
64 /*
65  * 		CONTROL OF CHIP
66  * PCF8591 Temp sensing control register definitions
67  *
68  * ---------------------------------------------
69  * | 0 | AOE | X | X | 0 | AIF | X | X |
70  * ---------------------------------------------
71  * AOE = Analog out enable.. not used on out implementation
72  * 5 & 4 = Analog Input Programming.. see data sheet for bits..
73  *
74  * AIF = Auto increment flag
75  * bits 1 & 0 are for the Chennel number.
76  */
77 
78 
79 #define	I2CTRANS_DATA	0
80 #define	I2CRAW_DATA	1
81 #define	TEMP_TABLE_SIZE	256
82 
83 #define	SHUTDOWN_TEMP_MIN	55
84 #define	SHUTDOWN_TEMP_MAX	85
85 
86 #ifdef DEBUG
87 #define	dbg_print(level, str) cmn_err(level, str);
88 #else
89 #define	dbg_print(level, str) {; }
90 #endif
91 
92 
93 extern int nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran);
94 static uchar_t _cpu_temps[TEMP_TABLE_SIZE + 4];	/* see attach */
95 
96 static void *pcf8591_soft_statep;
97 
98 /*
99  * cb ops (only need ioctl)
100  */
101 static int pcf8591_open(dev_t *, int, int, cred_t *);
102 static int pcf8591_close(dev_t, int, int, cred_t *);
103 static int pcf8591_read(dev_t dev, struct uio *uiop, cred_t *cred_p);
104 static int pcf8591_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
105 
106 static struct cb_ops pcf8591_cbops = {
107 	pcf8591_open,			/* open */
108 	pcf8591_close,			/* close */
109 	nodev,				/* strategy */
110 	nodev,				/* print */
111 	nodev,				/* dump */
112 	pcf8591_read,			/* read */
113 	nodev,				/* write */
114 	pcf8591_ioctl,			/* ioctl */
115 	nodev,				/* devmap */
116 	nodev,				/* mmap */
117 	nodev,				/* segmap */
118 	nochpoll,			/* poll */
119 	ddi_prop_op,			/* cb_prop_op */
120 	NULL,				/* streamtab */
121 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
122 	CB_REV,				/* rev */
123 	nodev,				/* int (*cb_aread)() */
124 	nodev				/* int (*cb_awrite)() */
125 };
126 
127 /*
128  * dev ops
129  */
130 static int pcf8591_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
131 		void **result);
132 static int pcf8591_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
133 static int pcf8591_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
134 
135 /* kstat routines */
136 static int pcf8591_add_kstats(struct pcf8591_unit *);
137 static void pcf8591_delete_kstats(struct pcf8591_unit *);
138 static int pcf8591_temp_kstat_update(kstat_t *, int);
139 static int pcf8591_read_chip(struct pcf8591_unit *, uint8_t, int);
140 static int pcf8591_read_props(struct pcf8591_unit *unitp);
141 
142 static struct dev_ops pcf8591_ops = {
143 	DEVO_REV,
144 	0,
145 	pcf8591_info,
146 	nulldev,
147 	nulldev,
148 	pcf8591_attach,
149 	pcf8591_detach,
150 	nodev,
151 	&pcf8591_cbops,
152 	NULL,
153 	NULL,
154 	ddi_quiesce_not_supported,	/* devo_quiesce */
155 };
156 
157 extern struct mod_ops mod_driverops;
158 
159 static struct modldrv pcf8591_modldrv = {
160 	&mod_driverops,		/* type of module - driver */
161 	"Netract pcf8591 (adio)",
162 	&pcf8591_ops,
163 };
164 
165 static struct modlinkage pcf8591_modlinkage = {
166 	MODREV_1,
167 	&pcf8591_modldrv,
168 	0
169 };
170 
171 char	_depends_on[] = "misc/i2c_svc";
172 
173 int	pcf8591_debug = 0x02;
174 static uint8_t translate_cputemp(uint8_t value);
175 
176 int
177 _init(void)
178 {
179 	register int    error;
180 
181 	error = mod_install(&pcf8591_modlinkage);
182 	if (error == 0) {
183 		(void) ddi_soft_state_init(&pcf8591_soft_statep,
184 		    sizeof (struct pcf8591_unit), PCF8591_MAX_DEVS);
185 	}
186 
187 	return (error);
188 }
189 
190 int
191 _fini(void)
192 {
193 	register int    error;
194 
195 	error = mod_remove(&pcf8591_modlinkage);
196 	if (error == 0) {
197 		ddi_soft_state_fini(&pcf8591_soft_statep);
198 	}
199 
200 	return (error);
201 }
202 
203 int
204 _info(struct modinfo *modinfop)
205 {
206 	return (mod_info(&pcf8591_modlinkage, modinfop));
207 }
208 
209 /*ARGSUSED*/
210 static int
211 pcf8591_open(dev_t *devp, int flags, int otyp, cred_t *credp)
212 {
213 	int err = 0;
214 	struct pcf8591_unit *unitp;
215 	minor_t minor = getminor(*devp);
216 
217 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
218 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
219 
220 	if (instance < 0) {
221 		return (ENXIO);
222 	}
223 
224 	unitp = (struct pcf8591_unit *)
225 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
226 
227 	if (unitp == NULL) {
228 		return (ENXIO);
229 	}
230 
231 	if (otyp != OTYP_CHR) {
232 		return (EINVAL);
233 	}
234 
235 	mutex_enter(&unitp->umutex);
236 
237 	if (flags & FEXCL) {
238 		if (unitp->pcf8591_oflag[channel] != 0) {
239 			err = EBUSY;
240 		} else {
241 			unitp->pcf8591_oflag[channel] = FEXCL;
242 		}
243 	} else {
244 		if (unitp->pcf8591_oflag[channel] == FEXCL) {
245 			err = EBUSY;
246 		} else {
247 			unitp->pcf8591_oflag[channel] = FOPEN;
248 		}
249 	}
250 
251 	mutex_exit(&unitp->umutex);
252 
253 	return (err);
254 }
255 
256 /*ARGSUSED*/
257 static int
258 pcf8591_close(dev_t devp, int flags, int otyp, cred_t *credp)
259 {
260 	struct pcf8591_unit *unitp;
261 	minor_t minor = getminor(devp);
262 
263 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
264 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
265 
266 #ifdef lint
267 	flags = flags;
268 	otyp = otyp;
269 #endif
270 
271 	if (instance < 0) {
272 		return (ENXIO);
273 	}
274 
275 	unitp = (struct pcf8591_unit *)
276 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
277 
278 	if (unitp == NULL) {
279 		return (ENXIO);
280 	}
281 
282 	mutex_enter(&unitp->umutex);
283 
284 	unitp->pcf8591_oflag[channel] = 0;
285 
286 	mutex_exit(&unitp->umutex);
287 
288 	return (DDI_SUCCESS);
289 }
290 
291 static int
292 pcf8591_io(dev_t dev, struct uio *uiop, int rw)
293 {
294 	int err = 0;
295 	struct pcf8591_unit *unitp;
296 	minor_t minor = getminor(dev);
297 
298 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
299 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
300 
301 	int		bytes_to_rw;
302 	int		translate = 0;
303 
304 	/*
305 	 * At this point we don't have a write operation to pcf8591.
306 	 */
307 	if (rw == B_WRITE) {
308 		return (EACCES);
309 	}
310 
311 	if (instance < 0) {
312 		return (ENXIO);
313 	}
314 
315 	unitp = (struct pcf8591_unit *)
316 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
317 	if (unitp == NULL) {
318 		return (ENXIO);
319 	}
320 
321 	if ((bytes_to_rw = uiop->uio_resid) > PCF8591_TRAN_SIZE) {
322 		return (EINVAL);
323 	}
324 
325 	/*
326 	 * Need to serialize all read operations, since there is a single
327 	 * i2c_transfer_t structure allocated for all read and write ops.
328 	 * We can't share the i2c bus among multiple transactions anyway,
329 	 * so this does not affect performance.
330 	 */
331 	mutex_enter(&unitp->umutex);
332 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
333 		if (cv_wait_sig(&unitp->pcf8591_cv, &unitp->umutex) <= 0) {
334 			mutex_exit(&unitp->umutex);
335 
336 			return (EINTR);
337 		}
338 	}
339 	unitp->pcf8591_flags = PCF8591_BUSY;
340 	mutex_exit(&unitp->umutex);
341 
342 	if (bytes_to_rw == 1)
343 		translate = 1;
344 	/*
345 	 * Event sequence:
346 	 * 1. set up the control register write, for now we'll always read
347 	 *    channel 0, which is the only active 8591 port on the Nordica
348 	 *    TODO: We'll need a minor node for each port that is used.
349 	 * 2. increment read count to read the throw-away byte
350 	 * 3. start the write/read of control/data registers
351 	 * 4. throw the first byte away
352 	 * 5. then return the data
353 	 */
354 
355 	unitp->i2c_tran->i2c_flags = I2C_WR_RD;
356 	unitp->i2c_tran->i2c_wlen = 1;
357 	unitp->i2c_tran->i2c_wbuf[0] = (unitp->pcf8591_inprog |
358 	    channel);
359 	/*
360 	 * read extra byte to throw away the first, (PCF8591 datasheet)
361 	 */
362 	unitp->i2c_tran->i2c_rlen = bytes_to_rw + 1;
363 
364 	if (nct_i2c_transfer(unitp->pcf8591_hdl,
365 	    unitp->i2c_tran) != I2C_SUCCESS) {
366 		err = EIO;
367 	} else {
368 		/*
369 		 * Throw away the first byte according to PCF8591 datasheet
370 		 * If translating, use the second byte.
371 		 */
372 		if (translate) {
373 			unitp->i2c_tran->i2c_rbuf[0] =
374 			    translate_cputemp(unitp->i2c_tran->i2c_rbuf[1]);
375 		} else {
376 			unitp->i2c_tran->i2c_rbuf[0] =
377 			    unitp->i2c_tran->i2c_rbuf[1];
378 			unitp->i2c_tran->i2c_rbuf[1] = 0;
379 		}
380 
381 		err = uiomove(unitp->i2c_tran->i2c_rbuf,
382 		    bytes_to_rw,
383 		    UIO_READ,
384 		    uiop);
385 	}
386 	mutex_enter(&unitp->umutex);
387 	unitp->pcf8591_flags = 0;
388 	cv_signal(&unitp->pcf8591_cv);
389 	mutex_exit(&unitp->umutex);
390 
391 	return (err);
392 }
393 
394 /*ARGSUSED*/
395 static int
396 pcf8591_read(dev_t dev, struct uio *uiop, cred_t *cred_p)
397 {
398 	return (pcf8591_io(dev, uiop, B_READ));
399 }
400 
401 static int
402 call_copyin(caddr_t arg, struct pcf8591_unit *unitp, int mode)
403 {
404 	uchar_t *wbuf;
405 	uchar_t *rbuf;
406 	i2c_transfer_t i2ct;
407 	i2c_transfer_t *i2ctp = unitp->i2c_tran;
408 
409 
410 	if (ddi_copyin((void *)arg, (caddr_t)&i2ct,
411 	    sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) {
412 		return (I2C_FAILURE);
413 	}
414 
415 	/*
416 	 * Save the read and write buffer pointers in the transfer
417 	 * structure, otherwise these will get overwritten when we
418 	 * do a bcopy. Restore once done.
419 	 */
420 
421 	wbuf = i2ctp->i2c_wbuf;
422 	rbuf = i2ctp->i2c_rbuf;
423 
424 	bcopy(&i2ct, i2ctp, sizeof (i2c_transfer_t));
425 
426 	i2ctp->i2c_wbuf = wbuf;
427 	i2ctp->i2c_rbuf = rbuf;
428 
429 	/*
430 	 * copyin the read and write buffers to the saved buffers.
431 	 */
432 
433 	if (i2ct.i2c_wlen != 0) {
434 		if (ddi_copyin(i2ct.i2c_wbuf, (caddr_t)i2ctp->i2c_wbuf,
435 		    i2ct.i2c_wlen, mode) != DDI_SUCCESS) {
436 				return (I2C_FAILURE);
437 			}
438 		}
439 
440 	return (I2C_SUCCESS);
441 }
442 
443 static int
444 call_copyout(caddr_t arg, struct pcf8591_unit *unitp, int mode)
445 {
446 	i2c_transfer_t i2ct;
447 	i2c_transfer_t *i2ctp = unitp->i2c_tran;
448 	uint16_t  i2c_actlen;
449 
450 	/*
451 	 * We will copyout the last three fields only, skipping
452 	 * the remaining ones, before copying the rbuf to the
453 	 * user buffer.
454 	 */
455 
456 	int uskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t),
457 	    kskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t);
458 
459 	/*
460 	 * First copyin the user structure to the temporary i2ct,
461 	 * so that we have the wbuf and rbuf addresses in it.
462 	 */
463 
464 	uskip = sizeof (i2c_transfer_t) - 3 * (sizeof (uint16_t));
465 
466 	/*
467 	 * copyout the last three out fields now.
468 	 */
469 
470 	if (ddi_copyout((void *)((intptr_t)i2ctp+kskip), (void *)
471 	    ((intptr_t)arg + uskip), 3*sizeof (uint16_t), mode)
472 	    != DDI_SUCCESS) {
473 		return (I2C_FAILURE);
474 		}
475 
476 	/*
477 	 * In case we have something to write, get the address of the read
478 	 * buffer.
479 	 */
480 
481 	if (i2ctp->i2c_rlen - i2ctp->i2c_r_resid > 0) {
482 
483 	if (ddi_copyin((void *)arg, &i2ct,
484 	    sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) {
485 		return (I2C_FAILURE);
486 	}
487 
488 	/*
489 	 * copyout the read buffer to the saved user buffer in i2ct.
490 	 */
491 
492 		i2c_actlen = i2ctp->i2c_rlen - i2ctp->i2c_r_resid;
493 		if (ddi_copyout(i2ctp->i2c_rbuf, i2ct.i2c_rbuf,
494 		    i2c_actlen, mode) != DDI_SUCCESS) {
495 				return (I2C_FAILURE);
496 			}
497 		}
498 
499 	return (I2C_SUCCESS);
500 }
501 
502 /*
503  * The ioctls will use the same name as the Javelin ioctls. We
504  * will have a very restricted set for MC, and unlike Javelin
505  * will not have a envctrl_chip structure to return values
506  * from the driver. All we will have is a uint8_t value to
507  * get or set values from the driver. Also, unlike the Javelin,
508  * where 'index' is used to specify the input port from where
509  * temperature is collected, here different minor nodes will be
510  * created by the driver for each port, eliminating the need for
511  * 'index' - leaving us with only the value to pass.
512  */
513 
514 /*ARGSUSED*/
515 static int
516 pcf8591_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
517 		cred_t *credp, int *rvalp)
518 {
519 	int err = 0;
520 	struct pcf8591_unit *unitp;
521 	minor_t minor = getminor(dev);
522 
523 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
524 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
525 
526 	unitp = (struct pcf8591_unit *)
527 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
528 
529 	mutex_enter(&unitp->umutex);
530 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
531 		if (cv_wait_sig(&unitp->pcf8591_cv, &unitp->umutex) <= 0) {
532 			mutex_exit(&unitp->umutex);
533 
534 			return (EINTR);
535 		}
536 	}
537 	unitp->pcf8591_flags = PCF8591_BUSY;
538 	mutex_exit(&unitp->umutex);
539 
540 	switch (cmd) {
541 
542 	case ENVC_IOC_GETTEMP: {
543 		/*
544 		 * Read the status byte from pcf8591 chip. The value will
545 		 * be already converted to Celcius by translate_cputemp.
546 		 */
547 		(void) pcf8591_read_chip(unitp, channel, 1);
548 		if (ddi_copyout(unitp->i2c_tran->i2c_rbuf,
549 		    (caddr_t)arg, sizeof (uint8_t), mode) != DDI_SUCCESS) {
550 			err = EFAULT;
551 		}
552 		break;
553 	}
554 
555 	case ENVC_IOC_GETMODE: {
556 		uint8_t curr_mode = unitp->current_mode;
557 
558 		if (ddi_copyout((caddr_t)&curr_mode, (caddr_t)arg,
559 		    sizeof (uint8_t), mode) != DDI_SUCCESS) {
560 			err = EFAULT;
561 		}
562 		break;
563 	}
564 
565 	case ENVC_IOC_SETMODE: {
566 		uint8_t curr_mode;
567 		if (ddi_copyin((caddr_t)arg, (caddr_t)&curr_mode,
568 		    sizeof (uint8_t), mode) != DDI_SUCCESS) {
569 				err = EFAULT;
570 				break;
571 		}
572 		if (curr_mode == ENVCTRL_DIAG_MODE ||
573 		    curr_mode == ENVCTRL_NORMAL_MODE) {
574 			unitp->current_mode = curr_mode; /* Don't do anything */
575 		}
576 		break;
577 	}
578 
579 	/* Testing, may be removed */
580 	case I2CDEV_TRAN:
581 		if (call_copyin((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
582 			err = EFAULT;
583 			break;
584 		}
585 		if (nct_i2c_transfer(unitp->pcf8591_hdl, unitp->i2c_tran)
586 		    != I2C_SUCCESS) {
587 			err = EFAULT;
588 			break;
589 		}
590 		if (call_copyout((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
591 			err = EFAULT;
592 			break;
593 		}
594 		break;
595 
596 	/*
597 	 * TESTING TRANSLATION from "adc" "table" property
598 	 * translate thermistor index into temp Celcius
599 	 */
600 	case I2CDEV_GETTEMP: {
601 		struct i2c_transfer *tp;
602 		if (call_copyin((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
603 			err = EFAULT;
604 			break;
605 		}
606 		tp = unitp->i2c_tran;
607 		if (tp->i2c_rlen != 1) {
608 			err = EINVAL;
609 			break;
610 		}
611 		/*
612 		 * Throw away the first byte according to PCF8591 datasheet,
613 		 * so read two bytes
614 		 */
615 		tp->i2c_rlen = 2;
616 		if (nct_i2c_transfer(unitp->pcf8591_hdl, unitp->i2c_tran)
617 		    != I2C_SUCCESS) {
618 			err = EFAULT;
619 			break;
620 		}
621 #ifdef DEBUG
622 		if (pcf8591_debug & 0x0010)
623 			cmn_err(CE_NOTE,
624 			    "pcf8591_ioctl: i2c_rlen=%d; "
625 			    "i2c_rbuf[0,1]=0x%x,0x%x\n",
626 			    tp->i2c_rlen, tp->i2c_rbuf[0], tp->i2c_rbuf[1]);
627 #endif /* DEBUG */
628 		/*
629 		 * Throw away the first byte according to PCF8591 datasheet
630 		 */
631 		if ((tp->i2c_rbuf[0] = translate_cputemp(tp->i2c_rbuf[1]))
632 		    == 0) {
633 			err = EINVAL;
634 			break;
635 		}
636 		tp->i2c_rbuf[1] = 0;
637 
638 		if (call_copyout((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
639 			err = EFAULT;
640 			break;
641 		}
642 		break;
643 	}
644 
645 	case I2CDEV_GETTABLES: {
646 		break;
647 	}
648 	default:
649 		err = EINVAL;
650 	}
651 
652 	mutex_enter(&unitp->umutex);
653 	unitp->pcf8591_flags = 0;
654 	cv_signal(&unitp->pcf8591_cv);
655 	mutex_exit(&unitp->umutex);
656 
657 	return (err);
658 }
659 
660 static int
661 pcf8591_do_detach(dev_info_t *dip)
662 {
663 	register struct pcf8591_unit *unitp;
664 	int instance;
665 	uint_t attach_flag;
666 
667 	instance = ddi_get_instance(dip);
668 	unitp = ddi_get_soft_state(pcf8591_soft_statep, instance);
669 	attach_flag = unitp->attach_flag;
670 
671 	if (attach_flag & PCF8591_KSTAT_INIT) {
672 		pcf8591_delete_kstats(unitp);
673 	}
674 
675 	if (attach_flag & PCF8591_LOCK_INIT) {
676 		mutex_destroy(&unitp->umutex);
677 		cv_destroy(&unitp->pcf8591_cv);
678 	}
679 
680 	/*
681 	 * Restore the lengths of the rbuf and wbuf, which was originally
682 	 * allocated so that the appropriate amount of rbuf and wbuf are
683 	 * freed.
684 	 */
685 	if (attach_flag & PCF8591_ALLOC_TRANSFER) {
686 		unitp->i2c_tran->i2c_wlen = MAX_WLEN;
687 		unitp->i2c_tran->i2c_rlen = MAX_RLEN;
688 		i2c_transfer_free(unitp->pcf8591_hdl, unitp->i2c_tran);
689 	}
690 
691 	if (attach_flag & PCF8591_REGISTER_CLIENT) {
692 		i2c_client_unregister(unitp->pcf8591_hdl);
693 	}
694 
695 	if (attach_flag & PCF8591_MINORS_CREATED) {
696 		ddi_remove_minor_node(dip, NULL);
697 	}
698 
699 	/*
700 	 * Free the memory allocated for the properties.
701 	 */
702 	if (attach_flag & PCF8591_PROPS_READ) {
703 		ddi_prop_free(unitp->props.name);
704 		if (unitp->props.num_chans_used) {
705 			ddi_prop_free(unitp->props.channels_in_use);
706 		}
707 
708 		if (unitp->props.channels_description) {
709 			ddi_prop_free(unitp->props.channels_description);
710 		}
711 	}
712 
713 	if (attach_flag & PCF8591_SOFT_STATE_ALLOC) {
714 		ddi_soft_state_free(pcf8591_soft_statep, instance);
715 	}
716 
717 	return (DDI_SUCCESS);
718 }
719 
720 static int
721 pcf8591_do_suspend(dev_info_t *dip)
722 {
723 	int instance = ddi_get_instance(dip);
724 	struct pcf8591_unit *unitp = (struct pcf8591_unit *)
725 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
726 
727 	if (unitp == NULL) {
728 		return (ENXIO);
729 	}
730 
731 	/*
732 	 * Set the busy flag so that future transactions block
733 	 * until resume.
734 	 */
735 	mutex_enter(&unitp->umutex);
736 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
737 		if (cv_wait_sig(&unitp->pcf8591_cv,
738 		    &unitp->umutex) <= 0) {
739 			mutex_exit(&unitp->umutex);
740 
741 			return (DDI_FAILURE);
742 		}
743 	}
744 	unitp->pcf8591_flags = PCF8591_BUSY;
745 	mutex_exit(&unitp->umutex);
746 
747 	return (DDI_SUCCESS);
748 }
749 
750 static int
751 pcf8591_do_resume(dev_info_t *dip)
752 {
753 	int instance = ddi_get_instance(dip);
754 	struct pcf8591_unit *unitp = (struct pcf8591_unit *)
755 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
756 	if (unitp == NULL) {
757 		return (ENXIO);
758 	}
759 
760 	mutex_enter(&unitp->umutex);
761 	unitp->pcf8591_flags = 0;
762 	cv_signal(&unitp->pcf8591_cv);
763 	mutex_exit(&unitp->umutex);
764 
765 	return (DDI_SUCCESS);
766 }
767 
768 static int
769 pcf8591_do_attach(dev_info_t *dip)
770 {
771 	register struct pcf8591_unit *unitp;
772 	int i, instance;
773 	char name[MAXNAMELEN];
774 	minor_t minor;
775 
776 	instance = ddi_get_instance(dip);
777 
778 	if (ddi_soft_state_zalloc(pcf8591_soft_statep, instance) != 0) {
779 		return (DDI_FAILURE);
780 	}
781 
782 	unitp = ddi_get_soft_state(pcf8591_soft_statep, instance);
783 
784 	if (unitp == NULL) {
785 		return (DDI_FAILURE);
786 	}
787 
788 	unitp->dip = dip;
789 
790 	unitp->attach_flag = PCF8591_SOFT_STATE_ALLOC;
791 
792 	if (pcf8591_read_props(unitp) != DDI_PROP_SUCCESS) {
793 		(void) pcf8591_do_detach(dip);
794 		return (DDI_FAILURE);
795 	}
796 
797 	unitp->attach_flag |= PCF8591_PROPS_READ;
798 
799 	/*
800 	 * Set the current operating mode to NORMAL_MODE.
801 	 */
802 	unitp->current_mode = ENVCTRL_NORMAL_MODE; /* normal mode */
803 
804 	(void) snprintf(unitp->pcf8591_name, PCF8591_NAMELEN,
805 	    "%s%d", ddi_driver_name(dip), instance);
806 
807 	/*
808 	 * Create a minor node corresponding to channel 0 to 3
809 	 */
810 	for (i = 0; i < PCF8591_MAX_CHANS; i++) {
811 	if (i == 0) {
812 		(void) sprintf(name, "cputemp");
813 	} else {
814 		(void) sprintf(name, "%d", i);
815 	}
816 	minor = PCF8591_MINOR_NUM(instance, i);
817 	if (ddi_create_minor_node(dip, name, S_IFCHR, minor,
818 	    PCF8591_NODE_TYPE, NULL) == DDI_FAILURE) {
819 			ddi_remove_minor_node(dip, NULL);
820 			(void) pcf8591_do_detach(dip);
821 			return (DDI_FAILURE);
822 		}
823 	}
824 
825 	unitp->attach_flag |= PCF8591_MINORS_CREATED;
826 
827 	if (i2c_client_register(dip, &unitp->pcf8591_hdl)
828 	    != I2C_SUCCESS) {
829 		(void) pcf8591_do_detach(dip);
830 		return (DDI_FAILURE);
831 	}
832 
833 	unitp->attach_flag |= PCF8591_REGISTER_CLIENT;
834 
835 	/*
836 	 * We allocate a single i2c_transfer_t structure for all
837 	 * i2c transactions.
838 	 */
839 	if (i2c_transfer_alloc(unitp->pcf8591_hdl, &unitp->i2c_tran,
840 	    MAX_WLEN, MAX_RLEN, KM_SLEEP) != I2C_SUCCESS) {
841 		(void) pcf8591_do_detach(dip);
842 		return (DDI_FAILURE);
843 	}
844 
845 	unitp->attach_flag |= PCF8591_ALLOC_TRANSFER;
846 
847 	/*
848 	 * The flags will be set to I2C_WR because for all reads from
849 	 * the 8591 we need to also write the control byte.
850 	 */
851 	unitp->i2c_tran->i2c_flags = I2C_WR;
852 	unitp->i2c_tran->i2c_version = I2C_XFER_REV;
853 
854 
855 	/*
856 	 * Set the analog programming mode to default. Upper nibble
857 	 * in control byte. Four single ended inputs, output not enabled.
858 	 */
859 	unitp->pcf8591_inprog = PCF8591_4SINGLE | PCF8591_ANALOG_INPUT_EN;
860 
861 	/*
862 	 * Set the open flag for each channel to 0.
863 	 */
864 	for (i = 0; i < PCF8591_MAX_CHANS; i++) {
865 		unitp->pcf8591_oflag[i] = 0;
866 	}
867 
868 	/*
869 	 * Set the busy flag to 0.
870 	 */
871 	unitp->pcf8591_flags = 0;
872 
873 	mutex_init(&unitp->umutex, NULL, MUTEX_DRIVER, NULL);
874 	cv_init(&unitp->pcf8591_cv, NULL, CV_DRIVER, NULL);
875 
876 	unitp->attach_flag |= PCF8591_LOCK_INIT;
877 
878 	if (pcf8591_add_kstats(unitp) != DDI_SUCCESS) {
879 		(void) pcf8591_do_detach(dip);
880 		return (DDI_FAILURE);
881 	}
882 
883 	unitp->attach_flag |= PCF8591_KSTAT_INIT;
884 
885 	ddi_report_dev(dip);
886 
887 	return (DDI_SUCCESS);
888 }
889 
890 /* ARGSUSED */
891 static int
892 pcf8591_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
893 {
894 	dev_t	dev;
895 	int	instance;
896 
897 	if (infocmd == DDI_INFO_DEVT2INSTANCE) {
898 		dev = (dev_t)arg;
899 		instance = PCF8591_MINOR_TO_DEVINST(getminor(dev));
900 		*result = (void *)(uintptr_t)instance;
901 		return (DDI_SUCCESS);
902 	}
903 	return (DDI_FAILURE);
904 }
905 
906 static int
907 pcf8591_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
908 {
909 	switch (cmd) {
910 	case DDI_ATTACH:
911 		return (pcf8591_do_attach(dip));
912 	case DDI_RESUME:
913 		return (pcf8591_do_resume(dip));
914 	default:
915 		return (DDI_FAILURE);
916 	}
917 }
918 
919 static int
920 pcf8591_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
921 {
922 	switch (cmd) {
923 	case DDI_DETACH:
924 		return (pcf8591_do_detach(dip));
925 	case DDI_SUSPEND:
926 		return (pcf8591_do_suspend(dip));
927 	default:
928 		return (DDI_FAILURE);
929 	}
930 }
931 
932 static uint8_t
933 translate_cputemp(uint8_t value)
934 {
935 	return (_cpu_temps[value]);
936 }
937 
938 static int
939 pcf8591_add_kstats(struct pcf8591_unit *unitp)
940 {
941 	if ((unitp->tempksp = kstat_create(I2C_PCF8591_NAME,
942 	    unitp->instance, I2C_KSTAT_CPUTEMP, "misc",
943 	    KSTAT_TYPE_RAW, sizeof (unitp->temp_kstats),
944 	    KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) {
945 
946 		return (DDI_FAILURE);
947 	}
948 
949 	/*
950 	 * The kstat fields are already initialized in the attach routine..
951 	 */
952 
953 	unitp->tempksp->ks_update = pcf8591_temp_kstat_update;
954 	unitp->tempksp->ks_private = (void *)unitp;
955 
956 	(void) strcpy(unitp->temp_kstats.label,
957 	    unitp->props.channels_description[0]);
958 	unitp->temp_kstats.type = ENVC_NETRACT_CPU_SENSOR;
959 
960 	kstat_install(unitp->tempksp);
961 
962 	return (DDI_SUCCESS);
963 }
964 
965 static void
966 pcf8591_delete_kstats(struct pcf8591_unit *unitp)
967 {
968 	kstat_delete(unitp->tempksp);
969 }
970 
971 static int
972 pcf8591_temp_kstat_update(kstat_t *ksp, int rw)
973 {
974 	struct pcf8591_unit *unitp;
975 	char *kstatp;
976 	int err = 0;
977 	int channel = 0;
978 	int warn_temp = 0;
979 	int shutdown_temp = 0;
980 
981 	unitp = (struct pcf8591_unit *)ksp->ks_private;
982 
983 	mutex_enter(&unitp->umutex);
984 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
985 		if (cv_wait_sig(&unitp->pcf8591_cv,
986 		    &unitp->umutex) <= 0) {
987 			mutex_exit(&unitp->umutex);
988 
989 			return (EINTR);
990 		}
991 	}
992 
993 	unitp->pcf8591_flags = PCF8591_BUSY;
994 	mutex_exit(&unitp->umutex);
995 
996 	kstatp = (char *)ksp->ks_data;
997 
998 	if (rw == KSTAT_WRITE) {
999 
1000 		/* check for the size of buffer */
1001 		if (ksp->ks_data_size != sizeof (unitp->temp_kstats)) {
1002 			err = EIO;
1003 			goto bail;
1004 		}
1005 
1006 		warn_temp = ((envctrl_temp_t *)kstatp)->warning_threshold;
1007 		shutdown_temp = ((envctrl_temp_t *)kstatp)->shutdown_threshold;
1008 
1009 		if (shutdown_temp < SHUTDOWN_TEMP_MIN || shutdown_temp >
1010 		    SHUTDOWN_TEMP_MAX) {
1011 			err = EIO;
1012 			goto bail;
1013 		}
1014 
1015 		if (warn_temp < 0 || shutdown_temp <= warn_temp) {
1016 			err = EIO;
1017 			goto bail;
1018 		}
1019 
1020 		/* write into kstat fields */
1021 		unitp->temp_kstats.warning_threshold = warn_temp;
1022 		unitp->temp_kstats.shutdown_threshold = shutdown_temp;
1023 
1024 	} else {
1025 		(void) pcf8591_read_chip(unitp, channel, 1);
1026 		unitp->temp_kstats.value =
1027 		    unitp->i2c_tran->i2c_rbuf[0];
1028 		bcopy((caddr_t)&unitp->temp_kstats, kstatp,
1029 		    sizeof (unitp->temp_kstats));
1030 	}
1031 
1032 bail:
1033 
1034 	mutex_enter(&unitp->umutex);
1035 	unitp->pcf8591_flags = 0;
1036 	cv_signal(&unitp->pcf8591_cv);
1037 	mutex_exit(&unitp->umutex);
1038 
1039 	return (err);
1040 }
1041 
1042 static int
1043 pcf8591_read_chip(struct pcf8591_unit *unitp, uint8_t channel,
1044 int size)
1045 {
1046 	int retval = I2C_SUCCESS;
1047 
1048 	/*
1049 	 * We need to read an extra byte, since as per specification
1050 	 * the first byte read should be discarded.
1051 	 */
1052 	i2c_transfer_t *tp = unitp->i2c_tran;
1053 	tp->i2c_flags = I2C_WR_RD;
1054 	tp->i2c_rlen = size+1;
1055 	tp->i2c_wlen = 1;
1056 	tp->i2c_wbuf[0] = (unitp->pcf8591_inprog |
1057 	    channel);
1058 
1059 	retval = nct_i2c_transfer(unitp->pcf8591_hdl, tp);
1060 	if (retval == I2C_SUCCESS) {
1061 		tp->i2c_rbuf[0] = translate_cputemp(tp->i2c_rbuf[1]);
1062 	}
1063 
1064 	if (tp->i2c_rbuf[0] == 0) {
1065 		retval = I2C_FAILURE;
1066 	}
1067 
1068 	return (retval);
1069 }
1070 
1071 /*
1072  * Reads the properties of the pcf8591 device.
1073  */
1074 static int
1075 pcf8591_read_props(struct pcf8591_unit *unitp)
1076 {
1077 	dev_info_t *dip = unitp->dip;
1078 	int i, retval = 0, prop_len;
1079 	int instance = ddi_get_instance(dip);
1080 	int warning_temp, shutdown_temp;
1081 	uint32_t *prop_value = NULL;
1082 	uchar_t *creg_prop;
1083 	char *function;
1084 	uint_t		tblsz;
1085 
1086 #ifdef lint
1087 	instance = instance;
1088 #endif
1089 	/*
1090 	 * Check for the pcf8591_function property, and make sure it's
1091 	 * cputemp.
1092 	 */
1093 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1094 	    "pcf8591_function", &function) != DDI_SUCCESS) {
1095 		dbg_print(CE_WARN, "Couldn't find pcf8591_function property");
1096 
1097 		return (DDI_FAILURE);
1098 	}
1099 
1100 	if (strcmp(function, "cputemp") != 0) {
1101 		dbg_print(CE_WARN, "pcf8591_function is not cputemp");
1102 		ddi_prop_free(function);
1103 
1104 		return (DDI_FAILURE);
1105 	}
1106 
1107 	ddi_prop_free(function);
1108 
1109 	retval = ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1110 	    "name", &unitp->props.name);
1111 	if (retval != DDI_PROP_SUCCESS) {
1112 
1113 		return (retval);
1114 	}
1115 #ifdef DEBUG
1116 	else if (pcf8591_debug & 0x02)
1117 		cmn_err(CE_NOTE,
1118 		    "pcf8591_read_props:ddi_prop_lookup_string(%s): \
1119 			found  %s ", "name", unitp->props.name);
1120 #endif /* DEBUG */
1121 
1122 	retval = ddi_getlongprop(DDI_DEV_T_ANY, dip,
1123 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP,
1124 	    "reg", (caddr_t)&prop_value, &prop_len);
1125 	if (retval == DDI_PROP_SUCCESS) {
1126 		unitp->props.i2c_bus		= (uint16_t)prop_value[0];
1127 		unitp->props.slave_address	= (uint16_t)prop_value[1];
1128 		kmem_free(prop_value, prop_len);
1129 #ifdef DEBUG
1130 		if (pcf8591_debug & 0x02)
1131 			cmn_err(CE_NOTE,
1132 			    "pcf8591:ddi_getlongprop(%s) returns %d,"
1133 			    " i2c_bus,slave=0x%x,0x%x",
1134 			    "reg", retval,  unitp->props.i2c_bus,
1135 			    unitp->props.slave_address);
1136 #endif /* DEBUG */
1137 	} else {
1138 		unitp->props.i2c_bus		= (uint16_t)-1;
1139 		unitp->props.slave_address	= (uint16_t)-1;
1140 #ifdef DEBUG
1141 		cmn_err(CE_WARN,
1142 		    "pcf8591_read_props:ddi_getlongprop(%s) returns %d,"
1143 		    " default it to 0x%x:0x%X",
1144 		    "reg", retval,  unitp->props.i2c_bus,
1145 		    unitp->props.slave_address);
1146 #endif /* DEBUG */
1147 	}
1148 	(void) ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1149 	    "channels-in-use", &prop_len);
1150 	retval = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
1151 	    dip, DDI_PROP_DONTPASS,
1152 	    "channels-in-use",
1153 	    (uchar_t **)&unitp->props.channels_in_use,
1154 	    &unitp->props.num_chans_used);
1155 	if (retval == DDI_PROP_SUCCESS) {
1156 		unitp->props.num_chans_used /= sizeof (pcf8591_channel_t);
1157 	} else {
1158 		unitp->props.num_chans_used = 0;
1159 	}
1160 
1161 #ifdef DEBUG
1162 	if (pcf8591_debug & 0x0002)
1163 		cmn_err(CE_NOTE,
1164 		    "pcf8591_read_props:ddi_prop_lookup_byte_array(%s)"
1165 		    "returns %d\n"
1166 		    "\t\tlength=%d, #elements=%d",
1167 		    "channels-in-use", retval,
1168 		    prop_len, unitp->props.num_chans_used);
1169 #endif /* DEBUG */
1170 
1171 	retval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
1172 	    DDI_PROP_DONTPASS, "channels-description",
1173 	    (char ***)&unitp->props.channels_description,
1174 	    (uint_t *)&prop_len);
1175 
1176 	if (retval != DDI_PROP_SUCCESS) {
1177 		prop_len = 0;
1178 		unitp->props.channels_description = NULL;
1179 	}
1180 
1181 #ifdef DEBUG
1182 	if (pcf8591_debug & 0x0002) {
1183 		cmn_err(CE_NOTE,
1184 		    "pcf8591_read_props:ddi_prop_lookup_string_array(%s)"
1185 		    "returns %d, length=%d",
1186 		    "channels-description", retval, prop_len);
1187 		for (i = 0; i < prop_len; ++i) {
1188 			cmn_err(CE_NOTE, "channels-description[%d]=<%s>",
1189 			    i, unitp->props.channels_description[i]);
1190 		}
1191 	}
1192 #endif /* DEBUG */
1193 
1194 	/*
1195 	 * The following code was borrowed from envctrltwo.c
1196 	 * I haven't yet investigated why the copy target is index + 2
1197 	 */
1198 	retval = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
1199 	    DDI_PROP_DONTPASS, "tables", &creg_prop, (uint_t *)&prop_len);
1200 
1201 	if (retval != DDI_PROP_SUCCESS) {
1202 #ifdef DEBUG
1203 		cmn_err(CE_WARN, "%s%d: Unable to read pcf8591 tables property",
1204 		    ddi_get_name(dip), instance);
1205 #endif /* DEBUG */
1206 
1207 		return (DDI_NOT_WELL_FORMED);
1208 	}
1209 
1210 	tblsz = (sizeof (_cpu_temps) / sizeof (uchar_t));
1211 	if (prop_len <= tblsz) {
1212 		for (i = 0; i < prop_len; i++) {
1213 			_cpu_temps[i] = creg_prop[i];
1214 		}
1215 	}
1216 #ifdef DEBUG
1217 	if (pcf8591_debug & 0x0002)
1218 		cmn_err(CE_NOTE, "pcf8591_read_props: _cpu_temps size=%d; "
1219 		    "tables prop_len=%d\n", tblsz, prop_len);
1220 #endif /* DEBUG */
1221 
1222 	ddi_prop_free(creg_prop);
1223 
1224 	/*
1225 	 * Read shutdown temp and warning temp properties.
1226 	 */
1227 	warning_temp = (int)ddi_getprop(DDI_DEV_T_ANY, dip,
1228 	    DDI_PROP_DONTPASS, "warning-temp", PCF8591_WARNING_TEMP);
1229 
1230 	shutdown_temp = (int)ddi_getprop(DDI_DEV_T_ANY, dip,
1231 	    DDI_PROP_DONTPASS, "shutdown-temp", PCF8591_SHUTDOWN_TEMP);
1232 
1233 	/*
1234 	 * Fill up the warning and shutdown temp values in kstat structure.
1235 	 */
1236 	unitp->temp_kstats.warning_threshold = warning_temp;
1237 	unitp->temp_kstats.shutdown_threshold = shutdown_temp;
1238 
1239 	return (DDI_PROP_SUCCESS);
1240 }
1241