Various updates to most of the smbus(4) drivers:

- Use printf() and device_printf() instead of log() in ichsmb(4).
- Create the mutex sooner during ichsmb(4) attach.
- Attach the interrupt handler later during ichsmb(4) attach to avoid
  races.
- Don't try to set PCIM_CMD_PORTEN in ichsmb(4) attach as the PCI bus
  driver does this already.
- Add locking to alpm(4), amdpm(4), amdsmb(4), intsmb(4), nfsmb(4), and
  viapm(4).
- Axe ALPM_SMBIO_BASE_ADDR, it's not really safe to write arbitrary values
  into BARs, and the PCI bus layer will allocate resources now if needed.
- Merge intpm(4) and intsmb(4) into just intsmb(4).  Previously, intpm(4)
  attached to the PCI device and created an intsmb(4) child.  Now,
  intsmb(4) just attaches to PCI directly.
- Change several intsmb functions to take a softc instead of a device_t
  to make things simpler.
This commit is contained in:
John Baldwin 2007-01-11 19:56:24 +00:00
parent bd5da49e44
commit 85064e683c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=165951
9 changed files with 1017 additions and 830 deletions

View file

@ -71,7 +71,7 @@ __FBSDID("$FreeBSD$");
#define ICHSMB_DEBUG 0
#if ICHSMB_DEBUG != 0 && defined(__CC_SUPPORTS___FUNC__)
#define DBG(fmt, args...) \
do { log(LOG_DEBUG, "%s: " fmt, __func__ , ## args); } while (0)
do { printf("%s: " fmt, __func__ , ## args); } while (0)
#else
#define DBG(fmt, args...) do { } while (0)
#endif
@ -110,26 +110,38 @@ ichsmb_attach(device_t dev)
const sc_p sc = device_get_softc(dev);
int error;
/* Create mutex */
mtx_init(&sc->mutex, device_get_nameunit(dev), "ichsmb", MTX_DEF);
/* Add child: an instance of the "smbus" device */
if ((sc->smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) {
log(LOG_ERR, "%s: no \"%s\" child found\n",
device_get_nameunit(dev), DRIVER_SMBUS);
return (ENXIO);
device_printf(dev, "no \"%s\" child found\n", DRIVER_SMBUS);
error = ENXIO;
goto fail;
}
/* Clear interrupt conditions */
bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, 0xff);
/* Add "smbus" child */
if ((error = bus_generic_attach(dev)) != 0) {
log(LOG_ERR, "%s: failed to attach child: %d\n",
device_get_nameunit(dev), error);
return (ENXIO);
/* Set up interrupt handler */
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
ichsmb_device_intr, sc, &sc->irq_handle);
if (error != 0) {
device_printf(dev, "can't setup irq\n");
goto fail;
}
/* Attach "smbus" child */
if ((error = bus_generic_attach(dev)) != 0) {
device_printf(dev, "failed to attach child: %d\n", error);
goto fail;
}
/* Create mutex */
mtx_init(&sc->mutex, device_get_nameunit(dev), "ichsmb", MTX_DEF);
return (0);
fail:
mtx_destroy(&sc->mutex);
return (error);
}
/********************************************************************
@ -518,8 +530,8 @@ ichsmb_device_intr(void *cookie)
ok_bits |= ichsmb_state_irqs[cmd_index];
}
if ((status & ~ok_bits) != 0) {
log(LOG_ERR, "%s: irq 0x%02x during %d\n",
device_get_nameunit(dev), status, cmd_index);
device_printf(dev, "irq 0x%02x during %d\n", status,
cmd_index);
bus_space_write_1(sc->io_bst, sc->io_bsh,
ICH_HST_STA, (status & ~ok_bits));
continue;
@ -529,12 +541,10 @@ ichsmb_device_intr(void *cookie)
if (status & ICH_HST_STA_SMBALERT_STS) {
static int smbalert_count = 16;
if (smbalert_count > 0) {
log(LOG_WARNING, "%s: SMBALERT# rec'd\n",
device_get_nameunit(dev));
device_printf(dev, "SMBALERT# rec'd\n");
if (--smbalert_count == 0) {
log(LOG_WARNING,
"%s: not logging anymore\n",
device_get_nameunit(dev));
device_printf(dev,
"not logging anymore\n");
}
}
}
@ -609,8 +619,7 @@ ichsmb_device_intr(void *cookie)
/* Too many loops? */
if (count == maxloops) {
log(LOG_ERR, "%s: interrupt loop, status=0x%02x\n",
device_get_nameunit(dev),
device_printf(dev, "interrupt loop, status=0x%02x\n",
bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
}
}
@ -635,8 +644,7 @@ ichsmb_wait(sc_p sc)
smb_error = sc->smb_error;
break;
case EWOULDBLOCK:
log(LOG_ERR, "%s: device timeout, status=0x%02x\n",
device_get_nameunit(dev),
device_printf(dev, "device timeout, status=0x%02x\n",
bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
sc->ich_cmd = -1;
smb_error = SMB_ETIMEOUT;

View file

@ -164,7 +164,6 @@ static int
ichsmb_pci_attach(device_t dev)
{
const sc_p sc = device_get_softc(dev);
u_int32_t cmd;
int error;
/* Initialize private state */
@ -180,7 +179,7 @@ ichsmb_pci_attach(device_t dev)
sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
&sc->io_rid, 0, ~0, 32, RF_ACTIVE);
if (sc->io_res == NULL) {
log(LOG_ERR, "%s: can't map I/O\n", device_get_nameunit(dev));
device_printf(dev, "can't map I/O\n");
error = ENXIO;
goto fail;
}
@ -192,27 +191,7 @@ ichsmb_pci_attach(device_t dev)
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->irq_rid, RF_ACTIVE | RF_SHAREABLE);
if (sc->irq_res == NULL) {
log(LOG_ERR, "%s: can't get IRQ\n", device_get_nameunit(dev));
error = ENXIO;
goto fail;
}
/* Set up interrupt handler */
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
ichsmb_device_intr, sc, &sc->irq_handle);
if (error != 0) {
log(LOG_ERR, "%s: can't setup irq\n", device_get_nameunit(dev));
goto fail;
}
/* Enable I/O mapping */
cmd = pci_read_config(dev, PCIR_COMMAND, 4);
cmd |= PCIM_CMD_PORTEN;
pci_write_config(dev, PCIR_COMMAND, cmd, 4);
cmd = pci_read_config(dev, PCIR_COMMAND, 4);
if ((cmd & PCIM_CMD_PORTEN) == 0) {
log(LOG_ERR, "%s: can't enable memory map\n",
device_get_nameunit(dev));
device_printf(dev, "can't get IRQ\n");
error = ENXIO;
goto fail;
}
@ -221,7 +200,10 @@ ichsmb_pci_attach(device_t dev)
pci_write_config(dev, ICH_HOSTC, ICH_HOSTC_HST_EN, 1);
/* Done */
return (ichsmb_attach(dev));
error = ichsmb_attach(dev);
if (error)
goto fail;
return (0);
fail:
/* Attach failed, release resources */

View file

@ -32,11 +32,12 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/resource.h>
@ -45,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/iicbus/iiconf.h>
#include <dev/smbus/smbconf.h>
#include "smbus_if.h"
@ -59,10 +59,8 @@ static int alpm_debug = 0;
#define ACER_M1543_PMU_ID 0x710110b9
/* Uncomment this line to force another I/O base address for SMB */
/* #define ALPM_SMBIO_BASE_ADDR 0x3a80 */
/* I/O registers offsets - the base address is programmed via the
/*
* I/O registers offsets - the base address is programmed via the
* SMBBA PCI configuration register
*/
#define SMBSTS 0x0 /* SMBus host/slave status register */
@ -74,6 +72,9 @@ static int alpm_debug = 0;
#define SMBHBLOCK 0x6 /* block register for host controller */
#define SMBHCMD 0x7 /* command register for host controller */
/* SMBHADDR mask. */
#define LSB 0x1 /* XXX: Better name: Read/Write? */
/* SMBSTS masks */
#define TERMINATE 0x80
#define BUS_COLLI 0x40
@ -101,7 +102,7 @@ static int alpm_debug = 0;
#define COM 0x4
#define COM_ENABLE_IO 0x1
#define SMBBA 0x14
#define SMBBA PCIR_BAR(1)
#define ATPC 0x5b
#define ATPC_SMBCTRL 0x04 /* XX linux has this as 0x6 */
@ -126,44 +127,27 @@ struct alpm_softc {
bus_space_tag_t smbst;
bus_space_handle_t smbsh;
device_t smbus;
struct mtx lock;
};
#define ALPM_LOCK(alpm) mtx_lock(&(alpm)->lock)
#define ALPM_UNLOCK(alpm) mtx_unlock(&(alpm)->lock)
#define ALPM_LOCK_ASSERT(alpm) mtx_assert(&(alpm)->lock, MA_OWNED)
#define ALPM_SMBINB(alpm,register) \
(bus_space_read_1(alpm->smbst, alpm->smbsh, register))
#define ALPM_SMBOUTB(alpm,register,value) \
(bus_space_write_1(alpm->smbst, alpm->smbsh, register, value))
static int alpm_detach(device_t dev);
static int
alpm_probe(device_t dev)
{
#ifdef ALPM_SMBIO_BASE_ADDR
u_int32_t l;
#endif
if (pci_get_devid(dev) == ACER_M1543_PMU_ID) {
device_set_desc(dev, "AcerLabs M15x3 Power Management Unit");
#ifdef ALPM_SMBIO_BASE_ADDR
if (bootverbose || alpm_debug)
device_printf(dev, "forcing base I/O at 0x%x\n",
ALPM_SMBIO_BASE_ADDR);
/* disable I/O */
l = pci_read_config(dev, COM, 2);
pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2);
/* set the I/O base address */
pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4);
/* enable I/O */
pci_write_config(dev, COM, l | COM_ENABLE_IO, 2);
if (bus_set_resource(dev, SYS_RES_IOPORT, SMBBA,
ALPM_SMBIO_BASE_ADDR, 256)) {
device_printf(dev, "could not set bus resource\n");
return (ENXIO);
}
#endif
return (BUS_PROBE_DEFAULT);
}
@ -234,9 +218,14 @@ alpm_attach(device_t dev)
}
alpm->smbst = rman_get_bustag(alpm->res);
alpm->smbsh = rman_get_bushandle(alpm->res);
mtx_init(&alpm->lock, device_get_nameunit(dev), "alpm", MTX_DEF);
/* attach the smbus */
alpm->smbus = device_add_child(dev, "smbus", -1);
if (alpm->smbus == NULL) {
alpm_detach(dev);
return (EINVAL);
}
bus_generic_attach(dev);
return (0);
@ -251,6 +240,7 @@ alpm_detach(device_t dev)
device_delete_child(dev, alpm->smbus);
alpm->smbus = NULL;
}
mtx_destroy(&alpm->lock);
if (alpm->res)
bus_release_resource(dev, SYS_RES_IOPORT, SMBBA, alpm->res);
@ -317,7 +307,7 @@ alpm_wait(struct alpm_softc *sc)
int error;
/* wait for command to complete and SMBus controller is idle */
while(count--) {
while (count--) {
DELAY(10);
sts = ALPM_SMBINB(sc, SMBSTS);
if (sts & SMI_I_STS)
@ -352,9 +342,12 @@ alpm_quick(device_t dev, u_char slave, int how)
struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (EBUSY);
}
switch (how) {
case SMB_QWRITE:
@ -375,6 +368,7 @@ alpm_quick(device_t dev, u_char slave, int how)
error = alpm_wait(sc);
ALPM_DEBUG(printf(", error=0x%x\n", error));
ALPM_UNLOCK(sc);
return (error);
}
@ -385,9 +379,12 @@ alpm_sendb(device_t dev, u_char slave, char byte)
struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE);
@ -397,6 +394,7 @@ alpm_sendb(device_t dev, u_char slave, char byte)
error = alpm_wait(sc);
ALPM_DEBUG(printf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
ALPM_UNLOCK(sc);
return (error);
}
@ -407,9 +405,12 @@ alpm_recvb(device_t dev, u_char slave, char *byte)
struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE);
@ -419,6 +420,7 @@ alpm_recvb(device_t dev, u_char slave, char *byte)
*byte = ALPM_SMBINB(sc, SMBHDATA);
ALPM_DEBUG(printf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
ALPM_UNLOCK(sc);
return (error);
}
@ -429,9 +431,12 @@ alpm_writeb(device_t dev, u_char slave, char cmd, char byte)
struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE);
@ -442,6 +447,7 @@ alpm_writeb(device_t dev, u_char slave, char cmd, char byte)
error = alpm_wait(sc);
ALPM_DEBUG(printf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
ALPM_UNLOCK(sc);
return (error);
}
@ -452,9 +458,12 @@ alpm_readb(device_t dev, u_char slave, char cmd, char *byte)
struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE);
@ -465,6 +474,7 @@ alpm_readb(device_t dev, u_char slave, char cmd, char *byte)
*byte = ALPM_SMBINB(sc, SMBHDATA);
ALPM_DEBUG(printf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
ALPM_UNLOCK(sc);
return (error);
}
@ -475,9 +485,12 @@ alpm_writew(device_t dev, u_char slave, char cmd, short word)
struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD);
@ -489,6 +502,7 @@ alpm_writew(device_t dev, u_char slave, char cmd, short word)
error = alpm_wait(sc);
ALPM_DEBUG(printf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
ALPM_UNLOCK(sc);
return (error);
}
@ -500,9 +514,12 @@ alpm_readw(device_t dev, u_char slave, char cmd, short *word)
int error;
u_char high, low;
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD);
@ -517,6 +534,7 @@ alpm_readw(device_t dev, u_char slave, char cmd, short *word)
}
ALPM_DEBUG(printf("alpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
ALPM_UNLOCK(sc);
return (error);
}
@ -530,9 +548,13 @@ alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
if (count < 1 || count > 32)
return (SMB_EINVAL);
ALPM_LOCK(sc);
alpm_clear(sc);
if(!alpm_idle(sc))
if(!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
@ -553,6 +575,7 @@ alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
error = alpm_wait(sc);
ALPM_DEBUG(printf("alpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
ALPM_UNLOCK(sc);
return (error);
}
@ -566,9 +589,13 @@ alpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
if (*count < 1 || *count > 32)
return (SMB_EINVAL);
ALPM_LOCK(sc);
alpm_clear(sc);
if (!alpm_idle(sc))
if (!alpm_idle(sc)) {
ALPM_UNLOCK(sc);
return (SMB_EBUSY);
}
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
@ -595,6 +622,7 @@ alpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
error:
ALPM_DEBUG(printf("alpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
ALPM_UNLOCK(sc);
return (error);
}

View file

@ -36,11 +36,12 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/resource.h>
@ -49,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/iicbus/iiconf.h>
#include <dev/smbus/smbconf.h>
#include "smbus_if.h"
@ -108,6 +108,8 @@ static int amdpm_debug = 0;
#define AMDSMB_GE_CYC_PROCCALL 4
#define AMDSMB_GE_CYC_BLOCK 5
#define LSB 0x1 /* XXX: Better name: Read/Write? */
#define AMDSMB_HSTADDR (0x04)
#define AMDSMB_HSTDATA (0x06)
#define AMDSMB_HSTCMD (0x08)
@ -123,10 +125,14 @@ struct amdpm_softc {
struct resource *res;
bus_space_tag_t smbst;
bus_space_handle_t smbsh;
device_t smbus;
struct mtx lock;
};
#define AMDPM_LOCK(amdpm) mtx_lock(&(amdpm)->lock)
#define AMDPM_UNLOCK(amdpm) mtx_unlock(&(amdpm)->lock)
#define AMDPM_LOCK_ASSERT(amdpm) mtx_assert(&(amdpm)->lock, MA_OWNED)
#define AMDPM_SMBINB(amdpm,register) \
(bus_space_read_1(amdpm->smbst, amdpm->smbsh, register))
#define AMDPM_SMBOUTB(amdpm,register,value) \
@ -136,6 +142,8 @@ struct amdpm_softc {
#define AMDPM_SMBOUTW(amdpm,register,value) \
(bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value))
static int amdpm_detach(device_t dev);
static int
amdpm_probe(device_t dev)
{
@ -207,11 +215,14 @@ amdpm_attach(device_t dev)
amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res);
amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res);
mtx_init(&amdpm_sc->lock, device_get_nameunit(dev), "amdpm", MTX_DEF);
/* Allocate a new smbus device */
amdpm_sc->smbus = device_add_child(dev, "smbus", -1);
if (!amdpm_sc->smbus)
if (!amdpm_sc->smbus) {
amdpm_detach(dev);
return (EINVAL);
}
bus_generic_attach(dev);
@ -228,6 +239,7 @@ amdpm_detach(device_t dev)
amdpm_sc->smbus = NULL;
}
mtx_destroy(&amdpm_sc->lock);
if (amdpm_sc->res)
bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid,
amdpm_sc->res);
@ -254,6 +266,8 @@ amdpm_callback(device_t dev, int index, void *data)
static int
amdpm_clear(struct amdpm_softc *sc)
{
AMDPM_LOCK_ASSERT(sc);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS);
DELAY(10);
@ -278,6 +292,7 @@ amdpm_idle(struct amdpm_softc *sc)
{
u_short sts;
AMDPM_LOCK_ASSERT(sc);
sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts));
@ -295,6 +310,7 @@ amdpm_wait(struct amdpm_softc *sc)
u_short sts = 0;
int error;
AMDPM_LOCK_ASSERT(sc);
/* Wait for command to complete (SMBus controller is idle) */
while(count--) {
DELAY(10);
@ -332,9 +348,12 @@ amdpm_quick(device_t dev, u_char slave, int how)
int error;
u_short l;
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (EBUSY);
}
switch (how) {
case SMB_QWRITE:
@ -354,6 +373,7 @@ amdpm_quick(device_t dev, u_char slave, int how)
error = amdpm_wait(sc);
AMDPM_DEBUG(printf(", error=0x%x\n", error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -365,9 +385,12 @@ amdpm_sendb(device_t dev, u_char slave, char byte)
int error;
u_short l;
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
@ -377,6 +400,7 @@ amdpm_sendb(device_t dev, u_char slave, char byte)
error = amdpm_wait(sc);
AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -388,9 +412,12 @@ amdpm_recvb(device_t dev, u_char slave, char *byte)
int error;
u_short l;
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
@ -400,6 +427,7 @@ amdpm_recvb(device_t dev, u_char slave, char *byte)
*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -411,9 +439,12 @@ amdpm_writeb(device_t dev, u_char slave, char cmd, char byte)
int error;
u_short l;
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
@ -424,6 +455,7 @@ amdpm_writeb(device_t dev, u_char slave, char cmd, char byte)
error = amdpm_wait(sc);
AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -435,9 +467,12 @@ amdpm_readb(device_t dev, u_char slave, char cmd, char *byte)
int error;
u_short l;
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
@ -448,6 +483,7 @@ amdpm_readb(device_t dev, u_char slave, char cmd, char *byte)
*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -459,9 +495,12 @@ amdpm_writew(device_t dev, u_char slave, char cmd, short word)
int error;
u_short l;
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word);
@ -472,6 +511,7 @@ amdpm_writew(device_t dev, u_char slave, char cmd, short word)
error = amdpm_wait(sc);
AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -483,9 +523,12 @@ amdpm_readw(device_t dev, u_char slave, char cmd, short *word)
int error;
u_short l;
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
@ -496,6 +539,7 @@ amdpm_readw(device_t dev, u_char slave, char cmd, short *word)
*word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -510,9 +554,13 @@ amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
if (count < 1 || count > 32)
return (SMB_EINVAL);
AMDPM_LOCK(sc);
amdpm_clear(sc);
if(!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
@ -535,6 +583,7 @@ amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
error = amdpm_wait(sc);
AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
AMDPM_UNLOCK(sc);
return (error);
}
@ -549,9 +598,13 @@ amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
if (*count < 1 || *count > 32)
return (SMB_EINVAL);
AMDPM_LOCK(sc);
amdpm_clear(sc);
if (!amdpm_idle(sc))
if (!amdpm_idle(sc)) {
AMDPM_UNLOCK(sc);
return (SMB_EBUSY);
}
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
@ -577,6 +630,7 @@ amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
error:
AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
AMDPM_UNLOCK(sc);
return (error);
}

View file

@ -2,11 +2,12 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/resource.h>
@ -15,7 +16,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/iicbus/iiconf.h>
#include <dev/smbus/smbconf.h>
#include "smbus_if.h"
@ -86,15 +86,21 @@ struct amdsmb_softc {
struct resource *res;
bus_space_tag_t smbst;
bus_space_handle_t smbsh;
device_t smbus;
struct mtx lock;
};
#define AMDSMB_ECINB(amdsmb, register) \
#define AMDSMB_LOCK(amdsmb) mtx_lock(&(amdsmb)->lock)
#define AMDSMB_UNLOCK(amdsmb) mtx_unlock(&(amdsmb)->lock)
#define AMDSMB_LOCK_ASSERT(amdsmb) mtx_assert(&(amdsmb)->lock, MA_OWNED)
#define AMDSMB_ECINB(amdsmb, register) \
(bus_space_read_1(amdsmb->smbst, amdsmb->smbsh, register))
#define AMDSMB_ECOUTB(amdsmb, register, value) \
(bus_space_write_1(amdsmb->smbst, amdsmb->smbsh, register, value))
static int amdsmb_detach(device_t dev);
static int
amdsmb_probe(device_t dev)
{
@ -133,11 +139,14 @@ amdsmb_attach(device_t dev)
amdsmb_sc->smbst = rman_get_bustag(amdsmb_sc->res);
amdsmb_sc->smbsh = rman_get_bushandle(amdsmb_sc->res);
mtx_init(&amdsmb_sc->lock, device_get_nameunit(dev), "amdsmb", MTX_DEF);
/* Allocate a new smbus device */
amdsmb_sc->smbus = device_add_child(dev, "smbus", -1);
if (!amdsmb_sc->smbus)
if (!amdsmb_sc->smbus) {
amdsmb_detach(dev);
return (EINVAL);
}
bus_generic_attach(dev);
@ -154,6 +163,7 @@ amdsmb_detach(device_t dev)
amdsmb_sc->smbus = NULL;
}
mtx_destroy(&amdsmb_sc->lock);
if (amdsmb_sc->res)
bus_release_resource(dev, SYS_RES_IOPORT, amdsmb_sc->rid,
amdsmb_sc->res);
@ -209,6 +219,7 @@ static int
amdsmb_ec_read(struct amdsmb_softc *sc, u_char addr, u_char *data)
{
AMDSMB_LOCK_ASSERT(sc);
if (amdsmb_ec_wait_write(sc))
return (1);
AMDSMB_ECOUTB(sc, EC_CMD, EC_CMD_RD);
@ -228,6 +239,7 @@ static int
amdsmb_ec_write(struct amdsmb_softc *sc, u_char addr, u_char data)
{
AMDSMB_LOCK_ASSERT(sc);
if (amdsmb_ec_wait_write(sc))
return (1);
AMDSMB_ECOUTB(sc, EC_CMD, EC_CMD_WR);
@ -249,6 +261,7 @@ amdsmb_wait(struct amdsmb_softc *sc)
u_char sts, temp;
int error, count;
AMDSMB_LOCK_ASSERT(sc);
amdsmb_ec_read(sc, SMB_PRTCL, &temp);
if (temp != 0)
{
@ -313,12 +326,14 @@ amdsmb_quick(device_t dev, u_char slave, int how)
panic("%s: unknown QUICK command (%x)!", __func__, how);
}
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, protocol);
error = amdsmb_wait(sc);
AMDSMB_DEBUG(printf(", error=0x%x\n", error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -329,6 +344,7 @@ amdsmb_sendb(device_t dev, u_char slave, char byte)
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_CMD, byte);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE);
@ -337,6 +353,7 @@ amdsmb_sendb(device_t dev, u_char slave, char byte)
AMDSMB_DEBUG(printf("amdsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n",
slave, byte, error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -347,6 +364,7 @@ amdsmb_recvb(device_t dev, u_char slave, char *byte)
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE);
@ -355,6 +373,7 @@ amdsmb_recvb(device_t dev, u_char slave, char *byte)
AMDSMB_DEBUG(printf("amdsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n",
slave, *byte, error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -365,6 +384,7 @@ amdsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_DATA, byte);
amdsmb_ec_write(sc, SMB_ADDR, slave);
@ -374,6 +394,7 @@ amdsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
AMDSMB_DEBUG(printf("amdsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, "
"error=0x%x\n", slave, cmd, byte, error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -384,6 +405,7 @@ amdsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA);
@ -393,6 +415,7 @@ amdsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
AMDSMB_DEBUG(printf("amdsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, "
"error=0x%x\n", slave, cmd, (unsigned char)*byte, error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -403,6 +426,7 @@ amdsmb_writew(device_t dev, u_char slave, char cmd, short word)
struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
int error;
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_DATA, word);
amdsmb_ec_write(sc, SMB_DATA + 1, word >> 8);
@ -413,6 +437,7 @@ amdsmb_writew(device_t dev, u_char slave, char cmd, short word)
AMDSMB_DEBUG(printf("amdsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, "
"error=0x%x\n", slave, cmd, word, error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -424,6 +449,7 @@ amdsmb_readw(device_t dev, u_char slave, char cmd, short *word)
u_char temp[2];
int error;
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA);
@ -436,6 +462,7 @@ amdsmb_readw(device_t dev, u_char slave, char cmd, short *word)
AMDSMB_DEBUG(printf("amdsmb: READW from 0x%x, cmd=0x%x, word=0x%x, "
"error=0x%x\n", slave, cmd, (unsigned short)*word, error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -449,6 +476,8 @@ amdsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
if (count < 1 || count > 32)
return (SMB_EINVAL);
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_BCNT, count);
for (i = 0; i < count; i++)
@ -460,6 +489,7 @@ amdsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
AMDSMB_DEBUG(printf("amdsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, "
"error=0x%x", slave, count, cmd, error));
AMDSMB_UNLOCK(sc);
return (error);
}
@ -473,6 +503,8 @@ amdsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
if (*count < 1 || *count > 32)
return (SMB_EINVAL);
AMDSMB_LOCK(sc);
amdsmb_ec_write(sc, SMB_CMD, cmd);
amdsmb_ec_write(sc, SMB_ADDR, slave);
amdsmb_ec_write(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA);
@ -489,6 +521,7 @@ amdsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
AMDSMB_DEBUG(printf("amdsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, "
"error=0x%x", slave, *count, cmd, error));
AMDSMB_UNLOCK(sc);
return (error);
}

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,7 @@
/* PCI Config Registers. */
#define PCI_BASE_ADDR_SMB 0x90 /* IO BAR. */
#define PCI_BASE_ADDR_PM 0x40
#define PCI_HST_CFG_SMB 0xd2 /*Host Configuration*/
#define PCI_HST_CFG_SMB 0xd2 /* Host Configuration */
#define PCI_INTR_SMB_SMI 0
#define PCI_INTR_SMB_IRQ9 8
#define PCI_INTR_SMB_ENABLE 1

View file

@ -2,11 +2,12 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/resource.h>
@ -15,7 +16,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/iicbus/iiconf.h>
#include <dev/smbus/smbconf.h>
#include "smbus_if.h"
@ -86,16 +86,23 @@ struct nfsmb_softc {
struct resource *res;
bus_space_tag_t smbst;
bus_space_handle_t smbsh;
device_t smbus;
device_t subdev;
struct mtx lock;
};
#define NFSMB_SMBINB(nfsmb, register) \
#define NFSMB_LOCK(nfsmb) mtx_lock(&(nfsmb)->lock)
#define NFSMB_UNLOCK(nfsmb) mtx_unlock(&(nfsmb)->lock)
#define NFSMB_LOCK_ASSERT(nfsmb) mtx_assert(&(nfsmb)->lock, MA_OWNED)
#define NFSMB_SMBINB(nfsmb, register) \
(bus_space_read_1(nfsmb->smbst, nfsmb->smbsh, register))
#define NFSMB_SMBOUTB(nfsmb, register, value) \
(bus_space_write_1(nfsmb->smbst, nfsmb->smbsh, register, value))
static int nfsmb_detach(device_t dev);
static int nfsmbsub_detach(device_t dev);
static int
nfsmbsub_probe(device_t dev)
{
@ -155,10 +162,14 @@ nfsmbsub_attach(device_t dev)
}
nfsmbsub_sc->smbst = rman_get_bustag(nfsmbsub_sc->res);
nfsmbsub_sc->smbsh = rman_get_bushandle(nfsmbsub_sc->res);
mtx_init(&nfsmbsub_sc->lock, device_get_nameunit(dev), "nfsmb",
MTX_DEF);
nfsmbsub_sc->smbus = device_add_child(dev, "smbus", -1);
if (nfsmbsub_sc->smbus == NULL)
if (nfsmbsub_sc->smbus == NULL) {
nfsmbsub_detach(dev);
return (EINVAL);
}
bus_generic_attach(dev);
@ -189,11 +200,14 @@ nfsmb_attach(device_t dev)
nfsmb_sc->smbst = rman_get_bustag(nfsmb_sc->res);
nfsmb_sc->smbsh = rman_get_bushandle(nfsmb_sc->res);
mtx_init(&nfsmb_sc->lock, device_get_nameunit(dev), "nfsmb", MTX_DEF);
/* Allocate a new smbus device */
nfsmb_sc->smbus = device_add_child(dev, "smbus", -1);
if (!nfsmb_sc->smbus)
if (!nfsmb_sc->smbus) {
nfsmb_detach(dev);
return (EINVAL);
}
nfsmb_sc->subdev = NULL;
switch (pci_get_device(dev)) {
@ -207,8 +221,10 @@ nfsmb_attach(device_t dev)
case NFSMB_DEVICEID_NF4_55_SMB:
/* Trying to add secondary device as slave */
nfsmb_sc->subdev = device_add_child(dev, "nfsmb", -1);
if (!nfsmb_sc->subdev)
if (!nfsmb_sc->subdev) {
nfsmb_detach(dev);
return (EINVAL);
}
break;
default:
break;
@ -231,6 +247,7 @@ nfsmbsub_detach(device_t dev)
device_delete_child(dev, nfsmbsub_sc->smbus);
nfsmbsub_sc->smbus = NULL;
}
mtx_destroy(&nfsmbsub_sc->lock);
if (nfsmbsub_sc->res) {
bus_release_resource(parent, SYS_RES_IOPORT, nfsmbsub_sc->rid,
nfsmbsub_sc->res);
@ -254,6 +271,7 @@ nfsmb_detach(device_t dev)
nfsmb_sc->smbus = NULL;
}
mtx_destroy(&nfsmb_sc->lock);
if (nfsmb_sc->res) {
bus_release_resource(dev, SYS_RES_IOPORT, nfsmb_sc->rid,
nfsmb_sc->res);
@ -285,6 +303,7 @@ nfsmb_wait(struct nfsmb_softc *sc)
u_char sts;
int error, count;
NFSMB_LOCK_ASSERT(sc);
if (NFSMB_SMBINB(sc, SMB_PRTCL) != 0)
{
count = 10000;
@ -346,12 +365,14 @@ nfsmb_quick(device_t dev, u_char slave, int how)
panic("%s: unknown QUICK command (%x)!", __func__, how);
}
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, protocol);
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf(", error=0x%x\n", error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -362,6 +383,7 @@ nfsmb_sendb(device_t dev, u_char slave, char byte)
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_CMD, byte);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_WRITE | SMB_PRTCL_BYTE);
@ -369,6 +391,7 @@ nfsmb_sendb(device_t dev, u_char slave, char byte)
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -379,6 +402,7 @@ nfsmb_recvb(device_t dev, u_char slave, char *byte)
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE);
@ -386,6 +410,7 @@ nfsmb_recvb(device_t dev, u_char slave, char *byte)
*byte = NFSMB_SMBINB(sc, SMB_DATA);
NFSMB_DEBUG(printf("nfsmb: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -396,6 +421,7 @@ nfsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_DATA, byte);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
@ -404,6 +430,7 @@ nfsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -414,6 +441,7 @@ nfsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BYTE_DATA);
@ -422,6 +450,7 @@ nfsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
*byte = NFSMB_SMBINB(sc, SMB_DATA);
NFSMB_DEBUG(printf("nfsmb: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, (unsigned char)*byte, error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -432,6 +461,7 @@ nfsmb_writew(device_t dev, u_char slave, char cmd, short word)
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_DATA, word);
NFSMB_SMBOUTB(sc, SMB_DATA + 1, word >> 8);
@ -441,6 +471,7 @@ nfsmb_writew(device_t dev, u_char slave, char cmd, short word)
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -451,6 +482,7 @@ nfsmb_readw(device_t dev, u_char slave, char cmd, short *word)
struct nfsmb_softc *sc = (struct nfsmb_softc *)device_get_softc(dev);
int error;
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_WORD_DATA);
@ -460,6 +492,7 @@ nfsmb_readw(device_t dev, u_char slave, char cmd, short *word)
(NFSMB_SMBINB(sc, SMB_DATA + 1) << 8);
NFSMB_DEBUG(printf("nfsmb: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, (unsigned short)*word, error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -473,6 +506,8 @@ nfsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
if (count < 1 || count > 32)
return (SMB_EINVAL);
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_BCNT, count);
for (i = 0; i < count; i++)
@ -483,6 +518,7 @@ nfsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
error = nfsmb_wait(sc);
NFSMB_DEBUG(printf("nfsmb: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
NFSMB_UNLOCK(sc);
return (error);
}
@ -496,6 +532,8 @@ nfsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
if (*count < 1 || *count > 32)
return (SMB_EINVAL);
NFSMB_LOCK(sc);
NFSMB_SMBOUTB(sc, SMB_CMD, cmd);
NFSMB_SMBOUTB(sc, SMB_ADDR, slave);
NFSMB_SMBOUTB(sc, SMB_PRTCL, SMB_PRTCL_READ | SMB_PRTCL_BLOCK_DATA);
@ -511,6 +549,7 @@ nfsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
}
NFSMB_DEBUG(printf("nfsmb: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
NFSMB_UNLOCK(sc);
return (error);
}

View file

@ -30,11 +30,12 @@ __FBSDID("$FreeBSD$");
#include "opt_isa.h"
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/resource.h>
@ -82,6 +83,10 @@ static int viapm_debug = 0;
#define VIAPM_TYP_686A 4
#define VIAPM_TYP_8233 5
#define VIAPM_LOCK(sc) mtx_lock(&(sc)->lock)
#define VIAPM_UNLOCK(sc) mtx_unlock(&(sc)->lock)
#define VIAPM_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED)
struct viapm_softc {
int type;
u_int32_t base;
@ -92,9 +97,9 @@ struct viapm_softc {
struct resource *iores;
struct resource *irqres;
void *irqih;
device_t iicbb;
device_t smbus;
struct mtx lock;
};
static devclass_t viapm_devclass;
@ -329,6 +334,7 @@ viapm_pro_attach(device_t dev)
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
u_int32_t l;
mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
&viapm->iorid, RF_ACTIVE))) {
device_printf(dev, "could not allocate bus space\n");
@ -394,6 +400,7 @@ viapm_pro_attach(device_t dev)
if (viapm->irqres)
bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
#endif
mtx_destroy(&viapm->lock);
return ENXIO;
}
@ -402,11 +409,12 @@ static int
viapm_586b_attach(device_t dev)
{
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
&viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) {
device_printf(dev, "could not allocate bus resource\n");
return ENXIO;
goto error;
}
viapm->st = rman_get_bustag(viapm->iores);
viapm->sh = rman_get_bushandle(viapm->iores);
@ -425,6 +433,7 @@ viapm_586b_attach(device_t dev)
if (viapm->iores)
bus_release_resource(dev, SYS_RES_IOPORT,
viapm->iorid, viapm->iores);
mtx_destroy(&viapm->lock);
return ENXIO;
}
@ -432,16 +441,16 @@ static int
viapm_586b_detach(device_t dev)
{
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
bus_generic_detach(dev);
if (viapm->iicbb) {
device_delete_child(dev, viapm->iicbb);
}
if (viapm->iores && (error = bus_release_resource(dev, SYS_RES_IOPORT,
viapm->iorid, viapm->iores)))
return (error);
if (viapm->iores)
bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid,
viapm->iores);
mtx_destroy(&viapm->lock);
return 0;
}
@ -450,22 +459,18 @@ static int
viapm_pro_detach(device_t dev)
{
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
bus_generic_detach(dev);
if (viapm->smbus) {
device_delete_child(dev, viapm->smbus);
}
if ((error = bus_release_resource(dev, SYS_RES_IOPORT,
viapm->iorid, viapm->iores)))
return (error);
bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
#ifdef notyet
if ((error = bus_release_resource(dev, SYS_RES_IRQ,
viapm->irqrid, viapm->irqres))
return (error);
bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
#endif
mtx_destroy(&viapm->lock);
return 0;
}
@ -482,6 +487,7 @@ viabb_setscl(device_t dev, int ctrl)
struct viapm_softc *viapm = device_get_softc(dev);
u_char val;
VIAPM_LOCK(viapm);
val = VIAPM_INB(GPIO_VAL);
if (ctrl)
@ -490,6 +496,7 @@ viabb_setscl(device_t dev, int ctrl)
val &= ~VIAPM_SCL;
VIAPM_OUTB(GPIO_VAL, val);
VIAPM_UNLOCK(viapm);
return;
}
@ -500,6 +507,7 @@ viabb_setsda(device_t dev, int data)
struct viapm_softc *viapm = device_get_softc(dev);
u_char val;
VIAPM_LOCK(viapm);
val = VIAPM_INB(GPIO_VAL);
if (data)
@ -508,6 +516,7 @@ viabb_setsda(device_t dev, int data)
val &= ~VIAPM_SDA;
VIAPM_OUTB(GPIO_VAL, val);
VIAPM_UNLOCK(viapm);
return;
}
@ -526,16 +535,24 @@ static int
viabb_getscl(device_t dev)
{
struct viapm_softc *viapm = device_get_softc(dev);
u_char val;
return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0);
VIAPM_LOCK(viapm);
val = VIAPM_INB(EXTSMI_VAL);
VIAPM_UNLOCK(viapm);
return ((val & VIAPM_SCL) != 0);
}
static int
viabb_getsda(device_t dev)
{
struct viapm_softc *viapm = device_get_softc(dev);
u_char val;
return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0);
VIAPM_LOCK(viapm);
val = VIAPM_INB(EXTSMI_VAL);
VIAPM_UNLOCK(viapm);
return ((val & VIAPM_SDA) != 0);
}
static int
@ -579,6 +596,8 @@ viapm_wait(struct viapm_softc *viapm)
u_char sts = 0;
int error;
VIAPM_LOCK_ASSERT(viapm);
/* wait for command to complete and SMBus controller is idle */
while(count--) {
DELAY(10);
@ -636,9 +655,12 @@ viasmb_quick(device_t dev, u_char slave, int how)
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
switch (how) {
case SMB_QWRITE:
@ -656,6 +678,7 @@ viasmb_quick(device_t dev, u_char slave, int how)
VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
error = viapm_wait(viapm);
VIAPM_UNLOCK(viapm);
return (error);
}
@ -666,9 +689,12 @@ viasmb_sendb(device_t dev, u_char slave, char byte)
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
VIAPM_OUTB(SMBHCMD, byte);
@ -678,6 +704,7 @@ viasmb_sendb(device_t dev, u_char slave, char byte)
error = viapm_wait(viapm);
VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
VIAPM_UNLOCK(viapm);
return (error);
}
@ -688,9 +715,12 @@ viasmb_recvb(device_t dev, u_char slave, char *byte)
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave | LSB);
@ -700,6 +730,7 @@ viasmb_recvb(device_t dev, u_char slave, char *byte)
*byte = VIAPM_INB(SMBHDATA0);
VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
VIAPM_UNLOCK(viapm);
return (error);
}
@ -710,9 +741,12 @@ viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
VIAPM_OUTB(SMBHCMD, cmd);
@ -723,6 +757,7 @@ viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
error = viapm_wait(viapm);
VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
VIAPM_UNLOCK(viapm);
return (error);
}
@ -733,9 +768,12 @@ viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave | LSB);
VIAPM_OUTB(SMBHCMD, cmd);
@ -746,6 +784,7 @@ viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
*byte = VIAPM_INB(SMBHDATA0);
VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
VIAPM_UNLOCK(viapm);
return (error);
}
@ -756,9 +795,12 @@ viasmb_writew(device_t dev, u_char slave, char cmd, short word)
struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
int error;
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
VIAPM_OUTB(SMBHCMD, cmd);
@ -770,6 +812,7 @@ viasmb_writew(device_t dev, u_char slave, char cmd, short word)
error = viapm_wait(viapm);
VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
VIAPM_UNLOCK(viapm);
return (error);
}
@ -781,9 +824,12 @@ viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
int error;
u_char high, low;
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave | LSB);
VIAPM_OUTB(SMBHCMD, cmd);
@ -798,6 +844,7 @@ viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
}
VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
VIAPM_UNLOCK(viapm);
return (error);
}
@ -812,9 +859,12 @@ viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
if (count < 1 || count > 32)
return (SMB_EINVAL);
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave & ~LSB);
VIAPM_OUTB(SMBHCMD, cmd);
@ -832,6 +882,7 @@ viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
error = viapm_wait(viapm);
VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
VIAPM_UNLOCK(viapm);
return (error);
@ -847,9 +898,12 @@ viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
if (*count < 1 || *count > 32)
return (SMB_EINVAL);
VIAPM_LOCK(viapm);
viapm_clear(viapm);
if (viapm_busy(viapm))
if (viapm_busy(viapm)) {
VIAPM_UNLOCK(viapm);
return (SMB_EBUSY);
}
VIAPM_OUTB(SMBHADDR, slave | LSB);
VIAPM_OUTB(SMBHCMD, cmd);
@ -872,6 +926,7 @@ viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
error:
VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
VIAPM_UNLOCK(viapm);
return (error);
}