forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/drivers/clk/clk-versaclock5.c
....@@ -1,17 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Driver for IDT Versaclock 5
34 *
45 * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
156 */
167
178 /*
....@@ -32,6 +23,8 @@
3223 #include <linux/rational.h>
3324 #include <linux/regmap.h>
3425 #include <linux/slab.h>
26
+
27
+#include <dt-bindings/clk/versaclock.h>
3528
3629 /* VersaClock5 registers */
3730 #define VC5_OTP_CONTROL 0x00
....@@ -76,7 +69,10 @@
7669 #define VC5_FEEDBACK_FRAC_DIV(n) (0x19 + (n))
7770 #define VC5_RC_CONTROL0 0x1e
7871 #define VC5_RC_CONTROL1 0x1f
79
-/* Register 0x20 is factory reserved */
72
+
73
+/* These registers are named "Unused Factory Reserved Registers" */
74
+#define VC5_RESERVED_X0(idx) (0x20 + ((idx) * 0x10))
75
+#define VC5_RESERVED_X0_BYPASS_SYNC BIT(7) /* bypass_sync<idx> bit */
8076
8177 /* Output divider control for divider 1,2,3,4 */
8278 #define VC5_OUT_DIV_CONTROL(idx) (0x21 + ((idx) * 0x10))
....@@ -94,10 +90,31 @@
9490 #define VC5_OUT_DIV_SKEW_INT(idx, n) (0x2b + ((idx) * 0x10) + (n))
9591 #define VC5_OUT_DIV_INT(idx, n) (0x2d + ((idx) * 0x10) + (n))
9692 #define VC5_OUT_DIV_SKEW_FRAC(idx) (0x2f + ((idx) * 0x10))
97
-/* Registers 0x30, 0x40, 0x50 are factory reserved */
9893
9994 /* Clock control register for clock 1,2 */
10095 #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n))
96
+#define VC5_CLK_OUTPUT_CFG0_CFG_SHIFT 5
97
+#define VC5_CLK_OUTPUT_CFG0_CFG_MASK GENMASK(7, VC5_CLK_OUTPUT_CFG0_CFG_SHIFT)
98
+
99
+#define VC5_CLK_OUTPUT_CFG0_CFG_LVPECL (VC5_LVPECL)
100
+#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS (VC5_CMOS)
101
+#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL33 (VC5_HCSL33)
102
+#define VC5_CLK_OUTPUT_CFG0_CFG_LVDS (VC5_LVDS)
103
+#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS2 (VC5_CMOS2)
104
+#define VC5_CLK_OUTPUT_CFG0_CFG_CMOSD (VC5_CMOSD)
105
+#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL25 (VC5_HCSL25)
106
+
107
+#define VC5_CLK_OUTPUT_CFG0_PWR_SHIFT 3
108
+#define VC5_CLK_OUTPUT_CFG0_PWR_MASK GENMASK(4, VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
109
+#define VC5_CLK_OUTPUT_CFG0_PWR_18 (0<<VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
110
+#define VC5_CLK_OUTPUT_CFG0_PWR_25 (2<<VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
111
+#define VC5_CLK_OUTPUT_CFG0_PWR_33 (3<<VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
112
+#define VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT 0
113
+#define VC5_CLK_OUTPUT_CFG0_SLEW_MASK GENMASK(1, VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
114
+#define VC5_CLK_OUTPUT_CFG0_SLEW_80 (0<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
115
+#define VC5_CLK_OUTPUT_CFG0_SLEW_85 (1<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
116
+#define VC5_CLK_OUTPUT_CFG0_SLEW_90 (2<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
117
+#define VC5_CLK_OUTPUT_CFG0_SLEW_100 (3<<VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
101118 #define VC5_CLK_OUTPUT_CFG1_EN_CLKBUF BIT(0)
102119
103120 #define VC5_CLK_OE_SHDN 0x68
....@@ -125,6 +142,8 @@
125142 #define VC5_HAS_INTERNAL_XTAL BIT(0)
126143 /* chip has PFD requency doubler */
127144 #define VC5_HAS_PFD_FREQ_DBL BIT(1)
145
+/* chip has bits to disable FOD sync */
146
+#define VC5_HAS_BYPASS_SYNC_BIT BIT(2)
128147
129148 /* Supported IDT VC5 models. */
130149 enum vc5_model {
....@@ -133,6 +152,7 @@
133152 IDT_VC5_5P49V5933,
134153 IDT_VC5_5P49V5935,
135154 IDT_VC6_5P49V6901,
155
+ IDT_VC6_5P49V6965,
136156 };
137157
138158 /* Structure to describe features of a particular VC5 model */
....@@ -153,6 +173,14 @@
153173 unsigned int num;
154174 };
155175
176
+struct vc5_out_data {
177
+ struct clk_hw hw;
178
+ struct vc5_driver_data *vc5;
179
+ unsigned int num;
180
+ unsigned int clk_output_cfg0;
181
+ unsigned int clk_output_cfg0_mask;
182
+};
183
+
156184 struct vc5_driver_data {
157185 struct i2c_client *client;
158186 struct regmap *regmap;
....@@ -166,31 +194,7 @@
166194 struct clk_hw clk_pfd;
167195 struct vc5_hw_data clk_pll;
168196 struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM];
169
- struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM];
170
-};
171
-
172
-static const char * const vc5_mux_names[] = {
173
- "mux"
174
-};
175
-
176
-static const char * const vc5_dbl_names[] = {
177
- "dbl"
178
-};
179
-
180
-static const char * const vc5_pfd_names[] = {
181
- "pfd"
182
-};
183
-
184
-static const char * const vc5_pll_names[] = {
185
- "pll"
186
-};
187
-
188
-static const char * const vc5_fod_names[] = {
189
- "fod0", "fod1", "fod2", "fod3",
190
-};
191
-
192
-static const char * const vc5_clk_out_names[] = {
193
- "out0_sel_i2cb", "out1", "out2", "out3", "out4",
197
+ struct vc5_out_data clk_out[VC5_MAX_CLK_OUT_NUM];
194198 };
195199
196200 /*
....@@ -573,13 +577,30 @@
573577
574578 static int vc5_clk_out_prepare(struct clk_hw *hw)
575579 {
576
- struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);
580
+ struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
577581 struct vc5_driver_data *vc5 = hwdata->vc5;
578582 const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM |
579583 VC5_OUT_DIV_CONTROL_SEL_EXT |
580584 VC5_OUT_DIV_CONTROL_EN_FOD;
581585 unsigned int src;
582586 int ret;
587
+
588
+ /*
589
+ * When enabling a FOD, all currently enabled FODs are briefly
590
+ * stopped in order to synchronize all of them. This causes a clock
591
+ * disruption to any unrelated chips that might be already using
592
+ * other clock outputs. Bypass the sync feature to avoid the issue,
593
+ * which is possible on the VersaClock 6E family via reserved
594
+ * registers.
595
+ */
596
+ if (vc5->chip_info->flags & VC5_HAS_BYPASS_SYNC_BIT) {
597
+ ret = regmap_update_bits(vc5->regmap,
598
+ VC5_RESERVED_X0(hwdata->num),
599
+ VC5_RESERVED_X0_BYPASS_SYNC,
600
+ VC5_RESERVED_X0_BYPASS_SYNC);
601
+ if (ret)
602
+ return ret;
603
+ }
583604
584605 /*
585606 * If the input mux is disabled, enable it first and
....@@ -599,12 +620,23 @@
599620 regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1),
600621 VC5_CLK_OUTPUT_CFG1_EN_CLKBUF,
601622 VC5_CLK_OUTPUT_CFG1_EN_CLKBUF);
623
+ if (hwdata->clk_output_cfg0_mask) {
624
+ dev_dbg(&vc5->client->dev, "Update output %d mask 0x%0X val 0x%0X\n",
625
+ hwdata->num, hwdata->clk_output_cfg0_mask,
626
+ hwdata->clk_output_cfg0);
627
+
628
+ regmap_update_bits(vc5->regmap,
629
+ VC5_CLK_OUTPUT_CFG(hwdata->num, 0),
630
+ hwdata->clk_output_cfg0_mask,
631
+ hwdata->clk_output_cfg0);
632
+ }
633
+
602634 return 0;
603635 }
604636
605637 static void vc5_clk_out_unprepare(struct clk_hw *hw)
606638 {
607
- struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);
639
+ struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
608640 struct vc5_driver_data *vc5 = hwdata->vc5;
609641
610642 /* Disable the clock buffer */
....@@ -614,7 +646,7 @@
614646
615647 static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw)
616648 {
617
- struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);
649
+ struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
618650 struct vc5_driver_data *vc5 = hwdata->vc5;
619651 const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM |
620652 VC5_OUT_DIV_CONTROL_SEL_EXT |
....@@ -644,7 +676,7 @@
644676
645677 static int vc5_clk_out_set_parent(struct clk_hw *hw, u8 index)
646678 {
647
- struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);
679
+ struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
648680 struct vc5_driver_data *vc5 = hwdata->vc5;
649681 const u8 mask = VC5_OUT_DIV_CONTROL_RESET |
650682 VC5_OUT_DIV_CONTROL_SELB_NORM |
....@@ -692,24 +724,140 @@
692724 case IDT_VC5_5P49V5925:
693725 case IDT_VC5_5P49V5935:
694726 case IDT_VC6_5P49V6901:
727
+ case IDT_VC6_5P49V6965:
695728 default:
696729 return n;
697730 }
698731 }
699732
733
+static int vc5_update_mode(struct device_node *np_output,
734
+ struct vc5_out_data *clk_out)
735
+{
736
+ u32 value;
737
+
738
+ if (!of_property_read_u32(np_output, "idt,mode", &value)) {
739
+ clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_CFG_MASK;
740
+ switch (value) {
741
+ case VC5_CLK_OUTPUT_CFG0_CFG_LVPECL:
742
+ case VC5_CLK_OUTPUT_CFG0_CFG_CMOS:
743
+ case VC5_CLK_OUTPUT_CFG0_CFG_HCSL33:
744
+ case VC5_CLK_OUTPUT_CFG0_CFG_LVDS:
745
+ case VC5_CLK_OUTPUT_CFG0_CFG_CMOS2:
746
+ case VC5_CLK_OUTPUT_CFG0_CFG_CMOSD:
747
+ case VC5_CLK_OUTPUT_CFG0_CFG_HCSL25:
748
+ clk_out->clk_output_cfg0 |=
749
+ value << VC5_CLK_OUTPUT_CFG0_CFG_SHIFT;
750
+ break;
751
+ default:
752
+ return -EINVAL;
753
+ }
754
+ }
755
+ return 0;
756
+}
757
+
758
+static int vc5_update_power(struct device_node *np_output,
759
+ struct vc5_out_data *clk_out)
760
+{
761
+ u32 value;
762
+
763
+ if (!of_property_read_u32(np_output, "idt,voltage-microvolt",
764
+ &value)) {
765
+ clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_PWR_MASK;
766
+ switch (value) {
767
+ case 1800000:
768
+ clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_18;
769
+ break;
770
+ case 2500000:
771
+ clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_25;
772
+ break;
773
+ case 3300000:
774
+ clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_33;
775
+ break;
776
+ default:
777
+ return -EINVAL;
778
+ }
779
+ }
780
+ return 0;
781
+}
782
+
783
+static int vc5_update_slew(struct device_node *np_output,
784
+ struct vc5_out_data *clk_out)
785
+{
786
+ u32 value;
787
+
788
+ if (!of_property_read_u32(np_output, "idt,slew-percent", &value)) {
789
+ clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_SLEW_MASK;
790
+ switch (value) {
791
+ case 80:
792
+ clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_80;
793
+ break;
794
+ case 85:
795
+ clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_85;
796
+ break;
797
+ case 90:
798
+ clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_90;
799
+ break;
800
+ case 100:
801
+ clk_out->clk_output_cfg0 |=
802
+ VC5_CLK_OUTPUT_CFG0_SLEW_100;
803
+ break;
804
+ default:
805
+ return -EINVAL;
806
+ }
807
+ }
808
+ return 0;
809
+}
810
+
811
+static int vc5_get_output_config(struct i2c_client *client,
812
+ struct vc5_out_data *clk_out)
813
+{
814
+ struct device_node *np_output;
815
+ char *child_name;
816
+ int ret = 0;
817
+
818
+ child_name = kasprintf(GFP_KERNEL, "OUT%d", clk_out->num + 1);
819
+ if (!child_name)
820
+ return -ENOMEM;
821
+
822
+ np_output = of_get_child_by_name(client->dev.of_node, child_name);
823
+ kfree(child_name);
824
+ if (!np_output)
825
+ return 0;
826
+
827
+ ret = vc5_update_mode(np_output, clk_out);
828
+ if (ret)
829
+ goto output_error;
830
+
831
+ ret = vc5_update_power(np_output, clk_out);
832
+ if (ret)
833
+ goto output_error;
834
+
835
+ ret = vc5_update_slew(np_output, clk_out);
836
+
837
+output_error:
838
+ if (ret) {
839
+ dev_err(&client->dev,
840
+ "Invalid clock output configuration OUT%d\n",
841
+ clk_out->num + 1);
842
+ }
843
+
844
+ of_node_put(np_output);
845
+
846
+ return ret;
847
+}
848
+
700849 static const struct of_device_id clk_vc5_of_match[];
701850
702
-static int vc5_probe(struct i2c_client *client,
703
- const struct i2c_device_id *id)
851
+static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id)
704852 {
705853 struct vc5_driver_data *vc5;
706
- struct clk_init_data init = {};
854
+ struct clk_init_data init;
707855 const char *parent_names[2];
708856 unsigned int n, idx = 0;
709857 int ret;
710858
711859 vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL);
712
- if (vc5 == NULL)
860
+ if (!vc5)
713861 return -ENOMEM;
714862
715863 i2c_set_clientdata(client, vc5);
....@@ -749,7 +897,7 @@
749897 if (!IS_ERR(vc5->pin_clkin)) {
750898 vc5->clk_mux_ins |= VC5_MUX_IN_CLKIN;
751899 parent_names[init.num_parents++] =
752
- __clk_get_name(vc5->pin_clkin);
900
+ __clk_get_name(vc5->pin_clkin);
753901 }
754902
755903 if (!init.num_parents) {
....@@ -757,115 +905,116 @@
757905 return -EINVAL;
758906 }
759907
760
- init.name = vc5_mux_names[0];
908
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node);
761909 init.ops = &vc5_mux_ops;
762910 init.flags = 0;
763911 init.parent_names = parent_names;
764912 vc5->clk_mux.init = &init;
765913 ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux);
766
- if (ret) {
767
- dev_err(&client->dev, "unable to register %s\n", init.name);
768
- goto err_clk;
769
- }
914
+ if (ret)
915
+ goto err_clk_register;
916
+ kfree(init.name); /* clock framework made a copy of the name */
770917
771918 if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) {
772919 /* Register frequency doubler */
773920 memset(&init, 0, sizeof(init));
774
- init.name = vc5_dbl_names[0];
921
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl",
922
+ client->dev.of_node);
775923 init.ops = &vc5_dbl_ops;
776924 init.flags = CLK_SET_RATE_PARENT;
777
- init.parent_names = vc5_mux_names;
925
+ init.parent_names = parent_names;
926
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
778927 init.num_parents = 1;
779928 vc5->clk_mul.init = &init;
780929 ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul);
781
- if (ret) {
782
- dev_err(&client->dev, "unable to register %s\n",
783
- init.name);
784
- goto err_clk;
785
- }
930
+ if (ret)
931
+ goto err_clk_register;
932
+ kfree(init.name); /* clock framework made a copy of the name */
786933 }
787934
788935 /* Register PFD */
789936 memset(&init, 0, sizeof(init));
790
- init.name = vc5_pfd_names[0];
937
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node);
791938 init.ops = &vc5_pfd_ops;
792939 init.flags = CLK_SET_RATE_PARENT;
940
+ init.parent_names = parent_names;
793941 if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL)
794
- init.parent_names = vc5_dbl_names;
942
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mul);
795943 else
796
- init.parent_names = vc5_mux_names;
944
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
797945 init.num_parents = 1;
798946 vc5->clk_pfd.init = &init;
799947 ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd);
800
- if (ret) {
801
- dev_err(&client->dev, "unable to register %s\n", init.name);
802
- goto err_clk;
803
- }
948
+ if (ret)
949
+ goto err_clk_register;
950
+ kfree(init.name); /* clock framework made a copy of the name */
804951
805952 /* Register PLL */
806953 memset(&init, 0, sizeof(init));
807
- init.name = vc5_pll_names[0];
954
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node);
808955 init.ops = &vc5_pll_ops;
809956 init.flags = CLK_SET_RATE_PARENT;
810
- init.parent_names = vc5_pfd_names;
957
+ init.parent_names = parent_names;
958
+ parent_names[0] = clk_hw_get_name(&vc5->clk_pfd);
811959 init.num_parents = 1;
812960 vc5->clk_pll.num = 0;
813961 vc5->clk_pll.vc5 = vc5;
814962 vc5->clk_pll.hw.init = &init;
815963 ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw);
816
- if (ret) {
817
- dev_err(&client->dev, "unable to register %s\n", init.name);
818
- goto err_clk;
819
- }
964
+ if (ret)
965
+ goto err_clk_register;
966
+ kfree(init.name); /* clock framework made a copy of the name */
820967
821968 /* Register FODs */
822969 for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) {
823970 idx = vc5_map_index_to_output(vc5->chip_info->model, n);
824971 memset(&init, 0, sizeof(init));
825
- init.name = vc5_fod_names[idx];
972
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d",
973
+ client->dev.of_node, idx);
826974 init.ops = &vc5_fod_ops;
827975 init.flags = CLK_SET_RATE_PARENT;
828
- init.parent_names = vc5_pll_names;
976
+ init.parent_names = parent_names;
977
+ parent_names[0] = clk_hw_get_name(&vc5->clk_pll.hw);
829978 init.num_parents = 1;
830979 vc5->clk_fod[n].num = idx;
831980 vc5->clk_fod[n].vc5 = vc5;
832981 vc5->clk_fod[n].hw.init = &init;
833982 ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw);
834
- if (ret) {
835
- dev_err(&client->dev, "unable to register %s\n",
836
- init.name);
837
- goto err_clk;
838
- }
983
+ if (ret)
984
+ goto err_clk_register;
985
+ kfree(init.name); /* clock framework made a copy of the name */
839986 }
840987
841988 /* Register MUX-connected OUT0_I2C_SELB output */
842989 memset(&init, 0, sizeof(init));
843
- init.name = vc5_clk_out_names[0];
990
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb",
991
+ client->dev.of_node);
844992 init.ops = &vc5_clk_out_ops;
845993 init.flags = CLK_SET_RATE_PARENT;
846
- init.parent_names = vc5_mux_names;
994
+ init.parent_names = parent_names;
995
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
847996 init.num_parents = 1;
848997 vc5->clk_out[0].num = idx;
849998 vc5->clk_out[0].vc5 = vc5;
850999 vc5->clk_out[0].hw.init = &init;
8511000 ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw);
852
- if (ret) {
853
- dev_err(&client->dev, "unable to register %s\n",
854
- init.name);
855
- goto err_clk;
856
- }
1001
+ if (ret)
1002
+ goto err_clk_register;
1003
+ kfree(init.name); /* clock framework made a copy of the name */
8571004
8581005 /* Register FOD-connected OUTx outputs */
8591006 for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) {
8601007 idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1);
861
- parent_names[0] = vc5_fod_names[idx];
1008
+ parent_names[0] = clk_hw_get_name(&vc5->clk_fod[idx].hw);
8621009 if (n == 1)
863
- parent_names[1] = vc5_mux_names[0];
1010
+ parent_names[1] = clk_hw_get_name(&vc5->clk_mux);
8641011 else
865
- parent_names[1] = vc5_clk_out_names[n - 1];
1012
+ parent_names[1] =
1013
+ clk_hw_get_name(&vc5->clk_out[n - 1].hw);
8661014
8671015 memset(&init, 0, sizeof(init));
868
- init.name = vc5_clk_out_names[idx + 1];
1016
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d",
1017
+ client->dev.of_node, idx + 1);
8691018 init.ops = &vc5_clk_out_ops;
8701019 init.flags = CLK_SET_RATE_PARENT;
8711020 init.parent_names = parent_names;
....@@ -873,13 +1022,15 @@
8731022 vc5->clk_out[n].num = idx;
8741023 vc5->clk_out[n].vc5 = vc5;
8751024 vc5->clk_out[n].hw.init = &init;
876
- ret = devm_clk_hw_register(&client->dev,
877
- &vc5->clk_out[n].hw);
878
- if (ret) {
879
- dev_err(&client->dev, "unable to register %s\n",
880
- init.name);
1025
+ ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw);
1026
+ if (ret)
1027
+ goto err_clk_register;
1028
+ kfree(init.name); /* clock framework made a copy of the name */
1029
+
1030
+ /* Fetch Clock Output configuration from DT (if specified) */
1031
+ ret = vc5_get_output_config(client, &vc5->clk_out[n]);
1032
+ if (ret)
8811033 goto err_clk;
882
- }
8831034 }
8841035
8851036 ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5);
....@@ -890,6 +1041,9 @@
8901041
8911042 return 0;
8921043
1044
+err_clk_register:
1045
+ dev_err(&client->dev, "unable to register %s\n", init.name);
1046
+ kfree(init.name); /* clock framework made a copy of the name */
8931047 err_clk:
8941048 if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
8951049 clk_unregister_fixed_rate(vc5->pin_xin);
....@@ -906,6 +1060,28 @@
9061060 clk_unregister_fixed_rate(vc5->pin_xin);
9071061
9081062 return 0;
1063
+}
1064
+
1065
+static int __maybe_unused vc5_suspend(struct device *dev)
1066
+{
1067
+ struct vc5_driver_data *vc5 = dev_get_drvdata(dev);
1068
+
1069
+ regcache_cache_only(vc5->regmap, true);
1070
+ regcache_mark_dirty(vc5->regmap);
1071
+
1072
+ return 0;
1073
+}
1074
+
1075
+static int __maybe_unused vc5_resume(struct device *dev)
1076
+{
1077
+ struct vc5_driver_data *vc5 = dev_get_drvdata(dev);
1078
+ int ret;
1079
+
1080
+ regcache_cache_only(vc5->regmap, false);
1081
+ ret = regcache_sync(vc5->regmap);
1082
+ if (ret)
1083
+ dev_err(dev, "Failed to restore register map: %d\n", ret);
1084
+ return ret;
9091085 }
9101086
9111087 static const struct vc5_chip_info idt_5p49v5923_info = {
....@@ -940,7 +1116,14 @@
9401116 .model = IDT_VC6_5P49V6901,
9411117 .clk_fod_cnt = 4,
9421118 .clk_out_cnt = 5,
943
- .flags = VC5_HAS_PFD_FREQ_DBL,
1119
+ .flags = VC5_HAS_PFD_FREQ_DBL | VC5_HAS_BYPASS_SYNC_BIT,
1120
+};
1121
+
1122
+static const struct vc5_chip_info idt_5p49v6965_info = {
1123
+ .model = IDT_VC6_5P49V6965,
1124
+ .clk_fod_cnt = 4,
1125
+ .clk_out_cnt = 5,
1126
+ .flags = VC5_HAS_BYPASS_SYNC_BIT,
9441127 };
9451128
9461129 static const struct i2c_device_id vc5_id[] = {
....@@ -949,6 +1132,7 @@
9491132 { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 },
9501133 { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 },
9511134 { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 },
1135
+ { "5p49v6965", .driver_data = IDT_VC6_5P49V6965 },
9521136 { }
9531137 };
9541138 MODULE_DEVICE_TABLE(i2c, vc5_id);
....@@ -959,13 +1143,17 @@
9591143 { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info },
9601144 { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info },
9611145 { .compatible = "idt,5p49v6901", .data = &idt_5p49v6901_info },
1146
+ { .compatible = "idt,5p49v6965", .data = &idt_5p49v6965_info },
9621147 { },
9631148 };
9641149 MODULE_DEVICE_TABLE(of, clk_vc5_of_match);
9651150
1151
+static SIMPLE_DEV_PM_OPS(vc5_pm_ops, vc5_suspend, vc5_resume);
1152
+
9661153 static struct i2c_driver vc5_driver = {
9671154 .driver = {
9681155 .name = "vc5",
1156
+ .pm = &vc5_pm_ops,
9691157 .of_match_table = clk_vc5_of_match,
9701158 },
9711159 .probe = vc5_probe,