1
1
// SPDX-License-Identifier: GPL-2.0
2
2
/*
3
- * Driver for Silicon Labs Si5341/ Si5340 Clock generator
3
+ * Driver for Silicon Labs Si5340, Si5341, Si5342, Si5344 and Si5345
4
4
* Copyright (C) 2019 Topic Embedded Products
5
5
* 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.
6
12
*/
7
13
8
14
#include <linux/clk.h>
18
24
19
25
#define SI5341_NUM_INPUTS 4
20
26
21
- #define SI5341_MAX_NUM_OUTPUTS 10
22
27
#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
23
32
24
- #define SI5341_NUM_SYNTH 5
25
33
#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
26
38
27
39
/* Range of the synthesizer fractional divider */
28
40
#define SI5341_SYNTH_N_MIN 10
@@ -65,6 +77,7 @@ struct clk_si5341 {
65
77
u64 freq_vco ; /* 13500–14256 MHz */
66
78
u8 num_outputs ;
67
79
u8 num_synth ;
80
+ u16 chip_id ;
68
81
};
69
82
#define to_clk_si5341 (_hw ) container_of(_hw, struct clk_si5341, hw)
70
83
@@ -142,6 +155,7 @@ static const char * const si5341_input_clock_names[] = {
142
155
};
143
156
144
157
/* Output configuration registers 0..9 are not quite logically organized */
158
+ /* Also for si5345 */
145
159
static const u16 si5341_reg_output_offset [] = {
146
160
0x0108 ,
147
161
0x010D ,
@@ -155,6 +169,7 @@ static const u16 si5341_reg_output_offset[] = {
155
169
0x013A ,
156
170
};
157
171
172
+ /* for si5340, si5342 and si5344 */
158
173
static const u16 si5340_reg_output_offset [] = {
159
174
0x0112 ,
160
175
0x0117 ,
@@ -974,12 +989,32 @@ static int si5341_probe_chip_id(struct clk_si5341 *data)
974
989
data -> reg_output_offset = si5341_reg_output_offset ;
975
990
data -> reg_rdiv_offset = si5341_reg_rdiv_offset ;
976
991
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 ;
977
1010
default :
978
1011
dev_err (& data -> i2c_client -> dev , "Model '%x' not supported\n" ,
979
1012
model );
980
1013
return - EINVAL ;
981
1014
}
982
1015
1016
+ data -> chip_id = model ;
1017
+
983
1018
return 0 ;
984
1019
}
985
1020
@@ -1054,6 +1089,11 @@ static const struct si5341_reg_default si5341_preamble[] = {
1054
1089
{ 0x0B4E , 0x1A },
1055
1090
};
1056
1091
1092
+ static const struct si5341_reg_default si5345_preamble [] = {
1093
+ { 0x0B25 , 0x00 },
1094
+ { 0x0540 , 0x01 },
1095
+ };
1096
+
1057
1097
static int si5341_send_preamble (struct clk_si5341 * data )
1058
1098
{
1059
1099
int res ;
@@ -1068,8 +1108,14 @@ static int si5341_send_preamble(struct clk_si5341 *data)
1068
1108
res = regmap_write (data -> regmap , 0xB24 , revision < 2 ? 0xD8 : 0xC0 );
1069
1109
if (res < 0 )
1070
1110
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 ));
1073
1119
if (res < 0 )
1074
1120
return res ;
1075
1121
@@ -1095,6 +1141,13 @@ static int si5341_finalize_defaults(struct clk_si5341 *data)
1095
1141
if (res < 0 )
1096
1142
return res ;
1097
1143
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
+
1098
1151
/* Datasheet does not explain these nameless registers */
1099
1152
res = regmap_write (data -> regmap , 0xB24 , revision < 2 ? 0xDB : 0xC3 );
1100
1153
if (res < 0 )
@@ -1499,13 +1552,19 @@ static int si5341_probe(struct i2c_client *client,
1499
1552
static const struct i2c_device_id si5341_id [] = {
1500
1553
{ "si5340" , 0 },
1501
1554
{ "si5341" , 1 },
1555
+ { "si5342" , 2 },
1556
+ { "si5344" , 4 },
1557
+ { "si5345" , 5 },
1502
1558
{ }
1503
1559
};
1504
1560
MODULE_DEVICE_TABLE (i2c , si5341_id );
1505
1561
1506
1562
static const struct of_device_id clk_si5341_of_match [] = {
1507
1563
{ .compatible = "silabs,si5340" },
1508
1564
{ .compatible = "silabs,si5341" },
1565
+ { .compatible = "silabs,si5342" },
1566
+ { .compatible = "silabs,si5344" },
1567
+ { .compatible = "silabs,si5345" },
1509
1568
{ }
1510
1569
};
1511
1570
MODULE_DEVICE_TABLE (of , clk_si5341_of_match );
0 commit comments