how does a PHY driver wildcard on PHY IDs from a .dts file?

Robert P. J. Day rpjday at crashcourse.ca
Wed Dec 12 04:57:02 EST 2018


  (note: could have asked this on the net ML or device tree ML but the
kn list has a lot of smart people so i'll throw it out here and hope
for the best.)

  from poking around PHY drivers lately, i can see how a PHY driver
can register to accept a wildcarded PHY ID pattern from a device tree
source file. here's an example from asix.c:

  #define PHY_ID_ASIX_AX88796B            0x003b1841

  ... snip ...

  static struct phy_driver asix_driver[] = { {
        .phy_id         = PHY_ID_ASIX_AX88796B,
        .name           = "Asix Electronics AX88796B",
        .phy_id_mask    = 0xfffffff0,
        .features       = PHY_BASIC_FEATURES,
        .soft_reset     = asix_soft_reset,
  } };

  module_phy_driver(asix_driver);

  static struct mdio_device_id __maybe_unused asix_tbl[] = {
        { PHY_ID_ASIX_AX88796B, 0xfffffff0 },
        { }
  };

so that represents a vendor (asix) whose precise PHY types are
distinguished by the value in the last nybble. what this means (as i
read it) is that, when creating a .dts file for a system, one would
put *precisely* the PHY ID in the .dts file, and the wildcarding in
the driver would be used to associate that entry with the appropriate
driver so that, in the above, any PHY ID value of the form 0x003b184X
(X being the low-order nybble) would map to this driver, correct?

  in addition, once the mdio_device_id array defines the PHY ID
patterns compatible with this driver, the phy_driver array defines,
based on the *actual* PHY ID, how to initialize for that specific PHY
type, and that is based on the fact that the device tree source files
provide the *exact* PHY type. does all this sound right so far?
because here's the extra complication, so i've phrased it as a kind of
puzzle.

  say i want to build an 8-port switch using PHYs from the acme
corporation of coyote falls, arizona. acme has four different PHYs
with different speeds, with the precise PHY IDs:

  0x1234.5671	1G
  0x1234.5672	2.5G
  0x1234.5675	5G
  0x1234.567A	10G

but here's the problem.

  imagine i've been given a bucket of these PHYs and they are
absolutely indistinguishable visually -- the only way to tell them
apart is, when the system powers up, the driver can read a PHY's H/W
register which contains the exact PHY ID of one of four possible
values as above. other than that, i have this bucket of PHYs and i
reach in, grab eight PHYs at random, and just bolt them into my
switch. some will be 1G, some 2.5G, and so on -- any combination is
possible -- so how do i handle this?

  first, it's obvious that i can't put precise PHY IDs in my device
tree source file since i have no idea what type will be at each PHY
address across different switches. the best i can do is just put in a
matching wildcard pattern, so in the .dts file, all eight PHY
definitions will have entries of the form:

  compatible = "ethernet-phy-id1234.5670"

the above simply identifies that it's a PHY from acme, and it's only
purpose is to get me to the appropriate driver. (as i see it, the last
nybble could be any value from 0 to F since it's not relevant but
let's leave it at 0 for now.)

on the driver side, i would define a single mdio_device_id as above:

  #define PHY_ID_ACME 0x12345670

  static struct mdio_device_id acme_tbl[] = {
    { PHY_ID_ACME, 0xfffffff0 },
    { }
  } ;

again, in the above, i can't possibly refine the wildcarding any
further since the actual PHY ID value from the device tree does not
distinguish between the four PHY types. once again, so far, so good?

  now here's where i'm unclear, as one would normally define an array
of phy_drivers that match the possible wildcarding, as in for the asix
example above:

  static struct phy_driver asix_driver[] = { {
        .phy_id         = PHY_ID_ASIX_AX88796B,
        .name           = "Asix Electronics AX88796B",
        .phy_id_mask    = 0xfffffff0,
        .features       = PHY_BASIC_FEATURES,
        .soft_reset     = asix_soft_reset,
  } };

but as i understand it (and i might be completely wrong), these
entries are based on matching that must be distinguishable from the
precise PHY ID value in the .dts tree, is that right?

  what this means (and, again, i could be wrong) is that if i *had* a
device tree that specified the precise acme PHYs at each address, i
could define four exact matches, one for each PHY type:

  .phy_id = 0x1234.5671
  .name = "Acme 1G PHY"
  .phy_id_mask = 0xffffffff


  .phy_id = 0x1234.5672
  .name = "Acme 2.5G PHY"
  .phy_id_mask = 0xffffffff


... etc etc ... and the phy_driver matching would be done based on the
exact PHY_ID for that PHY.

  but recall that my device tree source file does not have that info
-- only the generic acme corp identifier 0x1234.5670. so, as i
understand it, i can't define four different phy_driver entries,
because that precise information is simply not available to me *at*
*this* *time*. as i read it (and this is what i want to confirm), all
of the wildcarding used in defining the phy_driver entries must be
available from the PHY ID values in the device tree. and since i don't
have that, i can really define only a single phy_driver entry that
still encompasses all of the possible acme PHY types. is that correct?

  in the end, as i read it, given the scenario i've presented, it
seems that i can define only one level of wildcarding, with one
phy_driver entry that covers all that wildcarding, and all i can do is
wait until i get into the driver init routines to finally read the
PHY's H/W register to determine which of the four PHYs it is.

  i ask this as someone suggested that, no, even in this case, i can
define four phy_driver entries, one to match each *exact* PHY ID, but
i don't see how that's possible given that the exact PHY ID isn't
available until i read the H/W register. so am i misunderstanding
something here?

  anyway, didn't mean to go on this long but i wanted to make sure i
explained this properly. thoughts, anyone?

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                  http://crashcourse.ca/dokuwiki

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================



More information about the Kernelnewbies mailing list