Linux Audio

Check our new training course

Loading...
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *  Copyright (C) 2015 Atmel Corporation,
  4 *                     Nicolas Ferre <nicolas.ferre@atmel.com>
  5 *
  6 * Based on clk-programmable & clk-peripheral drivers by Boris BREZILLON.
 
 
 
 
 
 
  7 */
  8
  9#include <linux/bitfield.h>
 10#include <linux/clk-provider.h>
 11#include <linux/clkdev.h>
 12#include <linux/clk/at91_pmc.h>
 13#include <linux/of.h>
 14#include <linux/mfd/syscon.h>
 15#include <linux/regmap.h>
 16
 17#include "pmc.h"
 18
 
 
 
 
 19#define GENERATED_MAX_DIV	255
 20
 
 
 
 
 
 
 
 21struct clk_generated {
 22	struct clk_hw hw;
 23	struct regmap *regmap;
 24	struct clk_range range;
 25	spinlock_t *lock;
 26	u32 *mux_table;
 27	u32 id;
 28	u32 gckdiv;
 29	const struct clk_pcr_layout *layout;
 30	u8 parent_id;
 31	int chg_pid;
 32};
 33
 34#define to_clk_generated(hw) \
 35	container_of(hw, struct clk_generated, hw)
 36
 37static int clk_generated_enable(struct clk_hw *hw)
 38{
 39	struct clk_generated *gck = to_clk_generated(hw);
 40	unsigned long flags;
 41
 42	pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
 43		 __func__, gck->gckdiv, gck->parent_id);
 44
 45	spin_lock_irqsave(gck->lock, flags);
 46	regmap_write(gck->regmap, gck->layout->offset,
 47		     (gck->id & gck->layout->pid_mask));
 48	regmap_update_bits(gck->regmap, gck->layout->offset,
 49			   AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
 50			   gck->layout->cmd | AT91_PMC_PCR_GCKEN,
 51			   field_prep(gck->layout->gckcss_mask, gck->parent_id) |
 52			   gck->layout->cmd |
 53			   FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
 54			   AT91_PMC_PCR_GCKEN);
 55	spin_unlock_irqrestore(gck->lock, flags);
 56	return 0;
 57}
 58
 59static void clk_generated_disable(struct clk_hw *hw)
 60{
 61	struct clk_generated *gck = to_clk_generated(hw);
 62	unsigned long flags;
 63
 64	spin_lock_irqsave(gck->lock, flags);
 65	regmap_write(gck->regmap, gck->layout->offset,
 66		     (gck->id & gck->layout->pid_mask));
 67	regmap_update_bits(gck->regmap, gck->layout->offset,
 68			   gck->layout->cmd | AT91_PMC_PCR_GCKEN,
 69			   gck->layout->cmd);
 70	spin_unlock_irqrestore(gck->lock, flags);
 71}
 72
 73static int clk_generated_is_enabled(struct clk_hw *hw)
 74{
 75	struct clk_generated *gck = to_clk_generated(hw);
 76	unsigned long flags;
 77	unsigned int status;
 78
 79	spin_lock_irqsave(gck->lock, flags);
 80	regmap_write(gck->regmap, gck->layout->offset,
 81		     (gck->id & gck->layout->pid_mask));
 82	regmap_read(gck->regmap, gck->layout->offset, &status);
 83	spin_unlock_irqrestore(gck->lock, flags);
 84
 85	return !!(status & AT91_PMC_PCR_GCKEN);
 86}
 87
 88static unsigned long
 89clk_generated_recalc_rate(struct clk_hw *hw,
 90			  unsigned long parent_rate)
 91{
 92	struct clk_generated *gck = to_clk_generated(hw);
 93
 94	return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1);
 95}
 96
 97static void clk_generated_best_diff(struct clk_rate_request *req,
 98				    struct clk_hw *parent,
 99				    unsigned long parent_rate, u32 div,
100				    int *best_diff, long *best_rate)
101{
102	unsigned long tmp_rate;
103	int tmp_diff;
104
105	if (!div)
106		tmp_rate = parent_rate;
107	else
108		tmp_rate = parent_rate / div;
109	tmp_diff = abs(req->rate - tmp_rate);
110
111	if (*best_diff < 0 || *best_diff >= tmp_diff) {
112		*best_rate = tmp_rate;
113		*best_diff = tmp_diff;
114		req->best_parent_rate = parent_rate;
115		req->best_parent_hw = parent;
116	}
117}
118
119static int clk_generated_determine_rate(struct clk_hw *hw,
120					struct clk_rate_request *req)
121{
122	struct clk_generated *gck = to_clk_generated(hw);
123	struct clk_hw *parent = NULL;
124	struct clk_rate_request req_parent = *req;
125	long best_rate = -EINVAL;
126	unsigned long min_rate, parent_rate;
127	int best_diff = -1;
128	int i;
129	u32 div;
130
131	/* do not look for a rate that is outside of our range */
132	if (gck->range.max && req->rate > gck->range.max)
133		req->rate = gck->range.max;
134	if (gck->range.min && req->rate < gck->range.min)
135		req->rate = gck->range.min;
136
137	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
138		if (gck->chg_pid == i)
139			continue;
140
141		parent = clk_hw_get_parent_by_index(hw, i);
142		if (!parent)
143			continue;
144
145		parent_rate = clk_hw_get_rate(parent);
146		min_rate = DIV_ROUND_CLOSEST(parent_rate, GENERATED_MAX_DIV + 1);
147		if (!parent_rate ||
148		    (gck->range.max && min_rate > gck->range.max))
149			continue;
150
151		div = DIV_ROUND_CLOSEST(parent_rate, req->rate);
152		if (div > GENERATED_MAX_DIV + 1)
153			div = GENERATED_MAX_DIV + 1;
154
155		clk_generated_best_diff(req, parent, parent_rate, div,
156					&best_diff, &best_rate);
157
158		if (!best_diff)
159			break;
160	}
161
162	/*
163	 * The audio_pll rate can be modified, unlike the five others clocks
164	 * that should never be altered.
165	 * The audio_pll can technically be used by multiple consumers. However,
166	 * with the rate locking, the first consumer to enable to clock will be
167	 * the one definitely setting the rate of the clock.
168	 * Since audio IPs are most likely to request the same rate, we enforce
169	 * that the only clks able to modify gck rate are those of audio IPs.
170	 */
171
172	if (gck->chg_pid < 0)
173		goto end;
174
175	parent = clk_hw_get_parent_by_index(hw, gck->chg_pid);
176	if (!parent)
177		goto end;
178
179	for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
180		req_parent.rate = req->rate * div;
181		if (__clk_determine_rate(parent, &req_parent))
182			continue;
183		clk_generated_best_diff(req, parent, req_parent.rate, div,
184					&best_diff, &best_rate);
185
186		if (!best_diff)
187			break;
188	}
189
190end:
191	pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
192		 __func__, best_rate,
193		 __clk_get_name((req->best_parent_hw)->clk),
194		 req->best_parent_rate);
195
196	if (best_rate < 0 || (gck->range.max && best_rate > gck->range.max))
197		return -EINVAL;
198
199	req->rate = best_rate;
200	return 0;
201}
202
203/* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */
204static int clk_generated_set_parent(struct clk_hw *hw, u8 index)
205{
206	struct clk_generated *gck = to_clk_generated(hw);
207
208	if (index >= clk_hw_get_num_parents(hw))
209		return -EINVAL;
210
211	if (gck->mux_table)
212		gck->parent_id = clk_mux_index_to_val(gck->mux_table, 0, index);
213	else
214		gck->parent_id = index;
215
216	return 0;
217}
218
219static u8 clk_generated_get_parent(struct clk_hw *hw)
220{
221	struct clk_generated *gck = to_clk_generated(hw);
222
223	return gck->parent_id;
224}
225
226/* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */
227static int clk_generated_set_rate(struct clk_hw *hw,
228				  unsigned long rate,
229				  unsigned long parent_rate)
230{
231	struct clk_generated *gck = to_clk_generated(hw);
232	u32 div;
233
234	if (!rate)
235		return -EINVAL;
236
237	if (gck->range.max && rate > gck->range.max)
238		return -EINVAL;
239
240	div = DIV_ROUND_CLOSEST(parent_rate, rate);
241	if (div > GENERATED_MAX_DIV + 1 || !div)
242		return -EINVAL;
243
244	gck->gckdiv = div - 1;
245	return 0;
246}
247
248static const struct clk_ops generated_ops = {
249	.enable = clk_generated_enable,
250	.disable = clk_generated_disable,
251	.is_enabled = clk_generated_is_enabled,
252	.recalc_rate = clk_generated_recalc_rate,
253	.determine_rate = clk_generated_determine_rate,
254	.get_parent = clk_generated_get_parent,
255	.set_parent = clk_generated_set_parent,
256	.set_rate = clk_generated_set_rate,
257};
258
259/**
260 * clk_generated_startup - Initialize a given clock to its default parent and
261 * divisor parameter.
262 *
263 * @gck:	Generated clock to set the startup parameters for.
264 *
265 * Take parameters from the hardware and update local clock configuration
266 * accordingly.
267 */
268static void clk_generated_startup(struct clk_generated *gck)
269{
270	u32 tmp;
271	unsigned long flags;
272
273	spin_lock_irqsave(gck->lock, flags);
274	regmap_write(gck->regmap, gck->layout->offset,
275		     (gck->id & gck->layout->pid_mask));
276	regmap_read(gck->regmap, gck->layout->offset, &tmp);
277	spin_unlock_irqrestore(gck->lock, flags);
278
279	gck->parent_id = field_get(gck->layout->gckcss_mask, tmp);
280	gck->gckdiv = FIELD_GET(AT91_PMC_PCR_GCKDIV_MASK, tmp);
 
 
281}
282
283struct clk_hw * __init
284at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
285			    const struct clk_pcr_layout *layout,
286			    const char *name, const char **parent_names,
287			    u32 *mux_table, u8 num_parents, u8 id,
288			    const struct clk_range *range,
289			    int chg_pid)
290{
291	struct clk_generated *gck;
292	struct clk_init_data init;
293	struct clk_hw *hw;
294	int ret;
295
296	gck = kzalloc(sizeof(*gck), GFP_KERNEL);
297	if (!gck)
298		return ERR_PTR(-ENOMEM);
299
300	init.name = name;
301	init.ops = &generated_ops;
302	init.parent_names = parent_names;
303	init.num_parents = num_parents;
304	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
305	if (chg_pid >= 0)
306		init.flags |= CLK_SET_RATE_PARENT;
307
308	gck->id = id;
309	gck->hw.init = &init;
310	gck->regmap = regmap;
311	gck->lock = lock;
312	gck->range = *range;
313	gck->chg_pid = chg_pid;
314	gck->layout = layout;
315	gck->mux_table = mux_table;
316
317	clk_generated_startup(gck);
318	hw = &gck->hw;
319	ret = clk_hw_register(NULL, &gck->hw);
320	if (ret) {
321		kfree(gck);
322		hw = ERR_PTR(ret);
323	} else {
324		pmc_register_id(id);
325	}
326
327	return hw;
328}
v4.17
 
  1/*
  2 *  Copyright (C) 2015 Atmel Corporation,
  3 *                     Nicolas Ferre <nicolas.ferre@atmel.com>
  4 *
  5 * Based on clk-programmable & clk-peripheral drivers by Boris BREZILLON.
  6 *
  7 * This program is free software; you can redistribute it and/or modify
  8 * it under the terms of the GNU General Public License as published by
  9 * the Free Software Foundation; either version 2 of the License, or
 10 * (at your option) any later version.
 11 *
 12 */
 13
 
 14#include <linux/clk-provider.h>
 15#include <linux/clkdev.h>
 16#include <linux/clk/at91_pmc.h>
 17#include <linux/of.h>
 18#include <linux/mfd/syscon.h>
 19#include <linux/regmap.h>
 20
 21#include "pmc.h"
 22
 23#define PERIPHERAL_MAX		64
 24#define PERIPHERAL_ID_MIN	2
 25
 26#define GENERATED_SOURCE_MAX	6
 27#define GENERATED_MAX_DIV	255
 28
 29#define GCK_ID_SSC0		43
 30#define GCK_ID_SSC1		44
 31#define GCK_ID_I2S0		54
 32#define GCK_ID_I2S1		55
 33#define GCK_ID_CLASSD		59
 34#define GCK_INDEX_DT_AUDIO_PLL	5
 35
 36struct clk_generated {
 37	struct clk_hw hw;
 38	struct regmap *regmap;
 39	struct clk_range range;
 40	spinlock_t *lock;
 
 41	u32 id;
 42	u32 gckdiv;
 
 43	u8 parent_id;
 44	bool audio_pll_allowed;
 45};
 46
 47#define to_clk_generated(hw) \
 48	container_of(hw, struct clk_generated, hw)
 49
 50static int clk_generated_enable(struct clk_hw *hw)
 51{
 52	struct clk_generated *gck = to_clk_generated(hw);
 53	unsigned long flags;
 54
 55	pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
 56		 __func__, gck->gckdiv, gck->parent_id);
 57
 58	spin_lock_irqsave(gck->lock, flags);
 59	regmap_write(gck->regmap, AT91_PMC_PCR,
 60		     (gck->id & AT91_PMC_PCR_PID_MASK));
 61	regmap_update_bits(gck->regmap, AT91_PMC_PCR,
 62			   AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK |
 63			   AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
 64			   AT91_PMC_PCR_GCKCSS(gck->parent_id) |
 65			   AT91_PMC_PCR_CMD |
 66			   AT91_PMC_PCR_GCKDIV(gck->gckdiv) |
 67			   AT91_PMC_PCR_GCKEN);
 68	spin_unlock_irqrestore(gck->lock, flags);
 69	return 0;
 70}
 71
 72static void clk_generated_disable(struct clk_hw *hw)
 73{
 74	struct clk_generated *gck = to_clk_generated(hw);
 75	unsigned long flags;
 76
 77	spin_lock_irqsave(gck->lock, flags);
 78	regmap_write(gck->regmap, AT91_PMC_PCR,
 79		     (gck->id & AT91_PMC_PCR_PID_MASK));
 80	regmap_update_bits(gck->regmap, AT91_PMC_PCR,
 81			   AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
 82			   AT91_PMC_PCR_CMD);
 83	spin_unlock_irqrestore(gck->lock, flags);
 84}
 85
 86static int clk_generated_is_enabled(struct clk_hw *hw)
 87{
 88	struct clk_generated *gck = to_clk_generated(hw);
 89	unsigned long flags;
 90	unsigned int status;
 91
 92	spin_lock_irqsave(gck->lock, flags);
 93	regmap_write(gck->regmap, AT91_PMC_PCR,
 94		     (gck->id & AT91_PMC_PCR_PID_MASK));
 95	regmap_read(gck->regmap, AT91_PMC_PCR, &status);
 96	spin_unlock_irqrestore(gck->lock, flags);
 97
 98	return status & AT91_PMC_PCR_GCKEN ? 1 : 0;
 99}
