Reduce complexity of RSB by always using polling mode. Unfortunately
gpiobus methods can be called with non-sleepable locks held. Reviewed by: mmel
This commit is contained in:
parent
4e760f013d
commit
6a94069a5e
@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/module.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
@ -100,7 +99,6 @@ static struct ofw_compat_data compat_data[] = {
|
||||
|
||||
static struct resource_spec rsb_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
@ -125,12 +123,11 @@ static const struct {
|
||||
};
|
||||
|
||||
struct rsb_softc {
|
||||
struct resource *res[2];
|
||||
struct resource *res;
|
||||
struct mtx mtx;
|
||||
clk_t clk;
|
||||
hwreset_t rst;
|
||||
device_t iicbus;
|
||||
void *ih;
|
||||
int busy;
|
||||
uint32_t status;
|
||||
uint16_t cur_addr;
|
||||
@ -141,8 +138,8 @@ struct rsb_softc {
|
||||
#define RSB_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
#define RSB_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
||||
#define RSB_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED)
|
||||
#define RSB_READ(sc, reg) bus_read_4((sc)->res[0], (reg))
|
||||
#define RSB_WRITE(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val))
|
||||
#define RSB_READ(sc, reg) bus_read_4((sc)->res, (reg))
|
||||
#define RSB_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
|
||||
|
||||
static phandle_t
|
||||
rsb_get_node(device_t bus, device_t dev)
|
||||
@ -202,34 +199,24 @@ static int
|
||||
rsb_start(device_t dev)
|
||||
{
|
||||
struct rsb_softc *sc;
|
||||
int error, retry, polling;
|
||||
int error, retry;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
polling = cold || !THREAD_CAN_SLEEP();
|
||||
|
||||
RSB_ASSERT_LOCKED(sc);
|
||||
|
||||
/* Enable interrupts */
|
||||
if (!polling)
|
||||
RSB_WRITE(sc, RSB_INTE, INT_MASK);
|
||||
|
||||
/* Start the transfer */
|
||||
RSB_WRITE(sc, RSB_CTRL, GLOBAL_INT_ENB | START_TRANS);
|
||||
|
||||
/* Wait for transfer to complete */
|
||||
if (polling) {
|
||||
error = ETIMEDOUT;
|
||||
for (retry = RSB_I2C_TIMEOUT; retry > 0; retry--) {
|
||||
sc->status |= RSB_READ(sc, RSB_INTS);
|
||||
if ((sc->status & INT_TRANS_OVER) != 0) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
DELAY((1000 * hz) / RSB_I2C_TIMEOUT);
|
||||
error = ETIMEDOUT;
|
||||
for (retry = RSB_I2C_TIMEOUT; retry > 0; retry--) {
|
||||
sc->status |= RSB_READ(sc, RSB_INTS);
|
||||
if ((sc->status & INT_TRANS_OVER) != 0) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
error = mtx_sleep(sc, &sc->mtx, 0, "i2ciowait",
|
||||
RSB_I2C_TIMEOUT);
|
||||
DELAY((1000 * hz) / RSB_I2C_TIMEOUT);
|
||||
}
|
||||
if (error == 0 && (sc->status & INT_TRANS_OVER) == 0) {
|
||||
device_printf(dev, "transfer error, status 0x%08x\n",
|
||||
@ -237,9 +224,6 @@ rsb_start(device_t dev)
|
||||
error = EIO;
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
RSB_WRITE(sc, RSB_INTE, 0);
|
||||
|
||||
return (error);
|
||||
|
||||
}
|
||||
@ -389,23 +373,6 @@ rsb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
rsb_intr(void *arg)
|
||||
{
|
||||
struct rsb_softc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = arg;
|
||||
|
||||
RSB_LOCK(sc);
|
||||
val = RSB_READ(sc, RSB_INTS);
|
||||
RSB_WRITE(sc, RSB_INTS, val);
|
||||
sc->status |= val;
|
||||
if ((sc->status & INT_MASK) != 0)
|
||||
wakeup(sc);
|
||||
RSB_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
rsb_probe(device_t dev)
|
||||
{
|
||||
@ -443,19 +410,12 @@ rsb_attach(device_t dev)
|
||||
}
|
||||
}
|
||||
|
||||
if (bus_alloc_resources(dev, rsb_spec, sc->res) != 0) {
|
||||
if (bus_alloc_resources(dev, rsb_spec, &sc->res) != 0) {
|
||||
device_printf(dev, "cannot allocate resources for device\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, rsb_intr, sc, &sc->ih);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "cannot setup interrupt handler\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sc->iicbus = device_add_child(dev, "iicbus", -1);
|
||||
if (sc->iicbus == NULL) {
|
||||
device_printf(dev, "cannot add iicbus child device\n");
|
||||
@ -468,9 +428,7 @@ rsb_attach(device_t dev)
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
if (sc->ih != NULL)
|
||||
bus_teardown_intr(dev, sc->res[1], sc->ih);
|
||||
bus_release_resources(dev, rsb_spec, sc->res);
|
||||
bus_release_resources(dev, rsb_spec, &sc->res);
|
||||
if (sc->rst != NULL)
|
||||
hwreset_release(sc->rst);
|
||||
if (sc->clk != NULL)
|
||||
|
@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/gpio.h>
|
||||
#include <sys/module.h>
|
||||
#include <machine/bus.h>
|
||||
@ -246,7 +245,6 @@ axp81x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
AXP_LOCK(sc);
|
||||
THREAD_SLEEPING_OK();
|
||||
error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
|
||||
if (error == 0) {
|
||||
func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
|
||||
@ -258,7 +256,6 @@ axp81x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
|
||||
else
|
||||
*flags = 0;
|
||||
}
|
||||
THREAD_NO_SLEEPING();
|
||||
AXP_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
@ -277,7 +274,6 @@ axp81x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
AXP_LOCK(sc);
|
||||
THREAD_SLEEPING_OK();
|
||||
error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
|
||||
if (error == 0) {
|
||||
data &= ~AXP_GPIO_FUNC;
|
||||
@ -287,7 +283,6 @@ axp81x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
|
||||
}
|
||||
error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
|
||||
}
|
||||
THREAD_NO_SLEEPING();
|
||||
AXP_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
@ -306,7 +301,6 @@ axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
AXP_LOCK(sc);
|
||||
THREAD_SLEEPING_OK();
|
||||
error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
|
||||
if (error == 0) {
|
||||
func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
|
||||
@ -327,7 +321,6 @@ axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
|
||||
break;
|
||||
}
|
||||
}
|
||||
THREAD_NO_SLEEPING();
|
||||
AXP_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
@ -346,7 +339,6 @@ axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
AXP_LOCK(sc);
|
||||
THREAD_SLEEPING_OK();
|
||||
error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
|
||||
if (error == 0) {
|
||||
func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
|
||||
@ -363,7 +355,6 @@ axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
|
||||
}
|
||||
if (error == 0)
|
||||
error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
|
||||
THREAD_NO_SLEEPING();
|
||||
AXP_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
@ -383,7 +374,6 @@ axp81x_gpio_pin_toggle(device_t dev, uint32_t pin)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
AXP_LOCK(sc);
|
||||
THREAD_SLEEPING_OK();
|
||||
error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
|
||||
if (error == 0) {
|
||||
func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
|
||||
@ -403,7 +393,6 @@ axp81x_gpio_pin_toggle(device_t dev, uint32_t pin)
|
||||
}
|
||||
if (error == 0)
|
||||
error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
|
||||
THREAD_NO_SLEEPING();
|
||||
AXP_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
|
Loading…
Reference in New Issue
Block a user