1 // SPDX-License-Identifier: GPL-2.0+
3 * Driver for the Renesas PHY uPD60620.
5 * Copyright (C) 2015 Softing Industrial Automation GmbH
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/phy.h>
12 #define UPD60620_PHY_ID 0xb8242824
14 /* Extended Registers and values */
15 /* PHY Special Control/Status */
16 #define PHY_PHYSCR 0x1F /* PHY.31 */
17 #define PHY_PHYSCR_10MB 0x0004 /* PHY speed = 10mb */
18 #define PHY_PHYSCR_100MB 0x0008 /* PHY speed = 100mb */
19 #define PHY_PHYSCR_DUPLEX 0x0010 /* PHY Duplex */
21 /* PHY Special Modes */
22 #define PHY_SPM 0x12 /* PHY.18 */
26 static int upd60620_config_init(struct phy_device
*phydev
)
28 /* Enable support for passive HUBs (could be a strap option) */
29 /* PHYMODE: All speeds, HD in parallel detect */
30 return phy_write(phydev
, PHY_SPM
, 0x0180 | phydev
->mdio
.addr
);
33 /* Get PHY status from common registers */
35 static int upd60620_read_status(struct phy_device
*phydev
)
39 /* Read negotiated state */
40 phy_state
= phy_read(phydev
, MII_BMSR
);
45 linkmode_zero(phydev
->lp_advertising
);
47 phydev
->asym_pause
= 0;
49 if (phy_state
& (BMSR_ANEGCOMPLETE
| BMSR_LSTATUS
)) {
50 phy_state
= phy_read(phydev
, PHY_PHYSCR
);
54 if (phy_state
& (PHY_PHYSCR_10MB
| PHY_PHYSCR_100MB
)) {
56 phydev
->speed
= SPEED_10
;
57 phydev
->duplex
= DUPLEX_HALF
;
59 if (phy_state
& PHY_PHYSCR_100MB
)
60 phydev
->speed
= SPEED_100
;
61 if (phy_state
& PHY_PHYSCR_DUPLEX
)
62 phydev
->duplex
= DUPLEX_FULL
;
64 phy_state
= phy_read(phydev
, MII_LPA
);
68 mii_lpa_to_linkmode_lpa_t(phydev
->lp_advertising
,
71 phy_resolve_aneg_pause(phydev
);
77 MODULE_DESCRIPTION("Renesas uPD60620 PHY driver");
78 MODULE_AUTHOR("Bernd Edlinger <bernd.edlinger@hotmail.de>");
79 MODULE_LICENSE("GPL");
81 static struct phy_driver upd60620_driver
[1] = { {
82 .phy_id
= UPD60620_PHY_ID
,
83 .phy_id_mask
= 0xfffffffe,
84 .name
= "Renesas uPD60620",
85 /* PHY_BASIC_FEATURES */
87 .config_init
= upd60620_config_init
,
88 .read_status
= upd60620_read_status
,
91 module_phy_driver(upd60620_driver
);
93 static struct mdio_device_id __maybe_unused upd60620_tbl
[] = {
94 { UPD60620_PHY_ID
, 0xfffffffe },
98 MODULE_DEVICE_TABLE(mdio
, upd60620_tbl
);