^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2013 Pengutronix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <dt-bindings/clock/efm32-cmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define CMU_HFPERCLKEN0 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define CMU_MAX_CLKS 37
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static struct clk_hw_onecell_data *clk_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static void __init efm32gg_cmu_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct clk_hw **hws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) clk_data = kzalloc(struct_size(clk_data, hws, CMU_MAX_CLKS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (!clk_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) hws = clk_data->hws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) for (i = 0; i < CMU_MAX_CLKS; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) hws[i] = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pr_warn("Failed to map address range for efm32gg,cmu node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) hws[clk_HFXO] = clk_hw_register_fixed_rate(NULL, "HFXO", NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) 48000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) hws[clk_HFPERCLKUSART0] = clk_hw_register_gate(NULL, "HFPERCLK.USART0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) "HFXO", 0, base + CMU_HFPERCLKEN0, 0, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) hws[clk_HFPERCLKUSART1] = clk_hw_register_gate(NULL, "HFPERCLK.USART1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "HFXO", 0, base + CMU_HFPERCLKEN0, 1, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) hws[clk_HFPERCLKUSART2] = clk_hw_register_gate(NULL, "HFPERCLK.USART2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) "HFXO", 0, base + CMU_HFPERCLKEN0, 2, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) hws[clk_HFPERCLKUART0] = clk_hw_register_gate(NULL, "HFPERCLK.UART0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "HFXO", 0, base + CMU_HFPERCLKEN0, 3, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) hws[clk_HFPERCLKUART1] = clk_hw_register_gate(NULL, "HFPERCLK.UART1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) "HFXO", 0, base + CMU_HFPERCLKEN0, 4, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) hws[clk_HFPERCLKTIMER0] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) "HFXO", 0, base + CMU_HFPERCLKEN0, 5, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) hws[clk_HFPERCLKTIMER1] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "HFXO", 0, base + CMU_HFPERCLKEN0, 6, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) hws[clk_HFPERCLKTIMER2] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) "HFXO", 0, base + CMU_HFPERCLKEN0, 7, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) hws[clk_HFPERCLKTIMER3] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) "HFXO", 0, base + CMU_HFPERCLKEN0, 8, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) hws[clk_HFPERCLKACMP0] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) "HFXO", 0, base + CMU_HFPERCLKEN0, 9, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) hws[clk_HFPERCLKACMP1] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) "HFXO", 0, base + CMU_HFPERCLKEN0, 10, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) hws[clk_HFPERCLKI2C0] = clk_hw_register_gate(NULL, "HFPERCLK.I2C0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "HFXO", 0, base + CMU_HFPERCLKEN0, 11, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) hws[clk_HFPERCLKI2C1] = clk_hw_register_gate(NULL, "HFPERCLK.I2C1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) "HFXO", 0, base + CMU_HFPERCLKEN0, 12, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) hws[clk_HFPERCLKGPIO] = clk_hw_register_gate(NULL, "HFPERCLK.GPIO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "HFXO", 0, base + CMU_HFPERCLKEN0, 13, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) hws[clk_HFPERCLKVCMP] = clk_hw_register_gate(NULL, "HFPERCLK.VCMP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "HFXO", 0, base + CMU_HFPERCLKEN0, 14, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) hws[clk_HFPERCLKPRS] = clk_hw_register_gate(NULL, "HFPERCLK.PRS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) "HFXO", 0, base + CMU_HFPERCLKEN0, 15, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) hws[clk_HFPERCLKADC0] = clk_hw_register_gate(NULL, "HFPERCLK.ADC0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) "HFXO", 0, base + CMU_HFPERCLKEN0, 16, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) hws[clk_HFPERCLKDAC0] = clk_hw_register_gate(NULL, "HFPERCLK.DAC0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init);