summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/files.i3862
-rw-r--r--sys/conf/files.sparc642
-rw-r--r--sys/i386/isa/pcf.c633
-rw-r--r--sys/modules/Makefile1
-rw-r--r--sys/modules/i2c/controllers/pcf/Makefile11
6 files changed, 15 insertions, 635 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 14d18d9..8ca7082 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -763,6 +763,7 @@ dev/pccard/power_if.m standard
dev/pccbb/pccbb.c optional cbb
dev/pccbb/pccbb_isa.c optional cbb isa
dev/pccbb/pccbb_pci.c optional cbb pci
+dev/pcf/pcf.c optional pcf
dev/pci/eisa_pci.c optional pci eisa
dev/pci/fixup_pci.c optional pci
dev/pci/ignore_pci.c optional pci
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index e9d6597..4be8226 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -199,6 +199,7 @@ dev/mem/memutil.c optional mem
dev/mse/mse.c optional mse
dev/mse/mse_isa.c optional mse isa
dev/nve/if_nve.c optional nve pci
+dev/pcf/pcf_isa.c optional pcf
dev/ppc/ppc.c optional ppc
dev/ppc/ppc_puc.c optional ppc puc pci
dev/random/nehemiah.c optional random
@@ -325,7 +326,6 @@ i386/isa/isa.c optional isa
i386/isa/isa_dma.c optional isa
i386/isa/nmi.c standard
i386/isa/npx.c optional npx
-i386/isa/pcf.c optional pcf
i386/isa/pcvt/pcvt_drv.c optional vt
i386/isa/pcvt/pcvt_ext.c optional vt
i386/isa/pcvt/pcvt_kbd.c optional vt
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 47b1341..470cd2c 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -46,6 +46,8 @@ dev/ofw/ofw_console.c optional ofw_console
dev/ofw/openfirm.c standard
dev/ofw/openfirmio.c standard
dev/ofw/openpromio.c standard
+dev/pcf/envctrl.c optional pcf
+dev/pcf/pcf_ebus.c optional pcf ebus
dev/sound/sbus/cs4231.c optional snd_audiocs ebus
dev/sound/sbus/cs4231.c optional snd_audiocs sbus
dev/syscons/scgfbrndr.c optional sc
diff --git a/sys/i386/isa/pcf.c b/sys/i386/isa/pcf.c
deleted file mode 100644
index 10ef4ff..0000000
--- a/sys/i386/isa/pcf.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/*-
- * Copyright (c) 1998 Nicolas Souchu, Marc Bouget
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
-#include <isa/isareg.h>
-#include <isa/isavar.h>
-
-#include <dev/iicbus/iiconf.h>
-#include "iicbus_if.h"
-
-#define IO_PCFSIZE 2
-
-#define TIMEOUT 9999 /* XXX */
-
-/* Status bits of S1 register (read only) */
-#define nBB 0x01 /* busy when low set/reset by STOP/START*/
-#define LAB 0x02 /* lost arbitration bit in multi-master mode */
-#define AAS 0x04 /* addressed as slave */
-#define LRB 0x08 /* last received byte when not AAS */
-#define AD0 0x08 /* general call received when AAS */
-#define BER 0x10 /* bus error, misplaced START or STOP */
-#define STS 0x20 /* STOP detected in slave receiver mode */
-#define PIN 0x80 /* pending interrupt not (r/w) */
-
-/* Control bits of S1 register (write only) */
-#define ACK 0x01
-#define STO 0x02
-#define STA 0x04
-#define ENI 0x08
-#define ES2 0x10
-#define ES1 0x20
-#define ES0 0x40
-
-#define BUFSIZE 2048
-
-#define SLAVE_TRANSMITTER 0x1
-#define SLAVE_RECEIVER 0x2
-
-#define PCF_DEFAULT_ADDR 0xaa
-
-struct pcf_softc {
-
- int pcf_base; /* isa port */
- int pcf_flags;
- u_char pcf_addr; /* interface I2C address */
-
- int pcf_slave_mode; /* receiver or transmitter */
- int pcf_started; /* 1 if start condition sent */
-
- device_t iicbus; /* the corresponding iicbus */
-
- int rid_irq, rid_ioport;
- struct resource *res_irq, *res_ioport;
- void *intr_cookie;
-};
-
-static int pcf_probe(device_t);
-static int pcf_attach(device_t);
-static void pcfintr(void *arg);
-
-static int pcf_print_child(device_t, device_t);
-
-static int pcf_repeated_start(device_t, u_char, int);
-static int pcf_start(device_t, u_char, int);
-static int pcf_stop(device_t);
-static int pcf_write(device_t, char *, int, int *, int);
-static int pcf_read(device_t, char *, int, int *, int, int);
-static int pcf_rst_card(device_t, u_char, u_char, u_char *);
-
-static device_method_t pcf_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, pcf_probe),
- DEVMETHOD(device_attach, pcf_attach),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, pcf_print_child),
-
- /* iicbus interface */
- DEVMETHOD(iicbus_callback, iicbus_null_callback),
- DEVMETHOD(iicbus_repeated_start, pcf_repeated_start),
- DEVMETHOD(iicbus_start, pcf_start),
- DEVMETHOD(iicbus_stop, pcf_stop),
- DEVMETHOD(iicbus_write, pcf_write),
- DEVMETHOD(iicbus_read, pcf_read),
- DEVMETHOD(iicbus_reset, pcf_rst_card),
-
- { 0, 0 }
-};
-
-static driver_t pcf_driver = {
- "pcf",
- pcf_methods,
- sizeof(struct pcf_softc),
-};
-
-static devclass_t pcf_devclass;
-
-#define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev))
-
-static int
-pcf_probe(device_t pcfdev)
-{
- struct pcf_softc *pcf;
- device_t parent = device_get_parent(pcfdev);
- uintptr_t base;
-
- device_set_desc(pcfdev, "PCF8584 I2C bus controller");
-
- pcf = DEVTOSOFTC(pcfdev);
- bzero(pcf, sizeof(struct pcf_softc));
-
- pcf->rid_irq = pcf->rid_ioport = 0;
- pcf->res_irq = pcf->res_ioport = 0;
-
- /* IO port is mandatory */
- pcf->res_ioport = bus_alloc_resource(pcfdev, SYS_RES_IOPORT,
- &pcf->rid_ioport, 0ul, ~0ul,
- IO_PCFSIZE, RF_ACTIVE);
- if (pcf->res_ioport == 0) {
- device_printf(pcfdev, "cannot reserve I/O port range\n");
- goto error;
- }
- BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &base);
- pcf->pcf_base = base;
-
- pcf->pcf_flags = device_get_flags(pcfdev);
-
- if (!(pcf->pcf_flags & IIC_POLLED)) {
- pcf->res_irq = bus_alloc_resource(pcfdev, SYS_RES_IRQ, &pcf->rid_irq,
- 0ul, ~0ul, 1, RF_ACTIVE);
- if (pcf->res_irq == 0) {
- device_printf(pcfdev, "can't reserve irq, polled mode.\n");
- pcf->pcf_flags |= IIC_POLLED;
- }
- }
-
- /* reset the chip */
- pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL);
-
- return (0);
-error:
- if (pcf->res_ioport != 0) {
- bus_deactivate_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
- pcf->res_ioport);
- bus_release_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
- pcf->res_ioport);
- }
- return (ENXIO);
-}
-
-static int
-pcf_attach(device_t pcfdev)
-{
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
- device_t parent = device_get_parent(pcfdev);
- int error = 0;
-
- if (pcf->res_irq) {
- /* default to the tty mask for registration */ /* XXX */
- error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq, INTR_TYPE_NET,
- pcfintr, pcfdev, &pcf->intr_cookie);
- if (error)
- return (error);
- }
-
- pcf->iicbus = device_add_child(pcfdev, "iicbus", -1);
-
- /* probe and attach the iicbus */
- bus_generic_attach(pcfdev);
-
- return (0);
-}
-
-static int
-pcf_print_child(device_t bus, device_t dev)
-{
- struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(bus);
- int retval = 0;
-
- retval += bus_print_child_header(bus, dev);
- retval += printf(" on %s addr 0x%x\n", device_get_nameunit(bus),
- (int)pcf->pcf_addr);
-
- return (retval);
-}
-
-/*
- * PCF8584 datasheet : when operate at 8 MHz or more, a minimun time of
- * 6 clocks cycles must be left between two consecutives access
- */
-#define pcf_nops() DELAY(10)
-
-#define dummy_read(pcf) PCF_GET_S0(pcf)
-#define dummy_write(pcf) PCF_SET_S0(pcf, 0)
-
-/*
- * Specific register access to PCF8584
- */
-static void PCF_SET_S0(struct pcf_softc *pcf, int data)
-{
- outb(pcf->pcf_base, data);
- pcf_nops();
-}
-
-static void PCF_SET_S1(struct pcf_softc *pcf, int data)
-{
- outb(pcf->pcf_base+1, data);
- pcf_nops();
-}
-
-static char PCF_GET_S0(struct pcf_softc *pcf)
-{
- char data;
-
- data = inb(pcf->pcf_base);
- pcf_nops();
-
- return (data);
-}
-
-static char PCF_GET_S1(struct pcf_softc *pcf)
-{
- char data;
-
- data = inb(pcf->pcf_base+1);
- pcf_nops();
-
- return (data);
-}
-
-/*
- * Polling mode for master operations wait for a new
- * byte incomming or outgoing
- */
-static int pcf_wait_byte(struct pcf_softc *pcf)
-{
- int counter = TIMEOUT;
-
- while (counter--) {
-
- if ((PCF_GET_S1(pcf) & PIN) == 0)
- return (0);
- }
-
- return (IIC_ETIMEOUT);
-}
-
-static int pcf_stop(device_t pcfdev)
-{
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
-
- /*
- * Send STOP condition iff the START condition was previously sent.
- * STOP is sent only once even if an iicbus_stop() is called after
- * an iicbus_read()... see pcf_read(): the pcf needs to send the stop
- * before the last char is read.
- */
- if (pcf->pcf_started) {
- /* set stop condition and enable IT */
- PCF_SET_S1(pcf, PIN|ES0|ENI|STO|ACK);
-
- pcf->pcf_started = 0;
- }
-
- return (0);
-}
-
-
-static int pcf_noack(struct pcf_softc *pcf, int timeout)
-{
- int noack;
- int k = timeout/10;
-
- do {
- noack = PCF_GET_S1(pcf) & LRB;
- if (!noack)
- break;
- DELAY(10); /* XXX wait 10 us */
- } while (k--);
-
- return (noack);
-}
-
-static int pcf_repeated_start(device_t pcfdev, u_char slave, int timeout)
-{
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
- int error = 0;
-
- /* repeated start */
- PCF_SET_S1(pcf, ES0|STA|STO|ACK);
-
- /* set slave address to PCF. Last bit (LSB) must be set correctly
- * according to transfer direction */
- PCF_SET_S0(pcf, slave);
-
- /* wait for address sent, polling */
- if ((error = pcf_wait_byte(pcf)))
- goto error;
-
- /* check for ack */
- if (pcf_noack(pcf, timeout)) {
- error = IIC_ENOACK;
- goto error;
- }
-
- return (0);
-
-error:
- pcf_stop(pcfdev);
- return (error);
-}
-
-static int pcf_start(device_t pcfdev, u_char slave, int timeout)
-{
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
- int error = 0;
-
- if ((PCF_GET_S1(pcf) & nBB) == 0)
- return (IIC_EBUSBSY);
-
- /* set slave address to PCF. Last bit (LSB) must be set correctly
- * according to transfer direction */
- PCF_SET_S0(pcf, slave);
-
- /* START only */
- PCF_SET_S1(pcf, PIN|ES0|STA|ACK);
-
- pcf->pcf_started = 1;
-
- /* wait for address sent, polling */
- if ((error = pcf_wait_byte(pcf)))
- goto error;
-
- /* check for ACK */
- if (pcf_noack(pcf, timeout)) {
- error = IIC_ENOACK;
- goto error;
- }
-
- return (0);
-
-error:
- pcf_stop(pcfdev);
- return (error);
-}
-
-static void
-pcfintr(void *arg)
-{
- device_t pcfdev = (device_t)arg;
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
-
- char data, status, addr;
- char error = 0;
-
- status = PCF_GET_S1(pcf);
-
- if (status & PIN) {
- device_printf(pcfdev, "spurious interrupt, status=0x%x\n", status & 0xff);
-
- goto error;
- }
-
- if (status & LAB)
- device_printf(pcfdev, "bus arbitration lost!\n");
-
- if (status & BER) {
- error = IIC_EBUSERR;
- iicbus_intr(pcf->iicbus, INTR_ERROR, &error);
-
- goto error;
- }
-
- do {
- status = PCF_GET_S1(pcf);
-
- switch(pcf->pcf_slave_mode) {
-
- case SLAVE_TRANSMITTER:
- if (status & LRB) {
- /* ack interrupt line */
- dummy_write(pcf);
-
- /* no ack, don't send anymore */
- pcf->pcf_slave_mode = SLAVE_RECEIVER;
-
- iicbus_intr(pcf->iicbus, INTR_NOACK, NULL);
- break;
- }
-
- /* get data from upper code */
- iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data);
-
- PCF_SET_S0(pcf, data);
- break;
-
- case SLAVE_RECEIVER:
- if (status & AAS) {
- addr = PCF_GET_S0(pcf);
-
- if (status & AD0)
- iicbus_intr(pcf->iicbus, INTR_GENERAL, &addr);
- else
- iicbus_intr(pcf->iicbus, INTR_START, &addr);
-
- if (addr & LSB) {
- pcf->pcf_slave_mode = SLAVE_TRANSMITTER;
-
- /* get the first char from upper code */
- iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data);
-
- /* send first data byte */
- PCF_SET_S0(pcf, data);
- }
-
- break;
- }
-
- /* stop condition received? */
- if (status & STS) {
- /* ack interrupt line */
- dummy_read(pcf);
-
- /* emulate intr stop condition */
- iicbus_intr(pcf->iicbus, INTR_STOP, NULL);
-
- } else {
- /* get data, ack interrupt line */
- data = PCF_GET_S0(pcf);
-
- /* deliver the character */
- iicbus_intr(pcf->iicbus, INTR_RECEIVE, &data);
- }
- break;
-
- default:
- panic("%s: unknown slave mode (%d)!", __func__,
- pcf->pcf_slave_mode);
- }
-
- } while ((PCF_GET_S1(pcf) & PIN) == 0);
-
- return;
-
-error:
- /* unknown event on bus...reset PCF */
- PCF_SET_S1(pcf, PIN|ES0|ENI|ACK);
-
- pcf->pcf_slave_mode = SLAVE_RECEIVER;
-
- return;
-}
-
-static int pcf_rst_card(device_t pcfdev, u_char speed, u_char addr, u_char *oldaddr)
-{
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
-
- if (oldaddr)
- *oldaddr = pcf->pcf_addr;
-
- /* retrieve own address from bus level */
- if (!addr)
- pcf->pcf_addr = PCF_DEFAULT_ADDR;
- else
- pcf->pcf_addr = addr;
-
- PCF_SET_S1(pcf, PIN); /* initialize S1 */
-
- /* own address S'O<>0 */
- PCF_SET_S0(pcf, pcf->pcf_addr >> 1);
-
- /* select clock register */
- PCF_SET_S1(pcf, PIN|ES1);
-
- /* select bus speed : 18=90kb, 19=45kb, 1A=11kb, 1B=1.5kb */
- switch (speed) {
- case IIC_SLOW:
- PCF_SET_S0(pcf, 0x1b);
- break;
-
- case IIC_FAST:
- PCF_SET_S0(pcf, 0x19);
- break;
-
- case IIC_UNKNOWN:
- case IIC_FASTEST:
- default:
- PCF_SET_S0(pcf, 0x18);
- break;
- }
-
- /* set bus on, ack=yes, INT=yes */
- PCF_SET_S1(pcf, PIN|ES0|ENI|ACK);
-
- pcf->pcf_slave_mode = SLAVE_RECEIVER;
-
- return (0);
-}
-
-static int
-pcf_write(device_t pcfdev, char *buf, int len, int *sent, int timeout /* us */)
-{
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
- int bytes, error = 0;
-
-#ifdef PCFDEBUG
- printf("pcf%d: >> writing %d bytes\n", device_get_unit(pcfdev), len);
-#endif
-
- bytes = 0;
- while (len) {
-
- PCF_SET_S0(pcf, *buf++);
-
- /* wait for the byte to be send */
- if ((error = pcf_wait_byte(pcf)))
- goto error;
-
- /* check if ack received */
- if (pcf_noack(pcf, timeout)) {
- error = IIC_ENOACK;
- goto error;
- }
-
- len --;
- bytes ++;
- }
-
-error:
- *sent = bytes;
-
-#ifdef PCFDEBUG
- printf("pcf%d: >> %d bytes written (%d)\n",
- device_get_unit(pcfdev), bytes, error);
-#endif
-
- return (error);
-}
-
-static int
-pcf_read(device_t pcfdev, char *buf, int len, int *read, int last,
- int delay /* us */)
-{
- struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
- int bytes, error = 0;
-
-#ifdef PCFDEBUG
- printf("pcf%d: << reading %d bytes\n", device_get_unit(pcfdev), len);
-#endif
-
- /* trig the bus to get the first data byte in S0 */
- if (len) {
- if (len == 1 && last)
- /* just one byte to read */
- PCF_SET_S1(pcf, ES0); /* no ack */
-
- dummy_read(pcf);
- }
-
- bytes = 0;
- while (len) {
-
- /* XXX delay needed here */
-
- /* wait for trigged byte */
- if ((error = pcf_wait_byte(pcf))) {
- pcf_stop(pcfdev);
- goto error;
- }
-
- if (len == 1 && last)
- /* ok, last data byte already in S0, no I2C activity
- * on next PCF_GET_S0() */
- pcf_stop(pcfdev);
-
- else if (len == 2 && last)
- /* next trigged byte with no ack */
- PCF_SET_S1(pcf, ES0);
-
- /* receive byte, trig next byte */
- *buf++ = PCF_GET_S0(pcf);
-
- len --;
- bytes ++;
- };
-
-error:
- *read = bytes;
-
-#ifdef PCFDEBUG
- printf("pcf%d: << %d bytes read (%d)\n",
- device_get_unit(pcfdev), bytes, error);
-#endif
-
- return (error);
-}
-
-DRIVER_MODULE(pcf, isa, pcf_driver, pcf_devclass, 0, 0);
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index f3d6208..6338448 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -495,6 +495,7 @@ _smbfs= smbfs
.if ${MACHINE_ARCH} == "sparc64"
_auxio= auxio
_gem= gem
+_i2c= i2c
_sound= sound
.endif
diff --git a/sys/modules/i2c/controllers/pcf/Makefile b/sys/modules/i2c/controllers/pcf/Makefile
index 42d3ade..7227bec 100644
--- a/sys/modules/i2c/controllers/pcf/Makefile
+++ b/sys/modules/i2c/controllers/pcf/Makefile
@@ -1,8 +1,17 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../../i386/isa
+.PATH: ${.CURDIR}/../../../../dev/pcf
KMOD = pcf
SRCS = device_if.h bus_if.h iicbus_if.h isa_if.h \
pcf.c
+.if ${MACHINE_ARCH} != "sparc64"
+SRCS += pcf_isa.c
+.endif
+
+.if ${MACHINE_ARCH} == "sparc64"
+SRCS += envctrl.c
+SRCS += pcf_ebus.c
+.endif
+
.include <bsd.kmod.mk>
OpenPOWER on IntegriCloud