18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2013 Pengutronix 48c2ecf20Sopenharmony_ci * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include <linux/io.h> 78c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 88c2ecf20Sopenharmony_ci#include <linux/of.h> 98c2ecf20Sopenharmony_ci#include <linux/of_address.h> 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <dt-bindings/clock/efm32-cmu.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define CMU_HFPERCLKEN0 0x44 158c2ecf20Sopenharmony_ci#define CMU_MAX_CLKS 37 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic struct clk_hw_onecell_data *clk_data; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic void __init efm32gg_cmu_init(struct device_node *np) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci int i; 228c2ecf20Sopenharmony_ci void __iomem *base; 238c2ecf20Sopenharmony_ci struct clk_hw **hws; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci clk_data = kzalloc(struct_size(clk_data, hws, CMU_MAX_CLKS), 268c2ecf20Sopenharmony_ci GFP_KERNEL); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci if (!clk_data) 298c2ecf20Sopenharmony_ci return; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci hws = clk_data->hws; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci for (i = 0; i < CMU_MAX_CLKS; ++i) 348c2ecf20Sopenharmony_ci hws[i] = ERR_PTR(-ENOENT); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci base = of_iomap(np, 0); 378c2ecf20Sopenharmony_ci if (!base) { 388c2ecf20Sopenharmony_ci pr_warn("Failed to map address range for efm32gg,cmu node\n"); 398c2ecf20Sopenharmony_ci return; 408c2ecf20Sopenharmony_ci } 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci hws[clk_HFXO] = clk_hw_register_fixed_rate(NULL, "HFXO", NULL, 0, 438c2ecf20Sopenharmony_ci 48000000); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci hws[clk_HFPERCLKUSART0] = clk_hw_register_gate(NULL, "HFPERCLK.USART0", 468c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 0, 0, NULL); 478c2ecf20Sopenharmony_ci hws[clk_HFPERCLKUSART1] = clk_hw_register_gate(NULL, "HFPERCLK.USART1", 488c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 1, 0, NULL); 498c2ecf20Sopenharmony_ci hws[clk_HFPERCLKUSART2] = clk_hw_register_gate(NULL, "HFPERCLK.USART2", 508c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 2, 0, NULL); 518c2ecf20Sopenharmony_ci hws[clk_HFPERCLKUART0] = clk_hw_register_gate(NULL, "HFPERCLK.UART0", 528c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 3, 0, NULL); 538c2ecf20Sopenharmony_ci hws[clk_HFPERCLKUART1] = clk_hw_register_gate(NULL, "HFPERCLK.UART1", 548c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 4, 0, NULL); 558c2ecf20Sopenharmony_ci hws[clk_HFPERCLKTIMER0] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER0", 568c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 5, 0, NULL); 578c2ecf20Sopenharmony_ci hws[clk_HFPERCLKTIMER1] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER1", 588c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 6, 0, NULL); 598c2ecf20Sopenharmony_ci hws[clk_HFPERCLKTIMER2] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER2", 608c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 7, 0, NULL); 618c2ecf20Sopenharmony_ci hws[clk_HFPERCLKTIMER3] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER3", 628c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 8, 0, NULL); 638c2ecf20Sopenharmony_ci hws[clk_HFPERCLKACMP0] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP0", 648c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 9, 0, NULL); 658c2ecf20Sopenharmony_ci hws[clk_HFPERCLKACMP1] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP1", 668c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 10, 0, NULL); 678c2ecf20Sopenharmony_ci hws[clk_HFPERCLKI2C0] = clk_hw_register_gate(NULL, "HFPERCLK.I2C0", 688c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 11, 0, NULL); 698c2ecf20Sopenharmony_ci hws[clk_HFPERCLKI2C1] = clk_hw_register_gate(NULL, "HFPERCLK.I2C1", 708c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 12, 0, NULL); 718c2ecf20Sopenharmony_ci hws[clk_HFPERCLKGPIO] = clk_hw_register_gate(NULL, "HFPERCLK.GPIO", 728c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 13, 0, NULL); 738c2ecf20Sopenharmony_ci hws[clk_HFPERCLKVCMP] = clk_hw_register_gate(NULL, "HFPERCLK.VCMP", 748c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 14, 0, NULL); 758c2ecf20Sopenharmony_ci hws[clk_HFPERCLKPRS] = clk_hw_register_gate(NULL, "HFPERCLK.PRS", 768c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 15, 0, NULL); 778c2ecf20Sopenharmony_ci hws[clk_HFPERCLKADC0] = clk_hw_register_gate(NULL, "HFPERCLK.ADC0", 788c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 16, 0, NULL); 798c2ecf20Sopenharmony_ci hws[clk_HFPERCLKDAC0] = clk_hw_register_gate(NULL, "HFPERCLK.DAC0", 808c2ecf20Sopenharmony_ci "HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ciCLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init); 85