/** * \brief Unlock the commit control of a special function pin * * Unlocks the commit control of the given pin or group of pins. If a pin is a * JTAG/SWD or NMI, the pin may then be reconfigured as a GPIO pin. If the pin * is not locked by default, this has no effect. * * @param[in] gpioport GPIO block register address base @ref gpio_reg_base * @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified * by OR'ing then together. */ void gpio_unlock_commit(uint32_t gpioport, uint8_t gpios) { /* Unlock the GPIO_CR register */ GPIO_LOCK(gpioport) = GPIO_LOCK_UNLOCK_CODE; /* Enable committing changes */ GPIO_CR(gpioport) |= gpios; /* Lock the GPIO_CR register */ GPIO_LOCK(gpioport) = ~GPIO_LOCK_UNLOCK_CODE; }
/*! \brief lock GPIO pin \param[in] gpioport \arg GPIOx(x = A,B,C,D,F) \param[in] gpiopin \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ void gpio_pin_lock(uint32_t port, uint16_t pin) { uint32_t lock = 0x00010000; lock |= pin; /* lock key writing sequence: write 1->write 0->write 1-> read 0-> read 1 */ GPIO_LOCK(port) = lock; GPIO_LOCK(port) = pin; GPIO_LOCK(port) = lock; lock = GPIO_LOCK(port); lock = GPIO_LOCK(port); }
/*! \brief lock GPIO pin bit \param[in] gpio_periph: GPIOx(x = A,B) only one parameter can be selected which is shown as below: \arg GPIOx(x = A,B) \param[in] pin: GPIO pin one or more parameters can be selected which are shown as below: \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) { uint32_t lock = 0x00010000U; lock |= pin; /* lock key writing sequence: write 1->write 0->write 1->read 0->read 1 */ GPIO_LOCK(gpio_periph) = (uint32_t)lock; GPIO_LOCK(gpio_periph) = (uint32_t)pin; GPIO_LOCK(gpio_periph) = (uint32_t)lock; lock = GPIO_LOCK(gpio_periph); lock = GPIO_LOCK(gpio_periph); }
static void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask) { GPIO_LOCK(sc); GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask); GPIO_UNLOCK(sc); }
static void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin, unsigned int flags) { uint32_t mask; mask = 1 << pin->gp_pin; GPIO_LOCK(sc); /* * Manage input/output */ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); if (flags & GPIO_PIN_OUTPUT) { pin->gp_flags |= GPIO_PIN_OUTPUT; GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask); } else { pin->gp_flags |= GPIO_PIN_INPUT; GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask); } } GPIO_UNLOCK(sc); }
static int cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) { struct cambria_gpio_softc *sc = device_get_softc(dev); int error; uint8_t mask; mask = 1 << pin; if (pin >= GPIO_PINS) return (EINVAL); GPIO_LOCK(sc); if (value) sc->sc_val |= mask; else sc->sc_val &= ~mask; if (sc->sc_pins[pin].gp_flags != GPIO_PIN_OUTPUT) { /* just save, altering the latch will disable input */ GPIO_UNLOCK(sc); return (0); } if (value) sc->sc_latch |= mask; else sc->sc_latch &= ~mask; error = cambria_gpio_write(sc); GPIO_UNLOCK(sc); return (error); }
static int octeon_gpio_pin_toggle(device_t dev, uint32_t pin) { int i; uint64_t state; struct octeon_gpio_softc *sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); /* * XXX: Need to check if read returns actual state of output * pins or we need to keep this information by ourself */ state = cvmx_gpio_read(); if (state & (1 << pin)) cvmx_gpio_clear(1 << pin); else cvmx_gpio_set(1 << pin); GPIO_UNLOCK(sc); return (0); }
static void octeon_gpio_pin_configure(struct octeon_gpio_softc *sc, struct gpio_pin *pin, unsigned int flags) { uint32_t mask; cvmx_gpio_bit_cfgx_t gpio_cfgx; mask = 1 << pin->gp_pin; GPIO_LOCK(sc); /* * Manage input/output */ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { gpio_cfgx.u64 = cvmx_read_csr(CVMX_GPIO_BIT_CFGX(pin->gp_pin)); pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); if (flags & GPIO_PIN_OUTPUT) { pin->gp_flags |= GPIO_PIN_OUTPUT; gpio_cfgx.s.tx_oe = 1; } else { pin->gp_flags |= GPIO_PIN_INPUT; gpio_cfgx.s.tx_oe = 0; } if (flags & GPIO_PIN_INVIN) gpio_cfgx.s.rx_xor = 1; else gpio_cfgx.s.rx_xor = 0; cvmx_write_csr(CVMX_GPIO_BIT_CFGX(pin->gp_pin), gpio_cfgx.u64); } GPIO_UNLOCK(sc); }
static int pad_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct gpio_bank bank; struct pad_softc *sc; int pin_shift; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); if (get_bank(sc, pin, &bank, &pin_shift) != 0) return (EINVAL); GPIO_LOCK(sc); if (READ4(sc, bank.port, bank.con + 0x4) & (1 << pin_shift)) *val = 1; else *val = 0; GPIO_UNLOCK(sc); return (0); }
static int pad_pin_set(device_t dev, uint32_t pin, unsigned int value) { struct pad_softc *sc; struct gpio_bank bank; int pin_shift; int reg; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); if (get_bank(sc, pin, &bank, &pin_shift) != 0) return (EINVAL); GPIO_LOCK(sc); reg = READ4(sc, bank.port, bank.con + 0x4); reg &= ~(PIN_OUT << pin_shift); if (value) reg |= (PIN_OUT << pin_shift); WRITE4(sc, bank.port, bank.con + 0x4, reg); GPIO_UNLOCK(sc); return (0); }
/* * GPIO setup: * Enable the pins driving the RGB LED as outputs. */ static void gpio_setup(void) { /* * Configure GPIOF * This port is used to control the RGB LED */ periph_clock_enable(RCC_GPIOF); const u32 outpins = (LED_R | LED_G | LED_B); GPIO_DIR(RGB_PORT) |= outpins; /* Configure outputs. */ GPIO_DEN(RGB_PORT) |= outpins; /* Enable digital function on outputs. */ /* * Now take care of our buttons */ const u32 btnpins = USR_SW1 | USR_SW2; /* * PF0 is locked by default. We need to unlock the GPIO_CR register, * then enable PF0 commit. After we do this, we can setup PF0. If we * don't do this, any configuration done to PF0 is lost, and we will not * have a PF0 interrupt. */ GPIO_LOCK(GPIOF) = 0x4C4F434B; GPIO_CR(GPIOF) |= USR_SW2; /* Configure pins as inputs. */ GPIO_DIR(GPIOF) &= ~btnpins; /* Enable digital function on the pins. */ GPIO_DEN(GPIOF) |= btnpins; /* Pull-up the pins. We don't have an external pull-up */ GPIO_PUR(GPIOF) |= btnpins; }
static void ar71xx_gpio_intr(void *arg) { struct ar71xx_gpio_softc *sc = arg; GPIO_LOCK(sc); /* TODO: something useful */ GPIO_UNLOCK(sc); }
static int tegra_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) { struct tegra_gpio_softc *sc; sc = device_get_softc(dev); if (pin >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); gpio_write_masked(sc, GPIO_MSK_OUT, &sc->gpio_pins[pin], value); GPIO_UNLOCK(sc); return (0); }
static int tegra_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct tegra_gpio_softc *sc; sc = device_get_softc(dev); if (pin >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); *val = gpio_read(sc, GPIO_IN, &sc->gpio_pins[pin]); GPIO_UNLOCK(sc); return (0); }
static int tegra_gpio_pin_getname(device_t dev, uint32_t pin, char *name) { struct tegra_gpio_softc *sc; sc = device_get_softc(dev); if (pin >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); memcpy(name, sc->gpio_pins[pin].gp_name, GPIOMAXNAME); GPIO_UNLOCK(sc); return (0); }
static int tegra_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) { struct tegra_gpio_softc *sc; sc = device_get_softc(dev); if (pin >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); *caps = sc->gpio_pins[pin].gp_caps; GPIO_UNLOCK(sc); return (0); }
static inline void intr_write_modify(struct tegra_gpio_softc *sc, bus_addr_t reg, struct tegra_gpio_irqsrc *tgi, uint32_t val, uint32_t mask) { uint32_t tmp; int bit; bit = GPIO_BIT(tgi->irq); GPIO_LOCK(sc); tmp = bus_read_4(sc->mem_res, reg + GPIO_REGNUM(tgi->irq)); tmp &= ~(mask << bit); tmp |= val << bit; bus_write_4(sc->mem_res, reg + GPIO_REGNUM(tgi->irq), tmp); GPIO_UNLOCK(sc); }
static int tegra_gpio_pin_toggle(device_t dev, uint32_t pin) { struct tegra_gpio_softc *sc; sc = device_get_softc(dev); if (pin >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); gpio_write_masked(sc, GPIO_MSK_OE, &sc->gpio_pins[pin], gpio_read(sc, GPIO_IN, &sc->gpio_pins[pin]) ^ 1); GPIO_UNLOCK(sc); return (0); }
static int cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct cambria_gpio_softc *sc = device_get_softc(dev); int error = 0; if (pin >= GPIO_PINS) return (EINVAL); GPIO_LOCK(sc); if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT) *val = (sc->sc_latch & (1 << pin)) ? 1 : 0; else error = cambria_gpio_read(sc, pin, val); GPIO_UNLOCK(sc); return (error); }
static int cambria_gpio_pin_toggle(device_t dev, uint32_t pin) { struct cambria_gpio_softc *sc = device_get_softc(dev); int error = 0; if (pin >= GPIO_PINS) return (EINVAL); GPIO_LOCK(sc); sc->sc_val ^= (1 << pin); if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT) { sc->sc_latch ^= (1 << pin); error = cambria_gpio_write(sc); } GPIO_UNLOCK(sc); return (error); }
static int octeon_gpio_pin_getname(device_t dev, uint32_t pin, char *name) { struct octeon_gpio_softc *sc = device_get_softc(dev); int i; for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); GPIO_UNLOCK(sc); return (0); }
static int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) { struct ar71xx_gpio_softc *sc = device_get_softc(dev); int i; for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); *caps = sc->gpio_pins[i].gp_caps; GPIO_UNLOCK(sc); return (0); }
static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct ar71xx_gpio_softc *sc = device_get_softc(dev); int i; for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); *val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0; GPIO_UNLOCK(sc); return (0); }
static int octeon_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) { struct octeon_gpio_softc *sc = device_get_softc(dev); int i; for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); *flags = sc->gpio_pins[i].gp_flags; GPIO_UNLOCK(sc); return (0); }
static void pad_pin_configure(struct pad_softc *sc, struct gpio_pin *pin, unsigned int flags) { struct gpio_bank bank; int pin_shift; int reg; GPIO_LOCK(sc); /* * Manage input/output */ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); if (get_bank(sc, pin->gp_pin, &bank, &pin_shift) != 0) return; pin_shift *= 4; #if 0 printf("bank is 0x%08x pin_shift %d\n", bank.con, pin_shift); #endif if (flags & GPIO_PIN_OUTPUT) { pin->gp_flags |= GPIO_PIN_OUTPUT; reg = READ4(sc, bank.port, bank.con); reg &= ~(0xf << pin_shift); reg |= (PIN_OUT << pin_shift); WRITE4(sc, bank.port, bank.con, reg); } else { pin->gp_flags |= GPIO_PIN_INPUT; reg = READ4(sc, bank.port, bank.con); reg &= ~(0xf << pin_shift); WRITE4(sc, bank.port, bank.con, reg); } } GPIO_UNLOCK(sc); }
static int vf_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct vf_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); *val = (READ4(sc, GPIO_PDIR(i)) & (1 << (i % 32))) ? 1 : 0; GPIO_UNLOCK(sc); return (0); }
static int vf_gpio_pin_toggle(device_t dev, uint32_t pin) { struct vf_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); WRITE4(sc, GPIO_PTOR(i), (1 << (i % 32))); GPIO_UNLOCK(sc); return (0); }
static int tegra_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) { struct tegra_gpio_softc *sc; int cnf; sc = device_get_softc(dev); if (pin >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); cnf = gpio_read(sc, GPIO_CNF, &sc->gpio_pins[pin]); if (cnf == 0) { GPIO_UNLOCK(sc); return (ENXIO); } *flags = sc->gpio_pins[pin].gp_flags; GPIO_UNLOCK(sc); return (0); }
static int cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) { struct cambria_gpio_softc *sc = device_get_softc(dev); int error; uint8_t mask; mask = 1 << pin; if (pin >= GPIO_PINS) return (EINVAL); /* Filter out unwanted flags */ if ((flags &= sc->sc_pins[pin].gp_caps) != flags) return (EINVAL); /* Can't mix input/output together */ if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) return (EINVAL); GPIO_LOCK(sc); sc->sc_pins[pin].gp_flags = flags; /* * Writing a logical one sets the signal high and writing a logical * zero sets the signal low. To configure a digital I/O signal as an * input, a logical one must first be written to the data bit to * three-state the associated output. */ if (flags & GPIO_PIN_INPUT || sc->sc_val & mask) sc->sc_latch |= mask; /* input or output & high */ else sc->sc_latch &= ~mask; error = cambria_gpio_write(sc); GPIO_UNLOCK(sc); return (error); }
static int octeon_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct octeon_gpio_softc *sc = device_get_softc(dev); int i; uint64_t state; for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); GPIO_LOCK(sc); state = cvmx_gpio_read(); *val = (state & (1 << pin)) ? 1 : 0; GPIO_UNLOCK(sc); return (0); }