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