100
101static unsigned long
102clk_generated_recalc_rate(struct clk_hw *hw,
103			  unsigned long parent_rate)
104{
105	struct clk_generated *gck = to_clk_generated(hw);
106
107	return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1);
108}
109
110static void clk_generated_best_diff(struct clk_rate_request *req,
111				    struct clk_hw *parent,
112				    unsigned long parent_rate, u32 div,
113				    int *best_diff, long *best_rate)
114{
115	unsigned long tmp_rate;
116	int tmp_diff;
117
118	if (!div)
119		tmp_rate = parent_rate;
120	else
121		tmp_rate = parent_rate / div;
122	tmp_diff = abs(req->rate - tmp_rate);
123
124	if (*best_diff < 0 || *best_diff > tmp_diff) {
125		*best_rate = tmp_rate;
126		*best_diff = tmp_diff;
127		req->best_parent_rate = parent_rate;
128		req->best_parent_hw = parent;
129	}
130}
131
132static int clk_generated_determine_rate(struct clk_hw *hw,
133					struct clk_rate_request *req)
134{
135	struct clk_generated *gck = to_clk_generated(hw);
136	struct clk_hw *parent = NULL;
137	struct clk_rate_request req_parent = *req;
138	long best_rate = -EINVAL;
139	unsigned long min_rate, parent_rate;
140	int best_diff = -1;
141	int i;
142	u32 div;
143
144	for (i = 0; i < clk_hw_get_num_parents(hw) - 1; i++) {
 
 
 
 
 
 
 
 
 
145		parent = clk_hw_get_parent_by_index(hw, i);
146		if (!parent)
147			continue;
148
149		parent_rate = clk_hw_get_rate(parent);
150		min_rate = DIV_ROUND_CLOSEST(parent_rate, GENERATED_MAX_DIV + 1);
151		if (!parent_rate ||
152		    (gck->range.max && min_rate > gck->range.max))
153			continue;
154
155		div = DIV_ROUND_CLOSEST(parent_rate, req->rate);
 
 
156
157		clk_generated_best_diff(req, parent, parent_rate, div,
158					&best_diff, &best_rate);
159
160		if (!best_diff)
161			break;
162	}
163
164	/*
165	 * The audio_pll rate can be modified, unlike the five others clocks
166	 * that should never be altered.
167	 * The audio_pll can technically be used by multiple consumers. However,
168	 * with the rate locking, the first consumer to enable to clock will be
169	 * the one definitely setting the rate of the clock.
170	 * Since audio IPs are most likely to request the same rate, we enforce
171	 * that the only clks able to modify gck rate are those of audio IPs.
172	 */
173
174	if (!gck->audio_pll_allowed)
175		goto end;
176
177	parent = clk_hw_get_parent_by_index(hw, GCK_INDEX_DT_AUDIO_PLL);
178	if (!parent)
179		goto end;
180
181	for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
182		req_parent.rate = req->rate * div;
183		__clk_determine_rate(parent, &req_parent);
 
184		clk_generated_best_diff(req, parent, req_parent.rate, div,
185					&best_diff, &best_rate);
186
187		if (!best_diff)
188			break;
189	}
190
191end:
192	pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
193		 __func__, best_rate,
194		 __clk_get_name((req->best_parent_hw)->clk),
195		 req->best_parent_rate);
196
197	if (best_rate < 0)
198		return best_rate;
199
200	req->rate = best_rate;
201	return 0;
202}
203
204/* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */
205static int clk_generated_set_parent(struct clk_hw *hw, u8 index)
206{
207	struct clk_generated *gck = to_clk_generated(hw);
208
209	if (index >= clk_hw_get_num_parents(hw))
210		return -EINVAL;
211
212	gck->parent_id = index;
 
 
 
 
213	return 0;
214}
215
216static u8 clk_generated_get_parent(struct clk_hw *hw)
217{
218	struct clk_generated *gck = to_clk_generated(hw);
219
220	return gck->parent_id;
221}
222
223/* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */
224static int clk_generated_set_rate(struct clk_hw *hw,
225				  unsigned long rate,
226				  unsigned long parent_rate)
227{
228	struct clk_generated *gck = to_clk_generated(hw);
229	u32 div;
230
231	if (!rate)
232		return -EINVAL;
233
234	if (gck->range.max && rate > gck->range.max)
235		return -EINVAL;
236
237	div = DIV_ROUND_CLOSEST(parent_rate, rate);
238	if (div > GENERATED_MAX_DIV + 1 || !div)
239		return -EINVAL;
240
241	gck->gckdiv = div - 1;
242	return 0;
243}
244
245static const struct clk_ops generated_ops = {
246	.enable = clk_generated_enable,
247	.disable = clk_generated_disable,
248	.is_enabled = clk_generated_is_enabled,
249	.recalc_rate = clk_generated_recalc_rate,
250	.determine_rate = clk_generated_determine_rate,
251	.get_parent = clk_generated_get_parent,
252	.set_parent = clk_generated_set_parent,
253	.set_rate = clk_generated_set_rate,
254};
255
256/**
257 * clk_generated_startup - Initialize a given clock to its default parent and
258 * divisor parameter.
259 *
260 * @gck:	Generated clock to set the startup parameters for.
261 *
262 * Take parameters from the hardware and update local clock configuration
263 * accordingly.
264 */
265static void clk_generated_startup(struct clk_generated *gck)
266{
267	u32 tmp;
268	unsigned long flags;
269
270	spin_lock_irqsave(gck->lock, flags);
271	regmap_write(gck->regmap, AT91_PMC_PCR,
272		     (gck->id & AT91_PMC_PCR_PID_MASK));
273	regmap_read(gck->regmap, AT91_PMC_PCR, &tmp);
274	spin_unlock_irqrestore(gck->lock, flags);
275
276	gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
277					>> AT91_PMC_PCR_GCKCSS_OFFSET;
278	gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK)
279					>> AT91_PMC_PCR_GCKDIV_OFFSET;
280}
281
282static struct clk_hw * __init
283at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
 
