Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/allwinner/a10_gpio.c
Context not available. | |||||
#include <arm/allwinner/allwinner_machdep.h> | #include <arm/allwinner/allwinner_machdep.h> | ||||
#include <arm/allwinner/allwinner_pinctrl.h> | #include <arm/allwinner/allwinner_pinctrl.h> | ||||
#include <dev/extres/clk/clk.h> | |||||
#include <dev/extres/hwreset/hwreset.h> | |||||
#include "gpio_if.h" | #include "gpio_if.h" | ||||
/* | |||||
* A10 have 9 banks of gpio. | |||||
* 32 pins per bank: | |||||
* PA0 - PA17 | PB0 - PB23 | PC0 - PC24 | |||||
* PD0 - PD27 | PE0 - PE31 | PF0 - PF5 | |||||
* PG0 - PG9 | PH0 - PH27 | PI0 - PI12 | |||||
*/ | |||||
#define A10_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ | #define A10_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ | ||||
GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) | GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) | ||||
#define A10_GPIO_NONE 0 | #define A10_GPIO_NONE 0 | ||||
#define A10_GPIO_PULLUP 1 | #define A10_GPIO_PULLUP 1 | ||||
#define A10_GPIO_PULLDOWN 2 | #define A10_GPIO_PULLDOWN 2 | ||||
#define A10_GPIO_INPUT 0 | #define A10_GPIO_INPUT 0 | ||||
#define A10_GPIO_OUTPUT 1 | #define A10_GPIO_OUTPUT 1 | ||||
#define AW_GPIO_DRV_MASK 0x3 | #define AW_GPIO_DRV_MASK 0x3 | ||||
#define AW_GPIO_PUD_MASK 0x3 | #define AW_GPIO_PUD_MASK 0x3 | ||||
static struct ofw_compat_data compat_data[] = { | #define AW_PINCTRL 1 | ||||
{"allwinner,sun4i-a10-pinctrl", 1}, | #define AW_R_PINCTRL 2 | ||||
{"allwinner,sun7i-a20-pinctrl", 1}, | |||||
{"allwinner,sun6i-a31-pinctrl", 1}, | |||||
{"allwinner,sun6i-a31s-pinctrl", 1}, | |||||
{NULL, 0} | |||||
}; | |||||
struct a10_gpio_softc { | |||||
device_t sc_dev; | |||||
device_t sc_busdev; | |||||
struct mtx sc_mtx; | |||||
struct resource * sc_mem_res; | |||||
struct resource * sc_irq_res; | |||||
bus_space_tag_t sc_bst; | |||||
bus_space_handle_t sc_bsh; | |||||
void * sc_intrhand; | |||||
const struct allwinner_padconf * padconf; | |||||
}; | |||||
/* Defined in a10_padconf.c */ | /* Defined in a10_padconf.c */ | ||||
#ifdef SOC_ALLWINNER_A10 | #ifdef SOC_ALLWINNER_A10 | ||||
Context not available. | |||||
/* Defined in a31_padconf.c */ | /* Defined in a31_padconf.c */ | ||||
#ifdef SOC_ALLWINNER_A31 | #ifdef SOC_ALLWINNER_A31 | ||||
extern const struct allwinner_padconf a31_padconf; | extern const struct allwinner_padconf a31_padconf; | ||||
extern const struct allwinner_padconf a31_r_padconf; | |||||
#endif | #endif | ||||
/* Defined in a31s_padconf.c */ | /* Defined in a31s_padconf.c */ | ||||
#ifdef SOC_ALLWINNER_A31S | #ifdef SOC_ALLWINNER_A31S | ||||
extern const struct allwinner_padconf a31s_padconf; | extern const struct allwinner_padconf a31s_padconf; | ||||
#ifndef SOC_ALLWINNER_A31 | |||||
extern const struct allwinner_padconf a31_r_padconf; | |||||
#endif | |||||
#endif | |||||
static struct ofw_compat_data compat_data[] = { | |||||
#ifdef SOC_ALLWINNER_A10 | |||||
{"allwinner,sun4i-a10-pinctrl", (uintptr_t)&a10_padconf}, | |||||
#endif | |||||
#ifdef SOC_ALLWINNER_A20 | |||||
{"allwinner,sun7i-a20-pinctrl", (uintptr_t)&a20_padconf}, | |||||
#endif | |||||
#ifdef SOC_ALLWINNER_A31 | |||||
{"allwinner,sun6i-a31-pinctrl", (uintptr_t)&a31_padconf}, | |||||
{"allwinner,sun6i-a31-r-pinctrl", (uintptr_t)&a31_r_padconf}, | |||||
jmcneill: Instead of the ifndef below, why don't we just say `#if defined(SOC_ALLWINNER_A31) || defined… | |||||
manu_bidouilliste.comAuthorUnsubmitted Done Inline ActionsBecause sometimes I'm stupid that's why :) manu_bidouilliste.com: Because sometimes I'm stupid that's why :)
I'll change that | |||||
#endif | |||||
#ifdef SOC_ALLWINNER_A31S | |||||
{"allwinner,sun6i-a31s-pinctrl", (uintptr_t)&a31s_padconf}, | |||||
#ifndef SOC_ALLWINNER_A31 | |||||
{"allwinner,sun6i-a31-r-pinctrl", (uintptr_t)&a31_r_padconf}, | |||||
#endif | #endif | ||||
Done Inline ActionsThis compat string is duplicated on line 111 jmcneill: This compat string is duplicated on line 111 | |||||
#endif | |||||
{NULL, 0} | |||||
}; | |||||
struct a10_gpio_softc { | |||||
device_t sc_dev; | |||||
device_t sc_busdev; | |||||
struct mtx sc_mtx; | |||||
struct resource * sc_mem_res; | |||||
struct resource * sc_irq_res; | |||||
bus_space_tag_t sc_bst; | |||||
bus_space_handle_t sc_bsh; | |||||
void * sc_intrhand; | |||||
const struct allwinner_padconf * padconf; | |||||
}; | |||||
#define A10_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) | #define A10_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) | ||||
#define A10_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx) | #define A10_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx) | ||||
Context not available. | |||||
static int | static int | ||||
a10_gpio_attach(device_t dev) | a10_gpio_attach(device_t dev) | ||||
{ | { | ||||
int rid; | int rid, error; | ||||
phandle_t gpio; | phandle_t gpio; | ||||
struct a10_gpio_softc *sc; | struct a10_gpio_softc *sc; | ||||
clk_t clk; | |||||
hwreset_t rst; | |||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->sc_dev = dev; | sc->sc_dev = dev; | ||||
Done Inline ActionsAs discussed on IRC, we should move the padconf values to compat_data[] ocd_data, so something like: static struct ofw_compat_data compat_data[] = { #ifdef SOC_ALLWINNER_A10 { "allwinner,sun4i-a10-pinctrl", (uintptr_t)&a10_padconf }, #endif ... and here we can simply do: sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; jmcneill: As discussed on IRC, we should move the padconf values to compat_data[] ocd_data, so something… | |||||
Context not available. | |||||
goto fail; | goto fail; | ||||
/* Use the right pin data for the current SoC */ | /* Use the right pin data for the current SoC */ | ||||
switch (allwinner_soc_type()) { | sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev, | ||||
#ifdef SOC_ALLWINNER_A10 | compat_data)->ocd_data; | ||||
case ALLWINNERSOC_A10: | |||||
sc->padconf = &a10_padconf; | if (hwreset_get_by_ofw_idx(dev, 0, &rst) == 0) { | ||||
break; | error = hwreset_deassert(rst); | ||||
#endif | if (error != 0) { | ||||
#ifdef SOC_ALLWINNER_A20 | device_printf(dev, "cannot de-assert reset\n"); | ||||
case ALLWINNERSOC_A20: | return (error); | ||||
sc->padconf = &a20_padconf; | } | ||||
break; | } | ||||
#endif | |||||
#ifdef SOC_ALLWINNER_A31 | if (clk_get_by_ofw_index(dev, 0, &clk) == 0) { | ||||
case ALLWINNERSOC_A31: | error = clk_enable(clk); | ||||
sc->padconf = &a31_padconf; | if (error != 0) { | ||||
break; | device_printf(dev, "could not enable clock\n"); | ||||
#endif | return (error); | ||||
#ifdef SOC_ALLWINNER_A31S | } | ||||
case ALLWINNERSOC_A31S: | |||||
sc->padconf = &a31s_padconf; | |||||
break; | |||||
#endif | |||||
default: | |||||
return (ENOENT); | |||||
} | } | ||||
Done Inline ActionsShould this be protected with ifdef SOC_ALLWINNER_xxx ? jmcneill: Should this be protected with ifdef SOC_ALLWINNER_xxx ? | |||||
sc->sc_busdev = gpiobus_attach_bus(dev); | sc->sc_busdev = gpiobus_attach_bus(dev); | ||||
Context not available. |
Instead of the ifndef below, why don't we just say #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S) here? Same for the extern above.