dts: atmel_sam0: Add pinctrl structure

Add Atmel sam0 MCU series pinctrl devicetree bindings and
infrastructure.

Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
Gerson Fernando Budke 2021-05-18 18:59:59 -03:00 committed by Kumar Gala
commit c9879a58f7
7 changed files with 241 additions and 53 deletions

View file

@ -1,11 +1,14 @@
/*
* Copyright (c) 2020 Linaro Limited
* Copyright (c) 2021 Gerson Fernando Budke
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef PINCTRL_ATMEL_SAM_H_
#define PINCTRL_ATMEL_SAM_H_
#include <dt-bindings/dt-util.h>
#define PERIPH_a 0
#define PERIPH_b 1
#define PERIPH_c 2
@ -14,6 +17,12 @@
#define PERIPH_f 5
#define PERIPH_g 6
#define PERIPH_h 7
#define PERIPH_i 8
#define PERIPH_j 9
#define PERIPH_k 10
#define PERIPH_l 11
#define PERIPH_m 12
#define PERIPH_n 13
/* Create a pincfg device tree node:
*
@ -23,6 +32,9 @@
*
* NODE: NODE {
* atmel,pins = < &pio<port> <pin> PERIPH_<perip> >;
* flags_1;
* ...
* flags_N;
* }
*
* So for example:
@ -35,15 +47,42 @@
* atmel,pins = <&pioa 8 PERIPH_a>;
* }
*
* Flags are optional and should be pass one by one as arguments:
*
* DT_ATMEL_PORT(sercom0, pad0, a, 4, d, pinmux-enable);
*
* Will become:
*
* pa4d_sercom0_pad0: pa4d_sercom0_pad0 {
* atmel,pins = <&porta 0x4 0x3 >;
* pinmux-enable;
* }
*
* For the complete list of flags see atmel,sam[0]-pinctrl.yaml
*/
#define DT_ATMEL_PIN(inst, signal, port, pin, periph) \
p##port##pin##periph##_##inst##_##signal: \
p##port##pin##periph##_##inst##_##signal { \
atmel,pins = < &pio##port pin PERIPH_##periph >; }
#define DT_ATMEL_PINCTRL_FLAG(flag) flag;
#define DT_ATMEL_PINCTRL_FLAGS(...) \
MACRO_MAP_CAT(DT_ATMEL_PINCTRL_FLAG __VA_OPT__(,) __VA_ARGS__)
#define DT_ATMEL_GPIO(inst, signal, port, pin, periph) \
#define DT_ATMEL_PIN(inst, signal, port, pin, periph, ...) \
p##port##pin##periph##_##inst##_##signal: \
p##port##pin##periph##_##inst##_##signal { \
atmel,pins = < &gpio##port pin PERIPH_##periph >; }
atmel,pins = < &pio##port pin PERIPH_##periph >; \
DT_ATMEL_PINCTRL_FLAGS(__VA_ARGS__) \
}
#define DT_ATMEL_GPIO(inst, signal, port, pin, periph, ...) \
p##port##pin##periph##_##inst##_##signal: \
p##port##pin##periph##_##inst##_##signal { \
atmel,pins = < &gpio##port pin PERIPH_##periph >; \
DT_ATMEL_PINCTRL_FLAGS(__VA_ARGS__) \
}
#define DT_ATMEL_PORT(inst, signal, grouport, pin, periph, ...) \
p##grouport##pin##periph##_##inst##_##signal: \
p##grouport##pin##periph##_##inst##_##signal { \
atmel,pins = < &port##grouport pin PERIPH_##periph >; \
DT_ATMEL_PINCTRL_FLAGS(__VA_ARGS__) \
}
#endif /* PINCTRL_ATMEL_SAM_H_ */

View file

