1e0efc557SJoerg Wunsch /*- 2e0efc557SJoerg Wunsch * Copyright (c) 1998 Nicolas Souchu, Marc Bouget 3e0efc557SJoerg Wunsch * Copyright (c) 2004 Joerg Wunsch 4e0efc557SJoerg Wunsch * All rights reserved. 5e0efc557SJoerg Wunsch * 6e0efc557SJoerg Wunsch * Redistribution and use in source and binary forms, with or without 7e0efc557SJoerg Wunsch * modification, are permitted provided that the following conditions 8e0efc557SJoerg Wunsch * are met: 9e0efc557SJoerg Wunsch * 1. Redistributions of source code must retain the above copyright 10e0efc557SJoerg Wunsch * notice, this list of conditions and the following disclaimer. 11e0efc557SJoerg Wunsch * 2. Redistributions in binary form must reproduce the above copyright 12e0efc557SJoerg Wunsch * notice, this list of conditions and the following disclaimer in the 13e0efc557SJoerg Wunsch * documentation and/or other materials provided with the distribution. 14e0efc557SJoerg Wunsch * 15e0efc557SJoerg Wunsch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16e0efc557SJoerg Wunsch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e0efc557SJoerg Wunsch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18e0efc557SJoerg Wunsch * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19e0efc557SJoerg Wunsch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e0efc557SJoerg Wunsch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e0efc557SJoerg Wunsch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e0efc557SJoerg Wunsch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e0efc557SJoerg Wunsch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e0efc557SJoerg Wunsch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e0efc557SJoerg Wunsch * SUCH DAMAGE. 26e0efc557SJoerg Wunsch * 27e0efc557SJoerg Wunsch * $FreeBSD$ 28e0efc557SJoerg Wunsch */ 29e0efc557SJoerg Wunsch 30e0efc557SJoerg Wunsch #define IO_PCFSIZE 2 31e0efc557SJoerg Wunsch 32e0efc557SJoerg Wunsch #define TIMEOUT 9999 /* XXX */ 33e0efc557SJoerg Wunsch 34e0efc557SJoerg Wunsch /* Status bits of S1 register (read only) */ 35e0efc557SJoerg Wunsch #define nBB 0x01 /* busy when low set/reset by STOP/START*/ 36e0efc557SJoerg Wunsch #define LAB 0x02 /* lost arbitration bit in multi-master mode */ 37e0efc557SJoerg Wunsch #define AAS 0x04 /* addressed as slave */ 38e0efc557SJoerg Wunsch #define LRB 0x08 /* last received byte when not AAS */ 39e0efc557SJoerg Wunsch #define AD0 0x08 /* general call received when AAS */ 40e0efc557SJoerg Wunsch #define BER 0x10 /* bus error, misplaced START or STOP */ 41e0efc557SJoerg Wunsch #define STS 0x20 /* STOP detected in slave receiver mode */ 42e0efc557SJoerg Wunsch #define PIN 0x80 /* pending interrupt not (r/w) */ 43e0efc557SJoerg Wunsch 44e0efc557SJoerg Wunsch /* Control bits of S1 register (write only) */ 45e0efc557SJoerg Wunsch #define ACK 0x01 46e0efc557SJoerg Wunsch #define STO 0x02 47e0efc557SJoerg Wunsch #define STA 0x04 48e0efc557SJoerg Wunsch #define ENI 0x08 49e0efc557SJoerg Wunsch #define ES2 0x10 50e0efc557SJoerg Wunsch #define ES1 0x20 51e0efc557SJoerg Wunsch #define ESO 0x40 52e0efc557SJoerg Wunsch 53e0efc557SJoerg Wunsch #define BUFSIZE 2048 54e0efc557SJoerg Wunsch 55e0efc557SJoerg Wunsch #define SLAVE_TRANSMITTER 0x1 56e0efc557SJoerg Wunsch #define SLAVE_RECEIVER 0x2 57e0efc557SJoerg Wunsch 58e0efc557SJoerg Wunsch #define PCF_DEFAULT_ADDR 0xaa 59e0efc557SJoerg Wunsch 60e0efc557SJoerg Wunsch struct pcf_softc { 61e0efc557SJoerg Wunsch u_char pcf_addr; /* interface I2C address */ 62e0efc557SJoerg Wunsch int pcf_flags; /* IIC_POLLED? */ 63e0efc557SJoerg Wunsch int pcf_slave_mode; /* receiver or transmitter */ 64e0efc557SJoerg Wunsch int pcf_started; /* 1 if start condition sent */ 65e0efc557SJoerg Wunsch 66e0efc557SJoerg Wunsch device_t iicbus; /* the corresponding iicbus */ 67e0efc557SJoerg Wunsch 68e0efc557SJoerg Wunsch /* Resource handling stuff. */ 69e0efc557SJoerg Wunsch void *intr_cookie; 70e0efc557SJoerg Wunsch int rid_ioport; 71e0efc557SJoerg Wunsch int rid_irq; 72e0efc557SJoerg Wunsch struct resource *res_ioport; 73e0efc557SJoerg Wunsch struct resource *res_irq; 74e0efc557SJoerg Wunsch }; 75e0efc557SJoerg Wunsch #define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev)) 76e0efc557SJoerg Wunsch 77e0efc557SJoerg Wunsch /* 78e0efc557SJoerg Wunsch * PCF8584 datasheet : when operate at 8 MHz or more, a minimun time of 79e0efc557SJoerg Wunsch * 6 clocks cycles must be left between two consecutives access 80e0efc557SJoerg Wunsch */ 81e0efc557SJoerg Wunsch #define pcf_nops() DELAY(10) 82e0efc557SJoerg Wunsch 83e0efc557SJoerg Wunsch #define dummy_read(sc) pcf_get_S0(sc) 84e0efc557SJoerg Wunsch #define dummy_write(sc) pcf_set_S0(sc, 0) 85e0efc557SJoerg Wunsch 86e0efc557SJoerg Wunsch /* 87e0efc557SJoerg Wunsch * Specific register access to PCF8584 88e0efc557SJoerg Wunsch */ 89e0efc557SJoerg Wunsch static __inline__ void 90e0efc557SJoerg Wunsch pcf_set_S0(struct pcf_softc *sc, int data) 91e0efc557SJoerg Wunsch { 92e0efc557SJoerg Wunsch bus_space_write_1(sc->res_ioport->r_bustag, 93e0efc557SJoerg Wunsch sc->res_ioport->r_bushandle, 94e0efc557SJoerg Wunsch 0, data); 95e0efc557SJoerg Wunsch pcf_nops(); 96e0efc557SJoerg Wunsch } 97e0efc557SJoerg Wunsch 98e0efc557SJoerg Wunsch static __inline__ void 99e0efc557SJoerg Wunsch pcf_set_S1(struct pcf_softc *sc, int data) 100e0efc557SJoerg Wunsch { 101e0efc557SJoerg Wunsch bus_space_write_1(sc->res_ioport->r_bustag, 102e0efc557SJoerg Wunsch sc->res_ioport->r_bushandle, 103e0efc557SJoerg Wunsch 1, data); 104e0efc557SJoerg Wunsch pcf_nops(); 105e0efc557SJoerg Wunsch } 106e0efc557SJoerg Wunsch 107e0efc557SJoerg Wunsch static __inline__ char 108e0efc557SJoerg Wunsch pcf_get_S0(struct pcf_softc *sc) 109e0efc557SJoerg Wunsch { 110e0efc557SJoerg Wunsch char data; 111e0efc557SJoerg Wunsch 112e0efc557SJoerg Wunsch data = bus_space_read_1(sc->res_ioport->r_bustag, 113e0efc557SJoerg Wunsch sc->res_ioport->r_bushandle, 0); 114e0efc557SJoerg Wunsch pcf_nops(); 115e0efc557SJoerg Wunsch 116e0efc557SJoerg Wunsch return (data); 117e0efc557SJoerg Wunsch } 118e0efc557SJoerg Wunsch 119e0efc557SJoerg Wunsch static __inline__ char 120e0efc557SJoerg Wunsch pcf_get_S1(struct pcf_softc *sc) 121e0efc557SJoerg Wunsch { 122e0efc557SJoerg Wunsch char data; 123e0efc557SJoerg Wunsch 124e0efc557SJoerg Wunsch data = bus_space_read_1(sc->res_ioport->r_bustag, 125e0efc557SJoerg Wunsch sc->res_ioport->r_bushandle, 1); 126e0efc557SJoerg Wunsch pcf_nops(); 127e0efc557SJoerg Wunsch 128e0efc557SJoerg Wunsch return (data); 129e0efc557SJoerg Wunsch } 130e0efc557SJoerg Wunsch 131e0efc557SJoerg Wunsch extern int pcf_repeated_start(device_t, u_char, int); 132e0efc557SJoerg Wunsch extern int pcf_start(device_t, u_char, int); 133e0efc557SJoerg Wunsch extern int pcf_stop(device_t); 134e0efc557SJoerg Wunsch extern int pcf_write(device_t, char *, int, int *, int); 135e0efc557SJoerg Wunsch extern int pcf_read(device_t, char *, int, int *, int, int); 136e0efc557SJoerg Wunsch extern int pcf_rst_card(device_t, u_char, u_char, u_char *); 137e0efc557SJoerg Wunsch extern driver_intr_t pcf_intr; 138e0efc557SJoerg Wunsch 139e0efc557SJoerg Wunsch #define PCF_MODVER 1 140e0efc557SJoerg Wunsch #define PCF_MINVER 1 141e0efc557SJoerg Wunsch #define PCF_MAXVER 1 142e0efc557SJoerg Wunsch #define PCF_PREFVER PCF_MODVER 143