blob: 2508b5ed05ac51e0ca9ecf854b5b546007b66eba [file] [log] [blame]
/*
* Copyright (c) 2016 Piotr Mienkowski
* Copyright (c) 2018 Google LLC.
* Copyright (c) 2021 Gerson Fernando Budke
* SPDX-License-Identifier: Apache-2.0
*/
/** @file
* @brief Atmel SAM0 MCU family I/O Pin Controller (PORT)
*/
#include <stdbool.h>
#include "soc_port.h"
int soc_port_pinmux_set(PortGroup *pg, uint32_t pin, uint32_t func)
{
bool is_odd = pin & 1;
int idx = pin / 2U;
/* Each pinmux register holds the config for two pins. The
* even numbered pin goes in the bits 0..3 and the odd
* numbered pin in bits 4..7.
*/
if (is_odd) {
pg->PMUX[idx].bit.PMUXO = func;
} else {
pg->PMUX[idx].bit.PMUXE = func;
}
pg->PINCFG[pin].bit.PMUXEN = 1;
return 0;
}
void soc_port_configure(const struct soc_port_pin *pin)
{
PortGroup *pg = pin->regs;
uint32_t flags = pin->flags;
uint32_t func = (pin->flags & SOC_PORT_FUNC_MASK) >> SOC_PORT_FUNC_POS;
PORT_PINCFG_Type pincfg = { .reg = 0 };
/* Reset or analog I/O: all digital disabled */
pg->PINCFG[pin->pinum] = pincfg;
pg->DIRCLR.reg = (1 << pin->pinum);
pg->OUTCLR.reg = (1 << pin->pinum);
if (flags & SOC_PORT_PMUXEN_ENABLE) {
soc_port_pinmux_set(pg, pin->pinum, func);
return;
}
if (flags & (SOC_PORT_PULLUP | SOC_PORT_PULLDOWN)) {
if (flags & SOC_PORT_PULLUP) {
pg->OUTSET.reg = (1 << pin->pinum);
}
pincfg.bit.PULLEN = 1;
}
if (flags & SOC_PORT_INPUT_ENABLE) {
pincfg.bit.INEN = 1;
}
if (flags & SOC_PORT_OUTPUT_ENABLE) {
pg->DIRSET.reg = (1 << pin->pinum);
}
if (flags & SOC_PORT_STRENGTH_STRONGER) {
pincfg.bit.DRVSTR = 1;
}
pg->PINCFG[pin->pinum] = pincfg;
}
void soc_port_list_configure(const struct soc_port_pin pins[],
unsigned int size)
{
for (int i = 0; i < size; i++) {
soc_port_configure(&pins[i]);
}
}