a628a37929190f45a717eb8a5a03996d4b90f885
[openwrt/staging/981213.git] /
1 From d63710fc0f1a501fd75a7025e3070a96ffa1645f Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Fri, 15 Dec 2023 14:15:34 +0100
4 Subject: [PATCH 4/4] net: phy: add support for PHY package MMD read/write
5
6 Some PHY in PHY package may require to read/write MMD regs to correctly
7 configure the PHY package.
8
9 Add support for these additional required function in both lock and no
10 lock variant.
11
12 It's assumed that the entire PHY package is either C22 or C45. We use
13 C22 or C45 way of writing/reading to mmd regs based on the passed phydev
14 whether it's C22 or C45.
15
16 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
17 Signed-off-by: David S. Miller <davem@davemloft.net>
18 ---
19 drivers/net/phy/phy-core.c | 140 +++++++++++++++++++++++++++++++++++++
20 include/linux/phy.h | 16 +++++
21 2 files changed, 156 insertions(+)
22
23 --- a/drivers/net/phy/phy-core.c
24 +++ b/drivers/net/phy/phy-core.c
25 @@ -639,6 +639,146 @@ int phy_write_mmd(struct phy_device *phy
26 EXPORT_SYMBOL(phy_write_mmd);
27
28 /**
29 + * __phy_package_read_mmd - read MMD reg relative to PHY package base addr
30 + * @phydev: The phy_device struct
31 + * @addr_offset: The offset to be added to PHY package base_addr
32 + * @devad: The MMD to read from
33 + * @regnum: The register on the MMD to read
34 + *
35 + * Convenience helper for reading a register of an MMD on a given PHY
36 + * using the PHY package base address. The base address is added to
37 + * the addr_offset value.
38 + *
39 + * Same calling rules as for __phy_read();
40 + *
41 + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
42 + */
43 +int __phy_package_read_mmd(struct phy_device *phydev,
44 + unsigned int addr_offset, int devad,
45 + u32 regnum)
46 +{
47 + int addr = phy_package_address(phydev, addr_offset);
48 +
49 + if (addr < 0)
50 + return addr;
51 +
52 + if (regnum > (u16)~0 || devad > 32)
53 + return -EINVAL;
54 +
55 + return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
56 + regnum);
57 +}
58 +EXPORT_SYMBOL(__phy_package_read_mmd);
59 +
60 +/**
61 + * phy_package_read_mmd - read MMD reg relative to PHY package base addr
62 + * @phydev: The phy_device struct
63 + * @addr_offset: The offset to be added to PHY package base_addr
64 + * @devad: The MMD to read from
65 + * @regnum: The register on the MMD to read
66 + *
67 + * Convenience helper for reading a register of an MMD on a given PHY
68 + * using the PHY package base address. The base address is added to
69 + * the addr_offset value.
70 + *
71 + * Same calling rules as for phy_read();
72 + *
73 + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
74 + */
75 +int phy_package_read_mmd(struct phy_device *phydev,
76 + unsigned int addr_offset, int devad,
77 + u32 regnum)
78 +{
79 + int addr = phy_package_address(phydev, addr_offset);
80 + int val;
81 +
82 + if (addr < 0)
83 + return addr;
84 +
85 + if (regnum > (u16)~0 || devad > 32)
86 + return -EINVAL;
87 +
88 + phy_lock_mdio_bus(phydev);
89 + val = mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,
90 + regnum);
91 + phy_unlock_mdio_bus(phydev);
92 +
93 + return val;
94 +}
95 +EXPORT_SYMBOL(phy_package_read_mmd);
96 +
97 +/**
98 + * __phy_package_write_mmd - write MMD reg relative to PHY package base addr
99 + * @phydev: The phy_device struct
100 + * @addr_offset: The offset to be added to PHY package base_addr
101 + * @devad: The MMD to write to
102 + * @regnum: The register on the MMD to write
103 + * @val: value to write to @regnum
104 + *
105 + * Convenience helper for writing a register of an MMD on a given PHY
106 + * using the PHY package base address. The base address is added to
107 + * the addr_offset value.
108 + *
109 + * Same calling rules as for __phy_write();
110 + *
111 + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
112 + */
113 +int __phy_package_write_mmd(struct phy_device *phydev,
114 + unsigned int addr_offset, int devad,
115 + u32 regnum, u16 val)
116 +{
117 + int addr = phy_package_address(phydev, addr_offset);
118 +
119 + if (addr < 0)
120 + return addr;
121 +
122 + if (regnum > (u16)~0 || devad > 32)
123 + return -EINVAL;
124 +
125 + return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
126 + regnum, val);
127 +}
128 +EXPORT_SYMBOL(__phy_package_write_mmd);
129 +
130 +/**
131 + * phy_package_write_mmd - write MMD reg relative to PHY package base addr
132 + * @phydev: The phy_device struct
133 + * @addr_offset: The offset to be added to PHY package base_addr
134 + * @devad: The MMD to write to
135 + * @regnum: The register on the MMD to write
136 + * @val: value to write to @regnum
137 + *
138 + * Convenience helper for writing a register of an MMD on a given PHY
139 + * using the PHY package base address. The base address is added to
140 + * the addr_offset value.
141 + *
142 + * Same calling rules as for phy_write();
143 + *
144 + * NOTE: It's assumed that the entire PHY package is either C22 or C45.
145 + */
146 +int phy_package_write_mmd(struct phy_device *phydev,
147 + unsigned int addr_offset, int devad,
148 + u32 regnum, u16 val)
149 +{
150 + int addr = phy_package_address(phydev, addr_offset);
151 + int ret;
152 +
153 + if (addr < 0)
154 + return addr;
155 +
156 + if (regnum > (u16)~0 || devad > 32)
157 + return -EINVAL;
158 +
159 + phy_lock_mdio_bus(phydev);
160 + ret = mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,
161 + regnum, val);
162 + phy_unlock_mdio_bus(phydev);
163 +
164 + return ret;
165 +}
166 +EXPORT_SYMBOL(phy_package_write_mmd);
167 +
168 +/**
169 * phy_modify_changed - Function for modifying a PHY register
170 * @phydev: the phy_device struct
171 * @regnum: register number to modify
172 --- a/include/linux/phy.h
173 +++ b/include/linux/phy.h
174 @@ -1840,6 +1840,22 @@ static inline int __phy_package_write(st
175 return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
176 }
177
178 +int __phy_package_read_mmd(struct phy_device *phydev,
179 + unsigned int addr_offset, int devad,
180 + u32 regnum);
181 +
182 +int phy_package_read_mmd(struct phy_device *phydev,
183 + unsigned int addr_offset, int devad,
184 + u32 regnum);
185 +
186 +int __phy_package_write_mmd(struct phy_device *phydev,
187 + unsigned int addr_offset, int devad,
188 + u32 regnum, u16 val);
189 +
190 +int phy_package_write_mmd(struct phy_device *phydev,
191 + unsigned int addr_offset, int devad,
192 + u32 regnum, u16 val);
193 +
194 static inline bool __phy_package_set_once(struct phy_device *phydev,
195 unsigned int b)
196 {