Skip to content

Commit ea0a1fb

Browse files
committed
Merge branches 'clk-samsung', 'clk-formatting', 'clk-si5341' and 'clk-socfpga' into clk-next
* clk-samsung: clk: samsung: Remove redundant check in samsung_cmu_register_one * clk-formatting: clk: Fix continuation of of_clk_detect_critical() * clk-si5341: clk, clk-si5341: Support multiple input ports * clk-socfpga: clk: socfpga: stratix10: simplify parameter passing clk: stratix10: use do_div() for 64-bit calculation
4 parents 8d7a577 + be545c7 + 6927518 + 8c0e783 commit ea0a1fb

File tree

7 files changed

+258
-111
lines changed

7 files changed

+258
-111
lines changed

drivers/clk/clk-si5341.c

Lines changed: 196 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <linux/slab.h>
1717
#include <asm/unaligned.h>
1818

19+
#define SI5341_NUM_INPUTS 4
20+
1921
#define SI5341_MAX_NUM_OUTPUTS 10
2022
#define SI5340_MAX_NUM_OUTPUTS 4
2123

@@ -56,8 +58,8 @@ struct clk_si5341 {
5658
struct i2c_client *i2c_client;
5759
struct clk_si5341_synth synth[SI5341_NUM_SYNTH];
5860
struct clk_si5341_output clk[SI5341_MAX_NUM_OUTPUTS];
59-
struct clk *pxtal;
60-
const char *pxtal_name;
61+
struct clk *input_clk[SI5341_NUM_INPUTS];
62+
const char *input_clk_name[SI5341_NUM_INPUTS];
6163
const u16 *reg_output_offset;
6264
const u16 *reg_rdiv_offset;
6365
u64 freq_vco; /* 13500–14256 MHz */
@@ -78,10 +80,25 @@ struct clk_si5341_output_config {
7880
#define SI5341_DEVICE_REV 0x0005
7981
#define SI5341_STATUS 0x000C
8082
#define SI5341_SOFT_RST 0x001C
83+
#define SI5341_IN_SEL 0x0021
84+
#define SI5341_XAXB_CFG 0x090E
85+
#define SI5341_IN_EN 0x0949
86+
#define SI5341_INX_TO_PFD_EN 0x094A
87+
88+
/* Input selection */
89+
#define SI5341_IN_SEL_MASK 0x06
90+
#define SI5341_IN_SEL_SHIFT 1
91+
#define SI5341_IN_SEL_REGCTRL 0x01
92+
#define SI5341_INX_TO_PFD_SHIFT 4
93+
94+
/* XTAL config bits */
95+
#define SI5341_XAXB_CFG_EXTCLK_EN BIT(0)
96+
#define SI5341_XAXB_CFG_PDNB BIT(1)
8197

8298
/* Input dividers (48-bit) */
8399
#define SI5341_IN_PDIV(x) (0x0208 + ((x) * 10))
84100
#define SI5341_IN_PSET(x) (0x020E + ((x) * 10))
101+
#define SI5341_PX_UPD 0x0230
85102

86103
/* PLL configuration */
87104
#define SI5341_PLL_M_NUM 0x0235
@@ -120,6 +137,10 @@ struct si5341_reg_default {
120137
u8 value;
121138
};
122139

140+
static const char * const si5341_input_clock_names[] = {
141+
"in0", "in1", "in2", "xtal"
142+
};
143+
123144
/* Output configuration registers 0..9 are not quite logically organized */
124145
static const u16 si5341_reg_output_offset[] = {
125146
0x0108,
@@ -390,7 +411,112 @@ static unsigned long si5341_clk_recalc_rate(struct clk_hw *hw,
390411
return (unsigned long)res;
391412
}
392413

414+
static int si5341_clk_get_selected_input(struct clk_si5341 *data)
415+
{
416+
int err;
417+
u32 val;
418+
419+
err = regmap_read(data->regmap, SI5341_IN_SEL, &val);
420+
if (err < 0)
421+
return err;
422+
423+
return (val & SI5341_IN_SEL_MASK) >> SI5341_IN_SEL_SHIFT;
424+
}
425+
426+
static u8 si5341_clk_get_parent(struct clk_hw *hw)
427+
{
428+
struct clk_si5341 *data = to_clk_si5341(hw);
429+
int res = si5341_clk_get_selected_input(data);
430+
431+
if (res < 0)
432+
return 0; /* Apparently we cannot report errors */
433+
434+
return res;
435+
}
436+
437+
static int si5341_clk_reparent(struct clk_si5341 *data, u8 index)
438+
{
439+
int err;
440+
u8 val;
441+
442+
val = (index << SI5341_IN_SEL_SHIFT) & SI5341_IN_SEL_MASK;
443+
/* Enable register-based input selection */
444+
val |= SI5341_IN_SEL_REGCTRL;
445+
446+
err = regmap_update_bits(data->regmap,
447+
SI5341_IN_SEL, SI5341_IN_SEL_REGCTRL | SI5341_IN_SEL_MASK, val);
448+
if (err < 0)
449+
return err;
450+
451+
if (index < 3) {
452+
/* Enable input buffer for selected input */
453+
err = regmap_update_bits(data->regmap,
454+
SI5341_IN_EN, 0x07, BIT(index));
455+
if (err < 0)
456+
return err;
457+
458+
/* Enables the input to phase detector */
459+
err = regmap_update_bits(data->regmap, SI5341_INX_TO_PFD_EN,
460+
0x7 << SI5341_INX_TO_PFD_SHIFT,
461+
BIT(index + SI5341_INX_TO_PFD_SHIFT));
462+
if (err < 0)
463+
return err;
464+
465+
/* Power down XTAL oscillator and buffer */
466+
err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG,
467+
SI5341_XAXB_CFG_PDNB, 0);
468+
if (err < 0)
469+
return err;
470+
471+
/*
472+
* Set the P divider to "1". There's no explanation in the
473+
* datasheet of these registers, but the clockbuilder software
474+
* programs a "1" when the input is being used.
475+
*/
476+
err = regmap_write(data->regmap, SI5341_IN_PDIV(index), 1);
477+
if (err < 0)
478+
return err;
479+
480+
err = regmap_write(data->regmap, SI5341_IN_PSET(index), 1);
481+
if (err < 0)
482+
return err;
483+
484+
/* Set update PDIV bit */
485+
err = regmap_write(data->regmap, SI5341_PX_UPD, BIT(index));
486+
if (err < 0)
487+
return err;
488+
} else {
489+
/* Disable all input buffers */
490+
err = regmap_update_bits(data->regmap, SI5341_IN_EN, 0x07, 0);
491+
if (err < 0)
492+
return err;
493+
494+
/* Disable input to phase detector */
495+
err = regmap_update_bits(data->regmap, SI5341_INX_TO_PFD_EN,
496+
0x7 << SI5341_INX_TO_PFD_SHIFT, 0);
497+
if (err < 0)
498+
return err;
499+
500+
/* Power up XTAL oscillator and buffer */
501+
err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG,
502+
SI5341_XAXB_CFG_PDNB, SI5341_XAXB_CFG_PDNB);
503+
if (err < 0)
504+
return err;
505+
}
506+
507+
return 0;
508+
}
509+
510+
static int si5341_clk_set_parent(struct clk_hw *hw, u8 index)
511+
{
512+
struct clk_si5341 *data = to_clk_si5341(hw);
513+
514+
return si5341_clk_reparent(data, index);
515+
}
516+
393517
static const struct clk_ops si5341_clk_ops = {
518+
.set_parent = si5341_clk_set_parent,
519+
.get_parent = si5341_clk_get_parent,
394520
.recalc_rate = si5341_clk_recalc_rate,
395521
};
396522

@@ -985,7 +1111,8 @@ static const struct regmap_range si5341_regmap_volatile_range[] = {
9851111
regmap_reg_range(0x000C, 0x0012), /* Status */
9861112
regmap_reg_range(0x001C, 0x001E), /* reset, finc/fdec */
9871113
regmap_reg_range(0x00E2, 0x00FE), /* NVM, interrupts, device ready */
988-
/* Update bits for synth config */
1114+
/* Update bits for P divider and synth config */
1115+
regmap_reg_range(SI5341_PX_UPD, SI5341_PX_UPD),
9891116
regmap_reg_range(SI5341_SYNTH_N_UPD(0), SI5341_SYNTH_N_UPD(0)),
9901117
regmap_reg_range(SI5341_SYNTH_N_UPD(1), SI5341_SYNTH_N_UPD(1)),
9911118
regmap_reg_range(SI5341_SYNTH_N_UPD(2), SI5341_SYNTH_N_UPD(2)),
@@ -1122,6 +1249,7 @@ static int si5341_initialize_pll(struct clk_si5341 *data)
11221249
struct device_node *np = data->i2c_client->dev.of_node;
11231250
u32 m_num = 0;
11241251
u32 m_den = 0;
1252+
int sel;
11251253

11261254
if (of_property_read_u32(np, "silabs,pll-m-num", &m_num)) {
11271255
dev_err(&data->i2c_client->dev,
@@ -1135,19 +1263,64 @@ static int si5341_initialize_pll(struct clk_si5341 *data)
11351263
if (!m_num || !m_den) {
11361264
dev_err(&data->i2c_client->dev,
11371265
"PLL configuration invalid, assume 14GHz\n");
1138-
m_den = clk_get_rate(data->pxtal) / 10;
1266+
sel = si5341_clk_get_selected_input(data);
1267+
if (sel < 0)
1268+
return sel;
1269+
1270+
m_den = clk_get_rate(data->input_clk[sel]) / 10;
11391271
m_num = 1400000000;
11401272
}
11411273

11421274
return si5341_encode_44_32(data->regmap,
11431275
SI5341_PLL_M_NUM, m_num, m_den);
11441276
}
11451277

1278+
static int si5341_clk_select_active_input(struct clk_si5341 *data)
1279+
{
1280+
int res;
1281+
int err;
1282+
int i;
1283+
1284+
res = si5341_clk_get_selected_input(data);
1285+
if (res < 0)
1286+
return res;
1287+
1288+
/* If the current register setting is invalid, pick the first input */
1289+
if (!data->input_clk[res]) {
1290+
dev_dbg(&data->i2c_client->dev,
1291+
"Input %d not connected, rerouting\n", res);
1292+
res = -ENODEV;
1293+
for (i = 0; i < SI5341_NUM_INPUTS; ++i) {
1294+
if (data->input_clk[i]) {
1295+
res = i;
1296+
break;
1297+
}
1298+
}
1299+
if (res < 0) {
1300+
dev_err(&data->i2c_client->dev,
1301+
"No clock input available\n");
1302+
return res;
1303+
}
1304+
}
1305+
1306+
/* Make sure the selected clock is also enabled and routed */
1307+
err = si5341_clk_reparent(data, res);
1308+
if (err < 0)
1309+
return err;
1310+
1311+
err = clk_prepare_enable(data->input_clk[res]);
1312+
if (err < 0)
1313+
return err;
1314+
1315+
return res;
1316+
}
1317+
11461318
static int si5341_probe(struct i2c_client *client,
11471319
const struct i2c_device_id *id)
11481320
{
11491321
struct clk_si5341 *data;
11501322
struct clk_init_data init;
1323+
struct clk *input;
11511324
const char *root_clock_name;
11521325
const char *synth_clock_names[SI5341_NUM_SYNTH];
11531326
int err;
@@ -1161,12 +1334,16 @@ static int si5341_probe(struct i2c_client *client,
11611334

11621335
data->i2c_client = client;
11631336

1164-
data->pxtal = devm_clk_get(&client->dev, "xtal");
1165-
if (IS_ERR(data->pxtal)) {
1166-
if (PTR_ERR(data->pxtal) == -EPROBE_DEFER)
1167-
return -EPROBE_DEFER;
1168-
1169-
dev_err(&client->dev, "Missing xtal clock input\n");
1337+
for (i = 0; i < SI5341_NUM_INPUTS; ++i) {
1338+
input = devm_clk_get(&client->dev, si5341_input_clock_names[i]);
1339+
if (IS_ERR(input)) {
1340+
if (PTR_ERR(input) == -EPROBE_DEFER)
1341+
return -EPROBE_DEFER;
1342+
data->input_clk_name[i] = si5341_input_clock_names[i];
1343+
} else {
1344+
data->input_clk[i] = input;
1345+
data->input_clk_name[i] = __clk_get_name(input);
1346+
}
11701347
}
11711348

11721349
err = si5341_dt_parse_dt(client, config);
@@ -1188,9 +1365,6 @@ static int si5341_probe(struct i2c_client *client,
11881365
if (err < 0)
11891366
return err;
11901367

1191-
/* "Activate" the xtal (usually a fixed clock) */
1192-
clk_prepare_enable(data->pxtal);
1193-
11941368
if (of_property_read_bool(client->dev.of_node, "silabs,reprogram")) {
11951369
initialization_required = true;
11961370
} else {
@@ -1223,17 +1397,23 @@ static int si5341_probe(struct i2c_client *client,
12231397
ARRAY_SIZE(si5341_reg_defaults));
12241398
if (err < 0)
12251399
return err;
1400+
}
1401+
1402+
/* Input must be up and running at this point */
1403+
err = si5341_clk_select_active_input(data);
1404+
if (err < 0)
1405+
return err;
12261406

1407+
if (initialization_required) {
12271408
/* PLL configuration is required */
12281409
err = si5341_initialize_pll(data);
12291410
if (err < 0)
12301411
return err;
12311412
}
12321413

12331414
/* Register the PLL */
1234-
data->pxtal_name = __clk_get_name(data->pxtal);
1235-
init.parent_names = &data->pxtal_name;
1236-
init.num_parents = 1; /* For now, only XTAL input supported */
1415+
init.parent_names = data->input_clk_name;
1416+
init.num_parents = SI5341_NUM_INPUTS;
12371417
init.ops = &si5341_clk_ops;
12381418
init.flags = 0;
12391419
data->hw.init = &init;

drivers/clk/clk.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4865,8 +4865,8 @@ static int parent_ready(struct device_node *np)
48654865
*
48664866
* Return: error code or zero on success
48674867
*/
4868-
int of_clk_detect_critical(struct device_node *np,
4869-
int index, unsigned long *flags)
4868+
int of_clk_detect_critical(struct device_node *np, int index,
4869+
unsigned long *flags)
48704870
{
48714871
struct property *prop;
48724872
const __be32 *cur;

0 commit comments

Comments
 (0)