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) 2020 Linaro Limited
* Copyright (c) 2021 Gerson Fernando Budke
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#ifndef PINCTRL_ATMEL_SAM_H_ #ifndef PINCTRL_ATMEL_SAM_H_
#define PINCTRL_ATMEL_SAM_H_ #define PINCTRL_ATMEL_SAM_H_
#include <dt-bindings/dt-util.h>
#define PERIPH_a 0 #define PERIPH_a 0
#define PERIPH_b 1 #define PERIPH_b 1
#define PERIPH_c 2 #define PERIPH_c 2
@ -14,6 +17,12 @@
#define PERIPH_f 5 #define PERIPH_f 5
#define PERIPH_g 6 #define PERIPH_g 6
#define PERIPH_h 7 #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: /* Create a pincfg device tree node:
* *
@ -22,7 +31,10 @@
* NODE = p<port><pin><periph>_<inst>_<signal> * NODE = p<port><pin><periph>_<inst>_<signal>
* *
* NODE: NODE { * NODE: NODE {
* atmel,pins = < &pio<port> <pin> PERIPH_<perip> >; * atmel,pins = < &pio<port> <pin> PERIPH_<perip> >;
* flags_1;
* ...
* flags_N;
* } * }
* *
* So for example: * So for example:
@ -35,15 +47,42 @@
* atmel,pins = <&pioa 8 PERIPH_a>; * 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) \ #define DT_ATMEL_PINCTRL_FLAG(flag) flag;
p##port##pin##periph##_##inst##_##signal: \ #define DT_ATMEL_PINCTRL_FLAGS(...) \
p##port##pin##periph##_##inst##_##signal { \ MACRO_MAP_CAT(DT_ATMEL_PINCTRL_FLAG __VA_OPT__(,) __VA_ARGS__)
atmel,pins = < &pio##port pin PERIPH_##periph >; }
#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: \
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_ */ #endif /* PINCTRL_ATMEL_SAM_H_ */

View file

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

View file

@ -241,36 +241,47 @@
clock-names = "GCLK", "MCLK"; clock-names = "GCLK", "MCLK";
}; };
porta: gpio@41008000 { pinctrl@41008000 {
compatible = "atmel,sam0-gpio"; compatible = "atmel,sam0-pinctrl";
reg = <0x41008000 0x80>; #address-cells = <1>;
label = "PORTA"; #size-cells = <1>;
gpio-controller; ranges = <0x41008000 0x41008000 0x200>;
#gpio-cells = <2>;
};
portb: gpio@41008080 { porta: gpio@41008000 {
compatible = "atmel,sam0-gpio"; compatible = "atmel,sam0-gpio";
reg = <0x41008080 0x80>; reg = <0x41008000 0x80>;
label = "PORTB"; label = "PORTA";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; #atmel,pin-cells = <2>;
};
portc: gpio@41008100 { portb: gpio@41008080 {
compatible = "atmel,sam0-gpio"; compatible = "atmel,sam0-gpio";
reg = <0x41008100 0x80>; reg = <0x41008080 0x80>;
label = "PORTC"; label = "PORTB";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; #atmel,pin-cells = <2>;
};
portd: gpio@41008180 { portc: gpio@41008100 {
compatible = "atmel,sam0-gpio"; compatible = "atmel,sam0-gpio";
reg = <0x41008180 0x80>; reg = <0x41008100 0x80>;
label = "PORTD"; label = "PORTC";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
portd: gpio@41008180 {
compatible = "atmel,sam0-gpio";
reg = <0x41008180 0x80>;
label = "PORTD";
gpio-controller;
#gpio-cells = <2>;
#atmel,pin-cells = <2>;
};
}; };
usb0: usb@41000000 { usb0: usb@41000000 {

View file

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

View file

@ -14,6 +14,16 @@ properties:
"#gpio-cells": "#gpio-cells":
const: 2 const: 2
"#atmel,pin-cells":
type: int
required: true
const: 2
description: Number of items to expect in a atmel,pins specifier
gpio-cells: gpio-cells:
- pin - pin
- flags - 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) 2020 Linaro Ltd.
* Copyright (c) 2021 Gerson Fernando Budke
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -47,4 +48,61 @@
#define ATMEL_SAM0_DT_CPU_CLK_FREQ_HZ \ #define ATMEL_SAM0_DT_CPU_CLK_FREQ_HZ \
DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) 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_ */ #endif /* _ATMEL_SAM0_SOC_DT_H_ */