Skip to content

Commit ef396df

Browse files
claudiubezneabebarino
authored andcommitted
clk: at91: clk-utmi: add utmi support for sama7g5
Add UTMI support for SAMA7G5. SAMA7G5's UTMI control is done via XTALF register. Values written at bits 2..0 in this register correspond to the on board crystal oscillator frequency. Signed-off-by: Claudiu Beznea <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent 43b1bb4 commit ef396df

File tree

3 files changed

+104
-5
lines changed

3 files changed

+104
-5
lines changed

drivers/clk/at91/clk-utmi.c

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,11 @@ static const struct clk_ops utmi_ops = {
120120
.recalc_rate = clk_utmi_recalc_rate,
121121
};
122122

123-
struct clk_hw * __init
124-
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
125-
const char *name, const char *parent_name)
123+
static struct clk_hw * __init
124+
at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
125+
struct regmap *regmap_sfr,
126+
const char *name, const char *parent_name,
127+
const struct clk_ops *ops, unsigned long flags)
126128
{
127129
struct clk_utmi *utmi;
128130
struct clk_hw *hw;
@@ -134,10 +136,10 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
134136
return ERR_PTR(-ENOMEM);
135137

136138
init.name = name;
137-
init.ops = &utmi_ops;
139+
init.ops = ops;
138140
init.parent_names = parent_name ? &parent_name : NULL;
139141
init.num_parents = parent_name ? 1 : 0;
140-
init.flags = CLK_SET_RATE_GATE;
142+
init.flags = flags;
141143

142144
utmi->hw.init = &init;
143145
utmi->regmap_pmc = regmap_pmc;
@@ -152,3 +154,94 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
152154

153155
return hw;
154156
}
157+
158+
struct clk_hw * __init
159+
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
160+
const char *name, const char *parent_name)
161+
{
162+
return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name,
163+
parent_name, &utmi_ops, CLK_SET_RATE_GATE);
164+
}
165+
166+
static int clk_utmi_sama7g5_prepare(struct clk_hw *hw)
167+
{
168+
struct clk_utmi *utmi = to_clk_utmi(hw);
169+
struct clk_hw *hw_parent;
170+
unsigned long parent_rate;
171+
unsigned int val;
172+
173+
hw_parent = clk_hw_get_parent(hw);
174+
parent_rate = clk_hw_get_rate(hw_parent);
175+
176+
switch (parent_rate) {
177+
case 16000000:
178+
val = 0;
179+
break;
180+
case 20000000:
181+
val = 2;
182+
break;
183+
case 24000000:
184+
val = 3;
185+
break;
186+
case 32000000:
187+
val = 5;
188+
break;
189+
default:
190+
pr_err("UTMICK: unsupported main_xtal rate\n");
191+
return -EINVAL;
192+
}
193+
194+
regmap_write(utmi->regmap_pmc, AT91_PMC_XTALF, val);
195+
196+
return 0;
197+
198+
}
199+
200+
static int clk_utmi_sama7g5_is_prepared(struct clk_hw *hw)
201+
{
202+
struct clk_utmi *utmi = to_clk_utmi(hw);
203+
struct clk_hw *hw_parent;
204+
unsigned long parent_rate;
205+
unsigned int val;
206+
207+
hw_parent = clk_hw_get_parent(hw);
208+
parent_rate = clk_hw_get_rate(hw_parent);
209+
210+
regmap_read(utmi->regmap_pmc, AT91_PMC_XTALF, &val);
211+
switch (val & 0x7) {
212+
case 0:
213+
if (parent_rate == 16000000)
214+
return 1;
215+
break;
216+
case 2:
217+
if (parent_rate == 20000000)
218+
return 1;
219+
break;
220+
case 3:
221+
if (parent_rate == 24000000)
222+
return 1;
223+
break;
224+
case 5:
225+
if (parent_rate == 32000000)
226+
return 1;
227+
break;
228+
default:
229+
break;
230+
}
231+
232+
return 0;
233+
}
234+
235+
static const struct clk_ops sama7g5_utmi_ops = {
236+
.prepare = clk_utmi_sama7g5_prepare,
237+
.is_prepared = clk_utmi_sama7g5_is_prepared,
238+
.recalc_rate = clk_utmi_recalc_rate,
239+
};
240+
241+
struct clk_hw * __init
242+
at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name,
243+
const char *parent_name)
244+
{
245+
return at91_clk_register_utmi_internal(regmap_pmc, NULL, name,
246+
parent_name, &sama7g5_utmi_ops, 0);
247+
}

drivers/clk/at91/pmc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ struct clk_hw * __init
236236
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
237237
const char *name, const char *parent_name);
238238

239+
struct clk_hw * __init
240+
at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name,
241+
const char *parent_name);
242+
239243
#ifdef CONFIG_PM
240244
void pmc_register_id(u8 id);
241245
void pmc_register_pck(u8 pck);

include/linux/clk/at91_pmc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@
137137
#define AT91_PMC_PLLADIV2_ON (1 << 12)
138138
#define AT91_PMC_H32MXDIV BIT(24)
139139

140+
#define AT91_PMC_XTALF 0x34 /* Main XTAL Frequency Register [SAMA7G5 only] */
141+
140142
#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */
141143
#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */
142144
#define AT91_PMC_USBS_PLLA (0 << 0)

0 commit comments

Comments
 (0)