1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Driver for Silicon Labs Si544 Programmable Oscillator 4 * Copyright (C) 2018 Topic Embedded Products 5 * Author: Mike Looijmans <mike.looijmans@topic.nl> 6 */ 7 8 #include <linux/clk-provider.h> 9 #include <linux/delay.h> 10 #include <linux/module.h> 11 #include <linux/i2c.h> 12 #include <linux/regmap.h> 13 #include <linux/slab.h> 14 15 /* I2C registers (decimal as in datasheet) */ 16 #define SI544_REG_CONTROL 7 17 #define SI544_REG_OE_STATE 17 18 #define SI544_REG_HS_DIV 23 19 #define SI544_REG_LS_HS_DIV 24 20 #define SI544_REG_FBDIV0 26 21 #define SI544_REG_FBDIV8 27 22 #define SI544_REG_FBDIV16 28 23 #define SI544_REG_FBDIV24 29 24 #define SI544_REG_FBDIV32 30 25 #define SI544_REG_FBDIV40 31 26 #define SI544_REG_FCAL_OVR 69 27 #define SI544_REG_ADPLL_DELTA_M0 231 28 #define SI544_REG_ADPLL_DELTA_M8 232 29 #define SI544_REG_ADPLL_DELTA_M16 233 30 #define SI544_REG_PAGE_SELECT 255 31 32 /* Register values */ 33 #define SI544_CONTROL_RESET BIT(7) 34 #define SI544_CONTROL_MS_ICAL2 BIT(3) 35 36 #define SI544_OE_STATE_ODC_OE BIT(0) 37 38 /* Max freq depends on speed grade */ 39 #define SI544_MIN_FREQ 200000U 40 41 /* Si544 Internal oscilator runs at 55.05 MHz */ 42 #define FXO 55050000U 43 44 /* VCO range is 10.8 .. 12.1 GHz, max depends on speed grade */ 45 #define FVCO_MIN 10800000000ULL 46 47 #define HS_DIV_MAX 2046 48 #define HS_DIV_MAX_ODD 33 49 50 /* Lowest frequency synthesizeable using only the HS divider */ 51 #define MIN_HSDIV_FREQ (FVCO_MIN / HS_DIV_MAX) 52 53 enum si544_speed_grade { 54 si544a, 55 si544b, 56 si544c, 57 }; 58 59 struct clk_si544 { 60 struct clk_hw hw; 61 struct regmap *regmap; 62 struct i2c_client *i2c_client; 63 enum si544_speed_grade speed_grade; 64 }; 65 #define to_clk_si544(_hw) container_of(_hw, struct clk_si544, hw) 66 67 /** 68 * struct clk_si544_muldiv - Multiplier/divider settings 69 * @fb_div_frac: integer part of feedback divider (32 bits) 70 * @fb_div_int: fractional part of feedback divider (11 bits) 71 * @hs_div: 1st divider, 5..2046, must be even when >33 72 * @ls_div_bits: 2nd divider, as 2^x, range 0..5 73 * If ls_div_bits is non-zero, hs_div must be even 74 */ 75 struct clk_si544_muldiv { 76 u32 fb_div_frac; 77 u16 fb_div_int; 78 u16 hs_div; 79 u8 ls_div_bits; 80 }; 81 82 /* Enables or disables the output driver */ 83 static int si544_enable_output(struct clk_si544 *data, bool enable) 84 { 85 return regmap_update_bits(data->regmap, SI544_REG_OE_STATE, 86 SI544_OE_STATE_ODC_OE, enable ? SI544_OE_STATE_ODC_OE : 0); 87 } 88 89 /* Retrieve clock multiplier and dividers from hardware */ 90 static int si544_get_muldiv(struct clk_si544 *data, 91 struct clk_si544_muldiv *settings) 92 { 93 int err; 94 u8 reg[6]; 95 96 err = regmap_bulk_read(data->regmap, SI544_REG_HS_DIV, reg, 2); 97 if (err) 98 return err; 99 100 settings->ls_div_bits = (reg[1] >> 4) & 0x07; 101 settings->hs_div = (reg[1] & 0x07) << 8 | reg[0]; 102 103 err = regmap_bulk_read(data->regmap, SI544_REG_FBDIV0, reg, 6); 104 if (err) 105 return err; 106 107 settings->fb_div_int = reg[4] | (reg[5] & 0x07) << 8; 108 settings->fb_div_frac = reg[0] | reg[1] << 8 | reg[2] << 16 | 109 reg[3] << 24; 110 return 0; 111 } 112 113 static int si544_set_muldiv(struct clk_si544 *data, 114 struct clk_si544_muldiv *settings) 115 { 116 int err; 117 u8 reg[6]; 118 119 reg[0] = settings->hs_div; 120 reg[1] = settings->hs_div >> 8 | settings->ls_div_bits << 4; 121 122 err = regmap_bulk_write(data->regmap, SI544_REG_HS_DIV, reg, 2); 123 if (err < 0) 124 return err; 125 126 reg[0] = settings->fb_div_frac; 127 reg[1] = settings->fb_div_frac >> 8; 128 reg[2] = settings->fb_div_frac >> 16; 129 reg[3] = settings->fb_div_frac >> 24; 130 reg[4] = settings->fb_div_int; 131 reg[5] = settings->fb_div_int >> 8; 132 133 /* 134 * Writing to SI544_REG_FBDIV40 triggers the clock change, so that 135 * must be written last 136 */ 137 return regmap_bulk_write(data->regmap, SI544_REG_FBDIV0, reg, 6); 138 } 139 140 static bool is_valid_frequency(const struct clk_si544 *data, 141 unsigned long frequency) 142 { 143 unsigned long max_freq = 0; 144 145 if (frequency < SI544_MIN_FREQ) 146 return false; 147 148 switch (data->speed_grade) { 149 case si544a: 150 max_freq = 1500000000; 151 break; 152 case si544b: 153 max_freq = 800000000; 154 break; 155 case si544c: 156 max_freq = 350000000; 157 break; 158 } 159 160 return frequency <= max_freq; 161 } 162 163 /* Calculate divider settings for a given frequency */ 164 static int si544_calc_muldiv(struct clk_si544_muldiv *settings, 165 unsigned long frequency) 166 { 167 u64 vco; 168 u32 ls_freq; 169 u32 tmp; 170 u8 res; 171 172 /* Determine the minimum value of LS_DIV and resulting target freq. */ 173 ls_freq = frequency; 174 settings->ls_div_bits = 0; 175 176 if (frequency >= MIN_HSDIV_FREQ) { 177 settings->ls_div_bits = 0; 178 } else { 179 res = 1; 180 tmp = 2 * HS_DIV_MAX; 181 while (tmp <= (HS_DIV_MAX * 32)) { 182 if (((u64)frequency * tmp) >= FVCO_MIN) 183 break; 184 ++res; 185 tmp <<= 1; 186 } 187 settings->ls_div_bits = res; 188 ls_freq = frequency << res; 189 } 190 191 /* Determine minimum HS_DIV by rounding up */ 192 vco = FVCO_MIN + ls_freq - 1; 193 do_div(vco, ls_freq); 194 settings->hs_div = vco; 195 196 /* round up to even number when required */ 197 if ((settings->hs_div & 1) && 198 (settings->hs_div > HS_DIV_MAX_ODD || settings->ls_div_bits)) 199 ++settings->hs_div; 200 201 /* Calculate VCO frequency (in 10..12GHz range) */ 202 vco = (u64)ls_freq * settings->hs_div; 203 204 /* Calculate the integer part of the feedback divider */ 205 tmp = do_div(vco, FXO); 206 settings->fb_div_int = vco; 207 208 /* And the fractional bits using the remainder */ 209 vco = (u64)tmp << 32; 210 do_div(vco, FXO); 211 settings->fb_div_frac = vco; 212 213 return 0; 214 } 215 216 /* Calculate resulting frequency given the register settings */ 217 static unsigned long si544_calc_rate(struct clk_si544_muldiv *settings) 218 { 219 u32 d = settings->hs_div * BIT(settings->ls_div_bits); 220 u64 vco; 221 222 /* Calculate VCO from the fractional part */ 223 vco = (u64)settings->fb_div_frac * FXO; 224 vco += (FXO / 2); 225 vco >>= 32; 226 227 /* Add the integer part of the VCO frequency */ 228 vco += (u64)settings->fb_div_int * FXO; 229 230 /* Apply divider to obtain the generated frequency */ 231 do_div(vco, d); 232 233 return vco; 234 } 235 236 static unsigned long si544_recalc_rate(struct clk_hw *hw, 237 unsigned long parent_rate) 238 { 239 struct clk_si544 *data = to_clk_si544(hw); 240 struct clk_si544_muldiv settings; 241 int err; 242 243 err = si544_get_muldiv(data, &settings); 244 if (err) 245 return 0; 246 247 return si544_calc_rate(&settings); 248 } 249 250 static long si544_round_rate(struct clk_hw *hw, unsigned long rate, 251 unsigned long *parent_rate) 252 { 253 struct clk_si544 *data = to_clk_si544(hw); 254 struct clk_si544_muldiv settings; 255 int err; 256 257 if (!is_valid_frequency(data, rate)) 258 return -EINVAL; 259 260 err = si544_calc_muldiv(&settings, rate); 261 if (err) 262 return err; 263 264 return si544_calc_rate(&settings); 265 } 266 267 /* 268 * Update output frequency for "big" frequency changes 269 */ 270 static int si544_set_rate(struct clk_hw *hw, unsigned long rate, 271 unsigned long parent_rate) 272 { 273 struct clk_si544 *data = to_clk_si544(hw); 274 struct clk_si544_muldiv settings; 275 int err; 276 277 if (!is_valid_frequency(data, rate)) 278 return -EINVAL; 279 280 err = si544_calc_muldiv(&settings, rate); 281 if (err) 282 return err; 283 284 si544_enable_output(data, false); 285 286 /* Allow FCAL for this frequency update */ 287 err = regmap_write(data->regmap, SI544_REG_FCAL_OVR, 0); 288 if (err < 0) 289 return err; 290 291 292 err = si544_set_muldiv(data, &settings); 293 if (err < 0) 294 return err; /* Undefined state now, best to leave disabled */ 295 296 /* Trigger calibration */ 297 err = regmap_write(data->regmap, SI544_REG_CONTROL, 298 SI544_CONTROL_MS_ICAL2); 299 if (err < 0) 300 return err; 301 302 /* Applying a new frequency can take up to 10ms */ 303 usleep_range(10000, 12000); 304 305 si544_enable_output(data, true); 306 307 return err; 308 } 309 310 static const struct clk_ops si544_clk_ops = { 311 .recalc_rate = si544_recalc_rate, 312 .round_rate = si544_round_rate, 313 .set_rate = si544_set_rate, 314 }; 315 316 static bool si544_regmap_is_volatile(struct device *dev, unsigned int reg) 317 { 318 switch (reg) { 319 case SI544_REG_CONTROL: 320 case SI544_REG_FCAL_OVR: 321 return true; 322 default: 323 return false; 324 } 325 } 326 327 static const struct regmap_config si544_regmap_config = { 328 .reg_bits = 8, 329 .val_bits = 8, 330 .cache_type = REGCACHE_RBTREE, 331 .max_register = SI544_REG_PAGE_SELECT, 332 .volatile_reg = si544_regmap_is_volatile, 333 }; 334 335 static int si544_probe(struct i2c_client *client, 336 const struct i2c_device_id *id) 337 { 338 struct clk_si544 *data; 339 struct clk_init_data init; 340 int err; 341 342 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 343 if (!data) 344 return -ENOMEM; 345 346 init.ops = &si544_clk_ops; 347 init.flags = 0; 348 init.num_parents = 0; 349 data->hw.init = &init; 350 data->i2c_client = client; 351 data->speed_grade = id->driver_data; 352 353 if (of_property_read_string(client->dev.of_node, "clock-output-names", 354 &init.name)) 355 init.name = client->dev.of_node->name; 356 357 data->regmap = devm_regmap_init_i2c(client, &si544_regmap_config); 358 if (IS_ERR(data->regmap)) 359 return PTR_ERR(data->regmap); 360 361 i2c_set_clientdata(client, data); 362 363 /* Select page 0, just to be sure, there appear to be no more */ 364 err = regmap_write(data->regmap, SI544_REG_PAGE_SELECT, 0); 365 if (err < 0) 366 return err; 367 368 err = devm_clk_hw_register(&client->dev, &data->hw); 369 if (err) { 370 dev_err(&client->dev, "clock registration failed\n"); 371 return err; 372 } 373 err = devm_of_clk_add_hw_provider(&client->dev, of_clk_hw_simple_get, 374 &data->hw); 375 if (err) { 376 dev_err(&client->dev, "unable to add clk provider\n"); 377 return err; 378 } 379 380 return 0; 381 } 382 383 static const struct i2c_device_id si544_id[] = { 384 { "si544a", si544a }, 385 { "si544b", si544b }, 386 { "si544c", si544c }, 387 { } 388 }; 389 MODULE_DEVICE_TABLE(i2c, si544_id); 390 391 static const struct of_device_id clk_si544_of_match[] = { 392 { .compatible = "silabs,si544a" }, 393 { .compatible = "silabs,si544b" }, 394 { .compatible = "silabs,si544c" }, 395 { }, 396 }; 397 MODULE_DEVICE_TABLE(of, clk_si544_of_match); 398 399 static struct i2c_driver si544_driver = { 400 .driver = { 401 .name = "si544", 402 .of_match_table = clk_si544_of_match, 403 }, 404 .probe = si544_probe, 405 .id_table = si544_id, 406 }; 407 module_i2c_driver(si544_driver); 408 409 MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>"); 410 MODULE_DESCRIPTION("Si544 driver"); 411 MODULE_LICENSE("GPL"); 412