dddfcc201869c88038fedebb275faef205266178
[openwrt/staging/stintel.git] /
1 From c1e3f753f6b85d7636024159bb78f764e09492f1 Mon Sep 17 00:00:00 2001
2 From: Heiner Kallweit <hkallweit1@gmail.com>
3 Date: Sun, 10 Feb 2019 19:57:56 +0100
4 Subject: [PATCH 604/660] net: phy: add register modifying helpers returning 1
5 on change
6
7 When modifying registers there are scenarios where we need to know
8 whether the register content actually changed. This patch adds
9 new helpers to not break users of the current ones, phy_modify() etc.
10
11 Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
12 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
13 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
15 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
16 ---
17 drivers/net/phy/phy-core.c | 127 ++++++++++++++++++++++++++++++++++---
18 include/linux/phy.h | 12 +++-
19 2 files changed, 128 insertions(+), 11 deletions(-)
20
21 --- a/drivers/net/phy/phy-core.c
22 +++ b/drivers/net/phy/phy-core.c
23 @@ -364,7 +364,7 @@ int phy_write_mmd(struct phy_device *phy
24 EXPORT_SYMBOL(phy_write_mmd);
25
26 /**
27 - * __phy_modify() - Convenience function for modifying a PHY register
28 + * __phy_modify_changed() - Convenience function for modifying a PHY register
29 * @phydev: a pointer to a &struct phy_device
30 * @regnum: register number
31 * @mask: bit mask of bits to clear
32 @@ -372,16 +372,69 @@ EXPORT_SYMBOL(phy_write_mmd);
33 *
34 * Unlocked helper function which allows a PHY register to be modified as
35 * new register value = (old register value & ~mask) | set
36 + *
37 + * Returns negative errno, 0 if there was no change, and 1 in case of change
38 */
39 -int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
40 +int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
41 + u16 set)
42 {
43 - int ret;
44 + int new, ret;
45
46 ret = __phy_read(phydev, regnum);
47 if (ret < 0)
48 return ret;
49
50 - ret = __phy_write(phydev, regnum, (ret & ~mask) | set);
51 + new = (ret & ~mask) | set;
52 + if (new == ret)
53 + return 0;
54 +
55 + ret = __phy_write(phydev, regnum, new);
56 +
57 + return ret < 0 ? ret : 1;
58 +}
59 +EXPORT_SYMBOL_GPL(__phy_modify_changed);
60 +
61 +/**
62 + * phy_modify_changed - Function for modifying a PHY register
63 + * @phydev: the phy_device struct
64 + * @regnum: register number to modify
65 + * @mask: bit mask of bits to clear
66 + * @set: new value of bits set in mask to write to @regnum
67 + *
68 + * NOTE: MUST NOT be called from interrupt context,
69 + * because the bus read/write functions may wait for an interrupt
70 + * to conclude the operation.
71 + *
72 + * Returns negative errno, 0 if there was no change, and 1 in case of change
73 + */
74 +int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
75 +{
76 + int ret;
77 +
78 + mutex_lock(&phydev->mdio.bus->mdio_lock);
79 + ret = __phy_modify_changed(phydev, regnum, mask, set);
80 + mutex_unlock(&phydev->mdio.bus->mdio_lock);
81 +
82 + return ret;
83 +}
84 +EXPORT_SYMBOL_GPL(phy_modify_changed);
85 +
86 +/**
87 + * __phy_modify - Convenience function for modifying a PHY register
88 + * @phydev: the phy_device struct
89 + * @regnum: register number to modify
90 + * @mask: bit mask of bits to clear
91 + * @set: new value of bits set in mask to write to @regnum
92 + *
93 + * NOTE: MUST NOT be called from interrupt context,
94 + * because the bus read/write functions may wait for an interrupt
95 + * to conclude the operation.
96 + */
97 +int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
98 +{
99 + int ret;
100 +
101 + ret = __phy_modify_changed(phydev, regnum, mask, set);
102
103 return ret < 0 ? ret : 0;
104 }
105 @@ -411,7 +464,7 @@ int phy_modify(struct phy_device *phydev
106 EXPORT_SYMBOL_GPL(phy_modify);
107
108 /**
109 - * __phy_modify_mmd - Convenience function for modifying a register on MMD
110 + * __phy_modify_mmd_changed - Function for modifying a register on MMD
111 * @phydev: the phy_device struct
112 * @devad: the MMD containing register to modify
113 * @regnum: register number to modify
114 @@ -420,17 +473,73 @@ EXPORT_SYMBOL_GPL(phy_modify);
115 *
116 * Unlocked helper function which allows a MMD register to be modified as
117 * new register value = (old register value & ~mask) | set
118 + *
119 + * Returns negative errno, 0 if there was no change, and 1 in case of change
120 */
121 -int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
122 - u16 mask, u16 set)
123 +int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
124 + u16 mask, u16 set)
125 {
126 - int ret;
127 + int new, ret;
128
129 ret = __phy_read_mmd(phydev, devad, regnum);
130 if (ret < 0)
131 return ret;
132
133 - ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set);
134 + new = (ret & ~mask) | set;
135 + if (new == ret)
136 + return 0;
137 +
138 + ret = __phy_write_mmd(phydev, devad, regnum, new);
139 +
140 + return ret < 0 ? ret : 1;
141 +}
142 +EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed);
143 +
144 +/**
145 + * phy_modify_mmd_changed - Function for modifying a register on MMD
146 + * @phydev: the phy_device struct
147 + * @devad: the MMD containing register to modify
148 + * @regnum: register number to modify
149 + * @mask: bit mask of bits to clear
150 + * @set: new value of bits set in mask to write to @regnum
151 + *
152 + * NOTE: MUST NOT be called from interrupt context,
153 + * because the bus read/write functions may wait for an interrupt
154 + * to conclude the operation.
155 + *
156 + * Returns negative errno, 0 if there was no change, and 1 in case of change
157 + */
158 +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
159 + u16 mask, u16 set)
160 +{
161 + int ret;
162 +
163 + mutex_lock(&phydev->mdio.bus->mdio_lock);
164 + ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
165 + mutex_unlock(&phydev->mdio.bus->mdio_lock);
166 +
167 + return ret;
168 +}
169 +EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);
170 +
171 +/**
172 + * __phy_modify_mmd - Convenience function for modifying a register on MMD
173 + * @phydev: the phy_device struct
174 + * @devad: the MMD containing register to modify
175 + * @regnum: register number to modify
176 + * @mask: bit mask of bits to clear
177 + * @set: new value of bits set in mask to write to @regnum
178 + *
179 + * NOTE: MUST NOT be called from interrupt context,
180 + * because the bus read/write functions may wait for an interrupt
181 + * to conclude the operation.
182 + */
183 +int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
184 + u16 mask, u16 set)
185 +{
186 + int ret;
187 +
188 + ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
189
190 return ret < 0 ? ret : 0;
191 }
192 --- a/include/linux/phy.h
193 +++ b/include/linux/phy.h
194 @@ -795,13 +795,21 @@ int phy_write_mmd(struct phy_device *phy
195 */
196 int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
197
198 +int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
199 + u16 set);
200 +int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask,
201 + u16 set);
202 int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
203 int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
204
205 +int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
206 + u16 mask, u16 set);
207 +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
208 + u16 mask, u16 set);
209 int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
210 - u16 mask, u16 set);
211 + u16 mask, u16 set);
212 int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
213 - u16 mask, u16 set);
214 + u16 mask, u16 set);
215
216 /**
217 * __phy_set_bits - Convenience function for setting bits in a PHY register