^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * drivers/net/phy/micrel.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Driver for Micrel PHYs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: David J. Choi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2010-2013 Micrel, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (c) 2014 Johan Hovold <johan@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Support : Micrel Phys:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Giga phys: ksz9021, ksz9031, ksz9131
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * 100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * ksz8021, ksz8031, ksz8051,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * ksz8081, ksz8091,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * ksz8061,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Switch : ksz8873, ksz886x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * ksz9477
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/micrel_phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Operation Mode Strap Override */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MII_KSZPHY_OMSO 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define KSZPHY_OMSO_FACTORY_TEST BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define KSZPHY_OMSO_B_CAST_OFF BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define KSZPHY_OMSO_NAND_TREE_ON BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define KSZPHY_OMSO_RMII_OVERRIDE BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define KSZPHY_OMSO_MII_OVERRIDE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* general Interrupt control/status reg in vendor specific block. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MII_KSZPHY_INTCS 0x1B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define KSZPHY_INTCS_JABBER BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define KSZPHY_INTCS_RECEIVE_ERR BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define KSZPHY_INTCS_PAGE_RECEIVE BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define KSZPHY_INTCS_PARELLEL BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define KSZPHY_INTCS_LINK_PARTNER_ACK BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define KSZPHY_INTCS_LINK_DOWN BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define KSZPHY_INTCS_REMOTE_FAULT BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define KSZPHY_INTCS_LINK_UP BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) KSZPHY_INTCS_LINK_DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* PHY Control 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MII_KSZPHY_CTRL_1 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* PHY Control 2 / PHY Control (if no PHY Control 1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define MII_KSZPHY_CTRL_2 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MII_KSZPHY_CTRL MII_KSZPHY_CTRL_2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* bitmap of PHY register to set interrupt mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define KSZPHY_CTRL_INT_ACTIVE_HIGH BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define KSZPHY_RMII_REF_CLK_SEL BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Write/read to/from extended registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MII_KSZPHY_EXTREG 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define KSZPHY_EXTREG_WRITE 0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MII_KSZPHY_EXTREG_WRITE 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MII_KSZPHY_EXTREG_READ 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Extended registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MII_KSZPHY_CLK_CONTROL_PAD_SKEW 0x104
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define PS_TO_REG 200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct kszphy_hw_stat {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) const char *string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u8 bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static struct kszphy_hw_stat kszphy_hw_stats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { "phy_receive_errors", 21, 16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { "phy_idle_errors", 10, 8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct kszphy_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 led_mode_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u16 interrupt_level_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bool has_broadcast_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bool has_nand_tree_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) bool has_rmii_ref_clk_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct kszphy_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) const struct kszphy_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int led_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) bool rmii_ref_clk_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) bool rmii_ref_clk_sel_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u64 stats[ARRAY_SIZE(kszphy_hw_stats)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static const struct kszphy_type ksz8021_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .led_mode_reg = MII_KSZPHY_CTRL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .has_broadcast_disable = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .has_nand_tree_disable = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .has_rmii_ref_clk_sel = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const struct kszphy_type ksz8041_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .led_mode_reg = MII_KSZPHY_CTRL_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const struct kszphy_type ksz8051_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .led_mode_reg = MII_KSZPHY_CTRL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .has_nand_tree_disable = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static const struct kszphy_type ksz8081_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .led_mode_reg = MII_KSZPHY_CTRL_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .has_broadcast_disable = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .has_nand_tree_disable = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .has_rmii_ref_clk_sel = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const struct kszphy_type ks8737_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .interrupt_level_mask = BIT(14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static const struct kszphy_type ksz9021_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .interrupt_level_mask = BIT(14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int kszphy_extended_write(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u32 regnum, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) phy_write(phydev, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return phy_write(phydev, MII_KSZPHY_EXTREG_WRITE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int kszphy_extended_read(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) u32 regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) phy_write(phydev, MII_KSZPHY_EXTREG, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return phy_read(phydev, MII_KSZPHY_EXTREG_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int kszphy_ack_interrupt(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* bit[7..0] int status, which is a read and clear register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) rc = phy_read(phydev, MII_KSZPHY_INTCS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return (rc < 0) ? rc : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int kszphy_config_intr(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) const struct kszphy_type *type = phydev->drv->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u16 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (type && type->interrupt_level_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) mask = type->interrupt_level_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mask = KSZPHY_CTRL_INT_ACTIVE_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* set the interrupt pin active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) temp = phy_read(phydev, MII_KSZPHY_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (temp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) temp &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) phy_write(phydev, MII_KSZPHY_CTRL, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* enable / disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) temp = KSZPHY_INTCS_ALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return phy_write(phydev, MII_KSZPHY_INTCS, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int kszphy_rmii_clk_sel(struct phy_device *phydev, bool val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ctrl = phy_read(phydev, MII_KSZPHY_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (ctrl < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ctrl |= KSZPHY_RMII_REF_CLK_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ctrl &= ~KSZPHY_RMII_REF_CLK_SEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return phy_write(phydev, MII_KSZPHY_CTRL, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int kszphy_setup_led(struct phy_device *phydev, u32 reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int rc, temp, shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) case MII_KSZPHY_CTRL_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) shift = 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case MII_KSZPHY_CTRL_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) shift = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) temp = phy_read(phydev, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (temp < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) rc = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) temp &= ~(3 << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) temp |= val << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) rc = phy_write(phydev, reg, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) phydev_err(phydev, "failed to set led mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* Disable PHY address 0 as the broadcast address, so that it can be used as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * unique (non-broadcast) address on a shared bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int kszphy_broadcast_disable(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = phy_read(phydev, MII_KSZPHY_OMSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) phydev_err(phydev, "failed to disable broadcast address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int kszphy_nand_tree_disable(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ret = phy_read(phydev, MII_KSZPHY_OMSO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!(ret & KSZPHY_OMSO_NAND_TREE_ON))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ret = phy_write(phydev, MII_KSZPHY_OMSO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret & ~KSZPHY_OMSO_NAND_TREE_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) phydev_err(phydev, "failed to disable NAND tree mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* Some config bits need to be set again on resume, handle them here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int kszphy_config_reset(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct kszphy_priv *priv = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (priv->rmii_ref_clk_sel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) phydev_err(phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) "failed to set rmii reference clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (priv->led_mode >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int kszphy_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct kszphy_priv *priv = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) const struct kszphy_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) type = priv->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (type->has_broadcast_disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) kszphy_broadcast_disable(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (type->has_nand_tree_disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) kszphy_nand_tree_disable(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return kszphy_config_reset(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int ksz8041_fiber_mode(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct device_node *of_node = phydev->mdio.dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return of_property_read_bool(of_node, "micrel,fiber-mode");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static int ksz8041_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* Limit supported and advertised modes in fiber mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (ksz8041_fiber_mode(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) phydev->dev_flags |= MICREL_PHY_FXEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) linkmode_and(phydev->supported, phydev->supported, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) linkmode_and(phydev->advertising, phydev->advertising, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) phydev->autoneg = AUTONEG_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return kszphy_config_init(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static int ksz8041_config_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* Skip auto-negotiation in fiber mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (phydev->dev_flags & MICREL_PHY_FXEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) phydev->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return genphy_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) const bool ksz_8051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ret = phy_read(phydev, MII_BMSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* KSZ8051 PHY and KSZ8794/KSZ8795/KSZ8765 switch share the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * exact PHY ID. However, they can be told apart by the extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * capability registers presence. The KSZ8051 PHY has them while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * the switch does not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ret &= BMSR_ERCAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (ksz_8051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return !ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int ksz8051_match_phy_device(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return ksz8051_ksz8795_match_phy_device(phydev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static int ksz8081_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* KSZPHY_OMSO_FACTORY_TEST is set at de-assertion of the reset line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * based on the RXER (KSZ8081RNA/RND) or TXC (KSZ8081MNX/RNB) pin. If a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * pull-down is missing, the factory test mode should be cleared by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * manually writing a 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) phy_clear_bits(phydev, MII_KSZPHY_OMSO, KSZPHY_OMSO_FACTORY_TEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return kszphy_config_init(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int ksz8061_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return kszphy_config_init(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static int ksz8795_match_phy_device(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return ksz8051_ksz8795_match_phy_device(phydev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int ksz9021_load_values_from_of(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) const struct device_node *of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) u16 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) const char *field1, const char *field2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) const char *field3, const char *field4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int val1 = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int val2 = -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int val3 = -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int val4 = -4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) int newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int matches = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (!of_property_read_u32(of_node, field1, &val1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) matches++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!of_property_read_u32(of_node, field2, &val2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) matches++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (!of_property_read_u32(of_node, field3, &val3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) matches++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!of_property_read_u32(of_node, field4, &val4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) matches++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!matches)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (matches < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) newval = kszphy_extended_read(phydev, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) newval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (val1 != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (val2 != -2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (val3 != -3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (val4 != -4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return kszphy_extended_write(phydev, reg, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int ksz9021_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) const struct device *dev = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) const struct device_node *of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) const struct device *dev_walker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* The Micrel driver has a deprecated option to place phy OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * properties in the MAC node. Walk up the tree of devices to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * find a device with an OF node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) dev_walker = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) of_node = dev_walker->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) dev_walker = dev_walker->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) } while (!of_node && dev_walker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ksz9021_load_values_from_of(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) MII_KSZPHY_CLK_CONTROL_PAD_SKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) "txen-skew-ps", "txc-skew-ps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) "rxdv-skew-ps", "rxc-skew-ps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) ksz9021_load_values_from_of(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) MII_KSZPHY_RX_DATA_PAD_SKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) "rxd0-skew-ps", "rxd1-skew-ps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) "rxd2-skew-ps", "rxd3-skew-ps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ksz9021_load_values_from_of(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) MII_KSZPHY_TX_DATA_PAD_SKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) "txd0-skew-ps", "txd1-skew-ps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) "txd2-skew-ps", "txd3-skew-ps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) #define KSZ9031_PS_TO_REG 60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Extended registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* MMD Address 0x0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) #define MII_KSZ9031RN_FLP_BURST_TX_LO 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) #define MII_KSZ9031RN_FLP_BURST_TX_HI 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* MMD Address 0x2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) #define MII_KSZ9031RN_CONTROL_PAD_SKEW 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) #define MII_KSZ9031RN_RX_CTL_M GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) #define MII_KSZ9031RN_TX_CTL_M GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) #define MII_KSZ9031RN_RX_DATA_PAD_SKEW 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) #define MII_KSZ9031RN_RXD3 GENMASK(15, 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) #define MII_KSZ9031RN_RXD2 GENMASK(11, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) #define MII_KSZ9031RN_RXD1 GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) #define MII_KSZ9031RN_RXD0 GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) #define MII_KSZ9031RN_TX_DATA_PAD_SKEW 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) #define MII_KSZ9031RN_TXD3 GENMASK(15, 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) #define MII_KSZ9031RN_TXD2 GENMASK(11, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) #define MII_KSZ9031RN_TXD1 GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) #define MII_KSZ9031RN_TXD0 GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) #define MII_KSZ9031RN_CLK_PAD_SKEW 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) #define MII_KSZ9031RN_GTX_CLK GENMASK(9, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) #define MII_KSZ9031RN_RX_CLK GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* KSZ9031 has internal RGMII_IDRX = 1.2ns and RGMII_IDTX = 0ns. To
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * provide different RGMII options we need to configure delay offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * for each pad relative to build in delay.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* keep rx as "No delay adjustment" and set rx_clk to +0.60ns to get delays of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * 1.80ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) #define RX_ID 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) #define RX_CLK_ID 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* set rx to +0.30ns and rx_clk to -0.90ns to compensate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * internal 1.2ns delay.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) #define RX_ND 0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) #define RX_CLK_ND 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* set tx to -0.42ns and tx_clk to +0.96ns to get 1.38ns delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) #define TX_ID 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) #define TX_CLK_ID 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* set tx and tx_clk to "No delay adjustment" to keep 0ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * dealy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) #define TX_ND 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) #define TX_CLK_ND 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /* MMD Address 0x1C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) #define MII_KSZ9031RN_EDPD 0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) #define MII_KSZ9031RN_EDPD_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static int ksz9031_of_load_skew_values(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) const struct device_node *of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) u16 reg, size_t field_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) const char *field[], u8 numfields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) bool *update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int val[4] = {-1, -2, -3, -4};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int matches = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) u16 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u16 maxval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) u16 newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) for (i = 0; i < numfields; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!of_property_read_u32(of_node, field[i], val + i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) matches++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!matches)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) *update |= true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (matches < numfields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) newval = phy_read_mmd(phydev, 2, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) newval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) maxval = (field_sz == 4) ? 0xf : 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) for (i = 0; i < numfields; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (val[i] != -(i + 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) mask ^= maxval << (field_sz * i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) newval = (newval & mask) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) (((val[i] / KSZ9031_PS_TO_REG) & maxval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) << (field_sz * i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return phy_write_mmd(phydev, 2, reg, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* Center KSZ9031RNX FLP timing at 16ms. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static int ksz9031_center_flp_timing(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) result = phy_write_mmd(phydev, 0, MII_KSZ9031RN_FLP_BURST_TX_HI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 0x0006);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) result = phy_write_mmd(phydev, 0, MII_KSZ9031RN_FLP_BURST_TX_LO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 0x1A80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return genphy_restart_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* Enable energy-detect power-down mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static int ksz9031_enable_edpd(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) reg = phy_read_mmd(phydev, 0x1C, MII_KSZ9031RN_EDPD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return phy_write_mmd(phydev, 0x1C, MII_KSZ9031RN_EDPD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) reg | MII_KSZ9031RN_EDPD_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static int ksz9031_config_rgmii_delay(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) u16 rx, tx, rx_clk, tx_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) switch (phydev->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) case PHY_INTERFACE_MODE_RGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) tx = TX_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) tx_clk = TX_CLK_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) rx = RX_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) rx_clk = RX_CLK_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) case PHY_INTERFACE_MODE_RGMII_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) tx = TX_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) tx_clk = TX_CLK_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) rx = RX_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) rx_clk = RX_CLK_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case PHY_INTERFACE_MODE_RGMII_RXID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) tx = TX_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) tx_clk = TX_CLK_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) rx = RX_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) rx_clk = RX_CLK_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) case PHY_INTERFACE_MODE_RGMII_TXID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) tx = TX_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) tx_clk = TX_CLK_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) rx = RX_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) rx_clk = RX_CLK_ND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ret = phy_write_mmd(phydev, 2, MII_KSZ9031RN_CONTROL_PAD_SKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) FIELD_PREP(MII_KSZ9031RN_RX_CTL_M, rx) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) FIELD_PREP(MII_KSZ9031RN_TX_CTL_M, tx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ret = phy_write_mmd(phydev, 2, MII_KSZ9031RN_RX_DATA_PAD_SKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) FIELD_PREP(MII_KSZ9031RN_RXD3, rx) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) FIELD_PREP(MII_KSZ9031RN_RXD2, rx) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) FIELD_PREP(MII_KSZ9031RN_RXD1, rx) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) FIELD_PREP(MII_KSZ9031RN_RXD0, rx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) ret = phy_write_mmd(phydev, 2, MII_KSZ9031RN_TX_DATA_PAD_SKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) FIELD_PREP(MII_KSZ9031RN_TXD3, tx) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) FIELD_PREP(MII_KSZ9031RN_TXD2, tx) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) FIELD_PREP(MII_KSZ9031RN_TXD1, tx) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) FIELD_PREP(MII_KSZ9031RN_TXD0, tx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return phy_write_mmd(phydev, 2, MII_KSZ9031RN_CLK_PAD_SKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) FIELD_PREP(MII_KSZ9031RN_GTX_CLK, tx_clk) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) FIELD_PREP(MII_KSZ9031RN_RX_CLK, rx_clk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static int ksz9031_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) const struct device *dev = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) const struct device_node *of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static const char *clk_skews[2] = {"rxc-skew-ps", "txc-skew-ps"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) static const char *rx_data_skews[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) "rxd0-skew-ps", "rxd1-skew-ps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) "rxd2-skew-ps", "rxd3-skew-ps"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static const char *tx_data_skews[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) "txd0-skew-ps", "txd1-skew-ps",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) "txd2-skew-ps", "txd3-skew-ps"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static const char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) const struct device *dev_walker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) result = ksz9031_enable_edpd(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* The Micrel driver has a deprecated option to place phy OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * properties in the MAC node. Walk up the tree of devices to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * find a device with an OF node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dev_walker = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) of_node = dev_walker->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) dev_walker = dev_walker->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) } while (!of_node && dev_walker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) bool update = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (phy_interface_is_rgmii(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) result = ksz9031_config_rgmii_delay(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) ksz9031_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) MII_KSZ9031RN_CLK_PAD_SKEW, 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) clk_skews, 2, &update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ksz9031_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) MII_KSZ9031RN_CONTROL_PAD_SKEW, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) control_skews, 2, &update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ksz9031_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) rx_data_skews, 4, &update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ksz9031_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) tx_data_skews, 4, &update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (update && !phy_interface_is_rgmii(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) phydev_warn(phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) "*-skew-ps values should be used only with RGMII PHY modes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* Silicon Errata Sheet (DS80000691D or DS80000692D):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * When the device links in the 1000BASE-T slave mode only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * the optional 125MHz reference output clock (CLK125_NDO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * has wide duty cycle variation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * The optional CLK125_NDO clock does not meet the RGMII
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * 45/55 percent (min/max) duty cycle requirement and therefore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * cannot be used directly by the MAC side for clocking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * applications that have setup/hold time requirements on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * rising and falling clock edges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * Workaround:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * Force the phy to be the master to receive a stable clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * which meets the duty cycle requirement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (of_property_read_bool(of_node, "micrel,force-master")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) result = phy_read(phydev, MII_CTRL1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) goto err_force_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* enable master mode, config & prefer master */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) result |= CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) result = phy_write(phydev, MII_CTRL1000, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) goto err_force_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return ksz9031_center_flp_timing(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) err_force_master:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) phydev_err(phydev, "failed to force the phy to master mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) #define KSZ9131_SKEW_5BIT_MAX 2400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) #define KSZ9131_SKEW_4BIT_MAX 800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) #define KSZ9131_OFFSET 700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) #define KSZ9131_STEP 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static int ksz9131_of_load_skew_values(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct device_node *of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) u16 reg, size_t field_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) char *field[], u8 numfields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) int val[4] = {-(1 + KSZ9131_OFFSET), -(2 + KSZ9131_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) -(3 + KSZ9131_OFFSET), -(4 + KSZ9131_OFFSET)};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) int skewval, skewmax = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) int matches = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) u16 maxval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) u16 newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) u16 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* psec properties in dts should mean x pico seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (field_sz == 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) skewmax = KSZ9131_SKEW_5BIT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) skewmax = KSZ9131_SKEW_4BIT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) for (i = 0; i < numfields; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (!of_property_read_s32(of_node, field[i], &skewval)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (skewval < -KSZ9131_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) skewval = -KSZ9131_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) else if (skewval > skewmax)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) skewval = skewmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) val[i] = skewval + KSZ9131_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) matches++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (!matches)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (matches < numfields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) newval = phy_read_mmd(phydev, 2, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) newval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) maxval = (field_sz == 4) ? 0xf : 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) for (i = 0; i < numfields; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (val[i] != -(i + 1 + KSZ9131_OFFSET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) mask ^= maxval << (field_sz * i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) newval = (newval & mask) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) (((val[i] / KSZ9131_STEP) & maxval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) << (field_sz * i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return phy_write_mmd(phydev, 2, reg, newval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) #define KSZ9131RN_MMD_COMMON_CTRL_REG 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) #define KSZ9131RN_RXC_DLL_CTRL 76
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) #define KSZ9131RN_TXC_DLL_CTRL 77
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) #define KSZ9131RN_DLL_CTRL_BYPASS BIT_MASK(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) #define KSZ9131RN_DLL_ENABLE_DELAY 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) #define KSZ9131RN_DLL_DISABLE_DELAY BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static int ksz9131_config_rgmii_delay(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) u16 rxcdll_val, txcdll_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) switch (phydev->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) case PHY_INTERFACE_MODE_RGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) case PHY_INTERFACE_MODE_RGMII_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) case PHY_INTERFACE_MODE_RGMII_RXID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) rxcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) txcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) case PHY_INTERFACE_MODE_RGMII_TXID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) rxcdll_val = KSZ9131RN_DLL_DISABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) txcdll_val = KSZ9131RN_DLL_ENABLE_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ret = phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) KSZ9131RN_RXC_DLL_CTRL, KSZ9131RN_DLL_CTRL_BYPASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) rxcdll_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) KSZ9131RN_TXC_DLL_CTRL, KSZ9131RN_DLL_CTRL_BYPASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) txcdll_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static int ksz9131_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) const struct device *dev = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct device_node *of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) char *clk_skews[2] = {"rxc-skew-psec", "txc-skew-psec"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) char *rx_data_skews[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) "rxd0-skew-psec", "rxd1-skew-psec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) "rxd2-skew-psec", "rxd3-skew-psec"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) char *tx_data_skews[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) "txd0-skew-psec", "txd1-skew-psec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) "txd2-skew-psec", "txd3-skew-psec"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) char *control_skews[2] = {"txen-skew-psec", "rxdv-skew-psec"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) const struct device *dev_walker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev_walker = &phydev->mdio.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) of_node = dev_walker->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) dev_walker = dev_walker->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) } while (!of_node && dev_walker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (!of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (phy_interface_is_rgmii(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ret = ksz9131_config_rgmii_delay(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) ret = ksz9131_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) MII_KSZ9031RN_CLK_PAD_SKEW, 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) clk_skews, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) ret = ksz9131_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) MII_KSZ9031RN_CONTROL_PAD_SKEW, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) control_skews, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) ret = ksz9131_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) rx_data_skews, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ret = ksz9131_of_load_skew_values(phydev, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) tx_data_skews, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) #define KSZ8873MLL_GLOBAL_CONTROL_4 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static int ksz8873mll_read_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /* dummy read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) phydev->duplex = DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) phydev->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) phydev->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) phydev->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) phydev->link = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) phydev->pause = phydev->asym_pause = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) static int ksz9031_get_features(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = genphy_read_abilities(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) /* Silicon Errata Sheet (DS80000691D or DS80000692D):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * Whenever the device's Asymmetric Pause capability is set to 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * link-up may fail after a link-up to link-down transition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * The Errata Sheet is for ksz9031, but ksz9021 has the same issue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) * Workaround:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) * Do not enable the Asymmetric Pause capability bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* We force setting the Pause capability as the core will force the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * Asymmetric Pause capability to 1 otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) static int ksz9031_read_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) int regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) err = genphy_read_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) /* Make sure the PHY is not broken. Read idle error count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * and reset the PHY if it is maxed out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) regval = phy_read(phydev, MII_STAT1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if ((regval & 0xFF) == 0xFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) phy_init_hw(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) phydev->link = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) phydev->drv->config_intr(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return genphy_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) static int ksz8873mll_config_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) static int kszphy_get_sset_count(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return ARRAY_SIZE(kszphy_hw_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) static void kszphy_get_strings(struct phy_device *phydev, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) strlcpy(data + i * ETH_GSTRING_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) kszphy_hw_stats[i].string, ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static u64 kszphy_get_stat(struct phy_device *phydev, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct kszphy_hw_stat stat = kszphy_hw_stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) struct kszphy_priv *priv = phydev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) u64 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) val = phy_read(phydev, stat.reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (val < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) ret = U64_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) val = val & ((1 << stat.bits) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) priv->stats[i] += val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) ret = priv->stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static void kszphy_get_stats(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) struct ethtool_stats *stats, u64 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) data[i] = kszphy_get_stat(phydev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static int kszphy_suspend(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* Disable PHY Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (phy_interrupt_is_valid(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) phydev->interrupts = PHY_INTERRUPT_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (phydev->drv->config_intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) phydev->drv->config_intr(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) return genphy_suspend(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static int kszphy_resume(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) genphy_resume(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /* After switching from power-down to normal mode, an internal global
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * reset is automatically generated. Wait a minimum of 1 ms before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * read/write access to the PHY registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) ret = kszphy_config_reset(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* Enable PHY Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (phy_interrupt_is_valid(phydev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) phydev->interrupts = PHY_INTERRUPT_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (phydev->drv->config_intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) phydev->drv->config_intr(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static int kszphy_probe(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) const struct kszphy_type *type = phydev->drv->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) const struct device_node *np = phydev->mdio.dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) struct kszphy_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) phydev->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) priv->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (type->led_mode_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) ret = of_property_read_u32(np, "micrel,led-mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) &priv->led_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) priv->led_mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (priv->led_mode > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) phydev_err(phydev, "invalid led mode: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) priv->led_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) priv->led_mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) priv->led_mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) clk = devm_clk_get(&phydev->mdio.dev, "rmii-ref");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) /* NOTE: clk may be NULL if building without CONFIG_HAVE_CLK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (!IS_ERR_OR_NULL(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) unsigned long rate = clk_get_rate(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) bool rmii_ref_clk_sel_25_mhz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) "micrel,rmii-reference-clock-select-25-mhz");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (rate > 24500000 && rate < 25500000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) priv->rmii_ref_clk_sel_val = rmii_ref_clk_sel_25_mhz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) } else if (rate > 49500000 && rate < 50500000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) priv->rmii_ref_clk_sel_val = !rmii_ref_clk_sel_25_mhz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) phydev_err(phydev, "Clock rate out of range: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (ksz8041_fiber_mode(phydev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) phydev->port = PORT_FIBRE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /* Support legacy board-file configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) priv->rmii_ref_clk_sel = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) priv->rmii_ref_clk_sel_val = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static struct phy_driver ksphy_driver[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .phy_id = PHY_ID_KS8737,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) .name = "Micrel KS8737",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) .driver_data = &ks8737_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) .phy_id = PHY_ID_KSZ8021,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) .phy_id_mask = 0x00ffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) .name = "Micrel KSZ8021 or KSZ8031",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .driver_data = &ksz8021_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) .phy_id = PHY_ID_KSZ8031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) .phy_id_mask = 0x00ffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) .name = "Micrel KSZ8031",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .driver_data = &ksz8021_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) .phy_id = PHY_ID_KSZ8041,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) .name = "Micrel KSZ8041",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) .driver_data = &ksz8041_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) .config_init = ksz8041_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) .config_aneg = ksz8041_config_aneg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /* No suspend/resume callbacks because of errata DS80000700A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * receiver error following software power down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) .phy_id = PHY_ID_KSZ8041RNLI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) .name = "Micrel KSZ8041RNLI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) .driver_data = &ksz8041_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) .name = "Micrel KSZ8051",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) .driver_data = &ksz8051_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) .match_phy_device = ksz8051_match_phy_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) .phy_id = PHY_ID_KSZ8001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) .name = "Micrel KSZ8001 or KS8721",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .phy_id_mask = 0x00fffffc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) .driver_data = &ksz8041_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) .phy_id = PHY_ID_KSZ8081,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .name = "Micrel KSZ8081 or KSZ8091",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) .driver_data = &ksz8081_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) .config_init = ksz8081_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) .soft_reset = genphy_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) .suspend = kszphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) .resume = kszphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) .phy_id = PHY_ID_KSZ8061,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) .name = "Micrel KSZ8061",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) .config_init = ksz8061_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) .phy_id = PHY_ID_KSZ9021,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) .phy_id_mask = 0x000ffffe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) .name = "Micrel KSZ9021 Gigabit PHY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /* PHY_GBIT_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) .driver_data = &ksz9021_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) .get_features = ksz9031_get_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) .config_init = ksz9021_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) .read_mmd = genphy_read_mmd_unsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) .write_mmd = genphy_write_mmd_unsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) .phy_id = PHY_ID_KSZ9031,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) .name = "Micrel KSZ9031 Gigabit PHY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) .driver_data = &ksz9021_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) .get_features = ksz9031_get_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) .config_init = ksz9031_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) .soft_reset = genphy_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) .read_status = ksz9031_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) .resume = kszphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) .phy_id = PHY_ID_LAN8814,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) .name = "Microchip INDY Gigabit Quad PHY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .driver_data = &ksz9021_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .soft_reset = genphy_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .read_status = ksz9031_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) .resume = kszphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) .phy_id = PHY_ID_KSZ9131,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) .name = "Microchip KSZ9131 Gigabit PHY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) /* PHY_GBIT_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) .driver_data = &ksz9021_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) .probe = kszphy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) .config_init = ksz9131_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) .read_status = genphy_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) .ack_interrupt = kszphy_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) .config_intr = kszphy_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) .get_sset_count = kszphy_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) .get_strings = kszphy_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) .get_stats = kszphy_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) .resume = kszphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) .phy_id = PHY_ID_KSZ8873MLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) .name = "Micrel KSZ8873MLL Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) .config_aneg = ksz8873mll_config_aneg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) .read_status = ksz8873mll_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) .phy_id = PHY_ID_KSZ886X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) .name = "Micrel KSZ886X Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) .name = "Micrel KSZ87XX Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) /* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) .match_phy_device = ksz8795_match_phy_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) .phy_id = PHY_ID_KSZ9477,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) .phy_id_mask = MICREL_PHY_ID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) .name = "Microchip KSZ9477",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) /* PHY_GBIT_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) .config_init = kszphy_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) .suspend = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) .resume = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) module_phy_driver(ksphy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) MODULE_DESCRIPTION("Micrel PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) MODULE_AUTHOR("David J. Choi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) static struct mdio_device_id __maybe_unused micrel_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) { PHY_ID_KSZ9021, 0x000ffffe },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) { PHY_ID_KSZ9031, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) { PHY_ID_KSZ9131, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) { PHY_ID_KSZ8001, 0x00fffffc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) { PHY_ID_KS8737, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) { PHY_ID_KSZ8021, 0x00ffffff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) { PHY_ID_KSZ8031, 0x00ffffff },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) { PHY_ID_KSZ8041, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) { PHY_ID_KSZ8051, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) { PHY_ID_KSZ8061, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) { PHY_ID_KSZ8081, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) { PHY_ID_KSZ8873MLL, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) { PHY_ID_KSZ886X, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) { PHY_ID_LAN8814, MICREL_PHY_ID_MASK },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) MODULE_DEVICE_TABLE(mdio, micrel_tbl);