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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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