162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2013 Broadcom Corporation 462306a36Sopenharmony_ci * Copyright 2013 Linaro Limited 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/io.h> 862306a36Sopenharmony_ci#include <linux/of_address.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "clk-kona.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* These are used when a selector or trigger is found to be unneeded */ 1362306a36Sopenharmony_ci#define selector_clear_exists(sel) ((sel)->width = 0) 1462306a36Sopenharmony_ci#define trigger_clear_exists(trig) FLAG_CLEAR(trig, TRIG, EXISTS) 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* Validity checking */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic bool ccu_data_offsets_valid(struct ccu_data *ccu) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci struct ccu_policy *ccu_policy = &ccu->policy; 2162306a36Sopenharmony_ci u32 limit; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci limit = ccu->range - sizeof(u32); 2462306a36Sopenharmony_ci limit = round_down(limit, sizeof(u32)); 2562306a36Sopenharmony_ci if (ccu_policy_exists(ccu_policy)) { 2662306a36Sopenharmony_ci if (ccu_policy->enable.offset > limit) { 2762306a36Sopenharmony_ci pr_err("%s: bad policy enable offset for %s " 2862306a36Sopenharmony_ci "(%u > %u)\n", __func__, 2962306a36Sopenharmony_ci ccu->name, ccu_policy->enable.offset, limit); 3062306a36Sopenharmony_ci return false; 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci if (ccu_policy->control.offset > limit) { 3362306a36Sopenharmony_ci pr_err("%s: bad policy control offset for %s " 3462306a36Sopenharmony_ci "(%u > %u)\n", __func__, 3562306a36Sopenharmony_ci ccu->name, ccu_policy->control.offset, limit); 3662306a36Sopenharmony_ci return false; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci return true; 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic bool clk_requires_trigger(struct kona_clk *bcm_clk) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci struct peri_clk_data *peri = bcm_clk->u.peri; 4662306a36Sopenharmony_ci struct bcm_clk_sel *sel; 4762306a36Sopenharmony_ci struct bcm_clk_div *div; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci if (bcm_clk->type != bcm_clk_peri) 5062306a36Sopenharmony_ci return false; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci sel = &peri->sel; 5362306a36Sopenharmony_ci if (sel->parent_count && selector_exists(sel)) 5462306a36Sopenharmony_ci return true; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci div = &peri->div; 5762306a36Sopenharmony_ci if (!divider_exists(div)) 5862306a36Sopenharmony_ci return false; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci /* Fixed dividers don't need triggers */ 6162306a36Sopenharmony_ci if (!divider_is_fixed(div)) 6262306a36Sopenharmony_ci return true; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci div = &peri->pre_div; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return divider_exists(div) && !divider_is_fixed(div); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct peri_clk_data *peri; 7262306a36Sopenharmony_ci struct bcm_clk_policy *policy; 7362306a36Sopenharmony_ci struct bcm_clk_gate *gate; 7462306a36Sopenharmony_ci struct bcm_clk_hyst *hyst; 7562306a36Sopenharmony_ci struct bcm_clk_div *div; 7662306a36Sopenharmony_ci struct bcm_clk_sel *sel; 7762306a36Sopenharmony_ci struct bcm_clk_trig *trig; 7862306a36Sopenharmony_ci const char *name; 7962306a36Sopenharmony_ci u32 range; 8062306a36Sopenharmony_ci u32 limit; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci BUG_ON(bcm_clk->type != bcm_clk_peri); 8362306a36Sopenharmony_ci peri = bcm_clk->u.peri; 8462306a36Sopenharmony_ci name = bcm_clk->init_data.name; 8562306a36Sopenharmony_ci range = bcm_clk->ccu->range; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci limit = range - sizeof(u32); 8862306a36Sopenharmony_ci limit = round_down(limit, sizeof(u32)); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci policy = &peri->policy; 9162306a36Sopenharmony_ci if (policy_exists(policy)) { 9262306a36Sopenharmony_ci if (policy->offset > limit) { 9362306a36Sopenharmony_ci pr_err("%s: bad policy offset for %s (%u > %u)\n", 9462306a36Sopenharmony_ci __func__, name, policy->offset, limit); 9562306a36Sopenharmony_ci return false; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci gate = &peri->gate; 10062306a36Sopenharmony_ci hyst = &peri->hyst; 10162306a36Sopenharmony_ci if (gate_exists(gate)) { 10262306a36Sopenharmony_ci if (gate->offset > limit) { 10362306a36Sopenharmony_ci pr_err("%s: bad gate offset for %s (%u > %u)\n", 10462306a36Sopenharmony_ci __func__, name, gate->offset, limit); 10562306a36Sopenharmony_ci return false; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (hyst_exists(hyst)) { 10962306a36Sopenharmony_ci if (hyst->offset > limit) { 11062306a36Sopenharmony_ci pr_err("%s: bad hysteresis offset for %s " 11162306a36Sopenharmony_ci "(%u > %u)\n", __func__, 11262306a36Sopenharmony_ci name, hyst->offset, limit); 11362306a36Sopenharmony_ci return false; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci } else if (hyst_exists(hyst)) { 11762306a36Sopenharmony_ci pr_err("%s: hysteresis but no gate for %s\n", __func__, name); 11862306a36Sopenharmony_ci return false; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci div = &peri->div; 12262306a36Sopenharmony_ci if (divider_exists(div)) { 12362306a36Sopenharmony_ci if (div->u.s.offset > limit) { 12462306a36Sopenharmony_ci pr_err("%s: bad divider offset for %s (%u > %u)\n", 12562306a36Sopenharmony_ci __func__, name, div->u.s.offset, limit); 12662306a36Sopenharmony_ci return false; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci div = &peri->pre_div; 13162306a36Sopenharmony_ci if (divider_exists(div)) { 13262306a36Sopenharmony_ci if (div->u.s.offset > limit) { 13362306a36Sopenharmony_ci pr_err("%s: bad pre-divider offset for %s " 13462306a36Sopenharmony_ci "(%u > %u)\n", 13562306a36Sopenharmony_ci __func__, name, div->u.s.offset, limit); 13662306a36Sopenharmony_ci return false; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci sel = &peri->sel; 14162306a36Sopenharmony_ci if (selector_exists(sel)) { 14262306a36Sopenharmony_ci if (sel->offset > limit) { 14362306a36Sopenharmony_ci pr_err("%s: bad selector offset for %s (%u > %u)\n", 14462306a36Sopenharmony_ci __func__, name, sel->offset, limit); 14562306a36Sopenharmony_ci return false; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci trig = &peri->trig; 15062306a36Sopenharmony_ci if (trigger_exists(trig)) { 15162306a36Sopenharmony_ci if (trig->offset > limit) { 15262306a36Sopenharmony_ci pr_err("%s: bad trigger offset for %s (%u > %u)\n", 15362306a36Sopenharmony_ci __func__, name, trig->offset, limit); 15462306a36Sopenharmony_ci return false; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci trig = &peri->pre_trig; 15962306a36Sopenharmony_ci if (trigger_exists(trig)) { 16062306a36Sopenharmony_ci if (trig->offset > limit) { 16162306a36Sopenharmony_ci pr_err("%s: bad pre-trigger offset for %s (%u > %u)\n", 16262306a36Sopenharmony_ci __func__, name, trig->offset, limit); 16362306a36Sopenharmony_ci return false; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci return true; 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci/* A bit position must be less than the number of bits in a 32-bit register. */ 17162306a36Sopenharmony_cistatic bool bit_posn_valid(u32 bit_posn, const char *field_name, 17262306a36Sopenharmony_ci const char *clock_name) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci u32 limit = BITS_PER_BYTE * sizeof(u32) - 1; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci if (bit_posn > limit) { 17762306a36Sopenharmony_ci pr_err("%s: bad %s bit for %s (%u > %u)\n", __func__, 17862306a36Sopenharmony_ci field_name, clock_name, bit_posn, limit); 17962306a36Sopenharmony_ci return false; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci return true; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/* 18562306a36Sopenharmony_ci * A bitfield must be at least 1 bit wide. Both the low-order and 18662306a36Sopenharmony_ci * high-order bits must lie within a 32-bit register. We require 18762306a36Sopenharmony_ci * fields to be less than 32 bits wide, mainly because we use 18862306a36Sopenharmony_ci * shifting to produce field masks, and shifting a full word width 18962306a36Sopenharmony_ci * is not well-defined by the C standard. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_cistatic bool bitfield_valid(u32 shift, u32 width, const char *field_name, 19262306a36Sopenharmony_ci const char *clock_name) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci u32 limit = BITS_PER_BYTE * sizeof(u32); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (!width) { 19762306a36Sopenharmony_ci pr_err("%s: bad %s field width 0 for %s\n", __func__, 19862306a36Sopenharmony_ci field_name, clock_name); 19962306a36Sopenharmony_ci return false; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci if (shift + width > limit) { 20262306a36Sopenharmony_ci pr_err("%s: bad %s for %s (%u + %u > %u)\n", __func__, 20362306a36Sopenharmony_ci field_name, clock_name, shift, width, limit); 20462306a36Sopenharmony_ci return false; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci return true; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic bool 21062306a36Sopenharmony_ciccu_policy_valid(struct ccu_policy *ccu_policy, const char *ccu_name) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct bcm_lvm_en *enable = &ccu_policy->enable; 21362306a36Sopenharmony_ci struct bcm_policy_ctl *control; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci if (!bit_posn_valid(enable->bit, "policy enable", ccu_name)) 21662306a36Sopenharmony_ci return false; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci control = &ccu_policy->control; 21962306a36Sopenharmony_ci if (!bit_posn_valid(control->go_bit, "policy control GO", ccu_name)) 22062306a36Sopenharmony_ci return false; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (!bit_posn_valid(control->atl_bit, "policy control ATL", ccu_name)) 22362306a36Sopenharmony_ci return false; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (!bit_posn_valid(control->ac_bit, "policy control AC", ccu_name)) 22662306a36Sopenharmony_ci return false; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return true; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic bool policy_valid(struct bcm_clk_policy *policy, const char *clock_name) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci if (!bit_posn_valid(policy->bit, "policy", clock_name)) 23462306a36Sopenharmony_ci return false; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci return true; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci/* 24062306a36Sopenharmony_ci * All gates, if defined, have a status bit, and for hardware-only 24162306a36Sopenharmony_ci * gates, that's it. Gates that can be software controlled also 24262306a36Sopenharmony_ci * have an enable bit. And a gate that can be hardware or software 24362306a36Sopenharmony_ci * controlled will have a hardware/software select bit. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_cistatic bool gate_valid(struct bcm_clk_gate *gate, const char *field_name, 24662306a36Sopenharmony_ci const char *clock_name) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci if (!bit_posn_valid(gate->status_bit, "gate status", clock_name)) 24962306a36Sopenharmony_ci return false; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci if (gate_is_sw_controllable(gate)) { 25262306a36Sopenharmony_ci if (!bit_posn_valid(gate->en_bit, "gate enable", clock_name)) 25362306a36Sopenharmony_ci return false; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (gate_is_hw_controllable(gate)) { 25662306a36Sopenharmony_ci if (!bit_posn_valid(gate->hw_sw_sel_bit, 25762306a36Sopenharmony_ci "gate hw/sw select", 25862306a36Sopenharmony_ci clock_name)) 25962306a36Sopenharmony_ci return false; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci } else { 26262306a36Sopenharmony_ci BUG_ON(!gate_is_hw_controllable(gate)); 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci return true; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic bool hyst_valid(struct bcm_clk_hyst *hyst, const char *clock_name) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci if (!bit_posn_valid(hyst->en_bit, "hysteresis enable", clock_name)) 27162306a36Sopenharmony_ci return false; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (!bit_posn_valid(hyst->val_bit, "hysteresis value", clock_name)) 27462306a36Sopenharmony_ci return false; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci return true; 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci/* 28062306a36Sopenharmony_ci * A selector bitfield must be valid. Its parent_sel array must 28162306a36Sopenharmony_ci * also be reasonable for the field. 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_cistatic bool sel_valid(struct bcm_clk_sel *sel, const char *field_name, 28462306a36Sopenharmony_ci const char *clock_name) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci if (!bitfield_valid(sel->shift, sel->width, field_name, clock_name)) 28762306a36Sopenharmony_ci return false; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci if (sel->parent_count) { 29062306a36Sopenharmony_ci u32 max_sel; 29162306a36Sopenharmony_ci u32 limit; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * Make sure the selector field can hold all the 29562306a36Sopenharmony_ci * selector values we expect to be able to use. A 29662306a36Sopenharmony_ci * clock only needs to have a selector defined if it 29762306a36Sopenharmony_ci * has more than one parent. And in that case the 29862306a36Sopenharmony_ci * highest selector value will be in the last entry 29962306a36Sopenharmony_ci * in the array. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_ci max_sel = sel->parent_sel[sel->parent_count - 1]; 30262306a36Sopenharmony_ci limit = (1 << sel->width) - 1; 30362306a36Sopenharmony_ci if (max_sel > limit) { 30462306a36Sopenharmony_ci pr_err("%s: bad selector for %s " 30562306a36Sopenharmony_ci "(%u needs > %u bits)\n", 30662306a36Sopenharmony_ci __func__, clock_name, max_sel, 30762306a36Sopenharmony_ci sel->width); 30862306a36Sopenharmony_ci return false; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci } else { 31162306a36Sopenharmony_ci pr_warn("%s: ignoring selector for %s (no parents)\n", 31262306a36Sopenharmony_ci __func__, clock_name); 31362306a36Sopenharmony_ci selector_clear_exists(sel); 31462306a36Sopenharmony_ci kfree(sel->parent_sel); 31562306a36Sopenharmony_ci sel->parent_sel = NULL; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci return true; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/* 32262306a36Sopenharmony_ci * A fixed divider just needs to be non-zero. A variable divider 32362306a36Sopenharmony_ci * has to have a valid divider bitfield, and if it has a fraction, 32462306a36Sopenharmony_ci * the width of the fraction must not be no more than the width of 32562306a36Sopenharmony_ci * the divider as a whole. 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_cistatic bool div_valid(struct bcm_clk_div *div, const char *field_name, 32862306a36Sopenharmony_ci const char *clock_name) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci if (divider_is_fixed(div)) { 33162306a36Sopenharmony_ci /* Any fixed divider value but 0 is OK */ 33262306a36Sopenharmony_ci if (div->u.fixed == 0) { 33362306a36Sopenharmony_ci pr_err("%s: bad %s fixed value 0 for %s\n", __func__, 33462306a36Sopenharmony_ci field_name, clock_name); 33562306a36Sopenharmony_ci return false; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci return true; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci if (!bitfield_valid(div->u.s.shift, div->u.s.width, 34062306a36Sopenharmony_ci field_name, clock_name)) 34162306a36Sopenharmony_ci return false; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci if (divider_has_fraction(div)) 34462306a36Sopenharmony_ci if (div->u.s.frac_width > div->u.s.width) { 34562306a36Sopenharmony_ci pr_warn("%s: bad %s fraction width for %s (%u > %u)\n", 34662306a36Sopenharmony_ci __func__, field_name, clock_name, 34762306a36Sopenharmony_ci div->u.s.frac_width, div->u.s.width); 34862306a36Sopenharmony_ci return false; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci return true; 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci/* 35562306a36Sopenharmony_ci * If a clock has two dividers, the combined number of fractional 35662306a36Sopenharmony_ci * bits must be representable in a 32-bit unsigned value. This 35762306a36Sopenharmony_ci * is because we scale up a dividend using both dividers before 35862306a36Sopenharmony_ci * dividing to improve accuracy, and we need to avoid overflow. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_cistatic bool kona_dividers_valid(struct kona_clk *bcm_clk) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci struct peri_clk_data *peri = bcm_clk->u.peri; 36362306a36Sopenharmony_ci struct bcm_clk_div *div; 36462306a36Sopenharmony_ci struct bcm_clk_div *pre_div; 36562306a36Sopenharmony_ci u32 limit; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci BUG_ON(bcm_clk->type != bcm_clk_peri); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (!divider_exists(&peri->div) || !divider_exists(&peri->pre_div)) 37062306a36Sopenharmony_ci return true; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci div = &peri->div; 37362306a36Sopenharmony_ci pre_div = &peri->pre_div; 37462306a36Sopenharmony_ci if (divider_is_fixed(div) || divider_is_fixed(pre_div)) 37562306a36Sopenharmony_ci return true; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci limit = BITS_PER_BYTE * sizeof(u32); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return div->u.s.frac_width + pre_div->u.s.frac_width <= limit; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci/* A trigger just needs to represent a valid bit position */ 38462306a36Sopenharmony_cistatic bool trig_valid(struct bcm_clk_trig *trig, const char *field_name, 38562306a36Sopenharmony_ci const char *clock_name) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci return bit_posn_valid(trig->bit, field_name, clock_name); 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci/* Determine whether the set of peripheral clock registers are valid. */ 39162306a36Sopenharmony_cistatic bool 39262306a36Sopenharmony_ciperi_clk_data_valid(struct kona_clk *bcm_clk) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci struct peri_clk_data *peri; 39562306a36Sopenharmony_ci struct bcm_clk_policy *policy; 39662306a36Sopenharmony_ci struct bcm_clk_gate *gate; 39762306a36Sopenharmony_ci struct bcm_clk_hyst *hyst; 39862306a36Sopenharmony_ci struct bcm_clk_sel *sel; 39962306a36Sopenharmony_ci struct bcm_clk_div *div; 40062306a36Sopenharmony_ci struct bcm_clk_div *pre_div; 40162306a36Sopenharmony_ci struct bcm_clk_trig *trig; 40262306a36Sopenharmony_ci const char *name; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci BUG_ON(bcm_clk->type != bcm_clk_peri); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* 40762306a36Sopenharmony_ci * First validate register offsets. This is the only place 40862306a36Sopenharmony_ci * where we need something from the ccu, so we do these 40962306a36Sopenharmony_ci * together. 41062306a36Sopenharmony_ci */ 41162306a36Sopenharmony_ci if (!peri_clk_data_offsets_valid(bcm_clk)) 41262306a36Sopenharmony_ci return false; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci peri = bcm_clk->u.peri; 41562306a36Sopenharmony_ci name = bcm_clk->init_data.name; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci policy = &peri->policy; 41862306a36Sopenharmony_ci if (policy_exists(policy) && !policy_valid(policy, name)) 41962306a36Sopenharmony_ci return false; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci gate = &peri->gate; 42262306a36Sopenharmony_ci if (gate_exists(gate) && !gate_valid(gate, "gate", name)) 42362306a36Sopenharmony_ci return false; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci hyst = &peri->hyst; 42662306a36Sopenharmony_ci if (hyst_exists(hyst) && !hyst_valid(hyst, name)) 42762306a36Sopenharmony_ci return false; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci sel = &peri->sel; 43062306a36Sopenharmony_ci if (selector_exists(sel)) { 43162306a36Sopenharmony_ci if (!sel_valid(sel, "selector", name)) 43262306a36Sopenharmony_ci return false; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci } else if (sel->parent_count > 1) { 43562306a36Sopenharmony_ci pr_err("%s: multiple parents but no selector for %s\n", 43662306a36Sopenharmony_ci __func__, name); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci return false; 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci div = &peri->div; 44262306a36Sopenharmony_ci pre_div = &peri->pre_div; 44362306a36Sopenharmony_ci if (divider_exists(div)) { 44462306a36Sopenharmony_ci if (!div_valid(div, "divider", name)) 44562306a36Sopenharmony_ci return false; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci if (divider_exists(pre_div)) 44862306a36Sopenharmony_ci if (!div_valid(pre_div, "pre-divider", name)) 44962306a36Sopenharmony_ci return false; 45062306a36Sopenharmony_ci } else if (divider_exists(pre_div)) { 45162306a36Sopenharmony_ci pr_err("%s: pre-divider but no divider for %s\n", __func__, 45262306a36Sopenharmony_ci name); 45362306a36Sopenharmony_ci return false; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci trig = &peri->trig; 45762306a36Sopenharmony_ci if (trigger_exists(trig)) { 45862306a36Sopenharmony_ci if (!trig_valid(trig, "trigger", name)) 45962306a36Sopenharmony_ci return false; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci if (trigger_exists(&peri->pre_trig)) { 46262306a36Sopenharmony_ci if (!trig_valid(trig, "pre-trigger", name)) { 46362306a36Sopenharmony_ci return false; 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci if (!clk_requires_trigger(bcm_clk)) { 46762306a36Sopenharmony_ci pr_warn("%s: ignoring trigger for %s (not needed)\n", 46862306a36Sopenharmony_ci __func__, name); 46962306a36Sopenharmony_ci trigger_clear_exists(trig); 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci } else if (trigger_exists(&peri->pre_trig)) { 47262306a36Sopenharmony_ci pr_err("%s: pre-trigger but no trigger for %s\n", __func__, 47362306a36Sopenharmony_ci name); 47462306a36Sopenharmony_ci return false; 47562306a36Sopenharmony_ci } else if (clk_requires_trigger(bcm_clk)) { 47662306a36Sopenharmony_ci pr_err("%s: required trigger missing for %s\n", __func__, 47762306a36Sopenharmony_ci name); 47862306a36Sopenharmony_ci return false; 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci return kona_dividers_valid(bcm_clk); 48262306a36Sopenharmony_ci} 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_cistatic bool kona_clk_valid(struct kona_clk *bcm_clk) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci switch (bcm_clk->type) { 48762306a36Sopenharmony_ci case bcm_clk_peri: 48862306a36Sopenharmony_ci if (!peri_clk_data_valid(bcm_clk)) 48962306a36Sopenharmony_ci return false; 49062306a36Sopenharmony_ci break; 49162306a36Sopenharmony_ci default: 49262306a36Sopenharmony_ci pr_err("%s: unrecognized clock type (%d)\n", __func__, 49362306a36Sopenharmony_ci (int)bcm_clk->type); 49462306a36Sopenharmony_ci return false; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci return true; 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci/* 50062306a36Sopenharmony_ci * Scan an array of parent clock names to determine whether there 50162306a36Sopenharmony_ci * are any entries containing BAD_CLK_NAME. Such entries are 50262306a36Sopenharmony_ci * placeholders for non-supported clocks. Keep track of the 50362306a36Sopenharmony_ci * position of each clock name in the original array. 50462306a36Sopenharmony_ci * 50562306a36Sopenharmony_ci * Allocates an array of pointers to hold the names of all 50662306a36Sopenharmony_ci * non-null entries in the original array, and returns a pointer to 50762306a36Sopenharmony_ci * that array in *names. This will be used for registering the 50862306a36Sopenharmony_ci * clock with the common clock code. On successful return, 50962306a36Sopenharmony_ci * *count indicates how many entries are in that names array. 51062306a36Sopenharmony_ci * 51162306a36Sopenharmony_ci * If there is more than one entry in the resulting names array, 51262306a36Sopenharmony_ci * another array is allocated to record the parent selector value 51362306a36Sopenharmony_ci * for each (defined) parent clock. This is the value that 51462306a36Sopenharmony_ci * represents this parent clock in the clock's source selector 51562306a36Sopenharmony_ci * register. The position of the clock in the original parent array 51662306a36Sopenharmony_ci * defines that selector value. The number of entries in this array 51762306a36Sopenharmony_ci * is the same as the number of entries in the parent names array. 51862306a36Sopenharmony_ci * 51962306a36Sopenharmony_ci * The array of selector values is returned. If the clock has no 52062306a36Sopenharmony_ci * parents, no selector is required and a null pointer is returned. 52162306a36Sopenharmony_ci * 52262306a36Sopenharmony_ci * Returns a null pointer if the clock names array supplied was 52362306a36Sopenharmony_ci * null. (This is not an error.) 52462306a36Sopenharmony_ci * 52562306a36Sopenharmony_ci * Returns a pointer-coded error if an error occurs. 52662306a36Sopenharmony_ci */ 52762306a36Sopenharmony_cistatic u32 *parent_process(const char *clocks[], 52862306a36Sopenharmony_ci u32 *count, const char ***names) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci static const char **parent_names; 53162306a36Sopenharmony_ci static u32 *parent_sel; 53262306a36Sopenharmony_ci const char **clock; 53362306a36Sopenharmony_ci u32 parent_count; 53462306a36Sopenharmony_ci u32 bad_count = 0; 53562306a36Sopenharmony_ci u32 orig_count; 53662306a36Sopenharmony_ci u32 i; 53762306a36Sopenharmony_ci u32 j; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci *count = 0; /* In case of early return */ 54062306a36Sopenharmony_ci *names = NULL; 54162306a36Sopenharmony_ci if (!clocks) 54262306a36Sopenharmony_ci return NULL; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci /* 54562306a36Sopenharmony_ci * Count the number of names in the null-terminated array, 54662306a36Sopenharmony_ci * and find out how many of those are actually clock names. 54762306a36Sopenharmony_ci */ 54862306a36Sopenharmony_ci for (clock = clocks; *clock; clock++) 54962306a36Sopenharmony_ci if (*clock == BAD_CLK_NAME) 55062306a36Sopenharmony_ci bad_count++; 55162306a36Sopenharmony_ci orig_count = (u32)(clock - clocks); 55262306a36Sopenharmony_ci parent_count = orig_count - bad_count; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* If all clocks are unsupported, we treat it as no clock */ 55562306a36Sopenharmony_ci if (!parent_count) 55662306a36Sopenharmony_ci return NULL; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci /* Avoid exceeding our parent clock limit */ 55962306a36Sopenharmony_ci if (parent_count > PARENT_COUNT_MAX) { 56062306a36Sopenharmony_ci pr_err("%s: too many parents (%u > %u)\n", __func__, 56162306a36Sopenharmony_ci parent_count, PARENT_COUNT_MAX); 56262306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci /* 56662306a36Sopenharmony_ci * There is one parent name for each defined parent clock. 56762306a36Sopenharmony_ci * We also maintain an array containing the selector value 56862306a36Sopenharmony_ci * for each defined clock. If there's only one clock, the 56962306a36Sopenharmony_ci * selector is not required, but we allocate space for the 57062306a36Sopenharmony_ci * array anyway to keep things simple. 57162306a36Sopenharmony_ci */ 57262306a36Sopenharmony_ci parent_names = kmalloc_array(parent_count, sizeof(*parent_names), 57362306a36Sopenharmony_ci GFP_KERNEL); 57462306a36Sopenharmony_ci if (!parent_names) 57562306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci /* There is at least one parent, so allocate a selector array */ 57862306a36Sopenharmony_ci parent_sel = kmalloc_array(parent_count, sizeof(*parent_sel), 57962306a36Sopenharmony_ci GFP_KERNEL); 58062306a36Sopenharmony_ci if (!parent_sel) { 58162306a36Sopenharmony_ci kfree(parent_names); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 58462306a36Sopenharmony_ci } 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci /* Now fill in the parent names and selector arrays */ 58762306a36Sopenharmony_ci for (i = 0, j = 0; i < orig_count; i++) { 58862306a36Sopenharmony_ci if (clocks[i] != BAD_CLK_NAME) { 58962306a36Sopenharmony_ci parent_names[j] = clocks[i]; 59062306a36Sopenharmony_ci parent_sel[j] = i; 59162306a36Sopenharmony_ci j++; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci *names = parent_names; 59562306a36Sopenharmony_ci *count = parent_count; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci return parent_sel; 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic int 60162306a36Sopenharmony_ciclk_sel_setup(const char **clocks, struct bcm_clk_sel *sel, 60262306a36Sopenharmony_ci struct clk_init_data *init_data) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci const char **parent_names = NULL; 60562306a36Sopenharmony_ci u32 parent_count = 0; 60662306a36Sopenharmony_ci u32 *parent_sel; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* 60962306a36Sopenharmony_ci * If a peripheral clock has multiple parents, the value 61062306a36Sopenharmony_ci * used by the hardware to select that parent is represented 61162306a36Sopenharmony_ci * by the parent clock's position in the "clocks" list. Some 61262306a36Sopenharmony_ci * values don't have defined or supported clocks; these will 61362306a36Sopenharmony_ci * have BAD_CLK_NAME entries in the parents[] array. The 61462306a36Sopenharmony_ci * list is terminated by a NULL entry. 61562306a36Sopenharmony_ci * 61662306a36Sopenharmony_ci * We need to supply (only) the names of defined parent 61762306a36Sopenharmony_ci * clocks when registering a clock though, so we use an 61862306a36Sopenharmony_ci * array of parent selector values to map between the 61962306a36Sopenharmony_ci * indexes the common clock code uses and the selector 62062306a36Sopenharmony_ci * values we need. 62162306a36Sopenharmony_ci */ 62262306a36Sopenharmony_ci parent_sel = parent_process(clocks, &parent_count, &parent_names); 62362306a36Sopenharmony_ci if (IS_ERR(parent_sel)) { 62462306a36Sopenharmony_ci int ret = PTR_ERR(parent_sel); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci pr_err("%s: error processing parent clocks for %s (%d)\n", 62762306a36Sopenharmony_ci __func__, init_data->name, ret); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci return ret; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci init_data->parent_names = parent_names; 63362306a36Sopenharmony_ci init_data->num_parents = parent_count; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci sel->parent_count = parent_count; 63662306a36Sopenharmony_ci sel->parent_sel = parent_sel; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci return 0; 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic void clk_sel_teardown(struct bcm_clk_sel *sel, 64262306a36Sopenharmony_ci struct clk_init_data *init_data) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci kfree(sel->parent_sel); 64562306a36Sopenharmony_ci sel->parent_sel = NULL; 64662306a36Sopenharmony_ci sel->parent_count = 0; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci init_data->num_parents = 0; 64962306a36Sopenharmony_ci kfree(init_data->parent_names); 65062306a36Sopenharmony_ci init_data->parent_names = NULL; 65162306a36Sopenharmony_ci} 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_cistatic void peri_clk_teardown(struct peri_clk_data *data, 65462306a36Sopenharmony_ci struct clk_init_data *init_data) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci clk_sel_teardown(&data->sel, init_data); 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci/* 66062306a36Sopenharmony_ci * Caller is responsible for freeing the parent_names[] and 66162306a36Sopenharmony_ci * parent_sel[] arrays in the peripheral clock's "data" structure 66262306a36Sopenharmony_ci * that can be assigned if the clock has one or more parent clocks 66362306a36Sopenharmony_ci * associated with it. 66462306a36Sopenharmony_ci */ 66562306a36Sopenharmony_cistatic int 66662306a36Sopenharmony_ciperi_clk_setup(struct peri_clk_data *data, struct clk_init_data *init_data) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci init_data->flags = CLK_IGNORE_UNUSED; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci return clk_sel_setup(data->clocks, &data->sel, init_data); 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic void bcm_clk_teardown(struct kona_clk *bcm_clk) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci switch (bcm_clk->type) { 67662306a36Sopenharmony_ci case bcm_clk_peri: 67762306a36Sopenharmony_ci peri_clk_teardown(bcm_clk->u.data, &bcm_clk->init_data); 67862306a36Sopenharmony_ci break; 67962306a36Sopenharmony_ci default: 68062306a36Sopenharmony_ci break; 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci bcm_clk->u.data = NULL; 68362306a36Sopenharmony_ci bcm_clk->type = bcm_clk_none; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic void kona_clk_teardown(struct clk_hw *hw) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct kona_clk *bcm_clk; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci if (!hw) 69162306a36Sopenharmony_ci return; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci clk_hw_unregister(hw); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci bcm_clk = to_kona_clk(hw); 69662306a36Sopenharmony_ci bcm_clk_teardown(bcm_clk); 69762306a36Sopenharmony_ci} 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_cistatic int kona_clk_setup(struct kona_clk *bcm_clk) 70062306a36Sopenharmony_ci{ 70162306a36Sopenharmony_ci int ret; 70262306a36Sopenharmony_ci struct clk_init_data *init_data = &bcm_clk->init_data; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci switch (bcm_clk->type) { 70562306a36Sopenharmony_ci case bcm_clk_peri: 70662306a36Sopenharmony_ci ret = peri_clk_setup(bcm_clk->u.data, init_data); 70762306a36Sopenharmony_ci if (ret) 70862306a36Sopenharmony_ci return ret; 70962306a36Sopenharmony_ci break; 71062306a36Sopenharmony_ci default: 71162306a36Sopenharmony_ci pr_err("%s: clock type %d invalid for %s\n", __func__, 71262306a36Sopenharmony_ci (int)bcm_clk->type, init_data->name); 71362306a36Sopenharmony_ci return -EINVAL; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /* Make sure everything makes sense before we set it up */ 71762306a36Sopenharmony_ci if (!kona_clk_valid(bcm_clk)) { 71862306a36Sopenharmony_ci pr_err("%s: clock data invalid for %s\n", __func__, 71962306a36Sopenharmony_ci init_data->name); 72062306a36Sopenharmony_ci ret = -EINVAL; 72162306a36Sopenharmony_ci goto out_teardown; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci bcm_clk->hw.init = init_data; 72562306a36Sopenharmony_ci ret = clk_hw_register(NULL, &bcm_clk->hw); 72662306a36Sopenharmony_ci if (ret) { 72762306a36Sopenharmony_ci pr_err("%s: error registering clock %s (%d)\n", __func__, 72862306a36Sopenharmony_ci init_data->name, ret); 72962306a36Sopenharmony_ci goto out_teardown; 73062306a36Sopenharmony_ci } 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci return 0; 73362306a36Sopenharmony_ciout_teardown: 73462306a36Sopenharmony_ci bcm_clk_teardown(bcm_clk); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci return ret; 73762306a36Sopenharmony_ci} 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_cistatic void ccu_clks_teardown(struct ccu_data *ccu) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci u32 i; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci for (i = 0; i < ccu->clk_num; i++) 74462306a36Sopenharmony_ci kona_clk_teardown(&ccu->kona_clks[i].hw); 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_cistatic void kona_ccu_teardown(struct ccu_data *ccu) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci if (!ccu->base) 75062306a36Sopenharmony_ci return; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci of_clk_del_provider(ccu->node); /* safe if never added */ 75362306a36Sopenharmony_ci ccu_clks_teardown(ccu); 75462306a36Sopenharmony_ci of_node_put(ccu->node); 75562306a36Sopenharmony_ci ccu->node = NULL; 75662306a36Sopenharmony_ci iounmap(ccu->base); 75762306a36Sopenharmony_ci ccu->base = NULL; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic bool ccu_data_valid(struct ccu_data *ccu) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci struct ccu_policy *ccu_policy; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci if (!ccu_data_offsets_valid(ccu)) 76562306a36Sopenharmony_ci return false; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci ccu_policy = &ccu->policy; 76862306a36Sopenharmony_ci if (ccu_policy_exists(ccu_policy)) 76962306a36Sopenharmony_ci if (!ccu_policy_valid(ccu_policy, ccu->name)) 77062306a36Sopenharmony_ci return false; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci return true; 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_cistatic struct clk_hw * 77662306a36Sopenharmony_ciof_clk_kona_onecell_get(struct of_phandle_args *clkspec, void *data) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci struct ccu_data *ccu = data; 77962306a36Sopenharmony_ci unsigned int idx = clkspec->args[0]; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci if (idx >= ccu->clk_num) { 78262306a36Sopenharmony_ci pr_err("%s: invalid index %u\n", __func__, idx); 78362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return &ccu->kona_clks[idx].hw; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci/* 79062306a36Sopenharmony_ci * Set up a CCU. Call the provided ccu_clks_setup callback to 79162306a36Sopenharmony_ci * initialize the array of clocks provided by the CCU. 79262306a36Sopenharmony_ci */ 79362306a36Sopenharmony_civoid __init kona_dt_ccu_setup(struct ccu_data *ccu, 79462306a36Sopenharmony_ci struct device_node *node) 79562306a36Sopenharmony_ci{ 79662306a36Sopenharmony_ci struct resource res = { 0 }; 79762306a36Sopenharmony_ci resource_size_t range; 79862306a36Sopenharmony_ci unsigned int i; 79962306a36Sopenharmony_ci int ret; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci ret = of_address_to_resource(node, 0, &res); 80262306a36Sopenharmony_ci if (ret) { 80362306a36Sopenharmony_ci pr_err("%s: no valid CCU registers found for %pOFn\n", __func__, 80462306a36Sopenharmony_ci node); 80562306a36Sopenharmony_ci goto out_err; 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci range = resource_size(&res); 80962306a36Sopenharmony_ci if (range > (resource_size_t)U32_MAX) { 81062306a36Sopenharmony_ci pr_err("%s: address range too large for %pOFn\n", __func__, 81162306a36Sopenharmony_ci node); 81262306a36Sopenharmony_ci goto out_err; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci ccu->range = (u32)range; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci if (!ccu_data_valid(ccu)) { 81862306a36Sopenharmony_ci pr_err("%s: ccu data not valid for %pOFn\n", __func__, node); 81962306a36Sopenharmony_ci goto out_err; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci ccu->base = ioremap(res.start, ccu->range); 82362306a36Sopenharmony_ci if (!ccu->base) { 82462306a36Sopenharmony_ci pr_err("%s: unable to map CCU registers for %pOFn\n", __func__, 82562306a36Sopenharmony_ci node); 82662306a36Sopenharmony_ci goto out_err; 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci ccu->node = of_node_get(node); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /* 83162306a36Sopenharmony_ci * Set up each defined kona clock and save the result in 83262306a36Sopenharmony_ci * the clock framework clock array (in ccu->data). Then 83362306a36Sopenharmony_ci * register as a provider for these clocks. 83462306a36Sopenharmony_ci */ 83562306a36Sopenharmony_ci for (i = 0; i < ccu->clk_num; i++) { 83662306a36Sopenharmony_ci if (!ccu->kona_clks[i].ccu) 83762306a36Sopenharmony_ci continue; 83862306a36Sopenharmony_ci kona_clk_setup(&ccu->kona_clks[i]); 83962306a36Sopenharmony_ci } 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci ret = of_clk_add_hw_provider(node, of_clk_kona_onecell_get, ccu); 84262306a36Sopenharmony_ci if (ret) { 84362306a36Sopenharmony_ci pr_err("%s: error adding ccu %pOFn as provider (%d)\n", __func__, 84462306a36Sopenharmony_ci node, ret); 84562306a36Sopenharmony_ci goto out_err; 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci if (!kona_ccu_init(ccu)) 84962306a36Sopenharmony_ci pr_err("Broadcom %pOFn initialization had errors\n", node); 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci return; 85262306a36Sopenharmony_ciout_err: 85362306a36Sopenharmony_ci kona_ccu_teardown(ccu); 85462306a36Sopenharmony_ci pr_err("Broadcom %pOFn setup aborted\n", node); 85562306a36Sopenharmony_ci} 856