diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2018-12-26 15:41:37 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2019-01-07 19:33:26 -0500 |
commit | 70bbdf93347c814ae39b1cd04d04fd66706a8b7e (patch) | |
tree | 4b5139f17c15256c8be843e50602590575a0cde7 /src/sam3/gpio.c | |
parent | e70b70fb75bb9b6017df3f5ff2d900b897ad3a8c (diff) | |
download | kutter-70bbdf93347c814ae39b1cd04d04fd66706a8b7e.tar.gz kutter-70bbdf93347c814ae39b1cd04d04fd66706a8b7e.tar.xz kutter-70bbdf93347c814ae39b1cd04d04fd66706a8b7e.zip |
sam3: Rename src/sam3x8e to src/sam3
This is in preparation for merging sam3 and sam4 code into one
directory.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/sam3/gpio.c')
-rw-r--r-- | src/sam3/gpio.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/sam3/gpio.c b/src/sam3/gpio.c new file mode 100644 index 00000000..f48c5f0d --- /dev/null +++ b/src/sam3/gpio.c @@ -0,0 +1,133 @@ +// GPIO functions on sam3x8e +// +// Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net> +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "board/irq.h" // irq_save +#include "command.h" // shutdown +#include "compiler.h" // ARRAY_SIZE +#include "gpio.h" // gpio_out_setup +#include "internal.h" // gpio_peripheral +#include "sam3x8e.h" // Pio +#include "sched.h" // sched_shutdown + +static Pio * const digital_regs[] = { + PIOA, PIOB, PIOC, PIOD +}; + + +/**************************************************************** + * Pin multiplexing + ****************************************************************/ + +void +gpio_peripheral(uint32_t gpio, char ptype, int32_t pull_up) +{ + uint32_t bank = GPIO2PORT(gpio), bit = GPIO2BIT(gpio); + Pio *regs = digital_regs[bank]; + if (ptype == 'A') + regs->PIO_ABSR &= ~bit; + else + regs->PIO_ABSR |= bit; + if (pull_up > 0) + regs->PIO_PUER = bit; + else + regs->PIO_PUDR = bit; + regs->PIO_PDR = bit; +} + + +/**************************************************************** + * 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; + Pio *regs = digital_regs[GPIO2PORT(pin)]; + struct gpio_out g = { .regs=regs, .bit=GPIO2BIT(pin) }; + gpio_out_reset(g, val); + return g; +fail: + shutdown("Not an output pin"); +} + +void +gpio_out_reset(struct gpio_out g, uint8_t val) +{ + Pio *regs = g.regs; + irqstatus_t flag = irq_save(); + if (val) + regs->PIO_SODR = g.bit; + else + regs->PIO_CODR = g.bit; + regs->PIO_OER = g.bit; + regs->PIO_OWER = g.bit; + regs->PIO_PER = g.bit; + regs->PIO_PUDR = g.bit; + irq_restore(flag); +} + +void +gpio_out_toggle_noirq(struct gpio_out g) +{ + Pio *regs = g.regs; + regs->PIO_ODSR ^= g.bit; +} + +void +gpio_out_toggle(struct gpio_out g) +{ + irqstatus_t flag = irq_save(); + gpio_out_toggle_noirq(g); + irq_restore(flag); +} + +void +gpio_out_write(struct gpio_out g, uint8_t val) +{ + Pio *regs = g.regs; + if (val) + regs->PIO_SODR = g.bit; + else + regs->PIO_CODR = g.bit; +} + + +struct gpio_in +gpio_in_setup(uint8_t pin, int8_t pull_up) +{ + if (GPIO2PORT(pin) >= ARRAY_SIZE(digital_regs)) + goto fail; + uint32_t port = GPIO2PORT(pin); + PMC->PMC_PCER0 = 1 << (ID_PIOA + port); + struct gpio_in g = { .regs=digital_regs[port], .bit=GPIO2BIT(pin) }; + gpio_in_reset(g, pull_up); + return g; +fail: + shutdown("Not an input pin"); +} + +void +gpio_in_reset(struct gpio_in g, int8_t pull_up) +{ + Pio *regs = g.regs; + irqstatus_t flag = irq_save(); + if (pull_up) + regs->PIO_PUER = g.bit; + else + regs->PIO_PUDR = g.bit; + regs->PIO_ODR = g.bit; + regs->PIO_PER = g.bit; + irq_restore(flag); +} + +uint8_t +gpio_in_read(struct gpio_in g) +{ + Pio *regs = g.regs; + return !!(regs->PIO_PDSR & g.bit); +} |