Skip to content

Commit f9eec2e

Browse files
MikeLooijmansbebarino
authored andcommitted
clk: clk-si5341: Add support for the Si5345 series
Add support for the Si5342, Si5344 and Si5345 chips. These are equivalent to the Si5341 family, but with more clock input options (which are not supported yet by this driver). Signed-off-by: Mike Looijmans <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Acked-by: Rob Herring <[email protected]> Signed-off-by: Stephen Boyd <[email protected]>
1 parent 8f3d9f3 commit f9eec2e

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

Documentation/devicetree/bindings/clock/silabs,si5341.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
Binding for Silicon Labs Si5341 and Si5340 programmable i2c clock generator.
1+
Binding for Silicon Labs Si5340, Si5341 Si5342, Si5344 and Si5345 programmable
2+
i2c clock generator.
23

34
Reference
45
[1] Si5341 Data Sheet
56
https://www.silabs.com/documents/public/data-sheets/Si5341-40-D-DataSheet.pdf
67
[2] Si5341 Reference Manual
78
https://www.silabs.com/documents/public/reference-manuals/Si5341-40-D-RM.pdf
9+
[3] Si5345 Reference Manual
10+
https://www.silabs.com/documents/public/reference-manuals/Si5345-44-42-D-RM.pdf
811

912
The Si5341 and Si5340 are programmable i2c clock generators with up to 10 output
1013
clocks. The chip contains a PLL that sources 5 (or 4) multisynth clocks, which
1114
in turn can be directed to any of the 10 (or 4) outputs through a divider.
1215
The internal structure of the clock generators can be found in [2].
16+
The Si5345 is similar to the Si5341 with the addition of fractional input
17+
dividers and automatic input selection, as described in [3].
18+
The Si5342 and Si5344 are smaller versions of the Si5345, with 2 or 4 outputs.
1319

1420
The driver can be used in "as is" mode, reading the current settings from the
1521
chip at boot, in case you have a (pre-)programmed device. If the PLL is not
@@ -28,6 +34,9 @@ Required properties:
2834
- compatible: shall be one of the following:
2935
"silabs,si5340" - Si5340 A/B/C/D
3036
"silabs,si5341" - Si5341 A/B/C/D
37+
"silabs,si5342" - Si5342 A/B/C/D
38+
"silabs,si5344" - Si5344 A/B/C/D
39+
"silabs,si5345" - Si5345 A/B/C/D
3140
- reg: i2c device address, usually 0x74
3241
- #clock-cells: from common clock binding; shall be set to 2.
3342
The first value is "0" for outputs, "1" for synthesizers.

drivers/clk/clk-si5341.c

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/*
3-
* Driver for Silicon Labs Si5341/Si5340 Clock generator
3+
* Driver for Silicon Labs Si5340, Si5341, Si5342, Si5344 and Si5345
44
* Copyright (C) 2019 Topic Embedded Products
55
* Author: Mike Looijmans <[email protected]>
6+
*
7+
* The Si5341 has 10 outputs and 5 synthesizers.
8+
* The Si5340 is a smaller version of the Si5341 with only 4 outputs.
9+
* The Si5345 is similar to the Si5341, with the addition of fractional input
10+
* dividers and automatic input selection.
11+
* The Si5342 and Si5344 are smaller versions of the Si5345.
612
*/
713

814
#include <linux/clk.h>
@@ -18,11 +24,17 @@
1824

1925
#define SI5341_NUM_INPUTS 4
2026

21-
#define SI5341_MAX_NUM_OUTPUTS 10
2227
#define SI5340_MAX_NUM_OUTPUTS 4
28+
#define SI5341_MAX_NUM_OUTPUTS 10
29+
#define SI5342_MAX_NUM_OUTPUTS 2
30+
#define SI5344_MAX_NUM_OUTPUTS 4
31+
#define SI5345_MAX_NUM_OUTPUTS 10
2332

24-
#define SI5341_NUM_SYNTH 5
2533
#define SI5340_NUM_SYNTH 4
34+
#define SI5341_NUM_SYNTH 5
35+
#define SI5342_NUM_SYNTH 2
36+
#define SI5344_NUM_SYNTH 4
37+
#define SI5345_NUM_SYNTH 5
2638

2739
/* Range of the synthesizer fractional divider */
2840
#define SI5341_SYNTH_N_MIN 10
@@ -65,6 +77,7 @@ struct clk_si5341 {
6577
u64 freq_vco; /* 13500–14256 MHz */
6678
u8 num_outputs;
6779
u8 num_synth;
80+
u16 chip_id;
6881
};
6982
#define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw)
7083

@@ -142,6 +155,7 @@ static const char * const si5341_input_clock_names[] = {
142155
};
143156

