Subject: Re: RFC: Alchemy Au1550 SMBus driver on PSC
To: Shigeyuki Fukushima <shige@NetBSD.org>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: port-evbmips
Date: 03/02/2006 12:38:19
This looks pretty good.
Only one question: in aupsc_enable(), why do you bother to complain if
it is already enabled? I think this should be one of two things:
1) if it is a programmer error, then make it a KASSERT()
2) if there is some reason why its not programmer error, then you should
probably just do the disable() yourself, and maybe put a message in an
#ifdef DIAGNOSTIC or somesuch.
Otherwise, it looks pretty good. I will be able to put this to
immediate use pretty soon -- I want to hook a smart card interface up to
I2C. :-)
-- Garrett
Shigeyuki Fukushima wrote:
> Hi,
>
> I'm implementing SMBus driver on PSC(bus) device.
> Would you like to review the following files (attached with this mail):
>
> sys-arch-mips.diff: diffs for sys/arch/mips from -current.
> ausmbus_psc.c: smbus driver.
> smbusreg.c: definitions for SMBus registers
> (Au1550 DataBook 8.5)
>
> With implementing this driver, I revised up aupsc.c.
> Please review it intensively.
>
> ------------------------------------------------------------------------
>
> ? sys/arch/mips/alchemy/dev/ausmbus_psc.c
> ? sys/arch/mips/alchemy/dev/smbusreg.h
> Index: sys/arch/mips/alchemy/dev/aupsc.c
> ===================================================================
> RCS file: /cvsroot/src/sys/arch/mips/alchemy/dev/aupsc.c,v
> retrieving revision 1.1
> diff -u -r1.1 aupsc.c
> --- sys/arch/mips/alchemy/dev/aupsc.c 24 Feb 2006 14:34:31 -0000 1.1
> +++ sys/arch/mips/alchemy/dev/aupsc.c 2 Mar 2006 17:39:41 -0000
> @@ -59,21 +59,30 @@
>
> const struct aupsc_proto {
> const char *name;
> + int protocol;
> + int statreg;
> + int statbit;
> } aupsc_protos [] = {
> + { "ausmbus", AUPSC_SEL_SMBUS, AUPSC_SMBSTAT, SMBUS_STAT_SR },
> #if 0
> { "auaudio" },
> { "aui2s" },
> { "ausmbus" },
> { "auspi" },
> #endif
> - { NULL }
> + { NULL, AUPSC_SEL_DISABLE, 0, 0 }
> };
>
> static int aupsc_match(struct device *, struct cfdata *, void *);
> static void aupsc_attach(struct device *, struct device *, void *);
> -static int aupsc_submatch(struct device *parent, struct cfdata *cf,
> - const int *ldesc, void *aux);
> -static int aupsc_print(void *aux, const char *pnp);
> +static int aupsc_submatch(struct device *, struct cfdata *, const int *,
> + void *);
> +static int aupsc_print(void *, const char *);
> +
> +static void aupsc_enable(void *, int);
> +static void aupsc_disable(void *);
> +static void aupsc_suspend(void *);
> +
>
> CFATTACH_DECL(aupsc, sizeof(struct aupsc_softc),
> aupsc_match, aupsc_attach, NULL, NULL);
> @@ -97,6 +106,7 @@
> struct aupsc_softc *sc = (struct aupsc_softc *)self;
> struct aubus_attach_args *aa = (struct aubus_attach_args *)aux;
> struct aupsc_attach_args pa;
> + struct aupsc_controller ctrl;
>
> sc->sc_bust = aa->aa_st;
> if (bus_space_map(sc->sc_bust, aa->aa_addr,
> @@ -110,16 +120,37 @@
> rv = bus_space_read_4(sc->sc_bust, sc->sc_bush, AUPSC_SEL);
> bus_space_write_4(sc->sc_bust, sc->sc_bush,
> AUPSC_SEL, (rv & AUPSC_SEL_PS(AUPSC_SEL_DISABLE)));
> + bus_space_write_4(sc->sc_bust, sc->sc_bush,
> + AUPSC_CTRL, AUPSC_CTRL_ENA(AUPSC_CTRL_DISABLE));
>
> aprint_normal(": Alchemy PSC\n");
>
> + ctrl.psc_bust = sc->sc_bust;
> + ctrl.psc_bush = sc->sc_bush;
> + ctrl.psc_sel = &(sc->sc_pscsel);
> + ctrl.psc_enable = aupsc_enable;
> + ctrl.psc_disable = aupsc_disable;
> + ctrl.psc_suspend = aupsc_suspend;
> + pa.aupsc_ctrl = ctrl;
> +
> for (i = 0 ; aupsc_protos[i].name != NULL ; i++) {
> + struct aupsc_protocol_device p;
> + uint32_t s;
> +
> pa.aupsc_name = aupsc_protos[i].name;
> - pa.aupsc_bust = sc->sc_bust;
> - pa.aupsc_bush = sc->sc_bush;
>
> - (void) config_found_sm_loc(self, "aupsc", NULL,
> - &pa, aupsc_print, aupsc_submatch);
> + p.sc_dev = sc->sc_dev;
> + p.sc_ctrl = ctrl;
> +
> + aupsc_enable(&p, aupsc_protos[i].protocol);
> + s = bus_space_read_4(sc->sc_bust, sc->sc_bush,
> + aupsc_protos[i].statreg);
> + aupsc_disable(&p);
> +
> + if (s & aupsc_protos[i].statbit) {
> + (void) config_found_sm_loc(self, "aupsc", NULL,
> + &pa, aupsc_print, aupsc_submatch);
> + }
> }
> }
>
> @@ -141,3 +172,59 @@
>
> return UNCONF;
> }
> +
> +static void
> +aupsc_enable(void *arg, int proto)
> +{
> + struct aupsc_protocol_device *sc = arg;
> +
> + /* XXX: (TODO) setting clock AUPSC_SEL_CLK */
> + switch (proto) {
> + case AUPSC_SEL_SPI:
> + case AUPSC_SEL_I2S:
> + case AUPSC_SEL_AC97:
> + case AUPSC_SEL_SMBUS:
> + break;
> + case AUPSC_SEL_DISABLE:
> + aupsc_disable(arg);
> + break;
> + default:
> + printf("%s: aupsc_enable: unsupported protocol.\n",
> + sc->sc_dev.dv_xname);
> + return;
> + }
> +
> + if (*(sc->sc_ctrl.psc_sel) != AUPSC_SEL_DISABLE) {
> + printf("%s: aupsc_enable: please disable first.\n",
> + sc->sc_dev.dv_xname);
> + return;
> + }
> +
> + bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
> + AUPSC_SEL, AUPSC_SEL_PS(proto));
> + bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
> + AUPSC_CTRL, AUPSC_CTRL_ENA(AUPSC_CTRL_ENABLE));
> + delay(1);
> +}
> +
> +static void
> +aupsc_disable(void *arg)
> +{
> + struct aupsc_protocol_device *sc = arg;
> +
> + bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
> + AUPSC_SEL, AUPSC_SEL_PS(AUPSC_SEL_DISABLE));
> + bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
> + AUPSC_CTRL, AUPSC_CTRL_ENA(AUPSC_CTRL_DISABLE));
> + delay(1);
> +}
> +
> +static void
> +aupsc_suspend(void *arg)
> +{
> + struct aupsc_protocol_device *sc = arg;
> +
> + bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
> + AUPSC_CTRL, AUPSC_CTRL_ENA(AUPSC_CTRL_SUSPEND));
> + delay(1);
> +}
> Index: sys/arch/mips/alchemy/dev/aupscreg.h
> ===================================================================
> RCS file: /cvsroot/src/sys/arch/mips/alchemy/dev/aupscreg.h,v
> retrieving revision 1.1
> diff -u -r1.1 aupscreg.h
> --- sys/arch/mips/alchemy/dev/aupscreg.h 24 Feb 2006 14:34:31 -0000 1.1
> +++ sys/arch/mips/alchemy/dev/aupscreg.h 2 Mar 2006 17:39:41 -0000
> @@ -68,10 +68,13 @@
> * 00 = Disable/Reset
> * 01 = Reserved
> * 10 = Suspend
> - * 10 = Enable
> + * 11 = Enable
> */
> #define AUPSC_CTRL 0x04 /* R/W */
> # define AUPSC_CTRL_ENA(x) (x & 0x03)
> +# define AUPSC_CTRL_DISABLE 0
> +# define AUPSC_CTRL_SUSPEND 2
> +# define AUPSC_CTRL_ENABLE 3
>
> /* 0x0008 - 0x002F: Protocol-specific registers */
>
> @@ -124,5 +127,6 @@
> #define AUPSC_SMBEVNT 0x18 /* R/W */
> #define AUPSC_SMBTXRX 0x1c /* R/W */
> #define AUPSC_SMBTMR 0x20 /* R/W */
> +#include <mips/alchemy/dev/smbusreg.h>
>
> #endif /* _MIPS_ALCHEMY_DEV_AUPSCREG_H_ */
> Index: sys/arch/mips/alchemy/dev/aupscvar.h
> ===================================================================
> RCS file: /cvsroot/src/sys/arch/mips/alchemy/dev/aupscvar.h,v
> retrieving revision 1.1
> diff -u -r1.1 aupscvar.h
> --- sys/arch/mips/alchemy/dev/aupscvar.h 24 Feb 2006 14:34:31 -0000 1.1
> +++ sys/arch/mips/alchemy/dev/aupscvar.h 2 Mar 2006 17:39:41 -0000
> @@ -35,10 +35,23 @@
> #ifndef _MIPS_ALCHEMY_DEV_AUPSCVAR_H_
> #define _MIPS_ALCHEMY_DEV_AUPSCVAR_H_
>
> +struct aupsc_controller {
> + bus_space_tag_t psc_bust; /* Bus space tag */
> + bus_space_handle_t psc_bush; /* Bus space handle */
> + int * psc_sel; /* current protocol selection */
> + void (*psc_enable)(void *, int);
> + void (*psc_disable)(void *);
> + void (*psc_suspend)(void *);
> +};
> +
> struct aupsc_attach_args {
> const char * aupsc_name;
> - bus_space_tag_t aupsc_bust; /* Bus space tag */
> - bus_space_handle_t aupsc_bush; /* Bus space handle */
> + struct aupsc_controller aupsc_ctrl;
> +};
> +
> +struct aupsc_protocol_device {
> + struct device sc_dev;
> + struct aupsc_controller sc_ctrl;
> };
>
> #endif /* _MIPS_ALCHEMY_DEV_AUPSCVAR_H_ */
> Index: sys/arch/mips/conf/files.alchemy
> ===================================================================
> RCS file: /cvsroot/src/sys/arch/mips/conf/files.alchemy,v
> retrieving revision 1.10
> diff -u -r1.10 files.alchemy
> --- sys/arch/mips/conf/files.alchemy 24 Feb 2006 14:34:31 -0000 1.10
> +++ sys/arch/mips/conf/files.alchemy 2 Mar 2006 17:39:42 -0000
> @@ -60,10 +60,15 @@
> file arch/mips/alchemy/dev/augpio.c augpio
>
> # On-chip PSC
> -device aupsc
> +device aupsc { [addr=-1] }
> attach aupsc at aubus
> file arch/mips/alchemy/dev/aupsc.c aupsc
>
> +# On-chip PSC SMBus Protocol
> +device ausmbus: i2cbus, i2c_bitbang
> +attach ausmbus at aupsc
> +file arch/mips/alchemy/dev/ausmbus_psc.c ausmbus
> +
> # On-chip PCMCIA
> #
> # XXX: NOTE: As of Feb. 22, 2006, the aupcmcia bus is not quite
>
> ------------------------------------------------------------------------
>
> /* $NetBSD$ */
>
> /*-
> * Copyright (c) 2006 Shigeyuki Fukushima.
> * All rights reserved.
> *
> * Written by Shigeyuki Fukushima.
> *
> * 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. 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$");
>
> #include "locators.h"
>
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/device.h>
> #include <sys/errno.h>
> #include <sys/lock.h>
>
> #include <machine/bus.h>
> #include <machine/cpu.h>
>
> #include <mips/alchemy/dev/aupscreg.h>
> #include <mips/alchemy/dev/aupscvar.h>
> #include <mips/alchemy/dev/smbusreg.h>
>
> #include <dev/i2c/i2cvar.h>
> #include <dev/i2c/i2c_bitbang.h>
>
> struct ausmbus_softc {
> struct device sc_dev;
>
> /* protocol comoon fields */
> struct aupsc_controller sc_ctrl;
>
> /* protocol specific fields */
> struct i2c_controller sc_i2c;
> i2c_addr_t sc_smbus_slave_addr;
> };
>
> static int ausmbus_match(struct device *, struct cfdata *, void *);
> static void ausmbus_attach(struct device *, struct device *, void *);
>
> CFATTACH_DECL(ausmbus, sizeof(struct ausmbus_softc),
> ausmbus_match, ausmbus_attach, NULL, NULL);
>
> /* fuctions for i2c_controller */
> static int ausmbus_acquire_bus(void *, int);
> static void ausmbus_release_bus(void *, int);
> static int ausmbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
> const void *cmd, size_t cmdlen, void *vbuf,
> size_t buflen, int flags);
> static uint32_t ausmbus_reg_read(struct ausmbus_softc *, int);
> static void ausmbus_reg_write(struct ausmbus_softc *, int, uint32_t);
>
> static int
> ausmbus_match(struct device *parent, struct cfdata *cf, void *aux)
> {
> struct aupsc_attach_args *aa = (struct aupsc_attach_args *)aux;
>
> if (strcmp(aa->aupsc_name, cf->cf_name) != 0)
> return 0;
>
> return 1;
> }
>
> static void
> ausmbus_attach(struct device *parent, struct device *self, void *aux)
> {
> struct ausmbus_softc *sc = (struct ausmbus_softc *)self;
> struct aupsc_attach_args *aa = (struct aupsc_attach_args *)aux;
> struct i2cbus_attach_args iba;
>
> aprint_normal(": Alchemy PSC SMBus protocol\n");
>
> /* Initialize PSC */
> sc->sc_ctrl = aa->aupsc_ctrl;
>
> /* Initialize i2c_controller for SMBus */
> sc->sc_i2c.ic_cookie = sc;
> sc->sc_i2c.ic_acquire_bus = ausmbus_acquire_bus;
> sc->sc_i2c.ic_release_bus = ausmbus_release_bus;
> sc->sc_i2c.ic_send_start = NULL;
> sc->sc_i2c.ic_send_stop = NULL;
> sc->sc_i2c.ic_initiate_xfer = NULL;
> sc->sc_i2c.ic_read_byte = NULL;
> sc->sc_i2c.ic_write_byte = NULL;
> sc->sc_i2c.ic_exec = ausmbus_exec;
>
> ausmbus_acquire_bus(sc, 0);
> ausmbus_release_bus(sc, 0);
>
> iba.iba_name = "iic";
> iba.iba_tag = &sc->sc_i2c;
> (void) config_found(&sc->sc_dev, &iba, iicbus_print);
> }
>
> static int
> ausmbus_acquire_bus(void *arg, int flags)
> {
> struct ausmbus_softc *sc = arg;
> uint32_t v;
>
> /* Select SMBus Protocol & Enable PSC */
> sc->sc_ctrl.psc_enable(sc, AUPSC_SEL_SMBUS);
> v = ausmbus_reg_read(sc, AUPSC_SMBSTAT);
> if ((v & SMBUS_STAT_SR) == 0) {
> /* PSC is not ready */
> return -1;
> }
>
> /* Setup SMBus Configuration register */
> v = SMBUS_CFG_DD; /* Disable DMA */
> v |= SMBUS_CFG_RT_SET(SMBUS_CFG_RT_FIFO8); /* Rx FIFO 8data */
> v |= SMBUS_CFG_TT_SET(SMBUS_CFG_TT_FIFO8); /* Tx FIFO 8data */
> v |= SMBUS_CFG_DIV_SET(SMBUS_CFG_DIV8); /* pscn_mainclk/8 */
> v &= ~SMBUS_CFG_SFM; /* Standard Mode */
> ausmbus_reg_write(sc, AUPSC_SMBCFG, v);
>
> /* Setup SMBus Protocol Timing register */
> v = SMBUS_TMR_TH_SET(0)
> | SMBUS_TMR_PS_SET(0xf) | SMBUS_TMR_PU_SET(0xf)
> | SMBUS_TMR_SH_SET(0xf) | SMBUS_TMR_SU_SET(0xf)
> | SMBUS_TMR_CL_SET(0xf) | SMBUS_TMR_CH_SET(0xf);
> ausmbus_reg_write(sc, AUPSC_SMBTMR, v);
>
> /* Setup SMBus Mask register */
> v = SMBUS_MSK_ALLMASK;
> ausmbus_reg_write(sc, AUPSC_SMBMSK, v);
>
> /* SMBus Enable */
> v = ausmbus_reg_read(sc, AUPSC_SMBCFG);
> v |= SMBUS_CFG_DE;
> ausmbus_reg_write(sc, AUPSC_SMBCFG, v);
> v = ausmbus_reg_read(sc, AUPSC_SMBSTAT);
> if ((v & SMBUS_STAT_SR) == 0) {
> /* SMBus is not ready */
> return -1;
> }
>
> #if 0
> printf("config: 0x%08x\n", ausmbus_reg_read(sc, AUPSC_SMBCFG));
> printf("status: 0x%08x\n", ausmbus_reg_read(sc, AUPSC_SMBSTAT));
> printf("tmr : 0x%08x\n", ausmbus_reg_read(sc, AUPSC_SMBTMR));
> printf("mask : 0x%08x\n", ausmbus_reg_read(sc, AUPSC_SMBMSK));
> #endif
>
> return 0;
> }
>
> static void
> ausmbus_release_bus(void *arg, int flags)
> {
> struct ausmbus_softc *sc = arg;
>
> ausmbus_reg_write(sc, AUPSC_SMBCFG, 0);
> sc->sc_ctrl.psc_disable(sc);
>
> return;
> }
>
> static int
> ausmbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd,
> size_t cmdlen, void *vbuf, size_t buflen, int flags)
> {
> struct ausmbus_softc *sc = (struct ausmbus_softc *)cookie;
> sc->sc_smbus_slave_addr = addr;
>
> /* XXX now implementing... */
> return -1;
> }
>
> static uint32_t
> ausmbus_reg_read(struct ausmbus_softc *sc, int reg)
> {
>
> return bus_space_read_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
> reg);
> }
>
> static void
> ausmbus_reg_write(struct ausmbus_softc *sc, int reg, uint32_t val)
> {
>
> bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush,
> reg, val);
> }
>
> ------------------------------------------------------------------------
>
> /* $NetBSD$ */
>
> /*-
> * Copyright (c) 2006 Shigeyuki Fukushima.
> * All rights reserved.
> *
> * Written by Shigeyuki Fukushima.
> *
> * 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. 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.
> */
>
> #ifndef _MIPS_ALCHEMY_SMBUSREG_H_
> #define _MIPS_ALCHEMY_SMBUSREG_H_
>
> /*
> * psc_smbcfg: SMBus Configuration Register
> * RT: Rx FIFO Threshold
> * TT: Tx FIFO Threshold
> * DD: Disable DMA Transfers
> * DE: Device Enable
> * DIV: PSC Clock Divider (see psc_smbtmr)
> * GCE: General Call Enable
> * SFM: Standard/Fast Mode
> * SLV: Slave Address
> */
> #define SMBUS_CFG_RT (3u << 30) /* R/W */
> #define SMBUS_CFG_RT_SET(x) ((x & 0x3) << 30)
> #define SMBUS_CFG_RT_FIFO1 0
> #define SMBUS_CFG_RT_FIFO2 1
> #define SMBUS_CFG_RT_FIFO4 2
> #define SMBUS_CFG_RT_FIFO8 3
> #define SMBUS_CFG_TT (3u << 28) /* R/W */
> #define SMBUS_CFG_TT_SET(x) ((x & 0x3) << 28)
> #define SMBUS_CFG_TT_FIFO1 0
> #define SMBUS_CFG_TT_FIFO2 1
> #define SMBUS_CFG_TT_FIFO4 2
> #define SMBUS_CFG_TT_FIFO8 3
> #define SMBUS_CFG_DD (1u << 27) /* R/W */
> #define SMBUS_CFG_DE (1u << 26) /* R/W */
> #define SMBUS_CFG_DIV (3u << 13) /* R/W */
> #define SMBUS_CFG_DIV_SET(x) ((x & 0x3) << 13)
> #define SMBUS_CFG_DIV2 0 /* PSC_CLK = pscn_mainclk / 2 */
> #define SMBUS_CFG_DIV4 1 /* PSC_CLK = pscn_mainclk / 4 */
> #define SMBUS_CFG_DIV8 2 /* PSC_CLK = pscn_mainclk / 8 */
> #define SMBUS_CFG_DIV16 3 /* PSC_CLK = pscn_mainclk / 16 */
> #define SMBUS_CFG_GCE (1u << 3) /* R/W */
> #define SMBUS_CFG_SFM (1u << 8) /* R/W */
> #define SMBUS_CFG_SLV (127u << 1) /* R/W */
>
> /*
> * psc_smbmsk: SMBus Mask Register
> * DN: Data Not-acknowledged
> * AN: Address Not-acknowledged
> * AL: Arbitration Lost
> * RR: Mask Rx FIFO request intterrupt
> * RO: Mask Rx FIFO overflow intterrupt
> * RU: Mask Rx FIFO uderflow intterrupt
> * TR: Mask Tx FIFO request intterrupt
> * TO: Mask Tx FIFO overflow intterrupt
> * TU: Mask Tx FIFO uderflow intterrupt
> * SD: Mask Slave Done intterrupt
> * MD: Mask Master Done intterrupt
> */
> #define SMBUS_MSK_DN (1u << 30) /* R/W */
> #define SMBUS_MSK_AN (1u << 29) /* R/W */
> #define SMBUS_MSK_AL (1u << 28) /* R/W */
> #define SMBUS_MSK_RR (1u << 13) /* R/W */
> #define SMBUS_MSK_RO (1u << 12) /* R/W */
> #define SMBUS_MSK_RU (1u << 11) /* R/W */
> #define SMBUS_MSK_TR (1u << 10) /* R/W */
> #define SMBUS_MSK_TO (1u << 9) /* R/W */
> #define SMBUS_MSK_TU (1u << 8) /* R/W */
> #define SMBUS_MSK_SD (1u << 5) /* R/W */
> #define SMBUS_MSK_MD (1u << 4) /* R/W */
> #define SMBUS_MSK_ALLMASK (SMBUS_MSK_DN | SMBUS_MSK_AN | SMBUS_MSK_AL \
> | SMBUS_MSK_RR | SMBUS_MSK_RO | SMBUS_MSK_RU \
> | SMBUS_MSK_TR | SMBUS_MSK_TO | SMBUS_MSK_TU \
> | SMBUS_MSK_SD | SMBUS_MSK_MD)
>
> /*
> * psc_smbpcr: SMBus Protocol Control Register
> * DC: Data Clear
> * MS: Master Start
> */
> #define SMBUS_PCR_DC (1u << 2) /* R/W */
> #define SMBUS_PCR_MS (1u << 0) /* R/W */
>
> /*
> * psc_smbstat: SMBus Status Register
> * BB: SMBus bus busy
> * RF: Receive FIFO full
> * RE: Receive FIFO empty
> * RR: Receive request
> * TF: Transfer FIFO full
> * TE: Transfer FIFO empty
> * TR: Transfer request
> * SB: Slave busy
> * MB: Master busy
> * DI: Device interrupt
> * DR: Device ready
> * SR: PSC ready
> */
> #define SMBUS_STAT_BB (1u << 28) /* Read only */
> #define SMBUS_STAT_RF (1u << 13) /* Read only */
> #define SMBUS_STAT_RE (1u << 12) /* Read only */
> #define SMBUS_STAT_RR (1u << 11) /* Read only */
> #define SMBUS_STAT_TF (1u << 10) /* Read only */
> #define SMBUS_STAT_TE (1u << 9) /* Read only */
> #define SMBUS_STAT_TR (1u << 8) /* Read only */
> #define SMBUS_STAT_SB (1u << 5) /* Read only */
> #define SMBUS_STAT_MB (1u << 4) /* Read only */
> #define SMBUS_STAT_DI (1u << 2) /* Read only */
> #define SMBUS_STAT_DR (1u << 1) /* Read only */
> #define SMBUS_STAT_SR (1u << 0) /* Read only */
>
> /*
> * psc_smbevnt: SMBus Event Register
> * DN: Data Not-acknowledged
> * AN: Address Not-acknowledged
> * AL: Arbitration Lost
> * RR: Mask Rx FIFO request intterrupt
> * RO: Mask Rx FIFO overflow intterrupt
> * RU: Mask Rx FIFO uderflow intterrupt
> * TR: Mask Tx FIFO request intterrupt
> * TO: Mask Tx FIFO overflow intterrupt
> * TU: Mask Tx FIFO uderflow intterrupt
> * SD: Mask Slave Done intterrupt
> * MD: Mask Master Done intterrupt
> */
> #define SMBUS_EVNT_DN (1u << 30) /* R/W */
> #define SMBUS_EVNT_AN (1u << 29) /* R/W */
> #define SMBUS_EVNT_AL (1u << 28) /* R/W */
> #define SMBUS_EVNT_RR (1u << 13) /* R/W */
> #define SMBUS_EVNT_RO (1u << 12) /* R/W */
> #define SMBUS_EVNT_RU (1u << 11) /* R/W */
> #define SMBUS_EVNT_TR (1u << 10) /* R/W */
> #define SMBUS_EVNT_TO (1u << 9) /* R/W */
> #define SMBUS_EVNT_TU (1u << 8) /* R/W */
> #define SMBUS_EVNT_SD (1u << 5) /* R/W */
> #define SMBUS_EVNT_MD (1u << 4) /* R/W */
>
> /*
> * psc_smbtxrx: SMBus Tx/Rx Data Register
> * STP: Stop
> * RSR: Restart
> * ADDRDATA: Address/Data
> */
> #define SMBUS_TXRX_STP (1u << 29) /* Write only */
> #define SMBUS_TXRX_RSR (1u << 28) /* Write only */
> #define SMBUS_TXRX_ADDRDATA (255u << 0) /* R/W */
>
>
> /*
> * psc_smbtmr: SMBus Protocol Timers Register
> * TH: Tx Data Hold Timer
> * PS: Stop->Start Buffer Timer
> * PU: Stop Setup Timer
> * SH: Start Hold Timer
> * SU: Start Setup Timer
> * CL: Clock Low
> * CH: Clock High
> *
> * [SMBus Timing Parameter Values]
> *
> * Standard Mode Fast Mode
> * Timer Name (pscn_mainclk/8) = 6.25MHz (pscn_mainclk/2) = 25MHz
> * Time unit = 160ns Time unit = 40ns
> * psc_smbtmr Bus Timings psc_smbtmr Bus Timings
> * Tx Hold TX = 0x00 480ns TH = 0x02 320ns
> * Stop->Start PS = 0x0F 4800ns PS = 0x0F 1320ns
> * Stop Setup PU = 0x0F 4000ns PU = 0x0B 600ns
> * Start Hold SH = 0x0F 4000ns SH = 0x0B 600ns
> * Start Setup SU = 0x0F 4800ns SU = 0x0B 600ns
> * Clock Low CL = 0x0F 4800ns CL = 0x0F 1320ns
> * Clock High CH = 0x0F 4000ns CH = 0x0B 600ns
> */
> #define SMBUS_TMR_TH (3u << 30) /* R/W */
> #define SMBUS_TMR_TH_SET(x) ((x & 0x3) << 30)
> #define SMBUS_TMR_PS (31u << 25) /* R/W */
> #define SMBUS_TMR_PS_SET(x) ((x & 0x1f) << 25)
> #define SMBUS_TMR_PU (31u << 20) /* R/W */
> #define SMBUS_TMR_PU_SET(x) ((x & 0x1f) << 20)
> #define SMBUS_TMR_SH (31u << 15) /* R/W */
> #define SMBUS_TMR_SH_SET(x) ((x & 0x1f) << 15)
> #define SMBUS_TMR_SU (31u << 10) /* R/W */
> #define SMBUS_TMR_SU_SET(x) ((x & 0x1f) << 10)
> #define SMBUS_TMR_CL (31u << 5) /* R/W */
> #define SMBUS_TMR_CL_SET(x) ((x & 0x1f) << 5)
> #define SMBUS_TMR_CH (31u << 0) /* R/W */
> #define SMBUS_TMR_CH_SET(x) ((x & 0x1f) << 0)
>
> #endif /* _MIPS_ALCHEMY_SMBUSREG_H_ */
>
--
Garrett D'Amore, Principal Software Engineer
Tadpole Computer / Computing Technologies Division,
General Dynamics C4 Systems
http://www.tadpolecomputer.com/
Phone: 951 325-2134 Fax: 951 325-2191