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 vco += FXO / 2; /* Round to nearest multiple */ 211 do_div(vco, FXO); 212 settings->fb_div_frac = vco; 213 214 return 0; 215 } 216 217 /* Calculate resulting frequency given the register settings */ 218 static unsigned long si544_calc_rate(struct clk_si544_muldiv *settings) 219 { 220 u32 d = settings->hs_div * BIT(settings->ls_div_bits); 221 u64 vco; 222 223 /* Calculate VCO from the fractional part */ 224 vco = (u64)settings->fb_div_frac * FXO; 225 vco += (FXO / 2); 226 vco >>= 32; 227 228 /* Add the integer part of the VCO frequency */ 229 vco += (u64)settings->fb_div_int * FXO; 230 231 /* Apply divider to obtain the generated frequency */ 232 do_div(vco, d); 233 234 return vco; 235 } 236 237 static unsigned long si544_recalc_rate(struct clk_hw *hw, 238 unsigned long parent_rate) 239 { 240 struct clk_si544 *data = to_clk_si544(hw); 241 struct clk_si544_muldiv settings; 242 int err; 243 244 err = si544_get_muldiv(data, &settings); 245 if (err) 246 return 0; 247 248 return si544_calc_rate(&settings); 249 } 250 251 static long si544_round_rate(struct clk_hw *hw, unsigned long rate, 252 unsigned long *parent_rate) 253 { 254 struct clk_si544 *data = to_clk_si544(hw); 255 struct clk_si544_muldiv settings; 256 int err; 257 258 if (!is_valid_frequency(data, rate)) 259 return -EINVAL; 260 261 err = si544_calc_muldiv(&settings, rate); 262 if (err) 263 return err; 264 265 return si544_calc_rate(&settings); 266 } 267 268 /* 269 * Update output frequency for "big" frequency changes 270 */ 271 static int si544_set_rate(struct clk_hw *hw, unsigned long rate, 272 unsigned long parent_rate) 273 { 274 struct clk_si544 *data = to_clk_si544(hw); 275 struct clk_si544_muldiv settings; 276 int err; 277 278 if (!is_valid_frequency(data, rate)) 279 return -EINVAL; 280 281 err = si544_calc_muldiv(&settings, rate); 282 if (err) 283 return err; 284 285 si544_enable_output(data, false); 286 287 /* Allow FCAL for this frequency update */ 288 err = regmap_write(data->regmap, SI544_REG_FCAL_OVR, 0); 289 if (err < 0) 290 return err; 291 292 293 err = si544_set_muldiv(data, &settings); 294 if (err < 0) 295 return err; /* Undefined state now, best to leave disabled */ 296 297 /* Trigger calibration */ 298 err = regmap_write(data->regmap, SI544_REG_CONTROL, 299 SI544_CONTROL_MS_ICAL2); 300 if (err < 0) 301 return err; 302 303 /* Applying a new frequency can take up to 10ms */ 304 usleep_range(10000, 12000); 305 306 si544_enable_output(data, true); 307 308 return err; 309 } 310 311 static const struct clk_ops si544_clk_ops = { 312 .recalc_rate = si544_recalc_rate, 313 .round_rate = si544_round_rate, 314 .set_rate = si544_set_rate, 315 }; 316 317 static bool si544_regmap_is_volatile(struct device *dev, unsigned int reg) 318 { 319 switch (reg) { 320 case SI544_REG_CONTROL: 321 case SI544_REG_FCAL_OVR: 322 return true; 323 default: 324 return false; 325 } 326 } 327 328 static const struct regmap_config si544_regmap_config = { 329 .reg_bits = 8, 330 .val_bits = 8, 331 .cache_type = REGCACHE_RBTREE, 332 .max_register = SI544_REG_PAGE_SELECT, 333 .volatile_reg = si544_regmap_is_volatile, 334 }; 335 336 static int si544_probe(struct i2c_client *client, 337 const struct i2c_device_id *id) 338 { 339 struct clk_si544 *data; 340 struct clk_init_data init; 341 int err; 342 343 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 344 if (!data) 345 return -ENOMEM; 346 347 init.ops = &si544_clk_ops; 348 init.flags = 0; 349 init.num_parents = 0; 350 data->hw.init = &init; 351 data->i2c_client = client; 352 data->speed_grade = id->driver_data; 353 354 if (of_property_read_string(client->dev.of_node, "clock-output-names", 355 &init.name)) 356 init.name = client->dev.of_node->name; 357 358 data->regmap = devm_regmap_init_i2c(client, &si544_regmap_config); 359 if (IS_ERR(data->regmap)) 360 return PTR_ERR(data->regmap); 361 362 i2c_set_clientdata(client, data); 363 364 /* Select page 0, just to be sure, there appear to be no more */ 365 err = regmap_write(data->regmap, SI544_REG_PAGE_SELECT, 0); 366 if (err < 0) 367 return err; 368 369 err = devm_clk_hw_register(&client->dev, &data->hw); 370 if (err) { 371 dev_err(&client->dev, "clock registration failed\n"); 372 return err; 373 } 374 err = devm_of_clk_add_hw_provider(&client->dev, of_clk_hw_simple_get, 375 &data->hw); 376 if (err) { 377 dev_err(&client->dev, "unable to add clk provider\n"); 378 return err; 379 } 380 381 return 0; 382 } 383 384 static const struct i2c_device_id si544_id[] = { 385 { "si544a", si544a }, 386 { "si544b", si544b }, 387 { "si544c", si544c }, 388 { } 389 }; 390 MODULE_DEVICE_TABLE(i2c, si544_id); 391 392 static const struct of_device_id clk_si544_of_match[] = { 393 { .compatible = "silabs,si544a" }, 394 { .compatible = "silabs,si544b" }, 395 { .compatible = "silabs,si544c" }, 396 { }, 397 }; 398 MODULE_DEVICE_TABLE(of, clk_si544_of_match); 399 400 static struct i2c_driver si544_driver = { 401 .driver = { 402 .name = "si544", 403 .of_match_table = clk_si544_of_match, 404 }, 405 .probe = si544_probe, 406 .id_table = si544_id, 407 }; 408 module_i2c_driver(si544_driver); 409 410 MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>"); 411 MODULE_DESCRIPTION("Si544 driver"); 412 MODULE_LICENSE("GPL"); 413