Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <claudiu.beznea@microchip.com>
Link: https://lore.kernel.org/r/1595403506-8209-18-git-send-email-claudiu.beznea@microchip.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Claudiu Beznea and committed by
Stephen Boyd
ef396df9 43b1bb4a

+104 -5
+98 -5
drivers/clk/at91/clk-utmi.c
··· 120 120 .recalc_rate = clk_utmi_recalc_rate, 121 121 }; 122 122 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) 126 128 { 127 129 struct clk_utmi *utmi; 128 130 struct clk_hw *hw; ··· 136 134 return ERR_PTR(-ENOMEM); 137 135 138 136 init.name = name; 139 - init.ops = &utmi_ops; 137 + init.ops = ops; 140 138 init.parent_names = parent_name ? &parent_name : NULL; 141 139 init.num_parents = parent_name ? 1 : 0; 142 - init.flags = CLK_SET_RATE_GATE; 140 + init.flags = flags; 143 141 144 142 utmi->hw.init = &init; 145 143 utmi->regmap_pmc = regmap_pmc; ··· 153 151 } 154 152 155 153 return hw; 154 + } 155 + 156 + struct clk_hw * __init 157 + at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, 158 + const char *name, const char *parent_name) 159 + { 160 + return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name, 161 + parent_name, &utmi_ops, CLK_SET_RATE_GATE); 162 + } 163 + 164 + static int clk_utmi_sama7g5_prepare(struct clk_hw *hw) 165 + { 166 + struct clk_utmi *utmi = to_clk_utmi(hw); 167 + struct clk_hw *hw_parent; 168 + unsigned long parent_rate; 169 + unsigned int val; 170 + 171 + hw_parent = clk_hw_get_parent(hw); 172 + parent_rate = clk_hw_get_rate(hw_parent); 173 + 174 + switch (parent_rate) { 175 + case 16000000: 176 + val = 0; 177 + break; 178 + case 20000000: 179 + val = 2; 180 + break; 181 + case 24000000: 182 + val = 3; 183 + break; 184 + case 32000000: 185 + val = 5; 186 + break; 187 + default: 188 + pr_err("UTMICK: unsupported main_xtal rate\n"); 189 + return -EINVAL; 190 + } 191 + 192 + regmap_write(utmi->regmap_pmc, AT91_PMC_XTALF, val); 193 + 194 + return 0; 195 + 196 + } 197 + 198 + static int clk_utmi_sama7g5_is_prepared(struct clk_hw *hw) 199 + { 200 + struct clk_utmi *utmi = to_clk_utmi(hw); 201 + struct clk_hw *hw_parent; 202 + unsigned long parent_rate; 203 + unsigned int val; 204 + 205 + hw_parent = clk_hw_get_parent(hw); 206 + parent_rate = clk_hw_get_rate(hw_parent); 207 + 208 + regmap_read(utmi->regmap_pmc, AT91_PMC_XTALF, &val); 209 + switch (val & 0x7) { 210 + case 0: 211 + if (parent_rate == 16000000) 212 + return 1; 213 + break; 214 + case 2: 215 + if (parent_rate == 20000000) 216 + return 1; 217 + break; 218 + case 3: 219 + if (parent_rate == 24000000) 220 + return 1; 221 + break; 222 + case 5: 223 + if (parent_rate == 32000000) 224 + return 1; 225 + break; 226 + default: 227 + break; 228 + } 229 + 230 + return 0; 231 + } 232 + 233 + static const struct clk_ops sama7g5_utmi_ops = { 234 + .prepare = clk_utmi_sama7g5_prepare, 235 + .is_prepared = clk_utmi_sama7g5_is_prepared, 236 + .recalc_rate = clk_utmi_recalc_rate, 237 + }; 238 + 239 + struct clk_hw * __init 240 + at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name, 241 + const char *parent_name) 242 + { 243 + return at91_clk_register_utmi_internal(regmap_pmc, NULL, name, 244 + parent_name, &sama7g5_utmi_ops, 0); 156 245 }
+4
drivers/clk/at91/pmc.h
··· 236 236 at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, 237 237 const char *name, const char *parent_name); 238 238 239 + struct clk_hw * __init 240 + at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name, 241 + const char *parent_name); 242 + 239 243 #ifdef CONFIG_PM 240 244 void pmc_register_id(u8 id); 241 245 void pmc_register_pck(u8 pck);
+2
include/linux/clk/at91_pmc.h
··· 137 137 #define AT91_PMC_PLLADIV2_ON (1 << 12) 138 138 #define AT91_PMC_H32MXDIV BIT(24) 139 139 140 + #define AT91_PMC_XTALF 0x34 /* Main XTAL Frequency Register [SAMA7G5 only] */ 141 + 140 142 #define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */ 141 143 #define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */ 142 144 #define AT91_PMC_USBS_PLLA (0 << 0)