1 /* 2 * Copyright (c) 2016 Piotr Mienkowski 3 * Copyright (c) 2018 Google LLC. 4 * Copyright (c) 2021 Gerson Fernando Budke 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 /** @file 9 * @brief Atmel SAM0 MCU family I/O Pin Controller (PORT) 10 */ 11 12 #include <stdbool.h> 13 14 #include "soc_port.h" 15 soc_port_pinmux_set(PortGroup * pg,uint32_t pin,uint32_t func)16int soc_port_pinmux_set(PortGroup *pg, uint32_t pin, uint32_t func) 17 { 18 bool is_odd = pin & 1; 19 int idx = pin / 2U; 20 21 /* Each pinmux register holds the config for two pins. The 22 * even numbered pin goes in the bits 0..3 and the odd 23 * numbered pin in bits 4..7. 24 */ 25 if (is_odd) { 26 pg->PMUX[idx].bit.PMUXO = func; 27 } else { 28 pg->PMUX[idx].bit.PMUXE = func; 29 } 30 pg->PINCFG[pin].bit.PMUXEN = 1; 31 32 return 0; 33 } 34 soc_port_configure(const struct soc_port_pin * pin)35void soc_port_configure(const struct soc_port_pin *pin) 36 { 37 PortGroup *pg = pin->regs; 38 uint32_t flags = pin->flags; 39 uint32_t func = (pin->flags & SOC_PORT_FUNC_MASK) >> SOC_PORT_FUNC_POS; 40 PORT_PINCFG_Type pincfg = { .reg = 0 }; 41 42 /* Reset or analog I/O: all digital disabled */ 43 pg->PINCFG[pin->pinum] = pincfg; 44 pg->DIRCLR.reg = (1 << pin->pinum); 45 pg->OUTCLR.reg = (1 << pin->pinum); 46 47 if (flags & SOC_PORT_PMUXEN_ENABLE) { 48 soc_port_pinmux_set(pg, pin->pinum, func); 49 return; 50 } 51 52 if (flags & (SOC_PORT_PULLUP | SOC_PORT_PULLDOWN)) { 53 if (flags & SOC_PORT_PULLUP) { 54 pg->OUTSET.reg = (1 << pin->pinum); 55 } 56 57 pincfg.bit.PULLEN = 1; 58 } 59 60 if (flags & SOC_PORT_INPUT_ENABLE) { 61 pincfg.bit.INEN = 1; 62 } 63 64 if (flags & SOC_PORT_OUTPUT_ENABLE) { 65 pg->DIRSET.reg = (1 << pin->pinum); 66 } 67 68 if (flags & SOC_PORT_STRENGTH_STRONGER) { 69 pincfg.bit.DRVSTR = 1; 70 } 71 72 pg->PINCFG[pin->pinum] = pincfg; 73 } 74 soc_port_list_configure(const struct soc_port_pin pins[],unsigned int size)75void soc_port_list_configure(const struct soc_port_pin pins[], 76 unsigned int size) 77 { 78 for (int i = 0; i < size; i++) { 79 soc_port_configure(&pins[i]); 80 } 81 } 82