brintos

brintos / linux-shallow public Read only

0
0
Text · 21.0 KiB · 0c9c834 Raw
853 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Ingenic SoC CGU driver4 *5 * Copyright (c) 2013-2015 Imagination Technologies6 * Author: Paul Burton <paul.burton@mips.com>7 */8 9#include <linux/bitops.h>10#include <linux/clk.h>11#include <linux/clk-provider.h>12#include <linux/clkdev.h>13#include <linux/delay.h>14#include <linux/io.h>15#include <linux/iopoll.h>16#include <linux/math64.h>17#include <linux/of.h>18#include <linux/of_address.h>19#include <linux/slab.h>20#include <linux/spinlock.h>21#include <linux/time.h>22 23#include "cgu.h"24 25#define MHZ (1000 * 1000)26 27static inline const struct ingenic_cgu_clk_info *28to_clk_info(struct ingenic_clk *clk)29{30	return &clk->cgu->clock_info[clk->idx];31}32 33/**34 * ingenic_cgu_gate_get() - get the value of clock gate register bit35 * @cgu: reference to the CGU whose registers should be read36 * @info: info struct describing the gate bit37 *38 * Retrieves the state of the clock gate bit described by info. The39 * caller must hold cgu->lock.40 *41 * Return: true if the gate bit is set, else false.42 */43static inline bool44ingenic_cgu_gate_get(struct ingenic_cgu *cgu,45		     const struct ingenic_cgu_gate_info *info)46{47	return !!(readl(cgu->base + info->reg) & BIT(info->bit))48		^ info->clear_to_gate;49}50 51/**52 * ingenic_cgu_gate_set() - set the value of clock gate register bit53 * @cgu: reference to the CGU whose registers should be modified54 * @info: info struct describing the gate bit55 * @val: non-zero to gate a clock, otherwise zero56 *57 * Sets the given gate bit in order to gate or ungate a clock.58 *59 * The caller must hold cgu->lock.60 */61static inline void62ingenic_cgu_gate_set(struct ingenic_cgu *cgu,63		     const struct ingenic_cgu_gate_info *info, bool val)64{65	u32 clkgr = readl(cgu->base + info->reg);66 67	if (val ^ info->clear_to_gate)68		clkgr |= BIT(info->bit);69	else70		clkgr &= ~BIT(info->bit);71 72	writel(clkgr, cgu->base + info->reg);73}74 75/*76 * PLL operations77 */78 79static unsigned long80ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)81{82	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);83	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);84	struct ingenic_cgu *cgu = ingenic_clk->cgu;85	const struct ingenic_cgu_pll_info *pll_info;86	unsigned m, n, od, od_enc = 0;87	bool bypass;88	u32 ctl;89 90	BUG_ON(clk_info->type != CGU_CLK_PLL);91	pll_info = &clk_info->pll;92 93	ctl = readl(cgu->base + pll_info->reg);94 95	m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0);96	m += pll_info->m_offset;97	n = (ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0);98	n += pll_info->n_offset;99 100	if (pll_info->od_bits > 0) {101		od_enc = ctl >> pll_info->od_shift;102		od_enc &= GENMASK(pll_info->od_bits - 1, 0);103	}104 105	if (pll_info->bypass_bit >= 0) {106		ctl = readl(cgu->base + pll_info->bypass_reg);107 108		bypass = !!(ctl & BIT(pll_info->bypass_bit));109 110		if (bypass)111			return parent_rate;112	}113 114	for (od = 0; od < pll_info->od_max; od++)115		if (pll_info->od_encoding[od] == od_enc)116			break;117 118	/* if od_max = 0, od_bits should be 0 and od is fixed to 1. */119	if (pll_info->od_max == 0)120		BUG_ON(pll_info->od_bits != 0);121	else122		BUG_ON(od == pll_info->od_max);123	od++;124 125	return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,126		n * od);127}128 129static void130ingenic_pll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,131			unsigned long rate, unsigned long parent_rate,132			unsigned int *pm, unsigned int *pn, unsigned int *pod)133{134	unsigned int m, n, od = 1;135 136	/*137	 * The frequency after the input divider must be between 10 and 50 MHz.138	 * The highest divider yields the best resolution.139	 */140	n = parent_rate / (10 * MHZ);141	n = min_t(unsigned int, n, 1 << pll_info->n_bits);142	n = max_t(unsigned int, n, pll_info->n_offset);143 144	m = (rate / MHZ) * od * n / (parent_rate / MHZ);145	m = min_t(unsigned int, m, 1 << pll_info->m_bits);146	m = max_t(unsigned int, m, pll_info->m_offset);147 148	*pm = m;149	*pn = n;150	*pod = od;151}152 153static unsigned long154ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,155		 unsigned long rate, unsigned long parent_rate,156		 unsigned int *pm, unsigned int *pn, unsigned int *pod)157{158	const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;159	unsigned int m, n, od;160 161	if (pll_info->calc_m_n_od)162		(*pll_info->calc_m_n_od)(pll_info, rate, parent_rate, &m, &n, &od);163	else164		ingenic_pll_calc_m_n_od(pll_info, rate, parent_rate, &m, &n, &od);165 166	if (pm)167		*pm = m;168	if (pn)169		*pn = n;170	if (pod)171		*pod = od;172 173	return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,174		n * od);175}176 177static long178ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,179		       unsigned long *prate)180{181	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);182	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);183 184	return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);185}186 187static inline int ingenic_pll_check_stable(struct ingenic_cgu *cgu,188					   const struct ingenic_cgu_pll_info *pll_info)189{190	u32 ctl;191 192	if (pll_info->stable_bit < 0)193		return 0;194 195	return readl_poll_timeout(cgu->base + pll_info->reg, ctl,196				  ctl & BIT(pll_info->stable_bit),197				  0, 100 * USEC_PER_MSEC);198}199 200static int201ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,202		     unsigned long parent_rate)203{204	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);205	struct ingenic_cgu *cgu = ingenic_clk->cgu;206	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);207	const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;208	unsigned long rate, flags;209	unsigned int m, n, od;210	int ret = 0;211	u32 ctl;212 213	rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,214			       &m, &n, &od);215	if (rate != req_rate)216		pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n",217			clk_info->name, req_rate, rate);218 219	spin_lock_irqsave(&cgu->lock, flags);220	ctl = readl(cgu->base + pll_info->reg);221 222	ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift);223	ctl |= (m - pll_info->m_offset) << pll_info->m_shift;224 225	ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);226	ctl |= (n - pll_info->n_offset) << pll_info->n_shift;227 228	if (pll_info->od_bits > 0) {229		ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);230		ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;231	}232 233	writel(ctl, cgu->base + pll_info->reg);234 235	if (pll_info->set_rate_hook)236		pll_info->set_rate_hook(pll_info, rate, parent_rate);237 238	/* If the PLL is enabled, verify that it's stable */239	if (pll_info->enable_bit >= 0 && (ctl & BIT(pll_info->enable_bit)))240		ret = ingenic_pll_check_stable(cgu, pll_info);241 242	spin_unlock_irqrestore(&cgu->lock, flags);243 244	return ret;245}246 247static int ingenic_pll_enable(struct clk_hw *hw)248{249	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);250	struct ingenic_cgu *cgu = ingenic_clk->cgu;251	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);252	const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;253	unsigned long flags;254	int ret;255	u32 ctl;256 257	if (pll_info->enable_bit < 0)258		return 0;259 260	spin_lock_irqsave(&cgu->lock, flags);261	if (pll_info->bypass_bit >= 0) {262		ctl = readl(cgu->base + pll_info->bypass_reg);263 264		ctl &= ~BIT(pll_info->bypass_bit);265 266		writel(ctl, cgu->base + pll_info->bypass_reg);267	}268 269	ctl = readl(cgu->base + pll_info->reg);270 271	ctl |= BIT(pll_info->enable_bit);272 273	writel(ctl, cgu->base + pll_info->reg);274 275	ret = ingenic_pll_check_stable(cgu, pll_info);276	spin_unlock_irqrestore(&cgu->lock, flags);277 278	return ret;279}280 281static void ingenic_pll_disable(struct clk_hw *hw)282{283	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);284	struct ingenic_cgu *cgu = ingenic_clk->cgu;285	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);286	const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;287	unsigned long flags;288	u32 ctl;289 290	if (pll_info->enable_bit < 0)291		return;292 293	spin_lock_irqsave(&cgu->lock, flags);294	ctl = readl(cgu->base + pll_info->reg);295 296	ctl &= ~BIT(pll_info->enable_bit);297 298	writel(ctl, cgu->base + pll_info->reg);299	spin_unlock_irqrestore(&cgu->lock, flags);300}301 302static int ingenic_pll_is_enabled(struct clk_hw *hw)303{304	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);305	struct ingenic_cgu *cgu = ingenic_clk->cgu;306	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);307	const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;308	u32 ctl;309 310	if (pll_info->enable_bit < 0)311		return true;312 313	ctl = readl(cgu->base + pll_info->reg);314 315	return !!(ctl & BIT(pll_info->enable_bit));316}317 318static const struct clk_ops ingenic_pll_ops = {319	.recalc_rate = ingenic_pll_recalc_rate,320	.round_rate = ingenic_pll_round_rate,321	.set_rate = ingenic_pll_set_rate,322 323	.enable = ingenic_pll_enable,324	.disable = ingenic_pll_disable,325	.is_enabled = ingenic_pll_is_enabled,326};327 328/*329 * Operations for all non-PLL clocks330 */331 332static u8 ingenic_clk_get_parent(struct clk_hw *hw)333{334	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);335	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);336	struct ingenic_cgu *cgu = ingenic_clk->cgu;337	u32 reg;338	u8 i, hw_idx, idx = 0;339 340	if (clk_info->type & CGU_CLK_MUX) {341		reg = readl(cgu->base + clk_info->mux.reg);342		hw_idx = (reg >> clk_info->mux.shift) &343			 GENMASK(clk_info->mux.bits - 1, 0);344 345		/*346		 * Convert the hardware index to the parent index by skipping347		 * over any -1's in the parents array.348		 */349		for (i = 0; i < hw_idx; i++) {350			if (clk_info->parents[i] != -1)351				idx++;352		}353	}354 355	return idx;356}357 358static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)359{360	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);361	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);362	struct ingenic_cgu *cgu = ingenic_clk->cgu;363	unsigned long flags;364	u8 curr_idx, hw_idx, num_poss;365	u32 reg, mask;366 367	if (clk_info->type & CGU_CLK_MUX) {368		/*369		 * Convert the parent index to the hardware index by adding370		 * 1 for any -1 in the parents array preceding the given371		 * index. That is, we want the index of idx'th entry in372		 * clk_info->parents which does not equal -1.373		 */374		hw_idx = curr_idx = 0;375		num_poss = 1 << clk_info->mux.bits;376		for (; hw_idx < num_poss; hw_idx++) {377			if (clk_info->parents[hw_idx] == -1)378				continue;379			if (curr_idx == idx)380				break;381			curr_idx++;382		}383 384		/* idx should always be a valid parent */385		BUG_ON(curr_idx != idx);386 387		mask = GENMASK(clk_info->mux.bits - 1, 0);388		mask <<= clk_info->mux.shift;389 390		spin_lock_irqsave(&cgu->lock, flags);391 392		/* write the register */393		reg = readl(cgu->base + clk_info->mux.reg);394		reg &= ~mask;395		reg |= hw_idx << clk_info->mux.shift;396		writel(reg, cgu->base + clk_info->mux.reg);397 398		spin_unlock_irqrestore(&cgu->lock, flags);399		return 0;400	}401 402	return idx ? -EINVAL : 0;403}404 405static unsigned long406ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)407{408	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);409	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);410	struct ingenic_cgu *cgu = ingenic_clk->cgu;411	unsigned long rate = parent_rate;412	u32 div_reg, div;413	u8 parent;414 415	if (clk_info->type & CGU_CLK_DIV) {416		parent = ingenic_clk_get_parent(hw);417 418		if (!(clk_info->div.bypass_mask & BIT(parent))) {419			div_reg = readl(cgu->base + clk_info->div.reg);420			div = (div_reg >> clk_info->div.shift) &421			      GENMASK(clk_info->div.bits - 1, 0);422 423			if (clk_info->div.div_table)424				div = clk_info->div.div_table[div];425			else426				div = (div + 1) * clk_info->div.div;427 428			rate /= div;429		}430	} else if (clk_info->type & CGU_CLK_FIXDIV) {431		rate /= clk_info->fixdiv.div;432	}433 434	return rate;435}436 437static unsigned int438ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info,439			unsigned int div)440{441	unsigned int i, best_i = 0, best = (unsigned int)-1;442 443	for (i = 0; i < (1 << clk_info->div.bits)444				&& clk_info->div.div_table[i]; i++) {445		if (clk_info->div.div_table[i] >= div &&446		    clk_info->div.div_table[i] < best) {447			best = clk_info->div.div_table[i];448			best_i = i;449 450			if (div == best)451				break;452		}453	}454 455	return best_i;456}457 458static unsigned459ingenic_clk_calc_div(struct clk_hw *hw,460		     const struct ingenic_cgu_clk_info *clk_info,461		     unsigned long parent_rate, unsigned long req_rate)462{463	unsigned int div, hw_div;464	u8 parent;465 466	parent = ingenic_clk_get_parent(hw);467	if (clk_info->div.bypass_mask & BIT(parent))468		return 1;469 470	/* calculate the divide */471	div = DIV_ROUND_UP(parent_rate, req_rate);472 473	if (clk_info->div.div_table) {474		hw_div = ingenic_clk_calc_hw_div(clk_info, div);475 476		return clk_info->div.div_table[hw_div];477	}478 479	/* Impose hardware constraints */480	div = clamp_t(unsigned int, div, clk_info->div.div,481		      clk_info->div.div << clk_info->div.bits);482 483	/*484	 * If the divider value itself must be divided before being written to485	 * the divider register, we must ensure we don't have any bits set that486	 * would be lost as a result of doing so.487	 */488	div = DIV_ROUND_UP(div, clk_info->div.div);489	div *= clk_info->div.div;490 491	return div;492}493 494static int ingenic_clk_determine_rate(struct clk_hw *hw,495				      struct clk_rate_request *req)496{497	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);498	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);499	unsigned int div = 1;500 501	if (clk_info->type & CGU_CLK_DIV)502		div = ingenic_clk_calc_div(hw, clk_info, req->best_parent_rate,503					   req->rate);504	else if (clk_info->type & CGU_CLK_FIXDIV)505		div = clk_info->fixdiv.div;506	else if (clk_hw_can_set_rate_parent(hw))507		req->best_parent_rate = req->rate;508 509	req->rate = DIV_ROUND_UP(req->best_parent_rate, div);510	return 0;511}512 513static inline int ingenic_clk_check_stable(struct ingenic_cgu *cgu,514					   const struct ingenic_cgu_clk_info *clk_info)515{516	u32 reg;517 518	return readl_poll_timeout(cgu->base + clk_info->div.reg, reg,519				  !(reg & BIT(clk_info->div.busy_bit)),520				  0, 100 * USEC_PER_MSEC);521}522 523static int524ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,525		     unsigned long parent_rate)526{527	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);528	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);529	struct ingenic_cgu *cgu = ingenic_clk->cgu;530	unsigned long rate, flags;531	unsigned int hw_div, div;532	u32 reg, mask;533	int ret = 0;534 535	if (clk_info->type & CGU_CLK_DIV) {536		div = ingenic_clk_calc_div(hw, clk_info, parent_rate, req_rate);537		rate = DIV_ROUND_UP(parent_rate, div);538 539		if (rate != req_rate)540			return -EINVAL;541 542		if (clk_info->div.div_table)543			hw_div = ingenic_clk_calc_hw_div(clk_info, div);544		else545			hw_div = ((div / clk_info->div.div) - 1);546 547		spin_lock_irqsave(&cgu->lock, flags);548		reg = readl(cgu->base + clk_info->div.reg);549 550		/* update the divide */551		mask = GENMASK(clk_info->div.bits - 1, 0);552		reg &= ~(mask << clk_info->div.shift);553		reg |= hw_div << clk_info->div.shift;554 555		/* clear the stop bit */556		if (clk_info->div.stop_bit != -1)557			reg &= ~BIT(clk_info->div.stop_bit);558 559		/* set the change enable bit */560		if (clk_info->div.ce_bit != -1)561			reg |= BIT(clk_info->div.ce_bit);562 563		/* update the hardware */564		writel(reg, cgu->base + clk_info->div.reg);565 566		/* wait for the change to take effect */567		if (clk_info->div.busy_bit != -1)568			ret = ingenic_clk_check_stable(cgu, clk_info);569 570		spin_unlock_irqrestore(&cgu->lock, flags);571		return ret;572	}573 574	return -EINVAL;575}576 577static int ingenic_clk_enable(struct clk_hw *hw)578{579	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);580	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);581	struct ingenic_cgu *cgu = ingenic_clk->cgu;582	unsigned long flags;583 584	if (clk_info->type & CGU_CLK_GATE) {585		/* ungate the clock */586		spin_lock_irqsave(&cgu->lock, flags);587		ingenic_cgu_gate_set(cgu, &clk_info->gate, false);588		spin_unlock_irqrestore(&cgu->lock, flags);589 590		if (clk_info->gate.delay_us)591			udelay(clk_info->gate.delay_us);592	}593 594	return 0;595}596 597static void ingenic_clk_disable(struct clk_hw *hw)598{599	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);600	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);601	struct ingenic_cgu *cgu = ingenic_clk->cgu;602	unsigned long flags;603 604	if (clk_info->type & CGU_CLK_GATE) {605		/* gate the clock */606		spin_lock_irqsave(&cgu->lock, flags);607		ingenic_cgu_gate_set(cgu, &clk_info->gate, true);608		spin_unlock_irqrestore(&cgu->lock, flags);609	}610}611 612static int ingenic_clk_is_enabled(struct clk_hw *hw)613{614	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);615	const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);616	struct ingenic_cgu *cgu = ingenic_clk->cgu;617	int enabled = 1;618 619	if (clk_info->type & CGU_CLK_GATE)620		enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);621 622	return enabled;623}624 625static const struct clk_ops ingenic_clk_ops = {626	.get_parent = ingenic_clk_get_parent,627	.set_parent = ingenic_clk_set_parent,628 629	.recalc_rate = ingenic_clk_recalc_rate,630	.determine_rate = ingenic_clk_determine_rate,631	.set_rate = ingenic_clk_set_rate,632 633	.enable = ingenic_clk_enable,634	.disable = ingenic_clk_disable,635	.is_enabled = ingenic_clk_is_enabled,636};637 638/*639 * Setup functions.640 */641 642static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)643{644	const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];645	struct clk_init_data clk_init;646	struct ingenic_clk *ingenic_clk = NULL;647	struct clk *clk, *parent;648	const char *parent_names[4];649	unsigned caps, i, num_possible;650	int err = -EINVAL;651 652	BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));653 654	if (clk_info->type == CGU_CLK_EXT) {655		clk = of_clk_get_by_name(cgu->np, clk_info->name);656		if (IS_ERR(clk)) {657			pr_err("%s: no external clock '%s' provided\n",658			       __func__, clk_info->name);659			err = -ENODEV;660			goto out;661		}662		err = clk_register_clkdev(clk, clk_info->name, NULL);663		if (err) {664			clk_put(clk);665			goto out;666		}667		cgu->clocks.clks[idx] = clk;668		return 0;669	}670 671	if (!clk_info->type) {672		pr_err("%s: no clock type specified for '%s'\n", __func__,673		       clk_info->name);674		goto out;675	}676 677	ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);678	if (!ingenic_clk) {679		err = -ENOMEM;680		goto out;681	}682 683	ingenic_clk->hw.init = &clk_init;684	ingenic_clk->cgu = cgu;685	ingenic_clk->idx = idx;686 687	clk_init.name = clk_info->name;688	clk_init.flags = clk_info->flags;689	clk_init.parent_names = parent_names;690 691	caps = clk_info->type;692 693	if (caps & CGU_CLK_DIV) {694		caps &= ~CGU_CLK_DIV;695	} else if (!(caps & CGU_CLK_CUSTOM)) {696		/* pass rate changes to the parent clock */697		clk_init.flags |= CLK_SET_RATE_PARENT;698	}699 700	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {701		clk_init.num_parents = 0;702 703		if (caps & CGU_CLK_MUX)704			num_possible = 1 << clk_info->mux.bits;705		else706			num_possible = ARRAY_SIZE(clk_info->parents);707 708		for (i = 0; i < num_possible; i++) {709			if (clk_info->parents[i] == -1)710				continue;711 712			parent = cgu->clocks.clks[clk_info->parents[i]];713			parent_names[clk_init.num_parents] =714				__clk_get_name(parent);715			clk_init.num_parents++;716		}717 718		BUG_ON(!clk_init.num_parents);719		BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));720	} else {721		BUG_ON(clk_info->parents[0] == -1);722		clk_init.num_parents = 1;723		parent = cgu->clocks.clks[clk_info->parents[0]];724		parent_names[0] = __clk_get_name(parent);725	}726 727	if (caps & CGU_CLK_CUSTOM) {728		clk_init.ops = clk_info->custom.clk_ops;729 730		caps &= ~CGU_CLK_CUSTOM;731 732		if (caps) {733			pr_err("%s: custom clock may not be combined with type 0x%x\n",734			       __func__, caps);735			goto out;736		}737	} else if (caps & CGU_CLK_PLL) {738		clk_init.ops = &ingenic_pll_ops;739 740		caps &= ~CGU_CLK_PLL;741 742		if (caps) {743			pr_err("%s: PLL may not be combined with type 0x%x\n",744			       __func__, caps);745			goto out;746		}747	} else {748		clk_init.ops = &ingenic_clk_ops;749	}750 751	/* nothing to do for gates or fixed dividers */752	caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);753 754	if (caps & CGU_CLK_MUX) {755		if (!(caps & CGU_CLK_MUX_GLITCHFREE))756			clk_init.flags |= CLK_SET_PARENT_GATE;757 758		caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);759	}760 761	if (caps) {762		pr_err("%s: unknown clock type 0x%x\n", __func__, caps);763		goto out;764	}765 766	clk = clk_register(NULL, &ingenic_clk->hw);767	if (IS_ERR(clk)) {768		pr_err("%s: failed to register clock '%s'\n", __func__,769		       clk_info->name);770		err = PTR_ERR(clk);771		goto out;772	}773 774	err = clk_register_clkdev(clk, clk_info->name, NULL);775	if (err)776		goto out;777 778	cgu->clocks.clks[idx] = clk;779out:780	if (err)781		kfree(ingenic_clk);782	return err;783}784 785struct ingenic_cgu *786ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,787		unsigned num_clocks, struct device_node *np)788{789	struct ingenic_cgu *cgu;790 791	cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);792	if (!cgu)793		goto err_out;794 795	cgu->base = of_iomap(np, 0);796	if (!cgu->base) {797		pr_err("%s: failed to map CGU registers\n", __func__);798		goto err_out_free;799	}800 801	cgu->np = np;802	cgu->clock_info = clock_info;803	cgu->clocks.clk_num = num_clocks;804 805	spin_lock_init(&cgu->lock);806 807	return cgu;808 809err_out_free:810	kfree(cgu);811err_out:812	return NULL;813}814 815int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)816{817	unsigned i;818	int err;819 820	cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),821				   GFP_KERNEL);822	if (!cgu->clocks.clks) {823		err = -ENOMEM;824		goto err_out;825	}826 827	for (i = 0; i < cgu->clocks.clk_num; i++) {828		err = ingenic_register_clock(cgu, i);829		if (err)830			goto err_out_unregister;831	}832 833	err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,834				  &cgu->clocks);835	if (err)836		goto err_out_unregister;837 838	return 0;839 840err_out_unregister:841	for (i = 0; i < cgu->clocks.clk_num; i++) {842		if (!cgu->clocks.clks[i])843			continue;844		if (cgu->clock_info[i].type & CGU_CLK_EXT)845			clk_put(cgu->clocks.clks[i]);846		else847			clk_unregister(cgu->clocks.clks[i]);848	}849	kfree(cgu->clocks.clks);850err_out:851	return err;852}853