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