diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2017-05-06 21:47:04 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-05-15 15:15:52 -0400 |
commit | 2255176228effc67e868ca343f7354da2b7f4081 (patch) | |
tree | f9f91e9c08c20d731f88d1ca509f2bbeed157e11 /src/pru/gpio.c | |
parent | ccaa25eaa5d10291bff332f88194befe643b729f (diff) | |
download | kutter-2255176228effc67e868ca343f7354da2b7f4081.tar.gz kutter-2255176228effc67e868ca343f7354da2b7f4081.tar.xz kutter-2255176228effc67e868ca343f7354da2b7f4081.zip |
pru: Initial support for the Beaglebone PRU
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/pru/gpio.c')
-rw-r--r-- | src/pru/gpio.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/pru/gpio.c b/src/pru/gpio.c new file mode 100644 index 00000000..7fdbb0d6 --- /dev/null +++ b/src/pru/gpio.c @@ -0,0 +1,142 @@ +// GPIO functions on PRU +// +// Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net> +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "command.h" // shutdown +#include "compiler.h" // ARRAY_SIZE +#include "gpio.h" // gpio_out_setup +#include "sched.h" // sched_shutdown + + +/**************************************************************** + * Pin mappings + ****************************************************************/ + +#define GPIO(PORT, NUM) ((PORT) * 32 + (NUM)) +#define GPIO2PORT(PIN) ((PIN) / 32) +#define GPIO2BIT(PIN) (1<<((PIN) % 32)) + +struct gpio_regs { + uint32_t pad_0[77]; + volatile uint32_t oe; + volatile uint32_t datain; + volatile uint32_t dataout; + uint32_t pad_140[20]; + volatile uint32_t cleardataout; + volatile uint32_t setdataout; +}; + +static struct gpio_regs *digital_regs[] = { + (void*)0x44e07000, (void*)0x4804c000, (void*)0x481ac000, (void*)0x481ae000 +}; + +#define MUXPORT(offset) (((offset)-0x800) / 4) + +static uint8_t gpio_mux_offset[32 * ARRAY_SIZE(digital_regs)] = { + // gpio 0 + 0xff , 0xff , MUXPORT(0x950), MUXPORT(0x954), + MUXPORT(0x958), MUXPORT(0x95c), 0xff , MUXPORT(0x964), + MUXPORT(0x8d0), MUXPORT(0x8d4), MUXPORT(0x8d8), MUXPORT(0x8dc), + MUXPORT(0x978), MUXPORT(0x97c), MUXPORT(0x980), MUXPORT(0x984), + 0xff , 0xff , 0xff , 0xff , + MUXPORT(0x9b4), 0xff , MUXPORT(0x820), MUXPORT(0x824), + 0xff , 0xff , MUXPORT(0x828), MUXPORT(0x82c), + 0xff , 0xff , MUXPORT(0x870), MUXPORT(0x874), + + // gpio 1 + MUXPORT(0x800), MUXPORT(0x804), MUXPORT(0x808), MUXPORT(0x80c), + MUXPORT(0x810), MUXPORT(0x814), MUXPORT(0x818), MUXPORT(0x81c), + 0xff , 0xff , 0xff , 0xff , + MUXPORT(0x830), MUXPORT(0x834), MUXPORT(0x838), MUXPORT(0x83c), + MUXPORT(0x840), MUXPORT(0x844), MUXPORT(0x848), MUXPORT(0x84c), + 0xff , 0xff , 0xff , 0xff , + 0xff , 0xff , 0xff , 0xff , + MUXPORT(0x878), MUXPORT(0x87c), MUXPORT(0x880), MUXPORT(0x884), + + // gpio 2 + 0xff , MUXPORT(0x88c), MUXPORT(0x890), MUXPORT(0x894), + MUXPORT(0x898), MUXPORT(0x89c), MUXPORT(0x8a0), MUXPORT(0x8a4), + MUXPORT(0x8a8), MUXPORT(0x8ac), MUXPORT(0x8b0), MUXPORT(0x8b4), + MUXPORT(0x8b8), MUXPORT(0x8bc), MUXPORT(0x8c0), MUXPORT(0x8c4), + MUXPORT(0x8c8), MUXPORT(0x8cc), 0xff , 0xff , + 0xff , 0xff , MUXPORT(0x8e0), MUXPORT(0x8e4), + MUXPORT(0x8e8), MUXPORT(0x8ec), 0xff , 0xff , + 0xff , 0xff , 0xff , 0xff , + + // gpio 3 + 0xff , 0xff , 0xff , 0xff , + 0xff , 0xff , 0xff , 0xff , + 0xff , 0xff , 0xff , 0xff , + 0xff , 0xff , MUXPORT(0x990), MUXPORT(0x994), + MUXPORT(0x998), MUXPORT(0x99c), MUXPORT(0x9a0), MUXPORT(0x9a4), + MUXPORT(0x9a8), MUXPORT(0x9ac), 0xff , 0xff , + 0xff , 0xff , 0xff , 0xff , + 0xff , 0xff , 0xff , 0xff , +}; + +#define MUXREG(mux_offset) ((volatile uint32_t *)0x44e10800 + mux_offset) + + +/**************************************************************** + * General Purpose Input Output (GPIO) pins + ****************************************************************/ + +struct gpio_out +gpio_out_setup(uint8_t pin, uint8_t val) +{ + if (GPIO2PORT(pin) >= ARRAY_SIZE(digital_regs)) + goto fail; + uint8_t mux_offset = gpio_mux_offset[pin]; + if (mux_offset == 0xff) + goto fail; + struct gpio_regs *regs = digital_regs[GPIO2PORT(pin)]; + uint32_t bit = GPIO2BIT(pin); + struct gpio_out rv = (struct gpio_out){ .reg=®s->cleardataout, .bit=bit }; + gpio_out_write(rv, val); + regs->oe &= ~bit; + *MUXREG(mux_offset) = 0x0f; + return rv; +fail: + shutdown("Not an output pin"); +} + +void +gpio_out_toggle(struct gpio_out g) +{ + gpio_out_write(g, !(*g.reg & g.bit)); +} + +void +gpio_out_write(struct gpio_out g, uint8_t val) +{ + volatile uint32_t *reg = g.reg; + if (val) + reg++; + *reg = g.bit; +} + + +struct gpio_in +gpio_in_setup(uint8_t pin, int8_t pull_up) +{ + if (GPIO2PORT(pin) >= ARRAY_SIZE(digital_regs)) + goto fail; + uint8_t mux_offset = gpio_mux_offset[pin]; + if (mux_offset == 0xff) + goto fail; + struct gpio_regs *regs = digital_regs[GPIO2PORT(pin)]; + uint32_t bit = GPIO2BIT(pin); + regs->oe |= bit; + *MUXREG(mux_offset) = pull_up > 0 ? 0x37 : (pull_up < 0 ? 0x27 : 0x2f); + return (struct gpio_in){ .reg=®s->datain, .bit=bit }; +fail: + shutdown("Not an input pin"); +} + +uint8_t +gpio_in_read(struct gpio_in g) +{ + return !!(*g.reg & g.bit); +} |