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