Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/qoriq/ls1046_gpio.c
Show First 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | |||||
#define QORIQ_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->mutex) | #define QORIQ_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->mutex) | ||||
#define QORIQ_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mutex, MA_OWNED) | #define QORIQ_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mutex, MA_OWNED) | ||||
/* prototypes */ | /* prototypes */ | ||||
/* helpers */ | /* helpers */ | ||||
static int qoriq_make_gpio_res(device_t, struct gpio_res*); | static int qoriq_make_gpio_res(device_t, struct gpio_res*); | ||||
static uint32_t qoriq_gpio_reg_read(device_t, uint32_t); | static uint32_t qoriq_gpio_reg_read(device_t, uint32_t); | ||||
static void qoriq_gpio_reg_write(device_t, uint32_t, uint32_t); | static void qoriq_gpio_reg_write(device_t, uint32_t, uint32_t); | ||||
static void qoriq_gpio_reg_set(device_t, uint32_t, uint32_t); | static void qoriq_gpio_set(device_t, uint32_t, uint32_t, uint32_t); | ||||
static void qoriq_gpio_reg_clear(device_t, uint32_t, uint32_t); | |||||
static void qoriq_gpio_out_en(device_t, uint32_t, uint8_t); | |||||
static void qoriq_gpio_value_set(device_t, uint32_t, uint8_t); | |||||
static uint32_t qoriq_gpio_value_get(device_t, uint32_t); | |||||
static void qoriq_gpio_open_drain_set(device_t, uint32_t, uint8_t); | |||||
static int qoriq_gpio_configure(device_t, uint32_t, uint32_t); | static int qoriq_gpio_configure(device_t, uint32_t, uint32_t); | ||||
/* GPIO API */ | /* GPIO API */ | ||||
static int qoriq_gpio_probe(device_t); | static int qoriq_gpio_probe(device_t); | ||||
static int qoriq_gpio_attach(device_t); | static int qoriq_gpio_attach(device_t); | ||||
static device_t qoriq_gpio_get_bus(device_t); | static device_t qoriq_gpio_get_bus(device_t); | ||||
static int qoriq_gpio_pin_max(device_t, int*); | static int qoriq_gpio_pin_max(device_t, int*); | ||||
static int qoriq_gpio_pin_getname(device_t, uint32_t, char*); | static int qoriq_gpio_pin_getname(device_t, uint32_t, char*); | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | qoriq_gpio_reg_write(device_t dev, uint32_t reg, uint32_t val) | ||||
val = htobe32(val); | val = htobe32(val); | ||||
bus_write_4(sc->res.mem_res, reg, val); | bus_write_4(sc->res.mem_res, reg, val); | ||||
bus_barrier(sc->res.mem_res, reg, 4, BUS_SPACE_BARRIER_READ | | bus_barrier(sc->res.mem_res, reg, 4, BUS_SPACE_BARRIER_READ | | ||||
BUS_SPACE_BARRIER_WRITE); | BUS_SPACE_BARRIER_WRITE); | ||||
} | } | ||||
static void | static void | ||||
qoriq_gpio_reg_set(device_t dev, uint32_t reg, uint32_t pin) | qoriq_gpio_set(device_t dev, uint32_t reg, uint32_t pin, uint32_t set) | ||||
{ | { | ||||
uint32_t reg_val; | uint32_t val; | ||||
reg_val = qoriq_gpio_reg_read(dev, reg); | set = set != 0; | ||||
reg_val |= GPIO(pin); | val = (qoriq_gpio_reg_read(dev, reg) & ~(1U << pin)) | (set << pin); | ||||
qoriq_gpio_reg_write(dev, reg, reg_val); | qoriq_gpio_reg_write(dev, reg, val); | ||||
} | } | ||||
static void | |||||
qoriq_gpio_reg_clear(device_t dev, uint32_t reg, uint32_t pin) | |||||
{ | |||||
uint32_t reg_val; | |||||
reg_val = qoriq_gpio_reg_read(dev, reg); | |||||
reg_val &= ~(GPIO(pin)); | |||||
qoriq_gpio_reg_write(dev, reg, reg_val); | |||||
} | |||||
static void | |||||
qoriq_gpio_out_en(device_t dev, uint32_t pin, uint8_t enable) | |||||
{ | |||||
if (pin >= PIN_COUNT) | |||||
return; | |||||
if (enable != 0) | |||||
qoriq_gpio_reg_set(dev, DIRECTION, pin); | |||||
else | |||||
qoriq_gpio_reg_clear(dev, DIRECTION, pin); | |||||
} | |||||
static void | |||||
qoriq_gpio_value_set(device_t dev, uint32_t pin, uint8_t val) | |||||
{ | |||||
if (pin >= PIN_COUNT) | |||||
return; | |||||
if (val != 0) | |||||
qoriq_gpio_reg_set(dev, DATA, pin); | |||||
else | |||||
qoriq_gpio_reg_clear(dev, DATA, pin); | |||||
} | |||||
static uint32_t | |||||
qoriq_gpio_value_get(device_t dev, uint32_t pin) | |||||
{ | |||||
uint32_t reg_val; | |||||
if (pin >= PIN_COUNT) | |||||
return (0); | |||||
reg_val = qoriq_gpio_reg_read(dev, DATA); | |||||
return ((reg_val & GPIO(pin)) != 0); | |||||
} | |||||
static void | |||||
qoriq_gpio_open_drain_set(device_t dev, uint32_t pin, uint8_t val) | |||||
{ | |||||
if (pin >= PIN_COUNT) | |||||
return; | |||||
if (val != 0) | |||||
qoriq_gpio_reg_set(dev, OPEN_DRAIN, pin); | |||||
else | |||||
qoriq_gpio_reg_clear(dev, OPEN_DRAIN, pin); | |||||
} | |||||
static int | static int | ||||
qoriq_gpio_configure(device_t dev, uint32_t pin, uint32_t flags) | qoriq_gpio_configure(device_t dev, uint32_t pin, uint32_t flags) | ||||
{ | { | ||||
struct gpio_softc *sc = device_get_softc(dev); | struct gpio_softc *sc = device_get_softc(dev); | ||||
uint32_t newflags; | uint32_t newflags; | ||||
if (pin >= PIN_COUNT) | if (pin >= PIN_COUNT) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* | /* | ||||
* Pin cannot function as input and output at the same time. | * Pin cannot function as input and output at the same time. | ||||
* The same applies to open-drain and push-pull functionality. | * The same applies to open-drain and push-pull functionality. | ||||
*/ | */ | ||||
if (((flags & GPIO_PIN_INPUT) && (flags & GPIO_PIN_OUTPUT)) || | if (((flags & GPIO_PIN_INPUT) && (flags & GPIO_PIN_OUTPUT)) || | ||||
((flags & GPIO_PIN_OPENDRAIN) && (flags & GPIO_PIN_PUSHPULL))) | ((flags & GPIO_PIN_OPENDRAIN) && (flags & GPIO_PIN_PUSHPULL))) | ||||
return (EINVAL); | return (EINVAL); | ||||
QORIQ_GPIO_ASSERT_LOCKED(sc); | QORIQ_GPIO_ASSERT_LOCKED(sc); | ||||
if (flags & GPIO_PIN_INPUT) { | if (flags & GPIO_PIN_INPUT) { | ||||
newflags = GPIO_PIN_INPUT; | newflags = GPIO_PIN_INPUT; | ||||
qoriq_gpio_out_en(dev, pin, 0); | qoriq_gpio_set(dev, DIRECTION, pin, 0); | ||||
} | } | ||||
if (flags & GPIO_PIN_OUTPUT) { | if (flags & GPIO_PIN_OUTPUT) { | ||||
newflags = GPIO_PIN_OUTPUT; | newflags = GPIO_PIN_OUTPUT; | ||||
qoriq_gpio_out_en(dev, pin, 1); | qoriq_gpio_set(dev, DIRECTION, pin, 1); | ||||
if (flags & GPIO_PIN_OPENDRAIN) { | if (flags & GPIO_PIN_OPENDRAIN) { | ||||
newflags |= GPIO_PIN_OPENDRAIN; | newflags |= GPIO_PIN_OPENDRAIN; | ||||
qoriq_gpio_open_drain_set(dev, pin, 1); | qoriq_gpio_set(dev, OPEN_DRAIN, pin, 1); | ||||
} else { | } else { | ||||
newflags |= GPIO_PIN_PUSHPULL; | newflags |= GPIO_PIN_PUSHPULL; | ||||
qoriq_gpio_open_drain_set(dev, pin, 0); | qoriq_gpio_set(dev, OPEN_DRAIN, pin, 0); | ||||
} | } | ||||
} | } | ||||
sc->setup[pin].gp_flags = newflags; | sc->setup[pin].gp_flags = newflags; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | |||||
qoriq_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value) | qoriq_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value) | ||||
{ | { | ||||
struct gpio_softc *sc = device_get_softc(dev); | struct gpio_softc *sc = device_get_softc(dev); | ||||
if (value == NULL || pin >= PIN_COUNT) | if (value == NULL || pin >= PIN_COUNT) | ||||
return (EINVAL); | return (EINVAL); | ||||
QORIQ_GPIO_LOCK(sc); | QORIQ_GPIO_LOCK(sc); | ||||
*value = qoriq_gpio_value_get(dev, pin); | *value = (qoriq_gpio_reg_read(dev, DATA) & GPIO(pin)) != 0; | ||||
QORIQ_GPIO_UNLOCK(sc); | QORIQ_GPIO_UNLOCK(sc); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
qoriq_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value) | qoriq_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value) | ||||
{ | { | ||||
struct gpio_softc *sc = device_get_softc(dev); | struct gpio_softc *sc = device_get_softc(dev); | ||||
if (pin >= PIN_COUNT) | if (pin >= PIN_COUNT) | ||||
return (EINVAL); | return (EINVAL); | ||||
QORIQ_GPIO_LOCK(sc); | QORIQ_GPIO_LOCK(sc); | ||||
qoriq_gpio_value_set(dev, pin, value); | qoriq_gpio_set(dev, DATA, pin, value); | ||||
QORIQ_GPIO_UNLOCK(sc); | QORIQ_GPIO_UNLOCK(sc); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
qoriq_gpio_pin_toggle(device_t dev, uint32_t pin) | qoriq_gpio_pin_toggle(device_t dev, uint32_t pin) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 114 Lines • Show Last 20 Lines |