icplus.c (a0750d42e95192fa8d57796f35ca7189bd231bb4) icplus.c (32ab60e5392066e5c5f71a93e37ea36ab726a526)
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Driver for ICPlus PHYs
4 *
5 * Copyright (c) 2007 Freescale Semiconductor, Inc.
6 */
7#include <linux/kernel.h>
8#include <linux/string.h>

--- 23 unchanged lines hidden (view full) ---

32
33/* IP101A/G - IP1001 */
34#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
35#define IP1001_RXPHASE_SEL BIT(0) /* Add delay on RX_CLK */
36#define IP1001_TXPHASE_SEL BIT(1) /* Add delay on TX_CLK */
37#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
38#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
39#define IP101A_G_APS_ON BIT(1) /* IP101A/G APS Mode bit */
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Driver for ICPlus PHYs
4 *
5 * Copyright (c) 2007 Freescale Semiconductor, Inc.
6 */
7#include <linux/kernel.h>
8#include <linux/string.h>

--- 23 unchanged lines hidden (view full) ---

32
33/* IP101A/G - IP1001 */
34#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
35#define IP1001_RXPHASE_SEL BIT(0) /* Add delay on RX_CLK */
36#define IP1001_TXPHASE_SEL BIT(1) /* Add delay on TX_CLK */
37#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
38#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
39#define IP101A_G_APS_ON BIT(1) /* IP101A/G APS Mode bit */
40#define IP101A_G_AUTO_MDIX_DIS BIT(11)
40#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
41#define IP101A_G_IRQ_PIN_USED BIT(15) /* INTR pin used */
42#define IP101A_G_IRQ_ALL_MASK BIT(11) /* IRQ's inactive */
43#define IP101A_G_IRQ_SPEED_CHANGE BIT(2)
44#define IP101A_G_IRQ_DUPLEX_CHANGE BIT(1)
45#define IP101A_G_IRQ_LINK_CHANGE BIT(0)
41#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
42#define IP101A_G_IRQ_PIN_USED BIT(15) /* INTR pin used */
43#define IP101A_G_IRQ_ALL_MASK BIT(11) /* IRQ's inactive */
44#define IP101A_G_IRQ_SPEED_CHANGE BIT(2)
45#define IP101A_G_IRQ_DUPLEX_CHANGE BIT(1)
46#define IP101A_G_IRQ_LINK_CHANGE BIT(0)
47#define IP101A_G_PHY_STATUS 18
48#define IP101A_G_MDIX BIT(9)
49#define IP101A_G_PHY_SPEC_CTRL 30
50#define IP101A_G_FORCE_MDIX BIT(3)
46
47#define IP101G_PAGE_CONTROL 0x14
48#define IP101G_PAGE_CONTROL_MASK GENMASK(4, 0)
49#define IP101G_DIGITAL_IO_SPEC_CTRL 0x1d
50#define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32 BIT(2)
51
52#define IP101G_DEFAULT_PAGE 16
53

--- 240 unchanged lines hidden (view full) ---

294 ret = phy_modify_paged(phydev, 8, IP101G_P8_CNT_CTRL,
295 CNT_CTRL_RDCLR_EN, CNT_CTRL_RDCLR_EN);
296 if (ret)
297 return ret;
298
299 return ip101a_g_config_intr_pin(phydev);
300}
301
51
52#define IP101G_PAGE_CONTROL 0x14
53#define IP101G_PAGE_CONTROL_MASK GENMASK(4, 0)
54#define IP101G_DIGITAL_IO_SPEC_CTRL 0x1d
55#define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32 BIT(2)
56
57#define IP101G_DEFAULT_PAGE 16
58

--- 240 unchanged lines hidden (view full) ---

299 ret = phy_modify_paged(phydev, 8, IP101G_P8_CNT_CTRL,
300 CNT_CTRL_RDCLR_EN, CNT_CTRL_RDCLR_EN);
301 if (ret)
302 return ret;
303
304 return ip101a_g_config_intr_pin(phydev);
305}
306
307static int ip101a_g_read_status(struct phy_device *phydev)
308{
309 int oldpage, ret, stat1, stat2;
310
311 ret = genphy_read_status(phydev);
312 if (ret)
313 return ret;
314
315 oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
316 if (oldpage < 0)
317 return oldpage;
318
319 ret = __phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
320 if (ret < 0)
321 goto out;
322 stat1 = ret;
323
324 ret = __phy_read(phydev, IP101A_G_PHY_SPEC_CTRL);
325 if (ret < 0)
326 goto out;
327 stat2 = ret;
328
329 if (stat1 & IP101A_G_AUTO_MDIX_DIS) {
330 if (stat2 & IP101A_G_FORCE_MDIX)
331 phydev->mdix_ctrl = ETH_TP_MDI_X;
332 else
333 phydev->mdix_ctrl = ETH_TP_MDI;
334 } else {
335 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
336 }
337
338 if (stat2 & IP101A_G_MDIX)
339 phydev->mdix = ETH_TP_MDI_X;
340 else
341 phydev->mdix = ETH_TP_MDI;
342
343 ret = 0;
344
345out:
346 return phy_restore_page(phydev, oldpage, ret);
347}
348
349static int ip101a_g_config_mdix(struct phy_device *phydev)
350{
351 u16 ctrl = 0, ctrl2 = 0;
352 int oldpage, ret;
353
354 switch (phydev->mdix_ctrl) {
355 case ETH_TP_MDI:
356 ctrl = IP101A_G_AUTO_MDIX_DIS;
357 break;
358 case ETH_TP_MDI_X:
359 ctrl = IP101A_G_AUTO_MDIX_DIS;
360 ctrl2 = IP101A_G_FORCE_MDIX;
361 break;
362 case ETH_TP_MDI_AUTO:
363 break;
364 default:
365 return 0;
366 }
367
368 oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
369 if (oldpage < 0)
370 return oldpage;
371
372 ret = __phy_modify(phydev, IP10XX_SPEC_CTRL_STATUS,
373 IP101A_G_AUTO_MDIX_DIS, ctrl);
374 if (ret)
375 goto out;
376
377 ret = __phy_modify(phydev, IP101A_G_PHY_SPEC_CTRL,
378 IP101A_G_FORCE_MDIX, ctrl2);
379
380out:
381 return phy_restore_page(phydev, oldpage, ret);
382}
383
384static int ip101a_g_config_aneg(struct phy_device *phydev)
385{
386 int ret;
387
388 ret = ip101a_g_config_mdix(phydev);
389 if (ret)
390 return ret;
391
392 return genphy_config_aneg(phydev);
393}
394
302static int ip101a_g_ack_interrupt(struct phy_device *phydev)
303{
304 int err;
305
306 err = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
307 IP101A_G_IRQ_CONF_STATUS);
308 if (err < 0)
309 return err;

