Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/mediatek/mtk_gpio_v1.c
Show First 20 Lines • Show All 285 Lines • ▼ Show 20 Lines | mtk_gpio_attach(device_t dev) | ||||
if (OF_hasprop(node, "ralink,num-gpios") && (OF_getencprop(node, | if (OF_hasprop(node, "ralink,num-gpios") && (OF_getencprop(node, | ||||
"ralink,num-gpios", &num_pins, sizeof(num_pins)) >= 0)) | "ralink,num-gpios", &num_pins, sizeof(num_pins)) >= 0)) | ||||
sc->num_pins = num_pins; | sc->num_pins = num_pins; | ||||
else | else | ||||
sc->num_pins = MTK_GPIO_PINS; | sc->num_pins = MTK_GPIO_PINS; | ||||
for (i = 0; i < sc->num_pins; i++) { | for (i = 0; i < sc->num_pins; i++) { | ||||
sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | | sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | | ||||
GPIO_PIN_INVIN | GPIO_PIN_INVOUT; | GPIO_PIN_INVIN | GPIO_PIN_INVOUT | | ||||
GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING; | |||||
sc->pins[i].intr_polarity = INTR_POLARITY_HIGH; | sc->pins[i].intr_polarity = INTR_POLARITY_HIGH; | ||||
mizhka: sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
GPIO_PIN_INVIN |… | |||||
sc->pins[i].intr_trigger = INTR_TRIGGER_EDGE; | sc->pins[i].intr_trigger = INTR_TRIGGER_EDGE; | ||||
snprintf(sc->pins[i].pin_name, GPIOMAXNAME - 1, "gpio%c%d", | snprintf(sc->pins[i].pin_name, GPIOMAXNAME - 1, "gpio%c%d", | ||||
device_get_unit(dev) + 'a', i); | device_get_unit(dev) + 'a', i); | ||||
sc->pins[i].pin_name[GPIOMAXNAME - 1] = '\0'; | sc->pins[i].pin_name[GPIOMAXNAME - 1] = '\0'; | ||||
mtk_gpio_pin_probe(sc, i); | mtk_gpio_pin_probe(sc, i); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | |||||
out: | out: | ||||
MTK_GPIO_UNLOCK(sc); | MTK_GPIO_UNLOCK(sc); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
mtk_gpio_pic_map_fdt(struct mtk_gpio_softc *sc, | |||||
struct intr_map_data_fdt *daf, u_int *irqp, uint32_t *modep) | |||||
{ | |||||
u_int irq; | |||||
Not Done Inline Actionsuint32_t? mizhka: uint32_t? | |||||
if (daf->ncells != 1) { | |||||
device_printf(sc->dev, "Invalid #interrupt-cells\n"); | |||||
return (EINVAL); | |||||
} | |||||
irq = daf->cells[0]; | |||||
if (irq >= sc->num_pins) { | |||||
device_printf(sc->dev, "Invalid interrupt number %u\n", irq); | |||||
return (EINVAL); | |||||
} | |||||
*irqp = irq; | |||||
if (modep != NULL) | |||||
*modep = GPIO_INTR_EDGE_BOTH; | |||||
return (0); | |||||
} | |||||
static int | |||||
mtk_gpio_pic_map_gpio(struct mtk_gpio_softc *sc, | |||||
struct intr_map_data_gpio *dag, u_int *irqp, uint32_t *modep) | |||||
{ | |||||
u_int irq; | |||||
irq = dag->gpio_pin_num; | |||||
if (irq >= sc->num_pins) { | |||||
device_printf(sc->dev, "Invalid interrupt number %u\n", irq); | |||||
return (EINVAL); | |||||
} | |||||
*irqp = irq; | |||||
if (modep != NULL) | |||||
*modep = dag->gpio_intr_mode; | |||||
return (0); | |||||
} | |||||
static int | |||||
mtk_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, | mtk_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, | ||||
struct intr_irqsrc **isrcp) | struct intr_irqsrc **isrcp) | ||||
{ | { | ||||
struct intr_map_data_fdt *daf; | int error; | ||||
u_int irq; | |||||
struct mtk_gpio_softc *sc; | struct mtk_gpio_softc *sc; | ||||
if (data->type != INTR_MAP_DATA_FDT) | |||||
return (ENOTSUP); | |||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
daf = (struct intr_map_data_fdt *)data; | switch (data->type) { | ||||
case INTR_MAP_DATA_FDT: | |||||
error = (mtk_gpio_pic_map_fdt(sc, | |||||
(struct intr_map_data_fdt *)data, &irq, NULL)); | |||||
break; | |||||
case INTR_MAP_DATA_GPIO: | |||||
error = (mtk_gpio_pic_map_gpio(sc, | |||||
(struct intr_map_data_gpio *)data, &irq, NULL)); | |||||
break; | |||||
default: | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
if (daf->ncells != 1 || daf->cells[0] >= sc->num_pins) | if (error != 0) { | ||||
return (EINVAL); | device_printf(dev, "Invalid map type\n"); | ||||
return (error); | |||||
} | |||||
Not Done Inline Actionserror may be EINVAL. It's better to printf error before lost of context. mizhka: error may be EINVAL. It's better to printf error before lost of context. | |||||
*isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); | *isrcp = PIC_INTR_ISRC(sc, irq); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
mtk_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) | mtk_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) | ||||
{ | { | ||||
struct mtk_gpio_softc *sc; | struct mtk_gpio_softc *sc; | ||||
struct mtk_gpio_pin_irqsrc *pisrc; | struct mtk_gpio_pin_irqsrc *pisrc; | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | mtk_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc) | ||||
pisrc = (struct mtk_gpio_pin_irqsrc *)isrc; | pisrc = (struct mtk_gpio_pin_irqsrc *)isrc; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
MTK_GPIO_LOCK(sc); | MTK_GPIO_LOCK(sc); | ||||
MTK_WRITE_4(sc, GPIO_PIOINT, 1u << pisrc->irq); | MTK_WRITE_4(sc, GPIO_PIOINT, 1u << pisrc->irq); | ||||
MTK_GPIO_UNLOCK(sc); | MTK_GPIO_UNLOCK(sc); | ||||
} | } | ||||
static int | static int | ||||
mtk_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, | |||||
struct resource *res, struct intr_map_data *data) | |||||
{ | |||||
struct mtk_gpio_softc *sc; | |||||
uint32_t val; | |||||
int error; | |||||
uint32_t mode; | |||||
u_int irq; | |||||
if (data == NULL) | |||||
return (ENOTSUP); | |||||
sc = device_get_softc(dev); | |||||
switch (data->type) { | |||||
case INTR_MAP_DATA_FDT: | |||||
error = mtk_gpio_pic_map_fdt(sc, | |||||
(struct intr_map_data_fdt *)data, &irq, &mode); | |||||
break; | |||||
case INTR_MAP_DATA_GPIO: | |||||
error = mtk_gpio_pic_map_gpio(sc, | |||||
(struct intr_map_data_gpio *)data, &irq, &mode); | |||||
break; | |||||
default: | |||||
error = ENOTSUP; | |||||
break; | |||||
} | |||||
if (error != 0) | |||||
return (error); | |||||
MTK_GPIO_LOCK(sc); | |||||
if (mode == GPIO_INTR_EDGE_BOTH || mode == GPIO_INTR_EDGE_RISING) { | |||||
val = MTK_READ_4(sc, GPIO_PIORENA) | (1u << irq); | |||||
MTK_WRITE_4(sc, GPIO_PIORENA, val); | |||||
} | |||||
if (mode == GPIO_INTR_EDGE_BOTH || mode == GPIO_INTR_EDGE_FALLING) { | |||||
val = MTK_READ_4(sc, GPIO_PIOFENA) | (1u << irq); | |||||
MTK_WRITE_4(sc, GPIO_PIOFENA, val); | |||||
} | |||||
MTK_GPIO_UNLOCK(sc); | |||||
return (0); | |||||
} | |||||
static int | |||||
mtk_gpio_intr(void *arg) | mtk_gpio_intr(void *arg) | ||||
{ | { | ||||
struct mtk_gpio_softc *sc; | struct mtk_gpio_softc *sc; | ||||
uint32_t i, interrupts; | uint32_t i, interrupts; | ||||
sc = arg; | sc = arg; | ||||
interrupts = MTK_READ_4(sc, GPIO_PIOINT); | interrupts = MTK_READ_4(sc, GPIO_PIOINT); | ||||
MTK_WRITE_4(sc, GPIO_PIOINT, interrupts); | |||||
for (i = 0; interrupts != 0; i++, interrupts >>= 1) { | for (i = 0; interrupts != 0; i++, interrupts >>= 1) { | ||||
if ((interrupts & 0x1) == 0) | if ((interrupts & 0x1) == 0) | ||||
continue; | continue; | ||||
if (intr_isrc_dispatch(PIC_INTR_ISRC(sc, i), | if (intr_isrc_dispatch(PIC_INTR_ISRC(sc, i), | ||||
curthread->td_intr_frame) != 0) { | curthread->td_intr_frame) != 0) { | ||||
device_printf(sc->dev, "spurious interrupt %d\n", i); | device_printf(sc->dev, "spurious interrupt %d\n", i); | ||||
} | } | ||||
Show All 26 Lines | static device_method_t mtk_gpio_methods[] = { | ||||
DEVMETHOD(gpio_pin_get, mtk_gpio_pin_get), | DEVMETHOD(gpio_pin_get, mtk_gpio_pin_get), | ||||
DEVMETHOD(gpio_pin_set, mtk_gpio_pin_set), | DEVMETHOD(gpio_pin_set, mtk_gpio_pin_set), | ||||
DEVMETHOD(gpio_pin_toggle, mtk_gpio_pin_toggle), | DEVMETHOD(gpio_pin_toggle, mtk_gpio_pin_toggle), | ||||
/* Interrupt controller interface */ | /* Interrupt controller interface */ | ||||
DEVMETHOD(pic_disable_intr, mtk_gpio_pic_disable_intr), | DEVMETHOD(pic_disable_intr, mtk_gpio_pic_disable_intr), | ||||
DEVMETHOD(pic_enable_intr, mtk_gpio_pic_enable_intr), | DEVMETHOD(pic_enable_intr, mtk_gpio_pic_enable_intr), | ||||
DEVMETHOD(pic_map_intr, mtk_gpio_pic_map_intr), | DEVMETHOD(pic_map_intr, mtk_gpio_pic_map_intr), | ||||
DEVMETHOD(pic_setup_intr, mtk_gpio_pic_setup_intr), | |||||
DEVMETHOD(pic_post_filter, mtk_gpio_pic_post_filter), | DEVMETHOD(pic_post_filter, mtk_gpio_pic_post_filter), | ||||
DEVMETHOD(pic_post_ithread, mtk_gpio_pic_post_ithread), | DEVMETHOD(pic_post_ithread, mtk_gpio_pic_post_ithread), | ||||
DEVMETHOD(pic_pre_ithread, mtk_gpio_pic_pre_ithread), | DEVMETHOD(pic_pre_ithread, mtk_gpio_pic_pre_ithread), | ||||
/* ofw_bus interface */ | /* ofw_bus interface */ | ||||
DEVMETHOD(ofw_bus_get_node, mtk_gpio_get_node), | DEVMETHOD(ofw_bus_get_node, mtk_gpio_get_node), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
Show All 12 Lines |
sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |