1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * PHY package support 4 */ 5 6 #include <linux/of.h> 7 #include <linux/phy.h> 8 9 #include "phylib.h" 10 #include "phylib-internal.h" 11 12 /** 13 * struct phy_package_shared - Shared information in PHY packages 14 * @base_addr: Base PHY address of PHY package used to combine PHYs 15 * in one package and for offset calculation of phy_package_read/write 16 * @np: Pointer to the Device Node if PHY package defined in DT 17 * @refcnt: Number of PHYs connected to this shared data 18 * @flags: Initialization of PHY package 19 * @priv_size: Size of the shared private data @priv 20 * @priv: Driver private data shared across a PHY package 21 * 22 * Represents a shared structure between different phydev's in the same 23 * package, for example a quad PHY. See phy_package_join() and 24 * phy_package_leave(). 25 */ 26 struct phy_package_shared { 27 u8 base_addr; 28 /* With PHY package defined in DT this points to the PHY package node */ 29 struct device_node *np; 30 refcount_t refcnt; 31 unsigned long flags; 32 size_t priv_size; 33 34 /* private data pointer */ 35 /* note that this pointer is shared between different phydevs and 36 * the user has to take care of appropriate locking. It is allocated 37 * and freed automatically by phy_package_join() and 38 * phy_package_leave(). 39 */ 40 void *priv; 41 }; 42 43 struct device_node *phy_package_get_node(struct phy_device *phydev) 44 { 45 return phydev->shared->np; 46 } 47 EXPORT_SYMBOL_GPL(phy_package_get_node); 48 49 void *phy_package_get_priv(struct phy_device *phydev) 50 { 51 return phydev->shared->priv; 52 } 53 EXPORT_SYMBOL_GPL(phy_package_get_priv); 54 55 static int phy_package_address(struct phy_device *phydev, 56 unsigned int addr_offset) 57 { 58 struct phy_package_shared *shared = phydev->shared; 59 u8 base_addr = shared->base_addr; 60 61 if (addr_offset >= PHY_MAX_ADDR - base_addr) 62 return -EIO; 63 64 /* we know that addr will be in the range 0..31 and thus the 65 * implicit cast to a signed int is not a problem. 66 */ 67 return base_addr + addr_offset; 68 } 69 70 int __phy_package_read(struct phy_device *phydev, unsigned int addr_offset, 71 u32 regnum) 72 { 73 int addr = phy_package_address(phydev, addr_offset); 74 75 if (addr < 0) 76 return addr; 77 78 return __mdiobus_read(phydev->mdio.bus, addr, regnum); 79 } 80 EXPORT_SYMBOL_GPL(__phy_package_read); 81 82 int __phy_package_write(struct phy_device *phydev, unsigned int addr_offset, 83 u32 regnum, u16 val) 84 { 85 int addr = phy_package_address(phydev, addr_offset); 86 87 if (addr < 0) 88 return addr; 89 90 return __mdiobus_write(phydev->mdio.bus, addr, regnum, val); 91 } 92 EXPORT_SYMBOL_GPL(__phy_package_write); 93 94 /** 95 * __phy_package_read_mmd - read MMD reg relative to PHY package base addr 96 * @phydev: The phy_device struct 97 * @addr_offset: The offset to be added to PHY package base_addr 98 * @devad: The MMD to read from 99 * @regnum: The register on the MMD to read 100 * 101 * Convenience helper for reading a register of an MMD on a given PHY 102 * using the PHY package base address. The base address is added to 103 * the addr_offset value. 104 * 105 * Same calling rules as for __phy_read(); 106 * 107 * NOTE: It's assumed that the entire PHY package is either C22 or C45. 108 */ 109 int __phy_package_read_mmd(struct phy_device *phydev, 110 unsigned int addr_offset, int devad, 111 u32 regnum) 112 { 113 int addr = phy_package_address(phydev, addr_offset); 114 115 if (addr < 0) 116 return addr; 117 118 if (regnum > (u16)~0 || devad > 32) 119 return -EINVAL; 120 121 return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad, 122 regnum); 123 } 124 EXPORT_SYMBOL(__phy_package_read_mmd); 125 126 /** 127 * __phy_package_write_mmd - write MMD reg relative to PHY package base addr 128 * @phydev: The phy_device struct 129 * @addr_offset: The offset to be added to PHY package base_addr 130 * @devad: The MMD to write to 131 * @regnum: The register on the MMD to write 132 * @val: value to write to @regnum 133 * 134 * Convenience helper for writing a register of an MMD on a given PHY 135 * using the PHY package base address. The base address is added to 136 * the addr_offset value. 137 * 138 * Same calling rules as for __phy_write(); 139 * 140 * NOTE: It's assumed that the entire PHY package is either C22 or C45. 141 */ 142 int __phy_package_write_mmd(struct phy_device *phydev, 143 unsigned int addr_offset, int devad, 144 u32 regnum, u16 val) 145 { 146 int addr = phy_package_address(phydev, addr_offset); 147 148 if (addr < 0) 149 return addr; 150 151 if (regnum > (u16)~0 || devad > 32) 152 return -EINVAL; 153 154 return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad, 155 regnum, val); 156 } 157 EXPORT_SYMBOL(__phy_package_write_mmd); 158 159 static bool __phy_package_set_once(struct phy_device *phydev, unsigned int b) 160 { 161 struct phy_package_shared *shared = phydev->shared; 162 163 if (!shared) 164 return false; 165 166 return !test_and_set_bit(b, &shared->flags); 167 } 168 169 bool phy_package_init_once(struct phy_device *phydev) 170 { 171 return __phy_package_set_once(phydev, 0); 172 } 173 EXPORT_SYMBOL_GPL(phy_package_init_once); 174 175 bool phy_package_probe_once(struct phy_device *phydev) 176 { 177 return __phy_package_set_once(phydev, 1); 178 } 179 EXPORT_SYMBOL_GPL(phy_package_probe_once); 180 181 /** 182 * phy_package_join - join a common PHY group 183 * @phydev: target phy_device struct 184 * @base_addr: cookie and base PHY address of PHY package for offset 185 * calculation of global register access 186 * @priv_size: if non-zero allocate this amount of bytes for private data 187 * 188 * This joins a PHY group and provides a shared storage for all phydevs in 189 * this group. This is intended to be used for packages which contain 190 * more than one PHY, for example a quad PHY transceiver. 191 * 192 * The base_addr parameter serves as cookie which has to have the same values 193 * for all members of one group and as the base PHY address of the PHY package 194 * for offset calculation to access generic registers of a PHY package. 195 * Usually, one of the PHY addresses of the different PHYs in the package 196 * provides access to these global registers. 197 * The address which is given here, will be used in the phy_package_read() 198 * and phy_package_write() convenience functions as base and added to the 199 * passed offset in those functions. 200 * 201 * This will set the shared pointer of the phydev to the shared storage. 202 * If this is the first call for a this cookie the shared storage will be 203 * allocated. If priv_size is non-zero, the given amount of bytes are 204 * allocated for the priv member. 205 * 206 * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() 207 * with the same cookie but a different priv_size is an error. 208 */ 209 int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size) 210 { 211 struct mii_bus *bus = phydev->mdio.bus; 212 struct phy_package_shared *shared; 213 int ret; 214 215 if (base_addr < 0 || base_addr >= PHY_MAX_ADDR) 216 return -EINVAL; 217 218 mutex_lock(&bus->shared_lock); 219 shared = bus->shared[base_addr]; 220 if (!shared) { 221 ret = -ENOMEM; 222 shared = kzalloc(sizeof(*shared), GFP_KERNEL); 223 if (!shared) 224 goto err_unlock; 225 if (priv_size) { 226 shared->priv = kzalloc(priv_size, GFP_KERNEL); 227 if (!shared->priv) 228 goto err_free; 229 shared->priv_size = priv_size; 230 } 231 shared->base_addr = base_addr; 232 shared->np = NULL; 233 refcount_set(&shared->refcnt, 1); 234 bus->shared[base_addr] = shared; 235 } else { 236 ret = -EINVAL; 237 if (priv_size && priv_size != shared->priv_size) 238 goto err_unlock; 239 refcount_inc(&shared->refcnt); 240 } 241 mutex_unlock(&bus->shared_lock); 242 243 phydev->shared = shared; 244 245 return 0; 246 247 err_free: 248 kfree(shared); 249 err_unlock: 250 mutex_unlock(&bus->shared_lock); 251 return ret; 252 } 253 EXPORT_SYMBOL_GPL(phy_package_join); 254 255 /** 256 * of_phy_package_join - join a common PHY group in PHY package 257 * @phydev: target phy_device struct 258 * @priv_size: if non-zero allocate this amount of bytes for private data 259 * 260 * This is a variant of phy_package_join for PHY package defined in DT. 261 * 262 * The parent node of the @phydev is checked as a valid PHY package node 263 * structure (by matching the node name "ethernet-phy-package") and the 264 * base_addr for the PHY package is passed to phy_package_join. 265 * 266 * With this configuration the shared struct will also have the np value 267 * filled to use additional DT defined properties in PHY specific 268 * probe_once and config_init_once PHY package OPs. 269 * 270 * Returns < 0 on error, 0 on success. Esp. calling phy_package_join() 271 * with the same cookie but a different priv_size is an error. Or a parent 272 * node is not detected or is not valid or doesn't match the expected node 273 * name for PHY package. 274 */ 275 int of_phy_package_join(struct phy_device *phydev, size_t priv_size) 276 { 277 struct device_node *node = phydev->mdio.dev.of_node; 278 struct device_node *package_node; 279 u32 base_addr; 280 int ret; 281 282 if (!node) 283 return -EINVAL; 284 285 package_node = of_get_parent(node); 286 if (!package_node) 287 return -EINVAL; 288 289 if (!of_node_name_eq(package_node, "ethernet-phy-package")) { 290 ret = -EINVAL; 291 goto exit; 292 } 293 294 if (of_property_read_u32(package_node, "reg", &base_addr)) { 295 ret = -EINVAL; 296 goto exit; 297 } 298 299 ret = phy_package_join(phydev, base_addr, priv_size); 300 if (ret) 301 goto exit; 302 303 phydev->shared->np = package_node; 304 305 return 0; 306 exit: 307 of_node_put(package_node); 308 return ret; 309 } 310 EXPORT_SYMBOL_GPL(of_phy_package_join); 311 312 /** 313 * phy_package_leave - leave a common PHY group 314 * @phydev: target phy_device struct 315 * 316 * This leaves a PHY group created by phy_package_join(). If this phydev 317 * was the last user of the shared data between the group, this data is 318 * freed. Resets the phydev->shared pointer to NULL. 319 */ 320 void phy_package_leave(struct phy_device *phydev) 321 { 322 struct phy_package_shared *shared = phydev->shared; 323 struct mii_bus *bus = phydev->mdio.bus; 324 325 if (!shared) 326 return; 327 328 /* Decrease the node refcount on leave if present */ 329 if (shared->np) 330 of_node_put(shared->np); 331 332 if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { 333 bus->shared[shared->base_addr] = NULL; 334 mutex_unlock(&bus->shared_lock); 335 kfree(shared->priv); 336 kfree(shared); 337 } 338 339 phydev->shared = NULL; 340 } 341 EXPORT_SYMBOL_GPL(phy_package_leave); 342 343 static void devm_phy_package_leave(struct device *dev, void *res) 344 { 345 phy_package_leave(*(struct phy_device **)res); 346 } 347 348 /** 349 * devm_phy_package_join - resource managed phy_package_join() 350 * @dev: device that is registering this PHY package 351 * @phydev: target phy_device struct 352 * @base_addr: cookie and base PHY address of PHY package for offset 353 * calculation of global register access 354 * @priv_size: if non-zero allocate this amount of bytes for private data 355 * 356 * Managed phy_package_join(). Shared storage fetched by this function, 357 * phy_package_leave() is automatically called on driver detach. See 358 * phy_package_join() for more information. 359 */ 360 int devm_phy_package_join(struct device *dev, struct phy_device *phydev, 361 int base_addr, size_t priv_size) 362 { 363 struct phy_device **ptr; 364 int ret; 365 366 ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), 367 GFP_KERNEL); 368 if (!ptr) 369 return -ENOMEM; 370 371 ret = phy_package_join(phydev, base_addr, priv_size); 372 373 if (!ret) { 374 *ptr = phydev; 375 devres_add(dev, ptr); 376 } else { 377 devres_free(ptr); 378 } 379 380 return ret; 381 } 382 EXPORT_SYMBOL_GPL(devm_phy_package_join); 383 384 /** 385 * devm_of_phy_package_join - resource managed of_phy_package_join() 386 * @dev: device that is registering this PHY package 387 * @phydev: target phy_device struct 388 * @priv_size: if non-zero allocate this amount of bytes for private data 389 * 390 * Managed of_phy_package_join(). Shared storage fetched by this function, 391 * phy_package_leave() is automatically called on driver detach. See 392 * of_phy_package_join() for more information. 393 */ 394 int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, 395 size_t priv_size) 396 { 397 struct phy_device **ptr; 398 int ret; 399 400 ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), 401 GFP_KERNEL); 402 if (!ptr) 403 return -ENOMEM; 404 405 ret = of_phy_package_join(phydev, priv_size); 406 407 if (!ret) { 408 *ptr = phydev; 409 devres_add(dev, ptr); 410 } else { 411 devres_free(ptr); 412 } 413 414 return ret; 415 } 416 EXPORT_SYMBOL_GPL(devm_of_phy_package_join); 417 418 MODULE_DESCRIPTION("PHY package support"); 419 MODULE_LICENSE("GPL"); 420