From 233871d3b87f3ebad8bcfcb88ba877d56ca95a01 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Tue, 15 Jul 2025 09:47:08 +0800 Subject: [PATCH 1/9] west.yml: Update west.yml for Microchip sama7d65 hal Update west.yml for Microchip SAMA7D65 HAL. Signed-off-by: Tony Han --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 3634554334c3a..32a0f00aa4d83 100644 --- a/west.yml +++ b/west.yml @@ -195,7 +195,7 @@ manifest: groups: - hal - name: hal_microchip - revision: 32a79d481c056b2204a5701d5a5799f9e5130dd7 + revision: 0f72d7573468cc32f6baeebaa92fd04bebf7346a path: modules/hal/microchip groups: - hal From 680ebad8705240341c5a36d23cdc855bbc7ba1c8 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Thu, 3 Jul 2025 13:13:39 +0800 Subject: [PATCH 2/9] soc: microchip: sam: optimize clock name for sama75 programmable clock Change the location of the names for programable clocks from the stack to "static struct clk_programmable" array. Signed-off-by: Tony Han --- soc/microchip/sam/common/clk-programmable.c | 7 +++++-- soc/microchip/sam/common/pmc.h | 2 +- soc/microchip/sam/common/sama7g5.c | 7 +------ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/soc/microchip/sam/common/clk-programmable.c b/soc/microchip/sam/common/clk-programmable.c index fb17512c2e1a6..bbac3badb4c0a 100644 --- a/soc/microchip/sam/common/clk-programmable.c +++ b/soc/microchip/sam/common/clk-programmable.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -25,6 +26,7 @@ struct clk_programmable { uint8_t num_parents; uint8_t parent; const struct clk_programmable_layout *layout; + char name[8]; }; #define to_clk_programmable(ptr) CONTAINER_OF(ptr, struct clk_programmable, clk) @@ -79,7 +81,7 @@ static DEVICE_API(clock_control, programmable_api) = { .get_rate = clk_programmable_get_rate, }; -int clk_register_programmable(pmc_registers_t *const pmc, const char *name, +int clk_register_programmable(pmc_registers_t *const pmc, const struct device **parents, uint8_t num_parents, uint8_t id, const struct clk_programmable_layout *layout, @@ -102,9 +104,10 @@ int clk_register_programmable(pmc_registers_t *const pmc, const char *name, } memcpy(prog->parents, parents, sizeof(struct device *) * num_parents); + snprintf(prog->name, sizeof(prog->name), "prog%d", id); *clk = &prog->clk; - (*clk)->name = name; + (*clk)->name = prog->name; (*clk)->api = &programmable_api; prog->num_parents = num_parents; prog->id = id; diff --git a/soc/microchip/sam/common/pmc.h b/soc/microchip/sam/common/pmc.h index a46238f509ed1..e9127cbca743b 100644 --- a/soc/microchip/sam/common/pmc.h +++ b/soc/microchip/sam/common/pmc.h @@ -168,7 +168,7 @@ int sam9x60_clk_register_frac_pll(pmc_registers_t *const pmc, struct k_spinlock const struct clk_pll_characteristics *characteristics, const struct clk_pll_layout *layout, struct device **clk); -int clk_register_programmable(pmc_registers_t *const pmc, const char *name, +int clk_register_programmable(pmc_registers_t *const pmc, const struct device **parents, uint8_t num_parents, uint8_t id, const struct clk_programmable_layout *layout, diff --git a/soc/microchip/sam/common/sama7g5.c b/soc/microchip/sam/common/sama7g5.c index dbcb0a07d096e..1bf28fe1f882d 100644 --- a/soc/microchip/sam/common/sama7g5.c +++ b/soc/microchip/sam/common/sama7g5.c @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -1154,11 +1153,7 @@ void sam_pmc_setup(const struct device *dev) parents[7] = sama7g5_plls[PLL_ID_AUDIO][PLL_COMPID_DIV0].clk; parents[8] = sama7g5_plls[PLL_ID_ETH][PLL_COMPID_DIV0].clk; for (i = 0; i < 8; i++) { - char name[6]; - - snprintf(name, sizeof(name), "prog%d", i); - - ret = clk_register_programmable(regmap, name, parents, + ret = clk_register_programmable(regmap, parents, 9, i, &programmable_layout, sama7g5_prog_mux_table, &clk); From 6b8caa839e560b557a3e2fe9f8d1767875ed56dc Mon Sep 17 00:00:00 2001 From: Tony Han Date: Thu, 3 Jul 2025 13:39:04 +0800 Subject: [PATCH 3/9] soc: microchip: sam: optimize array size for sama7g5 registered clocks Replace the array size for sama7g5 registered clocks with macros and put the macros to soc.h with descriptions. Signed-off-by: Tony Han --- soc/microchip/sam/common/clk-generated.c | 2 +- soc/microchip/sam/common/clk-master.c | 4 ++-- soc/microchip/sam/common/clk-peripheral.c | 2 +- soc/microchip/sam/common/clk-sam9x60-pll.c | 6 +++--- soc/microchip/sam/common/clk-system.c | 2 +- soc/microchip/sam/sama7g5/soc.h | 9 +++++++++ 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/soc/microchip/sam/common/clk-generated.c b/soc/microchip/sam/common/clk-generated.c index e8452cc6bd6e4..4c6c5ae201046 100644 --- a/soc/microchip/sam/common/clk-generated.c +++ b/soc/microchip/sam/common/clk-generated.c @@ -29,7 +29,7 @@ struct clk_generated { #define to_clk_generated(ptr) CONTAINER_OF(ptr, struct clk_generated, clk) -static struct clk_generated clocks_gck[ID_PERIPH_MAX]; +static struct clk_generated clocks_gck[SOC_NUM_CLOCK_GENERATED]; static uint32_t clocks_gck_idx; static int clk_generated_on(const struct device *dev, clock_control_subsys_t sys) diff --git a/soc/microchip/sam/common/clk-master.c b/soc/microchip/sam/common/clk-master.c index f721ea466a03b..a56099a4e97eb 100644 --- a/soc/microchip/sam/common/clk-master.c +++ b/soc/microchip/sam/common/clk-master.c @@ -19,7 +19,7 @@ LOG_MODULE_REGISTER(clk_mck, CONFIG_CLOCK_CONTROL_LOG_LEVEL); #define PMC_MCR_CSS_SHIFT 16 -#define MASTER_MAX_ID 4 +#define MASTER_MAX_ID (SOC_NUM_CLOCK_MASTER - 1) #define to_clk_master(ptr) CONTAINER_OF(ptr, struct clk_master, clk) @@ -38,7 +38,7 @@ struct clk_master { uint8_t div; }; -static struct clk_master clocks_master[5]; +static struct clk_master clocks_master[SOC_NUM_CLOCK_MASTER]; static uint32_t clocks_master_idx; static inline bool clk_master_ready(struct clk_master *master) diff --git a/soc/microchip/sam/common/clk-peripheral.c b/soc/microchip/sam/common/clk-peripheral.c index 2fdc1117d340f..094c37d613c69 100644 --- a/soc/microchip/sam/common/clk-peripheral.c +++ b/soc/microchip/sam/common/clk-peripheral.c @@ -25,7 +25,7 @@ struct clk_peripheral { const struct clk_pcr_layout *layout; }; -static struct clk_peripheral clocks_periph[72]; +static struct clk_peripheral clocks_periph[SOC_NUM_CLOCK_PERIPHERAL]; static uint32_t clocks_periph_idx; #define to_clk_peripheral(ptr) CONTAINER_OF(ptr, struct clk_peripheral, clk) diff --git a/soc/microchip/sam/common/clk-sam9x60-pll.c b/soc/microchip/sam/common/clk-sam9x60-pll.c index 0a3a00d50a792..bd3d65d100200 100644 --- a/soc/microchip/sam/common/clk-sam9x60-pll.c +++ b/soc/microchip/sam/common/clk-sam9x60-pll.c @@ -46,7 +46,7 @@ LOG_MODULE_REGISTER(clk_pll, CONFIG_CLOCK_CONTROL_LOG_LEVEL); q * n_ + r * n_ / d_; \ }) -#define PLL_MAX_ID 7 +#define PLL_MAX_ID SOC_NUM_CLOCK_PLL_FRAC struct sam9x60_pll_core { pmc_registers_t *pmc; @@ -73,10 +73,10 @@ struct sam9x60_div { #define to_sam9x60_frac(ptr) CONTAINER_OF(ptr, struct sam9x60_frac, core) #define to_sam9x60_div(ptr) CONTAINER_OF(ptr, struct sam9x60_div, core) -static struct sam9x60_frac clocks_frac[7]; +static struct sam9x60_frac clocks_frac[SOC_NUM_CLOCK_PLL_FRAC]; static uint32_t clocks_frac_idx; -static struct sam9x60_div clocks_div[8]; +static struct sam9x60_div clocks_div[SOC_NUM_CLOCK_PLL_DIV]; static uint32_t clocks_div_idx; static inline bool sam9x60_pll_ready(pmc_registers_t *pmc, int id) diff --git a/soc/microchip/sam/common/clk-system.c b/soc/microchip/sam/common/clk-system.c index 453408a31935c..d300a8ce66a7d 100644 --- a/soc/microchip/sam/common/clk-system.c +++ b/soc/microchip/sam/common/clk-system.c @@ -25,7 +25,7 @@ struct clk_system { uint8_t id; }; -static struct clk_system clocks_sys[8]; +static struct clk_system clocks_sys[SOC_NUM_CLOCK_SYSTEM]; static uint32_t clocks_sys_idx; static inline int is_pck(int id) diff --git a/soc/microchip/sam/sama7g5/soc.h b/soc/microchip/sam/sama7g5/soc.h index cdacd1592f9d4..bc2c93b57e1e7 100644 --- a/soc/microchip/sam/sama7g5/soc.h +++ b/soc/microchip/sam/sama7g5/soc.h @@ -13,4 +13,13 @@ #include "sam.h" +/* number of clocks registered */ +#define SOC_NUM_CLOCK_PLL_FRAC 7 +#define SOC_NUM_CLOCK_PLL_DIV (SOC_NUM_CLOCK_PLL_FRAC + 1) /* AUDIO PLL: DIVPMC, DIVIO */ +#define SOC_NUM_CLOCK_MASTER 5 /* MCK 0 ~ 4 */ +#define SOC_NUM_CLOCK_PROGRAMMABLE 8 /* MCK 0 ~ 7 */ +#define SOC_NUM_CLOCK_SYSTEM 8 /* PCK 0 ~ 7 */ +#define SOC_NUM_CLOCK_PERIPHERAL 72 +#define SOC_NUM_CLOCK_GENERATED 46 + #endif /* __SAMA7G5_SOC__H_ */ From 1b7fa70c6a4f6bc01964295f26d76695d7a7c392 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Mon, 30 Jun 2025 17:18:39 +0800 Subject: [PATCH 4/9] soc: microchip: add new soc sama7d65 Product URL: https://www.microchip.com/en-us/product/SAMA7D65 Signed-off-by: Tony Han --- soc/microchip/sam/Kconfig | 5 ++ soc/microchip/sam/sama7d6/CMakeLists.txt | 9 +++ soc/microchip/sam/sama7d6/Kconfig.defconfig | 17 ++++++ soc/microchip/sam/sama7d6/Kconfig.soc | 15 +++++ .../sam/sama7d6/Kconfig.soc.sama7d65 | 11 ++++ soc/microchip/sam/sama7d6/soc.c | 56 +++++++++++++++++++ soc/microchip/sam/sama7d6/soc.h | 25 +++++++++ soc/microchip/sam/soc.yml | 3 + 8 files changed, 141 insertions(+) create mode 100644 soc/microchip/sam/sama7d6/CMakeLists.txt create mode 100644 soc/microchip/sam/sama7d6/Kconfig.defconfig create mode 100644 soc/microchip/sam/sama7d6/Kconfig.soc create mode 100644 soc/microchip/sam/sama7d6/Kconfig.soc.sama7d65 create mode 100644 soc/microchip/sam/sama7d6/soc.c create mode 100644 soc/microchip/sam/sama7d6/soc.h diff --git a/soc/microchip/sam/Kconfig b/soc/microchip/sam/Kconfig index 2f5bd7b320dfc..67a7dbef40237 100644 --- a/soc/microchip/sam/Kconfig +++ b/soc/microchip/sam/Kconfig @@ -3,6 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 # +config SOC_SERIES_SAMA7D6 + select ARM + select CPU_CORTEX_A7 + select SOC_EARLY_INIT_HOOK + config SOC_SERIES_SAMA7G5 select ARM select CPU_CORTEX_A7 diff --git a/soc/microchip/sam/sama7d6/CMakeLists.txt b/soc/microchip/sam/sama7d6/CMakeLists.txt new file mode 100644 index 0000000000000..8d91aceb1f3a8 --- /dev/null +++ b/soc/microchip/sam/sama7d6/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_sources(soc.c) +zephyr_include_directories(.) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/microchip/sam/sama7d6/Kconfig.defconfig b/soc/microchip/sam/sama7d6/Kconfig.defconfig new file mode 100644 index 0000000000000..ead3911c72cdd --- /dev/null +++ b/soc/microchip/sam/sama7d6/Kconfig.defconfig @@ -0,0 +1,17 @@ +# Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries +# +# SPDX-License-Identifier: Apache-2.0 +# + +if SOC_SERIES_SAMA7D6 + +config NUM_IRQS + default 189 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/soc/timer@e1800000,clock-frequency) + +config MMU + default y + +endif # SOC_SERIES_SAMA7D6 diff --git a/soc/microchip/sam/sama7d6/Kconfig.soc b/soc/microchip/sam/sama7d6/Kconfig.soc new file mode 100644 index 0000000000000..df6cb8ffc4e87 --- /dev/null +++ b/soc/microchip/sam/sama7d6/Kconfig.soc @@ -0,0 +1,15 @@ +# Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries +# +# SPDX-License-Identifier: Apache-2.0 +# + +config SOC_SERIES_SAMA7D6 + bool + select SOC_FAMILY_MICROCHIP_SAM + help + Enable support for Microchip SAM Microprocessors. + +config SOC_SERIES + default "sama7d6" if SOC_SERIES_SAMA7D6 + +rsource "Kconfig.soc.sam*" diff --git a/soc/microchip/sam/sama7d6/Kconfig.soc.sama7d65 b/soc/microchip/sam/sama7d6/Kconfig.soc.sama7d65 new file mode 100644 index 0000000000000..3fc0616ea77cb --- /dev/null +++ b/soc/microchip/sam/sama7d6/Kconfig.soc.sama7d65 @@ -0,0 +1,11 @@ +# Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries +# +# SPDX-License-Identifier: Apache-2.0 +# + +config SOC_SAMA7D65 + bool + select SOC_SERIES_SAMA7D6 + +config SOC + default "sama7d65" if SOC_SAMA7D65 diff --git a/soc/microchip/sam/sama7d6/soc.c b/soc/microchip/sam/sama7d6/soc.c new file mode 100644 index 0000000000000..39339f362ba67 --- /dev/null +++ b/soc/microchip/sam/sama7d6/soc.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include +#include +#include + +#define MMU_REGION_FLEXCOM_DEFN(idx, n) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flx##n)), \ + (MMU_REGION_FLAT_ENTRY("flexcom"#n, FLEXCOM##n##_BASE_ADDRESS, 0x4000, \ + MT_STRONGLY_ORDERED | MPERM_R | MPERM_W),), \ + ()) + +static const struct arm_mmu_region mmu_regions[] = { + MMU_REGION_FLAT_ENTRY("vectors", CONFIG_KERNEL_VM_BASE, 0x1000, + MT_STRONGLY_ORDERED | MPERM_R | MPERM_X), + + FOR_EACH_IDX(MMU_REGION_FLEXCOM_DEFN, (), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + + MMU_REGION_FLAT_ENTRY("gic", GIC_DISTRIBUTOR_BASE, 0x1100, + MT_STRONGLY_ORDERED | MPERM_R | MPERM_W), + + MMU_REGION_FLAT_ENTRY("pioa", PIO_BASE_ADDRESS, 0x4000, + MT_STRONGLY_ORDERED | MPERM_R | MPERM_W), + + MMU_REGION_FLAT_ENTRY("pit64b0", PIT64B0_BASE_ADDRESS, 0x4000, + MT_STRONGLY_ORDERED | MPERM_R | MPERM_W), + + MMU_REGION_FLAT_ENTRY("pmc", PMC_BASE_ADDRESS, 0x200, + MT_STRONGLY_ORDERED | MPERM_R | MPERM_W), + + MMU_REGION_FLAT_ENTRY("sckc", SCKC_BASE_ADDRESS, 0x4, + MT_STRONGLY_ORDERED | MPERM_R | MPERM_W), +}; + +const struct arm_mmu_config mmu_config = { + .num_regions = ARRAY_SIZE(mmu_regions), + .mmu_regions = mmu_regions, +}; + +void relocate_vector_table(void) +{ + write_vbar(CONFIG_KERNEL_VM_BASE); +} + +void soc_early_init_hook(void) +{ + /* Enable Generic clock for PIT64B0 for system tick */ + PMC_REGS->PMC_PCR = PMC_PCR_CMD(1) | PMC_PCR_GCLKEN(1) | PMC_PCR_EN(1) | + PMC_PCR_GCLKDIV(20 - 1) | PMC_PCR_GCLKCSS_MCK1 | + PMC_PCR_PID(ID_PIT64B0); +} diff --git a/soc/microchip/sam/sama7d6/soc.h b/soc/microchip/sam/sama7d6/soc.h new file mode 100644 index 0000000000000..35015e3b38e72 --- /dev/null +++ b/soc/microchip/sam/sama7d6/soc.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SAMA7D6_SOC__H_ +#define __SAMA7D6_SOC__H_ + +#ifdef CONFIG_SOC_SAMA7D65 +#define __SAMA7D65__ +#endif + +#include "sam.h" + +/* number of clocks registered */ +#define SOC_NUM_CLOCK_PLL_FRAC 9 +#define SOC_NUM_CLOCK_PLL_DIV (SOC_NUM_CLOCK_PLL_FRAC + 1) /* AUDIO PLL: DIVPMC, DIVIO */ +#define SOC_NUM_CLOCK_MASTER 10 /* MCK 0 ~ 9 */ +#define SOC_NUM_CLOCK_PROGRAMMABLE 8 /* MCK 0 ~ 7 */ +#define SOC_NUM_CLOCK_SYSTEM 8 /* PCK 0 ~ 7 */ +#define SOC_NUM_CLOCK_PERIPHERAL 72 +#define SOC_NUM_CLOCK_GENERATED 44 + +#endif /* __SAMA7D6_SOC__H_ */ diff --git a/soc/microchip/sam/soc.yml b/soc/microchip/sam/soc.yml index 8c180ee3c44ba..10387d9e60cd8 100644 --- a/soc/microchip/sam/soc.yml +++ b/soc/microchip/sam/soc.yml @@ -1,6 +1,9 @@ family: - name: microchip_sam series: + - name: sama7d6 + socs: + - name: sama7d65 - name: sama7g5 socs: - name: sama7g54 From 54e2cd21c63e8d9142234967829790a5f78f8fa9 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Tue, 1 Jul 2025 14:20:17 +0800 Subject: [PATCH 5/9] soc: microchip: sam: register clocks for sama7d65 Register sama7d65 clocks in sam_pmc_setup() which will be called by the PMC driver. Signed-off-by: Tony Han --- soc/microchip/sam/common/CMakeLists.txt | 3 +- soc/microchip/sam/common/pmc.h | 1 + soc/microchip/sam/common/sama7d65.c | 1382 +++++++++++++++++++++++ 3 files changed, 1385 insertions(+), 1 deletion(-) create mode 100644 soc/microchip/sam/common/sama7d65.c diff --git a/soc/microchip/sam/common/CMakeLists.txt b/soc/microchip/sam/common/CMakeLists.txt index bbb4727fdf383..50d11f5d75504 100644 --- a/soc/microchip/sam/common/CMakeLists.txt +++ b/soc/microchip/sam/common/CMakeLists.txt @@ -12,6 +12,7 @@ zephyr_sources(clk-peripheral.c) zephyr_sources(clk-programmable.c) zephyr_sources(clk-sam9x60-pll.c) zephyr_sources(clk-system.c) -zephyr_sources(clk-utmi.c) +zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAMA7G5 clk-utmi.c) zephyr_sources(pmc.c) +zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAMA7D6 sama7d65.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_SAMA7G5 sama7g5.c) diff --git a/soc/microchip/sam/common/pmc.h b/soc/microchip/sam/common/pmc.h index e9127cbca743b..72112c5185d30 100644 --- a/soc/microchip/sam/common/pmc.h +++ b/soc/microchip/sam/common/pmc.h @@ -68,6 +68,7 @@ struct clk_pll_characteristics { uint16_t *icpll; uint8_t *out; uint8_t upll : 1; + uint32_t acr; }; struct clk_programmable_layout { diff --git a/soc/microchip/sam/common/sama7d65.c b/soc/microchip/sam/common/sama7d65.c new file mode 100644 index 0000000000000..094f836752958 --- /dev/null +++ b/soc/microchip/sam/common/sama7d65.c @@ -0,0 +1,1382 @@ +/* + * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(pmc_setup, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1) + +#define SAMA7D65_INIT_TABLE(_table, _count) \ + do { \ + uint8_t _i; \ + for (_i = 0; _i < (_count); _i++) { \ + (_table)[_i] = _i; \ + } \ + } while (0) + +#define SAMA7D65_FILL_TABLE(_to, _from, _count) \ + do { \ + uint8_t _i; \ + for (_i = 0; _i < (_count); _i++) { \ + (_to)[_i] = (_from)[_i]; \ + } \ + } while (0) + +static struct k_spinlock pmc_pll_lock; +static struct k_spinlock pmc_mck0_lock; +static struct k_spinlock pmc_mckX_lock; +static struct k_spinlock pmc_pcr_lock; + +/* + * PLL clocks identifiers + * @PLL_ID_CPU: CPU PLL identifier + * @PLL_ID_SYS: System PLL identifier + * @PLL_ID_DDR: DDR PLL identifier + * @PLL_ID_IMG: Image subsystem PLL identifier + * @PLL_ID_BAUD: Baud PLL identifier + * @PLL_ID_AUDIO: Audio PLL identifier + * @PLL_ID_ETH: Ethernet PLL identifier + * @PLL_ID_LVDS: LVDS PLL identifier + * @PLL_ID_USB: USB PLL identifier + */ +enum pll_ids { + PLL_ID_CPU, + PLL_ID_SYS, + PLL_ID_DDR, + PLL_ID_GPU, + PLL_ID_BAUD, + PLL_ID_AUDIO, + PLL_ID_ETH, + PLL_ID_LVDS, + PLL_ID_USB, + PLL_ID_MAX, +}; + +/* + * PLL component identifier + * @PLL_COMPID_FRAC: Fractional PLL component identifier + * @PLL_COMPID_DIV0: 1st PLL divider component identifier + * @PLL_COMPID_DIV1: 2nd PLL divider component identifier + */ +enum pll_component_id { + PLL_COMPID_FRAC, + PLL_COMPID_DIV0, + PLL_COMPID_DIV1, +}; + +/* + * PLL type identifiers + * @PLL_TYPE_FRAC: fractional PLL identifier + * @PLL_TYPE_DIV: divider PLL identifier + */ +enum pll_type { + PLL_TYPE_FRAC, + PLL_TYPE_DIV, +}; + +/* Layout for fractional PLLs. */ +static const struct clk_pll_layout pll_layout_frac = { + .mul_mask = GENMASK(31, 24), + .frac_mask = GENMASK(21, 0), + .mul_shift = 24, + .frac_shift = 0, +}; + +/* Layout for DIVPMC dividers. */ +static const struct clk_pll_layout pll_layout_divpmc = { + .div_mask = GENMASK(7, 0), + .endiv_mask = BIT(29), + .div_shift = 0, + .endiv_shift = 29, +}; + +/* Layout for DIVIO dividers. */ +static const struct clk_pll_layout pll_layout_divio = { + .div_mask = GENMASK(19, 12), + .endiv_mask = BIT(30), + .div_shift = 12, + .endiv_shift = 30, +}; + +/* + * CPU PLL output range. + * Notice: The upper limit has been setup to 1000000002 due to hardware + * block which cannot output exactly 1GHz. + */ +static const struct clk_range cpu_pll_outputs[] = { + { .min = 2343750, .max = 1000000002 }, +}; + +/* PLL output range. */ +static const struct clk_range pll_outputs[] = { + { .min = 2343750, .max = 1200000000 }, +}; + +/* + * Min: fCOREPLLCK = 600 MHz, PMC_PLL_CTRL0.DIVPMC = 255 + * Max: fCOREPLLCK = 800 MHz, PMC_PLL_CTRL0.DIVPMC = 0 + */ +static const struct clk_range lvdspll_outputs[] = { + { .min = 16406250, .max = 800000000 }, +}; + +static const struct clk_range upll_outputs[] = { + { .min = 480000000, .max = 480000000 }, +}; + +/* Fractional PLL core output range. */ +static const struct clk_range core_outputs[] = { + { .min = 600000000, .max = 1200000000 }, +}; + +static const struct clk_range lvdspll_core_outputs[] = { + { .min = 600000000, .max = 1200000000 }, +}; + +static const struct clk_range upll_core_outputs[] = { + { .min = 600000000, .max = 1200000000 }, +}; + +/* CPU PLL characteristics. */ +static const struct clk_pll_characteristics cpu_pll_characteristics = { + .input = { .min = 12000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(cpu_pll_outputs), + .output = cpu_pll_outputs, + .core_output = core_outputs, + .acr = 0x00070010, +}; + +/* PLL characteristics. */ +static const struct clk_pll_characteristics pll_characteristics = { + .input = { .min = 12000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(pll_outputs), + .output = pll_outputs, + .core_output = core_outputs, + .acr = 0x00070010, +}; + +static const struct clk_pll_characteristics lvdspll_characteristics = { + .input = { .min = 12000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(lvdspll_outputs), + .output = lvdspll_outputs, + .core_output = lvdspll_core_outputs, + .acr = 0x00070010, +}; + +static const struct clk_pll_characteristics upll_characteristics = { + .input = { .min = 20000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(upll_outputs), + .output = upll_outputs, + .core_output = upll_core_outputs, + .acr = 0x12020010, + .upll = true, +}; + +/* + * SAMA7D65 PLL possible parents + * @SAMA7D65_PLL_PARENT_MAINCK: MAINCK is PLL a parent + * @SAMA7D65_PLL_PARENT_MAIN_XTAL: MAIN XTAL is a PLL parent + * @SAMA7D65_PLL_PARENT_FRACCK: Frac PLL is a PLL parent (for PLL dividers) + */ +enum sama7d65_pll_parent { + SAMA7D65_PLL_PARENT_MAINCK, + SAMA7D65_PLL_PARENT_MAIN_XTAL, + SAMA7D65_PLL_PARENT_FRACCK, +}; + +/* + * PLL clocks description + * @n: clock name + * @p: clock parent + * @l: clock layout + * @c: clock characteristics + * @hw: pointer to clk_hw + * @t: clock type + * @f: clock flags + * @p: clock parent + * @eid: export index in sama7d65->chws[] array + * @safe_div: intermediate divider need to be set on PRE_RATE_CHANGE + * notification + */ +static struct sama7d65_pll { + const char *n; + const struct clk_pll_layout *l; + const struct clk_pll_characteristics *c; + struct device *clk; + unsigned long f; + enum sama7d65_pll_parent p; + uint8_t t; + uint8_t eid; + uint8_t safe_div; +} sama7d65_plls[][PLL_ID_MAX] = { + [PLL_ID_CPU] = { + [PLL_COMPID_FRAC] = { + .n = "cpupll_fracck", + .p = SAMA7D65_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &cpu_pll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "cpupll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &cpu_pll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_CPUPLL, + /* + * Safe div=15 should be safe even for switching b/w 1GHz and + * 90MHz (frac pll might go up to 1.2GHz). + */ + .safe_div = 15, + }, + }, + + [PLL_ID_SYS] = { + [PLL_COMPID_FRAC] = { + .n = "syspll_fracck", + .p = SAMA7D65_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "syspll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_SYSPLL, + }, + }, + + [PLL_ID_DDR] = { + [PLL_COMPID_FRAC] = { + .n = "ddrpll_fracck", + .p = SAMA7D65_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "ddrpll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + }, + }, + + [PLL_ID_GPU] = { + [PLL_COMPID_FRAC] = { + .n = "gpupll_fracck", + .p = SAMA7D65_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "gpupll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + }, + }, + + [PLL_ID_BAUD] = { + [PLL_COMPID_FRAC] = { + .n = "baudpll_fracck", + .p = SAMA7D65_PLL_PARENT_MAINCK, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "baudpll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_BAUDPLL, + }, + }, + + [PLL_ID_AUDIO] = { + [PLL_COMPID_FRAC] = { + .n = "audiopll_fracck", + .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "audiopll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_AUDIOPMCPLL, + }, + + [PLL_COMPID_DIV1] = { + .n = "audiopll_diviock", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divio, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_AUDIOIOPLL, + }, + }, + + [PLL_ID_ETH] = { + [PLL_COMPID_FRAC] = { + .n = "ethpll_fracck", + .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, + .l = &pll_layout_frac, + .c = &pll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "ethpll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &pll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_ETHPLL, + }, + }, + + [PLL_ID_LVDS] = { + [PLL_COMPID_FRAC] = { + .n = "lvdspll_fracck", + .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, + .l = &pll_layout_frac, + .c = &lvdspll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "lvdspll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &lvdspll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_LVDSPLL, + }, + }, + + [PLL_ID_USB] = { + [PLL_COMPID_FRAC] = { + .n = "usbpll_fracck", + .p = SAMA7D65_PLL_PARENT_MAIN_XTAL, + .l = &pll_layout_frac, + .c = &upll_characteristics, + .t = PLL_TYPE_FRAC, + }, + + [PLL_COMPID_DIV0] = { + .n = "usbpll_divpmcck", + .p = SAMA7D65_PLL_PARENT_FRACCK, + .l = &pll_layout_divpmc, + .c = &upll_characteristics, + .t = PLL_TYPE_DIV, + .eid = PMC_UTMI, + }, + }, +}; + +/* Used to create an array entry identifying a PLL by its components. */ +#define PLL_IDS_TO_ARR_ENTRY(_id, _comp) { PLL_ID_##_id, PLL_COMPID_##_comp} + +/* + * Master clock (MCK[1..4]) description + * @n: clock name + * @ep_chg_chg_id: index in parents array that specifies the changeable + * @ep: extra parents names array (entry formed by PLL components + * identifiers (see enum pll_component_id)) + * @hw: pointer to clk_hw + * parent + * @ep_count: extra parents count + * @ep_mux_table: mux table for extra parents + * @id: clock id + * @eid: export index in sama7d65->chws[] array + * @c: true if clock is critical and cannot be disabled + */ +static struct { + const char *n; + struct { + int pll_id; + int pll_compid; + } ep[4]; + struct device *clk; + int ep_chg_id; + uint8_t ep_count; + uint8_t ep_mux_table[4]; + uint8_t id; + uint8_t eid; + uint8_t c; +} sama7d65_mckx[] = { + { .n = "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */ + { .n = "mck1", + .id = 1, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .ep_mux_table = { 5, }, + .ep_count = 1, + .ep_chg_id = INT_MIN, + .eid = PMC_MCK1, + .c = 1, }, + + { .n = "mck2", + .id = 2, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), }, + .ep_mux_table = { 5, 6, }, + .ep_count = 2, + .ep_chg_id = INT_MIN, + .c = 1, }, + + { .n = "mck3", + .id = 3, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), }, + .ep_mux_table = { 5, 6, }, + .ep_count = 2, + .ep_chg_id = INT_MIN, + .eid = PMC_MCK3, + .c = 1, }, + + { .n = "mck4", + .id = 4, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .ep_mux_table = { 5, }, + .ep_count = 1, + .ep_chg_id = INT_MIN, + .c = 1,}, + + { .n = "mck5", + .id = 5, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .ep_mux_table = { 5, }, + .ep_count = 1, + .ep_chg_id = INT_MIN, + .eid = PMC_MCK5, + .c = 1,}, + + { .n = "mck6", + .id = 6, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .ep_mux_table = { 5, }, + .ep_chg_id = INT_MIN, + .ep_count = 1, + .c = 1,}, + + { .n = "mck7", + .id = 7, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .ep_mux_table = { 5, }, + .ep_chg_id = INT_MIN, + .ep_count = 1,}, + + { .n = "mck8", + .id = 8, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .ep_mux_table = { 5, }, + .ep_chg_id = INT_MIN, + .ep_count = 1,}, + + { .n = "mck9", + .id = 9, + .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .ep_mux_table = { 5, }, + .ep_chg_id = INT_MIN, + .ep_count = 1, }, +}; + +/* + * System clock description + * @n: clock name + * @p: clock parent name + * @id: clock id + */ +static const struct { + const char *n; + const char *p; + uint8_t id; +} sama7d65_systemck[] = { + { .n = "pck0", .p = "prog0", .id = 8, }, + { .n = "pck1", .p = "prog1", .id = 9, }, + { .n = "pck2", .p = "prog2", .id = 10, }, + { .n = "pck3", .p = "prog3", .id = 11, }, + { .n = "pck4", .p = "prog4", .id = 12, }, + { .n = "pck5", .p = "prog5", .id = 13, }, + { .n = "pck6", .p = "prog6", .id = 14, }, + { .n = "pck7", .p = "prog7", .id = 15, }, +}; + +/* Mux table for programmable clocks. */ +static uint32_t sama7d65_prog_mux_table[] = { 0, 1, 2, 5, 7, 8, 9, 10, 12,}; + +/* + * Peripheral clock parent hw identifier (used to index in sama7d65_mckx[]) + * @PCK_PARENT_HW_MCK0: pck parent hw identifier is MCK0 + * @PCK_PARENT_HW_MCK1: pck parent hw identifier is MCK1 + * @PCK_PARENT_HW_MCK2: pck parent hw identifier is MCK2 + * @PCK_PARENT_HW_MCK3: pck parent hw identifier is MCK3 + * @PCK_PARENT_HW_MCK4: pck parent hw identifier is MCK4 + * @PCK_PARENT_HW_MCK5: pck parent hw identifier is MCK5 + * @PCK_PARENT_HW_MCK6: pck parent hw identifier is MCK6 + * @PCK_PARENT_HW_MCK7: pck parent hw identifier is MCK7 + * @PCK_PARENT_HW_MCK8: pck parent hw identifier is MCK8 + * @PCK_PARENT_HW_MCK9: pck parent hw identifier is MCK9 + * @PCK_PARENT_HW_MAX: max identifier + */ +enum sama7d65_pck_parent_hw_id { + PCK_PARENT_HW_MCK0, + PCK_PARENT_HW_MCK1, + PCK_PARENT_HW_MCK2, + PCK_PARENT_HW_MCK3, + PCK_PARENT_HW_MCK4, + PCK_PARENT_HW_MCK5, + PCK_PARENT_HW_MCK6, + PCK_PARENT_HW_MCK7, + PCK_PARENT_HW_MCK8, + PCK_PARENT_HW_MCK9, + PCK_PARENT_HW_MAX, +}; + +/* + * Peripheral clock description + * @n: clock name + * @p: clock parent hw id + * @r: clock range values + * @id: clock id + * @chgp: index in parent array of the changeable parent + */ +static struct { + const char *n; + enum sama7d65_pck_parent_hw_id p; + struct clk_range r; + uint8_t chgp; + uint8_t id; +} sama7d65_periphck[] = { + { .n = "pioA_clk", .p = PCK_PARENT_HW_MCK0, .id = 10, }, + { .n = "securam_clk", .p = PCK_PARENT_HW_MCK0, .id = 17, }, + { .n = "sfr_clk", .p = PCK_PARENT_HW_MCK7, .id = 18, }, + { .n = "hsmc_clk", .p = PCK_PARENT_HW_MCK5, .id = 20, }, + { .n = "xdmac0_clk", .p = PCK_PARENT_HW_MCK6, .id = 21, }, + { .n = "xdmac1_clk", .p = PCK_PARENT_HW_MCK6, .id = 22, }, + { .n = "xdmac2_clk", .p = PCK_PARENT_HW_MCK1, .id = 23, }, + { .n = "acc_clk", .p = PCK_PARENT_HW_MCK7, .id = 24, }, + { .n = "aes_clk", .p = PCK_PARENT_HW_MCK6, .id = 26, }, + { .n = "tzaesbasc_clk", .p = PCK_PARENT_HW_MCK8, .id = 27, }, + { .n = "asrc_clk", .p = PCK_PARENT_HW_MCK9, .id = 29, .r = { .max = 200000000, }, }, + { .n = "cpkcc_clk", .p = PCK_PARENT_HW_MCK0, .id = 30, }, + { .n = "eic_clk", .p = PCK_PARENT_HW_MCK7, .id = 33, }, + { .n = "flex0_clk", .p = PCK_PARENT_HW_MCK7, .id = 34, }, + { .n = "flex1_clk", .p = PCK_PARENT_HW_MCK7, .id = 35, }, + { .n = "flex2_clk", .p = PCK_PARENT_HW_MCK7, .id = 36, }, + { .n = "flex3_clk", .p = PCK_PARENT_HW_MCK7, .id = 37, }, + { .n = "flex4_clk", .p = PCK_PARENT_HW_MCK8, .id = 38, }, + { .n = "flex5_clk", .p = PCK_PARENT_HW_MCK8, .id = 39, }, + { .n = "flex6_clk", .p = PCK_PARENT_HW_MCK8, .id = 40, }, + { .n = "flex7_clk", .p = PCK_PARENT_HW_MCK8, .id = 41, }, + { .n = "flex8_clk", .p = PCK_PARENT_HW_MCK9, .id = 42, }, + { .n = "flex9_clk", .p = PCK_PARENT_HW_MCK9, .id = 43, }, + { .n = "flex10_clk", .p = PCK_PARENT_HW_MCK9, .id = 44, }, + { .n = "gmac0_clk", .p = PCK_PARENT_HW_MCK6, .id = 46, }, + { .n = "gmac1_clk", .p = PCK_PARENT_HW_MCK6, .id = 47, }, + { .n = "gmac0_tsu_clk", .p = PCK_PARENT_HW_MCK1, .id = 49, }, + { .n = "gmac1_tsu_clk", .p = PCK_PARENT_HW_MCK1, .id = 50, }, + { .n = "icm_clk", .p = PCK_PARENT_HW_MCK5, .id = 53, }, + { .n = "i2smcc0_clk", .p = PCK_PARENT_HW_MCK9, .id = 54, .r = { .max = 200000000, }, }, + { .n = "i2smcc1_clk", .p = PCK_PARENT_HW_MCK9, .id = 55, .r = { .max = 200000000, }, }, + { .n = "lcd_clk", .p = PCK_PARENT_HW_MCK3, .id = 56, }, + { .n = "matrix_clk", .p = PCK_PARENT_HW_MCK5, .id = 57, }, + { .n = "mcan0_clk", .p = PCK_PARENT_HW_MCK5, .id = 58, .r = { .max = 200000000, }, }, + { .n = "mcan1_clk", .p = PCK_PARENT_HW_MCK5, .id = 59, .r = { .max = 200000000, }, }, + { .n = "mcan2_clk", .p = PCK_PARENT_HW_MCK5, .id = 60, .r = { .max = 200000000, }, }, + { .n = "mcan3_clk", .p = PCK_PARENT_HW_MCK5, .id = 61, .r = { .max = 200000000, }, }, + { .n = "mcan4_clk", .p = PCK_PARENT_HW_MCK5, .id = 62, .r = { .max = 200000000, }, }, + { .n = "pdmc0_clk", .p = PCK_PARENT_HW_MCK9, .id = 64, .r = { .max = 200000000, }, }, + { .n = "pdmc1_clk", .p = PCK_PARENT_HW_MCK9, .id = 65, .r = { .max = 200000000, }, }, + { .n = "pit64b0_clk", .p = PCK_PARENT_HW_MCK7, .id = 66, }, + { .n = "pit64b1_clk", .p = PCK_PARENT_HW_MCK7, .id = 67, }, + { .n = "pit64b2_clk", .p = PCK_PARENT_HW_MCK7, .id = 68, }, + { .n = "pit64b3_clk", .p = PCK_PARENT_HW_MCK8, .id = 69, }, + { .n = "pit64b4_clk", .p = PCK_PARENT_HW_MCK8, .id = 70, }, + { .n = "pit64b5_clk", .p = PCK_PARENT_HW_MCK8, .id = 71, }, + { .n = "pwm_clk", .p = PCK_PARENT_HW_MCK7, .id = 72, }, + { .n = "qspi0_clk", .p = PCK_PARENT_HW_MCK5, .id = 73, }, + { .n = "qspi1_clk", .p = PCK_PARENT_HW_MCK5, .id = 74, }, + { .n = "sdmmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 75, }, + { .n = "sdmmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 76, }, + { .n = "sdmmc2_clk", .p = PCK_PARENT_HW_MCK1, .id = 77, }, + { .n = "sha_clk", .p = PCK_PARENT_HW_MCK6, .id = 78, }, + { .n = "spdifrx_clk", .p = PCK_PARENT_HW_MCK9, .id = 79, .r = { .max = 200000000, }, }, + { .n = "spdiftx_clk", .p = PCK_PARENT_HW_MCK9, .id = 80, .r = { .max = 200000000, }, }, + { .n = "ssc0_clk", .p = PCK_PARENT_HW_MCK7, .id = 81, .r = { .max = 200000000, }, }, + { .n = "ssc1_clk", .p = PCK_PARENT_HW_MCK8, .id = 82, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch0_clk", .p = PCK_PARENT_HW_MCK8, .id = 83, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch1_clk", .p = PCK_PARENT_HW_MCK8, .id = 84, .r = { .max = 200000000, }, }, + { .n = "tcb0_ch2_clk", .p = PCK_PARENT_HW_MCK8, .id = 85, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch0_clk", .p = PCK_PARENT_HW_MCK5, .id = 86, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch1_clk", .p = PCK_PARENT_HW_MCK5, .id = 87, .r = { .max = 200000000, }, }, + { .n = "tcb1_ch2_clk", .p = PCK_PARENT_HW_MCK5, .id = 88, .r = { .max = 200000000, }, }, + { .n = "tcpca_clk", .p = PCK_PARENT_HW_MCK5, .id = 89, }, + { .n = "tcpcb_clk", .p = PCK_PARENT_HW_MCK5, .id = 90, }, + { .n = "tdes_clk", .p = PCK_PARENT_HW_MCK6, .id = 91, }, + { .n = "trng_clk", .p = PCK_PARENT_HW_MCK6, .id = 92, }, + { .n = "udphsa_clk", .p = PCK_PARENT_HW_MCK5, .id = 99, }, + { .n = "udphsb_clk", .p = PCK_PARENT_HW_MCK5, .id = 100, }, + { .n = "uhphs_clk", .p = PCK_PARENT_HW_MCK5, .id = 101, }, + { .n = "dsi_clk", .p = PCK_PARENT_HW_MCK3, .id = 103, }, + { .n = "lvdsc_clk", .p = PCK_PARENT_HW_MCK3, .id = 104, }, +}; + +/* + * Generic clock description + * @n: clock name + * @pp: PLL parents (entry formed by PLL components identifiers + * (see enum pll_component_id)) + * @pp_mux_table: PLL parents mux table + * @r: clock output range + * @pp_chg_id: id in parent array of changeable PLL parent + * @pp_count: PLL parents count + * @id: clock id + */ +static const struct { + const char *n; + struct { + int pll_id; + int pll_compid; + } pp[8]; + const char pp_mux_table[8]; + struct clk_range r; + int pp_chg_id; + uint8_t pp_count; + uint8_t id; +} sama7d65_gck[] = { + { .n = "adc_gclk", + .id = 25, + .r = { .max = 100000000, }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 8, 9, }, + .pp_count = 2, + .pp_chg_id = INT_MIN, }, + + { .n = "asrc_gclk", + .id = 29, + .r = { .max = 200000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 9, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex0_gclk", + .id = 34, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = {8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex1_gclk", + .id = 35, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = {8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex2_gclk", + .id = 36, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = {8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex3_gclk", + .id = 37, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = {8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex4_gclk", + .id = 38, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex5_gclk", + .id = 39, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex6_gclk", + .id = 40, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex7_gclk", + .id = 41, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex8_gclk", + .id = 42, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex9_gclk", + .id = 43, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "flex10_gclk", + .id = 44, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 8, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "gmac0_gclk", + .id = 46, + .r = { .max = 125000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 10, }, + .pp_count = 1, + .pp_chg_id = 4, }, + + { .n = "gmac1_gclk", + .id = 47, + .r = { .max = 125000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 10, }, + .pp_count = 1, + .pp_chg_id = 4, }, + + { .n = "gmac0_tsu_gclk", + .id = 49, + .r = { .max = 400000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = {10, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "gmac1_tsu_gclk", + .id = 50, + .r = { .max = 400000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 10, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "i2smcc0_gclk", + .id = 54, + .r = { .max = 100000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 9, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "i2smcc1_gclk", + .id = 55, + .r = { .max = 100000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 9, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "lcdc_gclk", + .id = 56, + .r = { .max = 90000000 }, + .pp_count = 0, + .pp_chg_id = INT_MIN, + }, + + { .n = "mcan0_gclk", + .id = 58, + .r = { .max = 80000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, + .pp_mux_table = { 12 }, + .pp_count = 1, + .pp_chg_id = 4, }, + + { .n = "mcan1_gclk", + .id = 59, + .r = { .max = 80000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, + .pp_mux_table = { 12 }, + .pp_count = 1, + .pp_chg_id = 4, }, + + { .n = "mcan2_gclk", + .id = 60, + .r = { .max = 80000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, + .pp_mux_table = { 12 }, + .pp_count = 1, + .pp_chg_id = 4, }, + + { .n = "mcan3_gclk", + .id = 61, + .r = { .max = 80000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, + .pp_mux_table = { 12 }, + .pp_count = 1, + .pp_chg_id = 4, }, + + { .n = "mcan4_gclk", + .id = 62, + .r = { .max = 80000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(USB, DIV0), }, + .pp_mux_table = { 12 }, + .pp_count = 1, + .pp_chg_id = 4, }, + + { .n = "pdmc0_gclk", + .id = 64, + .r = { .max = 80000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 9 }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "pdmc1_gclk", + .id = 65, + .r = { .max = 80000000, }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 9, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "pit64b0_gclk", + .id = 66, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "pit64b1_gclk", + .id = 67, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "pit64b2_gclk", + .id = 68, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "pit64b3_gclk", + .id = 69, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = {8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "pit64b4_gclk", + .id = 70, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = {8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "pit64b5_gclk", + .id = 71, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = {8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "qspi0_gclk", + .id = 73, + .r = { .max = 400000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 5, 8, }, + .pp_count = 2, + .pp_chg_id = INT_MIN, }, + + { .n = "qspi1_gclk", + .id = 74, + .r = { .max = 266000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), }, + .pp_mux_table = { 5, 8, }, + .pp_count = 2, + .pp_chg_id = INT_MIN, }, + + { .n = "sdmmc0_gclk", + .id = 75, + .r = { .max = 208000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 10, }, + .pp_count = 2, + .pp_chg_id = 4, }, + + { .n = "sdmmc1_gclk", + .id = 76, + .r = { .max = 208000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 10, }, + .pp_count = 2, + .pp_chg_id = 4, }, + + { .n = "sdmmc2_gclk", + .id = 77, + .r = { .max = 208000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 10 }, + .pp_count = 2, + .pp_chg_id = 4, }, + + { .n = "spdifrx_gclk", + .id = 79, + .r = { .max = 150000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 9, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "spdiftx_gclk", + .id = 80, + .r = { .max = 25000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), }, + .pp_mux_table = { 9, }, + .pp_count = 1, + .pp_chg_id = INT_MIN, }, + + { .n = "tcb0_ch0_gclk", + .id = 83, + .r = { .max = 34000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "tcb1_ch0_gclk", + .id = 86, + .r = { .max = 67000000 }, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = { 8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN, }, + + { .n = "DSI_gclk", + .id = 103, + .r = {.max = 27000000}, + .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), }, + .pp_mux_table = {5}, + .pp_count = 1, + .pp_chg_id = INT_MIN,}, + + { .n = "I3CC_gclk", + .id = 105, + .r = {.max = 125000000}, + .pp = { PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), + PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), }, + .pp_mux_table = {8, 9, 10, }, + .pp_count = 3, + .pp_chg_id = INT_MIN,}, +}; + +/* MCK0 characteristics. */ +static const struct clk_master_characteristics mck0_characteristics = { + .output = {.min = 32768, .max = 200000000}, + .divisors = {1, 2, 4, 3, 5}, + .have_div3_pres = 1, +}; + +/* MCK0 layout. */ +static const struct clk_master_layout mck0_layout = { + .mask = 0x773, + .pres_shift = 4, + .offset = 0x28, +}; + +/* Programmable clock layout. */ +static const struct clk_programmable_layout programmable_layout = { + .pres_mask = 0xff, + .pres_shift = 8, + .css_mask = 0x1f, + .have_slck_mck = 0, + .is_pres_direct = 1, +}; + +/* Peripheral clock layout. */ +static const struct clk_pcr_layout sama7d65_pcr_layout = { + .offset = 0x88, + .cmd = BIT(31), + .gckcss_mask = GENMASK(12, 8), + .pid_mask = GENMASK(6, 0), +}; + +enum clock_count { + CLK_CNT_SYSTEM = 15 + 1, + CLK_CNT_PERIPH = 104 + 1, + CLK_CNT_GCK = 105 + 1, +}; + +static struct device *pmc_table[PMC_MCK5 + 1 + CLK_CNT_SYSTEM + CLK_CNT_PERIPH + CLK_CNT_GCK + + SOC_NUM_CLOCK_PROGRAMMABLE]; + +static int sam_pmc_register_pll(const struct device *dev, struct pmc_data *sama7d65_pmc) +{ + const struct sam_pmc_cfg *cfg = dev->config; + void *const regmap = cfg->reg; + struct device *clk; + int ret, i, j; + + for (i = 0; i < PLL_ID_MAX; i++) { + for (j = 0; j < 3; j++) { + const struct device *parent_hw; + + if (!sama7d65_plls[i][j].n) { + continue; + } + + switch (sama7d65_plls[i][j].t) { + case PLL_TYPE_FRAC: + switch (sama7d65_plls[i][j].p) { + case SAMA7D65_PLL_PARENT_MAINCK: + parent_hw = sama7d65_pmc->chws[PMC_MAIN]; + break; + case SAMA7D65_PLL_PARENT_MAIN_XTAL: + parent_hw = cfg->main_xtal; + break; + default: + /* Should not happen. */ + parent_hw = NULL; + break; + } + + ret = sam9x60_clk_register_frac_pll(regmap, + &pmc_pll_lock, + sama7d65_plls[i][j].n, + parent_hw, i, + sama7d65_plls[i][j].c, + sama7d65_plls[i][j].l, + &clk); + break; + + case PLL_TYPE_DIV: + ret = sam9x60_clk_register_div_pll(regmap, + &pmc_pll_lock, + sama7d65_plls[i][j].n, + sama7d65_plls[i][0].clk, i, + sama7d65_plls[i][j].c, + sama7d65_plls[i][j].l, + &clk); + break; + + default: + continue; + } + + if (ret) { + LOG_ERR("Register clock %s failed.", sama7d65_plls[i][j].n); + return ret; + } + + sama7d65_plls[i][j].clk = clk; + if (sama7d65_plls[i][j].eid) { + sama7d65_pmc->chws[sama7d65_plls[i][j].eid] = clk; + } + } + } + + return 0; +} + +static int sam_pmc_register_mckx(const struct device *dev, struct pmc_data *sama7d65_pmc) +{ + const struct sam_pmc_cfg *cfg = dev->config; + const struct device *parents[10]; + void *const regmap = cfg->reg; + uint32_t mux_table[8]; + struct device *clk; + int ret = 0; + int i, j; + + ret = clk_register_master_div(regmap, "mck0", sama7d65_plls[PLL_ID_CPU][1].clk, + &mck0_layout, &mck0_characteristics, &pmc_mck0_lock, 5, &clk); + if (ret) { + LOG_ERR("Register MCK0 clock failed."); + return ret; + } + sama7d65_mckx[PCK_PARENT_HW_MCK0].clk = sama7d65_pmc->chws[PMC_MCK] = clk; + + parents[0] = cfg->md_slck; + parents[1] = cfg->td_slck; + parents[2] = sama7d65_pmc->chws[PMC_MAIN]; + for (i = PCK_PARENT_HW_MCK1; i < ARRAY_SIZE(sama7d65_mckx); i++) { + uint8_t num_parents = 3 + sama7d65_mckx[i].ep_count; + struct device *tmp_parent_hws[8]; + + if (num_parents > ARRAY_SIZE(mux_table)) { + LOG_ERR("Array for mux table not enough"); + return -ENOMEM; + } + + SAMA7D65_INIT_TABLE(mux_table, 3); + SAMA7D65_FILL_TABLE(&mux_table[3], sama7d65_mckx[i].ep_mux_table, + sama7d65_mckx[i].ep_count); + for (j = 0; j < sama7d65_mckx[i].ep_count; j++) { + uint8_t pll_id = sama7d65_mckx[i].ep[j].pll_id; + uint8_t pll_compid = sama7d65_mckx[i].ep[j].pll_compid; + + tmp_parent_hws[j] = sama7d65_plls[pll_id][pll_compid].clk; + } + SAMA7D65_FILL_TABLE(&parents[3], tmp_parent_hws, sama7d65_mckx[i].ep_count); + + ret = clk_register_master(regmap, sama7d65_mckx[i].n, num_parents, parents, + mux_table, &pmc_mckX_lock, sama7d65_mckx[i].id, &clk); + if (ret) { + LOG_ERR("Register MCK%d clock failed.", i); + return ret; + } + + sama7d65_mckx[i].clk = clk; + if (sama7d65_mckx[i].eid) { + sama7d65_pmc->chws[sama7d65_mckx[i].eid] = clk; + } + } + + return 0; +} + +static int sam_pmc_register_generated(const struct device *dev, struct pmc_data *sama7d65_pmc) +{ + const struct sam_pmc_cfg *cfg = dev->config; + const struct device *parents[10]; + void *const regmap = cfg->reg; + uint32_t mux_table[8]; + struct device *clk; + int ret = 0; + int i, j; + + parents[0] = cfg->md_slck; + parents[1] = cfg->td_slck; + parents[2] = sama7d65_pmc->chws[PMC_MAIN]; + parents[3] = sama7d65_pmc->chws[PMC_MCK1]; + for (i = 0; i < ARRAY_SIZE(sama7d65_gck); i++) { + uint8_t num_parents = 4 + sama7d65_gck[i].pp_count; + struct device *tmp_parent_hws[8]; + + if (num_parents > ARRAY_SIZE(mux_table)) { + LOG_ERR("Array for mux table not enough"); + return -ENOMEM; + } + + SAMA7D65_INIT_TABLE(mux_table, 4); + SAMA7D65_FILL_TABLE(&mux_table[4], sama7d65_gck[i].pp_mux_table, + sama7d65_gck[i].pp_count); + for (j = 0; j < sama7d65_gck[i].pp_count; j++) { + uint8_t pll_id = sama7d65_gck[i].pp[j].pll_id; + uint8_t pll_compid = sama7d65_gck[i].pp[j].pll_compid; + + tmp_parent_hws[j] = sama7d65_plls[pll_id][pll_compid].clk; + } + SAMA7D65_FILL_TABLE(&parents[4], tmp_parent_hws, sama7d65_gck[i].pp_count); + + ret = clk_register_generated(regmap, &pmc_pcr_lock, + &sama7d65_pcr_layout, + sama7d65_gck[i].n, + parents, mux_table, + num_parents, + sama7d65_gck[i].id, + &sama7d65_gck[i].r, + sama7d65_gck[i].pp_chg_id, &clk); + if (ret) { + LOG_ERR("Register generated clock failed."); + return ret; + } + sama7d65_pmc->ghws[sama7d65_gck[i].id] = clk; + } + + return 0; +} + +void sam_pmc_setup(const struct device *dev) +{ + const struct sam_pmc_cfg *cfg = dev->config; + struct sam_pmc_data *data = dev->data; + const struct device *main_xtal = cfg->main_xtal; + const struct device *td_slck = cfg->td_slck; + const struct device *md_slck = cfg->md_slck; + + void *const regmap = cfg->reg; + const struct device *parents[10]; + struct pmc_data *sama7d65_pmc; + struct device *clk, *main_rc, *main_osc; + + uint32_t rate, bypass; + int ret, i; + + if (!td_slck || !md_slck || !main_xtal || !regmap) { + LOG_ERR("Incorrect parameters."); + return; + } + + if (CLK_CNT_SYSTEM != nck(sama7d65_systemck) || + CLK_CNT_PERIPH != nck(sama7d65_periphck) || + CLK_CNT_GCK != nck(sama7d65_gck)) { + LOG_ERR("Incorrect definitions could make array for pmc clocks not enough"); + return; + } + + sama7d65_pmc = pmc_data_allocate(PMC_MCK5 + 1, nck(sama7d65_systemck), + nck(sama7d65_periphck), nck(sama7d65_gck), + SOC_NUM_CLOCK_PROGRAMMABLE, &pmc_table[0]); + if (!sama7d65_pmc) { + LOG_ERR("allocate PMC data failed."); + return; + } + data->pmc = sama7d65_pmc; + + ret = clk_register_main_rc_osc(regmap, "main_rc_osc", MHZ(12), &main_rc); + if (ret) { + LOG_ERR("Register clock main_rc_osc failed."); + return; + } + + if (clock_control_get_rate(main_xtal, NULL, &rate)) { + LOG_ERR("get clock rate of main_xtal failed."); + return; + } + + bypass = 0; + ret = clk_register_main_osc(regmap, "main_osc", bypass, rate, &main_osc); + if (ret) { + LOG_ERR("Register clock main_osc failed."); + return; + } + + parents[0] = main_rc; + parents[1] = main_osc; + ret = clk_register_main(regmap, "mainck", parents, 2, &clk); + if (ret) { + LOG_ERR("Register clock mainck failed."); + return; + } + + sama7d65_pmc->chws[PMC_MAIN] = clk; + + ret = sam_pmc_register_pll(dev, sama7d65_pmc); + if (ret) { + return; + } + + ret = sam_pmc_register_mckx(dev, sama7d65_pmc); + if (ret) { + return; + } + + parents[0] = md_slck; + parents[1] = td_slck; + parents[2] = sama7d65_pmc->chws[PMC_MAIN]; + parents[3] = sama7d65_plls[PLL_ID_SYS][PLL_COMPID_DIV0].clk; + parents[4] = sama7d65_plls[PLL_ID_DDR][PLL_COMPID_DIV0].clk; + parents[5] = sama7d65_plls[PLL_ID_GPU][PLL_COMPID_DIV0].clk; + parents[6] = sama7d65_plls[PLL_ID_BAUD][PLL_COMPID_DIV0].clk; + parents[7] = sama7d65_plls[PLL_ID_AUDIO][PLL_COMPID_DIV0].clk; + parents[8] = sama7d65_plls[PLL_ID_ETH][PLL_COMPID_DIV0].clk; + for (i = 0; i < 8; i++) { + ret = clk_register_programmable(regmap, parents, 9, i, &programmable_layout, + sama7d65_prog_mux_table, &clk); + if (ret) { + LOG_ERR("Register programmable clock %d failed.", i); + return; + } + + sama7d65_pmc->pchws[i] = clk; + } + + for (i = 0; i < ARRAY_SIZE(sama7d65_systemck); i++) { + ret = clk_register_system(regmap, sama7d65_systemck[i].n, + sama7d65_pmc->pchws[i], + sama7d65_systemck[i].id, &clk); + if (ret) { + LOG_ERR("Register system clock %d failed.", i); + return; + } + + sama7d65_pmc->shws[sama7d65_systemck[i].id] = clk; + } + + for (i = 0; i < ARRAY_SIZE(sama7d65_periphck); i++) { + clk = sama7d65_mckx[sama7d65_periphck[i].p].clk; + ret = clk_register_peripheral(regmap, &pmc_pcr_lock, + &sama7d65_pcr_layout, + sama7d65_periphck[i].n, + clk, + sama7d65_periphck[i].id, + &sama7d65_periphck[i].r, + &clk); + if (ret) { + LOG_ERR("Register peripheral clock failed."); + return; + } + sama7d65_pmc->phws[sama7d65_periphck[i].id] = clk; + } + + ret = sam_pmc_register_generated(dev, sama7d65_pmc); + if (ret) { + return; + } + + LOG_DBG("Register PMC clocks successfully."); +} From 052eb01b73db5fd55961ceaba3ce2551c670c597 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Tue, 1 Jul 2025 14:08:43 +0800 Subject: [PATCH 6/9] include: dt-bindings: sam_pmc: add PMC clocks for SAMA7D65 Add LVDSPLL, MCK3 and MCK5 clock definitions for microchip SAMA7D65. Signed-off-by: Tony Han --- include/zephyr/dt-bindings/clock/microchip_sam_pmc.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/zephyr/dt-bindings/clock/microchip_sam_pmc.h b/include/zephyr/dt-bindings/clock/microchip_sam_pmc.h index 0656f3de97162..a2e2fa94051df 100644 --- a/include/zephyr/dt-bindings/clock/microchip_sam_pmc.h +++ b/include/zephyr/dt-bindings/clock/microchip_sam_pmc.h @@ -33,4 +33,9 @@ #define UTMI2 1 #define UTMI3 2 +/* SAMA7D65 */ +#define PMC_LVDSPLL (PMC_MAIN + 12) +#define PMC_MCK3 (PMC_MAIN + 20) +#define PMC_MCK5 (PMC_MAIN + 21) + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MICROCHIP_SAM_PMC_H_ */ From 3d0faa596f1b82b10c74ea95da5844534fcce0d7 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Tue, 1 Jul 2025 14:19:16 +0800 Subject: [PATCH 7/9] dts: microchip: add the DTSI file for sama7d65 Add the base DTSI file for Microchip sama7d65. Signed-off-by: Tony Han --- dts/arm/microchip/sam/sama7d65.dtsi | 421 ++++++++++++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 dts/arm/microchip/sam/sama7d65.dtsi diff --git a/dts/arm/microchip/sam/sama7d65.dtsi b/dts/arm/microchip/sam/sama7d65.dtsi new file mode 100644 index 0000000000000..a8de93d5151c8 --- /dev/null +++ b/dts/arm/microchip/sam/sama7d65.dtsi @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include +#include +#include +#include +#include + +/ { + model = "Microchip SAMA7D65 family SoC"; + compatible = "microchip,sama7d6"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0>; + }; + }; + + clocks { + main_xtal: main_xtal { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + slow_xtal: slow_xtal { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + }; + + soc { + clk32k: clock-controller@e001d500 { + compatible = "microchip,sama7g5-sckc", "microchip,sam9x60-sckc"; + reg = <0xe001d500 0x4>; + clocks = <&slow_xtal>; + #clock-cells = <1>; + }; + + flx0: flexcom@e1820000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe1820000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe1820000 0x800>; + status = "disabled"; + + i2c0: i2c0@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 34>; + status = "disabled"; + }; + + uart0: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 34>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx1: flexcom@e1824000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe1824000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe1824000 0x800>; + status = "disabled"; + + i2c1: i2c1@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 35>; + status = "disabled"; + }; + + uart1: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 35>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx2: flexcom@e1828000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe1828000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe1828000 0x800>; + status = "disabled"; + + i2c2: i2c2@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 36>; + status = "disabled"; + }; + + uart2: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 36>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx3: flexcom@e182c000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe182c000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe182c000 0x800>; + status = "disabled"; + + i2c3: i2c3@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; + status = "disabled"; + }; + + uart3: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx4: flexcom@e2018000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe2018000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2018000 0x800>; + status = "disabled"; + + i2c4: i2c4@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; + status = "disabled"; + }; + + uart4: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx5: flexcom@e201c000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe201c000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe201c000 0x800>; + status = "disabled"; + + i2c5: i2c5@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; + status = "disabled"; + }; + + uart5: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx6: flexcom@e2020000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe2020000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2020000 0x800>; + status = "disabled"; + + i2c6: i2c6@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 40>; + status = "disabled"; + }; + + uart6: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 40>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx7: flexcom@e2024000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe2024000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2024000 0x800>; + status = "disabled"; + + i2c7: i2c7@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 41>; + status = "disabled"; + }; + + uart7: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 41>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx8: flexcom@e281c000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe281c000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe281c000 0x800>; + status = "disabled"; + + i2c8: i2c8@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 42>; + status = "disabled"; + }; + + uart8: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 42>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx9: flexcom@e2820000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe2820000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2820000 0x800>; + status = "disabled"; + + i2c9: i2c9@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 43>; + status = "disabled"; + }; + + uart9: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 43>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + flx10: flexcom@e2824000 { + compatible = "microchip,sam-flexcom"; + reg = <0xe2824000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2824000 0x800>; + status = "disabled"; + + i2c10: i2c10@600 { + compatible = "atmel,sam-i2c-twi"; + reg = <0x600 0x200>; + clock-frequency = ; + interrupt-parent = <&gic>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 44>; + status = "disabled"; + }; + + uart10: serial@200 { + compatible = "atmel,sam-usart"; + reg = <0x200 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 44>; + interrupt-parent = <&gic>; + interrupts = ; + status = "disabled"; + }; + }; + + gic: interrupt-controller@e8c11000 { + compatible = "arm,gic-v2", "arm,gic"; + reg = <0xe8c11000 0x1000>, <0xe8c12000 0x100>; + interrupt-controller; + #interrupt-cells = <4>; + }; + + rtc: rtc@e001d800 { + compatible = "atmel,sam-rtc"; + reg = <0xe001d800 0x30>; + interrupt-parent = <&gic>; + interrupts = ; + clocks = <&clk32k 1>; + }; + + sram: memory@100000 { + compatible = "mmio-sram"; + reg = <0x00100000 DT_SIZE_K(128)>; + }; + + pinctrl: pinctrl@e0014000 { + compatible = "microchip,sama7g5-pinctrl"; + reg = <0xe0014000 0x800>; + }; + + pit64b0: timer@e1800000 { + compatible = "microchip,sam-pit64b", "microchip,sam9x60-pit64b"; + reg = <0xe1800000 0x4000>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 66>, <&pmc PMC_TYPE_GCK 66>; + clock-names = "pclk", "gclk"; + interrupt-parent = <&gic>; + interrupts = ; + }; + + pmc: clock-controller@e0018000 { + compatible = "microchip,sam-pmc"; + reg = <0xe0018000 0x200>; + #clock-cells = <2>; + clocks = <&clk32k 1>, <&clk32k 0>, <&main_xtal>; + clock-names = "td_slck", "md_slck", "main_xtal"; + }; + }; +}; From 6154c28a6dd178c4e8b302c1d44b4909680b3540 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Tue, 1 Jul 2025 14:14:01 +0800 Subject: [PATCH 8/9] boards: microchip: add new board sama7d65 Curiosity Kit Product URL: https://www.microchip.com/en-us/development-tool/EV63J76A Signed-off-by: Tony Han --- .../Kconfig.sama7d65_curiosity | 7 ++ .../sam/sama7d65_curiosity/board.yml | 6 + .../doc/img/sama7d65_curiosity.webp | Bin 0 -> 56576 bytes .../sam/sama7d65_curiosity/doc/index.rst | 109 ++++++++++++++++++ .../sama7d65_curiosity.yaml | 14 +++ .../sama7d65_curiosity_defconfig | 9 ++ 6 files changed, 145 insertions(+) create mode 100644 boards/microchip/sam/sama7d65_curiosity/Kconfig.sama7d65_curiosity create mode 100644 boards/microchip/sam/sama7d65_curiosity/board.yml create mode 100644 boards/microchip/sam/sama7d65_curiosity/doc/img/sama7d65_curiosity.webp create mode 100644 boards/microchip/sam/sama7d65_curiosity/doc/index.rst create mode 100644 boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.yaml create mode 100644 boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity_defconfig diff --git a/boards/microchip/sam/sama7d65_curiosity/Kconfig.sama7d65_curiosity b/boards/microchip/sam/sama7d65_curiosity/Kconfig.sama7d65_curiosity new file mode 100644 index 0000000000000..5556c4d81b09f --- /dev/null +++ b/boards/microchip/sam/sama7d65_curiosity/Kconfig.sama7d65_curiosity @@ -0,0 +1,7 @@ +# Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries +# +# SPDX-License-Identifier: Apache-2.0 +# + +config BOARD_SAMA7D65_CURIOSITY + select SOC_SAMA7D65 diff --git a/boards/microchip/sam/sama7d65_curiosity/board.yml b/boards/microchip/sam/sama7d65_curiosity/board.yml new file mode 100644 index 0000000000000..324e86c23c1c3 --- /dev/null +++ b/boards/microchip/sam/sama7d65_curiosity/board.yml @@ -0,0 +1,6 @@ +board: + name: sama7d65_curiosity + full_name: SAMA7D65 Curiosity Kit + vendor: microchip + socs: + - name: sama7d65 diff --git a/boards/microchip/sam/sama7d65_curiosity/doc/img/sama7d65_curiosity.webp b/boards/microchip/sam/sama7d65_curiosity/doc/img/sama7d65_curiosity.webp new file mode 100644 index 0000000000000000000000000000000000000000..a0d44e8e3a850462e44726fb71ced7863ac5813a GIT binary patch literal 56576 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 literal 0 HcmV?d00001 diff --git a/boards/microchip/sam/sama7d65_curiosity/doc/index.rst b/boards/microchip/sam/sama7d65_curiosity/doc/index.rst new file mode 100644 index 0000000000000..f374b1f2fdd99 --- /dev/null +++ b/boards/microchip/sam/sama7d65_curiosity/doc/index.rst @@ -0,0 +1,109 @@ +.. zephyr:board:: sama7d65_curiosity + +Overview +******** + +The EV63J76A (SAMA7D65 Curiosity Kit) is a development kit for evaluating and +prototyping with Microchip SAMA7D65 microprocessor (MPU). The SAMA7D65 MPU is a +high-performance ARM Cortex-A7 CPU-based embedded MPU running up to 1GHz. + +The board allows evaluation of powerful peripherals for connectivity, audio and +user interface applications, including MIPI-DSI and LVDS w/ 2D graphics, dual +Gigabit Ethernet w/ TSN and CAN-FD. The MPUs offer advanced security functions, +like tamper detection, secure boot, secure key stoarge, TRNG, PUF as well as +higher-performance crypto accelerators for AES and SHA. + +The SAMA7D65 series is supported by Microchip MPLAB-X development tools, Harmony +V3, Linux distributions and Microchip Graphic Suite (MGS) for Linux. The +SAMA7D65 is well-suited for industrial and automotive applications with +graphical displays support up to WXGA/720p. + +Hardware +******** +EV63J76A provides the following hardware components: + +- Processor + + - Microchip SAMA7D65-V/4HB (SoC 343-ball TFBGA, 14x14 mm, 0.65 mm pitch) + +- Memory + + - 8 Gb DDR3L (AS4C512M16D3LA-10BIN) + - 64 Mb QSPI NOR Flash with EUI-48 (Microchip SST26VF064BEUI-104I/MF) + - 4Gbit SLC NAND Flash (MX30LF4G28AD-XKI) + - 2Kb EEPROM with EUI-48 (Microchip 24AA025E48) + +- SD/MMC + + - One SD card socket, 4 bit + - One M.2 Radio Module interface, SDIO I/F + +- USB + + - One device USB Type-C connector + - Two host USB Type-A connectors (Microchip MIC2026-1YM) + +- Ethernet + + - One 10/100/1000 RGMII on board + - One 10/100/1000 RGMII SODIMM add-on slot (Microchip LAN8840-V/PSA) + +- Display + + - One MIPI-DSI 34-pin FPC connector + - One LVDS 30-pin FPC connector + +- Debug port + + - One UART Debug connector + - One JTAG interface + +- User interaction + + - One RGB (Red, Green, Blue) LED + - Four push button switches + +- CAN-FD + + - Three onboard CAN-FD transceivers + - Two interfaces available on mikroBUS slots + +- Expansion + + - Raspberry Pi 40-pin GPIO connector + - Two mikroBUS™ connectors + - Two PIOBU/System headers + +- Power management + + - Power Supply Unit (Microchip MCP16502TAB-E/S8B) + - Power Monitoring (Microchip PAC1934) + - Daughter cards power supply (Microchip MIC23450-AAAYML-TR) + - Backup power supply (CR1220 battery holder) + +- Board supply + + - System 5 VDC from USB Type-C + - System 5 VDC from DC Jack + +Supported Features +================== + +.. zephyr:board-supported-hw:: + +Connections and IOs +=================== + +The `SAMA7D65-Curiosity Kit User Guide`_ has detailed information about board connections. + +References +********** + +SAMA7D65 Product Page: + https://www.microchip.com/en-us/product/sama7d65 + +SAMA7D65 Curiosity Kit Page: + https://www.microchip.com/en-us/development-tool/EV63J76A + +.. _SAMA7D65-Curiosity Kit User Guide: + https://ww1.microchip.com/downloads/aemDocuments/documents/MPU32/ProductDocuments/UserGuides/SAMA7D65-Curiosity-Kit-User-Guide-DS50003806.pdf diff --git a/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.yaml b/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.yaml new file mode 100644 index 0000000000000..c8a1692f0e19c --- /dev/null +++ b/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.yaml @@ -0,0 +1,14 @@ +# Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries +# SPDX-License-Identifier: Apache-2.0 + +identifier: sama7d65_curiosity +name: SAMA7D65 Curiosity Kit +type: mcu +arch: arm +toolchain: + - zephyr +ram: 128 +supported: + - shell + - uart +vendor: microchip diff --git a/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity_defconfig b/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity_defconfig new file mode 100644 index 0000000000000..10b06d0f7f423 --- /dev/null +++ b/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity_defconfig @@ -0,0 +1,9 @@ +# Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK=y +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y From 30324560ad0b38d86cb400a92a1c1abe12c1e2f3 Mon Sep 17 00:00:00 2001 From: Tony Han Date: Tue, 1 Jul 2025 14:15:10 +0800 Subject: [PATCH 9/9] boards: microchip: sam: add device-tree file for sama7d65_curiosity Introduce sama7d65_curiosity.dts for sama7d65_curiosity board. Signed-off-by: Tony Han --- .../sama7d65_curiosity/sama7d65_curiosity.dts | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.dts diff --git a/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.dts b/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.dts new file mode 100644 index 0000000000000..36e6a911441b6 --- /dev/null +++ b/boards/microchip/sam/sama7d65_curiosity/sama7d65_curiosity.dts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +/dts-v1/; +#include +#include +#include +#include + +/ { + model = "SAMA7D65-Curiosity board"; + compatible = "microchip,sama7d65curiosity", "microchip,sama7d6", "microchip,sama7"; + + chosen { + zephyr,sram = &ddram; + zephyr,console = &uart6; + zephyr,shell-uart = &uart6; + }; + + clocks { + main_xtal { + clock-frequency = ; + }; + + slow_xtal { + clock-frequency = <32768>; + }; + }; + + ddram: ddram@60000000 { + compatible = "ddram"; + reg = <0x60000000 DT_SIZE_M(1024)>; + }; +}; + +&flx6 { + mchp,flexcom-mode = ; + status = "okay"; + + uart6: serial@200 { + current-speed = <115200>; + pinctrl-0 = <&pinctrl_uart6_default>; + pinctrl-names = "default"; + status = "okay"; + }; +}; + +&pinctrl { + pinctrl_uart6_default: uart6-default { + group1 { + pinmux = , + ; + bias-disable; + }; + }; +}; + +&pit64b0 { + clock-frequency = ; +};