xref: /onnv-gate/usr/src/uts/sun4u/io/envctrl_targets.c (revision 1341:6d7c4f090a72)
1*1341Sstevel /*
2*1341Sstevel  * CDDL HEADER START
3*1341Sstevel  *
4*1341Sstevel  * The contents of this file are subject to the terms of the
5*1341Sstevel  * Common Development and Distribution License (the "License").
6*1341Sstevel  * You may not use this file except in compliance with the License.
7*1341Sstevel  *
8*1341Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1341Sstevel  * or http://www.opensolaris.org/os/licensing.
10*1341Sstevel  * See the License for the specific language governing permissions
11*1341Sstevel  * and limitations under the License.
12*1341Sstevel  *
13*1341Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
14*1341Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1341Sstevel  * If applicable, add the following below this CDDL HEADER, with the
16*1341Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
17*1341Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1341Sstevel  *
19*1341Sstevel  * CDDL HEADER END
20*1341Sstevel  */
21*1341Sstevel 
22*1341Sstevel /*
23*1341Sstevel  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24*1341Sstevel  * Use is subject to license terms.
25*1341Sstevel  */
26*1341Sstevel 
27*1341Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*1341Sstevel 
29*1341Sstevel /*
30*1341Sstevel  * Low level environmental control routines.
31*1341Sstevel  * These routines implement the I2C bus protocol.
32*1341Sstevel  */
33*1341Sstevel 
34*1341Sstevel #define	EHC_SUCCESS 0
35*1341Sstevel #define	EHC_FAILURE (-1)
36*1341Sstevel #define	EHC_NO_SLAVE_ACK 3
37*1341Sstevel 
38*1341Sstevel #define	EHC_MAX_WAIT 100 /* decimal */
39*1341Sstevel 
40*1341Sstevel #define	EHC_S1_PIN 0x80
41*1341Sstevel #define	EHC_S1_ES1 0x20
42*1341Sstevel #define	EHC_S1_ES0 0x40
43*1341Sstevel #define	EHC_S1_NBB 0x01
44*1341Sstevel #define	EHC_S1_ACK 0x01
45*1341Sstevel #define	EHC_S1_STA 0x04
46*1341Sstevel #define	EHC_S1_STO 0x02
47*1341Sstevel #define	EHC_S1_LRB 0x08
48*1341Sstevel #define	EHC_S1_BER 0x10
49*1341Sstevel #define	EHC_S1_LAB 0x02
50*1341Sstevel #define	EHC_S1_AAS 0x04
51*1341Sstevel #define	EHC_S1_AD0 0x08
52*1341Sstevel #define	EHC_S1_STS 0x20
53*1341Sstevel 
54*1341Sstevel #define	EHC_S0_OWN 0x55
55*1341Sstevel #define	EHC_S0_CLK 0x1d
56*1341Sstevel 
57*1341Sstevel #define	EHC_BYTE_READ 0x01
58*1341Sstevel 
59*1341Sstevel #define	EHC_LONGEST_MSG 200000 /* 200 ms */
60*1341Sstevel 
61*1341Sstevel #define	DUMMY_WRITE_ADDR 0x20
62*1341Sstevel #define	DUMMY_WRITE_DATA 0x00
63*1341Sstevel 
64*1341Sstevel /*
65*1341Sstevel  * PCF8591 Chip Used for temperature sensors
66*1341Sstevel  *
67*1341Sstevel  * Addressing Register definition.
68*1341Sstevel  * A0-A2 valid range is 0-7
69*1341Sstevel  *
70*1341Sstevel  * ------------------------------------------------
71*1341Sstevel  * | 1 | 0 | 0 | 1 | A2 | A1 | A0 | R/W |
72*1341Sstevel  * ------------------------------------------------
73*1341Sstevel  */
74*1341Sstevel 
75*1341Sstevel 
76*1341Sstevel #define	EHC_PCF8591_MAX_DEVS	0x08
77*1341Sstevel 
78*1341Sstevel #define	EHC_DEV0	0x00
79*1341Sstevel #define	EHC_DEV1	0x02
80*1341Sstevel #define	EHC_DEV2	0x04
81*1341Sstevel #define	EHC_DEV3	0x06
82*1341Sstevel #define	EHC_DEV4	0x08
83*1341Sstevel #define	EHC_DEV5	0x0A
84*1341Sstevel #define	EHC_DEV6    	0x0C
85*1341Sstevel #define	EHC_DEV7	0x0E
86*1341Sstevel 
87*1341Sstevel 
88*1341Sstevel /*
89*1341Sstevel  * 		CONTROL OF CHIP
90*1341Sstevel  * PCF8591 Temp sensing control register definitions
91*1341Sstevel  *
92*1341Sstevel  * ---------------------------------------------
93*1341Sstevel  * | 0 | AOE | X | X | 0 | AIF | X | X |
94*1341Sstevel  * ---------------------------------------------
95*1341Sstevel  * AOE = Analog out enable.. not used on out implementation
96*1341Sstevel  * 5 & 4 = Analog Input Programming.. see data sheet for bits..
97*1341Sstevel  *
98*1341Sstevel  * AIF = Auto increment flag
99*1341Sstevel  * bits 1 & 0 are for the Chennel number.
100*1341Sstevel  */
101*1341Sstevel 
102*1341Sstevel #define	EHC_PCF8591_ANALOG_OUTPUT_EN	0x40
103*1341Sstevel #define	EHC_PCF8591_ANALOG_INPUT_EN	0x00
104*1341Sstevel #define	EHC_PCF8591_READ_BIT		0x01
105*1341Sstevel 
106*1341Sstevel 
107*1341Sstevel #define	EHC_PCF8591_AUTO_INCR 0x04
108*1341Sstevel #define	EHC_PCF8591_OSCILATOR 0x40
109*1341Sstevel 
110*1341Sstevel #define	EHC_PCF8591_MAX_PORTS	0x04
111*1341Sstevel 
112*1341Sstevel #define	EHC_PCF8591_CH_0	0x00
113*1341Sstevel #define	EHC_PCF8591_CH_1	0x01
114*1341Sstevel #define	EHC_PCF8591_CH_2	0x02
115*1341Sstevel #define	EHC_PCF8591_CH_3	0x03
116*1341Sstevel 
117*1341Sstevel 
118*1341Sstevel /*
119*1341Sstevel  * PCF8574 Fan Fail, Power Supply Fail Detector
120*1341Sstevel  * This device is driven by interrupts. Each time it interrupts
121*1341Sstevel  * you must look at the CSR to see which ports caused the interrupt
122*1341Sstevel  * they are indicated by a 1.
123*1341Sstevel  *
124*1341Sstevel  * Address map of this chip
125*1341Sstevel  *
126*1341Sstevel  * -------------------------------------------
127*1341Sstevel  * | 0 | 1 | 1 | 1 | A2 | A1 | A0 | 0 |
128*1341Sstevel  * -------------------------------------------
129*1341Sstevel  *
130*1341Sstevel  */
131*1341Sstevel 
132*1341Sstevel #define	EHC_PCF8574_PORT0	0x01
133*1341Sstevel #define	EHC_PCF8574_PORT1	0x02
134*1341Sstevel #define	EHC_PCF8574_PORT2	0x04
135*1341Sstevel #define	EHC_PCF8574_PORT3	0x08
136*1341Sstevel #define	EHC_PCF8574_PORT4	0x10
137*1341Sstevel #define	EHC_PCF8574_PORT5	0x20
138*1341Sstevel #define	EHC_PCF8574_PORT6	0x40
139*1341Sstevel #define	EHC_PCF8574_PORT7	0x80
140*1341Sstevel 
141*1341Sstevel /*
142*1341Sstevel  * Defines for the PCF8583 Clock Calendar Chip.
143*1341Sstevel  */
144*1341Sstevel #define	EHC_PCF8583_READ_BIT	0x01
145*1341Sstevel 
146*1341Sstevel struct ehc_pcd8584_regs {
147*1341Sstevel 	uint8_t s0;		/* Own Address S0' */
148*1341Sstevel 	uint8_t s1;		/* Control Status register */
149*1341Sstevel 	uint8_t clock_s2;	/* Clock programming register */
150*1341Sstevel };
151*1341Sstevel 
152*1341Sstevel struct ehc_envcunit {
153*1341Sstevel 	struct ehc_pcd8584_regs *bus_ctl_regs;
154*1341Sstevel 	ddi_acc_handle_t ctlr_handle;
155*1341Sstevel 	kmutex_t umutex;
156*1341Sstevel };
157*1341Sstevel 
158*1341Sstevel int ehc_debug = 0;
159*1341Sstevel 
160*1341Sstevel #define	DCMN_ERR if (ehc_debug & 0x1) cmn_err
161*1341Sstevel #define	DCMN2_ERR if (ehc_debug & 0x2) cmn_err
162*1341Sstevel 
163*1341Sstevel /*
164*1341Sstevel  * Prototypes for routines used in other modules.
165*1341Sstevel  */
166*1341Sstevel 
167*1341Sstevel void ehc_init_pcf8584(struct ehc_envcunit *);
168*1341Sstevel int ehc_read_tda8444(struct ehc_envcunit *ehcp);
169*1341Sstevel int ehc_write_tda8444(struct ehc_envcunit *, int, int, int, uint8_t *, int);
170*1341Sstevel int ehc_write_pcf8591(struct ehc_envcunit *, int, int, int, int, int,
171*1341Sstevel 	uint8_t *, int);
172*1341Sstevel int ehc_read_pcf8591(struct ehc_envcunit *, int, int, int, int, int,
173*1341Sstevel 	uint8_t *, int);
174*1341Sstevel int ehc_read_pcf8574a(struct ehc_envcunit *, int, uint8_t *, int);
175*1341Sstevel int ehc_write_pcf8574a(struct ehc_envcunit *, int, uint8_t *, int);
176*1341Sstevel int ehc_read_pcf8574(struct ehc_envcunit *, int, uint8_t *, int);
177*1341Sstevel int ehc_write_pcf8574(struct ehc_envcunit *, int, uint8_t *, int);
178*1341Sstevel int ehc_read_lm75(struct ehc_envcunit *, int, uint8_t *, int);
179*1341Sstevel int ehc_write_pcf8583(struct ehc_envcunit *, int, uint8_t *, int);
180*1341Sstevel 
181*1341Sstevel /*
182*1341Sstevel  * Prototypes for routines used only in this source module.
183*1341Sstevel  */
184*1341Sstevel 
185*1341Sstevel static int ehc_start_pcf8584(struct ehc_envcunit *, uint8_t);
186*1341Sstevel static void ehc_stop_pcf8584(struct ehc_envcunit *);
187*1341Sstevel static int ehc_read_pcf8584(struct ehc_envcunit *, uint8_t *);
188*1341Sstevel static int ehc_write_pcf8584(struct ehc_envcunit *, uint8_t);
189*1341Sstevel static int ehc_after_read_pcf8584(struct ehc_envcunit *, uint8_t *);
190*1341Sstevel 
191*1341Sstevel /*
192*1341Sstevel  * put host interface into master mode
193*1341Sstevel  */
194*1341Sstevel static int
ehc_start_pcf8584(struct ehc_envcunit * ehcp,uint8_t byteaddress)195*1341Sstevel ehc_start_pcf8584(struct ehc_envcunit *ehcp, uint8_t byteaddress)
196*1341Sstevel {
197*1341Sstevel 	uint8_t poll_status;
198*1341Sstevel 	uint8_t discard;
199*1341Sstevel 	int i;
200*1341Sstevel 
201*1341Sstevel 	/* wait if bus is busy */
202*1341Sstevel 
203*1341Sstevel 	i = 0;
204*1341Sstevel 	do {
205*1341Sstevel 		drv_usecwait(1000);
206*1341Sstevel 		poll_status =
207*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
208*1341Sstevel 		i++;
209*1341Sstevel 	} while (((poll_status & EHC_S1_NBB) == 0) && i < EHC_MAX_WAIT);
210*1341Sstevel 
211*1341Sstevel 	if (i == EHC_MAX_WAIT) {
212*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): busy bit clear failed");
213*1341Sstevel 		return (EHC_FAILURE);
214*1341Sstevel 	}
215*1341Sstevel 
216*1341Sstevel 	if (poll_status & EHC_S1_BER) {
217*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()1: Bus error");
218*1341Sstevel 		ehc_init_pcf8584(ehcp);
219*1341Sstevel 		return (EHC_FAILURE);
220*1341Sstevel 	}
221*1341Sstevel 
222*1341Sstevel 	if (poll_status & EHC_S1_LAB) {
223*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()1: Lost Arbitration");
224*1341Sstevel 		ehc_init_pcf8584(ehcp);
225*1341Sstevel 		return (EHC_FAILURE);
226*1341Sstevel 	}
227*1341Sstevel 
228*1341Sstevel 	/*
229*1341Sstevel 	 * This is a dummy arbitration using the lowest unused address
230*1341Sstevel 	 * possible. This step allows the PCF8584 to always win arbitration
231*1341Sstevel 	 * except in the case of "general call" being issued by the other
232*1341Sstevel 	 * master.
233*1341Sstevel 	 */
234*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, DUMMY_WRITE_ADDR);
235*1341Sstevel 
236*1341Sstevel 	/* generate the "start condition" and clock out the slave address */
237*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
238*1341Sstevel 		EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
239*1341Sstevel 
240*1341Sstevel 	/* wait for completion of transmission */
241*1341Sstevel 	i = 0;
242*1341Sstevel 	do {
243*1341Sstevel 		drv_usecwait(1000);
244*1341Sstevel 		poll_status =
245*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
246*1341Sstevel 		i++;
247*1341Sstevel 	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
248*1341Sstevel 
249*1341Sstevel 	if (i == EHC_MAX_WAIT) {
250*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_start_pcf8584_5(): read of S1 failed");
251*1341Sstevel 		return (EHC_FAILURE);
252*1341Sstevel 	}
253*1341Sstevel 
254*1341Sstevel 	if (poll_status & EHC_S1_BER) {
255*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()5: Bus error");
256*1341Sstevel 		ehc_init_pcf8584(ehcp);
257*1341Sstevel 		return (EHC_FAILURE);
258*1341Sstevel 	}
259*1341Sstevel 
260*1341Sstevel 	if (poll_status & EHC_S1_LAB) {
261*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()5: Lost Arbitration");
262*1341Sstevel 		ehc_init_pcf8584(ehcp);
263*1341Sstevel 		return (EHC_FAILURE);
264*1341Sstevel 	}
265*1341Sstevel 
266*1341Sstevel 	/* dummy write */
267*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, DUMMY_WRITE_DATA);
268*1341Sstevel 
269*1341Sstevel 	/* wait for completion of transmission */
270*1341Sstevel 	i = 0;
271*1341Sstevel 	do {
272*1341Sstevel 		drv_usecwait(1000);
273*1341Sstevel 		poll_status =
274*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
275*1341Sstevel 		i++;
276*1341Sstevel 	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
277*1341Sstevel 
278*1341Sstevel 	if (i == EHC_MAX_WAIT) {
279*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): read of S1 failed");
280*1341Sstevel 		return (EHC_FAILURE);
281*1341Sstevel 	}
282*1341Sstevel 
283*1341Sstevel 	if (poll_status & EHC_S1_BER) {
284*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()4: Bus error");
285*1341Sstevel 		ehc_init_pcf8584(ehcp);
286*1341Sstevel 		return (EHC_FAILURE);
287*1341Sstevel 	}
288*1341Sstevel 
289*1341Sstevel 	if (poll_status & EHC_S1_LAB) {
290*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()4: Lost Arbitration");
291*1341Sstevel 		ehc_init_pcf8584(ehcp);
292*1341Sstevel 		return (EHC_FAILURE);
293*1341Sstevel 	}
294*1341Sstevel 
295*1341Sstevel 	/*
296*1341Sstevel 	 * generate the repeated "start condition" and
297*1341Sstevel 	 * clock out the slave address
298*1341Sstevel 	 */
299*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
300*1341Sstevel 		EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
301*1341Sstevel 
302*1341Sstevel 	/* load the slave address */
303*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, byteaddress);
304*1341Sstevel 
305*1341Sstevel 	/* wait for completion of transmission */
306*1341Sstevel 	i = 0;
307*1341Sstevel 	do {
308*1341Sstevel 		drv_usecwait(1000);
309*1341Sstevel 		poll_status =
310*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
311*1341Sstevel 		i++;
312*1341Sstevel 	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
313*1341Sstevel 
314*1341Sstevel 	if (i == EHC_MAX_WAIT) {
315*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): read of S1 failed");
316*1341Sstevel 		return (EHC_FAILURE);
317*1341Sstevel 	}
318*1341Sstevel 
319*1341Sstevel 	if (poll_status & EHC_S1_BER) {
320*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()2: Bus error");
321*1341Sstevel 		ehc_init_pcf8584(ehcp);
322*1341Sstevel 		return (EHC_FAILURE);
323*1341Sstevel 	}
324*1341Sstevel 
325*1341Sstevel 	if (poll_status & EHC_S1_LAB) {
326*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()2: Lost Arbitration");
327*1341Sstevel 		ehc_init_pcf8584(ehcp);
328*1341Sstevel 		return (EHC_FAILURE);
329*1341Sstevel 	}
330*1341Sstevel 
331*1341Sstevel 	if (poll_status & EHC_S1_LRB) {
332*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): No slave ACK");
333*1341Sstevel 		return (EHC_NO_SLAVE_ACK);
334*1341Sstevel 	}
335*1341Sstevel 
336*1341Sstevel 	/*
337*1341Sstevel 	 * If this is a read we are setting up for (as indicated by
338*1341Sstevel 	 * the least significant byte being set), read
339*1341Sstevel 	 * and discard the first byte off the bus - this
340*1341Sstevel 	 * is the slave address.
341*1341Sstevel 	 */
342*1341Sstevel 
343*1341Sstevel 	i = 0;
344*1341Sstevel 	if (byteaddress & EHC_BYTE_READ) {
345*1341Sstevel 		discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
346*1341Sstevel #ifdef lint
347*1341Sstevel 		discard = discard;
348*1341Sstevel #endif
349*1341Sstevel 
350*1341Sstevel 		/* wait for completion of transmission */
351*1341Sstevel 		do {
352*1341Sstevel 			drv_usecwait(1000);
353*1341Sstevel 			poll_status =
354*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
355*1341Sstevel 			i++;
356*1341Sstevel 		} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
357*1341Sstevel 
358*1341Sstevel 		if (i == EHC_MAX_WAIT) {
359*1341Sstevel 			DCMN_ERR(CE_WARN,
360*1341Sstevel 				"ehc_start_pcf8584(): read of S1 failed");
361*1341Sstevel 			return (EHC_FAILURE);
362*1341Sstevel 		}
363*1341Sstevel 
364*1341Sstevel 		if (poll_status & EHC_S1_BER) {
365*1341Sstevel 			DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()3: Bus error");
366*1341Sstevel 			ehc_init_pcf8584(ehcp);
367*1341Sstevel 			return (EHC_FAILURE);
368*1341Sstevel 		}
369*1341Sstevel 		if (poll_status & EHC_S1_LAB) {
370*1341Sstevel 			DCMN2_ERR(CE_WARN,
371*1341Sstevel 				"ehc_start_pcf8584()3: Lost Arbitration");
372*1341Sstevel 			ehc_init_pcf8584(ehcp);
373*1341Sstevel 			return (EHC_FAILURE);
374*1341Sstevel 		}
375*1341Sstevel 
376*1341Sstevel 	}
377*1341Sstevel 
378*1341Sstevel 	return (EHC_SUCCESS);
379*1341Sstevel }
380*1341Sstevel 
381*1341Sstevel /*
382*1341Sstevel  * put host interface into slave/receiver mode
383*1341Sstevel  */
384*1341Sstevel static void
ehc_stop_pcf8584(struct ehc_envcunit * ehcp)385*1341Sstevel ehc_stop_pcf8584(struct ehc_envcunit *ehcp)
386*1341Sstevel {
387*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
388*1341Sstevel 		EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STO | EHC_S1_ACK);
389*1341Sstevel }
390*1341Sstevel 
391*1341Sstevel static int
ehc_read_pcf8584(struct ehc_envcunit * ehcp,uint8_t * data)392*1341Sstevel ehc_read_pcf8584(struct ehc_envcunit *ehcp, uint8_t *data)
393*1341Sstevel {
394*1341Sstevel 	uint8_t poll_status;
395*1341Sstevel 	int i = 0;
396*1341Sstevel 
397*1341Sstevel 	/* Read the byte of interest */
398*1341Sstevel 	*data = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
399*1341Sstevel 
400*1341Sstevel 	/* wait for completion of transmission */
401*1341Sstevel 	do {
402*1341Sstevel 		drv_usecwait(1000);
403*1341Sstevel 		poll_status =
404*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
405*1341Sstevel 		i++;
406*1341Sstevel 	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
407*1341Sstevel 
408*1341Sstevel 	if (i == EHC_MAX_WAIT) {
409*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_read_pcf8584(): read of S1 failed");
410*1341Sstevel 		return (EHC_FAILURE);
411*1341Sstevel 	}
412*1341Sstevel 
413*1341Sstevel 	if (poll_status & EHC_S1_BER) {
414*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_read_pcf8584(): Bus error");
415*1341Sstevel 		ehc_init_pcf8584(ehcp);
416*1341Sstevel 		return (EHC_FAILURE);
417*1341Sstevel 	}
418*1341Sstevel 
419*1341Sstevel 	if (poll_status & EHC_S1_LAB) {
420*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_read_pcf8584(): Lost Arbitration");
421*1341Sstevel 		ehc_init_pcf8584(ehcp);
422*1341Sstevel 		return (EHC_FAILURE);
423*1341Sstevel 	}
424*1341Sstevel 
425*1341Sstevel 	return (EHC_SUCCESS);
426*1341Sstevel }
427*1341Sstevel 
428*1341Sstevel /*
429*1341Sstevel  * host interface is in transmitter state, thus mode is master/transmitter
430*1341Sstevel  * NOTE to Bill: this check the LRB bit (only done in transmit mode).
431*1341Sstevel  */
432*1341Sstevel 
433*1341Sstevel static int
ehc_write_pcf8584(struct ehc_envcunit * ehcp,uint8_t data)434*1341Sstevel ehc_write_pcf8584(struct ehc_envcunit *ehcp, uint8_t data)
435*1341Sstevel {
436*1341Sstevel 	uint8_t poll_status;
437*1341Sstevel 	int i = 0;
438*1341Sstevel 
439*1341Sstevel 	/* send the data, EHC_S1_PIN should go to "1" immediately */
440*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, data);
441*1341Sstevel 
442*1341Sstevel 	/* wait for completion of transmission */
443*1341Sstevel 	do {
444*1341Sstevel 		drv_usecwait(1000);
445*1341Sstevel 		poll_status =
446*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
447*1341Sstevel 		i++;
448*1341Sstevel 	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
449*1341Sstevel 
450*1341Sstevel 	if (i == EHC_MAX_WAIT) {
451*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_write_pcf8584(): read of S1 failed");
452*1341Sstevel 		return (EHC_FAILURE);
453*1341Sstevel 	}
454*1341Sstevel 
455*1341Sstevel 	if (poll_status & EHC_S1_BER) {
456*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_write_pcf8584(): Bus error");
457*1341Sstevel 		ehc_init_pcf8584(ehcp);
458*1341Sstevel 		return (EHC_FAILURE);
459*1341Sstevel 	}
460*1341Sstevel 
461*1341Sstevel 	if (poll_status & EHC_S1_LAB) {
462*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_write_pcf8584(): Lost Arbitration");
463*1341Sstevel 		ehc_init_pcf8584(ehcp);
464*1341Sstevel 		return (EHC_FAILURE);
465*1341Sstevel 	}
466*1341Sstevel 
467*1341Sstevel 	if (poll_status & EHC_S1_LRB) {
468*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_write_pcf8584(): No slave ACK");
469*1341Sstevel 		return (EHC_NO_SLAVE_ACK);
470*1341Sstevel 	}
471*1341Sstevel 
472*1341Sstevel 	return (EHC_SUCCESS);
473*1341Sstevel }
474*1341Sstevel 
475*1341Sstevel static int
ehc_after_read_pcf8584(struct ehc_envcunit * ehcp,uint8_t * data)476*1341Sstevel ehc_after_read_pcf8584(struct ehc_envcunit *ehcp, uint8_t *data)
477*1341Sstevel {
478*1341Sstevel 	uint8_t discard;
479*1341Sstevel 	uint8_t poll_status;
480*1341Sstevel 	int i = 0;
481*1341Sstevel 
482*1341Sstevel 	/* set ACK in register S1 to 0 */
483*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_ES0);
484*1341Sstevel 
485*1341Sstevel 	/*
486*1341Sstevel 	 * Read the "byte-before-the-last-byte" - sets PIN bit to '1'
487*1341Sstevel 	 */
488*1341Sstevel 
489*1341Sstevel 	*data = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
490*1341Sstevel 
491*1341Sstevel 	/* wait for completion of transmission */
492*1341Sstevel 	do {
493*1341Sstevel 		drv_usecwait(1000);
494*1341Sstevel 		poll_status =
495*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
496*1341Sstevel 		i++;
497*1341Sstevel 	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
498*1341Sstevel 
499*1341Sstevel 	if (i == EHC_MAX_WAIT) {
500*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_after_rd_pcf8584(): read of S1 failed");
501*1341Sstevel 		return (EHC_FAILURE);
502*1341Sstevel 	}
503*1341Sstevel 
504*1341Sstevel 	if (poll_status & EHC_S1_BER) {
505*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_after_rd_pcf8584(): Bus error");
506*1341Sstevel 		ehc_init_pcf8584(ehcp);
507*1341Sstevel 		return (EHC_FAILURE);
508*1341Sstevel 	}
509*1341Sstevel 
510*1341Sstevel 	if (poll_status & EHC_S1_LAB) {
511*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_after_rd_pcf8584(): Lost Arbitration");
512*1341Sstevel 		ehc_init_pcf8584(ehcp);
513*1341Sstevel 		return (EHC_FAILURE);
514*1341Sstevel 	}
515*1341Sstevel 
516*1341Sstevel 	/*
517*1341Sstevel 	 * Generate the "stop" condition.
518*1341Sstevel 	 */
519*1341Sstevel 	ehc_stop_pcf8584(ehcp);
520*1341Sstevel 
521*1341Sstevel 	/*
522*1341Sstevel 	 * Read the "last" byte.
523*1341Sstevel 	 */
524*1341Sstevel 	discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
525*1341Sstevel #ifdef lint
526*1341Sstevel 	discard = discard;
527*1341Sstevel #endif
528*1341Sstevel 
529*1341Sstevel 	return (EHC_SUCCESS);
530*1341Sstevel }
531*1341Sstevel 
532*1341Sstevel /*
533*1341Sstevel  * Below this comment are the externally visible routines comprising the API
534*1341Sstevel  */
535*1341Sstevel 
536*1341Sstevel /*
537*1341Sstevel  * Initialize the 8584 chip
538*1341Sstevel  */
539*1341Sstevel 
540*1341Sstevel void
ehc_init_pcf8584(struct ehc_envcunit * ehcp)541*1341Sstevel ehc_init_pcf8584(struct ehc_envcunit *ehcp)
542*1341Sstevel {
543*1341Sstevel 	/*
544*1341Sstevel 	 * Writing PIN bit of S1 causes software reset.
545*1341Sstevel 	 * The next write to S0 will be S0' "own address".
546*1341Sstevel 	 */
547*1341Sstevel 
548*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_PIN);
549*1341Sstevel 
550*1341Sstevel 	/*
551*1341Sstevel 	 * Write the address which the controller chip will use
552*1341Sstevel 	 * (when addressed as a slave) on the I2C bus.
553*1341Sstevel 	 * DAF - should own address be passed as argument?
554*1341Sstevel 	 */
555*1341Sstevel 
556*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, EHC_S0_OWN);
557*1341Sstevel 
558*1341Sstevel 	/*
559*1341Sstevel 	 * Writing PIN bit and ES1 bit of S1 causes software
560*1341Sstevel 	 * reset and selects the S2 register for writing.
561*1341Sstevel 	 * Now, the next write to S0 will be the S2 clock
562*1341Sstevel 	 * control register.
563*1341Sstevel 	 */
564*1341Sstevel 
565*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
566*1341Sstevel 		EHC_S1_PIN | EHC_S1_ES1);
567*1341Sstevel 
568*1341Sstevel 	/*
569*1341Sstevel 	 * Write the value into register that sets internal system clock
570*1341Sstevel 	 * to 12 Mhz, and the I2C bus rate (SCL) to 9 Khz.
571*1341Sstevel 	 * DAF - should these be parameters?
572*1341Sstevel 	 */
573*1341Sstevel 
574*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, EHC_S0_CLK);
575*1341Sstevel 
576*1341Sstevel 	/*
577*1341Sstevel 	 * Writing PIN bit causes software reset and the ES0 bit
578*1341Sstevel 	 * selects the (S0) register for reading/writing.  The ACK
579*1341Sstevel 	 * bit being set causes controller to send ACK after each
580*1341Sstevel 	 * byte.
581*1341Sstevel 	 */
582*1341Sstevel 
583*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
584*1341Sstevel 		EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_ACK);
585*1341Sstevel 
586*1341Sstevel 	/*
587*1341Sstevel 	 * Multi-Master: Wait for a period of time equal to the
588*1341Sstevel 	 * longest I2C message.  This accounts for the case
589*1341Sstevel 	 * where multiple controllers and, if this particular one
590*1341Sstevel 	 * is "lagging", misses the BB (bus busy) condition.
591*1341Sstevel 	 * DAF - What does this need?
592*1341Sstevel 	 * We wait 200 ms since the longest transaction at this time
593*1341Sstevel 	 * on the i2c bus is a 256 byte read from the seprom which takes
594*1341Sstevel 	 * about 75 ms. Some additional buffer does no harm to the driver.
595*1341Sstevel 	 */
596*1341Sstevel 
597*1341Sstevel 	drv_usecwait(EHC_LONGEST_MSG);
598*1341Sstevel 
599*1341Sstevel }
600*1341Sstevel 
601*1341Sstevel int
ehc_read_tda8444(struct ehc_envcunit * ehcp)602*1341Sstevel ehc_read_tda8444(struct ehc_envcunit *ehcp)
603*1341Sstevel {
604*1341Sstevel #ifdef lint
605*1341Sstevel 	ehcp = ehcp;
606*1341Sstevel #endif
607*1341Sstevel 	return (EHC_FAILURE);
608*1341Sstevel }
609*1341Sstevel 
610*1341Sstevel /*
611*1341Sstevel  * Write to the TDA8444 chip.
612*1341Sstevel  * byteaddress = chip type base address | chip offset address.
613*1341Sstevel  */
614*1341Sstevel int
ehc_write_tda8444(struct ehc_envcunit * ehcp,int byteaddress,int instruction,int subaddress,uint8_t * buf,int size)615*1341Sstevel ehc_write_tda8444(struct ehc_envcunit *ehcp, int byteaddress, int instruction,
616*1341Sstevel 	int subaddress, uint8_t *buf, int size)
617*1341Sstevel {
618*1341Sstevel 	uint8_t control;
619*1341Sstevel 	int i, status;
620*1341Sstevel 
621*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
622*1341Sstevel 	ASSERT(subaddress < 8);
623*1341Sstevel 	ASSERT(instruction == 0xf || instruction == 0x0);
624*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
625*1341Sstevel 
626*1341Sstevel 	control = (instruction << 4) | subaddress;
627*1341Sstevel 
628*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
629*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
630*1341Sstevel 			/*
631*1341Sstevel 			 * Send the "stop" condition.
632*1341Sstevel 			 */
633*1341Sstevel 			ehc_stop_pcf8584(ehcp);
634*1341Sstevel 		}
635*1341Sstevel 		return (EHC_FAILURE);
636*1341Sstevel 	}
637*1341Sstevel 
638*1341Sstevel 	if ((status = ehc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
639*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
640*1341Sstevel 			/*
641*1341Sstevel 			 * Send the "stop" condition.
642*1341Sstevel 			 */
643*1341Sstevel 			ehc_stop_pcf8584(ehcp);
644*1341Sstevel 		}
645*1341Sstevel 		return (EHC_FAILURE);
646*1341Sstevel 	}
647*1341Sstevel 
648*1341Sstevel 	for (i = 0; i < size; i++) {
649*1341Sstevel 		if ((status = ehc_write_pcf8584(ehcp, (buf[i] & 0x3f))) !=
650*1341Sstevel 			EHC_SUCCESS) {
651*1341Sstevel 			if (status == EHC_NO_SLAVE_ACK)
652*1341Sstevel 				ehc_stop_pcf8584(ehcp);
653*1341Sstevel 			return (EHC_FAILURE);
654*1341Sstevel 		}
655*1341Sstevel 	}
656*1341Sstevel 
657*1341Sstevel 	ehc_stop_pcf8584(ehcp);
658*1341Sstevel 
659*1341Sstevel 	return (EHC_SUCCESS);
660*1341Sstevel }
661*1341Sstevel 
662*1341Sstevel /*
663*1341Sstevel  * Read from PCF8574A chip.
664*1341Sstevel  * byteaddress = chip type base address | chip offset address.
665*1341Sstevel  */
666*1341Sstevel int
ehc_read_pcf8574a(struct ehc_envcunit * ehcp,int byteaddress,uint8_t * buf,int size)667*1341Sstevel ehc_read_pcf8574a(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
668*1341Sstevel 	int size)
669*1341Sstevel {
670*1341Sstevel 	int i;
671*1341Sstevel 	int status;
672*1341Sstevel 	uint8_t discard;
673*1341Sstevel 
674*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
675*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
676*1341Sstevel 
677*1341Sstevel 	/*
678*1341Sstevel 	 * Put the bus into the start condition
679*1341Sstevel 	 */
680*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
681*1341Sstevel 			EHC_SUCCESS) {
682*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
683*1341Sstevel 			/*
684*1341Sstevel 			 * Send the "stop" condition.
685*1341Sstevel 			 */
686*1341Sstevel 			ehc_stop_pcf8584(ehcp);
687*1341Sstevel 			/*
688*1341Sstevel 			 * Read the last byte - discard it.
689*1341Sstevel 			 */
690*1341Sstevel 			discard =
691*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
692*1341Sstevel #ifdef lint
693*1341Sstevel 			discard = discard;
694*1341Sstevel #endif
695*1341Sstevel 		}
696*1341Sstevel 		return (EHC_FAILURE);
697*1341Sstevel 	}
698*1341Sstevel 
699*1341Sstevel 	for (i = 0; i < size - 1; i++) {
700*1341Sstevel 		if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
701*1341Sstevel 			return (EHC_FAILURE);
702*1341Sstevel 		}
703*1341Sstevel 	}
704*1341Sstevel 
705*1341Sstevel 	/*
706*1341Sstevel 	 * Handle the part of the bus protocol which comes
707*1341Sstevel 	 * after a read, including reading the last byte.
708*1341Sstevel 	 */
709*1341Sstevel 
710*1341Sstevel 	if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
711*1341Sstevel 		return (EHC_FAILURE);
712*1341Sstevel 	}
713*1341Sstevel 
714*1341Sstevel 	return (EHC_SUCCESS);
715*1341Sstevel }
716*1341Sstevel 
717*1341Sstevel /*
718*1341Sstevel  * Write to the PCF8574A chip.
719*1341Sstevel  * byteaddress = chip type base address | chip offset address.
720*1341Sstevel  */
721*1341Sstevel int
ehc_write_pcf8574a(struct ehc_envcunit * ehcp,int byteaddress,uint8_t * buf,int size)722*1341Sstevel ehc_write_pcf8574a(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
723*1341Sstevel 	int size)
724*1341Sstevel {
725*1341Sstevel 	int i;
726*1341Sstevel 	int status;
727*1341Sstevel 
728*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
729*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
730*1341Sstevel 
731*1341Sstevel 	/*
732*1341Sstevel 	 * Put the bus into the start condition (write)
733*1341Sstevel 	 */
734*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
735*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
736*1341Sstevel 			/*
737*1341Sstevel 			 * Send the "stop" condition.
738*1341Sstevel 			 */
739*1341Sstevel 			ehc_stop_pcf8584(ehcp);
740*1341Sstevel 		}
741*1341Sstevel 		return (EHC_FAILURE);
742*1341Sstevel 	}
743*1341Sstevel 
744*1341Sstevel 	/*
745*1341Sstevel 	 * Send the data - poll as needed.
746*1341Sstevel 	 */
747*1341Sstevel 	for (i = 0; i < size; i++) {
748*1341Sstevel 		if ((status = ehc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
749*1341Sstevel 			if (status == EHC_NO_SLAVE_ACK)
750*1341Sstevel 				ehc_stop_pcf8584(ehcp);
751*1341Sstevel 			return (EHC_FAILURE);
752*1341Sstevel 		}
753*1341Sstevel 	}
754*1341Sstevel 
755*1341Sstevel 	/*
756*1341Sstevel 	 * Transmission complete - generate stop condition and
757*1341Sstevel 	 * put device back into slave receiver mode.
758*1341Sstevel 	 */
759*1341Sstevel 	ehc_stop_pcf8584(ehcp);
760*1341Sstevel 
761*1341Sstevel 	return (EHC_SUCCESS);
762*1341Sstevel }
763*1341Sstevel 
764*1341Sstevel /*
765*1341Sstevel  * Read from the PCF8574 chip.
766*1341Sstevel  * byteaddress = chip type base address | chip offset address.
767*1341Sstevel  */
768*1341Sstevel int
ehc_read_pcf8574(struct ehc_envcunit * ehcp,int byteaddress,uint8_t * buf,int size)769*1341Sstevel ehc_read_pcf8574(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
770*1341Sstevel 	int size)
771*1341Sstevel {
772*1341Sstevel 	int i;
773*1341Sstevel 	int status;
774*1341Sstevel 	uint8_t discard;
775*1341Sstevel 
776*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
777*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
778*1341Sstevel 
779*1341Sstevel 	/*
780*1341Sstevel 	 * Put the bus into the start condition
781*1341Sstevel 	 */
782*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
783*1341Sstevel 			EHC_SUCCESS) {
784*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
785*1341Sstevel 			/*
786*1341Sstevel 			 * Send the "stop" condition.
787*1341Sstevel 			 */
788*1341Sstevel 			ehc_stop_pcf8584(ehcp);
789*1341Sstevel 			/*
790*1341Sstevel 			 * Read the last byte - discard it.
791*1341Sstevel 			 */
792*1341Sstevel 			discard =
793*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
794*1341Sstevel #ifdef lint
795*1341Sstevel 			discard = discard;
796*1341Sstevel #endif
797*1341Sstevel 		}
798*1341Sstevel 		return (EHC_FAILURE);
799*1341Sstevel 	}
800*1341Sstevel 
801*1341Sstevel 	for (i = 0; i < size - 1; i++) {
802*1341Sstevel 		if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
803*1341Sstevel 		return (EHC_FAILURE);
804*1341Sstevel 		}
805*1341Sstevel 	}
806*1341Sstevel 
807*1341Sstevel 	/*
808*1341Sstevel 	 * Handle the part of the bus protocol which comes
809*1341Sstevel 	 * after a read.
810*1341Sstevel 	 */
811*1341Sstevel 
812*1341Sstevel 	if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
813*1341Sstevel 		return (EHC_FAILURE);
814*1341Sstevel 	}
815*1341Sstevel 
816*1341Sstevel 	return (EHC_SUCCESS);
817*1341Sstevel }
818*1341Sstevel 
819*1341Sstevel /*
820*1341Sstevel  * Write to the PCF8574 chip.
821*1341Sstevel  * byteaddress = chip type base address | chip offset address.
822*1341Sstevel  */
823*1341Sstevel int
ehc_write_pcf8574(struct ehc_envcunit * ehcp,int byteaddress,uint8_t * buf,int size)824*1341Sstevel ehc_write_pcf8574(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
825*1341Sstevel 	int size)
826*1341Sstevel {
827*1341Sstevel 	int i;
828*1341Sstevel 	int status;
829*1341Sstevel 
830*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
831*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
832*1341Sstevel 
833*1341Sstevel 	/*
834*1341Sstevel 	 * Put the bus into the start condition (write)
835*1341Sstevel 	 */
836*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
837*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
838*1341Sstevel 			/*
839*1341Sstevel 			 * Send the "stop" condition.
840*1341Sstevel 			 */
841*1341Sstevel 			ehc_stop_pcf8584(ehcp);
842*1341Sstevel 		}
843*1341Sstevel 		return (EHC_FAILURE);
844*1341Sstevel 	}
845*1341Sstevel 
846*1341Sstevel 	/*
847*1341Sstevel 	 * Send the data - poll as needed.
848*1341Sstevel 	 */
849*1341Sstevel 	for (i = 0; i < size; i++) {
850*1341Sstevel 		if ((status = ehc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
851*1341Sstevel 			if (status == EHC_NO_SLAVE_ACK)
852*1341Sstevel 				ehc_stop_pcf8584(ehcp);
853*1341Sstevel 			return (EHC_FAILURE);
854*1341Sstevel 		}
855*1341Sstevel 	}
856*1341Sstevel 	/*
857*1341Sstevel 	 * Transmission complete - generate stop condition and
858*1341Sstevel 	 * put device back into slave receiver mode.
859*1341Sstevel 	 */
860*1341Sstevel 	ehc_stop_pcf8584(ehcp);
861*1341Sstevel 
862*1341Sstevel 	return (EHC_SUCCESS);
863*1341Sstevel }
864*1341Sstevel 
865*1341Sstevel /*
866*1341Sstevel  * Read from the LM75
867*1341Sstevel  * byteaddress = chip type base address | chip offset address.
868*1341Sstevel  */
869*1341Sstevel int
ehc_read_lm75(struct ehc_envcunit * ehcp,int byteaddress,uint8_t * buf,int size)870*1341Sstevel ehc_read_lm75(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
871*1341Sstevel 	int size)
872*1341Sstevel {
873*1341Sstevel 	int i;
874*1341Sstevel 	int status;
875*1341Sstevel 	uint8_t discard;
876*1341Sstevel 
877*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
878*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
879*1341Sstevel 
880*1341Sstevel 	/*
881*1341Sstevel 	 * Put the bus into the start condition
882*1341Sstevel 	 */
883*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
884*1341Sstevel 			EHC_SUCCESS) {
885*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
886*1341Sstevel 			/*
887*1341Sstevel 			 * Send the stop condition.
888*1341Sstevel 			 */
889*1341Sstevel 			ehc_stop_pcf8584(ehcp);
890*1341Sstevel 			/*
891*1341Sstevel 			 * Read the last byte - discard it.
892*1341Sstevel 			 */
893*1341Sstevel 			discard =
894*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
895*1341Sstevel #ifdef lint
896*1341Sstevel 			discard = discard;
897*1341Sstevel #endif
898*1341Sstevel 		}
899*1341Sstevel 		return (EHC_FAILURE);
900*1341Sstevel 	}
901*1341Sstevel 
902*1341Sstevel 	for (i = 0; i < size - 1; i++) {
903*1341Sstevel 		if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
904*1341Sstevel 			return (EHC_FAILURE);
905*1341Sstevel 		}
906*1341Sstevel 	}
907*1341Sstevel 
908*1341Sstevel 	/*
909*1341Sstevel 	 * Handle the part of the bus protocol which comes
910*1341Sstevel 	 * after a read.
911*1341Sstevel 	 */
912*1341Sstevel 	if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
913*1341Sstevel 		return (EHC_FAILURE);
914*1341Sstevel 	}
915*1341Sstevel 
916*1341Sstevel 	return (EHC_SUCCESS);
917*1341Sstevel }
918*1341Sstevel 
919*1341Sstevel /*
920*1341Sstevel  * Write to the PCF8583 chip.
921*1341Sstevel  * byteaddress = chip type base address | chip offset address.
922*1341Sstevel  */
923*1341Sstevel int
ehc_write_pcf8583(struct ehc_envcunit * ehcp,int byteaddress,uint8_t * buf,int size)924*1341Sstevel ehc_write_pcf8583(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf,
925*1341Sstevel 	int size)
926*1341Sstevel {
927*1341Sstevel 	int i;
928*1341Sstevel 	int status;
929*1341Sstevel 
930*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
931*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
932*1341Sstevel 
933*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
934*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
935*1341Sstevel 			/*
936*1341Sstevel 			 * Send the "stop" condition.
937*1341Sstevel 			 */
938*1341Sstevel 			ehc_stop_pcf8584(ehcp);
939*1341Sstevel 		}
940*1341Sstevel 		return (EHC_FAILURE);
941*1341Sstevel 	}
942*1341Sstevel 
943*1341Sstevel 	/*
944*1341Sstevel 	 * Send the data - poll as needed.
945*1341Sstevel 	 */
946*1341Sstevel 	for (i = 0; i < size; i++) {
947*1341Sstevel 		if ((status = ehc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
948*1341Sstevel 			if (status == EHC_NO_SLAVE_ACK)
949*1341Sstevel 				ehc_stop_pcf8584(ehcp);
950*1341Sstevel 			return (EHC_FAILURE);
951*1341Sstevel 		}
952*1341Sstevel 	}
953*1341Sstevel 
954*1341Sstevel 	/*
955*1341Sstevel 	 * Transmission complete - generate stop condition and
956*1341Sstevel 	 * put device back into slave receiver mode.
957*1341Sstevel 	 */
958*1341Sstevel 	ehc_stop_pcf8584(ehcp);
959*1341Sstevel 
960*1341Sstevel 	return (EHC_SUCCESS);
961*1341Sstevel }
962*1341Sstevel 
963*1341Sstevel /*
964*1341Sstevel  * Read from the PCF8591 chip.
965*1341Sstevel  */
966*1341Sstevel int
ehc_read_pcf8591(struct ehc_envcunit * ehcp,int byteaddress,int channel,int autoinc,int amode,int aenable,uint8_t * buf,int size)967*1341Sstevel ehc_read_pcf8591(struct ehc_envcunit *ehcp, int byteaddress, int channel,
968*1341Sstevel 	int autoinc, int amode, int aenable,  uint8_t *buf, int size)
969*1341Sstevel {
970*1341Sstevel 	int i;
971*1341Sstevel 	int status;
972*1341Sstevel 	register uint8_t control;
973*1341Sstevel 	uint8_t discard;
974*1341Sstevel 
975*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
976*1341Sstevel 	ASSERT(channel < 4);
977*1341Sstevel 	ASSERT(amode < 4);
978*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
979*1341Sstevel 
980*1341Sstevel 	/*
981*1341Sstevel 	 * Write the control word to the PCF8591.
982*1341Sstevel 	 * Follow the control word with a repeated START byte
983*1341Sstevel 	 * rather than a STOP so that reads can follow without giving
984*1341Sstevel 	 * up the bus.
985*1341Sstevel 	 */
986*1341Sstevel 
987*1341Sstevel 	control = ((aenable << 6) | (amode << 4) | (autoinc << 2) | channel);
988*1341Sstevel 
989*1341Sstevel 	if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
990*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
991*1341Sstevel 			ehc_stop_pcf8584(ehcp);
992*1341Sstevel 		}
993*1341Sstevel 		return (EHC_FAILURE);
994*1341Sstevel 	}
995*1341Sstevel 
996*1341Sstevel 	if ((status = ehc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
997*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK)
998*1341Sstevel 			ehc_stop_pcf8584(ehcp);
999*1341Sstevel 		return (EHC_FAILURE);
1000*1341Sstevel 	}
1001*1341Sstevel 
1002*1341Sstevel 	/*
1003*1341Sstevel 	 * The following two operations, 0x45 to S1, and the byteaddress
1004*1341Sstevel 	 * to S0, will result in a repeated START being sent out on the bus.
1005*1341Sstevel 	 * Refer to Fig.8 of Philips Semiconductors PCF8584 product spec.
1006*1341Sstevel 	 */
1007*1341Sstevel 
1008*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
1009*1341Sstevel 		EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
1010*1341Sstevel 
1011*1341Sstevel 	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0,
1012*1341Sstevel 		EHC_BYTE_READ | byteaddress);
1013*1341Sstevel 
1014*1341Sstevel 	i = 0;
1015*1341Sstevel 
1016*1341Sstevel 	do {
1017*1341Sstevel 		drv_usecwait(1000);
1018*1341Sstevel 		status =
1019*1341Sstevel 			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
1020*1341Sstevel 		i++;
1021*1341Sstevel 	} while ((status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
1022*1341Sstevel 
1023*1341Sstevel 	if (i == EHC_MAX_WAIT) {
1024*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_read_pcf8591(): read of S1 failed");
1025*1341Sstevel 		return (EHC_FAILURE);
1026*1341Sstevel 	}
1027*1341Sstevel 
1028*1341Sstevel 	if (status & EHC_S1_BER) {
1029*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_read_pcf8591(): Bus error");
1030*1341Sstevel 		ehc_init_pcf8584(ehcp);
1031*1341Sstevel 		return (EHC_FAILURE);
1032*1341Sstevel 	}
1033*1341Sstevel 
1034*1341Sstevel 	if (status & EHC_S1_LAB) {
1035*1341Sstevel 		DCMN2_ERR(CE_WARN, "ehc_read_pcf8591(): Lost Arbitration");
1036*1341Sstevel 		ehc_init_pcf8584(ehcp);
1037*1341Sstevel 		return (EHC_FAILURE);
1038*1341Sstevel 	}
1039*1341Sstevel 
1040*1341Sstevel 	if (status & EHC_S1_LRB) {
1041*1341Sstevel 		DCMN_ERR(CE_WARN, "ehc_read_pcf8591(): No slave ACK");
1042*1341Sstevel 		/*
1043*1341Sstevel 		 * Send the stop condition.
1044*1341Sstevel 		 */
1045*1341Sstevel 		ehc_stop_pcf8584(ehcp);
1046*1341Sstevel 		/*
1047*1341Sstevel 		 * Read the last byte - discard it.
1048*1341Sstevel 		 */
1049*1341Sstevel 		discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
1050*1341Sstevel #ifdef lint
1051*1341Sstevel 		discard = discard;
1052*1341Sstevel #endif
1053*1341Sstevel 		return (EHC_FAILURE);
1054*1341Sstevel 	}
1055*1341Sstevel 
1056*1341Sstevel 	/*
1057*1341Sstevel 	 * Discard first read as per PCF8584 master receiver protocol.
1058*1341Sstevel 	 * This is normally done in the ehc_start_pcf8584() routine.
1059*1341Sstevel 	 */
1060*1341Sstevel 	if ((status = ehc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) {
1061*1341Sstevel 		return (EHC_FAILURE);
1062*1341Sstevel 	}
1063*1341Sstevel 
1064*1341Sstevel 	/* Discard second read as per PCF8591 protocol */
1065*1341Sstevel 	if ((status = ehc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) {
1066*1341Sstevel 		return (EHC_FAILURE);
1067*1341Sstevel 	}
1068*1341Sstevel 
1069*1341Sstevel 	for (i = 0; i < size - 1; i++) {
1070*1341Sstevel 		if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
1071*1341Sstevel 			return (EHC_FAILURE);
1072*1341Sstevel 		}
1073*1341Sstevel 	}
1074*1341Sstevel 
1075*1341Sstevel 	if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
1076*1341Sstevel 		return (EHC_FAILURE);
1077*1341Sstevel 	}
1078*1341Sstevel 
1079*1341Sstevel 	return (EHC_SUCCESS);
1080*1341Sstevel }
1081*1341Sstevel 
1082*1341Sstevel /*
1083*1341Sstevel  * Write to the PCF8591 chip.
1084*1341Sstevel  * byteaddress = chip type base address | chip offset address.
1085*1341Sstevel  */
1086*1341Sstevel int
ehc_write_pcf8591(struct ehc_envcunit * ehcp,int byteaddress,int channel,int autoinc,int amode,int aenable,uint8_t * buf,int size)1087*1341Sstevel ehc_write_pcf8591(struct ehc_envcunit *ehcp, int byteaddress, int channel,
1088*1341Sstevel 	int autoinc, int amode, int aenable, uint8_t *buf, int size)
1089*1341Sstevel {
1090*1341Sstevel 	int i, status;
1091*1341Sstevel 	register uint8_t control;
1092*1341Sstevel 
1093*1341Sstevel 	ASSERT((byteaddress & 0x1) == 0);
1094*1341Sstevel 	ASSERT(MUTEX_HELD(&ehcp->umutex));
1095*1341Sstevel 
1096*1341Sstevel 	control = ((aenable << 6) | (amode << 4) | (autoinc << 2) | channel);
1097*1341Sstevel 
1098*1341Sstevel 	status = ehc_start_pcf8584(ehcp, byteaddress);
1099*1341Sstevel 	if (status != EHC_SUCCESS) {
1100*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK) {
1101*1341Sstevel 			/*
1102*1341Sstevel 			 * Send the "stop" condition.
1103*1341Sstevel 			 */
1104*1341Sstevel 			ehc_stop_pcf8584(ehcp);
1105*1341Sstevel 		}
1106*1341Sstevel 		return (EHC_FAILURE);
1107*1341Sstevel 	}
1108*1341Sstevel 
1109*1341Sstevel 	if ((status = ehc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
1110*1341Sstevel 		if (status == EHC_NO_SLAVE_ACK)
1111*1341Sstevel 			ehc_stop_pcf8584(ehcp);
1112*1341Sstevel 		return (EHC_FAILURE);
1113*1341Sstevel 	}
1114*1341Sstevel 
1115*1341Sstevel 	for (i = 0; i < size; i++) {
1116*1341Sstevel 		status = ehc_write_pcf8584(ehcp, buf[i]);
1117*1341Sstevel 		if (status != EHC_SUCCESS) {
1118*1341Sstevel 			if (status == EHC_NO_SLAVE_ACK)
1119*1341Sstevel 				ehc_stop_pcf8584(ehcp);
1120*1341Sstevel 			return (EHC_FAILURE);
1121*1341Sstevel 		}
1122*1341Sstevel 	}
1123*1341Sstevel 
1124*1341Sstevel 	ehc_stop_pcf8584(ehcp);
1125*1341Sstevel 
1126*1341Sstevel 	return (EHC_SUCCESS);
1127*1341Sstevel }
1128