hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
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,145 @@
757905 return -EINVAL;
758906 }
759907
760
- init.name = vc5_mux_names[0];
908
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node);
909
+ if (!init.name) {
910
+ ret = -ENOMEM;
911
+ goto err_clk;
912
+ }
913
+
761914 init.ops = &vc5_mux_ops;
762915 init.flags = 0;
763916 init.parent_names = parent_names;
764917 vc5->clk_mux.init = &init;
765918 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
- }
919
+ if (ret)
920
+ goto err_clk_register;
921
+ kfree(init.name); /* clock framework made a copy of the name */
770922
771923 if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) {
772924 /* Register frequency doubler */
773925 memset(&init, 0, sizeof(init));
774
- init.name = vc5_dbl_names[0];
926
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl",
927
+ client->dev.of_node);
928
+ if (!init.name) {
929
+ ret = -ENOMEM;
930
+ goto err_clk;
931
+ }
775932 init.ops = &vc5_dbl_ops;
776933 init.flags = CLK_SET_RATE_PARENT;
777
- init.parent_names = vc5_mux_names;
934
+ init.parent_names = parent_names;
935
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
778936 init.num_parents = 1;
779937 vc5->clk_mul.init = &init;
780938 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
- }
939
+ if (ret)
940
+ goto err_clk_register;
941
+ kfree(init.name); /* clock framework made a copy of the name */
786942 }
787943
788944 /* Register PFD */
789945 memset(&init, 0, sizeof(init));
790
- init.name = vc5_pfd_names[0];
946
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node);
947
+ if (!init.name) {
948
+ ret = -ENOMEM;
949
+ goto err_clk;
950
+ }
791951 init.ops = &vc5_pfd_ops;
792952 init.flags = CLK_SET_RATE_PARENT;
953
+ init.parent_names = parent_names;
793954 if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL)
794
- init.parent_names = vc5_dbl_names;
955
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mul);
795956 else
796
- init.parent_names = vc5_mux_names;
957
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
797958 init.num_parents = 1;
798959 vc5->clk_pfd.init = &init;
799960 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
- }
961
+ if (ret)
962
+ goto err_clk_register;
963
+ kfree(init.name); /* clock framework made a copy of the name */
804964
805965 /* Register PLL */
806966 memset(&init, 0, sizeof(init));
807
- init.name = vc5_pll_names[0];
967
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node);
968
+ if (!init.name) {
969
+ ret = -ENOMEM;
970
+ goto err_clk;
971
+ }
808972 init.ops = &vc5_pll_ops;
809973 init.flags = CLK_SET_RATE_PARENT;
810
- init.parent_names = vc5_pfd_names;
974
+ init.parent_names = parent_names;
975
+ parent_names[0] = clk_hw_get_name(&vc5->clk_pfd);
811976 init.num_parents = 1;
812977 vc5->clk_pll.num = 0;
813978 vc5->clk_pll.vc5 = vc5;
814979 vc5->clk_pll.hw.init = &init;
815980 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
- }
981
+ if (ret)
982
+ goto err_clk_register;
983
+ kfree(init.name); /* clock framework made a copy of the name */
820984
821985 /* Register FODs */
822986 for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) {
823987 idx = vc5_map_index_to_output(vc5->chip_info->model, n);
824988 memset(&init, 0, sizeof(init));
825
- init.name = vc5_fod_names[idx];
989
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d",
990
+ client->dev.of_node, idx);
991
+ if (!init.name) {
992
+ ret = -ENOMEM;
993
+ goto err_clk;
994
+ }
826995 init.ops = &vc5_fod_ops;
827996 init.flags = CLK_SET_RATE_PARENT;
828
- init.parent_names = vc5_pll_names;
997
+ init.parent_names = parent_names;
998
+ parent_names[0] = clk_hw_get_name(&vc5->clk_pll.hw);
829999 init.num_parents = 1;
8301000 vc5->clk_fod[n].num = idx;
8311001 vc5->clk_fod[n].vc5 = vc5;
8321002 vc5->clk_fod[n].hw.init = &init;
8331003 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
- }
1004
+ if (ret)
1005
+ goto err_clk_register;
1006
+ kfree(init.name); /* clock framework made a copy of the name */
8391007 }
8401008
8411009 /* Register MUX-connected OUT0_I2C_SELB output */
8421010 memset(&init, 0, sizeof(init));
843
- init.name = vc5_clk_out_names[0];
1011
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb",
1012
+ client->dev.of_node);
1013
+ if (!init.name) {
1014
+ ret = -ENOMEM;
1015
+ goto err_clk;
1016
+ }
8441017 init.ops = &vc5_clk_out_ops;
8451018 init.flags = CLK_SET_RATE_PARENT;
846
- init.parent_names = vc5_mux_names;
1019
+ init.parent_names = parent_names;
1020
+ parent_names[0] = clk_hw_get_name(&vc5->clk_mux);
8471021 init.num_parents = 1;
8481022 vc5->clk_out[0].num = idx;
8491023 vc5->clk_out[0].vc5 = vc5;
8501024 vc5->clk_out[0].hw.init = &init;
8511025 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
- }
1026
+ if (ret)
1027
+ goto err_clk_register;
1028
+ kfree(init.name); /* clock framework made a copy of the name */
8571029
8581030 /* Register FOD-connected OUTx outputs */
8591031 for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) {
8601032 idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1);
861
- parent_names[0] = vc5_fod_names[idx];
1033
+ parent_names[0] = clk_hw_get_name(&vc5->clk_fod[idx].hw);
8621034 if (n == 1)
863
- parent_names[1] = vc5_mux_names[0];
1035
+ parent_names[1] = clk_hw_get_name(&vc5->clk_mux);
8641036 else
865
- parent_names[1] = vc5_clk_out_names[n - 1];
1037
+ parent_names[1] =
1038
+ clk_hw_get_name(&vc5->clk_out[n - 1].hw);
8661039
8671040 memset(&init, 0, sizeof(init));
868
- init.name = vc5_clk_out_names[idx + 1];
1041
+ init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d",
1042
+ client->dev.of_node, idx + 1);
1043
+ if (!init.name) {
1044
+ ret = -ENOMEM;
1045
+ goto err_clk;
1046
+ }
8691047 init.ops = &vc5_clk_out_ops;
8701048 init.flags = CLK_SET_RATE_PARENT;
8711049 init.parent_names = parent_names;
....@@ -873,13 +1051,15 @@
8731051 vc5->clk_out[n].num = idx;
8741052 vc5->clk_out[n].vc5 = vc5;
8751053 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);
1054
+ ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw);
1055
+ if (ret)
1056
+ goto err_clk_register;
1057
+ kfree(init.name); /* clock framework made a copy of the name */
1058
+
1059
+ /* Fetch Clock Output configuration from DT (if specified) */
1060
+ ret = vc5_get_output_config(client, &vc5->clk_out[n]);
1061
+ if (ret)
8811062 goto err_clk;
882
- }
8831063 }
8841064
8851065 ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5);
....@@ -890,6 +1070,9 @@
8901070
8911071 return 0;
8921072
1073
+err_clk_register:
1074
+ dev_err(&client->dev, "unable to register %s\n", init.name);
1075
+ kfree(init.name); /* clock framework made a copy of the name */
8931076 err_clk:
8941077 if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
8951078 clk_unregister_fixed_rate(vc5->pin_xin);
....@@ -906,6 +1089,28 @@
9061089 clk_unregister_fixed_rate(vc5->pin_xin);
9071090
9081091 return 0;
1092
+}
1093
+
1094
+static int __maybe_unused vc5_suspend(struct device *dev)
1095
+{
1096
+ struct vc5_driver_data *vc5 = dev_get_drvdata(dev);
1097
+
1098
+ regcache_cache_only(vc5->regmap, true);
1099
+ regcache_mark_dirty(vc5->regmap);
1100
+
1101
+ return 0;
1102
+}
1103
+
1104
+static int __maybe_unused vc5_resume(struct device *dev)
1105
+{
1106
+ struct vc5_driver_data *vc5 = dev_get_drvdata(dev);
1107
+ int ret;
1108
+
1109
+ regcache_cache_only(vc5->regmap, false);
1110
+ ret = regcache_sync(vc5->regmap);
1111
+ if (ret)
1112
+ dev_err(dev, "Failed to restore register map: %d\n", ret);
1113
+ return ret;
9091114 }
9101115
9111116 static const struct vc5_chip_info idt_5p49v5923_info = {
....@@ -940,7 +1145,14 @@
9401145 .model = IDT_VC6_5P49V6901,
9411146 .clk_fod_cnt = 4,
9421147 .clk_out_cnt = 5,
943
- .flags = VC5_HAS_PFD_FREQ_DBL,
1148
+ .flags = VC5_HAS_PFD_FREQ_DBL | VC5_HAS_BYPASS_SYNC_BIT,
1149
+};
1150
+
1151
+static const struct vc5_chip_info idt_5p49v6965_info = {
1152
+ .model = IDT_VC6_5P49V6965,
1153
+ .clk_fod_cnt = 4,
1154
+ .clk_out_cnt = 5,
1155
+ .flags = VC5_HAS_BYPASS_SYNC_BIT,
9441156 };
9451157
9461158 static const struct i2c_device_id vc5_id[] = {
....@@ -949,6 +1161,7 @@
9491161 { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 },
9501162 { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 },
9511163 { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 },
1164
+ { "5p49v6965", .driver_data = IDT_VC6_5P49V6965 },
9521165 { }
9531166 };
9541167 MODULE_DEVICE_TABLE(i2c, vc5_id);
....@@ -959,13 +1172,17 @@
9591172 { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info },
9601173 { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info },
9611174 { .compatible = "idt,5p49v6901", .data = &idt_5p49v6901_info },
1175
+ { .compatible = "idt,5p49v6965", .data = &idt_5p49v6965_info },
9621176 { },
9631177 };
9641178 MODULE_DEVICE_TABLE(of, clk_vc5_of_match);
9651179
1180
+static SIMPLE_DEV_PM_OPS(vc5_pm_ops, vc5_suspend, vc5_resume);
1181
+
9661182 static struct i2c_driver vc5_driver = {
9671183 .driver = {
9681184 .name = "vc5",
1185
+ .pm = &vc5_pm_ops,
9691186 .of_match_table = clk_vc5_of_match,
9701187 },
9711188 .probe = vc5_probe,