Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)  * Amlogic Meson GXL Internal PHY Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2016 BayLibre, SAS. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Author: Neil Armstrong <narmstrong@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define TSTCNTL		20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define  TSTCNTL_READ		BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define  TSTCNTL_WRITE		BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define  TSTCNTL_REG_BANK_SEL	GENMASK(12, 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define  TSTCNTL_TEST_MODE	BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define  TSTCNTL_READ_ADDRESS	GENMASK(9, 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define  TSTCNTL_WRITE_ADDRESS	GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define TSTREAD1	21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define TSTWRITE	23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define INTSRC_FLAG	29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define  INTSRC_ANEG_PR		BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define  INTSRC_PARALLEL_FAULT	BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define  INTSRC_ANEG_LP_ACK	BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define  INTSRC_LINK_DOWN	BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define  INTSRC_REMOTE_FAULT	BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define  INTSRC_ANEG_COMPLETE	BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define INTSRC_MASK	30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define BANK_ANALOG_DSP		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define BANK_WOL		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define BANK_BIST		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) /* WOL Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define LPI_STATUS	0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define  LPI_STATUS_RSV12	BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) /* BIST Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define FR_PLL_CONTROL	0x1b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define FR_PLL_DIV0	0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define FR_PLL_DIV1	0x1d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static int meson_gxl_open_banks(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	/* Enable Analog and DSP register Bank access by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	 * toggling TSTCNTL_TEST_MODE bit in the TSTCNTL register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	ret = phy_write(phydev, TSTCNTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	ret = phy_write(phydev, TSTCNTL, TSTCNTL_TEST_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	ret = phy_write(phydev, TSTCNTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	return phy_write(phydev, TSTCNTL, TSTCNTL_TEST_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static void meson_gxl_close_banks(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	phy_write(phydev, TSTCNTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static int meson_gxl_read_reg(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			      unsigned int bank, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	ret = meson_gxl_open_banks(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	ret = phy_write(phydev, TSTCNTL, TSTCNTL_READ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			FIELD_PREP(TSTCNTL_REG_BANK_SEL, bank) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 			TSTCNTL_TEST_MODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			FIELD_PREP(TSTCNTL_READ_ADDRESS, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	ret = phy_read(phydev, TSTREAD1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	/* Close the bank access on our way out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	meson_gxl_close_banks(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	return ret;
^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) static int meson_gxl_write_reg(struct phy_device *phydev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			       unsigned int bank, unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			       uint16_t value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	ret = meson_gxl_open_banks(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	ret = phy_write(phydev, TSTWRITE, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	ret = phy_write(phydev, TSTCNTL, TSTCNTL_WRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			FIELD_PREP(TSTCNTL_REG_BANK_SEL, bank) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			TSTCNTL_TEST_MODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			FIELD_PREP(TSTCNTL_WRITE_ADDRESS, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	/* Close the bank access on our way out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	meson_gxl_close_banks(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int meson_gxl_config_init(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	/* Enable fractional PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	ret = meson_gxl_write_reg(phydev, BANK_BIST, FR_PLL_CONTROL, 0x5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	/* Program fraction FR_PLL_DIV1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	ret = meson_gxl_write_reg(phydev, BANK_BIST, FR_PLL_DIV1, 0x029a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	/* Program fraction FR_PLL_DIV1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	ret = meson_gxl_write_reg(phydev, BANK_BIST, FR_PLL_DIV0, 0xaaaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* This function is provided to cope with the possible failures of this phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * during aneg process. When aneg fails, the PHY reports that aneg is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * but the value found in MII_LPA is wrong:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  *  - Early failures: MII_LPA is just 0x0001. if MII_EXPANSION reports that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  *    the link partner (LP) supports aneg but the LP never acked our base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  *    code word, it is likely that we never sent it to begin with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  *  - Late failures: MII_LPA is filled with a value which seems to make sense
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  *    but it actually is not what the LP is advertising. It seems that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  *    can detect this using a magic bit in the WOL bank (reg 12 - bit 12).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  *    If this particular bit is not set when aneg is reported being done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  *    it means MII_LPA is likely to be wrong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * In both case, forcing a restart of the aneg process solve the problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * When this failure happens, the first retry is usually successful but,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  * in some cases, it may take up to 6 retries to get a decent result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int meson_gxl_read_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	int ret, wol, lpa, exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (phydev->autoneg == AUTONEG_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		ret = genphy_aneg_done(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		else if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			goto read_status_continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		/* Aneg is done, let's check everything is fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		wol = meson_gxl_read_reg(phydev, BANK_WOL, LPI_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		if (wol < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			return wol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		lpa = phy_read(phydev, MII_LPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		if (lpa < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			return lpa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		exp = phy_read(phydev, MII_EXPANSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		if (exp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		if (!(wol & LPI_STATUS_RSV12) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		    ((exp & EXPANSION_NWAY) && !(lpa & LPA_LPACK))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			/* Looks like aneg failed after all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			phydev_dbg(phydev, "LPA corruption - aneg restart\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			return genphy_restart_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) read_status_continue:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	return genphy_read_status(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static int meson_gxl_ack_interrupt(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	int ret = phy_read(phydev, INTSRC_FLAG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	return ret < 0 ? ret : 0;
^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 meson_gxl_config_intr(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		val = INTSRC_ANEG_PR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			| INTSRC_PARALLEL_FAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			| INTSRC_ANEG_LP_ACK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			| INTSRC_LINK_DOWN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			| INTSRC_REMOTE_FAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			| INTSRC_ANEG_COMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	/* Ack any pending IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	ret = meson_gxl_ack_interrupt(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	return phy_write(phydev, INTSRC_MASK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static struct phy_driver meson_gxl_phy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		PHY_ID_MATCH_EXACT(0x01814400),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		.name		= "Meson GXL Internal PHY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		/* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		.flags		= PHY_IS_INTERNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		.soft_reset     = genphy_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		.config_init	= meson_gxl_config_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		.read_status	= meson_gxl_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		.ack_interrupt	= meson_gxl_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		.config_intr	= meson_gxl_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		.suspend        = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		.resume         = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		PHY_ID_MATCH_EXACT(0x01803301),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		.name		= "Meson G12A Internal PHY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		/* PHY_BASIC_FEATURES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		.flags		= PHY_IS_INTERNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		.soft_reset     = genphy_soft_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		.ack_interrupt	= meson_gxl_ack_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		.config_intr	= meson_gxl_config_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		.suspend        = genphy_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		.resume         = genphy_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	},
^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 struct mdio_device_id __maybe_unused meson_gxl_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	{ PHY_ID_MATCH_VENDOR(0x01814400) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	{ PHY_ID_MATCH_VENDOR(0x01803301) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) module_phy_driver(meson_gxl_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) MODULE_DEVICE_TABLE(mdio, meson_gxl_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) MODULE_DESCRIPTION("Amlogic Meson GXL Internal PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) MODULE_AUTHOR("Baoqi wang");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) MODULE_LICENSE("GPL");