Skip to content

Commit b7bbf6e

Browse files
robhancocksedbebarino
authored andcommitted
clk: si5341: Allow different output VDD_SEL values
The driver was not previously programming the VDD_SEL values for each output to indicate what external VDDO voltage was used for each. Add ability to specify a regulator supplying the VDDO pin for each output of the device. The voltage of the regulator is used to automatically set the VDD_SEL value appropriately. If no regulator is specified and the chip is being reconfigured, assume 2.5V which appears to be the chip default. Signed-off-by: Robert Hancock <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent 3c9b49b commit b7bbf6e

File tree

1 file changed

+110
-26
lines changed

1 file changed

+110
-26
lines changed

drivers/clk/clk-si5341.c

Lines changed: 110 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/i2c.h>
2020
#include <linux/module.h>
2121
#include <linux/regmap.h>
22+
#include <linux/regulator/consumer.h>
2223
#include <linux/slab.h>
2324
#include <asm/unaligned.h>
2425

@@ -59,6 +60,7 @@ struct clk_si5341_synth {
5960
struct clk_si5341_output {
6061
struct clk_hw hw;
6162
struct clk_si5341 *data;
63+
struct regulator *vddo_reg;
6264
u8 index;
6365
};
6466
#define to_clk_si5341_output(_hw) \
@@ -84,6 +86,7 @@ struct clk_si5341 {
8486
struct clk_si5341_output_config {
8587
u8 out_format_drv_bits;
8688
u8 out_cm_ampl_bits;
89+
u8 vdd_sel_bits;
8790
bool synth_master;
8891
bool always_on;
8992
};
@@ -136,6 +139,8 @@ struct clk_si5341_output_config {
136139
#define SI5341_OUT_R_REG(output) \
137140
((output)->data->reg_rdiv_offset[(output)->index])
138141

142+
#define SI5341_OUT_MUX_VDD_SEL_MASK 0x38
143+
139144
/* Synthesize N divider */
140145
#define SI5341_SYNTH_N_NUM(x) (0x0302 + ((x) * 11))
141146
#define SI5341_SYNTH_N_DEN(x) (0x0308 + ((x) * 11))
@@ -1248,11 +1253,11 @@ static const struct regmap_config si5341_regmap_config = {
12481253
.volatile_table = &si5341_regmap_volatile,
12491254
};
12501255

1251-
static int si5341_dt_parse_dt(struct i2c_client *client,
1252-
struct clk_si5341_output_config *config)
1256+
static int si5341_dt_parse_dt(struct clk_si5341 *data,
1257+
struct clk_si5341_output_config *config)
12531258
{
12541259
struct device_node *child;
1255-
struct device_node *np = client->dev.of_node;
1260+
struct device_node *np = data->i2c_client->dev.of_node;
12561261
u32 num;
12571262
u32 val;
12581263

@@ -1261,13 +1266,13 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
12611266

12621267
for_each_child_of_node(np, child) {
12631268
if (of_property_read_u32(child, "reg", &num)) {
1264-
dev_err(&client->dev, "missing reg property of %s\n",
1269+
dev_err(&data->i2c_client->dev, "missing reg property of %s\n",
12651270
child->name);
12661271
goto put_child;
12671272
}
12681273

12691274
if (num >= SI5341_MAX_NUM_OUTPUTS) {
1270-
dev_err(&client->dev, "invalid clkout %d\n", num);
1275+
dev_err(&data->i2c_client->dev, "invalid clkout %d\n", num);
12711276
goto put_child;
12721277
}
12731278

@@ -1286,7 +1291,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
12861291
config[num].out_format_drv_bits |= 0xc0;
12871292
break;
12881293
default:
1289-
dev_err(&client->dev,
1294+
dev_err(&data->i2c_client->dev,
12901295
"invalid silabs,format %u for %u\n",
12911296
val, num);
12921297
goto put_child;
@@ -1299,7 +1304,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
12991304

13001305
if (!of_property_read_u32(child, "silabs,common-mode", &val)) {
13011306
if (val > 0xf) {
1302-
dev_err(&client->dev,
1307+
dev_err(&data->i2c_client->dev,
13031308
"invalid silabs,common-mode %u\n",
13041309
val);
13051310
goto put_child;
@@ -1310,7 +1315,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
13101315

13111316
if (!of_property_read_u32(child, "silabs,amplitude", &val)) {
13121317
if (val > 0xf) {
1313-
dev_err(&client->dev,
1318+
dev_err(&data->i2c_client->dev,
13141319
"invalid silabs,amplitude %u\n",
13151320
val);
13161321
goto put_child;
@@ -1327,6 +1332,34 @@ static int si5341_dt_parse_dt(struct i2c_client *client,
13271332

13281333
config[num].always_on =
13291334
of_property_read_bool(child, "always-on");
1335+
1336+
config[num].vdd_sel_bits = 0x08;
1337+
if (data->clk[num].vddo_reg) {
1338+
int vdd = regulator_get_voltage(data->clk[num].vddo_reg);
1339+
1340+
switch (vdd) {
1341+
case 3300000:
1342+
config[num].vdd_sel_bits |= 0 << 4;
1343+
break;
1344+
case 1800000:
1345+
config[num].vdd_sel_bits |= 1 << 4;
1346+
break;
1347+
case 2500000:
1348+
config[num].vdd_sel_bits |= 2 << 4;
1349+
break;
1350+
default:
1351+
dev_err(&data->i2c_client->dev,
1352+
"unsupported vddo voltage %d for %s\n",
1353+
vdd, child->name);
1354+
goto put_child;
1355+
}
1356+
} else {
1357+
/* chip seems to default to 2.5V when not set */
1358+
dev_warn(&data->i2c_client->dev,
1359+
"no regulator set, defaulting vdd_sel to 2.5V for %s\n",
1360+
child->name);
1361+
config[num].vdd_sel_bits |= 2 << 4;
1362+
}
13301363
}
13311364

13321365
return 0;
@@ -1452,31 +1485,57 @@ static int si5341_probe(struct i2c_client *client,
14521485
}
14531486
}
14541487

1455-
err = si5341_dt_parse_dt(client, config);
1488+
for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
1489+
char reg_name[10];
1490+
1491+
snprintf(reg_name, sizeof(reg_name), "vddo%d", i);
1492+
data->clk[i].vddo_reg = devm_regulator_get_optional(
1493+
&client->dev, reg_name);
1494+
if (IS_ERR(data->clk[i].vddo_reg)) {
1495+
err = PTR_ERR(data->clk[i].vddo_reg);
1496+
data->clk[i].vddo_reg = NULL;
1497+
if (err == -ENODEV)
1498+
continue;
1499+
goto cleanup;
1500+
} else {
1501+
err = regulator_enable(data->clk[i].vddo_reg);
1502+
if (err) {
1503+
dev_err(&client->dev,
1504+
"failed to enable %s regulator: %d\n",
1505+
reg_name, err);
1506+
data->clk[i].vddo_reg = NULL;
1507+
goto cleanup;
1508+
}
1509+
}
1510+
}
1511+
1512+
err = si5341_dt_parse_dt(data, config);
14561513
if (err)
1457-
return err;
1514+
goto cleanup;
14581515

14591516
if (of_property_read_string(client->dev.of_node, "clock-output-names",
14601517
&init.name))
14611518
init.name = client->dev.of_node->name;
14621519
root_clock_name = init.name;
14631520

14641521
data->regmap = devm_regmap_init_i2c(client, &si5341_regmap_config);
1465-
if (IS_ERR(data->regmap))
1466-
return PTR_ERR(data->regmap);
1522+
if (IS_ERR(data->regmap)) {
1523+
err = PTR_ERR(data->regmap);
1524+
goto cleanup;
1525+
}
14671526

14681527
i2c_set_clientdata(client, data);
14691528

14701529
err = si5341_probe_chip_id(data);
14711530
if (err < 0)
1472-
return err;
1531+
goto cleanup;
14731532

14741533
if (of_property_read_bool(client->dev.of_node, "silabs,reprogram")) {
14751534
initialization_required = true;
14761535
} else {
14771536
err = si5341_is_programmed_already(data);
14781537
if (err < 0)
1479-
return err;
1538+
goto cleanup;
14801539

14811540
initialization_required = !err;
14821541
}
@@ -1485,11 +1544,11 @@ static int si5341_probe(struct i2c_client *client,
14851544
/* Populate the regmap cache in preparation for "cache only" */
14861545
err = si5341_read_settings(data);
14871546
if (err < 0)
1488-
return err;
1547+
goto cleanup;
14891548

14901549
err = si5341_send_preamble(data);
14911550
if (err < 0)
1492-
return err;
1551+
goto cleanup;
14931552

14941553
/*
14951554
* We intend to send all 'final' register values in a single
@@ -1502,19 +1561,19 @@ static int si5341_probe(struct i2c_client *client,
15021561
err = si5341_write_multiple(data, si5341_reg_defaults,
15031562
ARRAY_SIZE(si5341_reg_defaults));
15041563
if (err < 0)
1505-
return err;
1564+
goto cleanup;
15061565
}
15071566

15081567
/* Input must be up and running at this point */
15091568
err = si5341_clk_select_active_input(data);
15101569
if (err < 0)
1511-
return err;
1570+
goto cleanup;
15121571

15131572
if (initialization_required) {
15141573
/* PLL configuration is required */
15151574
err = si5341_initialize_pll(data);
15161575
if (err < 0)
1517-
return err;
1576+
goto cleanup;
15181577
}
15191578

15201579
/* Register the PLL */
@@ -1527,7 +1586,7 @@ static int si5341_probe(struct i2c_client *client,
15271586
err = devm_clk_hw_register(&client->dev, &data->hw);
15281587
if (err) {
15291588
dev_err(&client->dev, "clock registration failed\n");
1530-
return err;
1589+
goto cleanup;
15311590
}
15321591

15331592
init.num_parents = 1;
@@ -1564,13 +1623,17 @@ static int si5341_probe(struct i2c_client *client,
15641623
regmap_write(data->regmap,
15651624
SI5341_OUT_CM(&data->clk[i]),
15661625
config[i].out_cm_ampl_bits);
1626+
regmap_update_bits(data->regmap,
1627+
SI5341_OUT_MUX_SEL(&data->clk[i]),
1628+
SI5341_OUT_MUX_VDD_SEL_MASK,
1629+
config[i].vdd_sel_bits);
15671630
}
15681631
err = devm_clk_hw_register(&client->dev, &data->clk[i].hw);
15691632
kfree(init.name); /* clock framework made a copy of the name */
15701633
if (err) {
15711634
dev_err(&client->dev,
15721635
"output %u registration failed\n", i);
1573-
return err;
1636+
goto cleanup;
15741637
}
15751638
if (config[i].always_on)
15761639
clk_prepare(data->clk[i].hw.clk);
@@ -1580,19 +1643,19 @@ static int si5341_probe(struct i2c_client *client,
15801643
data);
15811644
if (err) {
15821645
dev_err(&client->dev, "unable to add clk provider\n");
1583-
return err;
1646+
goto cleanup;
15841647
}
15851648

15861649
if (initialization_required) {
15871650
/* Synchronize */
15881651
regcache_cache_only(data->regmap, false);
15891652
err = regcache_sync(data->regmap);
15901653
if (err < 0)
1591-
return err;
1654+
goto cleanup;
15921655

15931656
err = si5341_finalize_defaults(data);
15941657
if (err < 0)
1595-
return err;
1658+
goto cleanup;
15961659
}
15971660

15981661
/* wait for device to report input clock present and PLL lock */
@@ -1601,21 +1664,41 @@ static int si5341_probe(struct i2c_client *client,
16011664
10000, 250000);
16021665
if (err) {
16031666
dev_err(&client->dev, "Error waiting for input clock or PLL lock\n");
1604-
return err;
1667+
goto cleanup;
16051668
}
16061669

16071670
/* clear sticky alarm bits from initialization */
16081671
err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
16091672
if (err) {
16101673
dev_err(&client->dev, "unable to clear sticky status\n");
1611-
return err;
1674+
goto cleanup;
16121675
}
16131676

16141677
/* Free the names, clk framework makes copies */
16151678
for (i = 0; i < data->num_synth; ++i)
16161679
devm_kfree(&client->dev, (void *)synth_clock_names[i]);
16171680

16181681
return 0;
1682+
1683+
cleanup:
1684+
for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
1685+
if (data->clk[i].vddo_reg)
1686+
regulator_disable(data->clk[i].vddo_reg);
1687+
}
1688+
return err;
1689+
}
1690+
1691+
static int si5341_remove(struct i2c_client *client)
1692+
{
1693+
struct clk_si5341 *data = i2c_get_clientdata(client);
1694+
int i;
1695+
1696+
for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
1697+
if (data->clk[i].vddo_reg)
1698+
regulator_disable(data->clk[i].vddo_reg);
1699+
}
1700+
1701+
return 0;
16191702
}
16201703

16211704
static const struct i2c_device_id si5341_id[] = {
@@ -1644,6 +1727,7 @@ static struct i2c_driver si5341_driver = {
16441727
.of_match_table = clk_si5341_of_match,
16451728
},
16461729
.probe = si5341_probe,
1730+
.remove = si5341_remove,
16471731
.id_table = si5341_id,
16481732
};
16491733
module_i2c_driver(si5341_driver);

0 commit comments

Comments
 (0)