Re: RFC: Alchemy Au1550 SMBus driver on PSC

"Garrett D'Amore" <[email protected]>
Newsgroups gmane.os.netbsd.ports.evbmips
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.