Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <mike.looijmans@topic.nl>
Link: https://lkml.kernel.org/r/20200507061544.11388-1-mike.looijmans@topic.nl
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Mike Looijmans and committed by
Stephen Boyd
f9eec2ea 8f3d9f35

+74 -6
+10 -1
Documentation/devicetree/bindings/clock/silabs,si5341.txt
··· 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. 2 3 3 4 Reference 4 5 [1] Si5341 Data Sheet 5 6 https://www.silabs.com/documents/public/data-sheets/Si5341-40-D-DataSheet.pdf 6 7 [2] Si5341 Reference Manual 7 8 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 8 11 9 12 The Si5341 and Si5340 are programmable i2c clock generators with up to 10 output 10 13 clocks. The chip contains a PLL that sources 5 (or 4) multisynth clocks, which 11 14 in turn can be directed to any of the 10 (or 4) outputs through a divider. 12 15 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. 13 19 14 20 The driver can be used in "as is" mode, reading the current settings from the 15 21 chip at boot, in case you have a (pre-)programmed device. If the PLL is not ··· 34 28 - compatible: shall be one of the following: 35 29 "silabs,si5340" - Si5340 A/B/C/D 36 30 "silabs,si5341" - Si5341 A/B/C/D 31 + "silabs,si5342" - Si5342 A/B/C/D 32 + "silabs,si5344" - Si5344 A/B/C/D 33 + "silabs,si5345" - Si5345 A/B/C/D 37 34 - reg: i2c device address, usually 0x74 38 35 - #clock-cells: from common clock binding; shall be set to 2. 39 36 The first value is "0" for outputs, "1" for synthesizers.
+64 -5
drivers/clk/clk-si5341.c
··· 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 <mike.looijmans@topic.nl> 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> ··· 24 18 25 19 #define SI5341_NUM_INPUTS 4 26 20 27 - #define SI5341_MAX_NUM_OUTPUTS 10 28 21 #define SI5340_MAX_NUM_OUTPUTS 4 22 + #define SI5341_MAX_NUM_OUTPUTS 10 23 + #define SI5342_MAX_NUM_OUTPUTS 2 24 + #define SI5344_MAX_NUM_OUTPUTS 4 25 + #define SI5345_MAX_NUM_OUTPUTS 10 29 26 30 - #define SI5341_NUM_SYNTH 5 31 27 #define SI5340_NUM_SYNTH 4 28 + #define SI5341_NUM_SYNTH 5 29 + #define SI5342_NUM_SYNTH 2 30 + #define SI5344_NUM_SYNTH 4 31 + #define SI5345_NUM_SYNTH 5 32 32 33 33 /* Range of the synthesizer fractional divider */ 34 34 #define SI5341_SYNTH_N_MIN 10 ··· 77 65 u64 freq_vco; /* 13500–14256 MHz */ 78 66 u8 num_outputs; 79 67 u8 num_synth; 68 + u16 chip_id; 80 69 }; 81 70 #define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw) 82 71 ··· 155 142 }; 156 143 157 144 /* Output configuration registers 0..9 are not quite logically organized */ 145 + /* Also for si5345 */ 158 146 static const u16 si5341_reg_output_offset[] = { 159 147 0x0108, 160 148 0x010D, ··· 169 155 0x013A, 170 156 }; 171 157 158 + /* for si5340, si5342 and si5344 */ 172 159 static const u16 si5340_reg_output_offset[] = { 173 160 0x0112, 174 161 0x0117, ··· 989 974 data->reg_output_offset = si5341_reg_output_offset; 990 975 data->reg_rdiv_offset = si5341_reg_rdiv_offset; 991 976 break; 977 + case 0x5342: 978 + data->num_outputs = SI5342_MAX_NUM_OUTPUTS; 979 + data->num_synth = SI5342_NUM_SYNTH; 980 + data->reg_output_offset = si5340_reg_output_offset; 981 + data->reg_rdiv_offset = si5340_reg_rdiv_offset; 982 + break; 983 + case 0x5344: 984 + data->num_outputs = SI5344_MAX_NUM_OUTPUTS; 985 + data->num_synth = SI5344_NUM_SYNTH; 986 + data->reg_output_offset = si5340_reg_output_offset; 987 + data->reg_rdiv_offset = si5340_reg_rdiv_offset; 988 + break; 989 + case 0x5345: 990 + data->num_outputs = SI5345_MAX_NUM_OUTPUTS; 991 + data->num_synth = SI5345_NUM_SYNTH; 992 + data->reg_output_offset = si5341_reg_output_offset; 993 + data->reg_rdiv_offset = si5341_reg_rdiv_offset; 994 + break; 992 995 default: 993 996 dev_err(&data->i2c_client->dev, "Model '%x' not supported\n", 994 997 model); 995 998 return -EINVAL; 996 999 } 1000 + 1001 + data->chip_id = model; 997 1002 998 1003 return 0; 999 1004 } ··· 1089 1054 { 0x0B4E, 0x1A }, 1090 1055 }; 1091 1056 1057 + static const struct si5341_reg_default si5345_preamble[] = { 1058 + { 0x0B25, 0x00 }, 1059 + { 0x0540, 0x01 }, 1060 + }; 1061 + 1092 1062 static int si5341_send_preamble(struct clk_si5341 *data) 1093 1063 { 1094 1064 int res; ··· 1108 1068 res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xD8 : 0xC0); 1109 1069 if (res < 0) 1110 1070 return res; 1111 - res = si5341_write_multiple(data, 1112 - si5341_preamble, ARRAY_SIZE(si5341_preamble)); 1071 + 1072 + /* The si5342..si5345 require a different preamble */ 1073 + if (data->chip_id > 0x5341) 1074 + res = si5341_write_multiple(data, 1075 + si5345_preamble, ARRAY_SIZE(si5345_preamble)); 1076 + else 1077 + res = si5341_write_multiple(data, 1078 + si5341_preamble, ARRAY_SIZE(si5341_preamble)); 1113 1079 if (res < 0) 1114 1080 return res; 1115 1081 ··· 1140 1094 res = regmap_write(data->regmap, SI5341_SOFT_RST, 0x01); 1141 1095 if (res < 0) 1142 1096 return res; 1097 + 1098 + /* The si5342..si5345 have an additional post-amble */ 1099 + if (data->chip_id > 0x5341) { 1100 + res = regmap_write(data->regmap, 0x540, 0x0); 1101 + if (res < 0) 1102 + return res; 1103 + } 1143 1104 1144 1105 /* Datasheet does not explain these nameless registers */ 1145 1106 res = regmap_write(data->regmap, 0xB24, revision < 2 ? 0xDB : 0xC3); ··· 1552 1499 static const struct i2c_device_id si5341_id[] = { 1553 1500 { "si5340", 0 }, 1554 1501 { "si5341", 1 }, 1502 + { "si5342", 2 }, 1503 + { "si5344", 4 }, 1504 + { "si5345", 5 }, 1555 1505 { } 1556 1506 }; 1557 1507 MODULE_DEVICE_TABLE(i2c, si5341_id); ··· 1562 1506 static const struct of_device_id clk_si5341_of_match[] = { 1563 1507 { .compatible = "silabs,si5340" }, 1564 1508 { .compatible = "silabs,si5341" }, 1509 + { .compatible = "silabs,si5342" }, 1510 + { .compatible = "silabs,si5344" }, 1511 + { .compatible = "silabs,si5345" }, 1565 1512 { } 1566 1513 }; 1567 1514 MODULE_DEVICE_TABLE(of, clk_si5341_of_match);