0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk-provider.h>
0009 #include <linux/delay.h>
0010 #include <linux/math64.h>
0011 #include <linux/module.h>
0012 #include <linux/i2c.h>
0013 #include <linux/regmap.h>
0014 #include <linux/slab.h>
0015
0016
0017 #define SI544_REG_CONTROL 7
0018 #define SI544_REG_OE_STATE 17
0019 #define SI544_REG_HS_DIV 23
0020 #define SI544_REG_LS_HS_DIV 24
0021 #define SI544_REG_FBDIV0 26
0022 #define SI544_REG_FBDIV8 27
0023 #define SI544_REG_FBDIV16 28
0024 #define SI544_REG_FBDIV24 29
0025 #define SI544_REG_FBDIV32 30
0026 #define SI544_REG_FBDIV40 31
0027 #define SI544_REG_FCAL_OVR 69
0028 #define SI544_REG_ADPLL_DELTA_M0 231
0029 #define SI544_REG_ADPLL_DELTA_M8 232
0030 #define SI544_REG_ADPLL_DELTA_M16 233
0031 #define SI544_REG_PAGE_SELECT 255
0032
0033
0034 #define SI544_CONTROL_RESET BIT(7)
0035 #define SI544_CONTROL_MS_ICAL2 BIT(3)
0036
0037 #define SI544_OE_STATE_ODC_OE BIT(0)
0038
0039
0040 #define SI544_MIN_FREQ 200000U
0041
0042
0043 #define FXO 55050000U
0044
0045
0046 #define FVCO_MIN 10800000000ULL
0047
0048 #define HS_DIV_MAX 2046
0049 #define HS_DIV_MAX_ODD 33
0050
0051
0052 #define MIN_HSDIV_FREQ (FVCO_MIN / HS_DIV_MAX)
0053
0054
0055 #define DELTA_M_MAX 8161512
0056 #define DELTA_M_FRAC_NUM 19
0057 #define DELTA_M_FRAC_DEN 20000
0058
0059 enum si544_speed_grade {
0060 si544a,
0061 si544b,
0062 si544c,
0063 };
0064
0065 struct clk_si544 {
0066 struct clk_hw hw;
0067 struct regmap *regmap;
0068 struct i2c_client *i2c_client;
0069 enum si544_speed_grade speed_grade;
0070 };
0071 #define to_clk_si544(_hw) container_of(_hw, struct clk_si544, hw)
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 struct clk_si544_muldiv {
0083 u32 fb_div_frac;
0084 u16 fb_div_int;
0085 u16 hs_div;
0086 u8 ls_div_bits;
0087 s32 delta_m;
0088 };
0089
0090
0091 static int si544_enable_output(struct clk_si544 *data, bool enable)
0092 {
0093 return regmap_update_bits(data->regmap, SI544_REG_OE_STATE,
0094 SI544_OE_STATE_ODC_OE, enable ? SI544_OE_STATE_ODC_OE : 0);
0095 }
0096
0097 static int si544_prepare(struct clk_hw *hw)
0098 {
0099 struct clk_si544 *data = to_clk_si544(hw);
0100
0101 return si544_enable_output(data, true);
0102 }
0103
0104 static void si544_unprepare(struct clk_hw *hw)
0105 {
0106 struct clk_si544 *data = to_clk_si544(hw);
0107
0108 si544_enable_output(data, false);
0109 }
0110
0111 static int si544_is_prepared(struct clk_hw *hw)
0112 {
0113 struct clk_si544 *data = to_clk_si544(hw);
0114 unsigned int val;
0115 int err;
0116
0117 err = regmap_read(data->regmap, SI544_REG_OE_STATE, &val);
0118 if (err < 0)
0119 return err;
0120
0121 return !!(val & SI544_OE_STATE_ODC_OE);
0122 }
0123
0124
0125 static int si544_get_muldiv(struct clk_si544 *data,
0126 struct clk_si544_muldiv *settings)
0127 {
0128 int err;
0129 u8 reg[6];
0130
0131 err = regmap_bulk_read(data->regmap, SI544_REG_HS_DIV, reg, 2);
0132 if (err)
0133 return err;
0134
0135 settings->ls_div_bits = (reg[1] >> 4) & 0x07;
0136 settings->hs_div = (reg[1] & 0x07) << 8 | reg[0];
0137
0138 err = regmap_bulk_read(data->regmap, SI544_REG_FBDIV0, reg, 6);
0139 if (err)
0140 return err;
0141
0142 settings->fb_div_int = reg[4] | (reg[5] & 0x07) << 8;
0143 settings->fb_div_frac = reg[0] | reg[1] << 8 | reg[2] << 16 |
0144 reg[3] << 24;
0145
0146 err = regmap_bulk_read(data->regmap, SI544_REG_ADPLL_DELTA_M0, reg, 3);
0147 if (err)
0148 return err;
0149
0150
0151 settings->delta_m = reg[0] << 8 | reg[1] << 16 | reg[2] << 24;
0152 settings->delta_m >>= 8;
0153
0154 return 0;
0155 }
0156
0157 static int si544_set_delta_m(struct clk_si544 *data, s32 delta_m)
0158 {
0159 u8 reg[3];
0160
0161 reg[0] = delta_m;
0162 reg[1] = delta_m >> 8;
0163 reg[2] = delta_m >> 16;
0164
0165 return regmap_bulk_write(data->regmap, SI544_REG_ADPLL_DELTA_M0,
0166 reg, 3);
0167 }
0168
0169 static int si544_set_muldiv(struct clk_si544 *data,
0170 struct clk_si544_muldiv *settings)
0171 {
0172 int err;
0173 u8 reg[6];
0174
0175 reg[0] = settings->hs_div;
0176 reg[1] = settings->hs_div >> 8 | settings->ls_div_bits << 4;
0177
0178 err = regmap_bulk_write(data->regmap, SI544_REG_HS_DIV, reg, 2);
0179 if (err < 0)
0180 return err;
0181
0182 reg[0] = settings->fb_div_frac;
0183 reg[1] = settings->fb_div_frac >> 8;
0184 reg[2] = settings->fb_div_frac >> 16;
0185 reg[3] = settings->fb_div_frac >> 24;
0186 reg[4] = settings->fb_div_int;
0187 reg[5] = settings->fb_div_int >> 8;
0188
0189
0190
0191
0192
0193 return regmap_bulk_write(data->regmap, SI544_REG_FBDIV0, reg, 6);
0194 }
0195
0196 static bool is_valid_frequency(const struct clk_si544 *data,
0197 unsigned long frequency)
0198 {
0199 unsigned long max_freq = 0;
0200
0201 if (frequency < SI544_MIN_FREQ)
0202 return false;
0203
0204 switch (data->speed_grade) {
0205 case si544a:
0206 max_freq = 1500000000;
0207 break;
0208 case si544b:
0209 max_freq = 800000000;
0210 break;
0211 case si544c:
0212 max_freq = 350000000;
0213 break;
0214 }
0215
0216 return frequency <= max_freq;
0217 }
0218
0219
0220 static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
0221 unsigned long frequency)
0222 {
0223 u64 vco;
0224 u32 ls_freq;
0225 u32 tmp;
0226 u8 res;
0227
0228
0229 ls_freq = frequency;
0230 settings->ls_div_bits = 0;
0231
0232 if (frequency >= MIN_HSDIV_FREQ) {
0233 settings->ls_div_bits = 0;
0234 } else {
0235 res = 1;
0236 tmp = 2 * HS_DIV_MAX;
0237 while (tmp <= (HS_DIV_MAX * 32)) {
0238 if (((u64)frequency * tmp) >= FVCO_MIN)
0239 break;
0240 ++res;
0241 tmp <<= 1;
0242 }
0243 settings->ls_div_bits = res;
0244 ls_freq = frequency << res;
0245 }
0246
0247
0248 vco = FVCO_MIN + ls_freq - 1;
0249 do_div(vco, ls_freq);
0250 settings->hs_div = vco;
0251
0252
0253 if ((settings->hs_div & 1) &&
0254 (settings->hs_div > HS_DIV_MAX_ODD || settings->ls_div_bits))
0255 ++settings->hs_div;
0256
0257
0258 vco = (u64)ls_freq * settings->hs_div;
0259
0260
0261 tmp = do_div(vco, FXO);
0262 settings->fb_div_int = vco;
0263
0264
0265 vco = (u64)tmp << 32;
0266 vco += FXO / 2;
0267 do_div(vco, FXO);
0268 settings->fb_div_frac = vco;
0269
0270
0271 settings->delta_m = 0;
0272
0273 return 0;
0274 }
0275
0276
0277 static unsigned long si544_calc_center_rate(
0278 const struct clk_si544_muldiv *settings)
0279 {
0280 u32 d = settings->hs_div * BIT(settings->ls_div_bits);
0281 u64 vco;
0282
0283
0284 vco = (u64)settings->fb_div_frac * FXO;
0285 vco += (FXO / 2);
0286 vco >>= 32;
0287
0288
0289 vco += (u64)settings->fb_div_int * FXO;
0290
0291
0292 do_div(vco, d);
0293
0294 return vco;
0295 }
0296
0297 static unsigned long si544_calc_rate(const struct clk_si544_muldiv *settings)
0298 {
0299 unsigned long rate = si544_calc_center_rate(settings);
0300 s64 delta = (s64)rate * (DELTA_M_FRAC_NUM * settings->delta_m);
0301
0302
0303
0304
0305
0306
0307 if (settings->delta_m < 0)
0308 delta -= ((s64)DELTA_M_MAX * DELTA_M_FRAC_DEN) / 2;
0309 else
0310 delta += ((s64)DELTA_M_MAX * DELTA_M_FRAC_DEN) / 2;
0311 delta = div64_s64(delta, ((s64)DELTA_M_MAX * DELTA_M_FRAC_DEN));
0312
0313 return rate + delta;
0314 }
0315
0316 static unsigned long si544_recalc_rate(struct clk_hw *hw,
0317 unsigned long parent_rate)
0318 {
0319 struct clk_si544 *data = to_clk_si544(hw);
0320 struct clk_si544_muldiv settings;
0321 int err;
0322
0323 err = si544_get_muldiv(data, &settings);
0324 if (err)
0325 return 0;
0326
0327 return si544_calc_rate(&settings);
0328 }
0329
0330 static long si544_round_rate(struct clk_hw *hw, unsigned long rate,
0331 unsigned long *parent_rate)
0332 {
0333 struct clk_si544 *data = to_clk_si544(hw);
0334
0335 if (!is_valid_frequency(data, rate))
0336 return -EINVAL;
0337
0338
0339 return rate;
0340 }
0341
0342
0343 static unsigned long si544_max_delta(unsigned long rate)
0344 {
0345 u64 num = rate;
0346
0347 num *= DELTA_M_FRAC_NUM;
0348 do_div(num, DELTA_M_FRAC_DEN);
0349
0350 return num;
0351 }
0352
0353 static s32 si544_calc_delta(s32 delta, s32 max_delta)
0354 {
0355 s64 n = (s64)delta * DELTA_M_MAX;
0356
0357 return div_s64(n, max_delta);
0358 }
0359
0360 static int si544_set_rate(struct clk_hw *hw, unsigned long rate,
0361 unsigned long parent_rate)
0362 {
0363 struct clk_si544 *data = to_clk_si544(hw);
0364 struct clk_si544_muldiv settings;
0365 unsigned long center;
0366 long max_delta;
0367 long delta;
0368 unsigned int old_oe_state;
0369 int err;
0370
0371 if (!is_valid_frequency(data, rate))
0372 return -EINVAL;
0373
0374
0375 err = si544_get_muldiv(data, &settings);
0376 if (err)
0377 return err;
0378
0379 center = si544_calc_center_rate(&settings);
0380 max_delta = si544_max_delta(center);
0381 delta = rate - center;
0382
0383 if (abs(delta) <= max_delta)
0384 return si544_set_delta_m(data,
0385 si544_calc_delta(delta, max_delta));
0386
0387
0388 err = si544_calc_muldiv(&settings, rate);
0389 if (err)
0390 return err;
0391
0392 err = regmap_read(data->regmap, SI544_REG_OE_STATE, &old_oe_state);
0393 if (err)
0394 return err;
0395
0396 si544_enable_output(data, false);
0397
0398
0399 err = regmap_write(data->regmap, SI544_REG_FCAL_OVR, 0);
0400 if (err < 0)
0401 return err;
0402
0403 err = si544_set_delta_m(data, settings.delta_m);
0404 if (err < 0)
0405 return err;
0406
0407 err = si544_set_muldiv(data, &settings);
0408 if (err < 0)
0409 return err;
0410
0411
0412 err = regmap_write(data->regmap, SI544_REG_CONTROL,
0413 SI544_CONTROL_MS_ICAL2);
0414 if (err < 0)
0415 return err;
0416
0417
0418 usleep_range(10000, 12000);
0419
0420 if (old_oe_state & SI544_OE_STATE_ODC_OE)
0421 si544_enable_output(data, true);
0422
0423 return err;
0424 }
0425
0426 static const struct clk_ops si544_clk_ops = {
0427 .prepare = si544_prepare,
0428 .unprepare = si544_unprepare,
0429 .is_prepared = si544_is_prepared,
0430 .recalc_rate = si544_recalc_rate,
0431 .round_rate = si544_round_rate,
0432 .set_rate = si544_set_rate,
0433 };
0434
0435 static bool si544_regmap_is_volatile(struct device *dev, unsigned int reg)
0436 {
0437 switch (reg) {
0438 case SI544_REG_CONTROL:
0439 case SI544_REG_FCAL_OVR:
0440 return true;
0441 default:
0442 return false;
0443 }
0444 }
0445
0446 static const struct regmap_config si544_regmap_config = {
0447 .reg_bits = 8,
0448 .val_bits = 8,
0449 .cache_type = REGCACHE_RBTREE,
0450 .max_register = SI544_REG_PAGE_SELECT,
0451 .volatile_reg = si544_regmap_is_volatile,
0452 };
0453
0454 static const struct i2c_device_id si544_id[] = {
0455 { "si544a", si544a },
0456 { "si544b", si544b },
0457 { "si544c", si544c },
0458 { }
0459 };
0460 MODULE_DEVICE_TABLE(i2c, si544_id);
0461
0462 static int si544_probe(struct i2c_client *client)
0463 {
0464 struct clk_si544 *data;
0465 struct clk_init_data init;
0466 const struct i2c_device_id *id = i2c_match_id(si544_id, client);
0467 int err;
0468
0469 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
0470 if (!data)
0471 return -ENOMEM;
0472
0473 init.ops = &si544_clk_ops;
0474 init.flags = 0;
0475 init.num_parents = 0;
0476 data->hw.init = &init;
0477 data->i2c_client = client;
0478 data->speed_grade = id->driver_data;
0479
0480 if (of_property_read_string(client->dev.of_node, "clock-output-names",
0481 &init.name))
0482 init.name = client->dev.of_node->name;
0483
0484 data->regmap = devm_regmap_init_i2c(client, &si544_regmap_config);
0485 if (IS_ERR(data->regmap))
0486 return PTR_ERR(data->regmap);
0487
0488 i2c_set_clientdata(client, data);
0489
0490
0491 err = regmap_write(data->regmap, SI544_REG_PAGE_SELECT, 0);
0492 if (err < 0)
0493 return err;
0494
0495 err = devm_clk_hw_register(&client->dev, &data->hw);
0496 if (err) {
0497 dev_err(&client->dev, "clock registration failed\n");
0498 return err;
0499 }
0500 err = devm_of_clk_add_hw_provider(&client->dev, of_clk_hw_simple_get,
0501 &data->hw);
0502 if (err) {
0503 dev_err(&client->dev, "unable to add clk provider\n");
0504 return err;
0505 }
0506
0507 return 0;
0508 }
0509
0510 static const struct of_device_id clk_si544_of_match[] = {
0511 { .compatible = "silabs,si544a" },
0512 { .compatible = "silabs,si544b" },
0513 { .compatible = "silabs,si544c" },
0514 { },
0515 };
0516 MODULE_DEVICE_TABLE(of, clk_si544_of_match);
0517
0518 static struct i2c_driver si544_driver = {
0519 .driver = {
0520 .name = "si544",
0521 .of_match_table = clk_si544_of_match,
0522 },
0523 .probe_new = si544_probe,
0524 .id_table = si544_id,
0525 };
0526 module_i2c_driver(si544_driver);
0527
0528 MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
0529 MODULE_DESCRIPTION("Si544 driver");
0530 MODULE_LICENSE("GPL");