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