162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Clock driver for the ARM Integrator/AP, Integrator/CP, Versatile AB and 462306a36Sopenharmony_ci * Versatile PB boards. 562306a36Sopenharmony_ci * Copyright (C) 2012 Linus Walleij 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/clk-provider.h> 862306a36Sopenharmony_ci#include <linux/err.h> 962306a36Sopenharmony_ci#include <linux/of.h> 1062306a36Sopenharmony_ci#include <linux/of_address.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "icst.h" 1362306a36Sopenharmony_ci#include "clk-icst.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define INTEGRATOR_HDR_LOCK_OFFSET 0x14 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define VERSATILE_SYS_OSCCLCD_OFFSET 0x1c 1862306a36Sopenharmony_ci#define VERSATILE_SYS_LOCK_OFFSET 0x20 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* Base offset for the core module */ 2162306a36Sopenharmony_cistatic void __iomem *cm_base; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic const struct icst_params cp_auxosc_params = { 2462306a36Sopenharmony_ci .vco_max = ICST525_VCO_MAX_5V, 2562306a36Sopenharmony_ci .vco_min = ICST525_VCO_MIN, 2662306a36Sopenharmony_ci .vd_min = 8, 2762306a36Sopenharmony_ci .vd_max = 263, 2862306a36Sopenharmony_ci .rd_min = 3, 2962306a36Sopenharmony_ci .rd_max = 65, 3062306a36Sopenharmony_ci .s2div = icst525_s2div, 3162306a36Sopenharmony_ci .idx2s = icst525_idx2s, 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic const struct clk_icst_desc cm_auxosc_desc __initconst = { 3562306a36Sopenharmony_ci .params = &cp_auxosc_params, 3662306a36Sopenharmony_ci .vco_offset = 0x1c, 3762306a36Sopenharmony_ci .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic const struct icst_params versatile_auxosc_params = { 4162306a36Sopenharmony_ci .vco_max = ICST307_VCO_MAX, 4262306a36Sopenharmony_ci .vco_min = ICST307_VCO_MIN, 4362306a36Sopenharmony_ci .vd_min = 4 + 8, 4462306a36Sopenharmony_ci .vd_max = 511 + 8, 4562306a36Sopenharmony_ci .rd_min = 1 + 2, 4662306a36Sopenharmony_ci .rd_max = 127 + 2, 4762306a36Sopenharmony_ci .s2div = icst307_s2div, 4862306a36Sopenharmony_ci .idx2s = icst307_idx2s, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic const struct clk_icst_desc versatile_auxosc_desc __initconst = { 5262306a36Sopenharmony_ci .params = &versatile_auxosc_params, 5362306a36Sopenharmony_ci .vco_offset = VERSATILE_SYS_OSCCLCD_OFFSET, 5462306a36Sopenharmony_ci .lock_offset = VERSATILE_SYS_LOCK_OFFSET, 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_cistatic void __init cm_osc_setup(struct device_node *np, 5762306a36Sopenharmony_ci const struct clk_icst_desc *desc) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct clk *clk; 6062306a36Sopenharmony_ci const char *clk_name = np->name; 6162306a36Sopenharmony_ci const char *parent_name; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (!cm_base) { 6462306a36Sopenharmony_ci /* Remap the core module base if not done yet */ 6562306a36Sopenharmony_ci struct device_node *parent; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci parent = of_get_parent(np); 6862306a36Sopenharmony_ci if (!parent) { 6962306a36Sopenharmony_ci pr_err("no parent on core module clock\n"); 7062306a36Sopenharmony_ci return; 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci cm_base = of_iomap(parent, 0); 7362306a36Sopenharmony_ci of_node_put(parent); 7462306a36Sopenharmony_ci if (!cm_base) { 7562306a36Sopenharmony_ci pr_err("could not remap core module base\n"); 7662306a36Sopenharmony_ci return; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci parent_name = of_clk_get_parent_name(np, 0); 8162306a36Sopenharmony_ci clk = icst_clk_register(NULL, desc, clk_name, parent_name, cm_base); 8262306a36Sopenharmony_ci if (!IS_ERR(clk)) 8362306a36Sopenharmony_ci of_clk_add_provider(np, of_clk_src_simple_get, clk); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic void __init of_integrator_cm_osc_setup(struct device_node *np) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci cm_osc_setup(np, &cm_auxosc_desc); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ciCLK_OF_DECLARE(integrator_cm_auxosc_clk, 9162306a36Sopenharmony_ci "arm,integrator-cm-auxosc", of_integrator_cm_osc_setup); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic void __init of_versatile_cm_osc_setup(struct device_node *np) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci cm_osc_setup(np, &versatile_auxosc_desc); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ciCLK_OF_DECLARE(versatile_cm_auxosc_clk, 9862306a36Sopenharmony_ci "arm,versatile-cm-auxosc", of_versatile_cm_osc_setup); 99