Commit db40c1aa1c100d8a9e33206575efd8b3678f31db
Committed by
Joe Hershberger
1 parent
f8e57c650d
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
drivers/net/phy: add fixed-phy / fixed-link support
This patch adds support for having a "fixed-link" to some other MAC (like some embedded switch-device). For this purpose we introduce a new phy-driver, called "Fixed PHY". Fixed PHY works only with CONFIG_DM_ETH enabled, since the fixed-link is described with a subnode below ethernet interface. Most ethernet drivers (unfortunately not all are following same scheme for searching/attaching phys) are calling "phy_connect(...)" for getting a phy-device. At this point we link in, we search here for a subnode called "fixed- link", once found we start phy_device_create(...) with the special phy- id PHY_FIXED_ID (0xa5a55a5a). During init the "Fixed PHY" driver has registered with this id and now gets probed, during probe we get all the details about fixed-link out of dts, later on the phy reports this values. Signed-off-by: Hannes Schmelzer <hannes.schmelzer@br-automation.com> Signed-off-by: Hannes Schmelzer <oe5hpm@oevsv.at> Acked-by: Joe Hershberger <joe.hershberger@ni.com> Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Showing 6 changed files with 146 additions and 3 deletions Side-by-side Diff
doc/device-tree-bindings/net/fixed-link.txt
1 | +Fixed link Device Tree binding | |
2 | +------------------------------ | |
3 | + | |
4 | +Some Ethernet MACs have a "fixed link", and are not connected to a | |
5 | +normal MDIO-managed PHY device. For those situations, a Device Tree | |
6 | +binding allows to describe a "fixed link". | |
7 | + | |
8 | +Such a fixed link situation is described by creating a 'fixed-link' | |
9 | +sub-node of the Ethernet MAC device node, with the following | |
10 | +properties: | |
11 | + | |
12 | +* 'speed' (integer, mandatory), to indicate the link speed. Accepted | |
13 | + values are 10, 100 and 1000 | |
14 | +* 'full-duplex' (boolean, optional), to indicate that full duplex is | |
15 | + used. When absent, half duplex is assumed. | |
16 | +* 'pause' (boolean, optional), to indicate that pause should be | |
17 | + enabled. | |
18 | +* 'asym-pause' (boolean, optional), to indicate that asym_pause should | |
19 | + be enabled. | |
20 | + | |
21 | +Examples: | |
22 | + | |
23 | +ethernet@0 { | |
24 | + ... | |
25 | + fixed-link { | |
26 | + speed = <1000>; | |
27 | + full-duplex; | |
28 | + }; | |
29 | + ... | |
30 | +}; |
drivers/net/phy/Kconfig
... | ... | @@ -90,5 +90,15 @@ |
90 | 90 | config PHY_XILINX |
91 | 91 | bool "Xilinx Ethernet PHYs support" |
92 | 92 | |
93 | +config PHY_FIXED | |
94 | + bool "Fixed-Link PHY" | |
95 | + depends on DM_ETH | |
96 | + help | |
97 | + Fixed PHY is used for having a 'fixed-link' to another MAC with a direct | |
98 | + connection (MII, RGMII, ...). | |
99 | + There is nothing like autoneogation and so | |
100 | + on, the link is always up with fixed speed and fixed duplex-setting. | |
101 | + More information: doc/device-tree-bindings/net/fixed-link.txt | |
102 | + | |
93 | 103 | endif #PHYLIB |
drivers/net/phy/Makefile
drivers/net/phy/fixed.c
1 | +/* | |
2 | + * Fixed-Link phy | |
3 | + * | |
4 | + * Copyright 2017 Bernecker & Rainer Industrieelektronik GmbH | |
5 | + * | |
6 | + * SPDX-License-Identifier: GPL-2.0+ | |
7 | + */ | |
8 | + | |
9 | +#include <config.h> | |
10 | +#include <common.h> | |
11 | +#include <phy.h> | |
12 | +#include <dm.h> | |
13 | +#include <fdt_support.h> | |
14 | + | |
15 | +DECLARE_GLOBAL_DATA_PTR; | |
16 | + | |
17 | +int fixedphy_probe(struct phy_device *phydev) | |
18 | +{ | |
19 | + struct fixed_link *priv; | |
20 | + int ofnode = phydev->addr; | |
21 | + u32 val; | |
22 | + | |
23 | + /* check for mandatory properties within fixed-link node */ | |
24 | + val = fdt_getprop_u32_default_node(gd->fdt_blob, | |
25 | + ofnode, 0, "speed", 0); | |
26 | + if (val != SPEED_10 && val != SPEED_100 && val != SPEED_1000) { | |
27 | + printf("ERROR: no/invalid speed given in fixed-link node!"); | |
28 | + return -EINVAL; | |
29 | + } | |
30 | + | |
31 | + priv = malloc(sizeof(*priv)); | |
32 | + if (!priv) | |
33 | + return -ENOMEM; | |
34 | + memset(priv, 0, sizeof(*priv)); | |
35 | + | |
36 | + phydev->priv = priv; | |
37 | + phydev->addr = 0; | |
38 | + | |
39 | + priv->link_speed = val; | |
40 | + priv->duplex = fdtdec_get_bool(gd->fdt_blob, ofnode, "full-duplex"); | |
41 | + priv->pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "pause"); | |
42 | + priv->asym_pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "asym-pause"); | |
43 | + | |
44 | + /* fixed-link phy must not be reset by core phy code */ | |
45 | + phydev->flags |= PHY_FLAG_BROKEN_RESET; | |
46 | + | |
47 | + return 0; | |
48 | +} | |
49 | + | |
50 | +int fixedphy_startup(struct phy_device *phydev) | |
51 | +{ | |
52 | + struct fixed_link *priv = phydev->priv; | |
53 | + | |
54 | + phydev->asym_pause = priv->asym_pause; | |
55 | + phydev->pause = priv->pause; | |
56 | + phydev->duplex = priv->duplex; | |
57 | + phydev->speed = priv->link_speed; | |
58 | + phydev->link = 1; | |
59 | + | |
60 | + return 0; | |
61 | +} | |
62 | + | |
63 | +int fixedphy_shutdown(struct phy_device *phydev) | |
64 | +{ | |
65 | + return 0; | |
66 | +} | |
67 | + | |
68 | +static struct phy_driver fixedphy_driver = { | |
69 | + .uid = PHY_FIXED_ID, | |
70 | + .mask = 0xffffffff, | |
71 | + .name = "Fixed PHY", | |
72 | + .features = PHY_GBIT_FEATURES | SUPPORTED_MII, | |
73 | + .probe = fixedphy_probe, | |
74 | + .startup = fixedphy_startup, | |
75 | + .shutdown = fixedphy_shutdown, | |
76 | +}; | |
77 | + | |
78 | +int phy_fixed_init(void) | |
79 | +{ | |
80 | + phy_register(&fixedphy_driver); | |
81 | + return 0; | |
82 | +} |
drivers/net/phy/phy.c
... | ... | @@ -515,7 +515,9 @@ |
515 | 515 | #ifdef CONFIG_PHY_MSCC |
516 | 516 | phy_mscc_init(); |
517 | 517 | #endif |
518 | - | |
518 | +#ifdef CONFIG_PHY_FIXED | |
519 | + phy_fixed_init(); | |
520 | +#endif | |
519 | 521 | return 0; |
520 | 522 | } |
521 | 523 | |
522 | 524 | |
... | ... | @@ -854,9 +856,24 @@ |
854 | 856 | struct eth_device *dev, phy_interface_t interface) |
855 | 857 | #endif |
856 | 858 | { |
857 | - struct phy_device *phydev; | |
859 | + struct phy_device *phydev = NULL; | |
860 | +#ifdef CONFIG_PHY_FIXED | |
861 | + int sn; | |
862 | + const char *name; | |
863 | + sn = fdt_first_subnode(gd->fdt_blob, dev->of_offset); | |
864 | + while (sn > 0) { | |
865 | + name = fdt_get_name(gd->fdt_blob, sn, NULL); | |
866 | + if (name != NULL && strcmp(name, "fixed-link") == 0) { | |
867 | + phydev = phy_device_create(bus, | |
868 | + sn, PHY_FIXED_ID, interface); | |
869 | + break; | |
870 | + } | |
871 | + sn = fdt_next_subnode(gd->fdt_blob, sn); | |
872 | + } | |
873 | +#endif | |
874 | + if (phydev == NULL) | |
875 | + phydev = phy_find_by_mask(bus, 1 << addr, interface); | |
858 | 876 | |
859 | - phydev = phy_find_by_mask(bus, 1 << addr, interface); | |
860 | 877 | if (phydev) |
861 | 878 | phy_connect_dev(phydev, dev); |
862 | 879 | else |
include/phy.h
... | ... | @@ -15,6 +15,8 @@ |
15 | 15 | #include <linux/ethtool.h> |
16 | 16 | #include <linux/mdio.h> |
17 | 17 | |
18 | +#define PHY_FIXED_ID 0xa5a55a5a | |
19 | + | |
18 | 20 | #define PHY_MAX_ADDR 32 |
19 | 21 | |
20 | 22 | #define PHY_FLAG_BROKEN_RESET (1 << 0) /* soft reset not supported */ |
... | ... | @@ -267,6 +269,7 @@ |
267 | 269 | int phy_vitesse_init(void); |
268 | 270 | int phy_xilinx_init(void); |
269 | 271 | int phy_mscc_init(void); |
272 | +int phy_fixed_init(void); | |
270 | 273 | |
271 | 274 | int board_phy_config(struct phy_device *phydev); |
272 | 275 | int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id); |
-
mentioned in commit f27bc8