--- 189 unchanged lines hidden (view full) ---

499 .name = "ICPlus IP101A",
500 .match_phy_device = ip101a_match_phy_device,
501 .probe = ip101a_g_probe,
502 .read_page = ip101a_read_page,
503 .write_page = ip101a_write_page,
504 .config_intr = ip101a_g_config_intr,
505 .handle_interrupt = ip101a_g_handle_interrupt,
506 .config_init = ip101a_config_init,
395static int ip101a_g_ack_interrupt(struct phy_device *phydev)
396{
397 int err;
398
399 err = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
400 IP101A_G_IRQ_CONF_STATUS);
401 if (err < 0)
402 return err;

--- 189 unchanged lines hidden (view full) ---

592 .name = "ICPlus IP101A",
593 .match_phy_device = ip101a_match_phy_device,
594 .probe = ip101a_g_probe,
595 .read_page = ip101a_read_page,
596 .write_page = ip101a_write_page,
597 .config_intr = ip101a_g_config_intr,
598 .handle_interrupt = ip101a_g_handle_interrupt,
599 .config_init = ip101a_config_init,
600 .config_aneg = ip101a_g_config_aneg,
601 .read_status = ip101a_g_read_status,
507 .soft_reset = genphy_soft_reset,
508 .suspend = genphy_suspend,
509 .resume = genphy_resume,
510}, {
511 .name = "ICPlus IP101G",
512 .match_phy_device = ip101g_match_phy_device,
513 .probe = ip101a_g_probe,
514 .read_page = ip101g_read_page,
515 .write_page = ip101g_write_page,
516 .config_intr = ip101a_g_config_intr,
517 .handle_interrupt = ip101a_g_handle_interrupt,
518 .config_init = ip101g_config_init,
602 .soft_reset = genphy_soft_reset,
603 .suspend = genphy_suspend,
604 .resume = genphy_resume,
605}, {
606 .name = "ICPlus IP101G",
607 .match_phy_device = ip101g_match_phy_device,
608 .probe = ip101a_g_probe,
609 .read_page = ip101g_read_page,
610 .write_page = ip101g_write_page,
611 .config_intr = ip101a_g_config_intr,
612 .handle_interrupt = ip101a_g_handle_interrupt,
613 .config_init = ip101g_config_init,
614 .config_aneg = ip101a_g_config_aneg,
615 .read_status = ip101a_g_read_status,
519 .soft_reset = genphy_soft_reset,
520 .get_sset_count = ip101g_get_sset_count,
521 .get_strings = ip101g_get_strings,
522 .get_stats = ip101g_get_stats,
523 .suspend = genphy_suspend,
524 .resume = genphy_resume,
525} };
526
527module_phy_driver(icplus_driver);
528
529static struct mdio_device_id __maybe_unused icplus_tbl[] = {
530 { PHY_ID_MATCH_MODEL(IP175C_PHY_ID) },
531 { PHY_ID_MATCH_MODEL(IP1001_PHY_ID) },
532 { PHY_ID_MATCH_EXACT(IP101A_PHY_ID) },
533 { }
534};
535
536MODULE_DEVICE_TABLE(mdio, icplus_tbl);
616 .soft_reset = genphy_soft_reset,
617 .get_sset_count = ip101g_get_sset_count,
618 .get_strings = ip101g_get_strings,
619 .get_stats = ip101g_get_stats,
620 .suspend = genphy_suspend,
621 .resume = genphy_resume,
622} };
623
624module_phy_driver(icplus_driver);
625
626static struct mdio_device_id __maybe_unused icplus_tbl[] = {
627 { PHY_ID_MATCH_MODEL(IP175C_PHY_ID) },
628 { PHY_ID_MATCH_MODEL(IP1001_PHY_ID) },
629 { PHY_ID_MATCH_EXACT(IP101A_PHY_ID) },
630 { }
631};
632
633MODULE_DEVICE_TABLE(mdio, icplus_tbl);