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