284			    const char *name, const char **parent_names,
285			    u8 num_parents, u8 id,
286			    const struct clk_range *range)
 
287{
288	struct clk_generated *gck;
289	struct clk_init_data init;
290	struct clk_hw *hw;
291	int ret;
292
293	gck = kzalloc(sizeof(*gck), GFP_KERNEL);
294	if (!gck)
295		return ERR_PTR(-ENOMEM);
296
297	init.name = name;
298	init.ops = &generated_ops;
299	init.parent_names = parent_names;
300	init.num_parents = num_parents;
301	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
302		CLK_SET_RATE_PARENT;
 
303
304	gck->id = id;
305	gck->hw.init = &init;
306	gck->regmap = regmap;
307	gck->lock = lock;
308	gck->range = *range;
 
 
 
309
310	clk_generated_startup(gck);
311	hw = &gck->hw;
312	ret = clk_hw_register(NULL, &gck->hw);
313	if (ret) {
314		kfree(gck);
315		hw = ERR_PTR(ret);
316	} else {
317		pmc_register_id(id);
318	}
319
320	return hw;
321}
322
323static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
324{
325	int num;
326	u32 id;
327	const char *name;
328	struct clk_hw *hw;
329	unsigned int num_parents;
330	const char *parent_names[GENERATED_SOURCE_MAX];
331	struct device_node *gcknp;
332	struct clk_range range = CLK_RANGE(0, 0);
333	struct regmap *regmap;
334	struct clk_generated *gck;
335
336	num_parents = of_clk_get_parent_count(np);
337	if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
338		return;
339
340	of_clk_parent_fill(np, parent_names, num_parents);
341
342	num = of_get_child_count(np);
343	if (!num || num > PERIPHERAL_MAX)
344		return;
345
346	regmap = syscon_node_to_regmap(of_get_parent(np));
347	if (IS_ERR(regmap))
348		return;
349
350	for_each_child_of_node(np, gcknp) {
351		if (of_property_read_u32(gcknp, "reg", &id))
352			continue;
353
354		if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
355			continue;
356
357		if (of_property_read_string(np, "clock-output-names", &name))
358			name = gcknp->name;
359
360		of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
361				      &range);
362
363		hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
364						  parent_names, num_parents,
365						  id, &range);
366
367		gck = to_clk_generated(hw);
368
369		if (of_device_is_compatible(np,
370					    "atmel,sama5d2-clk-generated")) {
371			if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 ||
372			    gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 ||
373			    gck->id == GCK_ID_CLASSD)
374				gck->audio_pll_allowed = true;
375			else
376				gck->audio_pll_allowed = false;
377		} else {
378			gck->audio_pll_allowed = false;
379		}
380
381		if (IS_ERR(hw))
382			continue;
383
384		of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
385	}
386}
387CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
388	       of_sama5d2_clk_generated_setup);