144157
/* Output configuration registers 0..9 are not quite logically organized */
158+
/* Also for si5345 */
145159
static const u16 si5341_reg_output_offset[] = {
146160
0x0108,
147161
0x010D,
@@ -155,6 +169,7 @@ static const u16 si5341_reg_output_offset[] = {
155169
0x013A,
156170
};
157171

172+
/* for si5340, si5342 and si5344 */
158173
static const u16 si5340_reg_output_offset[] = {
159174
0x0112,
160175
0x0117,
@@ -974,12 +989,32 @@ static int si5341_probe_chip_id(struct clk_si5341 *data)
974989
data->reg_output_offset = si5341_reg_output_offset;
975990
data->reg_rdiv_offset = si5341_reg_rdiv_offset;
976991
break;
992+
case 0x5342:
993+
data->num_outputs = SI5342_MAX_NUM_OUTPUTS;
994+
data->num_synth = SI5342_NUM_SYNTH;
995+
data->reg_output_offset = si5340_reg_output_offset;
996+
data->reg_rdiv_offset = si5340_reg_rdiv_offset;
997+
break;
998+
case 0x5344:
999+
data->num_outputs = SI5344_MAX_NUM_OUTPUTS;
1000+
data->num_synth = SI5344_NUM_SYNTH;
1001+
data->reg_output_offset = si5340_reg_output_offset;
1002+
data->reg_rdiv_offset = si5340_reg_rdiv_offset;
1003+
break;
1004+
case 0x5345:
1005+
data->num_outputs = SI5345_MAX_NUM_OUTPUTS;
1006+
data->num_synth = SI5345_NUM_SYNTH;
1007+
data->reg_output_offset = si5341_reg_output_offset;
1008+
data->reg_rdiv_offset = si5341_reg_rdiv_offset;
1009+
break;
9771010
default:
9781011
dev_err(&data->i2c_client->dev, "Model '%x' not supported\n",
9791012
model);
9801013
return -EINVAL;
9811014
}
9821015

1016+
data->chip_id = model;
1017+
9831018
return 0;
9841019
}
9851020

@@ -1054,6 +1089,11 @@ static const struct si5341_reg_default si5341_preamble[] = {
10541089
{ 0x0B4E, 0x1A },
10551090
};
10561091

1092+
static const struct si5341_reg_default si5345_preamble[] = {
1093+
{ 0x0B25, 0x00 },
1094+
{ 0x0540, 0x01 },
1095+
};
1096+
10571097
static int si5341_send_preamble(struct clk_si5341 *data)
10581098
{
10591099
int res;
@@ -1068,8 +1108,14 @@ static int si5341_send_preamble(struct clk_si5341 *data)
10681108
res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xD8 : 0xC0);
10691109
if (res < 0)
10701110
return res;
1071-
res = si5341_write_multiple(data,
1072-
si5341_preamble, ARRAY_SIZE(si5341_preamble));
1111+
1112+
/* The si5342..si5345 require a different preamble */
1113+
if (data->chip_id > 0x5341)
1114+
res = si5341_write_multiple(data,
1115+
si5345_preamble, ARRAY_SIZE(si5345_preamble));
1116+
else
1117+
res = si5341_write_multiple(data,
1118+
si5341_preamble, ARRAY_SIZE(si5341_preamble));
10731119
if (res < 0)
10741120
return res;
10751121

@@ -1095,6 +1141,13 @@ static int si5341_finalize_defaults(struct clk_si5341 *data)
10951141
if (res < 0)
10961142
return res;
10971143

1144+
/* The si5342..si5345 have an additional post-amble */
1145+
if (data->chip_id > 0x5341) {
1146+
res = regmap_write(data->regmap, 0x540, 0x0);
1147+
if (res < 0)
1148+
return res;
1149+
}
1150+
10981151
/* Datasheet does not explain these nameless registers */
10991152
res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xDB : 0xC3);
11001153
if (res < 0)
@@ -1499,13 +1552,19 @@ static int si5341_probe(struct i2c_client *client,
14991552
static const struct i2c_device_id si5341_id[] = {
15001553
{ "si5340", 0 },
15011554
{ "si5341", 1 },
1555+
{ "si5342", 2 },
1556+
{ "si5344", 4 },
1557+
{ "si5345", 5 },
15021558
{ }
15031559
};
15041560
MODULE_DEVICE_TABLE(i2c, si5341_id);
15051561

15061562
static const struct of_device_id clk_si5341_of_match[] = {
15071563
{ .compatible = "silabs,si5340" },
15081564
{ .compatible = "silabs,si5341" },
1565+
{ .compatible = "silabs,si5342" },
1566+
{ .compatible = "silabs,si5344" },
1567+
{ .compatible = "silabs,si5345" },
15091568
{ }
15101569
};
15111570
MODULE_DEVICE_TABLE(of, clk_si5341_of_match);

0 commit comments

Comments
 (0)