add chaos_calmer branch
[15.05/openwrt.git] / package / boot / uboot-oxnas / patches / 200-icplus-phy.patch
1 From e719404ee1241af679a51879eaad291bc27e4817 Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Tue, 2 Dec 2014 14:46:05 +0100
4 Subject: [PATCH] net/phy: add back icplus driver
5
6 IC+ phy driver was removed due to the lack of users some time ago.
7 Add it back, so we can use it.
8 ---
9  drivers/net/phy/Makefile |  1 +
10  drivers/net/phy/icplus.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
11  drivers/net/phy/phy.c    |  3 ++
12  3 files changed, 84 insertions(+)
13  create mode 100644 drivers/net/phy/icplus.c
14
15 --- a/drivers/net/phy/Makefile
16 +++ b/drivers/net/phy/Makefile
17 @@ -15,6 +15,7 @@ obj-$(CONFIG_PHY_ATHEROS) += atheros.o
18  obj-$(CONFIG_PHY_BROADCOM) += broadcom.o
19  obj-$(CONFIG_PHY_DAVICOM) += davicom.o
20  obj-$(CONFIG_PHY_ET1011C) += et1011c.o
21 +obj-$(CONFIG_PHY_ICPLUS) += icplus.o
22  obj-$(CONFIG_PHY_LXT) += lxt.o
23  obj-$(CONFIG_PHY_MARVELL) += marvell.o
24  obj-$(CONFIG_PHY_MICREL) += micrel.o
25 --- /dev/null
26 +++ b/drivers/net/phy/icplus.c
27 @@ -0,0 +1,93 @@
28 +/*
29 + * ICPlus PHY drivers
30 + *
31 + * SPDX-License-Identifier:    GPL-2.0+
32 + *
33 + * Copyright (c) 2007 Freescale Semiconductor, Inc.
34 + */
35 +#include <phy.h>
36 +
37 +/* IP101A/G - IP1001 */
38 +#define IP10XX_SPEC_CTRL_STATUS         16      /* Spec. Control Register */
39 +#define IP1001_SPEC_CTRL_STATUS_2       20      /* IP1001 Spec. Control Reg 2 */
40 +#define IP1001_PHASE_SEL_MASK           3       /* IP1001 RX/TXPHASE_SEL */
41 +#define IP1001_APS_ON                   11      /* IP1001 APS Mode  bit */
42 +#define IP101A_G_APS_ON                 2       /* IP101A/G APS Mode bit */
43 +#define IP101A_G_IRQ_CONF_STATUS        0x11    /* Conf Info IRQ & Status Reg */
44 +#define IP101A_G_IRQ_PIN_USED           (1<<15) /* INTR pin used */
45 +#define IP101A_G_IRQ_DEFAULT            IP101A_G_IRQ_PIN_USED
46 +#define IP1001LF_DRIVE_MASK     (15 << 5)
47 +#define IP1001LF_RXCLKDRIVE_HI  (2  << 5)
48 +#define IP1001LF_RXDDRIVE_HI    (2  << 7)
49 +#define IP1001LF_RXCLKDRIVE_M   (1  << 5)
50 +#define IP1001LF_RXDDRIVE_M     (1  << 7)
51 +#define IP1001LF_RXCLKDRIVE_L   (0  << 5)
52 +#define IP1001LF_RXDDRIVE_L     (0  << 7)
53 +#define IP1001LF_RXCLKDRIVE_VL  (3  << 5)
54 +#define IP1001LF_RXDDRIVE_VL    (3  << 7)
55 +
56 +static int ip1001_config(struct phy_device *phydev)
57 +{
58 +       int c;
59 +
60 +       /* Enable Auto Power Saving mode */
61 +       c = phy_read(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2);
62 +       if (c < 0)
63 +               return c;
64 +       c |= IP1001_APS_ON;
65 +       c = phy_write(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2, c);
66 +       if (c < 0)
67 +               return c;
68 +
69 +       /* INTR pin used: speed/link/duplex will cause an interrupt */
70 +       c = phy_write(phydev, MDIO_DEVAD_NONE, IP101A_G_IRQ_CONF_STATUS,
71 +                     IP101A_G_IRQ_DEFAULT);
72 +       if (c < 0)
73 +               return c;
74 +
75 +       if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
76 +               /*
77 +                * Additional delay (2ns) used to adjust RX clock phase
78 +                * at RGMII interface
79 +                */
80 +               c = phy_read(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS);
81 +               if (c < 0)
82 +                       return c;
83 +
84 +               c |= IP1001_PHASE_SEL_MASK;
85 +               /* adjust digtial drive strength */
86 +               c &= ~IP1001LF_DRIVE_MASK;
87 +               c |=  IP1001LF_RXCLKDRIVE_M;
88 +               c |=  IP1001LF_RXDDRIVE_M;
89 +               c = phy_write(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS,
90 +                             c);
91 +               if (c < 0)
92 +                       return c;
93 +       }
94 +
95 +       return 0;
96 +}
97 +
98 +static int ip1001_startup(struct phy_device *phydev)
99 +{
100 +       genphy_update_link(phydev);
101 +       genphy_parse_link(phydev);
102 +
103 +       return 0;
104 +}
105 +static struct phy_driver IP1001_driver = {
106 +       .name = "ICPlus IP1001",
107 +       .uid = 0x02430d90,
108 +       .mask = 0x0ffffff0,
109 +       .features = PHY_GBIT_FEATURES,
110 +       .config = &ip1001_config,
111 +       .startup = &ip1001_startup,
112 +       .shutdown = &genphy_shutdown,
113 +};
114 +
115 +int phy_icplus_init(void)
116 +{
117 +       phy_register(&IP1001_driver);
118 +
119 +       return 0;
120 +}
121 --- a/drivers/net/phy/phy.c
122 +++ b/drivers/net/phy/phy.c
123 @@ -454,6 +454,9 @@ int phy_init(void)
124  #ifdef CONFIG_PHY_ET1011C
125         phy_et1011c_init();
126  #endif
127 +#ifdef CONFIG_PHY_ICPLUS
128 +       phy_icplus_init();
129 +#endif
130  #ifdef CONFIG_PHY_LXT
131         phy_lxt_init();
132  #endif
133 --- a/include/phy.h
134 +++ b/include/phy.h
135 @@ -225,6 +225,7 @@ int phy_atheros_init(void);
136  int phy_broadcom_init(void);
137  int phy_davicom_init(void);
138  int phy_et1011c_init(void);
139 +int phy_icplus_init(void);
140  int phy_lxt_init(void);
141  int phy_marvell_init(void);
142  int phy_micrel_init(void);