tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: gpio interrups (2)
On Mon, Apr 25, 2016 at 10:29:25PM +0200, Manuel Bouyer wrote:
> Hello,
> here is a second version of my patch to add support for gpio interrupts.
> Based on feedback, I improved the allwinner backend.
> I also changed the gpio(4) implementation to support a callback
> from interrupt context, instead of the thread-based mutex+condvar
> (even for my case it's better as it allows me to use sysmon_taskq(9)
> instead of a dedicated thread).
>
> I still didn't find a good way to deal with IPLs at this point.
> Even pushing the callback suppport to MD code wouldn't work as it would
> also need some callback on spllower() and I can't see how to do this.
> The API supports a IPL parameter but at this point, only IPL_VM
> is allowed.
Attached is an updated patch, where gpio_pin_ctl_intr() checks if a callback
is already registered for a pin and retuns and error code. I think it's
better than KASSERT().
There is an i2c driver using this code:
https://github.com/mbouyer/marine_chartplotter/blob/master/software/NetBSD/driver/picbmc.c
--
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
NetBSD: 26 ans d'experience feront toujours la difference
--
Index: arch/arm/allwinner/awin_gpio.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/allwinner/awin_gpio.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 awin_gpio.c
--- arch/arm/allwinner/awin_gpio.c 2 Oct 2015 16:04:40 -0000 1.20
+++ arch/arm/allwinner/awin_gpio.c 28 Apr 2016 09:13:12 -0000
@@ -57,16 +57,7 @@ static void awin_gpio_attach(device_t, d
static int awin_gpio_pin_read(void *, int);
static void awin_gpio_pin_write(void *, int, int);
static void awin_gpio_pin_ctl(void *, int, int);
-
-#if 0
-static const int ist_maps[] = {
- [IST_LEVEL_LOW] = AWIN_PIO_EINT_LOW_LEVEL,
- [IST_LEVEL_HIGH] = AWIN_PIO_EINT_HIGH_LEVEL,
- [IST_EDGE_FALLING] = AWIN_PIO_EINT_POSITIVE_EDGE,
- [IST_EDGE_RISING] = AWIN_PIO_EINT_NEGATIVE_EDGE,
- [IST_EDGE_BOTH] = AWIN_PIO_EINT_DOUBLE_EDGE,
-};
-#endif
+static void awin_gpio_pin_irqen(void *, int, bool);
struct awin_gpio_pin_cfg {
uint32_t cfg[4];
@@ -77,16 +68,19 @@ struct awin_gpio_pin_cfg {
static struct awin_gpio_pin_group {
bus_addr_t grp_offset;
uint32_t grp_pin_mask;
+ uint32_t grp_pin_intr_mask;
uint32_t grp_pin_inuse_mask;
bus_space_handle_t grp_bsh;
struct awin_gpio_pin_cfg grp_cfg;
struct gpio_chipset_tag grp_gc_tag;
const int grp_index;
const char grp_nc_name[6];
+ device_t grp_gpio_dev;
} pin_groups[] = {
[0] = {
.grp_offset = AWIN_PIO_OFFSET + 0 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PA_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[0],
.gp_pin_read = awin_gpio_pin_read,
@@ -99,6 +93,7 @@ static struct awin_gpio_pin_group {
[1] = {
.grp_offset = AWIN_PIO_OFFSET + 1 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PB_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[1],
.gp_pin_read = awin_gpio_pin_read,
@@ -111,6 +106,7 @@ static struct awin_gpio_pin_group {
[2] = {
.grp_offset = AWIN_PIO_OFFSET + 2 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PC_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[2],
.gp_pin_read = awin_gpio_pin_read,
@@ -123,6 +119,7 @@ static struct awin_gpio_pin_group {
[3] = {
.grp_offset = AWIN_PIO_OFFSET + 3 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PD_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[3],
.gp_pin_read = awin_gpio_pin_read,
@@ -135,6 +132,7 @@ static struct awin_gpio_pin_group {
[4] = {
.grp_offset = AWIN_PIO_OFFSET + 4 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PE_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[4],
.gp_pin_read = awin_gpio_pin_read,
@@ -147,6 +145,7 @@ static struct awin_gpio_pin_group {
[5] = {
.grp_offset = AWIN_PIO_OFFSET + 5 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PF_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[5],
.gp_pin_read = awin_gpio_pin_read,
@@ -159,6 +158,7 @@ static struct awin_gpio_pin_group {
[6] = {
.grp_offset = AWIN_PIO_OFFSET + 6 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PG_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[6],
.gp_pin_read = awin_gpio_pin_read,
@@ -171,11 +171,13 @@ static struct awin_gpio_pin_group {
[7] = {
.grp_offset = AWIN_PIO_OFFSET + 7 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PH_PINS) - 1,
+ .grp_pin_intr_mask = AWIN_PIO_PH_EINT_PINS,
.grp_gc_tag = {
.gp_cookie = &pin_groups[7],
.gp_pin_read = awin_gpio_pin_read,
.gp_pin_write = awin_gpio_pin_write,
.gp_pin_ctl = awin_gpio_pin_ctl,
+ .gp_pin_irqen = awin_gpio_pin_irqen,
},
.grp_index = 7,
.grp_nc_name = "nc-ph",
@@ -183,6 +185,7 @@ static struct awin_gpio_pin_group {
[8] = {
.grp_offset = AWIN_PIO_OFFSET + 8 * AWIN_PIO_GRP_SIZE,
.grp_pin_mask = __BIT(AWIN_PIO_PI_PINS) - 1,
+ .grp_pin_intr_mask = 0,
.grp_gc_tag = {
.gp_cookie = &pin_groups[8],
.gp_pin_read = awin_gpio_pin_read,
@@ -201,6 +204,7 @@ static struct awin_gpio_pin_group {
.gp_pin_ctl = awin_gpio_pin_ctl,
},
.grp_pin_mask = 0,
+ .grp_pin_intr_mask = 0,
.grp_index = 9,
.grp_nc_name = "nc-pj",
},
@@ -213,6 +217,7 @@ static struct awin_gpio_pin_group {
.gp_pin_ctl = awin_gpio_pin_ctl,
},
.grp_pin_mask = 0,
+ .grp_pin_intr_mask = 0,
.grp_index = 10,
.grp_nc_name = "nc-pk",
},
@@ -225,6 +230,7 @@ static struct awin_gpio_pin_group {
.gp_pin_ctl = awin_gpio_pin_ctl,
},
.grp_pin_mask = 0,
+ .grp_pin_intr_mask = 0,
.grp_index = 11,
.grp_nc_name = "nc-pl",
},
@@ -237,6 +243,7 @@ static struct awin_gpio_pin_group {
.gp_pin_ctl = awin_gpio_pin_ctl,
},
.grp_pin_mask = 0,
+ .grp_pin_intr_mask = 0,
.grp_index = 12,
.grp_nc_name = "nc-pm",
},
@@ -249,6 +256,7 @@ static struct awin_gpio_pin_group {
.gp_pin_ctl = awin_gpio_pin_ctl,
},
.grp_pin_mask = 0,
+ .grp_pin_intr_mask = 0,
.grp_nc_name = "nc-pn",
},
};
@@ -258,13 +266,22 @@ static struct awin_gpio_softc {
device_t sc_dev;
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
+ bus_space_handle_t sc_eint_bsh;
+ void *sc_ih;
+ kmutex_t sc_intr_lock;
+ uint32_t sc_ecfg[4];
+ uint32_t sc_eintr_configured;
} awin_gpio_sc = {
.sc_bst = &armv7_generic_bs_tag,
};
+#define INT_OFFSET(x) ((x) - AWIN_PIO_INT_CFG0_REG)
+
CFATTACH_DECL_NEW(awin_gpio, sizeof(struct awin_gpio_softc),
awin_gpio_match, awin_gpio_attach, NULL, NULL);
+static int awin_gpio_intr(void *);
+
static int
awin_gpio_match(device_t parent, cfdata_t cf, void *aux)
{
@@ -345,13 +362,20 @@ awin_gpio_config_pins(device_t self)
pin->pin_num = num + (i << 5);
pin->pin_caps = pincaps;
pin->pin_flags = pincaps;
+ if ((grp->grp_pin_intr_mask & (1 << num)) != 0){
+ pin->pin_caps |=
+ GPIO_PIN_EVENTS |
+ GPIO_PIN_LEVEL |
+ GPIO_PIN_FALLING;
+ }
pin->pin_state = (data & 1) != 0;
pin++;
}
}
gba.gba_npins = pin - gba.gba_pins;
- config_found_ia(self, "gpiobus", &gba, awin_gpio_cfprint);
+ grp->grp_gpio_dev =
+ config_found_ia(self, "gpiobus", &gba, awin_gpio_cfprint);
}
}
#endif /* NGPIO > 0 */
@@ -372,6 +396,15 @@ awin_gpio_attach(device_t parent, device
aprint_naive("\n");
aprint_normal("\n");
+ sc->sc_ih = intr_establish(loc->loc_intr,
+ IPL_VM, IST_LEVEL | IST_MPSAFE,
+ awin_gpio_intr, &awin_gpio_sc);
+ if (sc->sc_ih == NULL) {
+ aprint_error_dev(self, "failed to establish interrupt %d\n",
+ loc->loc_intr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr);
for (u_int i = 0; i < __arraycount(pin_groups); i++) {
struct awin_gpio_pin_group * const grp = &pin_groups[i];
@@ -393,6 +426,32 @@ awin_gpio_attach(device_t parent, device
#endif
}
+static int
+awin_gpio_intr(void *a)
+{
+ struct awin_gpio_softc *sc = a;
+ uint32_t enabled;
+ uint32_t pending;
+ struct awin_gpio_pin_group * const grp = &pin_groups[7]; /* XXX */
+
+ mutex_enter(&sc->sc_intr_lock);
+ enabled = bus_space_read_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_CTL_REG));
+ pending = bus_space_read_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_STA_REG));
+ /* keep only enabled interrupts */
+ pending &= enabled;
+ /* mask and ack pending interrupts */
+ enabled &= ~pending;
+ bus_space_write_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_CTL_REG), enabled);
+ bus_space_write_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_STA_REG), pending);
+ mutex_exit(&sc->sc_intr_lock);
+ gpio_intr(grp->grp_gpio_dev, pending);
+ return 1;
+}
+
static u_int
awin_gpio_get_pin_func(const struct awin_gpio_pin_cfg *cfg, u_int pin)
{
@@ -457,6 +516,47 @@ awin_gpio_update_cfg_regs(bus_space_tag_
}
}
+static void
+awin_gpio_set_pin_eint(struct awin_gpio_softc *sc, int pin, uint32_t m)
+{
+ int g = (pin >> 3);
+ int s = ((pin & 7) * 4);
+ KASSERT(g < 4);
+ sc->sc_ecfg[g] &= ~(0xf << s);
+ sc->sc_ecfg[g] |= ((m & 0xf) << s);
+}
+
+static void
+awin_gpio_update_eint_regs(struct awin_gpio_softc *sc)
+{
+ int i;
+
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
+ for (i = 0; i < 4; i++) {
+ bus_space_write_4(sc->sc_bst, sc->sc_eint_bsh, i * 4,
+ sc->sc_ecfg[i]);
+ }
+}
+
+static void
+awin_gpio_clear_eint(struct awin_gpio_softc *sc, int pin)
+{
+ bus_space_write_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_STA_REG), (1U <<pin));
+}
+
+static void
+awin_gpio_update_eint_mask(struct awin_gpio_softc *sc)
+{
+ uint32_t enabled;
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
+ enabled = bus_space_read_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_CTL_REG));
+ enabled &= sc->sc_eintr_configured;
+ bus_space_write_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_CTL_REG), enabled);
+}
+
void
awin_gpio_init(void)
{
@@ -465,7 +565,6 @@ awin_gpio_init(void)
#ifdef VERBOSE_INIT_ARM
printf(" free");
#endif
-
if (awin_chip_id() == AWIN_CHIP_ID_A31) {
pin_groups[0].grp_pin_mask = __BIT(AWIN_A31_PIO_PA_PINS) - 1;
pin_groups[1].grp_pin_mask = __BIT(AWIN_A31_PIO_PB_PINS) - 1;
@@ -577,6 +676,15 @@ awin_gpio_init(void)
popcount32(grp->grp_pin_mask & ~grp->grp_pin_inuse_mask));
#endif
}
+
+ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_VM);
+ bus_space_subregion(sc->sc_bst, awin_core_bsh,
+ AWIN_PIO_OFFSET + AWIN_PIO_INT_CFG0_REG,
+ AWIN_PIO_INT_SIZE, &sc->sc_eint_bsh);
+ for (u_int i = 0; i < 3; i++) {
+ sc->sc_ecfg[i] = 0;
+ }
+ sc->sc_eintr_configured = 0;
}
bool
@@ -764,6 +872,7 @@ awin_gpio_pin_ctl(void *cookie, int pin,
{
struct awin_gpio_pin_group * const grp = cookie;
struct awin_gpio_pin_cfg ncfg = grp->grp_cfg;
+ struct awin_gpio_softc *sc = &awin_gpio_sc;
u_int pull_value = AWIN_PIO_PULL_NONE;
if (flags & GPIO_PIN_PULLUP) {
@@ -773,16 +882,74 @@ awin_gpio_pin_ctl(void *cookie, int pin,
}
awin_gpio_set_pin_pull(&ncfg, pin, pull_value);
- if (flags & GPIO_PIN_INPUT) {
- awin_gpio_set_pin_func(&ncfg, pin, AWIN_PIO_FUNC_INPUT);
- } else if (flags & GPIO_PIN_OUTPUT) {
- awin_gpio_set_pin_func(&ncfg, pin, AWIN_PIO_FUNC_OUTPUT);
+ mutex_enter(&sc->sc_intr_lock);
+ if (flags & GPIO_PIN_EVENTS) {
+ KASSERT(awin_chip_id() == AWIN_CHIP_ID_A20);
+ KASSERT(grp->grp_index == 7);
+ KASSERT(pin <= 21);
+ KASSERT((grp->grp_pin_intr_mask & (1 << pin)) != 0);
+ awin_gpio_set_pin_func(&ncfg, pin, AWIN_PIO_PH_EINT_FUNC);
+ if (flags & GPIO_PIN_LEVEL) {
+ if (flags & GPIO_PIN_FALLING) {
+ awin_gpio_set_pin_eint(sc, pin,
+ AWIN_PIO_EINT_LOW_LEVEL);
+ } else {
+ awin_gpio_set_pin_eint(sc, pin,
+ AWIN_PIO_EINT_HIGH_LEVEL);
+ }
+ } else {
+ if (flags & GPIO_PIN_FALLING) {
+ awin_gpio_set_pin_eint(sc, pin,
+ AWIN_PIO_EINT_NEGATIVE_EDGE);
+ } else {
+ awin_gpio_set_pin_eint(sc, pin,
+ AWIN_PIO_EINT_POSITIVE_EDGE);
+ }
+ }
+ awin_gpio_update_eint_regs(sc);
+ sc->sc_eintr_configured |= 1 << pin;
+ awin_gpio_clear_eint(sc, pin);
+ } else {
+ if ((grp->grp_pin_intr_mask & (1 << pin)) != 0) {
+ sc->sc_eintr_configured &= ~(1 << pin);
+ awin_gpio_update_eint_mask(sc);
+ awin_gpio_clear_eint(sc, pin);
+ }
+ if (flags & GPIO_PIN_INPUT) {
+ awin_gpio_set_pin_func(&ncfg, pin,
+ AWIN_PIO_FUNC_INPUT);
+ } else if (flags & GPIO_PIN_OUTPUT) {
+ awin_gpio_set_pin_func(&ncfg, pin,
+ AWIN_PIO_FUNC_OUTPUT);
+ }
}
/*
* Now update any config register that changed.
*/
awin_gpio_update_cfg_regs(&armv7_generic_bs_tag, grp, &ncfg);
+ mutex_exit(&sc->sc_intr_lock);
+}
+
+static void
+awin_gpio_pin_irqen(void *cookie, int pin, bool enable)
+{
+ struct awin_gpio_pin_group * const grp = cookie;
+ uint32_t enabled;
+ struct awin_gpio_softc *sc = &awin_gpio_sc;
+
+ KASSERT(grp->grp_index == 7);
+ mutex_enter(&sc->sc_intr_lock);
+ enabled = bus_space_read_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_CTL_REG));
+ if (enable)
+ enabled |= (1 << pin);
+ else
+ enabled &= ~(1 << pin);
+ enabled &= sc->sc_eintr_configured;
+ bus_space_write_4(sc->sc_bst, sc->sc_eint_bsh,
+ INT_OFFSET(AWIN_PIO_INT_CTL_REG), enabled);
+ mutex_exit(&sc->sc_intr_lock);
}
bool
Index: arch/arm/allwinner/awin_io.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/allwinner/awin_io.c,v
retrieving revision 1.44
diff -u -p -u -r1.44 awin_io.c
--- arch/arm/allwinner/awin_io.c 26 Dec 2015 16:56:41 -0000 1.44
+++ arch/arm/allwinner/awin_io.c 28 Apr 2016 09:13:12 -0000
@@ -97,7 +97,8 @@ awinio_print(void *aux, const char *pnp)
static const struct awin_locators awin_locators[] = {
{ "awinicu", OFFANDSIZE(INTC), NOPORT, NOINTR, A10|REQ },
- { "awingpio", OFFANDSIZE(PIO), NOPORT, NOINTR, A10|A20|A31|REQ },
+ { "awingpio", OFFANDSIZE(PIO), NOPORT, AWIN_IRQ_PIO, A10|A20|REQ },
+ { "awingpio", OFFANDSIZE(PIO), NOPORT, NOINTR, A31|REQ },
{ "awingpio", OFFANDSIZE(A80_PIO), NOPORT, NOINTR, A80|REQ },
{ "awindma", OFFANDSIZE(DMA), NOPORT, AWIN_IRQ_DMA, A10|A20 },
{ "awindma", OFFANDSIZE(DMA), NOPORT, AWIN_A31_IRQ_DMA, A31 },
Index: arch/arm/allwinner/awin_reg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/allwinner/awin_reg.h,v
retrieving revision 1.87
diff -u -p -u -r1.87 awin_reg.h
--- arch/arm/allwinner/awin_reg.h 12 Apr 2016 10:54:29 -0000 1.87
+++ arch/arm/allwinner/awin_reg.h 28 Apr 2016 09:13:12 -0000
@@ -1293,6 +1293,7 @@ struct awin_mmc_idma_descriptor {
#define AWIN_PIO_INT_DEB_REG 0x0218
#define AWIN_PIO_SDR_PAD_DEV_REG 0x0220
#define AWIN_PIO_SDR_PAD_PUL_REG 0x0224
+#define AWIN_PIO_INT_SIZE 0x0028
#define AWIN_PIO_CFG_PINMASK(pin) (7 << (4*((pin) & 7)))
#define AWIN_PIO_DRV_MASK(pin) ((x) << (2*((pin) & 15)))
Index: dev/gpio/gpio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/gpio/gpio.c,v
retrieving revision 1.57
diff -u -p -u -r1.57 gpio.c
--- dev/gpio/gpio.c 25 Jul 2014 08:10:36 -0000 1.57
+++ dev/gpio/gpio.c 28 Apr 2016 09:13:12 -0000
@@ -298,6 +298,45 @@ gpiobus_print(void *aux, const char *pnp
return UNCONF;
}
+/* called from backends when a interrupt even occurs */
+void
+gpio_intr(device_t self, uint32_t evts)
+{
+ struct gpio_softc *sc = device_private(self);
+ void (*callback)(void *);
+ void *callback_arg;
+
+ for (int i = 0; i < sc->sc_npins; i++) {
+ if (evts & (1 << i)) {
+ mutex_enter(&sc->sc_mtx);
+ callback = sc->sc_pins[i].pin_callback;
+ callback_arg = sc->sc_pins[i].pin_callback_arg;
+ DPRINTFN(2, ("gpio pin %d event callback %p\n", i, callback));
+ if (callback != NULL) {
+ callback(callback_arg);
+ }
+ mutex_exit(&sc->sc_mtx);
+ }
+ }
+}
+
+void *
+gpio_find_device(const char *name)
+{
+ device_t gpio_dev;
+ gpio_dev = device_find_by_xname(name);
+ if (gpio_dev == NULL)
+ return NULL;
+ return device_private(gpio_dev);
+}
+
+const char *
+gpio_get_name(void *gpio)
+{
+ struct gpio_softc *sc = gpio;
+ return device_xname(sc->sc_dev);
+}
+
/* return 1 if all pins can be mapped, 0 if not */
int
gpio_pin_can_map(void *gpio, int offset, uint32_t mask)
@@ -379,8 +418,42 @@ void
gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags)
{
struct gpio_softc *sc = gpio;
+ struct gpio_pin *pinp = &sc->sc_pins[map->pm_map[pin]];
- return gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
+ KASSERT((flags & GPIO_PIN_EVENTS) == 0);
+ mutex_enter(&sc->sc_mtx);
+ gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
+ pinp->pin_callback = NULL;
+ pinp->pin_callback_arg = NULL;
+ mutex_exit(&sc->sc_mtx);
+}
+
+int
+gpio_pin_ctl_intr(void *gpio, struct gpio_pinmap *map, int pin, int flags,
+ int ipl, void (*callback)(void *), void *arg)
+{
+ struct gpio_softc *sc = gpio;
+ struct gpio_pin *pinp = &sc->sc_pins[map->pm_map[pin]];
+ KASSERT((flags & GPIO_PIN_EVENTS) != 0);
+ if (ipl != IPL_VM)
+ return EINVAL;
+ mutex_enter(&sc->sc_mtx);
+ if (pinp->pin_callback != NULL) {
+ mutex_exit(&sc->sc_mtx);
+ return EEXIST;
+ }
+ pinp->pin_callback = callback;
+ pinp->pin_callback_arg = arg;
+ gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
+ mutex_exit(&sc->sc_mtx);
+ return 0;
+}
+
+void
+gpio_pin_irqen(void *gpio, struct gpio_pinmap *map, int pin, bool en)
+{
+ struct gpio_softc *sc = gpio;
+ gpiobus_pin_irqen(sc->sc_gc, map->pm_map[pin], en);
}
int
Index: dev/gpio/gpiovar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/gpio/gpiovar.h,v
retrieving revision 1.15
diff -u -p -u -r1.15 gpiovar.h
--- dev/gpio/gpiovar.h 13 Nov 2011 13:20:02 -0000 1.15
+++ dev/gpio/gpiovar.h 28 Apr 2016 09:13:12 -0000
@@ -31,6 +31,7 @@ typedef struct gpio_chipset_tag {
int (*gp_pin_read)(void *, int);
void (*gp_pin_write)(void *, int, int);
void (*gp_pin_ctl)(void *, int, int);
+ void (*gp_pin_irqen)(void *, int, bool);
} *gpio_chipset_tag_t;
/* GPIO pin description */
@@ -41,6 +42,8 @@ typedef struct gpio_pin {
int pin_state; /* current state */
int pin_mapped; /* is mapped */
gpio_chipset_tag_t pin_gc; /* reference the controller */
+ void (*pin_callback)(void *); /* irq callback */
+ void * pin_callback_arg; /* callback arg */
} gpio_pin_t;
/* Attach GPIO framework to the controller */
@@ -63,6 +66,8 @@ int gpiobus_print(void *, const char *);
((gc)->gp_pin_write((gc)->gp_cookie, (pin), (value)))
#define gpiobus_pin_ctl(gc, pin, flags) \
((gc)->gp_pin_ctl((gc)->gp_cookie, (pin), (flags)))
+#define gpiobus_pin_irqen(gc, pin, en) \
+ ((gc)->gp_pin_irqen((gc)->gp_cookie, (pin), (en)))
/* Attach devices connected to the GPIO pins */
struct gpio_attach_args {
@@ -90,16 +95,24 @@ struct gpio_name {
LIST_ENTRY(gpio_name) gp_next;
};
+void * gpio_find_device(const char *);
+const char * gpio_get_name(void *gpio);
int gpio_pin_can_map(void *, int, uint32_t);
int gpio_pin_map(void *, int, uint32_t, struct gpio_pinmap *);
void gpio_pin_unmap(void *, struct gpio_pinmap *);
int gpio_pin_read(void *, struct gpio_pinmap *, int);
void gpio_pin_write(void *, struct gpio_pinmap *, int, int);
void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int);
+int gpio_pin_ctl_intr(void *, struct gpio_pinmap *, int, int,
+ int, void (*)(void *), void *);
+void gpio_pin_irqen(void *, struct gpio_pinmap *, int, bool);
int gpio_pin_caps(void *, struct gpio_pinmap *, int);
+int gpio_pin_wait(void *, int);
int gpio_npins(uint32_t);
int gpio_lock(void *);
void gpio_unlock(void *);
+void gpio_intr(device_t, u_int32_t);
+
#endif /* !_DEV_GPIO_GPIOVAR_H_ */
Index: dev/i2c/ds1307.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/ds1307.c,v
retrieving revision 1.21
diff -u -p -u -r1.21 ds1307.c
--- dev/i2c/ds1307.c 20 Nov 2014 16:34:26 -0000 1.21
+++ dev/i2c/ds1307.c 28 Apr 2016 09:13:12 -0000
@@ -86,6 +86,8 @@ static const struct dsrtc_model dsrtc_mo
.dm_model = 1672,
.dm_rtc_start = DS1672_RTC_START,
.dm_rtc_size = DS1672_RTC_SIZE,
+ .dm_ch_reg = DS1672_CONTROL,
+ .dm_ch_value = DS1672_CONTROL_CH,
.dm_flags = 0,
}, {
.dm_model = 3231,
Index: dev/i2c/ds1307reg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/ds1307reg.h,v
retrieving revision 1.5
diff -u -p -u -r1.5 ds1307reg.h
--- dev/i2c/ds1307reg.h 12 Oct 2014 01:23:23 -0000 1.5
+++ dev/i2c/ds1307reg.h 28 Apr 2016 09:13:12 -0000
@@ -70,6 +70,7 @@
#define DS1672_CNTR3 0x02
#define DS1672_CNTR4 0x03
#define DS1672_CONTROL 0x04
+#define DS1672_CONTROL_CH (1 << 7) /* clock hold */
#define DS1672_TRICKLE 0x05
#define DS1672_RTC_START 0
Index: dev/i2c/files.i2c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/files.i2c,v
retrieving revision 1.69
diff -u -p -u -r1.69 files.i2c
--- dev/i2c/files.i2c 16 Dec 2015 07:56:48 -0000 1.69
+++ dev/i2c/files.i2c 28 Apr 2016 09:13:12 -0000
@@ -196,6 +196,11 @@ device ibmhawk: sysmon_envsys
attach ibmhawk at iic
file dev/i2c/ibmhawk.c ibmhawk
+# NXP TDA1998x HDMI transmitter
+device tda19988hdmi: edid, videomode
+attach tda19988hdmi at iic
+file dev/i2c/tda19988hdmi.c tda19988hdmi
+
# TI TPS65950 OMAP Power Management and System Companion Device
device tps65950pm: sysmon_wdog
attach tps65950pm at iic
@@ -260,3 +265,8 @@ file dev/i2c/titemp.c titemp
device as3722pmic: sysmon_wdog
attach as3722pmic at iic
file dev/i2c/as3722.c as3722pmic needs-flag
+
+# pic18f-based BMC
+device picbmc: sysmon_envsys
+attach picbmc at iic
+file dev/i2c/picbmc.c picbmc
Index: dev/pci/sisfb.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/sisfb.c,v
retrieving revision 1.5
diff -u -p -u -r1.5 sisfb.c
--- dev/pci/sisfb.c 26 Jan 2014 21:22:49 -0000 1.5
+++ dev/pci/sisfb.c 28 Apr 2016 09:13:12 -0000
@@ -488,12 +488,15 @@ sisfb_mmap(void *v, void *vs, off_t offs
prot, BUS_SPACE_MAP_LINEAR);
return pa;
}
- if (offset >= (fb->iobase & ~PAGE_MASK) &&
- offset <= ((fb->iobase + fb->iosize + PAGE_SIZE - 1) & ~PAGE_MASK)) {
- pa = bus_space_mmap(fb->iot, fb->iobase, offset - fb->iobase,
- prot, BUS_SPACE_MAP_LINEAR);
+#ifdef PCI_MAGIC_IO_RANGE
+ /* allow mapping of IO space */
+ if ((offset >= PCI_MAGIC_IO_RANGE) &&
+ (offset < PCI_MAGIC_IO_RANGE + 0x10000)) {
+ pa = bus_space_mmap(fb->iot, offset - PCI_MAGIC_IO_RANGE,
+ 0, prot, BUS_SPACE_MAP_LINEAR);
return pa;
- }
+ }
+#endif /* PCI_MAGIC_IO_RANGE */
return -1;
}
Index: dev/sdmmc/sdmmc_mem.c
===================================================================
RCS file: /cvsroot/src/sys/dev/sdmmc/sdmmc_mem.c,v
retrieving revision 1.50
diff -u -p -u -r1.50 sdmmc_mem.c
--- dev/sdmmc/sdmmc_mem.c 22 Dec 2015 09:56:06 -0000 1.50
+++ dev/sdmmc/sdmmc_mem.c 28 Apr 2016 09:13:12 -0000
@@ -98,6 +98,9 @@ static int sdmmc_mem_read_block_subr(str
uint32_t, u_char *, size_t);
static int sdmmc_mem_write_block_subr(struct sdmmc_function *, bus_dmamap_t,
uint32_t, u_char *, size_t);
+#ifdef SDMMC_DUMP_CSD
+void sdmmc_print_csd(sdmmc_response, struct sdmmc_csd *);
+#endif
static const struct {
const char *name;
Home |
Main Index |
Thread Index |
Old Index