how to distinguish between PHYs that are not distinguished in the device tree?

3 messages, 2 authors, 2018-12-12 · open the first message on its own page

how to distinguish between PHYs that are not distinguished in the device tree?

From: <hidden>
Date: 2018-12-12 13:39:58

  (i asked about this on the kernel newbies list earlier as a kind of
puzzle but i think i really want a definitive answer so i'm taking it
to the experts. (i will *try* to be concise.)

   imagine i'm building a bunch of 8-port switches, using PHYs from
acme corp, who manufacture four different PHYs that differ only in
their supported speeds, with PHY IDs that differ only in the final
nybble which identifies the PHY speed:

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

   the problem i have is that i have been handed a bucket of mixed
PHYs of all four types that are visually indistinguishable -- the
only way to tell them apart is, upon system boot, i can read a given
H/W register which precisely identifies the type of PHY of the four
possible types. however, in this situation, all i can do is reach into
the bucket, grab eight random PHYs, bolt them in, and somehow later
dynamically identify them at runtime. how to do this?

   first, i can't identify the precise PHY ID in the device tree file
since i have no idea what type will be at each of the eight PHY addresses,
so i will "wildcard" the compatible value for each of them thusly (where
the final nybble of zero is, of course, irrelevant):

   compatible = "ethernet-phy-id1234.5670"

i see no way to avoid this at the device tree level so ... onward.

   moving over to the driver, it seems pretty clear that, since the
PHY IDs i'm getting from the device tree are acme-generic, i would
have:

   #define PHY_ID_ACME_WILDCARD  0x12345670

   #define PHY_ID_ACME_1G        0x12345671
   #define PHY_ID_ACME_2G        0x12345672
   #define PHY_ID_ACME_5G        0x12345675
   #define PHY_ID_ACME_10G       0x1234567A

   #define PHY_ID_ACME_MASK      0xfffffff0
         ...
   static struct mdio_device_id __maybe_unused acme_tbl[] = {
         { PHY_ID_ACME_WILDCARD, 0xfffffff0 },
         { }
   };

   MODULE_DEVICE_TABLE(mdio, acme_tbl);

again, this seems fairly obvious since the PHY ID field for any PHY
will contain only that "generic" value. but here's the discussion i'm
having with a colleague.

   i'm fairly sure that i should have a single phy_driver structure
still incorporating the wildcard since, at this point, i still have no
idea what each PHY type is, so my suggestion was:

   static struct phy_driver acme_driver[] = { {
         .phy_id         = PHY_ID_ACME_WILDCARD,
         .name           = "An ACME PHY",
         .phy_id_mask    = PHY_ID_ACME_MASK,
         .features       = PHY_BASIC_FEATURES,
         ... snip ...
   } };

at which point, at probe time, for each PHY, i could read the
respective H/W register, then assign the proper value to the
phy_device phy_id field and use that from now on.

   my colleague suggests that, no, i could actually define
four phy_driver structures, one for each specific PHY,
as in:

   static struct phy_driver acme_driver[] = { {
         .phy_id         = PHY_ID_ACME_1G,
         .name           = "Acme 1G PHY",
         .phy_id_mask    = 0xffffffff,
         .features       = PHY_BASIC_FEATURES,
         ... snip ...
   }, {
         .phy_id         = PHY_ID_ACME_25G,
         .name           = "Acme 2.5G PHY",
         .phy_id_mask    = 0xffffffff,
         .features       = PHY_BASIC_FEATURES,
         ... snip ...

and so on.

   given that the precise PHY type is not available from the device tree,
could the above possibly work? or is it that, once i probe each PHY,
determine its precise type and write that type into the phy_id field
of the phy_device structure, the above would become relevant?

   any pointers appreciated.

rday

Re: how to distinguish between PHYs that are not distinguished in the device tree?

From: Andrew Lunn <andrew@lunn.ch>
Date: 2018-12-12 15:51:30

On Wed, Dec 12, 2018 at 08:16:55AM -0500, rpjday@crashcourse.ca wrote:
 (i asked about this on the kernel newbies list earlier as a kind of
puzzle but i think i really want a definitive answer so i'm taking it
to the experts. (i will *try* to be concise.)

  imagine i'm building a bunch of 8-port switches, using PHYs from
acme corp, who manufacture four different PHYs that differ only in
their supported speeds, with PHY IDs that differ only in the final
nybble which identifies the PHY speed:

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

  the problem i have is that i have been handed a bucket of mixed
PHYs of all four types that are visually indistinguishable -- the
only way to tell them apart is, upon system boot, i can read a given
H/W register which precisely identifies the type of PHY of the four
possible types. however, in this situation, all i can do is reach into
the bucket, grab eight random PHYs, bolt them in, and somehow later
dynamically identify them at runtime. how to do this?

  first, i can't identify the precise PHY ID in the device tree file
since i have no idea what type will be at each of the eight PHY addresses,
so i will "wildcard" the compatible value for each of them thusly (where
the final nybble of zero is, of course, irrelevant):

  compatible = "ethernet-phy-id1234.5670"
You don't need to specify any compatible string in the device
tree. The PHY subsystem looks at the ID registers to determine which
PHY driver to load. You only need to use ethernet-phy-id1234.5670 when
the PHY has the wrong ID in its registers.
  moving over to the driver, it seems pretty clear that, since the
PHY IDs i'm getting from the device tree are acme-generic, i would
have:

  #define PHY_ID_ACME_WILDCARD  0x12345670

  #define PHY_ID_ACME_1G        0x12345671
  #define PHY_ID_ACME_2G        0x12345672
  #define PHY_ID_ACME_5G        0x12345675
  #define PHY_ID_ACME_10G       0x1234567A

  #define PHY_ID_ACME_MASK      0xfffffff0
        ...
  static struct mdio_device_id __maybe_unused acme_tbl[] = {
        { PHY_ID_ACME_WILDCARD, 0xfffffff0 },
        { }
  };
 
  static struct phy_driver acme_driver[] = { {
        .phy_id         = PHY_ID_ACME_WILDCARD,
        .name           = "An ACME PHY",
        .phy_id_mask    = PHY_ID_ACME_MASK,
        .features       = PHY_BASIC_FEATURES,
You should try to set .features correct. So ideally, you want one
entry per PHY, listing to exact ID, the mask of 0xffffffff, and
.features set appropriately.

	  Andrew

Re: how to distinguish between PHYs that are not distinguished in the device tree?

From: <hidden>
Date: 2018-12-12 16:03:06

Quoting Andrew Lunn [off-list ref]:
On Wed, Dec 12, 2018 at 08:16:55AM -0500, rpjday@crashcourse.ca wrote:
quoted
 (i asked about this on the kernel newbies list earlier as a kind of
puzzle but i think i really want a definitive answer so i'm taking it
to the experts. (i will *try* to be concise.)

  imagine i'm building a bunch of 8-port switches, using PHYs from
acme corp, who manufacture four different PHYs that differ only in
their supported speeds, with PHY IDs that differ only in the final
nybble which identifies the PHY speed:

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

  the problem i have is that i have been handed a bucket of mixed
PHYs of all four types that are visually indistinguishable -- the
only way to tell them apart is, upon system boot, i can read a given
H/W register which precisely identifies the type of PHY of the four
possible types. however, in this situation, all i can do is reach into
the bucket, grab eight random PHYs, bolt them in, and somehow later
dynamically identify them at runtime. how to do this?

  first, i can't identify the precise PHY ID in the device tree file
since i have no idea what type will be at each of the eight PHY addresses,
so i will "wildcard" the compatible value for each of them thusly (where
the final nybble of zero is, of course, irrelevant):

  compatible = "ethernet-phy-id1234.5670"
You don't need to specify any compatible string in the device
tree. The PHY subsystem looks at the ID registers to determine which
PHY driver to load. You only need to use ethernet-phy-id1234.5670 when
the PHY has the wrong ID in its registers.
   ah, that clarifies things quite a lot, thanks.

rday
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help