^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Driver for Asix PHYs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Michael Schmitz <schmitzmic@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define PHY_ID_ASIX_AX88796B 0x003b1841
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) MODULE_DESCRIPTION("Asix PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) MODULE_AUTHOR("Michael Schmitz <schmitzmic@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * asix_soft_reset - software reset the PHY via BMCR_RESET bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Description: Perform a software PHY reset using the standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * BMCR_RESET bit and poll for the reset bit to be cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Toggle BMCR_RESET bit off to accommodate broken AX8796B PHY implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * such as used on the Individual Computers' X-Surf 100 Zorro card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Returns: 0 on success, < 0 on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int asix_soft_reset(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Asix PHY won't reset unless reset bit toggles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ret = phy_write(phydev, MII_BMCR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return genphy_soft_reset(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static struct phy_driver asix_driver[] = { {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .phy_id = PHY_ID_ASIX_AX88796B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .name = "Asix Electronics AX88796B",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .phy_id_mask = 0xfffffff0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .soft_reset = asix_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) module_phy_driver(asix_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static struct mdio_device_id __maybe_unused asix_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { PHY_ID_ASIX_AX88796B, 0xfffffff0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) MODULE_DEVICE_TABLE(mdio, asix_tbl);