2323
2424#include "mlxbf_gige.h"
2525#include "mlxbf_gige_regs.h"
26+ #include "mlxbf_gige_mdio_bf2.h"
27+ #include "mlxbf_gige_mdio_bf3.h"
2628
27- #define MLXBF_GIGE_MDIO_GW_OFFSET 0x0
28- #define MLXBF_GIGE_MDIO_CFG_OFFSET 0x4
29+ static struct mlxbf_gige_mdio_gw mlxbf_gige_mdio_gw_t [] = {
30+ [MLXBF_GIGE_VERSION_BF2 ] = {
31+ .gw_address = MLXBF2_GIGE_MDIO_GW_OFFSET ,
32+ .read_data_address = MLXBF2_GIGE_MDIO_GW_OFFSET ,
33+ .busy = {
34+ .mask = MLXBF2_GIGE_MDIO_GW_BUSY_MASK ,
35+ .shift = MLXBF2_GIGE_MDIO_GW_BUSY_SHIFT ,
36+ },
37+ .read_data = {
38+ .mask = MLXBF2_GIGE_MDIO_GW_AD_MASK ,
39+ .shift = MLXBF2_GIGE_MDIO_GW_AD_SHIFT ,
40+ },
41+ .write_data = {
42+ .mask = MLXBF2_GIGE_MDIO_GW_AD_MASK ,
43+ .shift = MLXBF2_GIGE_MDIO_GW_AD_SHIFT ,
44+ },
45+ .devad = {
46+ .mask = MLXBF2_GIGE_MDIO_GW_DEVAD_MASK ,
47+ .shift = MLXBF2_GIGE_MDIO_GW_DEVAD_SHIFT ,
48+ },
49+ .partad = {
50+ .mask = MLXBF2_GIGE_MDIO_GW_PARTAD_MASK ,
51+ .shift = MLXBF2_GIGE_MDIO_GW_PARTAD_SHIFT ,
52+ },
53+ .opcode = {
54+ .mask = MLXBF2_GIGE_MDIO_GW_OPCODE_MASK ,
55+ .shift = MLXBF2_GIGE_MDIO_GW_OPCODE_SHIFT ,
56+ },
57+ .st1 = {
58+ .mask = MLXBF2_GIGE_MDIO_GW_ST1_MASK ,
59+ .shift = MLXBF2_GIGE_MDIO_GW_ST1_SHIFT ,
60+ },
61+ },
62+ [MLXBF_GIGE_VERSION_BF3 ] = {
63+ .gw_address = MLXBF3_GIGE_MDIO_GW_OFFSET ,
64+ .read_data_address = MLXBF3_GIGE_MDIO_DATA_READ ,
65+ .busy = {
66+ .mask = MLXBF3_GIGE_MDIO_GW_BUSY_MASK ,
67+ .shift = MLXBF3_GIGE_MDIO_GW_BUSY_SHIFT ,
68+ },
69+ .read_data = {
70+ .mask = MLXBF3_GIGE_MDIO_GW_DATA_READ_MASK ,
71+ .shift = MLXBF3_GIGE_MDIO_GW_DATA_READ_SHIFT ,
72+ },
73+ .write_data = {
74+ .mask = MLXBF3_GIGE_MDIO_GW_DATA_MASK ,
75+ .shift = MLXBF3_GIGE_MDIO_GW_DATA_SHIFT ,
76+ },
77+ .devad = {
78+ .mask = MLXBF3_GIGE_MDIO_GW_DEVAD_MASK ,
79+ .shift = MLXBF3_GIGE_MDIO_GW_DEVAD_SHIFT ,
80+ },
81+ .partad = {
82+ .mask = MLXBF3_GIGE_MDIO_GW_PARTAD_MASK ,
83+ .shift = MLXBF3_GIGE_MDIO_GW_PARTAD_SHIFT ,
84+ },
85+ .opcode = {
86+ .mask = MLXBF3_GIGE_MDIO_GW_OPCODE_MASK ,
87+ .shift = MLXBF3_GIGE_MDIO_GW_OPCODE_SHIFT ,
88+ },
89+ .st1 = {
90+ .mask = MLXBF3_GIGE_MDIO_GW_ST1_MASK ,
91+ .shift = MLXBF3_GIGE_MDIO_GW_ST1_SHIFT ,
92+ },
93+ },
94+ };
2995
3096#define MLXBF_GIGE_MDIO_FREQ_REFERENCE 156250000ULL
3197#define MLXBF_GIGE_MDIO_COREPLL_CONST 16384ULL
47113/* Busy bit is set by software and cleared by hardware */
48114#define MLXBF_GIGE_MDIO_SET_BUSY 0x1
49115
50- /* MDIO GW register bits */
51- #define MLXBF_GIGE_MDIO_GW_AD_MASK GENMASK(15, 0)
52- #define MLXBF_GIGE_MDIO_GW_DEVAD_MASK GENMASK(20, 16)
53- #define MLXBF_GIGE_MDIO_GW_PARTAD_MASK GENMASK(25, 21)
54- #define MLXBF_GIGE_MDIO_GW_OPCODE_MASK GENMASK(27, 26)
55- #define MLXBF_GIGE_MDIO_GW_ST1_MASK GENMASK(28, 28)
56- #define MLXBF_GIGE_MDIO_GW_BUSY_MASK GENMASK(30, 30)
57-
58- /* MDIO config register bits */
59- #define MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK GENMASK(1, 0)
60- #define MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK GENMASK(2, 2)
61- #define MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK GENMASK(4, 4)
62- #define MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK GENMASK(15, 8)
63- #define MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(23, 16)
64- #define MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(31, 24)
65-
66- #define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
67- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
68- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
69- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
70- FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
71-
72116#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30
73117#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c
118+ #define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824
119+ #define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000010
74120
75121static struct resource corepll_params [] = {
76122 [MLXBF_GIGE_VERSION_BF2 ] = {
77123 .start = MLXBF_GIGE_BF2_COREPLL_ADDR ,
78124 .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1 ,
79125 .name = "COREPLL_RES"
80126 },
127+ [MLXBF_GIGE_VERSION_BF3 ] = {
128+ .start = MLXBF_GIGE_BF3_COREPLL_ADDR ,
129+ .end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1 ,
130+ .name = "COREPLL_RES"
131+ }
81132};
82133
83134/* Returns core clock i1clk in Hz */
@@ -134,19 +185,23 @@ static u8 mdio_period_map(struct mlxbf_gige *priv)
134185 return mdio_period ;
135186}
136187
137- static u32 mlxbf_gige_mdio_create_cmd (u16 data , int phy_add ,
188+ static u32 mlxbf_gige_mdio_create_cmd (struct mlxbf_gige_mdio_gw * mdio_gw , u16 data , int phy_add ,
138189 int phy_reg , u32 opcode )
139190{
140191 u32 gw_reg = 0 ;
141192
142- gw_reg |= FIELD_PREP (MLXBF_GIGE_MDIO_GW_AD_MASK , data );
143- gw_reg |= FIELD_PREP (MLXBF_GIGE_MDIO_GW_DEVAD_MASK , phy_reg );
144- gw_reg |= FIELD_PREP (MLXBF_GIGE_MDIO_GW_PARTAD_MASK , phy_add );
145- gw_reg |= FIELD_PREP (MLXBF_GIGE_MDIO_GW_OPCODE_MASK , opcode );
146- gw_reg |= FIELD_PREP (MLXBF_GIGE_MDIO_GW_ST1_MASK ,
147- MLXBF_GIGE_MDIO_CL22_ST1 );
148- gw_reg |= FIELD_PREP (MLXBF_GIGE_MDIO_GW_BUSY_MASK ,
149- MLXBF_GIGE_MDIO_SET_BUSY );
193+ gw_reg |= ((data << mdio_gw -> write_data .shift ) &
194+ mdio_gw -> write_data .mask );
195+ gw_reg |= ((phy_reg << mdio_gw -> devad .shift ) &
196+ mdio_gw -> devad .mask );
197+ gw_reg |= ((phy_add << mdio_gw -> partad .shift ) &
198+ mdio_gw -> partad .mask );
199+ gw_reg |= ((opcode << mdio_gw -> opcode .shift ) &
200+ mdio_gw -> opcode .mask );
201+ gw_reg |= ((MLXBF_GIGE_MDIO_CL22_ST1 << mdio_gw -> st1 .shift ) &
202+ mdio_gw -> st1 .mask );
203+ gw_reg |= ((MLXBF_GIGE_MDIO_SET_BUSY << mdio_gw -> busy .shift ) &
204+ mdio_gw -> busy .mask );
150205
151206 return gw_reg ;
152207}
@@ -162,25 +217,26 @@ static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg)
162217 return - EOPNOTSUPP ;
163218
164219 /* Send mdio read request */
165- cmd = mlxbf_gige_mdio_create_cmd (0 , phy_add , phy_reg , MLXBF_GIGE_MDIO_CL22_READ );
220+ cmd = mlxbf_gige_mdio_create_cmd (priv -> mdio_gw , 0 , phy_add , phy_reg ,
221+ MLXBF_GIGE_MDIO_CL22_READ );
166222
167- writel (cmd , priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET );
223+ writel (cmd , priv -> mdio_io + priv -> mdio_gw -> gw_address );
168224
169- ret = readl_poll_timeout_atomic (priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET ,
170- val , !(val & MLXBF_GIGE_MDIO_GW_BUSY_MASK ),
225+ ret = readl_poll_timeout_atomic (priv -> mdio_io + priv -> mdio_gw -> gw_address ,
226+ val , !(val & priv -> mdio_gw -> busy . mask ),
171227 5 , 1000000 );
172228
173229 if (ret ) {
174- writel (0 , priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET );
230+ writel (0 , priv -> mdio_io + priv -> mdio_gw -> gw_address );
175231 return ret ;
176232 }
177233
178- ret = readl (priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET );
234+ ret = readl (priv -> mdio_io + priv -> mdio_gw -> read_data_address );
179235 /* Only return ad bits of the gw register */
180- ret &= MLXBF_GIGE_MDIO_GW_AD_MASK ;
236+ ret &= priv -> mdio_gw -> read_data . mask ;
181237
182238 /* The MDIO lock is set on read. To release it, clear gw register */
183- writel (0 , priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET );
239+ writel (0 , priv -> mdio_io + priv -> mdio_gw -> gw_address );
184240
185241 return ret ;
186242}
@@ -197,17 +253,17 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
197253 return - EOPNOTSUPP ;
198254
199255 /* Send mdio write request */
200- cmd = mlxbf_gige_mdio_create_cmd (val , phy_add , phy_reg ,
256+ cmd = mlxbf_gige_mdio_create_cmd (priv -> mdio_gw , val , phy_add , phy_reg ,
201257 MLXBF_GIGE_MDIO_CL22_WRITE );
202- writel (cmd , priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET );
258+ writel (cmd , priv -> mdio_io + priv -> mdio_gw -> gw_address );
203259
204260 /* If the poll timed out, drop the request */
205- ret = readl_poll_timeout_atomic (priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET ,
206- temp , !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK ),
261+ ret = readl_poll_timeout_atomic (priv -> mdio_io + priv -> mdio_gw -> gw_address ,
262+ temp , !(temp & priv -> mdio_gw -> busy . mask ),
207263 5 , 1000000 );
208264
209265 /* The MDIO lock is set on read. To release it, clear gw register */
210- writel (0 , priv -> mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET );
266+ writel (0 , priv -> mdio_io + priv -> mdio_gw -> gw_address );
211267
212268 return ret ;
213269}
@@ -219,9 +275,20 @@ static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv)
219275
220276 mdio_period = mdio_period_map (priv );
221277
222- val = MLXBF_GIGE_MDIO_CFG_VAL ;
223- val |= FIELD_PREP (MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK , mdio_period );
224- writel (val , priv -> mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET );
278+ if (priv -> hw_version == MLXBF_GIGE_VERSION_BF2 ) {
279+ val = MLXBF2_GIGE_MDIO_CFG_VAL ;
280+ val |= FIELD_PREP (MLXBF2_GIGE_MDIO_CFG_MDC_PERIOD_MASK , mdio_period );
281+ writel (val , priv -> mdio_io + MLXBF2_GIGE_MDIO_CFG_OFFSET );
282+ } else {
283+ val = FIELD_PREP (MLXBF3_GIGE_MDIO_CFG_MDIO_MODE_MASK , 1 ) |
284+ FIELD_PREP (MLXBF3_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK , 1 );
285+ writel (val , priv -> mdio_io + MLXBF3_GIGE_MDIO_CFG_REG0 );
286+ val = FIELD_PREP (MLXBF3_GIGE_MDIO_CFG_MDC_PERIOD_MASK , mdio_period );
287+ writel (val , priv -> mdio_io + MLXBF3_GIGE_MDIO_CFG_REG1 );
288+ val = FIELD_PREP (MLXBF3_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK , 6 ) |
289+ FIELD_PREP (MLXBF3_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK , 13 );
290+ writel (val , priv -> mdio_io + MLXBF3_GIGE_MDIO_CFG_REG2 );
291+ }
225292}
226293
227294int mlxbf_gige_mdio_probe (struct platform_device * pdev , struct mlxbf_gige * priv )
@@ -230,6 +297,9 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
230297 struct resource * res ;
231298 int ret ;
232299
300+ if (priv -> hw_version > MLXBF_GIGE_VERSION_BF3 )
301+ return - ENODEV ;
302+
233303 priv -> mdio_io = devm_platform_ioremap_resource (pdev , MLXBF_GIGE_RES_MDIO9 );
234304 if (IS_ERR (priv -> mdio_io ))
235305 return PTR_ERR (priv -> mdio_io );
@@ -242,13 +312,15 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
242312 /* For backward compatibility with older ACPI tables, also keep
243313 * CLK resource internal to the driver.
244314 */
245- res = & corepll_params [MLXBF_GIGE_VERSION_BF2 ];
315+ res = & corepll_params [priv -> hw_version ];
246316 }
247317
248318 priv -> clk_io = devm_ioremap (dev , res -> start , resource_size (res ));
249319 if (!priv -> clk_io )
250320 return - ENOMEM ;
251321
322+ priv -> mdio_gw = & mlxbf_gige_mdio_gw_t [priv -> hw_version ];
323+
252324 mlxbf_gige_mdio_cfg (priv );
253325
254326 priv -> mdiobus = devm_mdiobus_alloc (dev );
0 commit comments