xref: /linux/drivers/phy/phy-common-props.c (revision d8f87aa5fa0a4276491fa8ef436cd22605a3f9ba)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * phy-common-props.c  --  Common PHY properties
4  *
5  * Copyright 2025-2026 NXP
6  */
7 #include <linux/export.h>
8 #include <linux/fwnode.h>
9 #include <linux/phy/phy-common-props.h>
10 #include <linux/printk.h>
11 #include <linux/property.h>
12 #include <linux/slab.h>
13 
14 /**
15  * fwnode_get_u32_prop_for_name - Find u32 property by name, or default value
16  * @fwnode: Pointer to firmware node, or NULL to use @default_val
17  * @name: Property name used as lookup key in @names_title (must not be NULL)
18  * @props_title: Name of u32 array property holding values
19  * @names_title: Name of string array property holding lookup keys
20  * @default_val: Default value if @fwnode is NULL or @props_title is empty
21  * @val: Pointer to store the returned value
22  *
23  * This function retrieves a u32 value from @props_title based on a name lookup
24  * in @names_title. The value stored in @val is determined as follows:
25  *
26  * - If @fwnode is NULL or @props_title is empty: @default_val is used
27  * - If @props_title has exactly one element and @names_title is empty:
28  *   that element is used
29  * - Otherwise: @val is set to the element at the same index where @name is
30  *   found in @names_title.
31  * - If @name is not found, the function looks for a "default" entry in
32  *   @names_title and uses the corresponding value from @props_title
33  *
34  * When both @props_title and @names_title are present, they must have the
35  * same number of elements (except when @props_title has exactly one element).
36  *
37  * Return: zero on success, negative error on failure.
38  */
39 static int fwnode_get_u32_prop_for_name(struct fwnode_handle *fwnode,
40 					const char *name,
41 					const char *props_title,
42 					const char *names_title,
43 					unsigned int default_val,
44 					unsigned int *val)
45 {
46 	int err, n_props, n_names, idx;
47 	u32 *props;
48 
49 	if (!name) {
50 		pr_err("Lookup key inside \"%s\" is mandatory\n", names_title);
51 		return -EINVAL;
52 	}
53 
54 	n_props = fwnode_property_count_u32(fwnode, props_title);
55 	if (n_props <= 0) {
56 		/* fwnode is NULL, or is missing requested property */
57 		*val = default_val;
58 		return 0;
59 	}
60 
61 	n_names = fwnode_property_string_array_count(fwnode, names_title);
62 	if (n_names >= 0 && n_props != n_names) {
63 		pr_err("%pfw mismatch between \"%s\" and \"%s\" property count (%d vs %d)\n",
64 		       fwnode, props_title, names_title, n_props, n_names);
65 		return -EINVAL;
66 	}
67 
68 	idx = fwnode_property_match_string(fwnode, names_title, name);
69 	if (idx < 0)
70 		idx = fwnode_property_match_string(fwnode, names_title, "default");
71 	/*
72 	 * If the mode name is missing, it can only mean the specified property
73 	 * is the default one for all modes, so reject any other property count
74 	 * than 1.
75 	 */
76 	if (idx < 0 && n_props != 1) {
77 		pr_err("%pfw \"%s \" property has %d elements, but cannot find \"%s\" in \"%s\" and there is no default value\n",
78 		       fwnode, props_title, n_props, name, names_title);
79 		return -EINVAL;
80 	}
81 
82 	if (n_props == 1) {
83 		err = fwnode_property_read_u32(fwnode, props_title, val);
84 		if (err)
85 			return err;
86 
87 		return 0;
88 	}
89 
90 	/* We implicitly know idx >= 0 here */
91 	props = kcalloc(n_props, sizeof(*props), GFP_KERNEL);
92 	if (!props)
93 		return -ENOMEM;
94 
95 	err = fwnode_property_read_u32_array(fwnode, props_title, props, n_props);
96 	if (err >= 0)
97 		*val = props[idx];
98 
99 	kfree(props);
100 
101 	return err;
102 }
103 
104 static int phy_get_polarity_for_mode(struct fwnode_handle *fwnode,
105 				     const char *mode_name,
106 				     unsigned int supported,
107 				     unsigned int default_val,
108 				     const char *polarity_prop,
109 				     const char *names_prop,
110 				     unsigned int *val)
111 {
112 	int err;
113 
114 	err = fwnode_get_u32_prop_for_name(fwnode, mode_name, polarity_prop,
115 					   names_prop, default_val, val);
116 	if (err)
117 		return err;
118 
119 	if (!(supported & BIT(*val))) {
120 		pr_err("%d is not a supported value for %pfw '%s' element '%s'\n",
121 		       *val, fwnode, polarity_prop, mode_name);
122 		err = -EOPNOTSUPP;
123 	}
124 
125 	return err;
126 }
127 
128 /**
129  * phy_get_rx_polarity - Get RX polarity for PHY differential lane
130  * @fwnode: Pointer to the PHY's firmware node.
131  * @mode_name: The name of the PHY mode to look up.
132  * @supported: Bit mask of PHY_POL_NORMAL, PHY_POL_INVERT and PHY_POL_AUTO
133  * @default_val: Default polarity value if property is missing
134  * @val: Pointer to returned polarity.
135  *
136  * Return: zero on success, negative error on failure.
137  */
138 int __must_check phy_get_rx_polarity(struct fwnode_handle *fwnode,
139 				     const char *mode_name,
140 				     unsigned int supported,
141 				     unsigned int default_val,
142 				     unsigned int *val)
143 {
144 	return phy_get_polarity_for_mode(fwnode, mode_name, supported,
145 					 default_val, "rx-polarity",
146 					 "rx-polarity-names", val);
147 }
148 EXPORT_SYMBOL_GPL(phy_get_rx_polarity);
149 
150 /**
151  * phy_get_tx_polarity - Get TX polarity for PHY differential lane
152  * @fwnode: Pointer to the PHY's firmware node.
153  * @mode_name: The name of the PHY mode to look up.
154  * @supported: Bit mask of PHY_POL_NORMAL and PHY_POL_INVERT
155  * @default_val: Default polarity value if property is missing
156  * @val: Pointer to returned polarity.
157  *
158  * Return: zero on success, negative error on failure.
159  */
160 int __must_check phy_get_tx_polarity(struct fwnode_handle *fwnode,
161 				     const char *mode_name, unsigned int supported,
162 				     unsigned int default_val, unsigned int *val)
163 {
164 	return phy_get_polarity_for_mode(fwnode, mode_name, supported,
165 					 default_val, "tx-polarity",
166 					 "tx-polarity-names", val);
167 }
168 EXPORT_SYMBOL_GPL(phy_get_tx_polarity);
169 
170 /**
171  * phy_get_manual_rx_polarity - Get manual RX polarity for PHY differential lane
172  * @fwnode: Pointer to the PHY's firmware node.
173  * @mode_name: The name of the PHY mode to look up.
174  * @val: Pointer to returned polarity.
175  *
176  * Helper for PHYs which do not support protocols with automatic RX polarity
177  * detection and correction.
178  *
179  * Return: zero on success, negative error on failure.
180  */
181 int __must_check phy_get_manual_rx_polarity(struct fwnode_handle *fwnode,
182 					    const char *mode_name,
183 					    unsigned int *val)
184 {
185 	return phy_get_rx_polarity(fwnode, mode_name,
186 				   BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT),
187 				   PHY_POL_NORMAL, val);
188 }
189 EXPORT_SYMBOL_GPL(phy_get_manual_rx_polarity);
190 
191 /**
192  * phy_get_manual_tx_polarity - Get manual TX polarity for PHY differential lane
193  * @fwnode: Pointer to the PHY's firmware node.
194  * @mode_name: The name of the PHY mode to look up.
195  * @val: Pointer to returned polarity.
196  *
197  * Helper for PHYs without any custom default value for the TX polarity.
198  *
199  * Return: zero on success, negative error on failure.
200  */
201 int __must_check phy_get_manual_tx_polarity(struct fwnode_handle *fwnode,
202 					    const char *mode_name,
203 					    unsigned int *val)
204 {
205 	return phy_get_tx_polarity(fwnode, mode_name,
206 				   BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT),
207 				   PHY_POL_NORMAL, val);
208 }
209 EXPORT_SYMBOL_GPL(phy_get_manual_tx_polarity);
210