blob: 731a37dee16b279042f1b89283724b2daa5984e5 [file] [log] [blame]
developer5e9bfbf2023-09-01 13:53:52 +08001// SPDX-License-Identifier: GPL-2.0+
2/*************************************************
3 * FILE NAME: air_en8811h_api.c
4 * PURPOSE:
5 * EN8811H PHY Driver for Linux
6 * NOTES:
7 *
8 * Copyright (C) 2023 Airoha Technology Corp.
9 *************************************************/
10
11/* INCLUDE FILE DECLARATIONS
12*/
13#include <linux/uaccess.h>
14#include <linux/trace_seq.h>
15#include <linux/seq_file.h>
16#include <linux/u64_stats_sync.h>
17#include <linux/dma-mapping.h>
18#include <linux/netdevice.h>
19#include <linux/ctype.h>
20#include <linux/of_mdio.h>
21#include <linux/of_address.h>
22#include <linux/mii.h>
23#include <linux/phy.h>
24#include <linux/debugfs.h>
25
26#include "air_en8811h.h"
27#include "air_en8811h_api.h"
28
29/*
30struct air_phy_debug {
31 struct dentry *root;
32};
33struct air_phy_debug air_debug;
34*/
35
36static const char * const tx_rx_string[32] = {
37 "Tx Reverse, Rx Normal",
38 "Tx Normal, Rx Normal",
39 "Tx Reverse, Rx Reverse",
40 "Tx Normal, Rx Reverse",
41};
42
43/* Airoha MII read function */
44static int __air_mii_cl22_read(struct mii_bus *ebus,
45 int addr, unsigned int phy_register)
46{
47 int read_data;
48#if (KERNEL_VERSION(4, 16, 0) < LINUX_VERSION_CODE)
49 read_data = __mdiobus_read(ebus, addr, phy_register);
50#else
51 read_data = ebus->read(ebus, addr, phy_register);
52#endif
53 return read_data;
54}
55/* Airoha MII write function */
56static int __air_mii_cl22_write(struct mii_bus *ebus, int addr,
57 unsigned int phy_register, unsigned int write_data)
58{
59 int ret = 0;
60#if (KERNEL_VERSION(4, 16, 0) < LINUX_VERSION_CODE)
61 ret = __mdiobus_write(ebus, addr, phy_register, write_data);
62#else
63 ret = ebus->write(ebus, addr, phy_register, write_data);
64#endif
65 return ret;
66}
67
68/* Airoha MII read function */
69int air_mii_cl22_read(struct mii_bus *ebus, int addr, unsigned int phy_register)
70{
71 int read_data;
72
73 mutex_lock(&ebus->mdio_lock);
74 read_data = __air_mii_cl22_read(ebus, addr, phy_register);
75 mutex_unlock(&ebus->mdio_lock);
76 return read_data;
77}
78/* Airoha MII write function */
79int air_mii_cl22_write(struct mii_bus *ebus, int addr,
80 unsigned int phy_register, unsigned int write_data)
81{
82 int ret = 0;
83
84 mutex_lock(&ebus->mdio_lock);
85 ret = __air_mii_cl22_write(ebus, addr, phy_register, write_data);
86 mutex_unlock(&ebus->mdio_lock);
87 return ret;
88}
89
90static int __air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg)
91{
92 int ret = 0;
93 int data;
94 struct device *dev = phydev_dev(phydev);
95 struct mii_bus *mbus = phydev_mdio_bus(phydev);
96 int addr = phydev_addr(phydev);
97
98 ret |= __air_mii_cl22_write(mbus, addr, MII_MMD_ACC_CTL_REG, devad);
99 ret |= __air_mii_cl22_write(mbus, addr, MII_MMD_ADDR_DATA_REG, reg);
100 ret |= __air_mii_cl22_write(mbus, addr,
101 MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
102 if (ret) {
103 dev_err(dev, "__air_mii_cl22_write, ret: %d\n", ret);
104 return INVALID_DATA;
105 }
106 data = __air_mii_cl22_read(mbus, addr, MII_MMD_ADDR_DATA_REG);
107 return data;
108}
109
110static int __air_mii_cl45_write(struct phy_device *phydev,
111 int devad, u16 reg, u16 write_data)
112{
113 int ret = 0;
114 struct device *dev = phydev_dev(phydev);
115 struct mii_bus *mbus = phydev_mdio_bus(phydev);
116 int addr = phydev_addr(phydev);
117
118 ret |= __air_mii_cl22_write(mbus, addr, MII_MMD_ACC_CTL_REG, devad);
119 ret |= __air_mii_cl22_write(mbus, addr, MII_MMD_ADDR_DATA_REG, reg);
120 ret |= __air_mii_cl22_write(mbus, addr,
121 MII_MMD_ACC_CTL_REG, MMD_OP_MODE_DATA | devad);
122 ret |= __air_mii_cl22_write(mbus, addr,
123 MII_MMD_ADDR_DATA_REG, write_data);
124 if (ret) {
125 dev_err(dev, "__air_mii_cl22_write, ret: %d\n", ret);
126 return ret;
127 }
128 return 0;
129}
130
131int air_mii_cl45_read(struct phy_device *phydev, int devad, u16 reg)
132{
133 int data;
134 struct device *dev = phydev_dev(phydev);
135 struct mii_bus *mbus = phydev_mdio_bus(phydev);
136
137 mutex_lock(&mbus->mdio_lock);
138 data = __air_mii_cl45_read(phydev, devad, reg);
139 mutex_unlock(&mbus->mdio_lock);
140 if (data == INVALID_DATA) {
141 dev_err(dev, "__airoha_cl45_read fail\n");
142 return INVALID_DATA;
143 }
144 return data;
145}
146
147int air_mii_cl45_write(struct phy_device *phydev,
148 int devad, u16 reg, u16 write_data)
149{
150 int ret = 0;
151 struct device *dev = phydev_dev(phydev);
152 struct mii_bus *mbus = phydev_mdio_bus(phydev);
153
154 mutex_lock(&mbus->mdio_lock);
155 ret |= __air_mii_cl45_write(phydev, devad, reg, write_data);
156 mutex_unlock(&mbus->mdio_lock);
157 if (ret) {
158 dev_err(dev, "__airoha_cl45_write, ret: %d\n", ret);
159 return ret;
160 }
161 return ret;
162}
163
164/* EN8811H PBUS read function */
165static unsigned int __air_pbus_reg_read(struct phy_device *phydev,
166 unsigned int pbus_address)
167{
168 struct mii_bus *mbus = phydev_mdio_bus(phydev);
169 int addr = phydev_addr(phydev);
170 struct device *dev = phydev_dev(phydev);
171 unsigned int pbus_data_low, pbus_data_high;
172 unsigned int pbus_data;
173 int ret = 0;
174
175 ret |= __air_mii_cl22_write(mbus, (addr + 8),
176 0x1F, (pbus_address >> 6));
177 pbus_data_low = __air_mii_cl22_read(mbus, (addr + 8),
178 ((pbus_address >> 2) & 0xf));
179 pbus_data_high = __air_mii_cl22_read(mbus, (addr + 8), 0x10);
180 pbus_data = (pbus_data_high << 16) + pbus_data_low;
181 if (ret) {
182 dev_err(dev, "%s: ret: %d\n", __func__, ret);
183 return ret;
184 }
185 return pbus_data;
186}
187
188unsigned int air_pbus_reg_read(struct phy_device *phydev,
189 unsigned int pbus_address)
190{
191 struct mii_bus *mbus = phydev_mdio_bus(phydev);
192 struct device *dev = phydev_dev(phydev);
193 int ret = 0;
194 unsigned int data;
195
196 mutex_lock(&mbus->mdio_lock);
197 data = __air_pbus_reg_read(phydev, pbus_address);
198 mutex_unlock(&mbus->mdio_lock);
199 if (ret) {
200 dev_err(dev, "%s: ret: %d\n", __func__, ret);
201 return ret;
202 }
203 return data;
204}
205
206/* EN8811H PBUS write function */
207static int __air_pbus_reg_write(struct phy_device *phydev,
208 unsigned int pbus_address, unsigned long pbus_data)
209{
210 struct mii_bus *mbus = phydev_mdio_bus(phydev);
211 int addr = phydev_addr(phydev);
212 struct device *dev = phydev_dev(phydev);
213 int ret = 0;
214
215 ret |= __air_mii_cl22_write(mbus, (addr + 8),
216 0x1F, (pbus_address >> 6));
217 ret |= __air_mii_cl22_write(mbus, (addr + 8),
218 ((pbus_address >> 2) & 0xf), (pbus_data & 0xFFFF));
219 ret |= __air_mii_cl22_write(mbus, (addr + 8),
220 0x10, (pbus_data >> 16));
221 if (ret) {
222 dev_err(dev, "%s: ret: %d\n", __func__, ret);
223 return ret;
224 }
225 return 0;
226}
227
228int air_pbus_reg_write(struct phy_device *phydev,
229 unsigned int pbus_address, unsigned int pbus_data)
230{
231 struct mii_bus *mbus = phydev_mdio_bus(phydev);
232 struct device *dev = phydev_dev(phydev);
233 int ret = 0;
234
235 mutex_lock(&mbus->mdio_lock);
236 ret |= __air_pbus_reg_write(phydev, pbus_address, pbus_data);
237 mutex_unlock(&mbus->mdio_lock);
238 if (ret) {
239 dev_err(dev, "%s: ret: %d\n", __func__, ret);
240 return ret;
241 }
242 return 0;
243}
244/* EN8811H BUCK write function */
245static int __air_buckpbus_reg_write(struct phy_device *phydev,
246 unsigned int pbus_address, unsigned int pbus_data)
247{
248 int ret = 0;
249 struct device *dev = phydev_dev(phydev);
250 struct mii_bus *mbus = phydev_mdio_bus(phydev);
251 int addr = phydev_addr(phydev);
252
253 /* page 4 */
254 ret |= __air_mii_cl22_write(mbus, addr, 0x1F, 4);
255 ret |= __air_mii_cl22_write(mbus, addr, 0x10, 0);
256 ret |= __air_mii_cl22_write(mbus, addr,
257 0x11, ((pbus_address >> 16) & 0xffff));
258 ret |= __air_mii_cl22_write(mbus, addr,
259 0x12, (pbus_address & 0xffff));
260 ret |= __air_mii_cl22_write(mbus, addr,
261 0x13, ((pbus_data >> 16) & 0xffff));
262 ret |= __air_mii_cl22_write(mbus, addr, 0x14, (pbus_data & 0xffff));
263 ret |= __air_mii_cl22_write(mbus, addr, 0x1F, 0);
264 if (ret < 0) {
265 dev_err(dev, "__air_mii_cl22_write, ret: %d\n", ret);
266 return ret;
267 }
268 return 0;
269}
270
271/* EN8811H BUCK read function */
272static unsigned int __air_buckpbus_reg_read(struct phy_device *phydev,
273 unsigned int pbus_address)
274{
275 unsigned int pbus_data = 0, pbus_data_low, pbus_data_high;
276 int ret = 0;
277 struct device *dev = phydev_dev(phydev);
278 struct mii_bus *mbus = phydev_mdio_bus(phydev);
279 int addr = phydev_addr(phydev);
280
281 /* page 4 */
282 ret |= __air_mii_cl22_write(mbus, addr, 0x1F, 4);
283 ret |= __air_mii_cl22_write(mbus, addr, 0x10, 0);
284 ret |= __air_mii_cl22_write(mbus, addr,
285 0x15, ((pbus_address >> 16) & 0xffff));
286 ret |= __air_mii_cl22_write(mbus, addr,
287 0x16, (pbus_address & 0xffff));
288 if (ret) {
289 dev_err(dev, "__air_mii_cl22_write, ret: %d\n", ret);
290 return PBUS_INVALID_DATA;
291 }
292
293 pbus_data_high = __air_mii_cl22_read(mbus, addr, 0x17);
294 pbus_data_low = __air_mii_cl22_read(mbus, addr, 0x18);
295 pbus_data = (pbus_data_high << 16) + pbus_data_low;
296 ret |= __air_mii_cl22_write(mbus, addr, 0x1F, 0);
297 if (ret) {
298 dev_err(dev, "__air_mii_cl22_write, ret: %d\n", ret);
299 return ret;
300 }
301 return pbus_data;
302}
303
304unsigned int air_buckpbus_reg_read(struct phy_device *phydev,
305 unsigned int pbus_address)
306{
307 unsigned int data;
308 struct device *dev = phydev_dev(phydev);
309 struct mii_bus *mbus = phydev_mdio_bus(phydev);
310
311 mutex_lock(&mbus->mdio_lock);
312 data = __air_buckpbus_reg_read(phydev, pbus_address);
313 mutex_unlock(&mbus->mdio_lock);
314 if (data == INVALID_DATA) {
315 dev_err(dev, "__air_buckpbus_reg_read fail\n");
316 return INVALID_DATA;
317 }
318 return data;
319}
320
321int air_buckpbus_reg_write(struct phy_device *phydev,
322 unsigned int pbus_address, unsigned int pbus_data)
323{
324 int ret = 0;
325 struct device *dev = phydev_dev(phydev);
326 struct mii_bus *mbus = phydev_mdio_bus(phydev);
327
328 mutex_lock(&mbus->mdio_lock);
329 ret |= __air_buckpbus_reg_write(phydev, pbus_address, pbus_data);
330 mutex_unlock(&mbus->mdio_lock);
331 if (ret) {
332 dev_err(dev, "__air_buckpbus_reg_write, ret: %d\n", ret);
333 return ret;
334 }
335 return ret;
336}
337
338static int air_resolve_an_speed(struct phy_device *phydev)
339{
340 int lpagb = 0, advgb = 0, common_adv_gb = 0;
341 int lpa = 0, adv = 0, common_adv = 0;
342 struct device *dev = phydev_dev(phydev);
343 struct mii_bus *mbus = phydev_mdio_bus(phydev);
344 int addr = phydev_addr(phydev);
345
346 dev_dbg(dev, "AN mode!\n");
347 dev_dbg(dev, "SPEED 1000/100!\n");
348 lpagb = air_mii_cl22_read(mbus,
349 addr, MII_STAT1000);
350 if (lpagb < 0)
351 return lpagb;
352 advgb = air_mii_cl22_read(mbus,
353 addr, MII_CTRL1000);
354 if (adv < 0)
355 return adv;
356 common_adv_gb = (lpagb & (advgb << 2));
357
358 lpa = air_mii_cl22_read(mbus, addr, MII_LPA);
359 if (lpa < 0)
360 return lpa;
361 adv = air_mii_cl22_read(mbus,
362 addr, MII_ADVERTISE);
363 if (adv < 0)
364 return adv;
365 phydev->pause = GET_BIT(adv, 10);
366 phydev->asym_pause = GET_BIT(adv, 11);
367 common_adv = (lpa & adv);
368
369 phydev->speed = SPEED_UNKNOWN;
370 phydev->duplex = DUPLEX_HALF;
371 if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) {
372 phydev->speed = SPEED_1000;
373 if (common_adv_gb & LPA_1000FULL)
374 phydev->duplex = DUPLEX_FULL;
375 } else if (common_adv & (LPA_100FULL | LPA_100HALF)) {
376 phydev->speed = SPEED_100;
377 if (common_adv & LPA_100FULL)
378 phydev->duplex = DUPLEX_FULL;
379 } else {
380 if (common_adv & LPA_10FULL)
381 phydev->duplex = DUPLEX_FULL;
382 }
383 return 0;
384}
385
386int air_get_autonego(struct phy_device *phydev, int *an)
387{
388 int reg;
389 struct mii_bus *mbus = phydev_mdio_bus(phydev);
390 int addr = phydev_addr(phydev);
391
392 reg = air_mii_cl22_read(mbus, addr, MII_BMCR);
393 if (reg < 0)
394 return -EINVAL;
395 if (reg & BMCR_ANENABLE)
396 *an = AUTONEG_ENABLE;
397 else
398 *an = AUTONEG_DISABLE;
399 return 0;
400}
401
402static int air_read_status(struct phy_device *phydev)
403{
404 int ret = 0, reg = 0, an = AUTONEG_DISABLE, bmcr = 0;
405 u32 pbus_value = 0;
406 struct device *dev = phydev_dev(phydev);
407 struct mii_bus *mbus = phydev_mdio_bus(phydev);
408 int addr = phydev_addr(phydev);
409
410 phydev->speed = SPEED_UNKNOWN;
411 phydev->duplex = DUPLEX_UNKNOWN;
412 phydev->pause = 0;
413 phydev->asym_pause = 0;
414 phydev->link = 0;
415 phydev->autoneg = AUTONEG_DISABLE;
416 reg = air_mii_cl22_read(mbus, addr, MII_BMSR);
417 if (reg < 0) {
418 dev_err(dev, "MII_BMSR reg %d!\n", reg);
419 return reg;
420 }
421 reg = air_mii_cl22_read(mbus, addr, MII_BMSR);
422 if (reg < 0) {
423 dev_err(dev, "MII_BMSR reg %d!\n", reg);
424 return reg;
425 }
426 if (reg & BMSR_LSTATUS) {
427 phydev->link = 1;
428 ret = air_get_autonego(phydev, &an);
429 if (ret < 0)
430 return ret;
431 phydev->autoneg = an;
432 pbus_value = air_buckpbus_reg_read(phydev, 0x109D4);
433 if (0x10 & pbus_value) {
434 phydev->speed = SPEED_2500;
435 phydev->duplex = DUPLEX_FULL;
436 } else {
437 ret = air_get_autonego(phydev, &an);
438 if (phydev->autoneg == AUTONEG_ENABLE) {
439 ret = air_resolve_an_speed(phydev);
440 if (ret < 0)
441 return ret;
442 } else {
443 dev_dbg(dev, "Force mode!\n");
444 bmcr = air_mii_cl22_read(mbus, addr, MII_BMCR);
445
446 if (bmcr < 0)
447 return bmcr;
448
449 if (bmcr & BMCR_FULLDPLX)
450 phydev->duplex = DUPLEX_FULL;
451 else
452 phydev->duplex = DUPLEX_HALF;
453
454 if (bmcr & BMCR_SPEED1000)
455 phydev->speed = SPEED_1000;
456 else if (bmcr & BMCR_SPEED100)
457 phydev->speed = SPEED_100;
458 else
459 phydev->speed = SPEED_UNKNOWN;
460 }
461 }
462 }
463
464 return ret;
465}
466#ifdef CONFIG_AIROHA_EN8811H_PHY_DEBUGFS
467static void air_polarity_help(void)
468{
469 pr_notice("\nUsage:\n"
470 "[debugfs] = /sys/kernel/debug/mdio-bus\':[phy_addr]\n"
471 "echo [tx polarity] [rx polarity] > /[debugfs]/polarity\n"
472 "option: tx_normal, tx_reverse, rx_normal, rx_revers\n");
473}
474
475static int air_set_polarity(struct phy_device *phydev, int tx_rx)
476{
477 int ret = 0;
478 unsigned int pbus_data = 0;
479
480 pr_debug("\nPolarit %s\n", tx_rx_string[tx_rx]);
481 pbus_data = air_buckpbus_reg_read(phydev, 0xca0f8) & ~(BIT(0) | BIT(1));
482 pbus_data |= tx_rx;
483 ret = air_buckpbus_reg_write(phydev, 0xca0f8, pbus_data);
484 if (ret < 0)
485 pr_notice("\n%s:air_buckpbus_reg_write fail\n", __func__);
486 pbus_data = air_buckpbus_reg_read(phydev, 0xca0f8);
487 pr_notice("\nPolarity %s confirm....(%02lx)\n",
488 tx_rx_string[tx_rx], pbus_data & (BIT(0) | BIT(1)));
489
490 return ret;
491}
492
493static int air_set_mode(struct phy_device *phydev, int dbg_mode)
494{
495 int ret = 0, val = 0;
496 unsigned int pbus_data = 0;
497 struct mii_bus *mbus = phydev_mdio_bus(phydev);
498 int addr = phydev_addr(phydev);
499
500 switch (dbg_mode) {
501 case AIR_PORT_MODE_FORCE_100:
502 pr_notice("\nForce 100M\n");
503 val = air_mii_cl22_read(mbus, addr, MII_ADVERTISE) | BIT(8);
504 ret = air_mii_cl22_write(mbus, addr, MII_ADVERTISE, val);
505 if (unlikely(ret < 0))
506 break;
507 val = air_mii_cl22_read(mbus, addr, MII_CTRL1000) & ~BIT(9);
508 ret = air_mii_cl22_write(mbus, addr, MII_CTRL1000, val);
509 if (unlikely(ret < 0))
510 break;
511 val = air_mii_cl45_read(phydev, 0x7, 0x20) & ~BIT(7);
512 ret = air_mii_cl45_write(phydev, 0x7, 0x20, val);
513 if (unlikely(ret < 0))
514 break;
515 val = air_mii_cl22_read(mbus, addr, MII_BMCR) | BIT(9);
516 ret = air_mii_cl22_write(mbus, addr, MII_BMCR, val);
517 if (unlikely(ret < 0))
518 break;
519 break;
520 case AIR_PORT_MODE_FORCE_1000:
521 pr_notice("\nForce 1000M\n");
522 val = air_mii_cl22_read(mbus, addr, MII_ADVERTISE) & ~BIT(8);
523 ret = air_mii_cl22_write(mbus, addr, MII_ADVERTISE, val);
524 if (unlikely(ret < 0))
525 break;
526 val = air_mii_cl22_read(mbus, addr, MII_CTRL1000) | BIT(9);
527 ret = air_mii_cl22_write(mbus, addr, MII_CTRL1000, val);
528 if (unlikely(ret < 0))
529 break;
530 val = air_mii_cl45_read(phydev, 0x7, 0x20) & ~BIT(7);
531 ret = air_mii_cl45_write(phydev, 0x7, 0x20, val);
532 if (unlikely(ret < 0))
533 break;
534 val = air_mii_cl22_read(mbus, addr, MII_BMCR) | BIT(9);
535 ret = air_mii_cl22_write(mbus, addr, MII_BMCR, val);
536 if (unlikely(ret < 0))
537 break;
538 break;
539 case AIR_PORT_MODE_FORCE_2500:
540 pr_notice("\nForce 2500M\n");
541 val = air_mii_cl22_read(mbus, addr, MII_ADVERTISE) & ~BIT(8);
542 ret = air_mii_cl22_write(mbus, addr, MII_ADVERTISE, val);
543 if (unlikely(ret < 0))
544 break;
545 val = air_mii_cl22_read(mbus, addr, MII_CTRL1000) & ~BIT(9);
546 ret = air_mii_cl22_write(mbus, addr, MII_CTRL1000, val);
547 if (unlikely(ret < 0))
548 break;
549 val = air_mii_cl45_read(phydev, 0x7, 0x20) | BIT(7);
550 ret = air_mii_cl45_write(phydev, 0x7, 0x20, val);
551 if (unlikely(ret < 0))
552 break;
553 val = air_mii_cl22_read(mbus, addr, MII_BMCR) | BIT(9);
554 ret = air_mii_cl22_write(mbus, addr, MII_BMCR, val);
555 if (unlikely(ret < 0))
556 break;
557 break;
558 case AIR_PORT_MODE_AUTONEGO:
559 pr_notice("\nAutonego mode\n");
560 val = air_mii_cl22_read(mbus, addr, MII_ADVERTISE) | BIT(8);
561 ret = air_mii_cl22_write(mbus, addr, MII_ADVERTISE, val);
562 if (unlikely(ret < 0))
563 break;
564 val = air_mii_cl22_read(mbus, addr, MII_CTRL1000) | BIT(9);
565 ret = air_mii_cl22_write(mbus, addr, MII_CTRL1000, val);
566 if (unlikely(ret < 0))
567 break;
568 val = air_mii_cl45_read(phydev, 0x7, 0x20) | BIT(7);
569 ret = air_mii_cl45_write(phydev, 0x7, 0x20, val);
570 if (unlikely(ret < 0))
571 break;
572 val = air_mii_cl22_read(mbus, addr, MII_BMCR) | BIT(9);
573 ret = air_mii_cl22_write(mbus, addr, MII_BMCR, val);
574 if (unlikely(ret < 0))
575 break;
576 break;
577 case AIR_PORT_MODE_POWER_DOWN:
578 pr_notice("\nPower Down\n");
579 val = air_mii_cl22_read(mbus, addr, MII_BMCR) | BIT(11);
580 ret = air_mii_cl22_write(mbus, addr, MII_BMCR, val);
581 if (unlikely(ret < 0))
582 break;
583 break;
584 case AIR_PORT_MODE_POWER_UP:
585 pr_notice("\nPower Up\n");
586 val = air_mii_cl22_read(mbus, addr, MII_BMCR) & ~BIT(11);
587 ret = air_mii_cl22_write(mbus, addr, MII_BMCR, val);
588 if (unlikely(ret < 0))
589 break;
590 break;
591 case AIR_PORT_MODE_FC_DIS:
592 pr_notice("\nFlow Control Disabled\n");
593 pbus_data = air_buckpbus_reg_read(phydev, 0xe0008);
594 pbus_data &= ~(BIT(6) | BIT(7));
595 ret = air_buckpbus_reg_write(phydev, 0xe0008, pbus_data);
596 if (unlikely(ret < 0))
597 break;
598 pbus_data = air_buckpbus_reg_read(phydev, 0xe000c);
599 pbus_data &= ~(BIT(0) | BIT(1));
600 ret = air_buckpbus_reg_write(phydev, 0xe000c, pbus_data);
601 if (unlikely(ret < 0))
602 break;
603 break;
604 case AIR_PORT_MODE_FC_EN:
605 pr_notice("\nFlow Control Enabled\n");
606 pbus_data = air_buckpbus_reg_read(phydev, 0xe0008);
607 pbus_data |= (BIT(6) | BIT(7));
608 ret = air_buckpbus_reg_write(phydev, 0xe0008, pbus_data);
609 if (unlikely(ret < 0))
610 break;
611 pbus_data = air_buckpbus_reg_read(phydev, 0xe000c);
612 pbus_data |= (BIT(0) | BIT(1));
613 ret = air_buckpbus_reg_write(phydev, 0xe000c, pbus_data);
614 if (unlikely(ret < 0))
615 break;
616 break;
617 default:
618 pr_notice("\nWrong Port mode\n");
619 break;
620 }
621 return ret;
622}
623
624static int airphy_info_show(struct seq_file *seq, void *v)
625{
626 struct phy_device *phydev = seq->private;
627 struct en8811h_priv *priv = phydev->priv;
628 unsigned int val = 0;
629
630 seq_puts(seq, "<<AIR EN8811H Driver info>>\n");
631 seq_printf(seq, "| Driver Version : %s\n",
632 EN8811H_DRIVER_VERSION);
633 val = air_buckpbus_reg_read(phydev, 0xcf914);
634 seq_printf(seq, "| Boot mode : %s\n",
635 ((val & BIT(24)) >> 24) ? "Flash" : "Download Code");
636 seq_printf(seq, "| EthMD32.dm.bin CRC32: %08x\n",
637 priv->dm_crc32);
638 seq_printf(seq, "| EthMD32.DSP.bin CRC32: %08x\n",
639 priv->dsp_crc32);
640 val = air_buckpbus_reg_read(phydev, 0x3b3c);
641 seq_printf(seq, "| MD32 FW Version : %08x\n", val);
642 val = air_mii_cl45_read(phydev, 0x1e, 0x8009);
643 seq_printf(seq, "| MD32 FW Status : %08x\n",
644 air_mii_cl45_read(phydev, 0x1e, 0x8009));
645 val = (air_buckpbus_reg_read(phydev, 0xca0f8) & 0x3);
646 seq_printf(seq, "| Tx, Rx Polarity : %s(%02d)\n",
647 tx_rx_string[val], val);
648
649 seq_puts(seq, "\n");
650
651 return 0;
652}
653
654static int airphy_info_open(struct inode *inode, struct file *file)
655{
656 return single_open(file, airphy_info_show, inode->i_private);
657}
658
659static int airphy_fcm_counter_show(struct phy_device *phydev,
660 struct seq_file *seq)
661{
662 int ret = 0;
663 u32 pkt_cnt = 0;
664
665 seq_puts(seq, "|\t<<FCM Counter>>\n");
666 seq_puts(seq, "| Rx from Line side_S :");
667 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe0090);
668 seq_printf(seq, "%010u |\n", pkt_cnt);
669 seq_puts(seq, "| Rx from Line side_T :");
670 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe0094);
671 seq_printf(seq, "%010u |\n", pkt_cnt);
672 seq_puts(seq, "| Tx to System side_S :");
673 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe009c);
674 seq_printf(seq, "%010u |\n", pkt_cnt);
675 seq_puts(seq, "| Tx to System side_T :");
676 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe00A0);
677 seq_printf(seq, "%010u |\n", pkt_cnt);
678 seq_puts(seq, "| Rx from System side_S :");
679 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe0078);
680 seq_printf(seq, "%010u |\n", pkt_cnt);
681 seq_puts(seq, "| Rx from System side_T :");
682 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe007C);
683 seq_printf(seq, "%010u |\n", pkt_cnt);
684 seq_puts(seq, "| Tx to Line side_S :");
685 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe0084);
686 seq_printf(seq, "%010u |\n", pkt_cnt);
687 seq_puts(seq, "| Tx to Line side_T :");
688 pkt_cnt = air_buckpbus_reg_read(phydev, 0xe0088);
689 seq_printf(seq, "%010u |\n", pkt_cnt);
690 ret = air_buckpbus_reg_write(phydev, 0xe0074, 0xf);
691 if (ret < 0)
692 return ret;
693 return 0;
694}
695
696static int airphy_ss_counter_show(struct phy_device *phydev,
697 struct seq_file *seq)
698{
699 int ret = 0;
700 u32 pkt_cnt = 0;
701
702 seq_puts(seq, "|\t<<SS Counter>>\n");
703 ret = air_buckpbus_reg_write(phydev, 0xC602C, 0x3);
704 if (ret < 0)
705 return ret;
706 seq_puts(seq, "| TX Start :");
707 pkt_cnt = air_buckpbus_reg_read(phydev, 0xC60B0);
708 seq_printf(seq, "%010u |\n", pkt_cnt);
709 seq_puts(seq, "| TX Terminal :");
710 pkt_cnt = air_buckpbus_reg_read(phydev, 0xC60B4);
711 seq_printf(seq, "%010u |\n", pkt_cnt);
712 seq_puts(seq, "| RX Start :");
713 pkt_cnt = air_buckpbus_reg_read(phydev, 0xC60BC);
714 seq_printf(seq, "%010u |\n", pkt_cnt);
715 seq_puts(seq, "| RX Terminal :");
716 pkt_cnt = air_buckpbus_reg_read(phydev, 0xC60C0);
717 seq_printf(seq, "%010u |\n\n", pkt_cnt);
718 ret = air_buckpbus_reg_write(phydev, 0xC602C, 0x4);
719 if (ret < 0)
720 return ret;
721 return 0;
722}
723
724static int airphy_counter_show(struct seq_file *seq, void *v)
725{
726 struct phy_device *phydev = seq->private;
727 struct mii_bus *mbus = phydev_mdio_bus(phydev);
728 int ret = 0, addr = phydev_addr(phydev);
729 u32 pkt_cnt = 0;
730
731 ret = air_read_status(phydev);
732 if (ret < 0)
733 return ret;
734 seq_puts(seq, "==========AIR PHY COUNTER==========\n");
735 ret = airphy_fcm_counter_show(phydev, seq);
736 if (ret < 0)
737 return ret;
738 if (phydev->link && phydev->speed == SPEED_2500) {
739 seq_puts(seq, "|\t<<LS Counter>>\n");
740 ret = air_buckpbus_reg_write(phydev, 0x30718, 0x10);
741 if (ret < 0)
742 return ret;
743 ret = air_buckpbus_reg_write(phydev, 0x30718, 0x0);
744 if (ret < 0)
745 return ret;
746 seq_puts(seq, "|\tBefore EF\n");
747 seq_puts(seq, "| TX to Line side_S :");
748 pkt_cnt = air_buckpbus_reg_read(phydev, 0x3071c);
749 seq_printf(seq, "%010u |\n", pkt_cnt);
750 seq_puts(seq, "| TX to Line side_T :");
751 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30720);
752 seq_printf(seq, "%010u |\n", pkt_cnt);
753 seq_puts(seq, "| RX from Line side_S :");
754 pkt_cnt = air_buckpbus_reg_read(phydev, 0x3072c);
755 seq_printf(seq, "%010u |\n", pkt_cnt);
756 seq_puts(seq, "| RX from Line side_T :");
757 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30730);
758 seq_printf(seq, "%010u |\n", pkt_cnt);
759 seq_puts(seq, "| TX_ENC :");
760 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30724);
761 seq_printf(seq, "%010u |\n", pkt_cnt);
762 seq_puts(seq, "| RX_DEC :");
763 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30728);
764 seq_printf(seq, "%010u |\n", pkt_cnt);
765 seq_puts(seq, "|\tAfter EF\n");
766 seq_puts(seq, "| TX to Line side_S :");
767 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30734);
768 seq_printf(seq, "%010u |\n", pkt_cnt);
769 seq_puts(seq, "| TX to Line side_T :");
770 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30738);
771 seq_printf(seq, "%010u |\n", pkt_cnt);
772 seq_puts(seq, "| RX from Line side_S :");
773 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30764);
774 seq_printf(seq, "%010u |\n", pkt_cnt);
775 seq_puts(seq, "| RX from Line side_T :");
776 pkt_cnt = air_buckpbus_reg_read(phydev, 0x30768);
777 seq_printf(seq, "%010u |\n", pkt_cnt);
778 ret = air_buckpbus_reg_write(phydev, 0x30718, 0x13);
779 if (ret < 0)
780 return ret;
781 ret = air_buckpbus_reg_write(phydev, 0x30718, 0x3);
782 if (ret < 0)
783 return ret;
784 ret = air_buckpbus_reg_write(phydev, 0x30718, 0x10);
785 if (ret < 0)
786 return ret;
787 ret = air_buckpbus_reg_write(phydev, 0x30718, 0x0);
788 if (ret < 0)
789 return ret;
790 seq_puts(seq, "|\t<<MAC Counter>>\n");
791 seq_puts(seq, "| TX Error from System side:");
792 pkt_cnt = air_buckpbus_reg_read(phydev, 0x131000);
793 seq_printf(seq, "%010u |\n", pkt_cnt);
794 seq_puts(seq, "| RX Error to System side :");
795 pkt_cnt = air_buckpbus_reg_read(phydev, 0x132000);
796 seq_printf(seq, "%010u |\n", pkt_cnt);
797 seq_puts(seq, "| TX from System side :");
798 pkt_cnt = air_buckpbus_reg_read(phydev, 0x131004);
799 seq_printf(seq, "%010u |\n", pkt_cnt);
800 seq_puts(seq, "| RX to System Side :");
801 pkt_cnt = air_buckpbus_reg_read(phydev, 0x132004);
802 seq_printf(seq, "%010u |\n", pkt_cnt);
803 }
804 if (phydev->link && ((phydev->speed != SPEED_2500))) {
805 seq_puts(seq, "|\t<<LS Counter>>\n");
806 ret = air_mii_cl22_write(mbus, addr, 0x1f, 1);
807 if (ret < 0)
808 return ret;
809 seq_puts(seq, "| RX from Line side :");
810 pkt_cnt = air_mii_cl22_read(mbus, addr, 0x12) & 0x7fff;
811 seq_printf(seq, "%010u |\n", pkt_cnt);
812 seq_puts(seq, "| RX Error from Line side :");
813 pkt_cnt = air_mii_cl22_read(mbus, addr, 0x17) & 0xff;
814 seq_printf(seq, "%010u |\n", pkt_cnt);
815 ret = air_mii_cl22_write(mbus, addr, 0x1f, 0);
816 if (ret < 0)
817 return ret;
818 ret = air_mii_cl22_write(mbus, addr, 0x1f, 0x52B5);
819 if (ret < 0)
820 return ret;
821 ret = air_mii_cl22_write(mbus, addr, 0x10, 0xBF92);
822 if (ret < 0)
823 return ret;
824 seq_puts(seq, "| TX to Line side :");
825 pkt_cnt = (air_mii_cl22_read(mbus, addr, 0x11) & 0x7ffe) >> 1;
826 seq_printf(seq, "%010u |\n", pkt_cnt);
827 seq_puts(seq, "| TX Error to Line side :");
828 pkt_cnt = air_mii_cl22_read(mbus, addr, 0x12);
829 pkt_cnt &= 0x7f;
830 seq_printf(seq, "%010u |\n", pkt_cnt);
831 ret = air_mii_cl22_write(mbus, addr, 0x1f, 0);
832 if (ret < 0)
833 return ret;
834 }
835 if (phydev->link) {
836 ret = airphy_ss_counter_show(phydev, seq);
837 if (ret < 0)
838 return ret;
839 }
840 return ret;
841}
842
843static int airphy_counter_open(struct inode *inode, struct file *file)
844{
845 return single_open(file, airphy_counter_show, inode->i_private);
846}
847
848static ssize_t airphy_polarity_write(struct file *file, const char __user *ptr,
849 size_t len, loff_t *off)
850{
851 struct phy_device *phydev = file->private_data;
852 char buf[32], param1[32], param2[32];
853 int count = len, ret = 0, tx_rx = 0;
854
855 memset(buf, 0, 32);
856 memset(param1, 0, 32);
857 memset(param2, 0, 32);
858
859 if (count > sizeof(buf) - 1)
860 return -EINVAL;
861 if (copy_from_user(buf, ptr, len))
862 return -EFAULT;
863 if (sscanf(buf, "%s %s", param1, param2) == -1)
864 return -EFAULT;
865
866 if (!strncmp("tx_normal", param1, strlen("tx_normal"))) {
867 if (!strncmp("rx_normal", param2, strlen("rx_normal")))
868 tx_rx = AIR_POL_TX_NOR_RX_NOR;
869 else if (!strncmp("rx_reverse", param2, strlen("rx_reverse")))
870 tx_rx = AIR_POL_TX_NOR_RX_REV;
871 else {
872 pr_notice("\nRx param is not correct.\n");
873 return -EINVAL;
874 }
875 } else if (!strncmp("tx_reverse", param1, strlen("tx_reverse"))) {
876 if (!strncmp("rx_normal", param2, strlen("rx_normal")))
877 tx_rx = AIR_POL_TX_REV_RX_NOR;
878 else if (!strncmp("rx_reverse", param2, strlen("rx_reverse")))
879 tx_rx = AIR_POL_TX_REV_RX_REV;
880 else {
881 pr_notice("\nRx param is not correct.\n");
882 return -EINVAL;
883 }
884 } else {
885 air_polarity_help();
886 return count;
887 }
888 pr_notice("\nSet Polarity %s\n", tx_rx_string[tx_rx]);
889 ret = air_set_polarity(phydev, tx_rx);
890 if (ret < 0)
891 return ret;
892 return count;
893}
894static void airphy_port_mode_help(void)
895{
896 pr_notice("\nUsage:\n"
897 "[debugfs] = /sys/kernel/debug/mdio-bus\':[phy_addr]\n"
898 "echo [mode] [para] > /[debugfs]/port_mode\n"
899 "echo re-an > /[debugfs]/port_mode\n"
900 "echo auto > /[debugfs]/port_mode\n"
901 "echo 2500 > /[debugfs]/port_mode\n"
902 "echo 1000 > /[debugfs]/port_mode\n"
903 "echo 100 > /[debugfs]/port_mode\n"
904 "echo power up/down > /[debugfs]/port_mode\n");
905}
906
907static ssize_t airphy_port_mode(struct file *file, const char __user *ptr,
908 size_t len, loff_t *off)
909{
910 struct phy_device *phydev = file->private_data;
911 char buf[32], cmd[32], param[32];
912 int count = len, ret = 0;
913 int num = 0, val = 0;
914
915 memset(buf, 0, 32);
916 memset(cmd, 0, 32);
917 memset(param, 0, 32);
918
919 if (count > sizeof(buf) - 1)
920 return -EINVAL;
921 if (copy_from_user(buf, ptr, len))
922 return -EFAULT;
923
924 num = sscanf(buf, "%s %s", cmd, param);
925 if (num < 1 || num > 3)
926 return -EFAULT;
927
928 if (!strncmp("auto", cmd, strlen("auto")))
929 ret = air_set_mode(phydev, AIR_PORT_MODE_AUTONEGO);
930 else if (!strncmp("2500", cmd, strlen("2500")))
931 ret = air_set_mode(phydev, AIR_PORT_MODE_FORCE_2500);
932 else if (!strncmp("1000", cmd, strlen("1000")))
933 ret = air_set_mode(phydev, AIR_PORT_MODE_FORCE_1000);
934 else if (!strncmp("100", cmd, strlen("100")))
935 ret = air_set_mode(phydev, AIR_PORT_MODE_FORCE_100);
936 else if (!strncmp("re-an", cmd, strlen("re-an"))) {
937 val = phy_read(phydev, MII_BMCR) | BIT(9);
938 ret = phy_write(phydev, MII_BMCR, val);
939 } else if (!strncmp("power", cmd, strlen("power"))) {
940 if (!strncmp("down", param, strlen("down")))
941 ret = air_set_mode(phydev, AIR_PORT_MODE_POWER_DOWN);
942 else if (!strncmp("up", param, strlen("up")))
943 ret = air_set_mode(phydev, AIR_PORT_MODE_POWER_UP);
944 } else if (!strncmp("int_sw_release", cmd, strlen("int_sw_release"))) {
945 ret = air_pbus_reg_write(phydev, 0xcf928, 0x0);
946 pr_notice("\ninternal sw reset released\n");
947 } else if (!strncmp("help", cmd, strlen("help"))) {
948 airphy_port_mode_help();
949 }
950
951 if (ret < 0)
952 return ret;
953
954 return count;
955}
956
957static void airphy_debugfs_buckpbus_help(void)
958{
959 pr_notice("\nUsage:\n"
960 "[debugfs] = /sys/kernel/debug/mdio-bus\':[phy_addr]\n"
961 "Read:\n"
962 "echo r [buckpbus_register] > /[debugfs]/buckpbus_op\n"
963 "Write:\n"
964 "echo w [buckpbus_register] [value] > /[debugfs]/buckpbus_op\n");
965}
966
967
968static ssize_t airphy_debugfs_buckpbus(struct file *file,
969 const char __user *buffer, size_t count,
970 loff_t *data)
971{
972 struct phy_device *phydev = file->private_data;
973 char buf[64];
974 int ret = 0;
975 unsigned int reg, val;
976
977 memset(buf, 0, 64);
978 if (count > sizeof(buf) - 1)
979 return -EINVAL;
980 if (copy_from_user(buf, buffer, count))
981 return -EFAULT;
982
983 if (buf[0] == 'w') {
984 if (sscanf(buf, "w %x %x", &reg, &val) == -1)
985 return -EFAULT;
986
987 pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n",
988 phydev_addr(phydev), reg, val);
989 ret = air_buckpbus_reg_write(phydev, reg, val);
990 if (ret < 0) {
991 pr_notice("\nbuckpbus_reg_write fail\n");
992 return -EIO;
993 }
994 val = air_buckpbus_reg_read(phydev, reg);
995 pr_notice("\nphy=%d, reg=0x%x, val=0x%x confirm..\n",
996 phydev_addr(phydev), reg, val);
997 } else if (buf[0] == 'r') {
998 if (sscanf(buf, "r %x", &reg) == -1)
999 return -EFAULT;
1000
1001 val = air_buckpbus_reg_read(phydev, reg);
1002 pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n",
1003 phydev_addr(phydev), reg, val);
1004 } else
1005 airphy_debugfs_buckpbus_help();
1006
1007 return count;
1008}
1009
1010static ssize_t airphy_debugfs_pbus(struct file *file,
1011 const char __user *buffer, size_t count,
1012 loff_t *data)
1013{
1014 struct phy_device *phydev = file->private_data;
1015 char buf[64];
1016 int ret = 0;
1017 unsigned int reg, val;
1018
1019 memset(buf, 0, 64);
1020 if (copy_from_user(buf, buffer, count))
1021 return -EFAULT;
1022
1023 if (buf[0] == 'w') {
1024 if (sscanf(buf, "w %x %x", &reg, &val) == -1)
1025 return -EFAULT;
1026
1027 pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n",
1028 phydev_addr(phydev), reg, val);
1029 ret = air_pbus_reg_write(phydev, reg, val);
1030 if (ret < 0) {
1031 pr_notice("\npbus_reg_write fail\n");
1032 return -EIO;
1033 }
1034 val = air_pbus_reg_read(phydev, reg);
1035 pr_notice("\nphy=%d, reg=0x%x, val=0x%x confirm..\n",
1036 phydev_addr(phydev), reg, val);
1037 } else if (buf[0] == 'r') {
1038 if (sscanf(buf, "r %x", &reg) == -1)
1039 return -EFAULT;
1040
1041 val = air_pbus_reg_read(phydev, reg);
1042 pr_notice("\nphy=%d, reg=0x%x, val=0x%x\n",
1043 phydev_addr(phydev), reg, val);
1044 } else
1045 airphy_debugfs_buckpbus_help();
1046
1047 return count;
1048}
1049
1050static int airphy_link_status(struct seq_file *seq, void *v)
1051{
1052 int ret = 0;
1053 struct phy_device *phydev = seq->private;
1054
1055 ret = air_read_status(phydev);
1056 if (ret < 0)
1057 return ret;
1058
1059 seq_printf(seq, "%s Information:\n", dev_name(phydev_dev(phydev)));
1060 seq_printf(seq, "\tPHYAD: %02d\n", phydev_addr(phydev));
1061 seq_printf(seq, "\tLink Status: %s\n", phydev->link ? "UP" : "DOWN");
1062 if (phydev->link) {
1063 seq_printf(seq, "\tAuto-Nego: %s\n",
1064 phydev->autoneg ? "on" : "off");
1065 seq_puts(seq, "\tSpeed: ");
1066 if (phydev->speed == SPEED_UNKNOWN)
1067 seq_printf(seq, "Unknown! (%i)\n", phydev->speed);
1068 else
1069 seq_printf(seq, "%uMb/s\n", phydev->speed);
1070
1071 seq_printf(seq, "\tDuplex: %s\n",
1072 phydev->duplex ? "Full" : "Half");
1073 seq_puts(seq, "\n");
1074 }
1075
1076 return ret;
1077}
1078
1079static int airphy_link_status_open(struct inode *inode, struct file *file)
1080{
1081 return single_open(file, airphy_link_status, inode->i_private);
1082}
1083
1084static int dbg_regs_show(struct seq_file *seq, void *v)
1085{
1086 struct phy_device *phydev = seq->private;
1087 struct mii_bus *mbus = phydev_mdio_bus(phydev);
1088 int addr = phydev_addr(phydev);
1089
1090 seq_puts(seq, "\t<<DEBUG REG DUMP>>\n");
1091 seq_printf(seq, "| RG_MII_BMSR : 0x%08x |\n",
1092 air_mii_cl22_read(mbus, addr, MII_BMSR));
1093 seq_printf(seq, "| RG_MII_REF_CLK : 0x%08x |\n",
1094 air_mii_cl22_read(mbus, addr, 0x1d));
1095 seq_printf(seq, "| RG_SYS_LINK_MODE : 0x%08x |\n",
1096 air_buckpbus_reg_read(phydev, 0xe0004));
1097 seq_printf(seq, "| RG_FCM_CTRL : 0x%08x |\n",
1098 air_buckpbus_reg_read(phydev, 0xe000C));
1099 seq_printf(seq, "| RG_SS_PAUSE_TIME : 0x%08x |\n",
1100 air_buckpbus_reg_read(phydev, 0xe0020));
1101 seq_printf(seq, "| RG_MIN_IPG_NUM : 0x%08x |\n",
1102 air_buckpbus_reg_read(phydev, 0xe002C));
1103 seq_printf(seq, "| RG_CTROL_0 : 0x%08x |\n",
1104 air_buckpbus_reg_read(phydev, 0xc0000));
1105 seq_printf(seq, "| RG_LINK_STATUS : 0x%08x |\n",
1106 air_buckpbus_reg_read(phydev, 0xc0b04));
1107 seq_printf(seq, "| RG_LINK_PARTNER_AN : 0x%08x |\n",
1108 air_buckpbus_reg_read(phydev, 0xc0014));
1109 seq_printf(seq, "| RG_FN_PWR_CTRL_STATUS : 0x%08x |\n",
1110 air_buckpbus_reg_read(phydev, 0x1020c));
1111 seq_printf(seq, "| RG_WHILE_LOOP_COUNT : 0x%08x |\n",
1112 air_buckpbus_reg_read(phydev, 0x3A48));
1113
1114 return 0;
1115}
1116
1117static int airphy_dbg_regs_show_open(struct inode *inode, struct file *file)
1118{
1119 return single_open(file, dbg_regs_show, inode->i_private);
1120}
1121
1122static const struct file_operations airphy_info_fops = {
1123 .owner = THIS_MODULE,
1124 .open = airphy_info_open,
1125 .read = seq_read,
1126 .llseek = noop_llseek,
1127};
1128
1129static const struct file_operations airphy_counter_fops = {
1130 .owner = THIS_MODULE,
1131 .open = airphy_counter_open,
1132 .read = seq_read,
1133 .llseek = noop_llseek,
1134};
1135
1136static const struct file_operations airphy_debugfs_buckpbus_fops = {
1137 .owner = THIS_MODULE,
1138 .open = simple_open,
1139 .write = airphy_debugfs_buckpbus,
1140 .llseek = noop_llseek,
1141};
1142
1143static const struct file_operations airphy_debugfs_pbus_fops = {
1144 .owner = THIS_MODULE,
1145 .open = simple_open,
1146 .write = airphy_debugfs_pbus,
1147 .llseek = noop_llseek,
1148};
1149
1150static const struct file_operations airphy_port_mode_fops = {
1151 .owner = THIS_MODULE,
1152 .open = simple_open,
1153 .write = airphy_port_mode,
1154 .llseek = noop_llseek,
1155};
1156
1157static const struct file_operations airphy_polarity_fops = {
1158 .owner = THIS_MODULE,
1159 .open = simple_open,
1160 .write = airphy_polarity_write,
1161 .llseek = noop_llseek,
1162};
1163
1164static const struct file_operations airphy_link_status_fops = {
1165 .owner = THIS_MODULE,
1166 .open = airphy_link_status_open,
1167 .read = seq_read,
1168 .llseek = noop_llseek,
1169};
1170
1171static const struct file_operations airphy_dbg_reg_show_fops = {
1172 .owner = THIS_MODULE,
1173 .open = airphy_dbg_regs_show_open,
1174 .read = seq_read,
1175 .llseek = noop_llseek,
1176};
1177
1178int airphy_debugfs_init(struct phy_device *phydev)
1179{
1180 int ret = 0;
1181 struct en8811h_priv *priv = phydev->priv;
1182 struct dentry *dir = priv->debugfs_root;
1183
1184 dev_dbg(phydev_dev(phydev), "%s: start\n", __func__);
1185 dir = debugfs_create_dir(dev_name(phydev_dev(phydev)), NULL);
1186 if (!dir) {
1187 dev_err(phydev_dev(phydev), "%s:err at %d\n",
1188 __func__, __LINE__);
1189 ret = -ENOMEM;
1190 }
1191 debugfs_create_file(DEBUGFS_DRIVER_INFO, S_IFREG | 0444,
1192 dir, phydev,
1193 &airphy_info_fops);
1194 debugfs_create_file(DEBUGFS_COUNTER, S_IFREG | 0444,
1195 dir, phydev,
1196 &airphy_counter_fops);
1197 debugfs_create_file(DEBUGFS_BUCKPBUS_OP, S_IFREG | 0200,
1198 dir, phydev,
1199 &airphy_debugfs_buckpbus_fops);
1200 debugfs_create_file(DEBUGFS_PBUS_OP, S_IFREG | 0200,
1201 dir, phydev,
1202 &airphy_debugfs_pbus_fops);
1203 debugfs_create_file(DEBUGFS_PORT_MODE, S_IFREG | 0200,
1204 dir, phydev,
1205 &airphy_port_mode_fops);
1206 debugfs_create_file(DEBUGFS_POLARITY, S_IFREG | 0200,
1207 dir, phydev,
1208 &airphy_polarity_fops);
1209 debugfs_create_file(DEBUGFS_LINK_STATUS, S_IFREG | 0444,
1210 dir, phydev,
1211 &airphy_link_status_fops);
1212 debugfs_create_file(DEBUGFS_DBG_REG_SHOW, S_IFREG | 0444,
1213 dir, phydev,
1214 &airphy_dbg_reg_show_fops);
1215
1216 priv->debugfs_root = dir;
1217 return ret;
1218}
1219
1220void air_debugfs_remove(struct phy_device *phydev)
1221{
1222 struct en8811h_priv *priv = phydev->priv;
1223
1224 debugfs_remove_recursive(priv->debugfs_root);
1225 priv->debugfs_root = NULL;
1226}
1227#endif /*CONFIG_AIROHA_EN8811H_PHY_DEBUGFS*/