Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156857919
D14755.id40469.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
30 KB
Referenced Files
None
Subscribers
None
D14755.id40469.diff
View Options
Index: sys/arm/mv/gpio.c
===================================================================
--- sys/arm/mv/gpio.c
+++ sys/arm/mv/gpio.c
@@ -71,13 +71,14 @@
int mem_rid;
struct resource * irq_res[GPIO_MAX_INTR_COUNT];
int irq_rid[GPIO_MAX_INTR_COUNT];
+ struct intr_event * gpio_events[MV_GPIO_MAX_NPINS];
void *ih_cookie[GPIO_MAX_INTR_COUNT];
bus_space_tag_t bst;
bus_space_handle_t bsh;
struct mtx mutex;
uint8_t pin_num; /* number of GPIO pins */
uint8_t irq_num; /* number of real IRQs occupied by GPIO controller */
- uint8_t use_high;
+ struct gpio_pin gpio_setup[MV_GPIO_MAX_NPINS];
/* Used for debouncing. */
uint32_t debounced_state_lo;
@@ -86,52 +87,56 @@
int *debounce_counters;
};
-static struct mv_gpio_softc *mv_gpio_softc = NULL;
-static uint32_t gpio_setup[MV_GPIO_MAX_NPINS];
+struct mv_gpio_pindev {
+ device_t dev;
+ int pin;
+};
static int mv_gpio_probe(device_t);
static int mv_gpio_attach(device_t);
-static int mv_gpio_intr(void *);
-static int mv_gpio_init(void);
-
-static void mv_gpio_double_edge_init(int pin);
-
-static int mv_gpio_debounce_setup(int pin);
-static int mv_gpio_debounce_init(int pin);
-static void mv_gpio_debounce_start(int pin);
-static int mv_gpio_debounce_prepare(int pin);
-static void mv_gpio_debounce(void *arg);
-static void mv_gpio_debounced_state_set(int pin, uint8_t new_state);
-static uint32_t mv_gpio_debounced_state_get(int pin);
-
-static void mv_gpio_exec_intr_handlers(uint32_t status, int high);
-static void mv_gpio_intr_handler(int pin);
-static uint32_t mv_gpio_reg_read(uint32_t reg);
-static void mv_gpio_reg_write(uint32_t reg, uint32_t val);
-static void mv_gpio_reg_set(uint32_t reg, uint32_t val);
-static void mv_gpio_reg_clear(uint32_t reg, uint32_t val);
-
-static void mv_gpio_blink(uint32_t pin, uint8_t enable);
-static void mv_gpio_polarity(uint32_t pin, uint8_t enable, uint8_t toggle);
-static void mv_gpio_level(uint32_t pin, uint8_t enable);
-static void mv_gpio_edge(uint32_t pin, uint8_t enable);
-static void mv_gpio_out_en(uint32_t pin, uint8_t enable);
-static void mv_gpio_int_ack(uint32_t pin);
-static void mv_gpio_value_set(uint32_t pin, uint8_t val);
-static uint32_t mv_gpio_value_get(uint32_t pin, uint8_t exclude_polar);
-
-static void mv_gpio_intr_mask(int pin);
-static void mv_gpio_intr_unmask(int pin);
-int mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt,
- void (*hand)(void *), void *arg, int pin, int flags, void **cookiep);
-
-int mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask);
-void mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable);
-uint8_t mv_gpio_in(uint32_t pin);
-
-#define MV_GPIO_LOCK() mtx_lock_spin(&mv_gpio_softc->mutex)
-#define MV_GPIO_UNLOCK() mtx_unlock_spin(&mv_gpio_softc->mutex)
-#define MV_GPIO_ASSERT_LOCKED() mtx_assert(&mv_gpio_softc->mutex, MA_OWNED)
+static int mv_gpio_intr(device_t, void *);
+static int mv_gpio_init(device_t);
+
+static void mv_gpio_double_edge_init(device_t, int);
+
+static int mv_gpio_debounce_setup(device_t, int);
+static int mv_gpio_debounce_prepare(device_t, int);
+static int mv_gpio_debounce_init(device_t, int);
+static void mv_gpio_debounce_start(device_t, int);
+static void mv_gpio_debounce(void *);
+static void mv_gpio_debounced_state_set(device_t, int, uint8_t);
+static uint32_t mv_gpio_debounced_state_get(device_t, int);
+
+static void mv_gpio_exec_intr_handlers(device_t, uint32_t, int);
+static void mv_gpio_intr_handler(device_t, int);
+static uint32_t mv_gpio_reg_read(device_t, uint32_t);
+static void mv_gpio_reg_write(device_t, uint32_t, uint32_t);
+static void mv_gpio_reg_set(device_t, uint32_t, uint32_t);
+static void mv_gpio_reg_clear(device_t, uint32_t, uint32_t);
+
+static void mv_gpio_blink(device_t, uint32_t, uint8_t);
+static void mv_gpio_polarity(device_t, uint32_t, uint8_t, uint8_t);
+static void mv_gpio_level(device_t, uint32_t, uint8_t);
+static void mv_gpio_edge(device_t, uint32_t, uint8_t);
+static void mv_gpio_out_en(device_t, uint32_t, uint8_t);
+static void mv_gpio_int_ack(struct mv_gpio_pindev *);
+static void mv_gpio_value_set(device_t, uint32_t, uint8_t);
+static uint32_t mv_gpio_value_get(device_t, uint32_t, uint8_t);
+
+static void mv_gpio_intr_mask(struct mv_gpio_pindev *);
+static void mv_gpio_intr_unmask(struct mv_gpio_pindev *);
+
+void mv_gpio_finish_intrhandler(struct mv_gpio_pindev *);
+int mv_gpio_setup_intrhandler(device_t, const char *,
+ driver_filter_t *, void (*)(void *), void *,
+ int, int, void **);
+int mv_gpio_configure(device_t, uint32_t, uint32_t, uint32_t);
+void mv_gpio_out(device_t, uint32_t, uint8_t, uint8_t);
+uint8_t mv_gpio_in(device_t, uint32_t);
+
+#define MV_GPIO_LOCK() mtx_lock_spin(&sc->mutex)
+#define MV_GPIO_UNLOCK() mtx_unlock_spin(&sc->mutex)
+#define MV_GPIO_ASSERT_LOCKED() mtx_assert(&sc->mutex, MA_OWNED)
static device_method_t mv_gpio_methods[] = {
DEVMETHOD(device_probe, mv_gpio_probe),
@@ -149,14 +154,14 @@
DRIVER_MODULE(gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0);
-typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int);
+typedef int (*gpios_phandler_t)(device_t, phandle_t, pcell_t *, int);
struct gpio_ctrl_entry {
const char *compat;
gpios_phandler_t handler;
};
-static int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len);
+static int mv_handle_gpios_prop(device_t, phandle_t, pcell_t *, int);
int gpio_get_config_from_dt(void);
struct gpio_ctrl_entry gpio_controllers[] = {
@@ -192,10 +197,6 @@
if (sc == NULL)
return (ENXIO);
- if (mv_gpio_softc != NULL)
- return (ENXIO);
- mv_gpio_softc = sc;
-
/* Get chip id and revision */
soc_id(&dev_id, &rev_id);
@@ -205,13 +206,11 @@
dev_id == MV_DEV_MV78100_Z0 ) {
sc->pin_num = 32;
sc->irq_num = 4;
- sc->use_high = 0;
} else if (dev_id == MV_DEV_88F6281 ||
dev_id == MV_DEV_88F6282) {
sc->pin_num = 50;
sc->irq_num = 7;
- sc->use_high = 1;
} else {
if (OF_getencprop(ofw_bus_get_node(dev), "pin-count", &pincnt,
@@ -294,15 +293,6 @@
bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0);
bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0);
- if (sc->use_high) {
- bus_space_write_4(sc->bst, sc->bsh,
- GPIO_HI_INT_EDGE_MASK, 0);
- bus_space_write_4(sc->bst, sc->bsh,
- GPIO_HI_INT_LEV_MASK, 0);
- bus_space_write_4(sc->bst, sc->bsh,
- GPIO_HI_INT_CAUSE, 0);
- }
-
for (i = 0; i < sc->irq_num; i++) {
if (bus_setup_intr(dev, sc->irq_res[i],
INTR_TYPE_MISC,
@@ -316,7 +306,7 @@
}
}
- error = mv_gpio_init();
+ error = mv_gpio_init(dev);
if (error) {
device_printf(dev, "WARNING: failed to initialize GPIO pins, "
"error = %d\n", error);
@@ -325,14 +315,18 @@
/* Clear interrupt status. */
bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0);
+ device_add_child(dev, "gpioc", device_get_unit(dev));
+ device_add_child(dev, "gpiobus", device_get_unit(dev));
+
return (0);
}
static int
-mv_gpio_intr(void *arg)
+mv_gpio_intr(device_t dev, void *arg)
{
uint32_t int_cause, gpio_val;
- uint32_t int_cause_hi, gpio_val_hi;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_LOCK();
@@ -340,30 +334,17 @@
* According to documentation, edge sensitive interrupts are asserted
* when unmasked GPIO_INT_CAUSE register bits are set.
*/
- int_cause = mv_gpio_reg_read(GPIO_INT_CAUSE);
- int_cause &= mv_gpio_reg_read(GPIO_INT_EDGE_MASK);
+ int_cause = mv_gpio_reg_read(dev, GPIO_INT_CAUSE);
+ int_cause &= mv_gpio_reg_read(dev, GPIO_INT_EDGE_MASK);
/*
* Level sensitive interrupts are asserted when unmasked GPIO_DATA_IN
* register bits are set.
*/
- gpio_val = mv_gpio_reg_read(GPIO_DATA_IN);
- gpio_val &= mv_gpio_reg_read(GPIO_INT_LEV_MASK);
+ gpio_val = mv_gpio_reg_read(dev, GPIO_DATA_IN);
+ gpio_val &= mv_gpio_reg_read(dev, GPIO_INT_LEV_MASK);
- int_cause_hi = 0;
- gpio_val_hi = 0;
- if (mv_gpio_softc->use_high) {
- int_cause_hi = mv_gpio_reg_read(GPIO_HI_INT_CAUSE);
- int_cause_hi &= mv_gpio_reg_read(GPIO_HI_INT_EDGE_MASK);
-
- gpio_val_hi = mv_gpio_reg_read(GPIO_HI_DATA_IN);
- gpio_val_hi &= mv_gpio_reg_read(GPIO_HI_INT_LEV_MASK);
- }
-
- mv_gpio_exec_intr_handlers(int_cause | gpio_val, 0);
-
- if (mv_gpio_softc->use_high)
- mv_gpio_exec_intr_handlers(int_cause_hi | gpio_val_hi, 1);
+ mv_gpio_exec_intr_handlers(dev, int_cause | gpio_val, 0);
MV_GPIO_UNLOCK();
@@ -374,31 +355,47 @@
* GPIO interrupt handling
*/
-static struct intr_event *gpio_events[MV_GPIO_MAX_NPINS];
+void
+mv_gpio_finish_intrhandler(struct mv_gpio_pindev *s)
+{
+ /* When we acheive full interrupt support
+ * This function will be opposite to
+ * mv_gpio_setup_intrhandler
+ */
+
+ /* Now it exists only to remind that
+ * there should be place to free mv_gpio_pindev
+ * allocated by mv_gpio_setup_intrhandler
+ */
+ free(s, M_DEVBUF);
+}
int
-mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt,
+mv_gpio_setup_intrhandler(device_t dev, const char *name, driver_filter_t *filt,
void (*hand)(void *), void *arg, int pin, int flags, void **cookiep)
{
struct intr_event *event;
int error;
+ struct mv_gpio_pindev *s;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
+ s = malloc(sizeof(struct mv_gpio_pindev), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (pin < 0 || pin >= mv_gpio_softc->pin_num)
+ if (pin < 0 || pin >= sc->pin_num)
return (ENXIO);
- event = gpio_events[pin];
+ event = sc->gpio_events[pin];
if (event == NULL) {
MV_GPIO_LOCK();
- if (gpio_setup[pin] & MV_GPIO_IN_DEBOUNCE) {
- error = mv_gpio_debounce_init(pin);
+ if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) {
+ error = mv_gpio_debounce_init(dev, pin);
if (error != 0) {
MV_GPIO_UNLOCK();
return (error);
}
- } else if (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE)
- mv_gpio_double_edge_init(pin);
+ } else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE)
+ mv_gpio_double_edge_init(dev, pin);
MV_GPIO_UNLOCK();
-
- error = intr_event_create(&event, (void *)pin, 0, pin,
+ error = intr_event_create(&event, (void *)s, 0, pin,
(void (*)(void *))mv_gpio_intr_mask,
(void (*)(void *))mv_gpio_intr_unmask,
(void (*)(void *))mv_gpio_int_ack,
@@ -406,7 +403,7 @@
"gpio%d:", pin);
if (error != 0)
return (error);
- gpio_events[pin] = event;
+ sc->gpio_events[pin] = event;
}
intr_event_add_handler(event, name, filt, hand, arg,
@@ -414,19 +411,22 @@
return (0);
}
-void
-mv_gpio_intr_mask(int pin)
+static void
+mv_gpio_intr_mask(struct mv_gpio_pindev *s)
{
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (s->pin >= sc->pin_num)
return;
MV_GPIO_LOCK();
- if (gpio_setup[pin] & (MV_GPIO_IN_IRQ_EDGE | MV_GPIO_IN_IRQ_DOUBLE_EDGE))
- mv_gpio_edge(pin, 0);
+ if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE |
+ MV_GPIO_IN_IRQ_DOUBLE_EDGE))
+ mv_gpio_edge(s->dev, s->pin, 0);
else
- mv_gpio_level(pin, 0);
+ mv_gpio_level(s->dev, s->pin, 0);
/*
* The interrupt has to be acknowledged before scheduling an interrupt
@@ -434,32 +434,41 @@
* (which can happen with shared IRQs e.g. PCI) while processing the
* current event.
*/
- mv_gpio_int_ack(pin);
+ mv_gpio_int_ack(s);
MV_GPIO_UNLOCK();
+
+ return;
}
-void
-mv_gpio_intr_unmask(int pin)
+static void
+mv_gpio_intr_unmask(struct mv_gpio_pindev *s)
{
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (s->pin >= sc->pin_num)
return;
MV_GPIO_LOCK();
- if (gpio_setup[pin] & (MV_GPIO_IN_IRQ_EDGE | MV_GPIO_IN_IRQ_DOUBLE_EDGE))
- mv_gpio_edge(pin, 1);
+ if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE |
+ MV_GPIO_IN_IRQ_DOUBLE_EDGE))
+ mv_gpio_edge(s->dev, s->pin, 1);
else
- mv_gpio_level(pin, 1);
+ mv_gpio_level(s->dev, s->pin, 1);
MV_GPIO_UNLOCK();
+
+ return;
}
static void
-mv_gpio_exec_intr_handlers(uint32_t status, int high)
+mv_gpio_exec_intr_handlers(device_t dev, uint32_t status, int high)
{
int i, pin;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_ASSERT_LOCKED();
@@ -467,13 +476,13 @@
while (status != 0) {
if (status & 1) {
pin = (high ? (i + GPIO_PINS_PER_REG) : i);
- if (gpio_setup[pin] & MV_GPIO_IN_DEBOUNCE)
- mv_gpio_debounce_start(pin);
- else if (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
- mv_gpio_polarity(pin, 0, 1);
- mv_gpio_intr_handler(pin);
+ if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE)
+ mv_gpio_debounce_start(dev, pin);
+ else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
+ mv_gpio_polarity(dev, pin, 0, 1);
+ mv_gpio_intr_handler(dev, pin);
} else
- mv_gpio_intr_handler(pin);
+ mv_gpio_intr_handler(dev, pin);
}
status >>= 1;
i++;
@@ -481,17 +490,19 @@
}
static void
-mv_gpio_intr_handler(int pin)
+mv_gpio_intr_handler(device_t dev, int pin)
{
#ifdef INTRNG
struct intr_irqsrc isrc;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_ASSERT_LOCKED();
#ifdef INTR_SOLO
isrc.isrc_filter = NULL;
#endif
- isrc.isrc_event = gpio_events[pin];
+ isrc.isrc_event = sc->gpio_events[pin];
if (isrc.isrc_event == NULL || TAILQ_EMPTY(&isrc.isrc_event->ie_handlers))
return;
@@ -501,11 +512,14 @@
}
int
-mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask)
+mv_gpio_configure(device_t dev, uint32_t pin, uint32_t flags, uint32_t mask)
{
int error;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
+ error = 0;
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return (EINVAL);
/* check flags consistency */
@@ -514,7 +528,7 @@
return (EINVAL);
if (mask & MV_GPIO_IN_DEBOUNCE) {
- error = mv_gpio_debounce_prepare(pin);
+ error = mv_gpio_debounce_prepare(dev, pin);
if (error != 0)
return (error);
}
@@ -522,19 +536,19 @@
MV_GPIO_LOCK();
if (mask & MV_GPIO_OUT_BLINK)
- mv_gpio_blink(pin, flags & MV_GPIO_OUT_BLINK);
+ mv_gpio_blink(dev, pin, flags & MV_GPIO_OUT_BLINK);
if (mask & MV_GPIO_IN_POL_LOW)
- mv_gpio_polarity(pin, flags & MV_GPIO_IN_POL_LOW, 0);
+ mv_gpio_polarity(dev, pin, flags & MV_GPIO_IN_POL_LOW, 0);
if (mask & MV_GPIO_IN_DEBOUNCE) {
- error = mv_gpio_debounce_setup(pin);
+ error = mv_gpio_debounce_setup(dev, pin);
if (error) {
MV_GPIO_UNLOCK();
return (error);
}
}
- gpio_setup[pin] &= ~(mask);
- gpio_setup[pin] |= (flags & mask);
+ sc->gpio_setup[pin].gp_flags &= ~(mask);
+ sc->gpio_setup[pin].gp_flags |= (flags & mask);
MV_GPIO_UNLOCK();
@@ -542,28 +556,33 @@
}
static void
-mv_gpio_double_edge_init(int pin)
+mv_gpio_double_edge_init(device_t dev, int pin)
{
uint8_t raw_read;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_ASSERT_LOCKED();
- raw_read = (mv_gpio_value_get(pin, 1) ? 1 : 0);
+ raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
if (raw_read)
- mv_gpio_polarity(pin, 1, 0);
+ mv_gpio_polarity(dev, pin, 1, 0);
else
- mv_gpio_polarity(pin, 0, 0);
+ mv_gpio_polarity(dev, pin, 0, 0);
}
static int
-mv_gpio_debounce_setup(int pin)
+mv_gpio_debounce_setup(device_t dev, int pin)
{
struct callout *c;
+ struct mv_gpio_softc *sc;
+
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_ASSERT_LOCKED();
- c = mv_gpio_softc->debounce_callouts[pin];
+ c = sc->debounce_callouts[pin];
if (c == NULL)
return (ENXIO);
@@ -576,12 +595,12 @@
}
static int
-mv_gpio_debounce_prepare(int pin)
+mv_gpio_debounce_prepare(device_t dev, int pin)
{
struct callout *c;
struct mv_gpio_softc *sc;
- sc = (struct mv_gpio_softc *)mv_gpio_softc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
c = sc->debounce_callouts[pin];
if (c == NULL) {
@@ -597,58 +616,63 @@
}
static int
-mv_gpio_debounce_init(int pin)
+mv_gpio_debounce_init(device_t dev, int pin)
{
uint8_t raw_read;
int *cnt;
+ struct mv_gpio_softc *sc;
- MV_GPIO_ASSERT_LOCKED();
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- cnt = &mv_gpio_softc->debounce_counters[pin];
+ MV_GPIO_ASSERT_LOCKED();
- raw_read = (mv_gpio_value_get(pin, 1) ? 1 : 0);
+ cnt = &sc->debounce_counters[pin];
+ raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
if (raw_read) {
- mv_gpio_polarity(pin, 1, 0);
+ mv_gpio_polarity(dev, pin, 1, 0);
*cnt = DEBOUNCE_HI_LO_MS / DEBOUNCE_CHECK_MS;
} else {
- mv_gpio_polarity(pin, 0, 0);
+ mv_gpio_polarity(dev, pin, 0, 0);
*cnt = DEBOUNCE_LO_HI_MS / DEBOUNCE_CHECK_MS;
}
- mv_gpio_debounced_state_set(pin, raw_read);
+ mv_gpio_debounced_state_set(dev, pin, raw_read);
return (0);
}
static void
-mv_gpio_debounce_start(int pin)
+mv_gpio_debounce_start(device_t dev, int pin)
{
struct callout *c;
- int *debounced_pin;
+ struct mv_gpio_pindev s = {dev, pin};
+ struct mv_gpio_pindev *sd;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_ASSERT_LOCKED();
- c = mv_gpio_softc->debounce_callouts[pin];
+ c = sc->debounce_callouts[pin];
if (c == NULL) {
- mv_gpio_int_ack(pin);
+ mv_gpio_int_ack(&s);
return;
}
if (callout_pending(c) || callout_active(c)) {
- mv_gpio_int_ack(pin);
+ mv_gpio_int_ack(&s);
return;
}
- debounced_pin = (int *)malloc(sizeof(int), M_DEVBUF,
- M_WAITOK);
- if (debounced_pin == NULL) {
- mv_gpio_int_ack(pin);
+ sd = (struct mv_gpio_pindev *)malloc(sizeof(struct mv_gpio_pindev),
+ M_DEVBUF, M_WAITOK);
+ if (sd == NULL) {
+ mv_gpio_int_ack(&s);
return;
}
- *debounced_pin = pin;
+ sd->pin = pin;
+ sd->dev = dev;
- callout_reset(c, DEBOUNCE_CHECK_TICKS, mv_gpio_debounce,
- debounced_pin);
+ callout_reset(c, DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, sd);
}
static void
@@ -656,15 +680,21 @@
{
uint8_t raw_read, last_state;
int pin;
+ device_t dev;
int *debounce_counter;
+ struct mv_gpio_softc *sc;
+ struct mv_gpio_pindev *s;
- pin = *((int *)arg);
+ s = (struct mv_gpio_pindev *)arg;
+ dev = s->dev;
+ pin = s->pin;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_LOCK();
- raw_read = (mv_gpio_value_get(pin, 1) ? 1 : 0);
- last_state = (mv_gpio_debounced_state_get(pin) ? 1 : 0);
- debounce_counter = &mv_gpio_softc->debounce_counters[pin];
+ raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
+ last_state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0);
+ debounce_counter = &sc->debounce_counters[pin];
if (raw_read == last_state) {
if (last_state)
@@ -674,15 +704,15 @@
*debounce_counter = DEBOUNCE_LO_HI_MS /
DEBOUNCE_CHECK_MS;
- callout_reset(mv_gpio_softc->debounce_callouts[pin],
+ callout_reset(sc->debounce_callouts[pin],
DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
} else {
*debounce_counter = *debounce_counter - 1;
if (*debounce_counter != 0)
- callout_reset(mv_gpio_softc->debounce_callouts[pin],
+ callout_reset(sc->debounce_callouts[pin],
DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
else {
- mv_gpio_debounced_state_set(pin, raw_read);
+ mv_gpio_debounced_state_set(dev, pin, raw_read);
if (last_state)
*debounce_counter = DEBOUNCE_HI_LO_MS /
@@ -691,19 +721,18 @@
*debounce_counter = DEBOUNCE_LO_HI_MS /
DEBOUNCE_CHECK_MS;
- if (((gpio_setup[pin] & MV_GPIO_IN_POL_LOW) &&
+ if (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) &&
(raw_read == 0)) ||
- (((gpio_setup[pin] & MV_GPIO_IN_POL_LOW) == 0) &&
+ (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) == 0) &&
raw_read) ||
- (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE))
- mv_gpio_intr_handler(pin);
+ (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE))
+ mv_gpio_intr_handler(dev, pin);
/* Toggle polarity for next edge. */
- mv_gpio_polarity(pin, 0, 1);
+ mv_gpio_polarity(dev, pin, 0, 1);
free(arg, M_DEVBUF);
- callout_deactivate(mv_gpio_softc->
- debounce_callouts[pin]);
+ callout_deactivate(sc->debounce_callouts[pin]);
}
}
@@ -711,17 +740,19 @@
}
static void
-mv_gpio_debounced_state_set(int pin, uint8_t new_state)
+mv_gpio_debounced_state_set(device_t dev, int pin, uint8_t new_state)
{
uint32_t *old_state;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_ASSERT_LOCKED();
if (pin >= GPIO_PINS_PER_REG) {
- old_state = &mv_gpio_softc->debounced_state_hi;
+ old_state = &sc->debounced_state_hi;
pin -= GPIO_PINS_PER_REG;
} else
- old_state = &mv_gpio_softc->debounced_state_lo;
+ old_state = &sc->debounced_state_lo;
if (new_state)
*old_state |= (1 << pin);
@@ -730,265 +761,255 @@
}
static uint32_t
-mv_gpio_debounced_state_get(int pin)
+mv_gpio_debounced_state_get(device_t dev, int pin)
{
uint32_t *state;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_ASSERT_LOCKED();
if (pin >= GPIO_PINS_PER_REG) {
- state = &mv_gpio_softc->debounced_state_hi;
+ state = &sc->debounced_state_hi;
pin -= GPIO_PINS_PER_REG;
} else
- state = &mv_gpio_softc->debounced_state_lo;
+ state = &sc->debounced_state_lo;
return (*state & (1 << pin));
}
void
-mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable)
+mv_gpio_out(device_t dev, uint32_t pin, uint8_t val, uint8_t enable)
{
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_LOCK();
- mv_gpio_value_set(pin, val);
- mv_gpio_out_en(pin, enable);
+ mv_gpio_value_set(dev, pin, val);
+ mv_gpio_out_en(dev, pin, enable);
MV_GPIO_UNLOCK();
}
uint8_t
-mv_gpio_in(uint32_t pin)
+mv_gpio_in(device_t dev, uint32_t pin)
{
uint8_t state;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
MV_GPIO_LOCK();
- if (gpio_setup[pin] & MV_GPIO_IN_DEBOUNCE) {
- if (gpio_setup[pin] & MV_GPIO_IN_POL_LOW)
- state = (mv_gpio_debounced_state_get(pin) ? 0 : 1);
+ if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) {
+ if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW)
+ state = (mv_gpio_debounced_state_get(dev, pin) ? 0 : 1);
else
- state = (mv_gpio_debounced_state_get(pin) ? 1 : 0);
- } else if (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
- if (gpio_setup[pin] & MV_GPIO_IN_POL_LOW)
- state = (mv_gpio_value_get(pin, 1) ? 0 : 1);
+ state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0);
+ } else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
+ if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW)
+ state = (mv_gpio_value_get(dev, pin, 1) ? 0 : 1);
else
- state = (mv_gpio_value_get(pin, 1) ? 1 : 0);
+ state = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
} else
- state = (mv_gpio_value_get(pin, 0) ? 1 : 0);
+ state = (mv_gpio_value_get(dev, pin, 0) ? 1 : 0);
- MV_GPIO_UNLOCK();
return (state);
}
static uint32_t
-mv_gpio_reg_read(uint32_t reg)
+mv_gpio_reg_read(device_t dev, uint32_t reg)
{
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- return (bus_space_read_4(mv_gpio_softc->bst,
- mv_gpio_softc->bsh, reg));
+ return (bus_space_read_4(sc->bst, sc->bsh, reg));
}
static void
-mv_gpio_reg_write(uint32_t reg, uint32_t val)
+mv_gpio_reg_write(device_t dev, uint32_t reg, uint32_t val)
{
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- bus_space_write_4(mv_gpio_softc->bst,
- mv_gpio_softc->bsh, reg, val);
+ bus_space_write_4(sc->bst, sc->bsh, reg, val);
}
static void
-mv_gpio_reg_set(uint32_t reg, uint32_t pin)
+mv_gpio_reg_set(device_t dev, uint32_t reg, uint32_t pin)
{
uint32_t reg_val;
- reg_val = mv_gpio_reg_read(reg);
+ reg_val = mv_gpio_reg_read(dev, reg);
reg_val |= GPIO(pin);
- mv_gpio_reg_write(reg, reg_val);
+ mv_gpio_reg_write(dev, reg, reg_val);
}
static void
-mv_gpio_reg_clear(uint32_t reg, uint32_t pin)
+mv_gpio_reg_clear(device_t dev, uint32_t reg, uint32_t pin)
{
uint32_t reg_val;
- reg_val = mv_gpio_reg_read(reg);
+ reg_val = mv_gpio_reg_read(dev, reg);
reg_val &= ~(GPIO(pin));
- mv_gpio_reg_write(reg, reg_val);
+ mv_gpio_reg_write(dev, reg, reg_val);
}
static void
-mv_gpio_out_en(uint32_t pin, uint8_t enable)
+mv_gpio_out_en(device_t dev, uint32_t pin, uint8_t enable)
{
uint32_t reg;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return;
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_DATA_OUT_EN_CTRL;
- pin -= GPIO_PINS_PER_REG;
- } else
- reg = GPIO_DATA_OUT_EN_CTRL;
+ reg = GPIO_DATA_OUT_EN_CTRL;
if (enable)
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(dev, reg, pin);
else
- mv_gpio_reg_set(reg, pin);
+ mv_gpio_reg_set(dev, reg, pin);
}
static void
-mv_gpio_blink(uint32_t pin, uint8_t enable)
+mv_gpio_blink(device_t dev, uint32_t pin, uint8_t enable)
{
uint32_t reg;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return;
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_BLINK_EN;
- pin -= GPIO_PINS_PER_REG;
- } else
- reg = GPIO_BLINK_EN;
+ reg = GPIO_BLINK_EN;
if (enable)
- mv_gpio_reg_set(reg, pin);
+ mv_gpio_reg_set(dev, reg, pin);
else
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(dev, reg, pin);
}
static void
-mv_gpio_polarity(uint32_t pin, uint8_t enable, uint8_t toggle)
+mv_gpio_polarity(device_t dev, uint32_t pin, uint8_t enable, uint8_t toggle)
{
uint32_t reg, reg_val;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return;
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_DATA_IN_POLAR;
- pin -= GPIO_PINS_PER_REG;
- } else
- reg = GPIO_DATA_IN_POLAR;
+ reg = GPIO_DATA_IN_POLAR;
if (toggle) {
- reg_val = mv_gpio_reg_read(reg) & GPIO(pin);
+ reg_val = mv_gpio_reg_read(dev, reg) & GPIO(pin);
if (reg_val)
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(dev, reg, pin);
else
- mv_gpio_reg_set(reg, pin);
+ mv_gpio_reg_set(dev, reg, pin);
} else if (enable)
- mv_gpio_reg_set(reg, pin);
+ mv_gpio_reg_set(dev, reg, pin);
else
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(dev, reg, pin);
}
static void
-mv_gpio_level(uint32_t pin, uint8_t enable)
+mv_gpio_level(device_t dev, uint32_t pin, uint8_t enable)
{
uint32_t reg;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return;
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_INT_LEV_MASK;
- pin -= GPIO_PINS_PER_REG;
- } else
- reg = GPIO_INT_LEV_MASK;
+ reg = GPIO_INT_LEV_MASK;
if (enable)
- mv_gpio_reg_set(reg, pin);
+ mv_gpio_reg_set(dev, reg, pin);
else
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(dev, reg, pin);
}
static void
-mv_gpio_edge(uint32_t pin, uint8_t enable)
+mv_gpio_edge(device_t dev, uint32_t pin, uint8_t enable)
{
uint32_t reg;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return;
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_INT_EDGE_MASK;
- pin -= GPIO_PINS_PER_REG;
- } else
- reg = GPIO_INT_EDGE_MASK;
+ reg = GPIO_INT_EDGE_MASK;
if (enable)
- mv_gpio_reg_set(reg, pin);
+ mv_gpio_reg_set(dev, reg, pin);
else
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(dev, reg, pin);
}
static void
-mv_gpio_int_ack(uint32_t pin)
+mv_gpio_int_ack(struct mv_gpio_pindev *s)
{
- uint32_t reg;
+ uint32_t reg, pin;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
+ pin = s->pin;
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return;
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_INT_CAUSE;
- pin -= GPIO_PINS_PER_REG;
- } else
- reg = GPIO_INT_CAUSE;
+ reg = GPIO_INT_CAUSE;
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(s->dev, reg, pin);
}
static uint32_t
-mv_gpio_value_get(uint32_t pin, uint8_t exclude_polar)
+mv_gpio_value_get(device_t dev, uint32_t pin, uint8_t exclude_polar)
{
uint32_t reg, polar_reg, reg_val, polar_reg_val;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return (0);
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_DATA_IN;
- pin -= GPIO_PINS_PER_REG;
- polar_reg = GPIO_HI_DATA_IN_POLAR;
- } else {
- reg = GPIO_DATA_IN;
- polar_reg = GPIO_DATA_IN_POLAR;
- }
+ reg = GPIO_DATA_IN;
+ polar_reg = GPIO_DATA_IN_POLAR;
- reg_val = mv_gpio_reg_read(reg);
+ reg_val = mv_gpio_reg_read(dev, reg);
if (exclude_polar) {
- polar_reg_val = mv_gpio_reg_read(polar_reg);
+ polar_reg_val = mv_gpio_reg_read(dev, polar_reg);
return ((reg_val & GPIO(pin)) ^ (polar_reg_val & GPIO(pin)));
} else
return (reg_val & GPIO(pin));
}
static void
-mv_gpio_value_set(uint32_t pin, uint8_t val)
+mv_gpio_value_set(device_t dev, uint32_t pin, uint8_t val)
{
uint32_t reg;
+ struct mv_gpio_softc *sc;
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (pin >= mv_gpio_softc->pin_num)
+ if (pin >= sc->pin_num)
return;
- if (pin >= GPIO_PINS_PER_REG) {
- reg = GPIO_HI_DATA_OUT;
- pin -= GPIO_PINS_PER_REG;
- } else
- reg = GPIO_DATA_OUT;
+ reg = GPIO_DATA_OUT;
if (val)
- mv_gpio_reg_set(reg, pin);
+ mv_gpio_reg_set(dev, reg, pin);
else
- mv_gpio_reg_clear(reg, pin);
+ mv_gpio_reg_clear(dev, reg, pin);
}
static int
-mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len)
+mv_handle_gpios_prop(device_t dev, phandle_t ctrl, pcell_t *gpios, int len)
{
pcell_t gpio_cells, pincnt;
int inc, t, tuples, tuple_size;
@@ -1028,18 +1049,18 @@
dir = gpios[1];
flags = gpios[2];
- mv_gpio_configure(pin, flags, ~0);
+ mv_gpio_configure(dev, pin, flags, ~0);
if (dir == 1)
/* Input. */
- mv_gpio_out_en(pin, 0);
+ mv_gpio_out_en(dev, pin, 0);
else {
/* Output. */
if (flags & MV_GPIO_OUT_OPEN_DRAIN)
- mv_gpio_out(pin, 0, 1);
+ mv_gpio_out(dev, pin, 0, 1);
if (flags & MV_GPIO_OUT_OPEN_SRC)
- mv_gpio_out(pin, 1, 1);
+ mv_gpio_out(dev, pin, 1, 1);
}
gpios += gpio_cells + inc;
}
@@ -1050,7 +1071,7 @@
#define MAX_PINS_PER_NODE 5
#define GPIOS_PROP_CELLS 4
static int
-mv_gpio_init(void)
+mv_gpio_init(device_t dev)
{
phandle_t child, parent, root, ctrl;
pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS];
@@ -1090,7 +1111,7 @@
if (ofw_bus_node_is_compatible(ctrl, e->compat))
/* Call a handler. */
- if ((rv = e->handler(ctrl,
+ if ((rv = e->handler(dev, ctrl,
(pcell_t *)&gpios, len)))
return (rv);
}
Index: sys/arm/mv/mvreg.h
===================================================================
--- sys/arm/mv/mvreg.h
+++ sys/arm/mv/mvreg.h
@@ -296,15 +296,6 @@
#define GPIO_INT_EDGE_MASK 0x18
#define GPIO_INT_LEV_MASK 0x1c
-#define GPIO_HI_DATA_OUT 0x40
-#define GPIO_HI_DATA_OUT_EN_CTRL 0x44
-#define GPIO_HI_BLINK_EN 0x48
-#define GPIO_HI_DATA_IN_POLAR 0x4c
-#define GPIO_HI_DATA_IN 0x50
-#define GPIO_HI_INT_CAUSE 0x54
-#define GPIO_HI_INT_EDGE_MASK 0x58
-#define GPIO_HI_INT_LEV_MASK 0x5c
-
#define GPIO(n) (1 << (n))
#define MV_GPIO_MAX_NPINS 64
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 17, 10:50 PM (1 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33215609
Default Alt Text
D14755.id40469.diff (30 KB)
Attached To
Mode
D14755: Make gpio driver able to work with many controllers
Attached
Detach File
Event Timeline
Log In to Comment