@ -161,12 +161,20 @@
label = "TIMER_4";
};
pinctrl@41004400 {
compatible = "atmel,sam0-pinctrl";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x41004400 0x41004400 0x100>;
porta: gpio@41004400 {
compatible = "atmel,sam0-gpio";
reg = <0x41004400 0x80>;
label = "PORTA";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
portb: gpio@41004480 {
@ -175,6 +183,8 @@
label = "PORTB";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
};
rtc: rtc@40001400 {

View file

@ -241,12 +241,19 @@
clock-names = "GCLK", "MCLK";
};
pinctrl@41008000 {
compatible = "atmel,sam0-pinctrl";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x41008000 0x41008000 0x200>;
porta: gpio@41008000 {
compatible = "atmel,sam0-gpio";
reg = <0x41008000 0x80>;
label = "PORTA";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
portb: gpio@41008080 {
@ -255,6 +262,7 @@
label = "PORTB";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
portc: gpio@41008100 {
@ -263,6 +271,7 @@
label = "PORTC";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
portd: gpio@41008180 {
@ -271,6 +280,8 @@
label = "PORTD";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
};
usb0: usb@41000000 {

View file

@ -29,12 +29,17 @@
#dma-cells = <2>;
};
pinctrl@41004400 {
ranges = <0x41004400 0x41004400 0x180>;
portc: gpio@41004500 {
compatible = "atmel,sam0-gpio";
reg = <0x41004500 0x80>;
label = "PORTC";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
};
pinmux_c: pinmux@41004500 {

View file

@ -14,6 +14,16 @@ properties:
"#gpio-cells":
const: 2
"#atmel,pin-cells":
type: int
required: true
const: 2
description: Number of items to expect in a atmel,pins specifier
gpio-cells:
- pin
- flags
atmel,pin-cells:
- pin
- peripheral

View file

@ -0,0 +1,55 @@
# Copyright (c) 2020, Linaro Limited
# Copyright (c) 2021, Gerson Fernando Budke
# SPDX-License-Identifier: Apache-2.0
description: |
Atmel SAM0 Pinctrl container node
The Atmel SAM0 pins implements following pin configuration option:
* bias-pull-up
* bias-pull-down
* drive-strength
* input-enable
* output-enable
* pinmux-enable
These options define devicetree flags that are converted to SoC flags at
ATMEL_SAM0_PIN_FLAGS().
compatible: "atmel,sam0-pinctrl"
include:
- name: base.yaml
- name: pincfg-node.yaml
child-binding:
property-allowlist:
- bias-pull-up
- bias-pull-down
- drive-strength
- input-enable
- output-enable
properties:
reg:
required: true
properties:
"#address-cells":
required: true
const: 1
"#size-cells":
required: true
const: 1
child-binding:
description: Atmel pins
properties:
"atmel,pins":
type: phandle-array
pinmux-enable:
required: false
type: boolean
description: |
Assign pin to an embedded device peripheral

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020 Linaro Ltd.
* Copyright (c) 2021 Gerson Fernando Budke
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -47,4 +48,61 @@
#define ATMEL_SAM0_DT_CPU_CLK_FREQ_HZ \
DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency)
/* Devicetree related macros to construct pin mux config data */
/* Get a node id from a pinctrl-0 prop at index 'i' */
#define NODE_ID_FROM_PINCTRL_0(node_id, i) \
DT_PHANDLE_BY_IDX(node_id, pinctrl_0, i)
/* Get PIN associated with pinctrl-0 pin at index 'i' */
#define ATMEL_SAM0_PIN(node_id, i) \
DT_PHA(NODE_ID_FROM_PINCTRL_0(node_id, i), atmel_pins, pin)
/* Get PIO register address associated with pinctrl-0 pin at index 'i' */
#define ATMEL_SAM0_PIN_TO_PORT_REG_ADDR(node_id, i) \
DT_REG_ADDR(DT_PHANDLE(NODE_ID_FROM_PINCTRL_0(node_id, i), atmel_pins))
/* Get peripheral cfg associated wiith pinctrl-0 pin at index 'i' */
#define ATMEL_SAM0_PIN_PERIPH(node_id, i) \
DT_PHA(NODE_ID_FROM_PINCTRL_0(node_id, i), atmel_pins, peripheral)
/* Helper function for ATMEL_SAM_PIN_FLAGS */
#define ATMEL_SAM0_PIN_FLAG(node_id, i, flag) \
DT_PROP(NODE_ID_FROM_PINCTRL_0(node_id, i), flag)
/* Convert DT flags to SoC flags */
#define ATMEL_SAM0_PIN_FLAGS(node_id, i) \
(ATMEL_SAM0_PIN_FLAG(node_id, i, bias_pull_up) << SOC_PORT_PULLUP_POS | \
ATMEL_SAM0_PIN_FLAG(node_id, i, bias_pull_down) << SOC_PORT_PULLUP_POS | \
ATMEL_SAM0_PIN_FLAG(node_id, i, input_enable) << SOC_PORT_INPUT_ENABLE_POS | \
ATMEL_SAM0_PIN_FLAG(node_id, i, output_enable) << SOC_PORT_OUTPUT_ENABLE_POS | \
ATMEL_SAM0_PIN_FLAG(node_id, i, pinmux_enable) << SOC_PORT_PMUXEN_ENABLE_POS)
/* Construct a soc_port_pin element for pin cfg */
#define ATMEL_SAM0_DT_PORT(node_id, idx) \
{ \
(PortGroup *)ATMEL_SAM0_PIN_TO_PORT_REG_ADDR(node_id, idx), \
ATMEL_SAM0_PIN(node_id, idx), \
ATMEL_SAM0_PIN_PERIPH(node_id, idx) << SOC_PORT_FUNC_POS | \
ATMEL_SAM0_PIN_FLAGS(node_id, idx) \
}
/* Get the number of pins for pinctrl-0 */
#define ATMEL_SAM0_DT_NUM_PINS(node_id) DT_PROP_LEN(node_id, pinctrl_0)
#define ATMEL_SAM0_DT_INST_NUM_PINS(inst) \
ATMEL_SAM0_DT_NUM_PINS(DT_DRV_INST(inst))
/* internal macro to structure things for use with UTIL_LISTIFY */
#define ATMEL_SAM0_DT_PIN_ELEM(idx, node_id) ATMEL_SAM0_DT_PORT(node_id, idx),
/* Construct an array intializer for soc_port_pin for a device instance */
#define ATMEL_SAM0_DT_PINS(node_id) \
{ UTIL_LISTIFY(ATMEL_SAM0_DT_NUM_PINS(node_id), \
ATMEL_SAM0_DT_PIN_ELEM, node_id) \
}
#define ATMEL_SAM0_DT_INST_PINS(inst) \
ATMEL_SAM0_DT_PINS(DT_DRV_INST(inst))
#endif /* _ATMEL_SAM0_SOC_DT_H_ */