From e01c0e25059ad8b00715565ed1dc7fca887c8e5a Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Sat, 9 Nov 2024 16:33:58 +0100 Subject: [PATCH 1/6] devicetree: Introduce assigned-clock property Some platforms require special clock selection options. This could be made using the already defined assigned-clocks. This introduces the assigned-clocks and assigned-clock-names properties to generalize those conditions. Signed-off-by: Gerson Fernando Budke --- dts/bindings/base/base.yaml | 8 + include/zephyr/devicetree/clocks.h | 325 +++++++++++++++++++++++++++++ 2 files changed, 333 insertions(+) diff --git a/dts/bindings/base/base.yaml b/dts/bindings/base/base.yaml index 676292a296af2f..478cc2b6194acc 100644 --- a/dts/bindings/base/base.yaml +++ b/dts/bindings/base/base.yaml @@ -60,6 +60,14 @@ properties: type: string-array description: name of each clock + assigned-clocks: + type: phandle-array + description: Assigned-clock information + + assigned-clock-names: + type: string-array + description: Name of each assigned-clock + "#address-cells": type: int description: number of address cells in reg property diff --git a/include/zephyr/devicetree/clocks.h b/include/zephyr/devicetree/clocks.h index 1721de650ec909..64bb7df43521e4 100644 --- a/include/zephyr/devicetree/clocks.h +++ b/include/zephyr/devicetree/clocks.h @@ -347,6 +347,331 @@ extern "C" { #define DT_INST_CLOCKS_CELL(inst, cell) \ DT_INST_CLOCKS_CELL_BY_IDX(inst, 0, cell) +/** + * @brief Test if a node has a assigned-clocks phandle-array property at a given index + * + * This expands to 1 if the given index is valid assigned-clocks property phandle-array index. + * Otherwise, it expands to 0. + * + * Example devicetree fragment: + * + * n1: node-1 { + * assigned-clocks = <...>, <...>; + * }; + * + * n2: node-2 { + * assigned-clocks = <...>; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 0) // 1 + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 1) // 1 + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 2) // 0 + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n2), 1) // 0 + * + * @param node_id node identifier; may or may not have any assigned-clocks property + * @param idx index of a assigned-clocks property phandle-array whose existence to check + * @return 1 if the index exists, 0 otherwise + */ +#define DT_ASSIGNED_CLOCKS_HAS_IDX(node_id, idx) \ + DT_PROP_HAS_IDX(node_id, assigned_clocks, idx) + +/** + * @brief Test if a node has a clock-names array property holds a given name + * + * This expands to 1 if the name is available as assigned-clocks-name array property cell. + * Otherwise, it expands to 0. + * + * Example devicetree fragment: + * + * n1: node-1 { + * assigned-clocks = <...>, <...>; + * clock-names = "alpha", "beta"; + * }; + * + * n2: node-2 { + * assigned-clocks = <...>; + * clock-names = "alpha"; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n1), alpha) // 1 + * DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n1), beta) // 1 + * DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n2), beta) // 0 + * + * @param node_id node identifier; may or may not have any clock-names property. + * @param name lowercase-and-underscores clock-names cell value name to check + * @return 1 if the assigned-clock name exists, 0 otherwise + */ +#define DT_ASSIGNED_CLOCKS_HAS_NAME(node_id, name) \ + DT_PROP_HAS_NAME(node_id, assigned_clocks, name) + +/** + * @brief Get the number of elements in a assigned-clocks property + * + * Example devicetree fragment: + * + * n1: node-1 { + * assigned-clocks = <&foo>, <&bar>; + * }; + * + * n2: node-2 { + * assigned-clocks = <&foo>; + * }; + * + * Example usage: + * + * DT_NUM_ASSIGNED_CLOCKS(DT_NODELABEL(n1)) // 2 + * DT_NUM_ASSIGNED_CLOCKS(DT_NODELABEL(n2)) // 1 + * + * @param node_id node identifier with a assigned-clocks property + * @return number of elements in the property + */ +#define DT_NUM_ASSIGNED_CLOCKS(node_id) \ + DT_PROP_LEN(node_id, assigned-clocks) + + +/** + * @brief Get the node identifier for the controller phandle from a + * "assigned-clocks" phandle-array property at an index + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { ... }; + * + * clk2: clock-controller@... { ... }; + * + * n: node { + * assigned-clocks = <&clk1 10 20>, <&clk2 30 40>; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(n), 0)) // DT_NODELABEL(clk1) + * DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(n), 1)) // DT_NODELABEL(clk2) + * + * @param node_id node identifier + * @param idx logical index into "assigned-clocks" + * @return the node identifier for the clock controller referenced at + * index "idx" + * @see DT_PHANDLE_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, idx) \ + DT_PHANDLE_BY_IDX(node_id, assigned_clocks, idx) + +/** + * @brief Equivalent to DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, 0) + * @param node_id node identifier + * @return a node identifier for the assigned-clocks controller at index 0 + * in "assigned-clocks" + * @see DT_ASSIGNED_CLOCKS_CTLR_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CTLR(node_id) DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, 0) + +/** + * @brief Get the node identifier for the controller phandle from a + * assigned-clocks phandle-array property by name + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { ... }; + * + * clk2: clock-controller@... { ... }; + * + * n: node { + * assigned-clocks = <&clk1 10 20>, <&clk2 30 40>; + * clock-names = "alpha", "beta"; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(DT_NODELABEL(n), beta) // DT_NODELABEL(clk2) + * + * @param node_id node identifier + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @return the node identifier for the clock controller referenced by name + * @see DT_PHANDLE_BY_NAME() + */ +#define DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(node_id, name) \ + DT_PHANDLE_BY_NAME(node_id, assigned_clocks, name) + +/** + * @brief Get a assigned-clock specifier's cell value at an index + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { + * compatible = "vnd,clock"; + * #assigned-clock-cells = < 2 >; + * }; + * + * n: node { + * assigned-clocks = < &clk1 10 20 >, < &clk1 30 40 >; + * }; + * + * Bindings fragment for the vnd,clock compatible: + * + * assigned-clock-cells: + * - bus + * - bits + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_NODELABEL(n), 0, bus) // 10 + * DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_NODELABEL(n), 1, bits) // 40 + * + * @param node_id node identifier for a node with a assigned-clocks property + * @param idx logical index into assigned-clocks property + * @param cell lowercase-and-underscores cell name + * @return the cell value at index "idx" + * @see DT_PHA_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, idx, cell) \ + DT_PHA_BY_IDX(node_id, assigned_clocks, idx, cell) + +/** + * @brief Get a assigned-clock specifier's cell value by name + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { + * compatible = "vnd,clock"; + * #assigned-clock-cells = < 2 >; + * }; + * + * n: node { + * assigned-clocks = < &clk1 10 20 >, < &clk1 30 40 >; + * clock-names = "alpha", "beta"; + * }; + * + * Bindings fragment for the vnd,clock compatible: + * + * assigned-clock-cells: + * - bus + * - bits + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_NODELABEL(n), alpha, bus) // 10 + * DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_NODELABEL(n), beta, bits) // 40 + * + * @param node_id node identifier for a node with a assigned-clocks property + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @param cell lowercase-and-underscores cell name + * @return the cell value in the specifier at the named element + * @see DT_PHA_BY_NAME() + */ +#define DT_ASSIGNED_CLOCKS_CELL_BY_NAME(node_id, name, cell) \ + DT_PHA_BY_NAME(node_id, assigned_clocks, name, cell) + +/** + * @brief Equivalent to DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, 0, cell) + * @param node_id node identifier for a node with a assigned-clocks property + * @param cell lowercase-and-underscores cell name + * @return the cell value at index 0 + * @see DT_ASSIGNED_CLOCKS_CELL_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CELL(node_id, cell) DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, 0, cell) + +/** + * @brief Equivalent to DT_ASSIGNED_CLOCKS_HAS_IDX(DT_DRV_INST(inst), idx) + * @param inst DT_DRV_COMPAT instance number; may or may not have any assigned-clocks property + * @param idx index of a assigned-clocks property phandle-array whose existence to check + * @return 1 if the index exists, 0 otherwise + */ +#define DT_INST_ASSIGNED_CLOCKS_HAS_IDX(inst, idx) \ + DT_ASSIGNED_CLOCKS_HAS_IDX(DT_DRV_INST(inst), idx) + +/** + * @brief Equivalent to DT_CLOCK_HAS_NAME(DT_DRV_INST(inst), name) + * @param inst DT_DRV_COMPAT instance number; may or may not have any clock-names property. + * @param name lowercase-and-underscores clock-names cell value name to check + * @return 1 if the assigned-clock name exists, 0 otherwise + */ +#define DT_INST_ASSIGNED_CLOCKS_HAS_NAME(inst, name) \ + DT_ASSIGNED_CLOCKS_HAS_NAME(DT_DRV_INST(inst), name) + +/** + * @brief Equivalent to DT_NUM_ASSIGNED_CLOCKS(DT_DRV_INST(inst)) + * @param inst instance number + * @return number of elements in the assigned-clocks property + */ +#define DT_INST_NUM_ASSIGNED_CLOCKS(inst) \ + DT_NUM_ASSIGNED_CLOCKS(DT_DRV_INST(inst)) + +/** + * @brief Get the node identifier for the controller phandle from a + * "assigned-clocks" phandle-array property at an index + * + * @param inst instance number + * @param idx logical index into "assigned-clocks" + * @return the node identifier for the clock controller referenced at + * index "idx" + * @see DT_ASSIGNED_CLOCKS_CTLR_BY_IDX() + */ +#define DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, idx) \ + DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_DRV_INST(inst), idx) + +/** + * @brief Equivalent to DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, 0) + * @param inst instance number + * @return a node identifier for the assigned-clocks controller at index 0 + * in "assigned-clocks" + * @see DT_ASSIGNED_CLOCKS_CTLR() + */ +#define DT_INST_ASSIGNED_CLOCKS_CTLR(inst) DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, 0) + +/** + * @brief Get the node identifier for the controller phandle from a + * assigned-clocks phandle-array property by name + * + * @param inst instance number + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @return the node identifier for the clock controller referenced by + * the named element + * @see DT_ASSIGNED_CLOCKS_CTLR_BY_NAME() + */ +#define DT_INST_ASSIGNED_CLOCKS_CTLR_BY_NAME(inst, name) \ + DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(DT_DRV_INST(inst), name) + +/** + * @brief Get a DT_DRV_COMPAT instance's assigned-clock specifier's cell value + * at an index + * @param inst DT_DRV_COMPAT instance number + * @param idx logical index into assigned-clocks property + * @param cell lowercase-and-underscores cell name + * @return the cell value at index "idx" + * @see DT_ASSIGNED_CLOCKS_CELL_BY_IDX() + */ +#define DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, idx, cell) \ + DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_DRV_INST(inst), idx, cell) + +/** + * @brief Get a DT_DRV_COMPAT instance's assigned-clock specifier's cell value by name + * @param inst DT_DRV_COMPAT instance number + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @param cell lowercase-and-underscores cell name + * @return the cell value in the specifier at the named element + * @see DT_ASSIGNED_CLOCKS_CELL_BY_NAME() + */ +#define DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(inst, name, cell) \ + DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_DRV_INST(inst), name, cell) + +/** + * @brief Equivalent to DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, 0, cell) + * @param inst DT_DRV_COMPAT instance number + * @param cell lowercase-and-underscores cell name + * @return the value of the cell inside the specifier at index 0 + */ +#define DT_INST_ASSIGNED_CLOCKS_CELL(inst, cell) \ + DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, 0, cell) + /** * @} */ From 0b2f3271ab8ed7a2781040ee5e06bbb606f0f449 Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Fri, 1 Nov 2024 10:12:43 +0100 Subject: [PATCH 2/6] dts: rtc: sam0: Add clock properties Add properties to differentiate the timer counter operating modes. This properties are necessary to spetialize the driver to be used as a normal 16/32-bit counter or to provide the clock/calendar functions. Signed-off-by: Gerson Fernando Budke --- drivers/timer/Kconfig.sam0_rtc | 4 +- drivers/timer/sam0_rtc_timer.c | 6 +- dts/arm/atmel/samc2x.dtsi | 43 ++++++----- dts/arm/atmel/samd2x.dtsi | 38 +++++---- dts/arm/atmel/samd5x.dtsi | 52 +++++++------ dts/arm/atmel/saml2x.dtsi | 11 ++- dts/bindings/rtc/atmel,sam0-rtc.yaml | 110 ++++++++++++++++++++++++++- 7 files changed, 199 insertions(+), 65 deletions(-) diff --git a/drivers/timer/Kconfig.sam0_rtc b/drivers/timer/Kconfig.sam0_rtc index 14c4ee73939fdb..05e4485ae18c83 100644 --- a/drivers/timer/Kconfig.sam0_rtc +++ b/drivers/timer/Kconfig.sam0_rtc @@ -1,12 +1,14 @@ # Copyright (c) 2014-2015 Wind River Systems, Inc. # Copyright (c) 2016 Cadence Design Systems, Inc. # Copyright (c) 2019 Intel Corp. +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 config SAM0_RTC_TIMER bool "Atmel SAM0 series RTC timer" default y - depends on DT_HAS_ATMEL_SAM0_RTC_ENABLED + depends on DT_HAS_ATMEL_SAM0_RTC_ENABLED \ + && $(dt_nodelabel_bool_prop,rtc,systimer) select PINCTRL select TICKLESS_CAPABLE help diff --git a/drivers/timer/sam0_rtc_timer.c b/drivers/timer/sam0_rtc_timer.c index 8e87b1848bb307..4495bf3ded6906 100644 --- a/drivers/timer/sam0_rtc_timer.c +++ b/drivers/timer/sam0_rtc_timer.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 omSquare s.r.o. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -249,7 +250,6 @@ static int sys_clock_driver_init(void) { int retval; - #ifdef MCLK MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC; OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K; @@ -257,7 +257,7 @@ static int sys_clock_driver_init(void) /* Set up bus clock and GCLK generator. */ PM->APBAMASK.reg |= PM_APBAMASK_RTC; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(RTC_GCLK_ID) | GCLK_CLKCTRL_CLKEN - | GCLK_GEN(DT_INST_PROP(0, clock_generator)); + | GCLK_GEN(DT_INST_PROP(0, gclk)); /* Synchronize GCLK. */ while (GCLK->STATUS.bit.SYNCBUSY) { @@ -265,7 +265,7 @@ static int sys_clock_driver_init(void) #endif retval = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); - if (retval < 0) { + if (retval < 0 && retval != -ENOENT) { return retval; } diff --git a/dts/arm/atmel/samc2x.dtsi b/dts/arm/atmel/samc2x.dtsi index a0e57c5c75f191..aff054ad6272dd 100644 --- a/dts/arm/atmel/samc2x.dtsi +++ b/dts/arm/atmel/samc2x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Kamil Serwus + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +14,21 @@ / { aliases { + port-a = &porta; + port-b = &portb; + port-c = &portc; + + rtc = &rtc; + + sercom-0 = &sercom0; + sercom-1 = &sercom1; + sercom-2 = &sercom2; + sercom-3 = &sercom3; + + tcc-0 = &tcc0; + tcc-1 = &tcc1; + tcc-2 = &tcc2; + watchdog0 = &wdog; }; @@ -43,21 +59,6 @@ <0x0080A048 0x4>; }; - aliases { - port-a = &porta; - port-b = &portb; - port-c = &portc; - - sercom-0 = &sercom0; - sercom-1 = &sercom1; - sercom-2 = &sercom2; - sercom-3 = &sercom3; - - tcc-0 = &tcc0; - tcc-1 = &tcc1; - tcc-2 = &tcc2; - }; - soc { nvmctrl: nvmctrl@41004000 { compatible = "atmel,sam0-nvmctrl"; @@ -225,9 +226,15 @@ rtc: rtc@40002400 { compatible = "atmel,sam0-rtc"; - reg = <0x40002400 0x1C>; - interrupts = <3 0>; - clock-generator = <0>; + gclk = <4>; + reg = <0x40002400 0x24>; + interrupts = <2 0>; + alarms-count = <1>; + cal-constant = <(4096 * 240)>; + clocks = <&mclk 0x14 9 &osc32kctrl>; + clock-names = "MCLK", "OSC32KCTRL"; + assigned-clocks = <&osc32kctrl 0>; + assigned-clock-names = "OSC32KCTRL"; status = "disabled"; }; }; diff --git a/dts/arm/atmel/samd2x.dtsi b/dts/arm/atmel/samd2x.dtsi index c247daffc1a516..7cdf4d98c9a787 100644 --- a/dts/arm/atmel/samd2x.dtsi +++ b/dts/arm/atmel/samd2x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +14,22 @@ / { aliases { + adc-0 = &adc; + + port-a = &porta; + port-b = &portb; + + rtc = &rtc; + + sercom-0 = &sercom0; + sercom-1 = &sercom1; + sercom-2 = &sercom2; + sercom-3 = &sercom3; + sercom-4 = &sercom4; + sercom-5 = &sercom5; + + tc-4 = &tc4; + watchdog0 = &wdog; }; @@ -43,21 +60,6 @@ <0x0080A048 0x4>; }; - aliases { - port-a = &porta; - port-b = &portb; - adc-0 = &adc; - - sercom-0 = &sercom0; - sercom-1 = &sercom1; - sercom-2 = &sercom2; - sercom-3 = &sercom3; - sercom-4 = &sercom4; - sercom-5 = &sercom5; - - tc-4 = &tc4; - }; - soc { nvmctrl: nvmctrl@41004000 { compatible = "atmel,sam0-nvmctrl"; @@ -178,7 +180,11 @@ compatible = "atmel,sam0-rtc"; reg = <0x40001400 0x1C>; interrupts = <3 0>; - clock-generator = <0>; + gclk = <4>; + clocks = <&gclk 4 4>, <&pm 0x18 5>; + clock-names = "GCLK", "PM"; + alarms-count = <1>; + cal-constant = <(1024 * 976)>; status = "disabled"; }; diff --git a/dts/arm/atmel/samd5x.dtsi b/dts/arm/atmel/samd5x.dtsi index b64abc5de4554c..d2b985f13bfeb0 100644 --- a/dts/arm/atmel/samd5x.dtsi +++ b/dts/arm/atmel/samd5x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 ML!PA Consulting GmbH + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,28 +12,6 @@ #include / { - chosen { - zephyr,flash-controller = &nvmctrl; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-m4f"; - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - - mpu: mpu@e000ed90 { - compatible = "arm,armv7m-mpu"; - reg = <0xe000ed90 0x40>; - }; - }; - }; - aliases { adc-0 = &adc0; adc-1 = &adc1; @@ -42,6 +21,8 @@ port-c = &portc; port-d = &portd; + rtc = &rtc; + sercom-0 = &sercom0; sercom-1 = &sercom1; sercom-2 = &sercom2; @@ -66,9 +47,28 @@ }; chosen { + zephyr,flash-controller = &nvmctrl; zephyr,entropy = &trng; }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv7m-mpu"; + reg = <0xe000ed90 0x40>; + }; + }; + }; + soc { sram0: memory@20000000 { compatible = "mmio-sram"; @@ -286,7 +286,13 @@ compatible = "atmel,sam0-rtc"; reg = <0x40002400 0x1C>; interrupts = <11 0>; - clock-generator = <0>; + gclk = <4>; + clocks = <&mclk 0x14 9 &osc32kctrl>; + clock-names = "MCLK", "OSC32KCTRL"; + alarms-count = <2>; + cal-constant = <(8192 * 128)>; + assigned-clocks = <&osc32kctrl 0>; + assigned-clock-names = "OSC32KCTRL"; status = "disabled"; }; diff --git a/dts/arm/atmel/saml2x.dtsi b/dts/arm/atmel/saml2x.dtsi index 2bad616c81af94..e130192055d7dc 100644 --- a/dts/arm/atmel/saml2x.dtsi +++ b/dts/arm/atmel/saml2x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Argentum Systems Ltd. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +14,8 @@ / { aliases { + rtc = &rtc; + watchdog0 = &wdog; }; @@ -169,7 +172,13 @@ compatible = "atmel,sam0-rtc"; reg = <0x40002000 0x1c>; interrupts = <2 0>; - clock-generator = <0>; + gclk = <4>; + alarms-count = <1>; + cal-constant = <(8192 * 128)>; + clocks = <&mclk 0x14 8 &osc32kctrl>; + clock-names = "MCLK", "OSC32KCTRL"; + assigned-clocks = <&osc32kctrl 0>; + assigned-clock-names = "OSC32KCTRL"; status = "disabled"; }; diff --git a/dts/bindings/rtc/atmel,sam0-rtc.yaml b/dts/bindings/rtc/atmel,sam0-rtc.yaml index f2210e8bfb4e06..adead65ff4be3f 100644 --- a/dts/bindings/rtc/atmel,sam0-rtc.yaml +++ b/dts/bindings/rtc/atmel,sam0-rtc.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2018 omSquare s.r.o. +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 RTC @@ -6,14 +7,117 @@ description: Atmel SAM0 RTC compatible: "atmel,sam0-rtc" include: - - name: rtc.yaml + - name: rtc-device.yaml - name: pinctrl-device.yaml properties: reg: required: true - clock-generator: + gclk: type: int - description: clock generator index required: true + description: | + Generic Clock Generator source + + cal-constant: + type: int + required: true + description: | + Define the constant used to calculate the calibration. More + information can be found in the datasheet of each SoC series + at RTC Frequency Correction topic. + + Example: + Correction in ppm = (FREQCORR.VALUE * 1e6 ppm) / (8192 * 128) + + &rtc { + cal-constant = <8192 * 128>; + }; + + systimer: + type: boolean + description: | + Selects RTC peripheral to be used as a system timer and replace + the ARM systick. When this option is selected the normal RTC + functionality is in exclusive mode and the normal RTC functions + will not be available. + + The systimer exclusive functionality can be enabled using the + following devicetree entry: + + &rtc { + status = "okay"; + systimer; + }; + + counter-mode: + type: string + enum: + - "count-32" + - "count-16" + - "clock" + description: | + Configure the RTC counter operating mode. In mode 0, the counter + register is configured as a 32-bit counter. In mode 1, simmilar + to mode 0, the counter register is only 16-bit counter. In mode + 2 the counter register is configured as a clock/calendar. + + &rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + }; + + prescaler: + type: int + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + - 256 + - 512 + - 1024 + description: | + Enable CLKOUT at given frequency. When disabled, CLKOUT pin is LOW. + The default is 0 and corresponds to the disable the CLKOUT signal. + + &rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + }; + + event-control-msk: + type: int + default: 0 + description: | + Enable peripheral event sources by bitmask. By default all the channels + are always disabled. + + Event Table: + + bit Event Source + 0 Periodic Interval 0 Event Output + 1 Periodic Interval 1 Event Output + 2 Periodic Interval 2 Event Output + 3 Periodic Interval 3 Event Output + 4 Periodic Interval 4 Event Output + 5 Periodic Interval 5 Event Output + 6 Periodic Interval 6 Event Output + 7 Periodic Interval 7 Event Output + 8 Compare/Alarm 0 Event Output + 9 Compare/Alarm 0 Event Output + 14 Tamper Event Output + 15 Overflow Event Output + 16 Tamper Event Input + + Example how to enable Compare/Alarm 0 Event Output: + &rtc { + event-control-msk = <100>; + }; From 6c48d1ba6316c4fd687314c4d2c2ae3ae9e2e88f Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Sat, 9 Nov 2024 17:31:43 +0100 Subject: [PATCH 3/6] clocks: atmel: sam0: Fix gclk and mclk clock bindings The Atmel SAM0 SoC enable peripherals clocks in distinct places: PM and MCLK. The old devices had defined the peripheral clock enable bit at PM. On the newer devices this was extracted on a dedicated memory section called Master Clock (MCLK). This change excludes the dedicated bindings in favor of a generic approach that cover all cases. Now the clocks properties is complemented by the assigned-clocks property. It gives the liberty to user to customize the clock source from a generic clock or configure the direct connections. All peripherals drivers were reworked with the newer solution. Signed-off-by: Gerson Fernando Budke --- drivers/adc/adc_sam0.c | 116 ++++++++-------- drivers/can/can_sam0.c | 24 ++-- drivers/counter/counter_sam0_tc32.c | 125 ++++++++---------- drivers/dac/dac_sam0.c | 58 ++++---- drivers/i2c/i2c_sam0.c | 43 +++--- drivers/pwm/pwm_sam0_tcc.c | 72 +++++----- drivers/serial/uart_sam0.c | 53 +++----- drivers/spi/spi_sam0.c | 45 +++---- dts/arm/atmel/samc21.dtsi | 12 +- dts/arm/atmel/samc2x.dtsi | 30 ++++- dts/arm/atmel/samd20.dtsi | 51 ++++++- dts/arm/atmel/samd21.dtsi | 53 +++++++- dts/arm/atmel/samd2x.dtsi | 16 +-- dts/arm/atmel/samd5x.dtsi | 69 ++++++++-- dts/arm/atmel/same5x.dtsi | 4 + dts/arm/atmel/saml21.dtsi | 44 +++++- dts/arm/atmel/saml2x.dtsi | 26 ++-- dts/arm/atmel/samr21.dtsi | 100 +------------- dts/bindings/adc/atmel,sam0-adc.yaml | 7 +- dts/bindings/arm/atmel,samd2x-pm.yaml | 19 --- dts/bindings/clock/atmel,sam0-gclk.yaml | 65 +++++++++ dts/bindings/clock/atmel,sam0-mclk.yaml | 48 +++++++ dts/bindings/clock/atmel,sam0-osc32kctrl.yaml | 37 ++++++ dts/bindings/clock/atmel,samc2x-gclk.yaml | 18 --- dts/bindings/clock/atmel,samc2x-mclk.yaml | 19 --- dts/bindings/clock/atmel,samd2x-gclk.yaml | 18 --- dts/bindings/clock/atmel,samd5x-gclk.yaml | 18 --- dts/bindings/clock/atmel,samd5x-mclk.yaml | 19 --- dts/bindings/clock/atmel,saml2x-gclk.yaml | 18 --- dts/bindings/clock/atmel,saml2x-mclk.yaml | 19 --- dts/bindings/rtc/atmel,sam0-rtc.yaml | 14 +- dts/bindings/serial/atmel,sam0-uart.yaml | 6 + soc/atmel/sam0/common/atmel_sam0_dt.h | 28 +++- 33 files changed, 681 insertions(+), 613 deletions(-) delete mode 100644 dts/bindings/arm/atmel,samd2x-pm.yaml create mode 100644 dts/bindings/clock/atmel,sam0-gclk.yaml create mode 100644 dts/bindings/clock/atmel,sam0-mclk.yaml create mode 100644 dts/bindings/clock/atmel,sam0-osc32kctrl.yaml delete mode 100644 dts/bindings/clock/atmel,samc2x-gclk.yaml delete mode 100644 dts/bindings/clock/atmel,samc2x-mclk.yaml delete mode 100644 dts/bindings/clock/atmel,samd2x-gclk.yaml delete mode 100644 dts/bindings/clock/atmel,samd5x-gclk.yaml delete mode 100644 dts/bindings/clock/atmel,samd5x-mclk.yaml delete mode 100644 dts/bindings/clock/atmel,saml2x-gclk.yaml delete mode 100644 dts/bindings/clock/atmel,saml2x-mclk.yaml diff --git a/drivers/adc/adc_sam0.c b/drivers/adc/adc_sam0.c index b7b1f59aa8ed74..06d73173ea36e8 100644 --- a/drivers/adc/adc_sam0.c +++ b/drivers/adc/adc_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Derek Hageman + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -46,18 +47,12 @@ struct adc_sam0_data { struct adc_sam0_cfg { Adc *regs; const struct pinctrl_dev_config *pcfg; - -#ifdef MCLK + volatile uint32_t *mclk; uint32_t mclk_mask; - uint32_t gclk_mask; + uint32_t gclk_gen; uint16_t gclk_id; -#else - uint32_t gclk; -#endif - uint32_t freq; uint16_t prescaler; - void (*config_func)(const struct device *dev); }; @@ -449,14 +444,17 @@ static int adc_sam0_init(const struct device *dev) Adc *const adc = cfg->regs; int retval; -#ifdef MCLK - GCLK->PCHCTRL[cfg->gclk_id].reg = cfg->gclk_mask | GCLK_PCHCTRL_CHEN; + *cfg->mclk |= cfg->mclk_mask; - MCLK_ADC |= cfg->mclk_mask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; #else - PM->APBCMASK.bit.ADC_ = 1; - - GCLK->CLKCTRL.reg = cfg->gclk | GCLK_CLKCTRL_CLKEN; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); @@ -515,14 +513,6 @@ static const struct adc_driver_api adc_sam0_api = { #ifdef MCLK -#define ADC_SAM0_CLOCK_CONTROL(n) \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_mask = UTIL_CAT(GCLK_PCHCTRL_GEN_GCLK, \ - DT_INST_PROP(n, gclk)), \ - .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch), \ - .prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \ - UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)), - #define ADC_SAM0_CONFIGURE(n) \ do { \ const struct adc_sam0_cfg *const cfg = dev->config; \ @@ -534,24 +524,18 @@ do { \ #else -#define ADC_SAM0_CLOCK_CONTROL(n) \ - .gclk = UTIL_CAT(GCLK_CLKCTRL_GEN_GCLK, DT_INST_PROP(n, gclk)) |\ - GCLK_CLKCTRL_ID_ADC, \ - .prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \ - UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)), - #define ADC_SAM0_CONFIGURE(n) \ do { \ const struct adc_sam0_cfg *const cfg = dev->config; \ Adc * const adc = cfg->regs; \ /* Linearity is split across two words */ \ - uint32_t lin = ((*(uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) & \ + uint32_t lin = ((*(uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) & \ ADC_FUSES_LINEARITY_0_Msk) >> \ ADC_FUSES_LINEARITY_0_Pos; \ lin |= (((*(uint32_t *)ADC_FUSES_LINEARITY_1_ADDR) & \ ADC_FUSES_LINEARITY_1_Msk) >> \ ADC_FUSES_LINEARITY_1_Pos) << 4; \ - uint32_t bias = ((*(uint32_t *)ADC_FUSES_BIASCAL_ADDR) & \ + uint32_t bias = ((*(uint32_t *)ADC_FUSES_BIASCAL_ADDR) & \ ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos; \ adc->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | \ ADC_CALIB_LINEARITY_CAL(lin); \ @@ -559,37 +543,47 @@ do { \ #endif -#define ADC_SAM0_DEVICE(n) \ - PINCTRL_DT_INST_DEFINE(n); \ - static void adc_sam0_config_##n(const struct device *dev); \ - static const struct adc_sam0_cfg adc_sam_cfg_##n = { \ - .regs = (Adc *)DT_INST_REG_ADDR(n), \ - ADC_SAM0_CLOCK_CONTROL(n) \ - .freq = UTIL_CAT(UTIL_CAT(SOC_ATMEL_SAM0_GCLK, \ - DT_INST_PROP(n, gclk)), \ - _FREQ_HZ) / \ - DT_INST_PROP(n, prescaler), \ - .config_func = &adc_sam0_config_##n, \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - }; \ - static struct adc_sam0_data adc_sam_data_##n = { \ - ADC_CONTEXT_INIT_TIMER(adc_sam_data_##n, ctx), \ - ADC_CONTEXT_INIT_LOCK(adc_sam_data_##n, ctx), \ - ADC_CONTEXT_INIT_SYNC(adc_sam_data_##n, ctx), \ - }; \ - DEVICE_DT_INST_DEFINE(n, adc_sam0_init, NULL, \ - &adc_sam_data_##n, \ - &adc_sam_cfg_##n, POST_KERNEL, \ - CONFIG_ADC_INIT_PRIORITY, \ - &adc_sam0_api); \ - static void adc_sam0_config_##n(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, resrdy, irq), \ - DT_INST_IRQ_BY_NAME(n, resrdy, priority), \ - adc_sam0_isr, \ - DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(n, resrdy, irq)); \ - ADC_SAM0_CONFIGURE(n); \ +#define ADC_SAM0_GCLK_FREQ(n) \ + UTIL_CAT(UTIL_CAT(SOC_ATMEL_SAM0_GCLK, \ + DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen)), \ + _FREQ_HZ) + +#define ADC_SAM0_FREQ(n) \ + .prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \ + UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)), \ + .freq = ADC_SAM0_GCLK_FREQ(n) / DT_INST_PROP(n, prescaler) + +#define ADC_SAM0_DEVICE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static void adc_sam0_config_##n(const struct device *dev); \ + static const struct adc_sam0_cfg adc_sam_cfg_##n = { \ + .regs = (Adc *)DT_INST_REG_ADDR(n), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + ADC_SAM0_FREQ(n), \ + .config_func = &adc_sam0_config_##n, \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + }; \ + static struct adc_sam0_data adc_sam_data_##n = { \ + ADC_CONTEXT_INIT_TIMER(adc_sam_data_##n, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_sam_data_##n, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_sam_data_##n, ctx), \ + }; \ + DEVICE_DT_INST_DEFINE(n, adc_sam0_init, NULL, \ + &adc_sam_data_##n, \ + &adc_sam_cfg_##n, POST_KERNEL, \ + CONFIG_ADC_INIT_PRIORITY, \ + &adc_sam0_api); \ + static void adc_sam0_config_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, resrdy, irq), \ + DT_INST_IRQ_BY_NAME(n, resrdy, priority), \ + adc_sam0_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, resrdy, irq)); \ + ADC_SAM0_CONFIGURE(n); \ } DT_INST_FOREACH_STATUS_OKAY(ADC_SAM0_DEVICE) diff --git a/drivers/can/can_sam0.c b/drivers/can/can_sam0.c index adcbf6a567db66..8c92922e299b9e 100644 --- a/drivers/can/can_sam0.c +++ b/drivers/can/can_sam0.c @@ -3,6 +3,7 @@ * Copyright (c) 2021 Alexander Wachter * Copyright (c) 2022 Kamil Serwus * Copyright (c) 2023 Sebastian Schlupp + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,7 +27,8 @@ struct can_sam0_config { const struct pinctrl_dev_config *pcfg; volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; + uint32_t gclk_gen; + uint16_t gclk_id; int divider; }; @@ -109,6 +111,12 @@ static int can_sam0_get_core_clock(const struct device *dev, uint32_t *rate) static void can_sam0_clock_enable(const struct can_sam0_config *cfg) { + *cfg->mclk |= cfg->mclk_mask; + + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; + /* Enable the GLCK7 with DIV*/ #if defined(CONFIG_SOC_SERIES_SAME51) || defined(CONFIG_SOC_SERIES_SAME54) /*DFFL has to be used as clock source for the ATSAME51/54 family of SoCs*/ @@ -121,13 +129,6 @@ static void can_sam0_clock_enable(const struct can_sam0_config *cfg) | GCLK_GENCTRL_DIV(cfg->divider) | GCLK_GENCTRL_GENEN; #endif - - /* Route channel */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK7 - | GCLK_PCHCTRL_CHEN; - - /* Enable CAN clock in MCLK */ - *cfg->mclk |= cfg->mclk_mask; } static int can_sam0_init(const struct device *dev) @@ -211,9 +212,10 @@ static void config_can_##inst##_irq(void) \ static const struct can_sam0_config can_sam0_cfg_##inst = { \ .base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \ .mram = (mem_addr_t)POINTER_TO_UINT(&can_sam0_mram_##inst), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(inst), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, periph_ch), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(inst, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(inst), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(inst, bit), \ .divider = DT_INST_PROP(inst, divider), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .config_irq = config_can_##inst##_irq, \ diff --git a/drivers/counter/counter_sam0_tc32.c b/drivers/counter/counter_sam0_tc32.c index 7dde721febd842..5560a4105e8ee3 100644 --- a/drivers/counter/counter_sam0_tc32.c +++ b/drivers/counter/counter_sam0_tc32.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Derek Hageman + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,16 +32,11 @@ struct counter_sam0_tc32_config { struct counter_config_info info; TcCount32 *regs; const struct pinctrl_dev_config *pcfg; -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; + uint32_t gclk_gen; uint16_t gclk_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif uint16_t prescaler; - void (*irq_config_func)(const struct device *dev); }; @@ -336,20 +332,17 @@ static int counter_sam0_tc32_initialize(const struct device *dev) TcCount32 *tc = cfg->regs; int retval; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - - /* Enable TC clock in MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif /* @@ -403,60 +396,52 @@ static const struct counter_driver_api counter_sam0_tc32_driver_api = { }; -#ifdef MCLK -#define COUNTER_SAM0_TC32_CLOCK_CONTROL(n) \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch), -#else -#define COUNTER_SAM0_TC32_CLOCK_CONTROL(n) \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id), -#endif - -#define SAM0_TC32_PRESCALER(n) \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(n, prescaler), \ +#define SAM0_TC32_PRESCALER(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, prescaler), \ (DT_INST_PROP(n, prescaler)), (1)) -#define COUNTER_SAM0_TC32_DEVICE(n) \ - PINCTRL_DT_INST_DEFINE(n); \ - static void counter_sam0_tc32_config_##n(const struct device *dev); \ - static const struct counter_sam0_tc32_config \ - \ - counter_sam0_tc32_dev_config_##n = { \ - .info = { \ - .max_top_value = UINT32_MAX, \ - .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ - SAM0_TC32_PRESCALER(n), \ - .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ - .channels = 1 \ - }, \ - .regs = (TcCount32 *)DT_INST_REG_ADDR(n), \ - COUNTER_SAM0_TC32_CLOCK_CONTROL(n) \ - .prescaler = UTIL_CAT(TC_CTRLA_PRESCALER_DIV, \ - SAM0_TC32_PRESCALER(n)), \ - .irq_config_func = &counter_sam0_tc32_config_##n, \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - }; \ - \ - static struct counter_sam0_tc32_data counter_sam0_tc32_dev_data_##n;\ - \ - DEVICE_DT_INST_DEFINE(n, \ - &counter_sam0_tc32_initialize, \ - NULL, \ - &counter_sam0_tc32_dev_data_##n, \ - &counter_sam0_tc32_dev_config_##n, \ - PRE_KERNEL_1, \ - CONFIG_COUNTER_INIT_PRIORITY, \ - &counter_sam0_tc32_driver_api); \ - \ - static void counter_sam0_tc32_config_##n(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_INST_IRQN(n), \ - DT_INST_IRQ(n, priority), \ - counter_sam0_tc32_isr, \ - DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQN(n)); \ +#define COUNTER_SAM0_TC32_DEVICE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static void counter_sam0_tc32_config_##n(const struct device *dev); \ + static const struct counter_sam0_tc32_config \ + \ + counter_sam0_tc32_dev_config_##n = { \ + .info = { \ + .max_top_value = UINT32_MAX, \ + .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ + SAM0_TC32_PRESCALER(n), \ + .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ + .channels = 1 \ + }, \ + .regs = (TcCount32 *)DT_INST_REG_ADDR(n), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + .prescaler = UTIL_CAT(TC_CTRLA_PRESCALER_DIV, \ + SAM0_TC32_PRESCALER(n)), \ + .irq_config_func = &counter_sam0_tc32_config_##n, \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + }; \ + \ + static struct counter_sam0_tc32_data counter_sam0_tc32_dev_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &counter_sam0_tc32_initialize, \ + NULL, \ + &counter_sam0_tc32_dev_data_##n, \ + &counter_sam0_tc32_dev_config_##n, \ + PRE_KERNEL_1, \ + CONFIG_COUNTER_INIT_PRIORITY, \ + &counter_sam0_tc32_driver_api); \ + \ + static void counter_sam0_tc32_config_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + counter_sam0_tc32_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ } DT_INST_FOREACH_STATUS_OKAY(COUNTER_SAM0_TC32_DEVICE) diff --git a/drivers/dac/dac_sam0.c b/drivers/dac/dac_sam0.c index d831eb44e75b31..7bfc088ab52264 100644 --- a/drivers/dac/dac_sam0.c +++ b/drivers/dac/dac_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,8 +28,10 @@ LOG_MODULE_REGISTER(dac_sam0, CONFIG_DAC_LOG_LEVEL); struct dac_sam0_cfg { Dac *regs; const struct pinctrl_dev_config *pcfg; - uint8_t pm_apbc_bit; - uint8_t gclk_clkctrl_id; + volatile uint32_t *mclk; + uint32_t mclk_mask; + uint32_t gclk_gen; + uint16_t gclk_id; uint8_t refsel; }; @@ -77,18 +80,24 @@ static int dac_sam0_init(const struct device *dev) Dac *regs = cfg->regs; int retval; - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; + *cfg->mclk |= cfg->mclk_mask; + +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; +#endif retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); if (retval < 0) { return retval; } - /* Enable the clock in PM */ - PM->APBCMASK.reg |= 1 << cfg->pm_apbc_bit; - /* Reset then configure the DAC */ regs->CTRLA.bit.SWRST = 1; while (regs->STATUS.bit.SYNCBUSY) { @@ -110,24 +119,25 @@ static const struct dac_driver_api api_sam0_driver_api = { .write_value = dac_sam0_write_value }; -#define SAM0_DAC_REFSEL(n) \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(n, reference), \ +#define SAM0_DAC_REFSEL(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, reference), \ (DT_INST_ENUM_IDX(n, reference)), (0)) -#define SAM0_DAC_INIT(n) \ - PINCTRL_DT_INST_DEFINE(n); \ - static const struct dac_sam0_cfg dac_sam0_cfg_##n = { \ - .regs = (Dac *)DT_INST_REG_ADDR(n), \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - .pm_apbc_bit = DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit), \ - .gclk_clkctrl_id = \ - DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id), \ - .refsel = UTIL_CAT(SAM0_DAC_REFSEL_, SAM0_DAC_REFSEL(n)), \ - }; \ - \ - DEVICE_DT_INST_DEFINE(n, &dac_sam0_init, NULL, NULL, \ - &dac_sam0_cfg_##n, POST_KERNEL, \ - CONFIG_DAC_INIT_PRIORITY, \ +#define SAM0_DAC_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static const struct dac_sam0_cfg dac_sam0_cfg_##n = { \ + .regs = (Dac *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + .refsel = UTIL_CAT(SAM0_DAC_REFSEL_, SAM0_DAC_REFSEL(n)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &dac_sam0_init, NULL, NULL, \ + &dac_sam0_cfg_##n, POST_KERNEL, \ + CONFIG_DAC_INIT_PRIORITY, \ &api_sam0_driver_api) DT_INST_FOREACH_STATUS_OKAY(SAM0_DAC_INIT); diff --git a/drivers/i2c/i2c_sam0.c b/drivers/i2c/i2c_sam0.c index ff0b6c67fb652c..55a155c7168328 100644 --- a/drivers/i2c/i2c_sam0.c +++ b/drivers/i2c/i2c_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Derek Hageman + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,14 +35,10 @@ struct i2c_sam0_dev_config { SercomI2cm *regs; const struct pinctrl_dev_config *pcfg; uint32_t bitrate; -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif + uint32_t gclk_gen; + uint16_t gclk_id; void (*irq_config_func)(const struct device *dev); #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN @@ -711,20 +708,19 @@ static int i2c_sam0_initialize(const struct device *dev) SercomI2cm *i2c = cfg->regs; int retval; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - /* Enable SERCOM clock in MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable SERCOM clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif + /* Disable all I2C interrupts */ i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; @@ -822,9 +818,10 @@ static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \ .regs = (SercomI2cm *)DT_INST_REG_ADDR(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .bitrate = DT_INST_PROP(n, clock_frequency), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .irq_config_func = &i2c_sam0_irq_config_##n, \ I2C_SAM0_DMA_CHANNELS(n) \ } @@ -834,8 +831,10 @@ static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \ .regs = (SercomI2cm *)DT_INST_REG_ADDR(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .bitrate = DT_INST_PROP(n, clock_frequency), \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .irq_config_func = &i2c_sam0_irq_config_##n, \ I2C_SAM0_DMA_CHANNELS(n) \ } diff --git a/drivers/pwm/pwm_sam0_tcc.c b/drivers/pwm/pwm_sam0_tcc.c index 3a12c81b76c9a9..34dafb6da0a9c5 100644 --- a/drivers/pwm/pwm_sam0_tcc.c +++ b/drivers/pwm/pwm_sam0_tcc.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,15 +26,10 @@ struct pwm_sam0_config { uint8_t counter_size; uint16_t prescaler; uint32_t freq; - -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; + uint32_t gclk_gen; uint16_t gclk_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif }; /* Wait for the peripheral to finish all commands */ @@ -106,15 +102,17 @@ static int pwm_sam0_init(const struct device *dev) Tcc *regs = cfg->regs; int retval; - /* Enable the clocks */ -#ifdef MCLK - GCLK->PCHCTRL[cfg->gclk_id].reg = - GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; *cfg->mclk |= cfg->mclk_mask; + +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; #else - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - PM->APBCMASK.reg |= cfg->pm_apbcmask; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); @@ -140,34 +138,26 @@ static const struct pwm_driver_api pwm_sam0_driver_api = { .get_cycles_per_sec = pwm_sam0_get_cycles_per_sec, }; -#ifdef MCLK -#define PWM_SAM0_INIT_CLOCKS(inst) \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(inst), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, mclk, bit)), \ - .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, periph_ch) -#else -#define PWM_SAM0_INIT_CLOCKS(inst) \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, clkctrl_id) -#endif - -#define PWM_SAM0_INIT(inst) \ - PINCTRL_DT_INST_DEFINE(inst); \ - static const struct pwm_sam0_config pwm_sam0_config_##inst = { \ - .regs = (Tcc *)DT_INST_REG_ADDR(inst), \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ - .channels = DT_INST_PROP(inst, channels), \ - .counter_size = DT_INST_PROP(inst, counter_size), \ - .prescaler = UTIL_CAT(TCC_CTRLA_PRESCALER_DIV, \ - DT_INST_PROP(inst, prescaler)), \ - .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ - DT_INST_PROP(inst, prescaler), \ - PWM_SAM0_INIT_CLOCKS(inst), \ - }; \ - \ - DEVICE_DT_INST_DEFINE(inst, &pwm_sam0_init, NULL, \ - NULL, &pwm_sam0_config_##inst, \ - POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ +#define PWM_SAM0_INIT(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + static const struct pwm_sam0_config pwm_sam0_config_##inst = { \ + .regs = (Tcc *)DT_INST_REG_ADDR(inst), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .channels = DT_INST_PROP(inst, channels), \ + .counter_size = DT_INST_PROP(inst, counter_size), \ + .prescaler = UTIL_CAT(TCC_CTRLA_PRESCALER_DIV, \ + DT_INST_PROP(inst, prescaler)), \ + .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ + DT_INST_PROP(inst, prescaler), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(inst, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(inst), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(inst, bit), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &pwm_sam0_init, NULL, \ + NULL, &pwm_sam0_config_##inst, \ + POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ &pwm_sam0_driver_api); DT_INST_FOREACH_STATUS_OKAY(PWM_SAM0_INIT) diff --git a/drivers/serial/uart_sam0.c b/drivers/serial/uart_sam0.c index 35931fe5a17a09..1851bc53e5160f 100644 --- a/drivers/serial/uart_sam0.c +++ b/drivers/serial/uart_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,14 +36,11 @@ struct uart_sam0_dev_cfg { uint32_t baudrate; uint32_t pads; bool collision_detect; -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif + uint32_t gclk_gen; + uint16_t gclk_id; + #if CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_SAM0_ASYNC void (*irq_config_func)(const struct device *dev); #endif @@ -510,20 +508,17 @@ static int uart_sam0_init(const struct device *dev) SercomUsart * const usart = cfg->regs; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - - /* Enable SERCOM clock in MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable SERCOM clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif /* Disable all USART interrupts */ @@ -1272,34 +1267,20 @@ static void uart_sam0_irq_config_##n(const struct device *dev) \ #define UART_SAM0_SERCOM_COLLISION_DETECT(n) \ (DT_INST_PROP(n, collision_detection)) -#ifdef MCLK -#define UART_SAM0_CONFIG_DEFN(n) \ -static const struct uart_sam0_dev_cfg uart_sam0_config_##n = { \ - .regs = (SercomUsart *)DT_INST_REG_ADDR(n), \ - .baudrate = DT_INST_PROP(n, current_speed), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch),\ - .pads = UART_SAM0_SERCOM_PADS(n), \ - .collision_detect = UART_SAM0_SERCOM_COLLISION_DETECT(n), \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - UART_SAM0_IRQ_HANDLER_FUNC(n) \ - UART_SAM0_DMA_CHANNELS(n) \ -} -#else #define UART_SAM0_CONFIG_DEFN(n) \ static const struct uart_sam0_dev_cfg uart_sam0_config_##n = { \ .regs = (SercomUsart *)DT_INST_REG_ADDR(n), \ .baudrate = DT_INST_PROP(n, current_speed), \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .pads = UART_SAM0_SERCOM_PADS(n), \ .collision_detect = UART_SAM0_SERCOM_COLLISION_DETECT(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ UART_SAM0_IRQ_HANDLER_FUNC(n) \ UART_SAM0_DMA_CHANNELS(n) \ } -#endif #define UART_SAM0_DEVICE_INIT(n) \ PINCTRL_DT_INST_DEFINE(n); \ diff --git a/drivers/spi/spi_sam0.c b/drivers/spi/spi_sam0.c index b0da362ea86f66..aa58ddd491d1c9 100644 --- a/drivers/spi/spi_sam0.c +++ b/drivers/spi/spi_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,14 +28,12 @@ struct spi_sam0_config { SercomSpi *regs; uint32_t pads; const struct pinctrl_dev_config *pcfg; -#ifdef MCLK + volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif + uint32_t gclk_gen; + uint16_t gclk_id; + #ifdef CONFIG_SPI_ASYNC const struct device *dma_dev; uint8_t tx_dma_request; @@ -645,20 +644,17 @@ static int spi_sam0_init(const struct device *dev) struct spi_sam0_data *data = dev->data; SercomSpi *regs = cfg->regs; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - - /* Enable the MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable SERCOM clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif /* Disable all SPI interrupts */ @@ -721,9 +717,10 @@ static const struct spi_driver_api spi_sam0_driver_api = { #define SPI_SAM0_DEFINE_CONFIG(n) \ static const struct spi_sam0_config spi_sam0_config_##n = { \ .regs = (SercomSpi *)DT_INST_REG_ADDR(n), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .pads = SPI_SAM0_SERCOM_PADS(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ SPI_SAM0_DMA_CHANNELS(n) \ @@ -732,8 +729,10 @@ static const struct spi_sam0_config spi_sam0_config_##n = { \ #define SPI_SAM0_DEFINE_CONFIG(n) \ static const struct spi_sam0_config spi_sam0_config_##n = { \ .regs = (SercomSpi *)DT_INST_REG_ADDR(n), \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .pads = SPI_SAM0_SERCOM_PADS(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ SPI_SAM0_DMA_CHANNELS(n) \ diff --git a/dts/arm/atmel/samc21.dtsi b/dts/arm/atmel/samc21.dtsi index 095e98437f05b1..de5106a73a5ae5 100644 --- a/dts/arm/atmel/samc21.dtsi +++ b/dts/arm/atmel/samc21.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Kamil Serwus + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,7 +22,8 @@ interrupt-names = "resrdy"; clocks = <&gclk 34>, <&mclk 0x1c 18>; clock-names = "GCLK", "MCLK"; - gclk = <0>; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; prescaler = <4>; #io-channel-cells = <1>; }; @@ -32,6 +34,8 @@ interrupts = <13 0>; clocks = <&gclk 23>, <&mclk 0x1c 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -41,6 +45,8 @@ interrupts = <14 0>; clocks = <&gclk 25>, <&mclk 0x1c 6>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -51,6 +57,8 @@ interrupt-names = "int0"; clocks = <&gclk 26>, <&mclk 0x10 8>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; divider = <12>; status = "disabled"; @@ -63,6 +71,8 @@ interrupt-names = "int0"; clocks = <&gclk 27>, <&mclk 0x10 9>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; divider = <12>; status = "disabled"; diff --git a/dts/arm/atmel/samc2x.dtsi b/dts/arm/atmel/samc2x.dtsi index aff054ad6272dd..824d61198cedc0 100644 --- a/dts/arm/atmel/samc2x.dtsi +++ b/dts/arm/atmel/samc2x.dtsi @@ -76,15 +76,23 @@ }; mclk: mclk@40000800 { - compatible = "atmel,samc2x-mclk"; + compatible = "atmel,sam0-mclk"; reg = <0x40000800 0x400>; #clock-cells = <2>; }; + osc32kctrl: osc32kctrl@40001400 { + compatible = "atmel,sam0-osc32kctrl"; + reg = <0x40001400 0x400>; + #clock-cells = <0>; + #assigned-clock-cells = <1>; + }; + gclk: gclk@40001c00 { - compatible = "atmel,samc2x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40001c00 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; eic: eic@40002800 { @@ -119,7 +127,8 @@ interrupt-names = "resrdy"; clocks = <&gclk 33>, <&mclk 0x1c 17>; clock-names = "GCLK", "MCLK"; - gclk = <0>; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; prescaler = <4>; #io-channel-cells = <1>; }; @@ -130,6 +139,8 @@ interrupts = <9 0>; clocks = <&gclk 19>, <&mclk 0x1c 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -139,6 +150,8 @@ interrupts = <10 0>; clocks = <&gclk 20>, <&mclk 0x1c 2>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -148,6 +161,8 @@ interrupts = <11 0>; clocks = <&gclk 21>, <&mclk 0x1c 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -157,6 +172,8 @@ interrupts = <12 0>; clocks = <&gclk 22>, <&mclk 0x1c 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -166,6 +183,8 @@ interrupts = <17 0>; clocks = <&gclk 28>, <&mclk 0x1c 9>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -177,6 +196,8 @@ interrupts = <18 0>; clocks = <&gclk 28>, <&mclk 0x1c 10>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -188,6 +209,8 @@ interrupts = <19 0>; clocks = <&gclk 29>, <&mclk 0x1c 11>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <16>; @@ -226,7 +249,6 @@ rtc: rtc@40002400 { compatible = "atmel,sam0-rtc"; - gclk = <4>; reg = <0x40002400 0x24>; interrupts = <2 0>; alarms-count = <1>; diff --git a/dts/arm/atmel/samd20.dtsi b/dts/arm/atmel/samd20.dtsi index 01af6c4e4503de..f18f4fb135d17e 100644 --- a/dts/arm/atmel/samd20.dtsi +++ b/dts/arm/atmel/samd20.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Sean Nyekjaer + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +21,8 @@ interrupts = <13 0>; clocks = <&gclk 0x13>, <&pm 0x20 8>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tc2: tc@42002800 { @@ -28,6 +31,8 @@ interrupts = <15 0>; clocks = <&gclk 0x14>, <&pm 0x20 10>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tc6: tc@42003800 { @@ -36,61 +41,93 @@ interrupts = <19 0>; clocks = <&gclk 0x16>, <&pm 0x20 14>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; }; }; +&adc { + interrupts = <21 0>; + interrupt-names = "resrdy"; + /* + * 2.1 MHz is ADC max clock + * 8 MHz GCLK / 4 = 2 MHz + * Generator 3: DFLL48M / 8MHz + */ + clocks = <&gclk 0x17>, <&pm 0x20 16>; + clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 3>; + assigned-clock-names = "GCLK"; +}; + &dac0 { interrupts = <23 0>; clocks = <&gclk 26>, <&pm 0x20 18>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom0 { interrupts = <7 0>; clocks = <&gclk 0xd>, <&pm 0x20 2>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom1 { interrupts = <8 0>; clocks = <&gclk 0xe>, <&pm 0x20 3>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom2 { interrupts = <9 0>; clocks = <&gclk 0xf>, <&pm 0x20 4>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom3 { interrupts = <10 0>; clocks = <&gclk 0x10>, <&pm 0x20 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom4 { interrupts = <11 0>; clocks = <&gclk 0x11>, <&pm 0x20 6>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom5 { interrupts = <12 0>; clocks = <&gclk 0x12>, <&pm 0x20 7>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; -&tc4 { - interrupts = <17 0>; - clocks = <&gclk 0x15>, <&pm 0x20 12>; +&rtc { + clocks = <&gclk 2>, <&pm 0x18 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 4>; + assigned-clock-names = "GCLK"; }; -&adc { - interrupts = <21 0>; - interrupt-names = "resrdy"; - clocks = <&gclk 0x17>, <&pm 0x20 16>; +&tc4 { + interrupts = <17 0>; + clocks = <&gclk 0x15>, <&pm 0x20 12>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; diff --git a/dts/arm/atmel/samd21.dtsi b/dts/arm/atmel/samd21.dtsi index f8b12ed570ae90..f2f0477a7adbe8 100644 --- a/dts/arm/atmel/samd21.dtsi +++ b/dts/arm/atmel/samd21.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,6 +34,8 @@ interrupts = <21 0>; clocks = <&gclk 0x1d>, <&pm 0x20 14>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tcc0: tcc@42002000 { @@ -41,6 +44,8 @@ interrupts = <15 0>; clocks = <&gclk 26>, <&pm 0x20 8>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -52,6 +57,8 @@ interrupts = <16 0>; clocks = <&gclk 26>, <&pm 0x20 9>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <24>; @@ -63,6 +70,8 @@ interrupts = <17 0>; clocks = <&gclk 27>, <&pm 0x20 10>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <16>; @@ -70,57 +79,87 @@ }; }; +&adc { + /* + * 2.1 MHz is ADC max clock + * 8 MHz GCLK / 4 = 2 MHz + * Generator 3: DFLL48M / 8MHz + */ + clocks = <&gclk 0x1e>, <&pm 0x20 16>; + clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 3>; + assigned-clock-names = "GCLK"; + interrupts = <23 0>; + interrupt-names = "resrdy"; +}; + &dac0 { interrupts = <25 0>; clocks = <&gclk 33>, <&pm 0x20 18>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom0 { interrupts = <9 0>; clocks = <&gclk 0x14>, <&pm 0x20 2>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom1 { interrupts = <10 0>; clocks = <&gclk 0x15>, <&pm 0x20 3>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom2 { interrupts = <11 0>; clocks = <&gclk 0x16>, <&pm 0x20 4>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom3 { interrupts = <12 0>; clocks = <&gclk 0x17>, <&pm 0x20 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom4 { interrupts = <13 0>; clocks = <&gclk 0x18>, <&pm 0x20 6>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom5 { interrupts = <14 0>; clocks = <&gclk 0x19>, <&pm 0x20 7>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; -&tc4 { - interrupts = <19 0>; - clocks = <&gclk 0x1c>, <&pm 0x20 12>; +&rtc { + clocks = <&gclk 4>, <&pm 0x18 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 4>; + assigned-clock-names = "GCLK"; }; -&adc { - clocks = <&gclk 0x1e>, <&pm 0x20 16>; +&tc4 { + interrupts = <19 0>; + clocks = <&gclk 0x1c>, <&pm 0x20 12>; clock-names = "GCLK", "PM"; - interrupts = <23 0>; - interrupt-names = "resrdy"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; diff --git a/dts/arm/atmel/samd2x.dtsi b/dts/arm/atmel/samd2x.dtsi index 7cdf4d98c9a787..d1ac51b784cb2e 100644 --- a/dts/arm/atmel/samd2x.dtsi +++ b/dts/arm/atmel/samd2x.dtsi @@ -77,16 +77,17 @@ }; pm: pm@40000400 { - compatible = "atmel,samd2x-pm"; + compatible = "atmel,sam0-mclk"; reg = <0x40000400 0x400>; interrupts = <0 0>; #clock-cells = <2>; }; gclk: gclk@40000c00 { - compatible = "atmel,samd2x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40000c00 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; eic: eic@40001800 { @@ -180,23 +181,16 @@ compatible = "atmel,sam0-rtc"; reg = <0x40001400 0x1C>; interrupts = <3 0>; - gclk = <4>; - clocks = <&gclk 4 4>, <&pm 0x18 5>; - clock-names = "GCLK", "PM"; alarms-count = <1>; cal-constant = <(1024 * 976)>; + clocks = <&gclk 4 4>, <&pm 0x18 5>; + clock-names = "GCLK", "PM"; status = "disabled"; }; adc: adc@42004000 { compatible = "atmel,sam0-adc"; reg = <0x42004000 0x2B>; - - /* - * 2.1 MHz max, so clock it with the - * 8 MHz GCLK / 4 = 2 MHz - */ - gclk = <3>; prescaler = <4>; #io-channel-cells = <1>; }; diff --git a/dts/arm/atmel/samd5x.dtsi b/dts/arm/atmel/samd5x.dtsi index d2b985f13bfeb0..d651d888daed05 100644 --- a/dts/arm/atmel/samd5x.dtsi +++ b/dts/arm/atmel/samd5x.dtsi @@ -89,15 +89,23 @@ }; mclk: mclk@40000800 { - compatible = "atmel,samd5x-mclk"; + compatible = "atmel,sam0-mclk"; reg = <0x40000800 0x400>; #clock-cells = <2>; }; + osc32kctrl: osc32kctrl@40001400 { + compatible = "atmel,sam0-osc32kctrl"; + reg = <0x40001400 0x400>; + #clock-cells = <0>; + #assigned-clock-cells = <1>; + }; + gclk: gclk@40001c00 { - compatible = "atmel,samd5x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40001c00 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; nvmctrl: nvmctrl@41004000 { @@ -164,6 +172,8 @@ status = "disabled"; clocks = <&gclk 7>, <&mclk 0x14 12>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; sercom1: sercom@40003400 { @@ -173,6 +183,8 @@ status = "disabled"; clocks = <&gclk 8>, <&mclk 0x14 13>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; sercom2: sercom@41012000 { @@ -182,6 +194,8 @@ status = "disabled"; clocks = <&gclk 23>, <&mclk 0x18 9>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; sercom3: sercom@41014000 { @@ -191,6 +205,8 @@ status = "disabled"; clocks = <&gclk 24>, <&mclk 0x18 10>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; sercom4: sercom@43000000 { @@ -200,6 +216,8 @@ status = "disabled"; clocks = <&gclk 34>, <&mclk 0x20 0>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; sercom5: sercom@43000400 { @@ -209,6 +227,8 @@ status = "disabled"; clocks = <&gclk 35>, <&mclk 0x20 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; sercom6: sercom@43000800 { @@ -218,6 +238,8 @@ status = "disabled"; clocks = <&gclk 36>, <&mclk 0x20 2>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; sercom7: sercom@43000c00 { @@ -227,6 +249,8 @@ status = "disabled"; clocks = <&gclk 37>, <&mclk 0x20 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; pinctrl: pinctrl@41008000 { @@ -284,9 +308,8 @@ rtc: rtc@40002400 { compatible = "atmel,sam0-rtc"; - reg = <0x40002400 0x1C>; + reg = <0x40002400 0x40>; interrupts = <11 0>; - gclk = <4>; clocks = <&mclk 0x14 9 &osc32kctrl>; clock-names = "MCLK", "OSC32KCTRL"; alarms-count = <2>; @@ -301,18 +324,19 @@ reg = <0x43001C00 0x4A>; interrupts = <118 0>, <119 0>; interrupt-names = "overrun", "resrdy"; - /* - * 16 MHz max, source clock must not exceed 100 MHz. + * 16 MHz is ADC max clock, source clock must not exceed 100 MHz. * - table 54-8, section 54.6, page 2020 * - table 54-24, section 54.10.4, page 2031 - * -> 48 MHz GCLK(2) / 4 = 12 MHz + * 48 MHz GCLK / 4 = 12 MHz + * Generator 2: DFLL48M / 4 */ - gclk = <2>; - prescaler = <4>; + prescaler = <4>; #io-channel-cells = <1>; clocks = <&gclk 40>, <&mclk 0x20 7>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; calib-offset = <0>; }; @@ -321,18 +345,19 @@ reg = <0x43002000 0x4A>; interrupts = <120 0>, <121 0>; interrupt-names = "overrun", "resrdy"; - /* - * 16 MHz max, source clock must not exceed 100 MHz. + * 16 MHz is ADC max clock, source clock must not exceed 100 MHz. * - table 54-8, section 54.6, page 2020 * - table 54-24, section 54.10.4, page 2031 - * -> 48 MHz GCLK(2) / 4 = 12 MHz + * 48 MHz GCLK / 4 = 12 MHz + * Generator 2: DFLL48M / 4 */ - gclk = <2>; prescaler = <4>; #io-channel-cells = <1>; clocks = <&gclk 41>, <&mclk 0x20 8>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; calib-offset = <14>; }; @@ -342,6 +367,8 @@ interrupts = <107 0>; clocks = <&gclk 9>, <&mclk 0x14 14>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tc2: tc@4101a000 { @@ -350,6 +377,8 @@ interrupts = <109 0>; clocks = <&gclk 26>, <&mclk 0x18 13>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tc4: tc@42001400 { @@ -358,6 +387,8 @@ interrupts = <111 0>; clocks = <&gclk 30>, <&mclk 0x1c 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tc6: tc@43001400 { @@ -366,6 +397,8 @@ interrupts = <113 0>; clocks = <&gclk 39>, <&mclk 0x20 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tcc0: tcc@41016000 { @@ -375,6 +408,8 @@ <90 0>, <91 0>; clocks = <&gclk 25>, <&mclk 0x18 11>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <6>; counter-size = <24>; }; @@ -385,6 +420,8 @@ interrupts = <92 0>, <93 0>, <94 0>, <95 0>, <96 0>; clocks = <&gclk 25>, <&mclk 0x18 12>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; }; @@ -395,6 +432,8 @@ interrupts = <97 0>, <98 0>, <99 0>, <100 0>; clocks = <&gclk 29>, <&mclk 0x1c 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <3>; counter-size = <16>; }; @@ -405,6 +444,8 @@ interrupts = <101 0>, <102 0>, <103 0>; clocks = <&gclk 29>, <&mclk 0x1c 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <16>; }; @@ -415,6 +456,8 @@ interrupts = <104 0>, <105 0>, <106 0>; clocks = <&gclk 38>, <&mclk 0x20 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <16>; }; diff --git a/dts/arm/atmel/same5x.dtsi b/dts/arm/atmel/same5x.dtsi index 750094cfafef9e..1a17a71fdaa682 100644 --- a/dts/arm/atmel/same5x.dtsi +++ b/dts/arm/atmel/same5x.dtsi @@ -34,6 +34,8 @@ interrupt-names = "int0", "int1"; clocks = <&gclk 27>, <&mclk 0x10 17>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; divider = <12>; status = "disabled"; @@ -46,6 +48,8 @@ interrupt-names = "int0", "int1"; clocks = <&gclk 28>, <&mclk 0x10 18>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; divider = <12>; status = "disabled"; diff --git a/dts/arm/atmel/saml21.dtsi b/dts/arm/atmel/saml21.dtsi index 524c28d3d2defa..d438e49057d71f 100644 --- a/dts/arm/atmel/saml21.dtsi +++ b/dts/arm/atmel/saml21.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Argentum Systems Ltd. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,6 +30,8 @@ interrupts = <14 0>; clocks = <&gclk 25>, <&mclk 0x1c 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -40,6 +43,8 @@ interrupts = <15 0>; clocks = <&gclk 25>, <&mclk 0x1c 6>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -51,6 +56,8 @@ interrupts = <16 0>; clocks = <&gclk 26>, <&mclk 0x1c 7>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <16>; @@ -58,57 +65,80 @@ }; }; +&adc { + interrupts = <22 0>; + interrupt-names = "resrdy"; + /* + * 16 MHz is ADC max clock + * 48 MHz DFLL / 2 / 2 = 12 MHz + * Generator 3: 48MHz + */ + clocks = <&gclk 30>, <&mclk 0x20 3>; + clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 3>; + assigned-clock-names = "GCLK"; +}; + &dac { interrupts = <24 0>; clocks = <&gclk 32>, <&mclk 0x1c 12>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom0 { interrupts = <8 0>; clocks = <&gclk 18>, <&mclk 0x1c 0>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom1 { interrupts = <9 0>; clocks = <&gclk 19>, <&mclk 0x1c 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom2 { interrupts = <10 0>; clocks = <&gclk 20>, <&mclk 0x1c 2>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom3 { interrupts = <11 0>; clocks = <&gclk 21>, <&mclk 0x1c 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom4 { interrupts = <12 0>; clocks = <&gclk 22>, <&mclk 0x1c 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom5 { interrupts = <13 0>; clocks = <&gclk 24>, <&mclk 0x20 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &tc4 { interrupts = <21 0>; clocks = <&gclk 29>, <&mclk 0x20 2>; clock-names = "GCLK", "MCLK"; -}; - -&adc { - interrupts = <22 0>; - interrupt-names = "resrdy"; - clocks = <&gclk 30>, <&mclk 0x20 3>; - clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; diff --git a/dts/arm/atmel/saml2x.dtsi b/dts/arm/atmel/saml2x.dtsi index e130192055d7dc..28774e7666e986 100644 --- a/dts/arm/atmel/saml2x.dtsi +++ b/dts/arm/atmel/saml2x.dtsi @@ -65,23 +65,24 @@ }; }; - pm: pm@40000400 { - compatible = "atmel,saml2x-pm"; + mclk: mclk@40000400 { + compatible = "atmel,sam0-mclk"; reg = <0x40000400 0x400>; - interrupts = <0 0>; #clock-cells = <2>; }; - mclk: mclk@40000400 { - compatible = "atmel,saml2x-mclk"; - reg = <0x40000400 0x400>; - #clock-cells = <2>; + osc32kctrl: osc32kctrl@40001000 { + compatible = "atmel,sam0-osc32kctrl"; + reg = <0x40001000 0x400>; + #clock-cells = <0>; + #assigned-clock-cells = <1>; }; gclk: gclk@40001800 { - compatible = "atmel,saml2x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40001800 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; dmac: dmac@44000400 { @@ -170,9 +171,8 @@ rtc: rtc@40002000 { compatible = "atmel,sam0-rtc"; - reg = <0x40002000 0x1c>; + reg = <0x40002000 0x44>; interrupts = <2 0>; - gclk = <4>; alarms-count = <1>; cal-constant = <(8192 * 128)>; clocks = <&mclk 0x14 8 &osc32kctrl>; @@ -185,12 +185,6 @@ adc: adc@43000c00 { compatible = "atmel,sam0-adc"; reg = <0x43000c00 0x30>; - - /* - * 16 MHz max, so clock it with the - * 48 MHz DFLL / 2 / 2 = 12 MHz - */ - gclk = <3>; prescaler = <2>; #io-channel-cells = <1>; }; diff --git a/dts/arm/atmel/samr21.dtsi b/dts/arm/atmel/samr21.dtsi index 786597c3ca31fa..9b67073db85492 100644 --- a/dts/arm/atmel/samr21.dtsi +++ b/dts/arm/atmel/samr21.dtsi @@ -1,10 +1,11 @@ /* * Copyright (c) 2019 Benjamin Valentin + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ -#include +#include / { aliases { @@ -12,21 +13,6 @@ }; soc { - usb0: usb@41005000 { - compatible = "atmel,sam0-usb"; - status = "disabled"; - reg = <0x41005000 0x1000>; - interrupts = <7 0>; - num-bidir-endpoints = <8>; - }; - - dmac: dmac@41004800 { - compatible = "atmel,sam0-dmac"; - reg = <0x41004800 0x50>; - interrupts = <6 0>; - #dma-cells = <2>; - }; - pinctrl: pinctrl@41004400 { ranges = <0x41004400 0x41004400 0x180>; @@ -43,87 +29,5 @@ compatible = "atmel,sam0-pinmux"; reg = <0x41004500 0x80>; }; - - tcc0: tcc@42002000 { - compatible = "atmel,sam0-tcc"; - reg = <0x42002000 0x80>; - interrupts = <15 0>; - clocks = <&gclk 26>, <&pm 0x20 8>; - clock-names = "GCLK", "PM"; - - channels = <4>; - counter-size = <24>; - }; - - tcc1: tcc@42002400 { - compatible = "atmel,sam0-tcc"; - reg = <0x42002400 0x80>; - interrupts = <16 0>; - clocks = <&gclk 26>, <&pm 0x20 9>; - clock-names = "GCLK", "PM"; - - channels = <2>; - counter-size = <24>; - }; - - tcc2: tcc@42002800 { - compatible = "atmel,sam0-tcc"; - reg = <0x42002800 0x80>; - interrupts = <17 0>; - clocks = <&gclk 27>, <&pm 0x20 10>; - clock-names = "GCLK", "PM"; - - channels = <2>; - counter-size = <16>; - }; }; }; - -&sercom0 { - interrupts = <9 0>; - clocks = <&gclk 0x14>, <&pm 0x20 2>; - clock-names = "GCLK", "PM"; -}; - -&sercom1 { - interrupts = <10 0>; - clocks = <&gclk 0x15>, <&pm 0x20 3>; - clock-names = "GCLK", "PM"; -}; - -&sercom2 { - interrupts = <11 0>; - clocks = <&gclk 0x16>, <&pm 0x20 4>; - clock-names = "GCLK", "PM"; -}; - -&sercom3 { - interrupts = <12 0>; - clocks = <&gclk 0x17>, <&pm 0x20 5>; - clock-names = "GCLK", "PM"; -}; - -&sercom4 { - interrupts = <13 0>; - clocks = <&gclk 0x18>, <&pm 0x20 6>; - clock-names = "GCLK", "PM"; -}; - -&sercom5 { - interrupts = <14 0>; - clocks = <&gclk 0x19>, <&pm 0x20 7>; - clock-names = "GCLK", "PM"; -}; - -&tc4 { - interrupts = <19 0>; - clocks = <&gclk 0x1c>, <&pm 0x20 12>; - clock-names = "GCLK", "PM"; -}; - -&adc { - clocks = <&gclk 0x1e>, <&pm 0x20 16>; - clock-names = "GCLK", "PM"; - interrupts = <23 0>; - interrupt-names = "resrdy"; -}; diff --git a/dts/bindings/adc/atmel,sam0-adc.yaml b/dts/bindings/adc/atmel,sam0-adc.yaml index e403b2316b6b7f..7616613235ff8c 100644 --- a/dts/bindings/adc/atmel,sam0-adc.yaml +++ b/dts/bindings/adc/atmel,sam0-adc.yaml @@ -22,10 +22,11 @@ properties: clock-names: required: true - gclk: - type: int + assigned-clocks: + required: true + + assigned-clock-names: required: true - description: generic clock generator source prescaler: type: int diff --git a/dts/bindings/arm/atmel,samd2x-pm.yaml b/dts/bindings/arm/atmel,samd2x-pm.yaml deleted file mode 100644 index 7fa232b815d1af..00000000000000 --- a/dts/bindings/arm/atmel,samd2x-pm.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD2x Power Manager (PM) - -compatible: "atmel,samd2x-pm" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/clock/atmel,sam0-gclk.yaml b/dts/bindings/clock/atmel,sam0-gclk.yaml new file mode 100644 index 00000000000000..d8f011bf64d0a0 --- /dev/null +++ b/dts/bindings/clock/atmel,sam0-gclk.yaml @@ -0,0 +1,65 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +description: Atmel SAMD0 Generic Clock Controller (GCLK) + +compatible: "atmel,sam0-gclk" + +include: + - base.yaml + - clock-controller.yaml + +properties: + reg: + required: true + + "#clock-cells": + const: 1 + description: | + - The ID cell is the peripheral identification. + + These information are used on GCLK->CLKCTRL register to select the + clock for an specific peripheral. + + Example 1: Connect the XOSC32K to RTC on SAMD2x + Assuming that generator 2 have the following configuration: + GLKC->GENCTRL: + SRC: 5 (XOSC32K) + ID: 2 (Generator 2) + + Then to enable the clock to the peripheral + Generator: 2 + Identificator: 4 (GCLK_RTC) + + &rtc { + /* The peripheral is fixed and it is defined at soc devictree + * clocks property + */ + clocks = <&gclk 4>, <&pm 0x18 5>; + clock-names = "GCLK", "PM"; + + /* The generator is user selectable and because of that it is + * defined at board + */ + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + }; + + Example 2: Connect the XOSC32K to RTC on SAMD5x + In the SAMD5x the RTC is direct connected on the OSC32KCTRL and no + generator is used. See atmel,sam0-osc32kctrl.yaml for reference. + + "#assigned-clock-cells": + required: true + type: int + const: 1 + description: | + - The GEN cell is an integer number that represents the index of + the generic clock generator. It is usually a number between 0~8 + but could be more depending of the SoC. + +clock-cells: + - id + +assigned-clock-cells: + - gen diff --git a/dts/bindings/clock/atmel,sam0-mclk.yaml b/dts/bindings/clock/atmel,sam0-mclk.yaml new file mode 100644 index 00000000000000..efc07b6ffa98f9 --- /dev/null +++ b/dts/bindings/clock/atmel,sam0-mclk.yaml @@ -0,0 +1,48 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +description: Atmel SAM0 Main Clock Controller (MCLK) + +compatible: "atmel,sam0-mclk" + +include: + - base.yaml + - clock-controller.yaml + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + description: | + - The OFFSET cell is an address of a bus mask. The buses can be + AHB and APB[A-D]. Each bus mask can enable a paripheral clock + selecting the BIT position in the mask. + - The BIT cell is the peripheral bit mask. + + These information are used on PM and MCLK register to select the + clock for an specific peripheral. The generator 2 is used on this + example and can be defined by the user at board. + + Example: Enable SERCOM0 on SAMD21 + &sercom0 { + clocks = <&gclk 0x14>, <&pm 0x20 2>; + clock-names = "GCLK", "PM"; + + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + }; + + Example: Enable SERCOM0 on SAME54 + &sercom0 { + clocks = <&gclk 7>, <&mclk 0x14 12>; + clock-names = "GCLK", "MCLK"; + + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + }; + +clock-cells: + - offset + - bit diff --git a/dts/bindings/clock/atmel,sam0-osc32kctrl.yaml b/dts/bindings/clock/atmel,sam0-osc32kctrl.yaml new file mode 100644 index 00000000000000..e3c7e607e1b024 --- /dev/null +++ b/dts/bindings/clock/atmel,sam0-osc32kctrl.yaml @@ -0,0 +1,37 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +description: Atmel SAM0 32kHz Oscillator Controller (OSC32KCTRL) + +compatible: "atmel,sam0-osc32kctrl" + +include: + - base.yaml + - clock-controller.yaml + +properties: + reg: + required: true + + "#clock-cells": + const: 0 + + "#assigned-clock-cells": + required: true + type: int + const: 1 + description: | + It selects the OSC32CTRL clock to be routed to RTC peripheral + + Example: Connect the XOSC32K to RTC on SAMD5x + + &rtc { + clocks = <&mclk 0x14 9 &osc32kctrl>; + clock-names = "MCLK", "OSC32KCTRL"; + + assigned-clocks = <&osc32kctrl 4>; + assigned-clock-names = "OSC32KCTRL"; + }; + +assigned-clock-cells: + - src diff --git a/dts/bindings/clock/atmel,samc2x-gclk.yaml b/dts/bindings/clock/atmel,samc2x-gclk.yaml deleted file mode 100644 index d1e97272df72f4..00000000000000 --- a/dts/bindings/clock/atmel,samc2x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2022 Kamil Serwus -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMC2x Generic Clock Controller (GCLK) - -compatible: "atmel,samc2x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - periph_ch diff --git a/dts/bindings/clock/atmel,samc2x-mclk.yaml b/dts/bindings/clock/atmel,samc2x-mclk.yaml deleted file mode 100644 index 227fa5246c0150..00000000000000 --- a/dts/bindings/clock/atmel,samc2x-mclk.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2022, Kamil Serwus -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMC2x Generic Clock Controller (MCLK) - -compatible: "atmel,samc2x-mclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/clock/atmel,samd2x-gclk.yaml b/dts/bindings/clock/atmel,samd2x-gclk.yaml deleted file mode 100644 index f5188aef05f90a..00000000000000 --- a/dts/bindings/clock/atmel,samd2x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD2x Generic Clock Controller (GCLK) - -compatible: "atmel,samd2x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - clkctrl_id diff --git a/dts/bindings/clock/atmel,samd5x-gclk.yaml b/dts/bindings/clock/atmel,samd5x-gclk.yaml deleted file mode 100644 index 68fd94b44eb82a..00000000000000 --- a/dts/bindings/clock/atmel,samd5x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD5x Generic Clock Controller (GCLK) - -compatible: "atmel,samd5x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - periph_ch diff --git a/dts/bindings/clock/atmel,samd5x-mclk.yaml b/dts/bindings/clock/atmel,samd5x-mclk.yaml deleted file mode 100644 index 603196570daea9..00000000000000 --- a/dts/bindings/clock/atmel,samd5x-mclk.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD5x Generic Clock Controller (MCLK) - -compatible: "atmel,samd5x-mclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/clock/atmel,saml2x-gclk.yaml b/dts/bindings/clock/atmel,saml2x-gclk.yaml deleted file mode 100644 index 3c9020d505237c..00000000000000 --- a/dts/bindings/clock/atmel,saml2x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2021 Argentum Systems Ltd. -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAML2x Generic Clock Controller (GCLK) - -compatible: "atmel,saml2x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - periph_ch diff --git a/dts/bindings/clock/atmel,saml2x-mclk.yaml b/dts/bindings/clock/atmel,saml2x-mclk.yaml deleted file mode 100644 index ed89ba36f12e37..00000000000000 --- a/dts/bindings/clock/atmel,saml2x-mclk.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2021 Argentum Systems Ltd. -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAML2x Generic Clock Controller (MCLK) - -compatible: "atmel,saml2x-mclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/rtc/atmel,sam0-rtc.yaml b/dts/bindings/rtc/atmel,sam0-rtc.yaml index adead65ff4be3f..ca6a326eefec69 100644 --- a/dts/bindings/rtc/atmel,sam0-rtc.yaml +++ b/dts/bindings/rtc/atmel,sam0-rtc.yaml @@ -14,11 +14,17 @@ properties: reg: required: true - gclk: - type: int + clocks: + required: true + + clock-names: + required: true + + assigned-clocks: + required: true + + assigned-clock-names: required: true - description: | - Generic Clock Generator source cal-constant: type: int diff --git a/dts/bindings/serial/atmel,sam0-uart.yaml b/dts/bindings/serial/atmel,sam0-uart.yaml index f817137d7b69e4..d0a648dd563364 100644 --- a/dts/bindings/serial/atmel,sam0-uart.yaml +++ b/dts/bindings/serial/atmel,sam0-uart.yaml @@ -19,6 +19,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + rxpo: type: int required: true diff --git a/soc/atmel/sam0/common/atmel_sam0_dt.h b/soc/atmel/sam0/common/atmel_sam0_dt.h index f803596c872ac4..bc727c1707f785 100644 --- a/soc/atmel/sam0/common/atmel_sam0_dt.h +++ b/soc/atmel/sam0/common/atmel_sam0_dt.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2020 Linaro Ltd. - * Copyright (c) 2021 Gerson Fernando Budke + * Copyright (c) 2021-2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,12 +12,28 @@ #ifndef _ATMEL_SAM0_DT_H_ #define _ATMEL_SAM0_DT_H_ -/* Helper macro to get MCLK register address for corresponding - * that has corresponding clock enable bit. +#define ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, cell) \ + (volatile uint32_t *) \ + (DT_REG_ADDR(DT_INST_PHANDLE_BY_NAME(n, clocks, cell)) + \ + DT_INST_CLOCKS_CELL_BY_NAME(n, cell, offset)) + +#define ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, name, cell) \ + BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, name, cell)) + +/* Helper macro to get register address that control peripheral clock + * enable bit. + */ +#define ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mclk)), \ + (ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, mclk)), \ + (ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, pm))) + +/* Helper macro to get peripheral clock bit mask. */ -#define MCLK_MASK_DT_INT_REG_ADDR(n) \ - (DT_REG_ADDR(DT_INST_PHANDLE_BY_NAME(n, clocks, mclk)) + \ - DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, offset)) +#define ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, cell) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mclk)), \ + (ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, mclk, cell)), \ + (ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, pm, cell))) /* Helper macros for use with ATMEL SAM0 DMAC controller * return 0xff as default value if there is no 'dmas' property From 8af71d42b93b675e9d41d42a05719a32d6038548 Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Fri, 1 Nov 2024 16:49:53 +0100 Subject: [PATCH 4/6] soc: atmel: sam0: Configure GCLK[4] to RTC Configure the Generic Clock Generator to be used as source to RTC. The index 4 is now reserved to RTC. Signed-off-by: Gerson Fernando Budke --- drivers/timer/sam0_rtc_timer.c | 6 +- soc/atmel/sam0/common/Kconfig.samd2x | 16 +++++ soc/atmel/sam0/common/Kconfig.samd5x | 29 ++++++++ soc/atmel/sam0/common/soc_samc2x.c | 6 ++ soc/atmel/sam0/common/soc_samd2x.c | 104 ++++++++++----------------- soc/atmel/sam0/common/soc_samd5x.c | 51 +++++++++++-- soc/atmel/sam0/common/soc_saml2x.c | 3 + 7 files changed, 140 insertions(+), 75 deletions(-) diff --git a/drivers/timer/sam0_rtc_timer.c b/drivers/timer/sam0_rtc_timer.c index 4495bf3ded6906..66b1db27d8096c 100644 --- a/drivers/timer/sam0_rtc_timer.c +++ b/drivers/timer/sam0_rtc_timer.c @@ -248,8 +248,6 @@ uint32_t sys_clock_cycle_get_32(void) static int sys_clock_driver_init(void) { - int retval; - #ifdef MCLK MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC; OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K; @@ -264,10 +262,12 @@ static int sys_clock_driver_init(void) } #endif - retval = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); +#ifndef CONFIG_TICKLESS_KERNEL + int retval = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); if (retval < 0 && retval != -ENOENT) { return retval; } +#endif /* Reset module to hardware defaults. */ rtc_reset(); diff --git a/soc/atmel/sam0/common/Kconfig.samd2x b/soc/atmel/sam0/common/Kconfig.samd2x index f23b6557963139..e9a210a2167586 100644 --- a/soc/atmel/sam0/common/Kconfig.samd2x +++ b/soc/atmel/sam0/common/Kconfig.samd2x @@ -1,3 +1,4 @@ +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 if SOC_SERIES_SAMD20 || SOC_SERIES_SAMD21 || SOC_SERIES_SAMR21 @@ -35,6 +36,21 @@ config SOC_ATMEL_SAMD_XOSC32K_CRYSTAL Enable the crystal oscillator (if disabled, expect a clock signal on XIN32). +DT_ATMEL_RTC := $(dt_nodelabel_path,rtc) +DT_ATMEL_RTC_COUNTER_CLOCK_MODE := $(dt_node_str_prop_equals,$(DT_ATMEL_RTC),counter-mode,clock) + +config SOC_ATMEL_SAMD_XOSC32K_PRESCALER + int "XOSC32 Generic Clock Prescaler" + range 1 512 + default 32 if "$(DT_ATMEL_RTC_COUNTER_CLOCK_MODE)" + default 1 + depends on SOC_ATMEL_SAMD_XOSC32K + help + Configure the prescaler for the generic clock output + connected on the xosc32. When using RTC in calendar mode + the GCLK should be divided by 32 to RTC receive the + 1024 Hz reference clock. + config SOC_ATMEL_SAMD_XOSC bool "External 0.4..32 MHz clock source" help diff --git a/soc/atmel/sam0/common/Kconfig.samd5x b/soc/atmel/sam0/common/Kconfig.samd5x index dd05fe605d1e47..aa930f2652af59 100644 --- a/soc/atmel/sam0/common/Kconfig.samd5x +++ b/soc/atmel/sam0/common/Kconfig.samd5x @@ -1,4 +1,5 @@ # Copyright (c) 2019 ML!PA Consulting GmbH +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 if SOC_SERIES_SAMD51 || SOC_SERIES_SAME51 || SOC_SERIES_SAME53 || SOC_SERIES_SAME54 @@ -10,6 +11,34 @@ config SOC_ATMEL_SAMD5X_XOSC32K startup. This can then be selected as the main clock source for the SOC. +config SOC_ATMEL_SAMD5X_XOSC32K_CRYSTAL + bool "External 32.768 kHz clock is a crystal oscillator" + depends on SOC_ATMEL_SAMD5X_XOSC32K + default y + help + Enable the crystal oscillator (if disabled, expect a clock + signal on XIN32). + +config SOC_ATMEL_SAMD5X_XOSC32K_GAIN_HS + bool "XOSC32 High Speed gain" + depends on SOC_ATMEL_SAMD5X_XOSC32K + help + When this option is selected the gain is set High Speed + instead standard. + +DT_ATMEL_RTC := $(dt_nodelabel_path,rtc) +DT_ATMEL_RTC_COUNTER_CLOCK_MODE := $(dt_node_str_prop_equals,$(DT_ATMEL_RTC),counter-mode,clock) + +config SOC_ATMEL_SAMD5X_OSC32K_PRESCALER + int "XOSC32 Generic Clock Prescaler" + range 1 512 + default 32 if "$(DT_ATMEL_RTC_COUNTER_CLOCK_MODE)" + default 1 + help + Configure the prescaler for the generic clock output connected on the + xosc32 or osculp32k. When using RTC in calendar mode the GCLK should + be divided by 32 to RTC receive the 1024 Hz reference clock. + choice prompt "Main clock source" default SOC_ATMEL_SAMD5X_DEFAULT_AS_MAIN diff --git a/soc/atmel/sam0/common/soc_samc2x.c b/soc/atmel/sam0/common/soc_samc2x.c index 1581b62eef2e75..763ebd1aa6dd40 100644 --- a/soc/atmel/sam0/common/soc_samc2x.c +++ b/soc/atmel/sam0/common/soc_samc2x.c @@ -10,6 +10,12 @@ * @brief Atmel SAMC MCU series initialization code */ +/* GCLK Gen 0 -> GCLK_MAIN @ OSC48M + * GCLK Gen 2 -> WDT @ reserved + * GCLK Gen 0 -> ADC @ OSC48M + * GCLK Gen 4 -> RTC @ reserved + */ + #include #include #include diff --git a/soc/atmel/sam0/common/soc_samd2x.c b/soc/atmel/sam0/common/soc_samd2x.c index f915459a576627..e5cf512233796f 100644 --- a/soc/atmel/sam0/common/soc_samd2x.c +++ b/soc/atmel/sam0/common/soc_samd2x.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2017 Google LLC. * Copyright (c) 2023 Ionut Catalin Pavel - * Copyright (c) 2023 Gerson Fernando Budke + * Copyright (c) 2023-2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ * GCLK Gen 1 -> DFLL48M (variable) * GCLK Gen 2 -> WDT @ 32768 Hz * GCLK Gen 3 -> ADC @ 8 MHz + * GCLK Gen 4 -> RTC @ xtal 32768 Hz */ #include @@ -38,6 +39,23 @@ #define FUSES_OSC32K_CAL_Msk FUSES_OSC32KCAL_Msk #endif +static void gclk_connect(uint8_t gclk, uint32_t src, uint32_t div, uint32_t flags) +{ + GCLK->GENDIV.reg = GCLK_GENDIV_ID(gclk) + | GCLK_GENDIV_DIV(div); + + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk) + | GCLK_GENCTRL_GENEN + | src + | flags; + + while (GCLK->STATUS.bit.SYNCBUSY) { + } +} + static inline void osc8m_init(void) { uint32_t reg; @@ -57,19 +75,7 @@ static inline void osc8m_init(void) /* Use 8Mhz clock as gclk_main to allow switching between clocks * when using bootloaders */ - GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) - | GCLK_GENDIV_DIV(0); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0) - | GCLK_GENCTRL_SRC_OSC8M - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_GENEN; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + gclk_connect(0, GCLK_GENCTRL_SRC_OSC8M, 0, 0); } #if !CONFIG_SOC_ATMEL_SAMD_OSC32K || CONFIG_SOC_ATMEL_SAMD_DEFAULT_AS_MAIN @@ -149,28 +155,17 @@ static inline void dfll48m_init(void) { uint32_t fcal, ccal; - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(1) + gclk_connect(1, #if CONFIG_SOC_ATMEL_SAMD_OSC32K_AS_MAIN - | GCLK_GENCTRL_SRC_OSC32K + GCLK_GENCTRL_SRC_OSC32K, #elif CONFIG_SOC_ATMEL_SAMD_XOSC32K_AS_MAIN - | GCLK_GENCTRL_SRC_XOSC32K + GCLK_GENCTRL_SRC_XOSC32K, #elif CONFIG_SOC_ATMEL_SAMD_OSC8M_AS_MAIN - | GCLK_GENCTRL_SRC_OSC8M + GCLK_GENCTRL_SRC_OSC8M, #elif CONFIG_SOC_ATMEL_SAMD_XOSC_AS_MAIN - | GCLK_GENCTRL_SRC_XOSC + GCLK_GENCTRL_SRC_XOSC, #endif - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_RUNSTDBY - | GCLK_GENCTRL_GENEN; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) - | GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK1_DIV); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + SOC_ATMEL_SAM0_GCLK1_DIV, GCLK_GENCTRL_RUNSTDBY); /* Route multiplexer 0 to DFLL48M */ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(0) @@ -222,19 +217,7 @@ static inline void flash_waitstates_init(void) #else static inline void gclk_main_configure(void) { - GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) - | GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK0_DIV); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0) - | GCLK_GENCTRL_SRC_DFLL48M - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_GENEN; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + gclk_connect(0, GCLK_GENCTRL_SRC_DFLL48M, SOC_ATMEL_SAM0_GCLK0_DIV, 0); } #endif @@ -243,19 +226,16 @@ static inline void gclk_main_configure(void) #else static inline void gclk_adc_configure(void) { - GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) - | GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK3_DIV); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(3) - | GCLK_GENCTRL_SRC_DFLL48M - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_GENEN; + gclk_connect(3, GCLK_GENCTRL_SRC_DFLL48M, SOC_ATMEL_SAM0_GCLK3_DIV, 0); +} +#endif - while (GCLK->STATUS.bit.SYNCBUSY) { - } +#if !CONFIG_RTC_ATMEL_SAM0 || CONFIG_SOC_ATMEL_SAMD_DEFAULT_AS_MAIN +#define gclk_rtc_configure() +#else +static inline void gclk_rtc_configure(void) +{ + gclk_connect(4, GCLK_GENCTRL_SRC_XOSC32K, CONFIG_SOC_ATMEL_SAMD_XOSC32K_PRESCALER, 0); } #endif @@ -264,16 +244,7 @@ static inline void gclk_adc_configure(void) #else static inline void gclk_wdt_configure(void) { - GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) - | GCLK_GENDIV_DIV(4); - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) - | GCLK_GENCTRL_GENEN - | GCLK_GENCTRL_SRC_OSCULP32K - | GCLK_GENCTRL_DIVSEL; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + gclk_connect(2, GCLK_GENCTRL_SRC_OSCULP32K, 4, GCLK_GENCTRL_DIVSEL); } #endif @@ -296,6 +267,7 @@ void soc_reset_hook(void) flash_waitstates_init(); gclk_main_configure(); gclk_adc_configure(); + gclk_rtc_configure(); gclk_wdt_configure(); osc8m_disable(); } diff --git a/soc/atmel/sam0/common/soc_samd5x.c b/soc/atmel/sam0/common/soc_samd5x.c index f9f337f0f3b2f5..db57aa21bf65de 100644 --- a/soc/atmel/sam0/common/soc_samd5x.c +++ b/soc/atmel/sam0/common/soc_samd5x.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2019 ML!PA Consulting GmbH - * Copyright (c) 2023 Gerson Fernando Budke + * Copyright (c) 2023-2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,18 @@ * @brief Atmel SAMD MCU series initialization code */ +/* The CPU clock will be configured to the DT requested value, + * and run via DFLL48M. + * + * Reference -> GCLK Gen 1 -> DFLL48M -> GCLK Gen 0 -> GCLK_MAIN + * + * GCLK Gen 0 -> GCLK_MAIN @ DPLL0 + * GCLK Gen 1 -> DFLL48M @ 32768 Hz + * GCLK Gen 2 -> USB @ DFLL48M + * GCLK Gen 3 -> ADC @ reserved + * GCLK Gen 4 -> RTC @ xtal 32768 Hz + */ + #include #include #include @@ -19,16 +31,33 @@ #define SAM0_DPLL_FREQ_MIN_HZ (96000000U) #define SAM0_DPLL_FREQ_MAX_HZ (200000000U) -#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN -static void osc32k_init(void) +#if !CONFIG_SOC_ATMEL_SAMD5X_XOSC32K +#define xosc32k_init() +#else +static inline void xosc32k_init(void) { - OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_XTALEN - | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_RUNSTDBY - | OSC32KCTRL_XOSC32K_STARTUP(0) | OSC32KCTRL_XOSC32K_CGM_XT; + OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_CRYSTAL + | OSC32KCTRL_XOSC32K_XTALEN +#endif +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_GAIN_HS + | OSC32KCTRL_XOSC32K_CGM_HS +#else + | OSC32KCTRL_XOSC32K_CGM_XT +#endif + | OSC32KCTRL_XOSC32K_EN32K + | OSC32KCTRL_XOSC32K_EN1K + | OSC32KCTRL_XOSC32K_RUNSTDBY + | OSC32KCTRL_XOSC32K_STARTUP(1); while (!OSC32KCTRL->STATUS.bit.XOSC32KRDY) { } +} +#endif +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN +static void osc32k_init(void) +{ GCLK->GENCTRL[1].reg = GCLK_GENCTRL_SRC(GCLK_SOURCE_XOSC32K) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; @@ -127,6 +156,7 @@ void soc_reset_hook(void) CMCC->CTRL.bit.CEN = 0; gclk_reset(); + xosc32k_init(); osc32k_init(); dfll_init(); dpll_init(0, dfll_div * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); @@ -136,4 +166,13 @@ void soc_reset_hook(void) /* connect GCLK2 to 48 MHz DFLL for USB */ gclk_connect(2, GCLK_SOURCE_DFLL48M, 0); + + /* connect GCLK4 to xosc32k for RTC. The output is 1024 Hz*/ + gclk_connect(4, +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K + GCLK_SOURCE_XOSC32K, +#else + GCLK_SOURCE_OSCULP32K, +#endif + CONFIG_SOC_ATMEL_SAMD5X_OSC32K_PRESCALER); } diff --git a/soc/atmel/sam0/common/soc_saml2x.c b/soc/atmel/sam0/common/soc_saml2x.c index 3dd657a52f2251..88e694b6b21434 100644 --- a/soc/atmel/sam0/common/soc_saml2x.c +++ b/soc/atmel/sam0/common/soc_saml2x.c @@ -27,6 +27,7 @@ * GCLK Gen 1 -> DFLL48M (variable) * GCLK Gen 2 -> USB @ 48 MHz * GCLK Gen 3 -> ADC @ 24 MHz (further /2 in the ADC peripheral) + * GCLK Gen 4 -> RTC @ reserved */ static inline void gclk_reset(void) @@ -57,6 +58,7 @@ static inline void osc32k_init(void) | !OSC32KCTRL_OSC32K_ONDEMAND | OSC32KCTRL_OSC32K_RUNSTDBY | OSC32KCTRL_OSC32K_EN32K + | OSC32KCTRL_OSC32K_EN1K | OSC32KCTRL_OSC32K_ENABLE; /* wait for ready */ @@ -75,6 +77,7 @@ static inline void xosc32k_init(void) | !OSC32KCTRL_XOSC32K_ONDEMAND | OSC32KCTRL_XOSC32K_RUNSTDBY | OSC32KCTRL_XOSC32K_EN32K + | OSC32KCTRL_XOSC32K_EN1K #if CONFIG_SOC_ATMEL_SAML_XOSC32K_CRYSTAL | OSC32KCTRL_XOSC32K_XTALEN #endif From c4951b18a0e3645e5670943480ed5926800ac89d Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Sun, 17 Nov 2024 14:47:53 +0100 Subject: [PATCH 5/6] drivers: rtc: sam0: Add realtime clock driver Add Atmel sam0 rtc calendar driver. Signed-off-by: Gerson Fernando Budke --- drivers/rtc/CMakeLists.txt | 1 + drivers/rtc/Kconfig | 1 + drivers/rtc/Kconfig.sam0 | 10 + drivers/rtc/rtc_sam0.c | 637 ++++++++++++++++++ .../rtc/rtc_api/boards/samc21n_xpro.conf | 3 + .../rtc/rtc_api/boards/samd20_xpro.conf | 3 + .../rtc/rtc_api/boards/same54_xpro.conf | 3 + .../rtc/rtc_api/boards/saml21_xpro.conf | 3 + .../rtc/rtc_api/boards/samr21_xpro.conf | 3 + 9 files changed, 664 insertions(+) create mode 100644 drivers/rtc/Kconfig.sam0 create mode 100644 drivers/rtc/rtc_sam0.c create mode 100644 tests/drivers/rtc/rtc_api/boards/samc21n_xpro.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/samd20_xpro.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/same54_xpro.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/saml21_xpro.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/samr21_xpro.conf diff --git a/drivers/rtc/CMakeLists.txt b/drivers/rtc/CMakeLists.txt index 6b298b969b71c8..eab48049825929 100644 --- a/drivers/rtc/CMakeLists.txt +++ b/drivers/rtc/CMakeLists.txt @@ -22,6 +22,7 @@ zephyr_library_sources_ifdef(CONFIG_RTC_SHELL rtc_shell.c) zephyr_library_sources_ifdef(CONFIG_RTC_FAKE rtc_fake.c) zephyr_library_sources_ifdef(CONFIG_RTC_SMARTBOND rtc_smartbond.c) zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM rtc_sam.c) +zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM0 rtc_sam0.c) zephyr_library_sources_ifdef(CONFIG_RTC_RPI_PICO rtc_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_RTC_RV3028 rtc_rv3028.c) zephyr_library_sources_ifdef(CONFIG_RTC_NUMAKER rtc_numaker.c) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5dd3eaf1301b7a..2cb2046824b48b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -53,6 +53,7 @@ source "drivers/rtc/Kconfig.pcf8563" source "drivers/rtc/Kconfig.rpi_pico" source "drivers/rtc/Kconfig.rv3028" source "drivers/rtc/Kconfig.sam" +source "drivers/rtc/Kconfig.sam0" source "drivers/rtc/Kconfig.smartbond" source "drivers/rtc/Kconfig.stm32" source "drivers/rtc/Kconfig.numaker" diff --git a/drivers/rtc/Kconfig.sam0 b/drivers/rtc/Kconfig.sam0 new file mode 100644 index 00000000000000..2221fee0d883d2 --- /dev/null +++ b/drivers/rtc/Kconfig.sam0 @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +config RTC_ATMEL_SAM0 + bool "Atmel SAM RTC driver" + default y + depends on DT_HAS_ATMEL_SAM0_RTC_ENABLED \ + && !$(dt_nodelabel_bool_prop,rtc,systimer) + help + Atmel Real-Time Clock (RTC) driver used on SAM0 SoC series. diff --git a/drivers/rtc/rtc_sam0.c b/drivers/rtc/rtc_sam0.c new file mode 100644 index 00000000000000..8e559c556dc92a --- /dev/null +++ b/drivers/rtc/rtc_sam0.c @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2024 Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT atmel_sam0_rtc + +/** @file + * @brief RTC driver for Atmel SAM0 MCU family. + */ + +#include + +#include +#include +#include "rtc_utils.h" + +#include +LOG_MODULE_REGISTER(rtc_sam0, CONFIG_RTC_LOG_LEVEL); + +#define RTC_SAM0_TIME_MASK \ + (RTC_ALARM_TIME_MASK_SECOND \ + | RTC_ALARM_TIME_MASK_MINUTE \ + | RTC_ALARM_TIME_MASK_HOUR \ + | RTC_ALARM_TIME_MASK_MONTHDAY \ + | RTC_ALARM_TIME_MASK_MONTH \ + | RTC_ALARM_TIME_MASK_YEAR \ + ) + +#define RTC_SAM0_CALIBRATE_PPB_MAX (127) +#define RTC_SAM0_CALIBRATE_PPB_QUANTA (1000) + +enum rtc_sam0_counter_mode { + COUNTER_MODE_0, + COUNTER_MODE_1, + COUNTER_MODE_2, +}; + +struct rtc_sam0_config { + Rtc *regs; + enum rtc_sam0_counter_mode mode; + uint16_t prescaler; + + volatile uint32_t *mclk; + uint32_t mclk_mask; + uint32_t gclk_gen; + uint16_t gclk_id; + bool has_gclk; + bool has_osc32kctrl; + uint8_t osc32_src; + uint32_t evt_ctrl_msk; + +#ifdef CONFIG_RTC_ALARM + uint8_t alarms_count; +#endif /* CONFIG_RTC_ALARM */ +#ifdef CONFIG_RTC_CALIBRATION + int32_t cal_constant; +#endif +}; + +struct rtc_sam0_data_cb { + rtc_alarm_callback cb; + void *cb_data; +}; + +struct rtc_sam0_data { + struct k_spinlock lock; +#ifdef CONFIG_RTC_ALARM + struct rtc_sam0_data_cb *const alarms; +#endif /* CONFIG_RTC_ALARM */ +}; + +static inline void rtc_sam0_sync(Rtc *rtc) +{ + /* Wait for synchronization */ +#ifdef MCLK + while (rtc->MODE0.SYNCBUSY.reg & RTC_MODE0_SYNCBUSY_MASK) { + } +#else + while (rtc->MODE0.STATUS.reg & RTC_STATUS_SYNCBUSY) { + } +#endif +} + +static int rtc_sam0_set_time(const struct device *dev, const struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + uint32_t datetime = 0; + + if (rtc_utils_validate_rtc_time(timeptr, RTC_SAM0_TIME_MASK) == false) { + return -EINVAL; + } + + datetime |= RTC_MODE2_CLOCK_SECOND(timeptr->tm_sec); + datetime |= RTC_MODE2_CLOCK_MINUTE(timeptr->tm_min); + datetime |= RTC_MODE2_CLOCK_HOUR(timeptr->tm_hour); + datetime |= RTC_MODE2_CLOCK_DAY(timeptr->tm_mday); + datetime |= RTC_MODE2_CLOCK_MONTH(timeptr->tm_mon + 1); + datetime |= RTC_MODE2_CLOCK_YEAR(timeptr->tm_year - 99); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + +#ifdef MCLK + regs->CTRLA.reg &= ~RTC_MODE0_CTRLA_ENABLE; + rtc_sam0_sync(cfg->regs); + regs->CLOCK.reg = datetime; + regs->CTRLA.reg |= RTC_MODE0_CTRLA_ENABLE; +#else + regs->CTRL.reg &= ~RTC_MODE0_CTRL_ENABLE; + rtc_sam0_sync(cfg->regs); + regs->CLOCK.reg = datetime; + regs->CTRL.reg |= RTC_MODE0_CTRL_ENABLE; +#endif + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rtc_sam0_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + RTC_MODE2_CLOCK_Type calendar = cfg->regs->MODE2.CLOCK; + + timeptr->tm_sec = calendar.bit.SECOND; + timeptr->tm_min = calendar.bit.MINUTE; + timeptr->tm_hour = calendar.bit.HOUR; + timeptr->tm_mday = calendar.bit.DAY; + timeptr->tm_mon = calendar.bit.MONTH - 1; + timeptr->tm_year = calendar.bit.YEAR + 99; + timeptr->tm_wday = -1; + timeptr->tm_yday = -1; + timeptr->tm_isdst = -1; + timeptr->tm_nsec = 0; + + LOG_DBG("D/M/Y H:M:S %02d/%02d/%02d %02d:%02d:%02d", + timeptr->tm_mday, timeptr->tm_mon + 1, timeptr->tm_year - 99, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + + return 0; +} + +#ifdef CONFIG_RTC_ALARM +static uint32_t rtc_sam0_datetime_from_tm(const struct rtc_time *timeptr, uint32_t mask) +{ + uint32_t datetime = 0; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + datetime |= RTC_MODE2_CLOCK_SECOND(timeptr->tm_sec); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + datetime |= RTC_MODE2_CLOCK_MINUTE(timeptr->tm_min); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + datetime |= RTC_MODE2_CLOCK_HOUR(timeptr->tm_hour); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + datetime |= RTC_MODE2_CLOCK_DAY(timeptr->tm_mday); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + datetime |= RTC_MODE2_CLOCK_MONTH(timeptr->tm_mon + 1); + } + + if (mask & RTC_ALARM_TIME_MASK_YEAR) { + datetime |= RTC_MODE2_CLOCK_YEAR(timeptr->tm_year - 99); + } + + return datetime; +} + +static void rtc_sam0_tm_from_datetime(struct rtc_time *timeptr, uint32_t mask, + RTC_MODE2_ALARM_Type calendar) +{ + memset(timeptr, 0x00, sizeof(struct rtc_time)); + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + timeptr->tm_sec = calendar.bit.SECOND; + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + timeptr->tm_min = calendar.bit.MINUTE; + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + timeptr->tm_hour = calendar.bit.HOUR; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + timeptr->tm_mday = calendar.bit.DAY; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + timeptr->tm_mon = calendar.bit.MONTH - 1; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + timeptr->tm_year = calendar.bit.YEAR + 99; + } + + timeptr->tm_wday = -1; + timeptr->tm_yday = -1; + timeptr->tm_isdst = -1; + timeptr->tm_nsec = 0; +} + +static uint32_t rtc_sam0_alarm_msk_from_mask(uint32_t mask) +{ + uint32_t alarm_mask = 0; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + alarm_mask = RTC_MODE2_MASK_SEL_SS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + alarm_mask = RTC_MODE2_MASK_SEL_MMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + alarm_mask = RTC_MODE2_MASK_SEL_HHMMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + alarm_mask = RTC_MODE2_MASK_SEL_DDHHMMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + alarm_mask = RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_YEAR) { + alarm_mask = RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val; + } + + return alarm_mask; +} + +static uint32_t rtc_sam0_mask_from_alarm_msk(uint32_t alarm_mask) +{ + uint32_t mask = 0; + + switch (alarm_mask) { + case RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_YEAR; + case RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_MONTH; + case RTC_MODE2_MASK_SEL_DDHHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + case RTC_MODE2_MASK_SEL_HHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_HOUR; + case RTC_MODE2_MASK_SEL_MMSS_Val: + mask |= RTC_ALARM_TIME_MASK_MINUTE; + case RTC_MODE2_MASK_SEL_SS_Val: + mask |= RTC_ALARM_TIME_MASK_SECOND; + } + + return mask; +} + +static int rtc_sam0_alarm_get_supported_fields(const struct device *dev, uint16_t id, + uint16_t *mask) +{ + ARG_UNUSED(dev); + ARG_UNUSED(id); + + *mask = RTC_SAM0_TIME_MASK; + + return 0; +} + +static int rtc_sam0_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + uint32_t mask_supported = RTC_SAM0_TIME_MASK; + uint32_t datetime; + uint32_t alarm_msk; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + if ((mask > 0) && (timeptr == NULL)) { + return -EINVAL; + } + + if (mask & ~mask_supported) { + return -EINVAL; + } + + if (rtc_utils_validate_rtc_time(timeptr, mask) == false) { + return -EINVAL; + } + + datetime = rtc_sam0_datetime_from_tm(timeptr, mask); + alarm_msk = rtc_sam0_alarm_msk_from_mask(mask); + + LOG_INF("S: datetime: %d, mask: %d", datetime, alarm_msk); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + irq_disable(DT_INST_IRQN(0)); + + rtc_sam0_sync(cfg->regs); + regs->Mode2Alarm[id].ALARM.reg = datetime; + regs->Mode2Alarm[id].MASK.reg = RTC_MODE2_MASK_SEL(alarm_msk); + regs->INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM(BIT(id)); + + irq_enable(DT_INST_IRQN(0)); + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rtc_sam0_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + RTC_MODE2_ALARM_Type datetime; + uint32_t alarm_msk; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + if ((mask == NULL) || (timeptr == NULL)) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + rtc_sam0_sync(cfg->regs); + + datetime = regs->Mode2Alarm[id].ALARM; + alarm_msk = regs->Mode2Alarm[id].MASK.reg; + + LOG_INF("G: datetime: %d, mask: %d", datetime.reg, alarm_msk); + + k_spin_unlock(&data->lock, key); + + *mask = rtc_sam0_mask_from_alarm_msk(alarm_msk); + + rtc_sam0_tm_from_datetime(timeptr, *mask, datetime); + + return 0; +} + +static int rtc_sam0_alarm_is_pending(const struct device *dev, uint16_t id) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if ((regs->INTFLAG.reg & RTC_MODE2_INTFLAG_ALARM(BIT(id))) == 0) { + k_spin_unlock(&data->lock, key); + + return 0; + } + + regs->INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM(BIT(id)); + + k_spin_unlock(&data->lock, key); + + return 1; +} + +static int rtc_sam0_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + irq_disable(DT_INST_IRQN(0)); + + data->alarms[id].cb = callback; + data->alarms[id].cb_data = user_data; + + if (callback) { + regs->INTENSET.reg = RTC_MODE2_INTENSET_ALARM(BIT(id)); + } else { + regs->INTENCLR.reg = RTC_MODE2_INTENCLR_ALARM(BIT(id)); + } + + irq_enable(DT_INST_IRQN(0)); + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static void rtc_sam0_isr(const struct device *dev) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + uint32_t int_flags = regs->INTFLAG.reg; + + for (int i = 0; i < cfg->alarms_count; ++i) { + if (int_flags & RTC_MODE2_INTFLAG_ALARM(BIT(i))) { + if (data->alarms[i].cb != NULL) { + data->alarms[i].cb(dev, i, data->alarms[i].cb_data); + } + } + } + + regs->INTFLAG.reg |= int_flags; +} + +#endif /* CONFIG_RTC_ALARM */ + +#ifdef CONFIG_RTC_CALIBRATION +static int rtc_sam0_set_calibration(const struct device *dev, int32_t calibration) +{ + const struct rtc_sam0_config *cfg = dev->config; + RtcMode2 *regs = &cfg->regs->MODE2; + int32_t correction = (int32_t)((float)cfg->cal_constant + * (float)calibration + * (float)1e-9) + ; + uint32_t abs_correction = abs(correction); + + LOG_DBG("Correction: %d, Absolute: %d, Calibration: %d", + correction, abs_correction, calibration); + + if (abs_correction == 0) { + regs->FREQCORR.reg = 0; + return 0; + } + + if (abs_correction > RTC_SAM0_CALIBRATE_PPB_MAX) { + LOG_ERR("The calibration %d result in an out of range value %d", + calibration, abs_correction); + return -EINVAL; + } + + rtc_sam0_sync(cfg->regs); + regs->FREQCORR.reg = RTC_FREQCORR_VALUE(abs_correction) + | (correction < 0 ? RTC_FREQCORR_SIGN : 0) + ; + + LOG_DBG("W REG: 0x%02x", regs->FREQCORR.reg); + + return 0; +} + +static int rtc_sam0_get_calibration(const struct device *dev, int32_t *calibration) +{ + const struct rtc_sam0_config *cfg = dev->config; + RtcMode2 *regs = &cfg->regs->MODE2; + int32_t correction; + + if (calibration == NULL) { + return -EINVAL; + } + + correction = regs->FREQCORR.bit.VALUE; + + if (correction == 0) { + *calibration = 0; + } else { + *calibration = (correction * 1e9) / cfg->cal_constant; + } + + if (regs->FREQCORR.bit.SIGN) { + *calibration *= -1; + } + + LOG_DBG("R REG: 0x%02x", regs->FREQCORR.reg); + + return 0; +} +#endif /* CONFIG_RTC_CALIBRATION */ + +static int rtc_sam0_init(const struct device *dev) +{ + const struct rtc_sam0_config *cfg = dev->config; + RtcMode0 *regs = &cfg->regs->MODE0; + + LOG_DBG("Counter Mode %d selected", cfg->mode); + LOG_DBG("gclk_id: %d, gclk_gen: %d, prescaler: %d, osc32k: %d", + cfg->gclk_id, cfg->gclk_gen, cfg->prescaler, cfg->osc32_src); + + *cfg->mclk |= cfg->mclk_mask; + +#ifdef MCLK + if (cfg->has_gclk) { + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; + } +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; +#endif + rtc_sam0_sync(cfg->regs); + +#ifdef MCLK + if (cfg->has_osc32kctrl) { + OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL(cfg->osc32_src); + } +#endif + + rtc_sam0_sync(cfg->regs); + regs->EVCTRL.reg = (cfg->evt_ctrl_msk & RTC_MODE0_EVCTRL_MASK); + +#ifdef MCLK + regs->CTRLA.reg = RTC_MODE0_CTRLA_ENABLE + | RTC_MODE0_CTRLA_COUNTSYNC + | RTC_MODE0_CTRLA_MODE(cfg->mode) + | RTC_MODE0_CTRLA_PRESCALER(cfg->prescaler + 1) + ; +#else + regs->CTRL.reg = RTC_MODE0_CTRL_ENABLE + | RTC_MODE0_CTRL_MODE(cfg->mode) + | RTC_MODE0_CTRL_PRESCALER(cfg->prescaler) + ; +#endif + + regs->INTFLAG.reg = 0; +#ifdef CONFIG_RTC_ALARM + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + rtc_sam0_isr, + DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_INST_IRQN(0)); +#endif + return 0; +} + +static const struct rtc_driver_api rtc_sam0_driver_api = { + .set_time = rtc_sam0_set_time, + .get_time = rtc_sam0_get_time, +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = rtc_sam0_alarm_get_supported_fields, + .alarm_set_time = rtc_sam0_alarm_set_time, + .alarm_get_time = rtc_sam0_alarm_get_time, + .alarm_is_pending = rtc_sam0_alarm_is_pending, + .alarm_set_callback = rtc_sam0_alarm_set_callback, +#endif /* CONFIG_RTC_ALARM */ +#ifdef CONFIG_RTC_CALIBRATION + .set_calibration = rtc_sam0_set_calibration, + .get_calibration = rtc_sam0_get_calibration, +#endif /* CONFIG_RTC_CALIBRATION */ +}; + +#define RTC_SAM0_GCLK(n) \ + COND_CODE_1(DT_INST_CLOCKS_HAS_NAME(n, gclk), \ + ( \ + .has_gclk = true, \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id) \ + ), \ + ( \ + .has_gclk = false, \ + .gclk_gen = 0, \ + .gclk_id = 0 \ + )) + +#define RTC_SAM0_OSC32KCTRL(n) \ + COND_CODE_1(DT_INST_CLOCKS_HAS_NAME(n, osc32kctrl), \ + ( \ + .has_osc32kctrl = true, \ + .osc32_src = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, osc32kctrl, src) \ + ), \ + ( \ + .has_osc32kctrl = false, \ + .osc32_src = 0 \ + )) + +#define RTC_SAM0_DEVICE(n) \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(n, counter_mode), \ + "sam0:rtc: Missing counter-mode devicetree property"); \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(n, prescaler), \ + "sam0:rtc: Missing prescaler devicetree property"); \ + \ + static const struct rtc_sam0_config rtc_sam0_config_##n = { \ + .regs = (Rtc *)DT_INST_REG_ADDR(n), \ + .mode = DT_INST_ENUM_IDX(n, counter_mode), \ + .prescaler = DT_INST_ENUM_IDX(n, prescaler), \ + .evt_ctrl_msk = DT_INST_PROP(n, event_control_msk), \ + RTC_SAM0_GCLK(n), \ + RTC_SAM0_OSC32KCTRL(n), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + IF_ENABLED(CONFIG_RTC_ALARM, ( \ + .alarms_count = DT_INST_PROP(n, alarms_count), \ + )) \ + IF_ENABLED(CONFIG_RTC_CALIBRATION, ( \ + .cal_constant = DT_INST_PROP(n, cal_constant), \ + )) \ + }; \ + \ + IF_ENABLED(CONFIG_RTC_ALARM, ( \ + static struct rtc_sam0_data_cb \ + rtc_sam0_data_cb_##n[DT_INST_PROP(n, alarms_count)] = {}; \ + )) \ + \ + static struct rtc_sam0_data rtc_sam0_data_##n = { \ + IF_ENABLED(CONFIG_RTC_ALARM, ( \ + .alarms = rtc_sam0_data_cb_##n, \ + )) \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, rtc_sam0_init, \ + NULL, \ + &rtc_sam0_data_##n, \ + &rtc_sam0_config_##n, POST_KERNEL, \ + CONFIG_RTC_INIT_PRIORITY, \ + &rtc_sam0_driver_api); \ + +DT_INST_FOREACH_STATUS_OKAY(RTC_SAM0_DEVICE); diff --git a/tests/drivers/rtc/rtc_api/boards/samc21n_xpro.conf b/tests/drivers/rtc/rtc_api/boards/samc21n_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/samc21n_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/samd20_xpro.conf b/tests/drivers/rtc/rtc_api/boards/samd20_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/samd20_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/same54_xpro.conf b/tests/drivers/rtc/rtc_api/boards/same54_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/same54_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/saml21_xpro.conf b/tests/drivers/rtc/rtc_api/boards/saml21_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/saml21_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/samr21_xpro.conf b/tests/drivers/rtc/rtc_api/boards/samr21_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/samr21_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y From 8ce6005dfd7df2916bcfdd9894561b0fdd734804 Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Sun, 17 Nov 2024 14:48:32 +0100 Subject: [PATCH 6/6] boards: atmel: sam0: Add rtc configs Add configurations to allow use of RTC driver and tests. Signed-off-by: Gerson Fernando Budke --- boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts | 8 ++++++++ boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml | 1 + boards/atmel/sam0/samd20_xpro/samd20_xpro.dts | 6 ++++++ boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml | 1 + boards/atmel/sam0/samd21_xpro/samd21_xpro.dts | 6 ++++++ boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml | 1 + boards/atmel/sam0/same54_xpro/same54_xpro.dts | 8 ++++++++ boards/atmel/sam0/same54_xpro/same54_xpro.yaml | 1 + boards/atmel/sam0/saml21_xpro/saml21_xpro.dts | 8 ++++++++ boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml | 1 + boards/atmel/sam0/samr21_xpro/samr21_xpro.dts | 6 ++++++ boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml | 1 + boards/atmel/sam0/samr34_xpro/samr34_xpro.dts | 8 ++++++++ boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml | 1 + 14 files changed, 57 insertions(+) diff --git a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts index 3827dc104d993c..006a588ad77a02 100644 --- a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts +++ b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts @@ -82,6 +82,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml index 428d79e1110643..64d075fa29740e 100644 --- a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml +++ b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml @@ -18,6 +18,7 @@ supported: - gpio - i2c - pwm + - rtc - spi - uart vendor: atmel diff --git a/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts b/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts index 83f5df99c05a2e..59e890b328ba67 100644 --- a/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts +++ b/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts @@ -51,6 +51,12 @@ clock-frequency = ; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-spi"; diff --git a/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml b/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml index 548bd6c462a885..4c9558124e7ed6 100644 --- a/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml +++ b/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml @@ -13,6 +13,7 @@ supported: - flash - gpio - i2c + - rtc - spi - uart - watchdog diff --git a/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts b/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts index f390bc106de9a9..74a496b392af5b 100644 --- a/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts +++ b/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts @@ -71,6 +71,12 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml index c41c94432857c6..c5cc5de6726da6 100644 --- a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml +++ b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml @@ -18,6 +18,7 @@ supported: - gpio - i2c - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/same54_xpro/same54_xpro.dts b/boards/atmel/sam0/same54_xpro/same54_xpro.dts index f8d957727cd4d5..2666c055dc7b48 100644 --- a/boards/atmel/sam0/same54_xpro/same54_xpro.dts +++ b/boards/atmel/sam0/same54_xpro/same54_xpro.dts @@ -68,6 +68,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom2 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/same54_xpro/same54_xpro.yaml b/boards/atmel/sam0/same54_xpro/same54_xpro.yaml index 1cddeeaf7ad9d5..27bb5f475064ae 100644 --- a/boards/atmel/sam0/same54_xpro/same54_xpro.yaml +++ b/boards/atmel/sam0/same54_xpro/same54_xpro.yaml @@ -18,6 +18,7 @@ supported: - i2c - netif:eth - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts b/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts index c0e0e43d666ba3..65f4b0c8531b80 100644 --- a/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts +++ b/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts @@ -71,6 +71,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-spi"; diff --git a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml index be39f0dc5173ec..b92484160db0aa 100644 --- a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml +++ b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml @@ -18,6 +18,7 @@ supported: - gpio - i2c - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts b/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts index 01ed0e8826ce38..5f553d24e7a9c6 100644 --- a/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts +++ b/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts @@ -116,6 +116,12 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml b/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml index 25ce756d667c9c..ebc4edc5aa2ed8 100644 --- a/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml +++ b/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml @@ -18,6 +18,7 @@ supported: - i2c - netif - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts b/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts index 964cd8af4dfc9f..cea5d539eda3d7 100644 --- a/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts +++ b/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts @@ -71,6 +71,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml index 488fba3bb324e9..0b88aec5649b06 100644 --- a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml +++ b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml @@ -18,6 +18,7 @@ supported: - gpio - i2c - pwm + - rtc - spi - uart - usb_device