Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/powerpc Add on-chip IIC driver.
details: https://anonhg.NetBSD.org/src/rev/caec20deedac
branches: trunk
changeset: 552322:caec20deedac
user: shige <shige%NetBSD.org@localhost>
date: Tue Sep 23 14:56:08 2003 +0000
description:
Add on-chip IIC driver.
Add some definitions for IIC driver.
diffstat:
sys/arch/powerpc/conf/files.ibm4xx | 7 +-
sys/arch/powerpc/ibm4xx/dev/iic.c | 592 +++++++++++++++++++++++++++++++++++
sys/arch/powerpc/ibm4xx/dev/iicreg.h | 91 +++++-
sys/arch/powerpc/ibm4xx/dev/iicvar.h | 91 +++++
4 files changed, 778 insertions(+), 3 deletions(-)
diffs (truncated from 829 to 300 lines):
diff -r edb71f990762 -r caec20deedac sys/arch/powerpc/conf/files.ibm4xx
--- a/sys/arch/powerpc/conf/files.ibm4xx Tue Sep 23 14:55:01 2003 +0000
+++ b/sys/arch/powerpc/conf/files.ibm4xx Tue Sep 23 14:56:08 2003 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.ibm4xx,v 1.3 2002/11/23 19:42:41 thorpej Exp $
+# $NetBSD: files.ibm4xx,v 1.4 2003/09/23 14:56:10 shige Exp $
#
# IBM 4xx specific configuration info
@@ -31,6 +31,11 @@
attach emac at opb
file arch/powerpc/ibm4xx/dev/if_emac.c emac
+# On-chip IIC device(s)
+device iic {[addr = -1], [irq = -1]}
+attach iic at opb
+file arch/powerpc/ibm4xx/dev/iic.c iic
+
# Watchdog timer
device wdog: sysmon_wdog
attach wdog at opb
diff -r edb71f990762 -r caec20deedac sys/arch/powerpc/ibm4xx/dev/iic.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/powerpc/ibm4xx/dev/iic.c Tue Sep 23 14:56:08 2003 +0000
@@ -0,0 +1,592 @@
+/* $NetBSD: iic.c,v 1.1 2003/09/23 14:56:08 shige Exp $ */
+
+/*
+ * Copyright (c) 2003 Shigeyuki Fukushima.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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>
+__KERNEL_RCSID(0, "$NetBSD: iic.c,v 1.1 2003/09/23 14:56:08 shige Exp $");
+
+#include "locators.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <powerpc/ibm4xx/dcr405gp.h>
+#include <powerpc/ibm4xx/ibm405gp.h>
+#include <powerpc/ibm4xx/dev/opbvar.h>
+#include <powerpc/ibm4xx/dev/iicreg.h>
+#include <powerpc/ibm4xx/dev/iicvar.h>
+
+#define IIC_READ(sc, reg) \
+ bus_space_read_1(sc->sc_st, sc->sc_sh, (reg))
+#define IIC_WRITE(sc, reg, val) \
+ bus_space_write_1(sc->sc_st, sc->sc_sh, (reg), (val))
+
+/*
+ * XXX: builtin devices
+ */
+#define NVRAM_BASE 0xf0000000
+const struct iicbus_dev {
+ const char *name;
+ bus_addr_t addr;
+ int irq;
+} iicbus_devs[] = {
+ { "rtc", NVRAM_BASE, -1 },
+ { NULL }
+};
+
+static int iic_match(struct device *, struct cfdata *, void *);
+static void iic_attach(struct device *, struct device *, void *);
+static int iic_submatch(struct device *, struct cfdata *, void *);
+static int iic_print(void *, const char *);
+
+static void iic_reset(struct iic_softc *sc);
+static int iic_master_xfer(struct iic_softc *sc,
+ int rpst_flag, int rw_flag,
+ u_int16_t addr, int addrtype,
+ u_char *data, int len);
+static int iic_master_read_bytes(struct iic_softc *sc,
+ u_char *buf, int count, int rpst_flag);
+static int iic_master_write_bytes(struct iic_softc *sc,
+ u_char *buf, int count, int rpst_flag);
+static void iic_xfer_poll(struct iic_softc *sc);
+static int iic_err_status(struct iic_softc *sc);
+
+#ifdef IIC_DEBUG
+static void iic_print_register(struct iic_softc *sc);
+#endif
+
+CFATTACH_DECL(iic, sizeof(struct device),
+ iic_match, iic_attach, NULL, NULL);
+
+/*
+ * Probe for the IIC.
+ */
+static int
+iic_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct opb_attach_args *oaa = aux;
+
+ /* match only on-chip iic devices */
+ if (strcmp(oaa->opb_name, cf->cf_name) == 0)
+ return (1);
+
+ return (0);
+}
+
+static int
+iic_submatch(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct iicbus_attach_args *iaa = aux;
+
+ if (cf->cf_loc[IICCF_ADDR] != IICCF_ADDR_DEFAULT &&
+ cf->cf_loc[IICCF_ADDR] != iaa->iicb_addr)
+ return (0);
+
+ return (config_match(parent, cf, aux));
+}
+
+/*
+ * Attach the IIC.
+ */
+static void
+iic_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct opb_attach_args *oaa = aux;
+ struct iicbus_attach_args iaa;
+ struct iic_softc *sc = (struct iic_softc *)self;
+ int i;
+
+ sc->sc_st = oaa->opb_bt;
+ sc->sc_sh = oaa->opb_addr;
+ sc->sc_dmat = oaa->opb_dmat;
+
+ printf(": 405GP IIC\n");
+
+ /*
+ * Reset the chip to a known state.
+ */
+ iic_reset(sc);
+
+#if 0
+ {
+ /* test code */
+ u_char sr, buf[2];
+
+ buf[0] = 0x00;
+ buf[1] = 0x37;
+
+ iic_master_xfer(sc, IIC_XFER_RPTST, IIC_XFER_WRITE,
+ 0x6f, IIC_ADM_7BIT, &buf[0], 2);
+
+ iic_master_xfer(sc, IIC_XFER_NRMST, IIC_XFER_READ,
+ 0x6f, IIC_ADM_7BIT, &sr, 1);
+
+ printf("SR(0x%x): 0x%x\n", buf[1], sr);
+ }
+#endif
+
+ for (i = 0 ; iicbus_devs[i].name != NULL ; i++) {
+ iaa.iicb_name = iicbus_devs[i].name;
+ iaa.iicb_addr = iicbus_devs[i].addr;
+ iaa.iicb_irq = iicbus_devs[i].irq;
+ iaa.iicb_bt = oaa->opb_bt;
+ iaa.iicb_dmat = oaa->opb_dmat;
+ iaa.adap = sc;
+
+ (void) config_found_sm(self, &iaa, iic_print, iic_submatch);
+ }
+
+ return;
+}
+
+static int
+iic_print(void *aux, const char *pnp)
+{
+ struct iicbus_attach_args *iaa = aux;
+
+ if (pnp)
+ printf("%s at %s", iaa->iicb_name, pnp);
+ if (iaa->iicb_addr != IICCF_ADDR_DEFAULT)
+ aprint_normal(" addr 0x%08lx", iaa->iicb_addr);
+ if (iaa->iicb_irq != IICCF_IRQ_DEFAULT)
+ aprint_normal(" irq %d", iaa->iicb_irq);
+
+ return (UNCONF);
+}
+
+/*
+ * iic_read()
+ */
+int iic_read(struct iic_softc *sc, u_char saddr,
+ u_char *addr, int alen, u_char *data, int dlen)
+{
+ int ret;
+
+ ret = iic_master_xfer(sc, IIC_XFER_RPTST, IIC_XFER_WRITE,
+ saddr, IIC_ADM_7BIT, addr, alen);
+
+ ret = iic_master_xfer(sc, IIC_XFER_NRMST, IIC_XFER_READ,
+ saddr, IIC_ADM_7BIT, data, dlen);
+
+ return (ret);
+}
+
+/*
+ * iic_write()
+ */
+int iic_write(struct iic_softc *sc, u_char saddr,
+ u_char *addr, int alen, u_char *data, int dlen)
+{
+ int ret;
+ u_char d[alen + dlen];
+
+ memcpy(d, addr, alen);
+ memcpy(d+alen, data, dlen);
+ ret = iic_master_xfer(sc, IIC_XFER_NRMST, IIC_XFER_WRITE,
+ saddr, IIC_ADM_7BIT, d, (alen + dlen));
+
+ return (ret);
+}
+
+/*
+ * iic_reset()
+ * Perform IIC Soft Reset
+ */
+static void
+iic_reset(struct iic_softc *sc)
+{
+ /* Clear Low/High Master Address */
+ IIC_WRITE(sc, IIC_LMADR, 0x0);
+ IIC_WRITE(sc, IIC_HMADR, 0x0);
+
+ /* Clear Low/High Slave Address */
+ IIC_WRITE(sc, IIC_LSADR, 0x0);
+ IIC_WRITE(sc, IIC_HSADR, 0x0);
+
+ /* Clear any active interrupts */
+ IIC_WRITE(sc, IIC_STS, IIC_STS_SCMP | IIC_STS_IRQA);
+
+ /* Clear all writable status bits */
+ IIC_WRITE(sc, IIC_EXTSTS, IIC_EXTSTS_IRQP
+ | IIC_EXTSTS_IRQD
+ | IIC_EXTSTS_LA
+ | IIC_EXTSTS_ICT
+ | IIC_EXTSTS_XFRA);
+
+ /* Clear all writable status bits */
+ IIC_WRITE(sc, IIC_CLKDIV, IIC_CLKDIV_70MHZ); /* XXX: OBS266 66MHz */
+
+ /* Clear all interrupt mask bits */
+ /* IIC_WRITE(sc, IIC_INTRMSK, IIC_INTRMSK_EIMTC); */
+ IIC_WRITE(sc, IIC_INTRMSK, 0x0);
+
+ /* Clear Transfer Counter */
+ IIC_WRITE(sc, IIC_XFRCNT, 0x0);
+
+ /* Clear status set */
+ IIC_WRITE(sc, IIC_XTCNTLSS, IIC_XTCNTLSS_SRC
+ | IIC_XTCNTLSS_SRS
+ | IIC_XTCNTLSS_SWC
+ | IIC_XTCNTLSS_SWS);
+
+ /*
+ * Initialize Mode Control
+ * Flushes master and slave data buffers
+ * Enables IIC Standard mode (100Kb clock)
+ * Disables Interrupts
+ * Disables Slave Mode
+ * Enables Interrupt
+ * Enables Exit Unknown State
+ * Hold IIC Serial Clock Low
+ */
+ IIC_WRITE(sc, IIC_MDCNTL, IIC_MDCNTL_FMDB
+ | IIC_MDCNTL_FSDB
Home |
Main Index |
Thread Index |
Old Index