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 "clk-kona.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <linux/io.h>
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/clk-provider.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci * "Policies" affect the frequencies of bus clocks provided by a
1662306a36Sopenharmony_ci * CCU.  (I believe these polices are named "Deep Sleep", "Economy",
1762306a36Sopenharmony_ci * "Normal", and "Turbo".)  A lower policy number has lower power
1862306a36Sopenharmony_ci * consumption, and policy 2 is the default.
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_ci#define CCU_POLICY_COUNT	4
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define CCU_ACCESS_PASSWORD      0xA5A500
2362306a36Sopenharmony_ci#define CLK_GATE_DELAY_LOOP      2000
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/* Bitfield operations */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Produces a mask of set bits covering a range of a 32-bit value */
2862306a36Sopenharmony_cistatic inline u32 bitfield_mask(u32 shift, u32 width)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	return ((1 << width) - 1) << shift;
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* Extract the value of a bitfield found within a given register value */
3462306a36Sopenharmony_cistatic inline u32 bitfield_extract(u32 reg_val, u32 shift, u32 width)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	return (reg_val & bitfield_mask(shift, width)) >> shift;
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/* Replace the value of a bitfield found within a given register value */
4062306a36Sopenharmony_cistatic inline u32 bitfield_replace(u32 reg_val, u32 shift, u32 width, u32 val)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	u32 mask = bitfield_mask(shift, width);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	return (reg_val & ~mask) | (val << shift);
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* Divider and scaling helpers */
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* Convert a divider into the scaled divisor value it represents. */
5062306a36Sopenharmony_cistatic inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	return (u64)reg_div + ((u64)1 << div->u.s.frac_width);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/*
5662306a36Sopenharmony_ci * Build a scaled divider value as close as possible to the
5762306a36Sopenharmony_ci * given whole part (div_value) and fractional part (expressed
5862306a36Sopenharmony_ci * in billionths).
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_ciu64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	u64 combined;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	BUG_ON(!div_value);
6562306a36Sopenharmony_ci	BUG_ON(billionths >= BILLION);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	combined = (u64)div_value * BILLION + billionths;
6862306a36Sopenharmony_ci	combined <<= div->u.s.frac_width;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return DIV_ROUND_CLOSEST_ULL(combined, BILLION);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* The scaled minimum divisor representable by a divider */
7462306a36Sopenharmony_cistatic inline u64
7562306a36Sopenharmony_ciscaled_div_min(struct bcm_clk_div *div)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	if (divider_is_fixed(div))
7862306a36Sopenharmony_ci		return (u64)div->u.fixed;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	return scaled_div_value(div, 0);
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* The scaled maximum divisor representable by a divider */
8462306a36Sopenharmony_ciu64 scaled_div_max(struct bcm_clk_div *div)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	u32 reg_div;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	if (divider_is_fixed(div))
8962306a36Sopenharmony_ci		return (u64)div->u.fixed;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	reg_div = ((u32)1 << div->u.s.width) - 1;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	return scaled_div_value(div, reg_div);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/*
9762306a36Sopenharmony_ci * Convert a scaled divisor into its divider representation as
9862306a36Sopenharmony_ci * stored in a divider register field.
9962306a36Sopenharmony_ci */
10062306a36Sopenharmony_cistatic inline u32
10162306a36Sopenharmony_cidivider(struct bcm_clk_div *div, u64 scaled_div)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	BUG_ON(scaled_div < scaled_div_min(div));
10462306a36Sopenharmony_ci	BUG_ON(scaled_div > scaled_div_max(div));
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return (u32)(scaled_div - ((u64)1 << div->u.s.frac_width));
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/* Return a rate scaled for use when dividing by a scaled divisor. */
11062306a36Sopenharmony_cistatic inline u64
11162306a36Sopenharmony_ciscale_rate(struct bcm_clk_div *div, u32 rate)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	if (divider_is_fixed(div))
11462306a36Sopenharmony_ci		return (u64)rate;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	return (u64)rate << div->u.s.frac_width;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/* CCU access */
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/* Read a 32-bit register value from a CCU's address space. */
12262306a36Sopenharmony_cistatic inline u32 __ccu_read(struct ccu_data *ccu, u32 reg_offset)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	return readl(ccu->base + reg_offset);
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/* Write a 32-bit register value into a CCU's address space. */
12862306a36Sopenharmony_cistatic inline void
12962306a36Sopenharmony_ci__ccu_write(struct ccu_data *ccu, u32 reg_offset, u32 reg_val)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	writel(reg_val, ccu->base + reg_offset);
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic inline unsigned long ccu_lock(struct ccu_data *ccu)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	unsigned long flags;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	spin_lock_irqsave(&ccu->lock, flags);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	return flags;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_cistatic inline void ccu_unlock(struct ccu_data *ccu, unsigned long flags)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	spin_unlock_irqrestore(&ccu->lock, flags);
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci/*
14862306a36Sopenharmony_ci * Enable/disable write access to CCU protected registers.  The
14962306a36Sopenharmony_ci * WR_ACCESS register for all CCUs is at offset 0.
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic inline void __ccu_write_enable(struct ccu_data *ccu)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	if (ccu->write_enabled) {
15462306a36Sopenharmony_ci		pr_err("%s: access already enabled for %s\n", __func__,
15562306a36Sopenharmony_ci			ccu->name);
15662306a36Sopenharmony_ci		return;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci	ccu->write_enabled = true;
15962306a36Sopenharmony_ci	__ccu_write(ccu, 0, CCU_ACCESS_PASSWORD | 1);
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic inline void __ccu_write_disable(struct ccu_data *ccu)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	if (!ccu->write_enabled) {
16562306a36Sopenharmony_ci		pr_err("%s: access wasn't enabled for %s\n", __func__,
16662306a36Sopenharmony_ci			ccu->name);
16762306a36Sopenharmony_ci		return;
16862306a36Sopenharmony_ci	}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	__ccu_write(ccu, 0, CCU_ACCESS_PASSWORD);
17162306a36Sopenharmony_ci	ccu->write_enabled = false;
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/*
17562306a36Sopenharmony_ci * Poll a register in a CCU's address space, returning when the
17662306a36Sopenharmony_ci * specified bit in that register's value is set (or clear).  Delay
17762306a36Sopenharmony_ci * a microsecond after each read of the register.  Returns true if
17862306a36Sopenharmony_ci * successful, or false if we gave up trying.
17962306a36Sopenharmony_ci *
18062306a36Sopenharmony_ci * Caller must ensure the CCU lock is held.
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_cistatic inline bool
18362306a36Sopenharmony_ci__ccu_wait_bit(struct ccu_data *ccu, u32 reg_offset, u32 bit, bool want)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	unsigned int tries;
18662306a36Sopenharmony_ci	u32 bit_mask = 1 << bit;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	for (tries = 0; tries < CLK_GATE_DELAY_LOOP; tries++) {
18962306a36Sopenharmony_ci		u32 val;
19062306a36Sopenharmony_ci		bool bit_val;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci		val = __ccu_read(ccu, reg_offset);
19362306a36Sopenharmony_ci		bit_val = (val & bit_mask) != 0;
19462306a36Sopenharmony_ci		if (bit_val == want)
19562306a36Sopenharmony_ci			return true;
19662306a36Sopenharmony_ci		udelay(1);
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci	pr_warn("%s: %s/0x%04x bit %u was never %s\n", __func__,
19962306a36Sopenharmony_ci		ccu->name, reg_offset, bit, want ? "set" : "clear");
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return false;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci/* Policy operations */
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic bool __ccu_policy_engine_start(struct ccu_data *ccu, bool sync)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	struct bcm_policy_ctl *control = &ccu->policy.control;
20962306a36Sopenharmony_ci	u32 offset;
21062306a36Sopenharmony_ci	u32 go_bit;
21162306a36Sopenharmony_ci	u32 mask;
21262306a36Sopenharmony_ci	bool ret;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	/* If we don't need to control policy for this CCU, we're done. */
21562306a36Sopenharmony_ci	if (!policy_ctl_exists(control))
21662306a36Sopenharmony_ci		return true;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	offset = control->offset;
21962306a36Sopenharmony_ci	go_bit = control->go_bit;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	/* Ensure we're not busy before we start */
22262306a36Sopenharmony_ci	ret = __ccu_wait_bit(ccu, offset, go_bit, false);
22362306a36Sopenharmony_ci	if (!ret) {
22462306a36Sopenharmony_ci		pr_err("%s: ccu %s policy engine wouldn't go idle\n",
22562306a36Sopenharmony_ci			__func__, ccu->name);
22662306a36Sopenharmony_ci		return false;
22762306a36Sopenharmony_ci	}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	/*
23062306a36Sopenharmony_ci	 * If it's a synchronous request, we'll wait for the voltage
23162306a36Sopenharmony_ci	 * and frequency of the active load to stabilize before
23262306a36Sopenharmony_ci	 * returning.  To do this we select the active load by
23362306a36Sopenharmony_ci	 * setting the ATL bit.
23462306a36Sopenharmony_ci	 *
23562306a36Sopenharmony_ci	 * An asynchronous request instead ramps the voltage in the
23662306a36Sopenharmony_ci	 * background, and when that process stabilizes, the target
23762306a36Sopenharmony_ci	 * load is copied to the active load and the CCU frequency
23862306a36Sopenharmony_ci	 * is switched.  We do this by selecting the target load
23962306a36Sopenharmony_ci	 * (ATL bit clear) and setting the request auto-copy (AC bit
24062306a36Sopenharmony_ci	 * set).
24162306a36Sopenharmony_ci	 *
24262306a36Sopenharmony_ci	 * Note, we do NOT read-modify-write this register.
24362306a36Sopenharmony_ci	 */
24462306a36Sopenharmony_ci	mask = (u32)1 << go_bit;
24562306a36Sopenharmony_ci	if (sync)
24662306a36Sopenharmony_ci		mask |= 1 << control->atl_bit;
24762306a36Sopenharmony_ci	else
24862306a36Sopenharmony_ci		mask |= 1 << control->ac_bit;
24962306a36Sopenharmony_ci	__ccu_write(ccu, offset, mask);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	/* Wait for indication that operation is complete. */
25262306a36Sopenharmony_ci	ret = __ccu_wait_bit(ccu, offset, go_bit, false);
25362306a36Sopenharmony_ci	if (!ret)
25462306a36Sopenharmony_ci		pr_err("%s: ccu %s policy engine never started\n",
25562306a36Sopenharmony_ci			__func__, ccu->name);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return ret;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic bool __ccu_policy_engine_stop(struct ccu_data *ccu)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	struct bcm_lvm_en *enable = &ccu->policy.enable;
26362306a36Sopenharmony_ci	u32 offset;
26462306a36Sopenharmony_ci	u32 enable_bit;
26562306a36Sopenharmony_ci	bool ret;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/* If we don't need to control policy for this CCU, we're done. */
26862306a36Sopenharmony_ci	if (!policy_lvm_en_exists(enable))
26962306a36Sopenharmony_ci		return true;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	/* Ensure we're not busy before we start */
27262306a36Sopenharmony_ci	offset = enable->offset;
27362306a36Sopenharmony_ci	enable_bit = enable->bit;
27462306a36Sopenharmony_ci	ret = __ccu_wait_bit(ccu, offset, enable_bit, false);
27562306a36Sopenharmony_ci	if (!ret) {
27662306a36Sopenharmony_ci		pr_err("%s: ccu %s policy engine already stopped\n",
27762306a36Sopenharmony_ci			__func__, ccu->name);
27862306a36Sopenharmony_ci		return false;
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* Now set the bit to stop the engine (NO read-modify-write) */
28262306a36Sopenharmony_ci	__ccu_write(ccu, offset, (u32)1 << enable_bit);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Wait for indication that it has stopped. */
28562306a36Sopenharmony_ci	ret = __ccu_wait_bit(ccu, offset, enable_bit, false);
28662306a36Sopenharmony_ci	if (!ret)
28762306a36Sopenharmony_ci		pr_err("%s: ccu %s policy engine never stopped\n",
28862306a36Sopenharmony_ci			__func__, ccu->name);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return ret;
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci/*
29462306a36Sopenharmony_ci * A CCU has four operating conditions ("policies"), and some clocks
29562306a36Sopenharmony_ci * can be disabled or enabled based on which policy is currently in
29662306a36Sopenharmony_ci * effect.  Such clocks have a bit in a "policy mask" register for
29762306a36Sopenharmony_ci * each policy indicating whether the clock is enabled for that
29862306a36Sopenharmony_ci * policy or not.  The bit position for a clock is the same for all
29962306a36Sopenharmony_ci * four registers, and the 32-bit registers are at consecutive
30062306a36Sopenharmony_ci * addresses.
30162306a36Sopenharmony_ci */
30262306a36Sopenharmony_cistatic bool policy_init(struct ccu_data *ccu, struct bcm_clk_policy *policy)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	u32 offset;
30562306a36Sopenharmony_ci	u32 mask;
30662306a36Sopenharmony_ci	int i;
30762306a36Sopenharmony_ci	bool ret;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	if (!policy_exists(policy))
31062306a36Sopenharmony_ci		return true;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/*
31362306a36Sopenharmony_ci	 * We need to stop the CCU policy engine to allow update
31462306a36Sopenharmony_ci	 * of our policy bits.
31562306a36Sopenharmony_ci	 */
31662306a36Sopenharmony_ci	if (!__ccu_policy_engine_stop(ccu)) {
31762306a36Sopenharmony_ci		pr_err("%s: unable to stop CCU %s policy engine\n",
31862306a36Sopenharmony_ci			__func__, ccu->name);
31962306a36Sopenharmony_ci		return false;
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	/*
32362306a36Sopenharmony_ci	 * For now, if a clock defines its policy bit we just mark
32462306a36Sopenharmony_ci	 * it "enabled" for all four policies.
32562306a36Sopenharmony_ci	 */
32662306a36Sopenharmony_ci	offset = policy->offset;
32762306a36Sopenharmony_ci	mask = (u32)1 << policy->bit;
32862306a36Sopenharmony_ci	for (i = 0; i < CCU_POLICY_COUNT; i++) {
32962306a36Sopenharmony_ci		u32 reg_val;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci		reg_val = __ccu_read(ccu, offset);
33262306a36Sopenharmony_ci		reg_val |= mask;
33362306a36Sopenharmony_ci		__ccu_write(ccu, offset, reg_val);
33462306a36Sopenharmony_ci		offset += sizeof(u32);
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	/* We're done updating; fire up the policy engine again. */
33862306a36Sopenharmony_ci	ret = __ccu_policy_engine_start(ccu, true);
33962306a36Sopenharmony_ci	if (!ret)
34062306a36Sopenharmony_ci		pr_err("%s: unable to restart CCU %s policy engine\n",
34162306a36Sopenharmony_ci			__func__, ccu->name);
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	return ret;
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci/* Gate operations */
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci/* Determine whether a clock is gated.  CCU lock must be held.  */
34962306a36Sopenharmony_cistatic bool
35062306a36Sopenharmony_ci__is_clk_gate_enabled(struct ccu_data *ccu, struct bcm_clk_gate *gate)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	u32 bit_mask;
35362306a36Sopenharmony_ci	u32 reg_val;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/* If there is no gate we can assume it's enabled. */
35662306a36Sopenharmony_ci	if (!gate_exists(gate))
35762306a36Sopenharmony_ci		return true;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	bit_mask = 1 << gate->status_bit;
36062306a36Sopenharmony_ci	reg_val = __ccu_read(ccu, gate->offset);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	return (reg_val & bit_mask) != 0;
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci/* Determine whether a clock is gated. */
36662306a36Sopenharmony_cistatic bool
36762306a36Sopenharmony_ciis_clk_gate_enabled(struct ccu_data *ccu, struct bcm_clk_gate *gate)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	long flags;
37062306a36Sopenharmony_ci	bool ret;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	/* Avoid taking the lock if we can */
37362306a36Sopenharmony_ci	if (!gate_exists(gate))
37462306a36Sopenharmony_ci		return true;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	flags = ccu_lock(ccu);
37762306a36Sopenharmony_ci	ret = __is_clk_gate_enabled(ccu, gate);
37862306a36Sopenharmony_ci	ccu_unlock(ccu, flags);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	return ret;
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/*
38462306a36Sopenharmony_ci * Commit our desired gate state to the hardware.
38562306a36Sopenharmony_ci * Returns true if successful, false otherwise.
38662306a36Sopenharmony_ci */
38762306a36Sopenharmony_cistatic bool
38862306a36Sopenharmony_ci__gate_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	u32 reg_val;
39162306a36Sopenharmony_ci	u32 mask;
39262306a36Sopenharmony_ci	bool enabled = false;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	BUG_ON(!gate_exists(gate));
39562306a36Sopenharmony_ci	if (!gate_is_sw_controllable(gate))
39662306a36Sopenharmony_ci		return true;		/* Nothing we can change */
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	reg_val = __ccu_read(ccu, gate->offset);
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	/* For a hardware/software gate, set which is in control */
40162306a36Sopenharmony_ci	if (gate_is_hw_controllable(gate)) {
40262306a36Sopenharmony_ci		mask = (u32)1 << gate->hw_sw_sel_bit;
40362306a36Sopenharmony_ci		if (gate_is_sw_managed(gate))
40462306a36Sopenharmony_ci			reg_val |= mask;
40562306a36Sopenharmony_ci		else
40662306a36Sopenharmony_ci			reg_val &= ~mask;
40762306a36Sopenharmony_ci	}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	/*
41062306a36Sopenharmony_ci	 * If software is in control, enable or disable the gate.
41162306a36Sopenharmony_ci	 * If hardware is, clear the enabled bit for good measure.
41262306a36Sopenharmony_ci	 * If a software controlled gate can't be disabled, we're
41362306a36Sopenharmony_ci	 * required to write a 0 into the enable bit (but the gate
41462306a36Sopenharmony_ci	 * will be enabled).
41562306a36Sopenharmony_ci	 */
41662306a36Sopenharmony_ci	mask = (u32)1 << gate->en_bit;
41762306a36Sopenharmony_ci	if (gate_is_sw_managed(gate) && (enabled = gate_is_enabled(gate)) &&
41862306a36Sopenharmony_ci			!gate_is_no_disable(gate))
41962306a36Sopenharmony_ci		reg_val |= mask;
42062306a36Sopenharmony_ci	else
42162306a36Sopenharmony_ci		reg_val &= ~mask;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	__ccu_write(ccu, gate->offset, reg_val);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	/* For a hardware controlled gate, we're done */
42662306a36Sopenharmony_ci	if (!gate_is_sw_managed(gate))
42762306a36Sopenharmony_ci		return true;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/* Otherwise wait for the gate to be in desired state */
43062306a36Sopenharmony_ci	return __ccu_wait_bit(ccu, gate->offset, gate->status_bit, enabled);
43162306a36Sopenharmony_ci}
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci/*
43462306a36Sopenharmony_ci * Initialize a gate.  Our desired state (hardware/software select,
43562306a36Sopenharmony_ci * and if software, its enable state) is committed to hardware
43662306a36Sopenharmony_ci * without the usual checks to see if it's already set up that way.
43762306a36Sopenharmony_ci * Returns true if successful, false otherwise.
43862306a36Sopenharmony_ci */
43962306a36Sopenharmony_cistatic bool gate_init(struct ccu_data *ccu, struct bcm_clk_gate *gate)
44062306a36Sopenharmony_ci{
44162306a36Sopenharmony_ci	if (!gate_exists(gate))
44262306a36Sopenharmony_ci		return true;
44362306a36Sopenharmony_ci	return __gate_commit(ccu, gate);
44462306a36Sopenharmony_ci}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci/*
44762306a36Sopenharmony_ci * Set a gate to enabled or disabled state.  Does nothing if the
44862306a36Sopenharmony_ci * gate is not currently under software control, or if it is already
44962306a36Sopenharmony_ci * in the requested state.  Returns true if successful, false
45062306a36Sopenharmony_ci * otherwise.  CCU lock must be held.
45162306a36Sopenharmony_ci */
45262306a36Sopenharmony_cistatic bool
45362306a36Sopenharmony_ci__clk_gate(struct ccu_data *ccu, struct bcm_clk_gate *gate, bool enable)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	bool ret;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	if (!gate_exists(gate) || !gate_is_sw_managed(gate))
45862306a36Sopenharmony_ci		return true;	/* Nothing to do */
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (!enable && gate_is_no_disable(gate)) {
46162306a36Sopenharmony_ci		pr_warn("%s: invalid gate disable request (ignoring)\n",
46262306a36Sopenharmony_ci			__func__);
46362306a36Sopenharmony_ci		return true;
46462306a36Sopenharmony_ci	}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	if (enable == gate_is_enabled(gate))
46762306a36Sopenharmony_ci		return true;	/* No change */
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	gate_flip_enabled(gate);
47062306a36Sopenharmony_ci	ret = __gate_commit(ccu, gate);
47162306a36Sopenharmony_ci	if (!ret)
47262306a36Sopenharmony_ci		gate_flip_enabled(gate);	/* Revert the change */
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	return ret;
47562306a36Sopenharmony_ci}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci/* Enable or disable a gate.  Returns 0 if successful, -EIO otherwise */
47862306a36Sopenharmony_cistatic int clk_gate(struct ccu_data *ccu, const char *name,
47962306a36Sopenharmony_ci			struct bcm_clk_gate *gate, bool enable)
48062306a36Sopenharmony_ci{
48162306a36Sopenharmony_ci	unsigned long flags;
48262306a36Sopenharmony_ci	bool success;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	/*
48562306a36Sopenharmony_ci	 * Avoid taking the lock if we can.  We quietly ignore
48662306a36Sopenharmony_ci	 * requests to change state that don't make sense.
48762306a36Sopenharmony_ci	 */
48862306a36Sopenharmony_ci	if (!gate_exists(gate) || !gate_is_sw_managed(gate))
48962306a36Sopenharmony_ci		return 0;
49062306a36Sopenharmony_ci	if (!enable && gate_is_no_disable(gate))
49162306a36Sopenharmony_ci		return 0;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	flags = ccu_lock(ccu);
49462306a36Sopenharmony_ci	__ccu_write_enable(ccu);
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	success = __clk_gate(ccu, gate, enable);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	__ccu_write_disable(ccu);
49962306a36Sopenharmony_ci	ccu_unlock(ccu, flags);
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	if (success)
50262306a36Sopenharmony_ci		return 0;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	pr_err("%s: failed to %s gate for %s\n", __func__,
50562306a36Sopenharmony_ci		enable ? "enable" : "disable", name);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	return -EIO;
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci/* Hysteresis operations */
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci/*
51362306a36Sopenharmony_ci * If a clock gate requires a turn-off delay it will have
51462306a36Sopenharmony_ci * "hysteresis" register bits defined.  The first, if set, enables
51562306a36Sopenharmony_ci * the delay; and if enabled, the second bit determines whether the
51662306a36Sopenharmony_ci * delay is "low" or "high" (1 means high).  For now, if it's
51762306a36Sopenharmony_ci * defined for a clock, we set it.
51862306a36Sopenharmony_ci */
51962306a36Sopenharmony_cistatic bool hyst_init(struct ccu_data *ccu, struct bcm_clk_hyst *hyst)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	u32 offset;
52262306a36Sopenharmony_ci	u32 reg_val;
52362306a36Sopenharmony_ci	u32 mask;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	if (!hyst_exists(hyst))
52662306a36Sopenharmony_ci		return true;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	offset = hyst->offset;
52962306a36Sopenharmony_ci	mask = (u32)1 << hyst->en_bit;
53062306a36Sopenharmony_ci	mask |= (u32)1 << hyst->val_bit;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	reg_val = __ccu_read(ccu, offset);
53362306a36Sopenharmony_ci	reg_val |= mask;
53462306a36Sopenharmony_ci	__ccu_write(ccu, offset, reg_val);
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	return true;
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci/* Trigger operations */
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci/*
54262306a36Sopenharmony_ci * Caller must ensure CCU lock is held and access is enabled.
54362306a36Sopenharmony_ci * Returns true if successful, false otherwise.
54462306a36Sopenharmony_ci */
54562306a36Sopenharmony_cistatic bool __clk_trigger(struct ccu_data *ccu, struct bcm_clk_trig *trig)
54662306a36Sopenharmony_ci{
54762306a36Sopenharmony_ci	/* Trigger the clock and wait for it to finish */
54862306a36Sopenharmony_ci	__ccu_write(ccu, trig->offset, 1 << trig->bit);
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	return __ccu_wait_bit(ccu, trig->offset, trig->bit, false);
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci/* Divider operations */
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci/* Read a divider value and return the scaled divisor it represents. */
55662306a36Sopenharmony_cistatic u64 divider_read_scaled(struct ccu_data *ccu, struct bcm_clk_div *div)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	unsigned long flags;
55962306a36Sopenharmony_ci	u32 reg_val;
56062306a36Sopenharmony_ci	u32 reg_div;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	if (divider_is_fixed(div))
56362306a36Sopenharmony_ci		return (u64)div->u.fixed;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	flags = ccu_lock(ccu);
56662306a36Sopenharmony_ci	reg_val = __ccu_read(ccu, div->u.s.offset);
56762306a36Sopenharmony_ci	ccu_unlock(ccu, flags);
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	/* Extract the full divider field from the register value */
57062306a36Sopenharmony_ci	reg_div = bitfield_extract(reg_val, div->u.s.shift, div->u.s.width);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	/* Return the scaled divisor value it represents */
57362306a36Sopenharmony_ci	return scaled_div_value(div, reg_div);
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci/*
57762306a36Sopenharmony_ci * Convert a divider's scaled divisor value into its recorded form
57862306a36Sopenharmony_ci * and commit it into the hardware divider register.
57962306a36Sopenharmony_ci *
58062306a36Sopenharmony_ci * Returns 0 on success.  Returns -EINVAL for invalid arguments.
58162306a36Sopenharmony_ci * Returns -ENXIO if gating failed, and -EIO if a trigger failed.
58262306a36Sopenharmony_ci */
58362306a36Sopenharmony_cistatic int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
58462306a36Sopenharmony_ci			struct bcm_clk_div *div, struct bcm_clk_trig *trig)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	bool enabled;
58762306a36Sopenharmony_ci	u32 reg_div;
58862306a36Sopenharmony_ci	u32 reg_val;
58962306a36Sopenharmony_ci	int ret = 0;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	BUG_ON(divider_is_fixed(div));
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	/*
59462306a36Sopenharmony_ci	 * If we're just initializing the divider, and no initial
59562306a36Sopenharmony_ci	 * state was defined in the device tree, we just find out
59662306a36Sopenharmony_ci	 * what its current value is rather than updating it.
59762306a36Sopenharmony_ci	 */
59862306a36Sopenharmony_ci	if (div->u.s.scaled_div == BAD_SCALED_DIV_VALUE) {
59962306a36Sopenharmony_ci		reg_val = __ccu_read(ccu, div->u.s.offset);
60062306a36Sopenharmony_ci		reg_div = bitfield_extract(reg_val, div->u.s.shift,
60162306a36Sopenharmony_ci						div->u.s.width);
60262306a36Sopenharmony_ci		div->u.s.scaled_div = scaled_div_value(div, reg_div);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci		return 0;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	/* Convert the scaled divisor to the value we need to record */
60862306a36Sopenharmony_ci	reg_div = divider(div, div->u.s.scaled_div);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	/* Clock needs to be enabled before changing the rate */
61162306a36Sopenharmony_ci	enabled = __is_clk_gate_enabled(ccu, gate);
61262306a36Sopenharmony_ci	if (!enabled && !__clk_gate(ccu, gate, true)) {
61362306a36Sopenharmony_ci		ret = -ENXIO;
61462306a36Sopenharmony_ci		goto out;
61562306a36Sopenharmony_ci	}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	/* Replace the divider value and record the result */
61862306a36Sopenharmony_ci	reg_val = __ccu_read(ccu, div->u.s.offset);
61962306a36Sopenharmony_ci	reg_val = bitfield_replace(reg_val, div->u.s.shift, div->u.s.width,
62062306a36Sopenharmony_ci					reg_div);
62162306a36Sopenharmony_ci	__ccu_write(ccu, div->u.s.offset, reg_val);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	/* If the trigger fails we still want to disable the gate */
62462306a36Sopenharmony_ci	if (!__clk_trigger(ccu, trig))
62562306a36Sopenharmony_ci		ret = -EIO;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	/* Disable the clock again if it was disabled to begin with */
62862306a36Sopenharmony_ci	if (!enabled && !__clk_gate(ccu, gate, false))
62962306a36Sopenharmony_ci		ret = ret ? ret : -ENXIO;	/* return first error */
63062306a36Sopenharmony_ciout:
63162306a36Sopenharmony_ci	return ret;
63262306a36Sopenharmony_ci}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci/*
63562306a36Sopenharmony_ci * Initialize a divider by committing our desired state to hardware
63662306a36Sopenharmony_ci * without the usual checks to see if it's already set up that way.
63762306a36Sopenharmony_ci * Returns true if successful, false otherwise.
63862306a36Sopenharmony_ci */
63962306a36Sopenharmony_cistatic bool div_init(struct ccu_data *ccu, struct bcm_clk_gate *gate,
64062306a36Sopenharmony_ci			struct bcm_clk_div *div, struct bcm_clk_trig *trig)
64162306a36Sopenharmony_ci{
64262306a36Sopenharmony_ci	if (!divider_exists(div) || divider_is_fixed(div))
64362306a36Sopenharmony_ci		return true;
64462306a36Sopenharmony_ci	return !__div_commit(ccu, gate, div, trig);
64562306a36Sopenharmony_ci}
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_cistatic int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
64862306a36Sopenharmony_ci			struct bcm_clk_div *div, struct bcm_clk_trig *trig,
64962306a36Sopenharmony_ci			u64 scaled_div)
65062306a36Sopenharmony_ci{
65162306a36Sopenharmony_ci	unsigned long flags;
65262306a36Sopenharmony_ci	u64 previous;
65362306a36Sopenharmony_ci	int ret;
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	BUG_ON(divider_is_fixed(div));
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	previous = div->u.s.scaled_div;
65862306a36Sopenharmony_ci	if (previous == scaled_div)
65962306a36Sopenharmony_ci		return 0;	/* No change */
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	div->u.s.scaled_div = scaled_div;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	flags = ccu_lock(ccu);
66462306a36Sopenharmony_ci	__ccu_write_enable(ccu);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	ret = __div_commit(ccu, gate, div, trig);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	__ccu_write_disable(ccu);
66962306a36Sopenharmony_ci	ccu_unlock(ccu, flags);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	if (ret)
67262306a36Sopenharmony_ci		div->u.s.scaled_div = previous;		/* Revert the change */
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	return ret;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci/* Common clock rate helpers */
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci/*
68162306a36Sopenharmony_ci * Implement the common clock framework recalc_rate method, taking
68262306a36Sopenharmony_ci * into account a divider and an optional pre-divider.  The
68362306a36Sopenharmony_ci * pre-divider register pointer may be NULL.
68462306a36Sopenharmony_ci */
68562306a36Sopenharmony_cistatic unsigned long clk_recalc_rate(struct ccu_data *ccu,
68662306a36Sopenharmony_ci			struct bcm_clk_div *div, struct bcm_clk_div *pre_div,
68762306a36Sopenharmony_ci			unsigned long parent_rate)
68862306a36Sopenharmony_ci{
68962306a36Sopenharmony_ci	u64 scaled_parent_rate;
69062306a36Sopenharmony_ci	u64 scaled_div;
69162306a36Sopenharmony_ci	u64 result;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (!divider_exists(div))
69462306a36Sopenharmony_ci		return parent_rate;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	if (parent_rate > (unsigned long)LONG_MAX)
69762306a36Sopenharmony_ci		return 0;	/* actually this would be a caller bug */
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	/*
70062306a36Sopenharmony_ci	 * If there is a pre-divider, divide the scaled parent rate
70162306a36Sopenharmony_ci	 * by the pre-divider value first.  In this case--to improve
70262306a36Sopenharmony_ci	 * accuracy--scale the parent rate by *both* the pre-divider
70362306a36Sopenharmony_ci	 * value and the divider before actually computing the
70462306a36Sopenharmony_ci	 * result of the pre-divider.
70562306a36Sopenharmony_ci	 *
70662306a36Sopenharmony_ci	 * If there's only one divider, just scale the parent rate.
70762306a36Sopenharmony_ci	 */
70862306a36Sopenharmony_ci	if (pre_div && divider_exists(pre_div)) {
70962306a36Sopenharmony_ci		u64 scaled_rate;
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci		scaled_rate = scale_rate(pre_div, parent_rate);
71262306a36Sopenharmony_ci		scaled_rate = scale_rate(div, scaled_rate);
71362306a36Sopenharmony_ci		scaled_div = divider_read_scaled(ccu, pre_div);
71462306a36Sopenharmony_ci		scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate,
71562306a36Sopenharmony_ci							scaled_div);
71662306a36Sopenharmony_ci	} else  {
71762306a36Sopenharmony_ci		scaled_parent_rate = scale_rate(div, parent_rate);
71862306a36Sopenharmony_ci	}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	/*
72162306a36Sopenharmony_ci	 * Get the scaled divisor value, and divide the scaled
72262306a36Sopenharmony_ci	 * parent rate by that to determine this clock's resulting
72362306a36Sopenharmony_ci	 * rate.
72462306a36Sopenharmony_ci	 */
72562306a36Sopenharmony_ci	scaled_div = divider_read_scaled(ccu, div);
72662306a36Sopenharmony_ci	result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, scaled_div);
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	return (unsigned long)result;
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci/*
73262306a36Sopenharmony_ci * Compute the output rate produced when a given parent rate is fed
73362306a36Sopenharmony_ci * into two dividers.  The pre-divider can be NULL, and even if it's
73462306a36Sopenharmony_ci * non-null it may be nonexistent.  It's also OK for the divider to
73562306a36Sopenharmony_ci * be nonexistent, and in that case the pre-divider is also ignored.
73662306a36Sopenharmony_ci *
73762306a36Sopenharmony_ci * If scaled_div is non-null, it is used to return the scaled divisor
73862306a36Sopenharmony_ci * value used by the (downstream) divider to produce that rate.
73962306a36Sopenharmony_ci */
74062306a36Sopenharmony_cistatic long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div,
74162306a36Sopenharmony_ci				struct bcm_clk_div *pre_div,
74262306a36Sopenharmony_ci				unsigned long rate, unsigned long parent_rate,
74362306a36Sopenharmony_ci				u64 *scaled_div)
74462306a36Sopenharmony_ci{
74562306a36Sopenharmony_ci	u64 scaled_parent_rate;
74662306a36Sopenharmony_ci	u64 min_scaled_div;
74762306a36Sopenharmony_ci	u64 max_scaled_div;
74862306a36Sopenharmony_ci	u64 best_scaled_div;
74962306a36Sopenharmony_ci	u64 result;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	BUG_ON(!divider_exists(div));
75262306a36Sopenharmony_ci	BUG_ON(!rate);
75362306a36Sopenharmony_ci	BUG_ON(parent_rate > (u64)LONG_MAX);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	/*
75662306a36Sopenharmony_ci	 * If there is a pre-divider, divide the scaled parent rate
75762306a36Sopenharmony_ci	 * by the pre-divider value first.  In this case--to improve
75862306a36Sopenharmony_ci	 * accuracy--scale the parent rate by *both* the pre-divider
75962306a36Sopenharmony_ci	 * value and the divider before actually computing the
76062306a36Sopenharmony_ci	 * result of the pre-divider.
76162306a36Sopenharmony_ci	 *
76262306a36Sopenharmony_ci	 * If there's only one divider, just scale the parent rate.
76362306a36Sopenharmony_ci	 *
76462306a36Sopenharmony_ci	 * For simplicity we treat the pre-divider as fixed (for now).
76562306a36Sopenharmony_ci	 */
76662306a36Sopenharmony_ci	if (divider_exists(pre_div)) {
76762306a36Sopenharmony_ci		u64 scaled_rate;
76862306a36Sopenharmony_ci		u64 scaled_pre_div;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci		scaled_rate = scale_rate(pre_div, parent_rate);
77162306a36Sopenharmony_ci		scaled_rate = scale_rate(div, scaled_rate);
77262306a36Sopenharmony_ci		scaled_pre_div = divider_read_scaled(ccu, pre_div);
77362306a36Sopenharmony_ci		scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate,
77462306a36Sopenharmony_ci							scaled_pre_div);
77562306a36Sopenharmony_ci	} else {
77662306a36Sopenharmony_ci		scaled_parent_rate = scale_rate(div, parent_rate);
77762306a36Sopenharmony_ci	}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	/*
78062306a36Sopenharmony_ci	 * Compute the best possible divider and ensure it is in
78162306a36Sopenharmony_ci	 * range.  A fixed divider can't be changed, so just report
78262306a36Sopenharmony_ci	 * the best we can do.
78362306a36Sopenharmony_ci	 */
78462306a36Sopenharmony_ci	if (!divider_is_fixed(div)) {
78562306a36Sopenharmony_ci		best_scaled_div = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate,
78662306a36Sopenharmony_ci							rate);
78762306a36Sopenharmony_ci		min_scaled_div = scaled_div_min(div);
78862306a36Sopenharmony_ci		max_scaled_div = scaled_div_max(div);
78962306a36Sopenharmony_ci		if (best_scaled_div > max_scaled_div)
79062306a36Sopenharmony_ci			best_scaled_div = max_scaled_div;
79162306a36Sopenharmony_ci		else if (best_scaled_div < min_scaled_div)
79262306a36Sopenharmony_ci			best_scaled_div = min_scaled_div;
79362306a36Sopenharmony_ci	} else {
79462306a36Sopenharmony_ci		best_scaled_div = divider_read_scaled(ccu, div);
79562306a36Sopenharmony_ci	}
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	/* OK, figure out the resulting rate */
79862306a36Sopenharmony_ci	result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, best_scaled_div);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	if (scaled_div)
80162306a36Sopenharmony_ci		*scaled_div = best_scaled_div;
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	return (long)result;
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci/* Common clock parent helpers */
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci/*
80962306a36Sopenharmony_ci * For a given parent selector (register field) value, find the
81062306a36Sopenharmony_ci * index into a selector's parent_sel array that contains it.
81162306a36Sopenharmony_ci * Returns the index, or BAD_CLK_INDEX if it's not found.
81262306a36Sopenharmony_ci */
81362306a36Sopenharmony_cistatic u8 parent_index(struct bcm_clk_sel *sel, u8 parent_sel)
81462306a36Sopenharmony_ci{
81562306a36Sopenharmony_ci	u8 i;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	BUG_ON(sel->parent_count > (u32)U8_MAX);
81862306a36Sopenharmony_ci	for (i = 0; i < sel->parent_count; i++)
81962306a36Sopenharmony_ci		if (sel->parent_sel[i] == parent_sel)
82062306a36Sopenharmony_ci			return i;
82162306a36Sopenharmony_ci	return BAD_CLK_INDEX;
82262306a36Sopenharmony_ci}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci/*
82562306a36Sopenharmony_ci * Fetch the current value of the selector, and translate that into
82662306a36Sopenharmony_ci * its corresponding index in the parent array we registered with
82762306a36Sopenharmony_ci * the clock framework.
82862306a36Sopenharmony_ci *
82962306a36Sopenharmony_ci * Returns parent array index that corresponds with the value found,
83062306a36Sopenharmony_ci * or BAD_CLK_INDEX if the found value is out of range.
83162306a36Sopenharmony_ci */
83262306a36Sopenharmony_cistatic u8 selector_read_index(struct ccu_data *ccu, struct bcm_clk_sel *sel)
83362306a36Sopenharmony_ci{
83462306a36Sopenharmony_ci	unsigned long flags;
83562306a36Sopenharmony_ci	u32 reg_val;
83662306a36Sopenharmony_ci	u32 parent_sel;
83762306a36Sopenharmony_ci	u8 index;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	/* If there's no selector, there's only one parent */
84062306a36Sopenharmony_ci	if (!selector_exists(sel))
84162306a36Sopenharmony_ci		return 0;
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	/* Get the value in the selector register */
84462306a36Sopenharmony_ci	flags = ccu_lock(ccu);
84562306a36Sopenharmony_ci	reg_val = __ccu_read(ccu, sel->offset);
84662306a36Sopenharmony_ci	ccu_unlock(ccu, flags);
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	parent_sel = bitfield_extract(reg_val, sel->shift, sel->width);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	/* Look up that selector's parent array index and return it */
85162306a36Sopenharmony_ci	index = parent_index(sel, parent_sel);
85262306a36Sopenharmony_ci	if (index == BAD_CLK_INDEX)
85362306a36Sopenharmony_ci		pr_err("%s: out-of-range parent selector %u (%s 0x%04x)\n",
85462306a36Sopenharmony_ci			__func__, parent_sel, ccu->name, sel->offset);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	return index;
85762306a36Sopenharmony_ci}
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci/*
86062306a36Sopenharmony_ci * Commit our desired selector value to the hardware.
86162306a36Sopenharmony_ci *
86262306a36Sopenharmony_ci * Returns 0 on success.  Returns -EINVAL for invalid arguments.
86362306a36Sopenharmony_ci * Returns -ENXIO if gating failed, and -EIO if a trigger failed.
86462306a36Sopenharmony_ci */
86562306a36Sopenharmony_cistatic int
86662306a36Sopenharmony_ci__sel_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
86762306a36Sopenharmony_ci			struct bcm_clk_sel *sel, struct bcm_clk_trig *trig)
86862306a36Sopenharmony_ci{
86962306a36Sopenharmony_ci	u32 parent_sel;
87062306a36Sopenharmony_ci	u32 reg_val;
87162306a36Sopenharmony_ci	bool enabled;
87262306a36Sopenharmony_ci	int ret = 0;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	BUG_ON(!selector_exists(sel));
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	/*
87762306a36Sopenharmony_ci	 * If we're just initializing the selector, and no initial
87862306a36Sopenharmony_ci	 * state was defined in the device tree, we just find out
87962306a36Sopenharmony_ci	 * what its current value is rather than updating it.
88062306a36Sopenharmony_ci	 */
88162306a36Sopenharmony_ci	if (sel->clk_index == BAD_CLK_INDEX) {
88262306a36Sopenharmony_ci		u8 index;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci		reg_val = __ccu_read(ccu, sel->offset);
88562306a36Sopenharmony_ci		parent_sel = bitfield_extract(reg_val, sel->shift, sel->width);
88662306a36Sopenharmony_ci		index = parent_index(sel, parent_sel);
88762306a36Sopenharmony_ci		if (index == BAD_CLK_INDEX)
88862306a36Sopenharmony_ci			return -EINVAL;
88962306a36Sopenharmony_ci		sel->clk_index = index;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci		return 0;
89262306a36Sopenharmony_ci	}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	BUG_ON((u32)sel->clk_index >= sel->parent_count);
89562306a36Sopenharmony_ci	parent_sel = sel->parent_sel[sel->clk_index];
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	/* Clock needs to be enabled before changing the parent */
89862306a36Sopenharmony_ci	enabled = __is_clk_gate_enabled(ccu, gate);
89962306a36Sopenharmony_ci	if (!enabled && !__clk_gate(ccu, gate, true))
90062306a36Sopenharmony_ci		return -ENXIO;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	/* Replace the selector value and record the result */
90362306a36Sopenharmony_ci	reg_val = __ccu_read(ccu, sel->offset);
90462306a36Sopenharmony_ci	reg_val = bitfield_replace(reg_val, sel->shift, sel->width, parent_sel);
90562306a36Sopenharmony_ci	__ccu_write(ccu, sel->offset, reg_val);
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	/* If the trigger fails we still want to disable the gate */
90862306a36Sopenharmony_ci	if (!__clk_trigger(ccu, trig))
90962306a36Sopenharmony_ci		ret = -EIO;
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	/* Disable the clock again if it was disabled to begin with */
91262306a36Sopenharmony_ci	if (!enabled && !__clk_gate(ccu, gate, false))
91362306a36Sopenharmony_ci		ret = ret ? ret : -ENXIO;	/* return first error */
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	return ret;
91662306a36Sopenharmony_ci}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci/*
91962306a36Sopenharmony_ci * Initialize a selector by committing our desired state to hardware
92062306a36Sopenharmony_ci * without the usual checks to see if it's already set up that way.
92162306a36Sopenharmony_ci * Returns true if successful, false otherwise.
92262306a36Sopenharmony_ci */
92362306a36Sopenharmony_cistatic bool sel_init(struct ccu_data *ccu, struct bcm_clk_gate *gate,
92462306a36Sopenharmony_ci			struct bcm_clk_sel *sel, struct bcm_clk_trig *trig)
92562306a36Sopenharmony_ci{
92662306a36Sopenharmony_ci	if (!selector_exists(sel))
92762306a36Sopenharmony_ci		return true;
92862306a36Sopenharmony_ci	return !__sel_commit(ccu, gate, sel, trig);
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci/*
93262306a36Sopenharmony_ci * Write a new value into a selector register to switch to a
93362306a36Sopenharmony_ci * different parent clock.  Returns 0 on success, or an error code
93462306a36Sopenharmony_ci * (from __sel_commit()) otherwise.
93562306a36Sopenharmony_ci */
93662306a36Sopenharmony_cistatic int selector_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
93762306a36Sopenharmony_ci			struct bcm_clk_sel *sel, struct bcm_clk_trig *trig,
93862306a36Sopenharmony_ci			u8 index)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	unsigned long flags;
94162306a36Sopenharmony_ci	u8 previous;
94262306a36Sopenharmony_ci	int ret;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	previous = sel->clk_index;
94562306a36Sopenharmony_ci	if (previous == index)
94662306a36Sopenharmony_ci		return 0;	/* No change */
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	sel->clk_index = index;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	flags = ccu_lock(ccu);
95162306a36Sopenharmony_ci	__ccu_write_enable(ccu);
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	ret = __sel_commit(ccu, gate, sel, trig);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	__ccu_write_disable(ccu);
95662306a36Sopenharmony_ci	ccu_unlock(ccu, flags);
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	if (ret)
95962306a36Sopenharmony_ci		sel->clk_index = previous;	/* Revert the change */
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	return ret;
96262306a36Sopenharmony_ci}
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci/* Clock operations */
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_cistatic int kona_peri_clk_enable(struct clk_hw *hw)
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
96962306a36Sopenharmony_ci	struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	return clk_gate(bcm_clk->ccu, bcm_clk->init_data.name, gate, true);
97262306a36Sopenharmony_ci}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_cistatic void kona_peri_clk_disable(struct clk_hw *hw)
97562306a36Sopenharmony_ci{
97662306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
97762306a36Sopenharmony_ci	struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	(void)clk_gate(bcm_clk->ccu, bcm_clk->init_data.name, gate, false);
98062306a36Sopenharmony_ci}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_cistatic int kona_peri_clk_is_enabled(struct clk_hw *hw)
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
98562306a36Sopenharmony_ci	struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0;
98862306a36Sopenharmony_ci}
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_cistatic unsigned long kona_peri_clk_recalc_rate(struct clk_hw *hw,
99162306a36Sopenharmony_ci			unsigned long parent_rate)
99262306a36Sopenharmony_ci{
99362306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
99462306a36Sopenharmony_ci	struct peri_clk_data *data = bcm_clk->u.peri;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div,
99762306a36Sopenharmony_ci				parent_rate);
99862306a36Sopenharmony_ci}
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_cistatic long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
100162306a36Sopenharmony_ci			unsigned long *parent_rate)
100262306a36Sopenharmony_ci{
100362306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
100462306a36Sopenharmony_ci	struct bcm_clk_div *div = &bcm_clk->u.peri->div;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	if (!divider_exists(div))
100762306a36Sopenharmony_ci		return clk_hw_get_rate(hw);
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	/* Quietly avoid a zero rate */
101062306a36Sopenharmony_ci	return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div,
101162306a36Sopenharmony_ci				rate ? rate : 1, *parent_rate, NULL);
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_cistatic int kona_peri_clk_determine_rate(struct clk_hw *hw,
101562306a36Sopenharmony_ci					struct clk_rate_request *req)
101662306a36Sopenharmony_ci{
101762306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
101862306a36Sopenharmony_ci	struct clk_hw *current_parent;
101962306a36Sopenharmony_ci	unsigned long parent_rate;
102062306a36Sopenharmony_ci	unsigned long best_delta;
102162306a36Sopenharmony_ci	unsigned long best_rate;
102262306a36Sopenharmony_ci	u32 parent_count;
102362306a36Sopenharmony_ci	long rate;
102462306a36Sopenharmony_ci	u32 which;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	/*
102762306a36Sopenharmony_ci	 * If there is no other parent to choose, use the current one.
102862306a36Sopenharmony_ci	 * Note:  We don't honor (or use) CLK_SET_RATE_NO_REPARENT.
102962306a36Sopenharmony_ci	 */
103062306a36Sopenharmony_ci	WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
103162306a36Sopenharmony_ci	parent_count = (u32)bcm_clk->init_data.num_parents;
103262306a36Sopenharmony_ci	if (parent_count < 2) {
103362306a36Sopenharmony_ci		rate = kona_peri_clk_round_rate(hw, req->rate,
103462306a36Sopenharmony_ci						&req->best_parent_rate);
103562306a36Sopenharmony_ci		if (rate < 0)
103662306a36Sopenharmony_ci			return rate;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci		req->rate = rate;
103962306a36Sopenharmony_ci		return 0;
104062306a36Sopenharmony_ci	}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	/* Unless we can do better, stick with current parent */
104362306a36Sopenharmony_ci	current_parent = clk_hw_get_parent(hw);
104462306a36Sopenharmony_ci	parent_rate = clk_hw_get_rate(current_parent);
104562306a36Sopenharmony_ci	best_rate = kona_peri_clk_round_rate(hw, req->rate, &parent_rate);
104662306a36Sopenharmony_ci	best_delta = abs(best_rate - req->rate);
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	/* Check whether any other parent clock can produce a better result */
104962306a36Sopenharmony_ci	for (which = 0; which < parent_count; which++) {
105062306a36Sopenharmony_ci		struct clk_hw *parent = clk_hw_get_parent_by_index(hw, which);
105162306a36Sopenharmony_ci		unsigned long delta;
105262306a36Sopenharmony_ci		unsigned long other_rate;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci		BUG_ON(!parent);
105562306a36Sopenharmony_ci		if (parent == current_parent)
105662306a36Sopenharmony_ci			continue;
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci		/* We don't support CLK_SET_RATE_PARENT */
105962306a36Sopenharmony_ci		parent_rate = clk_hw_get_rate(parent);
106062306a36Sopenharmony_ci		other_rate = kona_peri_clk_round_rate(hw, req->rate,
106162306a36Sopenharmony_ci						      &parent_rate);
106262306a36Sopenharmony_ci		delta = abs(other_rate - req->rate);
106362306a36Sopenharmony_ci		if (delta < best_delta) {
106462306a36Sopenharmony_ci			best_delta = delta;
106562306a36Sopenharmony_ci			best_rate = other_rate;
106662306a36Sopenharmony_ci			req->best_parent_hw = parent;
106762306a36Sopenharmony_ci			req->best_parent_rate = parent_rate;
106862306a36Sopenharmony_ci		}
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	req->rate = best_rate;
107262306a36Sopenharmony_ci	return 0;
107362306a36Sopenharmony_ci}
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_cistatic int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
107662306a36Sopenharmony_ci{
107762306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
107862306a36Sopenharmony_ci	struct peri_clk_data *data = bcm_clk->u.peri;
107962306a36Sopenharmony_ci	struct bcm_clk_sel *sel = &data->sel;
108062306a36Sopenharmony_ci	struct bcm_clk_trig *trig;
108162306a36Sopenharmony_ci	int ret;
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	BUG_ON(index >= sel->parent_count);
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	/* If there's only one parent we don't require a selector */
108662306a36Sopenharmony_ci	if (!selector_exists(sel))
108762306a36Sopenharmony_ci		return 0;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	/*
109062306a36Sopenharmony_ci	 * The regular trigger is used by default, but if there's a
109162306a36Sopenharmony_ci	 * pre-trigger we want to use that instead.
109262306a36Sopenharmony_ci	 */
109362306a36Sopenharmony_ci	trig = trigger_exists(&data->pre_trig) ? &data->pre_trig
109462306a36Sopenharmony_ci					       : &data->trig;
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	ret = selector_write(bcm_clk->ccu, &data->gate, sel, trig, index);
109762306a36Sopenharmony_ci	if (ret == -ENXIO) {
109862306a36Sopenharmony_ci		pr_err("%s: gating failure for %s\n", __func__,
109962306a36Sopenharmony_ci			bcm_clk->init_data.name);
110062306a36Sopenharmony_ci		ret = -EIO;	/* Don't proliferate weird errors */
110162306a36Sopenharmony_ci	} else if (ret == -EIO) {
110262306a36Sopenharmony_ci		pr_err("%s: %strigger failed for %s\n", __func__,
110362306a36Sopenharmony_ci			trig == &data->pre_trig ? "pre-" : "",
110462306a36Sopenharmony_ci			bcm_clk->init_data.name);
110562306a36Sopenharmony_ci	}
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	return ret;
110862306a36Sopenharmony_ci}
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_cistatic u8 kona_peri_clk_get_parent(struct clk_hw *hw)
111162306a36Sopenharmony_ci{
111262306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
111362306a36Sopenharmony_ci	struct peri_clk_data *data = bcm_clk->u.peri;
111462306a36Sopenharmony_ci	u8 index;
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci	index = selector_read_index(bcm_clk->ccu, &data->sel);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	/* Not all callers would handle an out-of-range value gracefully */
111962306a36Sopenharmony_ci	return index == BAD_CLK_INDEX ? 0 : index;
112062306a36Sopenharmony_ci}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_cistatic int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
112362306a36Sopenharmony_ci			unsigned long parent_rate)
112462306a36Sopenharmony_ci{
112562306a36Sopenharmony_ci	struct kona_clk *bcm_clk = to_kona_clk(hw);
112662306a36Sopenharmony_ci	struct peri_clk_data *data = bcm_clk->u.peri;
112762306a36Sopenharmony_ci	struct bcm_clk_div *div = &data->div;
112862306a36Sopenharmony_ci	u64 scaled_div = 0;
112962306a36Sopenharmony_ci	int ret;
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	if (parent_rate > (unsigned long)LONG_MAX)
113262306a36Sopenharmony_ci		return -EINVAL;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	if (rate == clk_hw_get_rate(hw))
113562306a36Sopenharmony_ci		return 0;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	if (!divider_exists(div))
113862306a36Sopenharmony_ci		return rate == parent_rate ? 0 : -EINVAL;
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	/*
114162306a36Sopenharmony_ci	 * A fixed divider can't be changed.  (Nor can a fixed
114262306a36Sopenharmony_ci	 * pre-divider be, but for now we never actually try to
114362306a36Sopenharmony_ci	 * change that.)  Tolerate a request for a no-op change.
114462306a36Sopenharmony_ci	 */
114562306a36Sopenharmony_ci	if (divider_is_fixed(&data->div))
114662306a36Sopenharmony_ci		return rate == parent_rate ? 0 : -EINVAL;
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	/*
114962306a36Sopenharmony_ci	 * Get the scaled divisor value needed to achieve a clock
115062306a36Sopenharmony_ci	 * rate as close as possible to what was requested, given
115162306a36Sopenharmony_ci	 * the parent clock rate supplied.
115262306a36Sopenharmony_ci	 */
115362306a36Sopenharmony_ci	(void)round_rate(bcm_clk->ccu, div, &data->pre_div,
115462306a36Sopenharmony_ci				rate ? rate : 1, parent_rate, &scaled_div);
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	/*
115762306a36Sopenharmony_ci	 * We aren't updating any pre-divider at this point, so
115862306a36Sopenharmony_ci	 * we'll use the regular trigger.
115962306a36Sopenharmony_ci	 */
116062306a36Sopenharmony_ci	ret = divider_write(bcm_clk->ccu, &data->gate, &data->div,
116162306a36Sopenharmony_ci				&data->trig, scaled_div);
116262306a36Sopenharmony_ci	if (ret == -ENXIO) {
116362306a36Sopenharmony_ci		pr_err("%s: gating failure for %s\n", __func__,
116462306a36Sopenharmony_ci			bcm_clk->init_data.name);
116562306a36Sopenharmony_ci		ret = -EIO;	/* Don't proliferate weird errors */
116662306a36Sopenharmony_ci	} else if (ret == -EIO) {
116762306a36Sopenharmony_ci		pr_err("%s: trigger failed for %s\n", __func__,
116862306a36Sopenharmony_ci			bcm_clk->init_data.name);
116962306a36Sopenharmony_ci	}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	return ret;
117262306a36Sopenharmony_ci}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_cistruct clk_ops kona_peri_clk_ops = {
117562306a36Sopenharmony_ci	.enable = kona_peri_clk_enable,
117662306a36Sopenharmony_ci	.disable = kona_peri_clk_disable,
117762306a36Sopenharmony_ci	.is_enabled = kona_peri_clk_is_enabled,
117862306a36Sopenharmony_ci	.recalc_rate = kona_peri_clk_recalc_rate,
117962306a36Sopenharmony_ci	.determine_rate = kona_peri_clk_determine_rate,
118062306a36Sopenharmony_ci	.set_parent = kona_peri_clk_set_parent,
118162306a36Sopenharmony_ci	.get_parent = kona_peri_clk_get_parent,
118262306a36Sopenharmony_ci	.set_rate = kona_peri_clk_set_rate,
118362306a36Sopenharmony_ci};
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci/* Put a peripheral clock into its initial state */
118662306a36Sopenharmony_cistatic bool __peri_clk_init(struct kona_clk *bcm_clk)
118762306a36Sopenharmony_ci{
118862306a36Sopenharmony_ci	struct ccu_data *ccu = bcm_clk->ccu;
118962306a36Sopenharmony_ci	struct peri_clk_data *peri = bcm_clk->u.peri;
119062306a36Sopenharmony_ci	const char *name = bcm_clk->init_data.name;
119162306a36Sopenharmony_ci	struct bcm_clk_trig *trig;
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	BUG_ON(bcm_clk->type != bcm_clk_peri);
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	if (!policy_init(ccu, &peri->policy)) {
119662306a36Sopenharmony_ci		pr_err("%s: error initializing policy for %s\n",
119762306a36Sopenharmony_ci			__func__, name);
119862306a36Sopenharmony_ci		return false;
119962306a36Sopenharmony_ci	}
120062306a36Sopenharmony_ci	if (!gate_init(ccu, &peri->gate)) {
120162306a36Sopenharmony_ci		pr_err("%s: error initializing gate for %s\n", __func__, name);
120262306a36Sopenharmony_ci		return false;
120362306a36Sopenharmony_ci	}
120462306a36Sopenharmony_ci	if (!hyst_init(ccu, &peri->hyst)) {
120562306a36Sopenharmony_ci		pr_err("%s: error initializing hyst for %s\n", __func__, name);
120662306a36Sopenharmony_ci		return false;
120762306a36Sopenharmony_ci	}
120862306a36Sopenharmony_ci	if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) {
120962306a36Sopenharmony_ci		pr_err("%s: error initializing divider for %s\n", __func__,
121062306a36Sopenharmony_ci			name);
121162306a36Sopenharmony_ci		return false;
121262306a36Sopenharmony_ci	}
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	/*
121562306a36Sopenharmony_ci	 * For the pre-divider and selector, the pre-trigger is used
121662306a36Sopenharmony_ci	 * if it's present, otherwise we just use the regular trigger.
121762306a36Sopenharmony_ci	 */
121862306a36Sopenharmony_ci	trig = trigger_exists(&peri->pre_trig) ? &peri->pre_trig
121962306a36Sopenharmony_ci					       : &peri->trig;
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	if (!div_init(ccu, &peri->gate, &peri->pre_div, trig)) {
122262306a36Sopenharmony_ci		pr_err("%s: error initializing pre-divider for %s\n", __func__,
122362306a36Sopenharmony_ci			name);
122462306a36Sopenharmony_ci		return false;
122562306a36Sopenharmony_ci	}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	if (!sel_init(ccu, &peri->gate, &peri->sel, trig)) {
122862306a36Sopenharmony_ci		pr_err("%s: error initializing selector for %s\n", __func__,
122962306a36Sopenharmony_ci			name);
123062306a36Sopenharmony_ci		return false;
123162306a36Sopenharmony_ci	}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	return true;
123462306a36Sopenharmony_ci}
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_cistatic bool __kona_clk_init(struct kona_clk *bcm_clk)
123762306a36Sopenharmony_ci{
123862306a36Sopenharmony_ci	switch (bcm_clk->type) {
123962306a36Sopenharmony_ci	case bcm_clk_peri:
124062306a36Sopenharmony_ci		return __peri_clk_init(bcm_clk);
124162306a36Sopenharmony_ci	default:
124262306a36Sopenharmony_ci		BUG();
124362306a36Sopenharmony_ci	}
124462306a36Sopenharmony_ci	return false;
124562306a36Sopenharmony_ci}
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci/* Set a CCU and all its clocks into their desired initial state */
124862306a36Sopenharmony_cibool __init kona_ccu_init(struct ccu_data *ccu)
124962306a36Sopenharmony_ci{
125062306a36Sopenharmony_ci	unsigned long flags;
125162306a36Sopenharmony_ci	unsigned int which;
125262306a36Sopenharmony_ci	struct kona_clk *kona_clks = ccu->kona_clks;
125362306a36Sopenharmony_ci	bool success = true;
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	flags = ccu_lock(ccu);
125662306a36Sopenharmony_ci	__ccu_write_enable(ccu);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	for (which = 0; which < ccu->clk_num; which++) {
125962306a36Sopenharmony_ci		struct kona_clk *bcm_clk = &kona_clks[which];
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci		if (!bcm_clk->ccu)
126262306a36Sopenharmony_ci			continue;
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci		success &= __kona_clk_init(bcm_clk);
126562306a36Sopenharmony_ci	}
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	__ccu_write_disable(ccu);
126862306a36Sopenharmony_ci	ccu_unlock(ccu, flags);
126962306a36Sopenharmony_ci	return success;
127062306a36Sopenharmony_ci}
1271