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