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_OUTPUT 1 | |||||
#define A10_GPIO_INPUT 0 | #define AW_GPIO_DRV_MASK 0x3 | ||||
#define A10_GPIO_OUTPUT 1 | #define AW_GPIO_PUD_MASK 0x3 | ||||
#define AW_GPIO_DRV_MASK 0x3 | #define AW_PINCTRL 1 | ||||
#define AW_GPIO_PUD_MASK 0x3 | #define AW_R_PINCTRL 2 | ||||
static struct ofw_compat_data compat_data[] = { | static struct ofw_compat_data compat_data[] = { | ||||
{"allwinner,sun4i-a10-pinctrl", 1}, | {"allwinner,sun4i-a10-pinctrl", AW_PINCTRL}, | ||||
{"allwinner,sun7i-a20-pinctrl", 1}, | {"allwinner,sun7i-a20-pinctrl", AW_PINCTRL}, | ||||
{"allwinner,sun6i-a31-pinctrl", 1}, | {"allwinner,sun6i-a31-pinctrl", AW_PINCTRL}, | ||||
{"allwinner,sun6i-a31s-pinctrl", 1}, | {"allwinner,sun6i-a31-r-pinctrl", AW_R_PINCTRL}, | ||||
{"allwinner,sun6i-a31s-pinctrl", AW_PINCTRL}, | |||||
{NULL, 0} | {NULL, 0} | ||||
}; | }; | ||||
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; | ||||
jmcneill: Instead of the ifndef below, why don't we just say `#if defined(SOC_ALLWINNER_A31) || defined… | |||||
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 | |||||
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; | ||||
Done Inline ActionsThis compat string is duplicated on line 111 jmcneill: This compat string is duplicated on line 111 | |||||
#ifndef SOC_ALLWINNER_A31 | |||||
extern const struct allwinner_padconf a31_r_padconf; | |||||
#endif | |||||
#endif | #endif | ||||
#define A10_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx) | #define A10_GPIO_LOCK(_sc) mtx_lock_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; | ||||
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()) { | switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { | ||||
case AW_PINCTRL: | |||||
switch (allwinner_soc_type()) { | |||||
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… | |||||
#ifdef SOC_ALLWINNER_A10 | #ifdef SOC_ALLWINNER_A10 | ||||
case ALLWINNERSOC_A10: | case ALLWINNERSOC_A10: | ||||
sc->padconf = &a10_padconf; | sc->padconf = &a10_padconf; | ||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef SOC_ALLWINNER_A20 | #ifdef SOC_ALLWINNER_A20 | ||||
case ALLWINNERSOC_A20: | case ALLWINNERSOC_A20: | ||||
sc->padconf = &a20_padconf; | sc->padconf = &a20_padconf; | ||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef SOC_ALLWINNER_A31 | #ifdef SOC_ALLWINNER_A31 | ||||
case ALLWINNERSOC_A31: | case ALLWINNERSOC_A31: | ||||
sc->padconf = &a31_padconf; | sc->padconf = &a31_padconf; | ||||
break; | |||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef SOC_ALLWINNER_A31S | #ifdef SOC_ALLWINNER_A31S | ||||
case ALLWINNERSOC_A31S: | case ALLWINNERSOC_A31S: | ||||
sc->padconf = &a31s_padconf; | sc->padconf = &a31s_padconf; | ||||
break; | break; | ||||
#endif | #endif | ||||
default: | default: | ||||
return (ENOENT); | return (ENOENT); | ||||
} | |||||
break; | |||||
case AW_R_PINCTRL: | |||||
jmcneillUnsubmitted Done Inline ActionsShould this be protected with ifdef SOC_ALLWINNER_xxx ? jmcneill: Should this be protected with ifdef SOC_ALLWINNER_xxx ? | |||||
sc->padconf = &a31_r_padconf; | |||||
break; | |||||
} | |||||
if (hwreset_get_by_ofw_idx(dev, 0, &rst) == 0) { | |||||
error = hwreset_deassert(rst); | |||||
if (error != 0) { | |||||
device_printf(dev, "cannot de-assert reset\n"); | |||||
return (error); | |||||
} | |||||
} | |||||
if (clk_get_by_ofw_index(dev, 0, &clk) == 0) { | |||||
error = clk_enable(clk); | |||||
if (error != 0) { | |||||
device_printf(dev, "could not enable clock\n"); | |||||
return (error); | |||||
} | |||||
} | } | ||||
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.