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)16 int 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)35 void 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)75 void 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