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:
Jared McNeill 2016-05-15 16:43:47 +00:00
parent 4e760f013d
commit 6a94069a5e
2 changed files with 13 additions and 66 deletions
sys/arm/allwinner

View File

@ -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)

View File

@ -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);