blob: cd3c1c596ae766d167077139a937bd3c7804e698 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Edgar E. Iglesias721aed72015-09-25 23:46:08 -07002/*
3 * TI PHY drivers
4 *
Edgar E. Iglesias721aed72015-09-25 23:46:08 -07005 */
6#include <common.h>
7#include <phy.h>
Dan Murphy085445c2016-05-02 15:45:59 -05008#include <linux/compat.h>
9#include <malloc.h>
10
Dan Murphy085445c2016-05-02 15:45:59 -050011#include <dm.h>
12#include <dt-bindings/net/ti-dp83867.h>
13
Edgar E. Iglesias721aed72015-09-25 23:46:08 -070014
15/* TI DP83867 */
16#define DP83867_DEVADDR 0x1f
17
18#define MII_DP83867_PHYCTRL 0x10
19#define MII_DP83867_MICR 0x12
Siva Durga Prasad Paladugu85b949f2016-03-25 12:53:43 +053020#define MII_DP83867_CFG2 0x14
21#define MII_DP83867_BISCR 0x16
Edgar E. Iglesias721aed72015-09-25 23:46:08 -070022#define DP83867_CTRL 0x1f
23
24/* Extended Registers */
Murali Karicheri63d31922018-06-28 14:26:34 -050025#define DP83867_CFG4 0x0031
Edgar E. Iglesias721aed72015-09-25 23:46:08 -070026#define DP83867_RGMIICTL 0x0032
Janine Hagemannbe71a742018-08-28 08:25:38 +020027#define DP83867_STRAP_STS1 0x006E
Edgar E. Iglesias721aed72015-09-25 23:46:08 -070028#define DP83867_RGMIIDCTL 0x0086
Mugunthan V N64631702017-01-24 11:15:40 -060029#define DP83867_IO_MUX_CFG 0x0170
Edgar E. Iglesias721aed72015-09-25 23:46:08 -070030
31#define DP83867_SW_RESET BIT(15)
32#define DP83867_SW_RESTART BIT(14)
33
34/* MICR Interrupt bits */
35#define MII_DP83867_MICR_AN_ERR_INT_EN BIT(15)
36#define MII_DP83867_MICR_SPEED_CHNG_INT_EN BIT(14)
37#define MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN BIT(13)
38#define MII_DP83867_MICR_PAGE_RXD_INT_EN BIT(12)
39#define MII_DP83867_MICR_AUTONEG_COMP_INT_EN BIT(11)
40#define MII_DP83867_MICR_LINK_STS_CHNG_INT_EN BIT(10)
41#define MII_DP83867_MICR_FALSE_CARRIER_INT_EN BIT(8)
42#define MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN BIT(4)
43#define MII_DP83867_MICR_WOL_INT_EN BIT(3)
44#define MII_DP83867_MICR_XGMII_ERR_INT_EN BIT(2)
45#define MII_DP83867_MICR_POL_CHNG_INT_EN BIT(1)
46#define MII_DP83867_MICR_JABBER_INT_EN BIT(0)
47
48/* RGMIICTL bits */
49#define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1)
50#define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0)
51
Janine Hagemannbe71a742018-08-28 08:25:38 +020052/* STRAP_STS1 bits */
53#define DP83867_STRAP_STS1_RESERVED BIT(11)
54
Edgar E. Iglesias721aed72015-09-25 23:46:08 -070055/* PHY CTRL bits */
56#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14
Janine Hagemannbe71a742018-08-28 08:25:38 +020057#define DP83867_PHYCR_RESERVED_MASK BIT(11)
Michal Simek01790632015-10-19 10:43:30 +020058#define DP83867_MDI_CROSSOVER 5
59#define DP83867_MDI_CROSSOVER_AUTO 2
Siva Durga Prasad Paladugu85b949f2016-03-25 12:53:43 +053060#define DP83867_MDI_CROSSOVER_MDIX 2
61#define DP83867_PHYCTRL_SGMIIEN 0x0800
62#define DP83867_PHYCTRL_RXFIFO_SHIFT 12
63#define DP83867_PHYCTRL_TXFIFO_SHIFT 14
Edgar E. Iglesias721aed72015-09-25 23:46:08 -070064
65/* RGMIIDCTL bits */
66#define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
67
Siva Durga Prasad Paladugu85b949f2016-03-25 12:53:43 +053068/* CFG2 bits */
69#define MII_DP83867_CFG2_SPEEDOPT_10EN 0x0040
70#define MII_DP83867_CFG2_SGMII_AUTONEGEN 0x0080
71#define MII_DP83867_CFG2_SPEEDOPT_ENH 0x0100
72#define MII_DP83867_CFG2_SPEEDOPT_CNT 0x0800
73#define MII_DP83867_CFG2_SPEEDOPT_INTLOW 0x2000
74#define MII_DP83867_CFG2_MASK 0x003F
75
Dan Murphy085445c2016-05-02 15:45:59 -050076/* User setting - can be taken from DTS */
77#define DEFAULT_RX_ID_DELAY DP83867_RGMIIDCTL_2_25_NS
78#define DEFAULT_TX_ID_DELAY DP83867_RGMIIDCTL_2_75_NS
79#define DEFAULT_FIFO_DEPTH DP83867_PHYCR_FIFO_DEPTH_4_B_NIB
80
Mugunthan V N64631702017-01-24 11:15:40 -060081/* IO_MUX_CFG bits */
82#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f
83
84#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0
85#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f
Grygorii Strashkob3b9b122019-11-18 23:04:43 +020086#define DP83867_IO_MUX_CFG_CLK_O_DISABLE BIT(6)
Janine Hagemann0f347a02018-08-28 08:25:39 +020087#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8
88#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \
89 GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT)
Mugunthan V N64631702017-01-24 11:15:40 -060090
Janine Hagemannfba725f2018-08-28 08:25:37 +020091/* CFG4 bits */
92#define DP83867_CFG4_PORT_MIRROR_EN BIT(0)
93
94enum {
95 DP83867_PORT_MIRRORING_KEEP,
96 DP83867_PORT_MIRRORING_EN,
97 DP83867_PORT_MIRRORING_DIS,
98};
99
Dan Murphy085445c2016-05-02 15:45:59 -0500100struct dp83867_private {
101 int rx_id_delay;
102 int tx_id_delay;
103 int fifo_depth;
Mugunthan V N64631702017-01-24 11:15:40 -0600104 int io_impedance;
Murali Karicheri63d31922018-06-28 14:26:34 -0500105 bool rxctrl_strap_quirk;
Janine Hagemannfba725f2018-08-28 08:25:37 +0200106 int port_mirroring;
Grygorii Strashkob3b9b122019-11-18 23:04:43 +0200107 bool set_clk_output;
Trent Piepho2529dea2019-05-10 17:49:08 +0000108 unsigned int clk_output_sel;
Dan Murphy085445c2016-05-02 15:45:59 -0500109};
110
Janine Hagemannfba725f2018-08-28 08:25:37 +0200111static int dp83867_config_port_mirroring(struct phy_device *phydev)
112{
113 struct dp83867_private *dp83867 =
114 (struct dp83867_private *)phydev->priv;
115 u16 val;
116
Carlo Caione4c29dc12019-02-08 17:25:07 +0000117 val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
Janine Hagemannfba725f2018-08-28 08:25:37 +0200118
119 if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN)
120 val |= DP83867_CFG4_PORT_MIRROR_EN;
121 else
122 val &= ~DP83867_CFG4_PORT_MIRROR_EN;
123
Carlo Caione4c29dc12019-02-08 17:25:07 +0000124 phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
Janine Hagemannfba725f2018-08-28 08:25:37 +0200125
126 return 0;
127}
128
Dan Murphy085445c2016-05-02 15:45:59 -0500129#if defined(CONFIG_DM_ETH)
130/**
131 * dp83867_data_init - Convenience function for setting PHY specific data
132 *
133 * @phydev: the phy_device struct
134 */
135static int dp83867_of_init(struct phy_device *phydev)
136{
137 struct dp83867_private *dp83867 = phydev->priv;
Grygorii Strashkob8d7ec72018-07-05 12:02:49 -0500138 ofnode node;
Grygorii Strashkob3b9b122019-11-18 23:04:43 +0200139 int ret;
Janine Hagemann0f347a02018-08-28 08:25:39 +0200140
Michal Simek6845b362019-03-16 12:43:17 +0100141 node = phy_get_ofnode(phydev);
142 if (!ofnode_valid(node))
143 return -EINVAL;
144
Grygorii Strashkob3b9b122019-11-18 23:04:43 +0200145 /* Optional configuration */
146 ret = ofnode_read_u32(node, "ti,clk-output-sel",
147 &dp83867->clk_output_sel);
148 /* If not set, keep default */
149 if (!ret) {
150 dp83867->set_clk_output = true;
151 /* Valid values are 0 to DP83867_CLK_O_SEL_REF_CLK or
152 * DP83867_CLK_O_SEL_OFF.
153 */
154 if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK &&
155 dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) {
156 pr_debug("ti,clk-output-sel value %u out of range\n",
157 dp83867->clk_output_sel);
158 return -EINVAL;
159 }
160 }
Grygorii Strashkob8d7ec72018-07-05 12:02:49 -0500161
Grygorii Strashko3ab75cf2018-06-28 14:26:35 -0500162 if (ofnode_read_bool(node, "ti,max-output-impedance"))
Mugunthan V N64631702017-01-24 11:15:40 -0600163 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
Grygorii Strashko3ab75cf2018-06-28 14:26:35 -0500164 else if (ofnode_read_bool(node, "ti,min-output-impedance"))
Mugunthan V N64631702017-01-24 11:15:40 -0600165 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
166 else
167 dp83867->io_impedance = -EINVAL;
Dan Murphy085445c2016-05-02 15:45:59 -0500168
Grygorii Strashko3ab75cf2018-06-28 14:26:35 -0500169 if (ofnode_read_bool(node, "ti,dp83867-rxctrl-strap-quirk"))
Murali Karicheri63d31922018-06-28 14:26:34 -0500170 dp83867->rxctrl_strap_quirk = true;
Grygorii Strashko3ab75cf2018-06-28 14:26:35 -0500171 dp83867->rx_id_delay = ofnode_read_u32_default(node,
172 "ti,rx-internal-delay",
Trent Piephoc2df9b42019-05-09 19:41:51 +0000173 DEFAULT_RX_ID_DELAY);
Dan Murphy085445c2016-05-02 15:45:59 -0500174
Grygorii Strashko3ab75cf2018-06-28 14:26:35 -0500175 dp83867->tx_id_delay = ofnode_read_u32_default(node,
176 "ti,tx-internal-delay",
Trent Piephoc2df9b42019-05-09 19:41:51 +0000177 DEFAULT_TX_ID_DELAY);
Dan Murphy085445c2016-05-02 15:45:59 -0500178
Grygorii Strashko3ab75cf2018-06-28 14:26:35 -0500179 dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
Trent Piephoc2df9b42019-05-09 19:41:51 +0000180 DEFAULT_FIFO_DEPTH);
Janine Hagemannfba725f2018-08-28 08:25:37 +0200181 if (ofnode_read_bool(node, "enet-phy-lane-swap"))
182 dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN;
183
184 if (ofnode_read_bool(node, "enet-phy-lane-no-swap"))
185 dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS;
186
Dan Murphy085445c2016-05-02 15:45:59 -0500187 return 0;
188}
189#else
190static int dp83867_of_init(struct phy_device *phydev)
191{
192 struct dp83867_private *dp83867 = phydev->priv;
193
194 dp83867->rx_id_delay = DEFAULT_RX_ID_DELAY;
195 dp83867->tx_id_delay = DEFAULT_TX_ID_DELAY;
196 dp83867->fifo_depth = DEFAULT_FIFO_DEPTH;
Mugunthan V N64631702017-01-24 11:15:40 -0600197 dp83867->io_impedance = -EINVAL;
Dan Murphy085445c2016-05-02 15:45:59 -0500198
199 return 0;
200}
201#endif
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700202
203static int dp83867_config(struct phy_device *phydev)
204{
Dan Murphy085445c2016-05-02 15:45:59 -0500205 struct dp83867_private *dp83867;
Siva Durga Prasad Paladugu85b949f2016-03-25 12:53:43 +0530206 unsigned int val, delay, cfg2;
Janine Hagemannbe71a742018-08-28 08:25:38 +0200207 int ret, bs;
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700208
Grygorii Strashkoee622f02019-11-18 23:04:41 +0200209 dp83867 = (struct dp83867_private *)phydev->priv;
Dan Murphy085445c2016-05-02 15:45:59 -0500210
Grygorii Strashkoee622f02019-11-18 23:04:41 +0200211 ret = dp83867_of_init(phydev);
212 if (ret)
213 return ret;
Dan Murphy085445c2016-05-02 15:45:59 -0500214
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700215 /* Restart the PHY. */
216 val = phy_read(phydev, MDIO_DEVAD_NONE, DP83867_CTRL);
217 phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL,
218 val | DP83867_SW_RESTART);
219
Murali Karicheri63d31922018-06-28 14:26:34 -0500220 /* Mode 1 or 2 workaround */
221 if (dp83867->rxctrl_strap_quirk) {
Carlo Caione4c29dc12019-02-08 17:25:07 +0000222 val = phy_read_mmd(phydev, DP83867_DEVADDR,
223 DP83867_CFG4);
Murali Karicheri63d31922018-06-28 14:26:34 -0500224 val &= ~BIT(7);
Carlo Caione4c29dc12019-02-08 17:25:07 +0000225 phy_write_mmd(phydev, DP83867_DEVADDR,
226 DP83867_CFG4, val);
Murali Karicheri63d31922018-06-28 14:26:34 -0500227 }
228
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700229 if (phy_interface_is_rgmii(phydev)) {
230 ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
Michal Simek01790632015-10-19 10:43:30 +0200231 (DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |
Dan Murphy085445c2016-05-02 15:45:59 -0500232 (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT));
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700233 if (ret)
Dan Murphy085445c2016-05-02 15:45:59 -0500234 goto err_out;
Janine Hagemannbe71a742018-08-28 08:25:38 +0200235
236 /* The code below checks if "port mirroring" N/A MODE4 has been
237 * enabled during power on bootstrap.
238 *
239 * Such N/A mode enabled by mistake can put PHY IC in some
240 * internal testing mode and disable RGMII transmission.
241 *
242 * In this particular case one needs to check STRAP_STS1
243 * register's bit 11 (marked as RESERVED).
244 */
245
Carlo Caione4c29dc12019-02-08 17:25:07 +0000246 bs = phy_read_mmd(phydev, DP83867_DEVADDR,
247 DP83867_STRAP_STS1);
Janine Hagemannbe71a742018-08-28 08:25:38 +0200248 val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL);
249 if (bs & DP83867_STRAP_STS1_RESERVED) {
250 val &= ~DP83867_PHYCR_RESERVED_MASK;
251 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
252 val);
253 }
254
Dan Murphy0a71cd72016-05-02 15:46:02 -0500255 } else if (phy_interface_is_sgmii(phydev)) {
Siva Durga Prasad Paladugu85b949f2016-03-25 12:53:43 +0530256 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
257 (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
258
259 cfg2 = phy_read(phydev, phydev->addr, MII_DP83867_CFG2);
260 cfg2 &= MII_DP83867_CFG2_MASK;
261 cfg2 |= (MII_DP83867_CFG2_SPEEDOPT_10EN |
262 MII_DP83867_CFG2_SGMII_AUTONEGEN |
263 MII_DP83867_CFG2_SPEEDOPT_ENH |
264 MII_DP83867_CFG2_SPEEDOPT_CNT |
265 MII_DP83867_CFG2_SPEEDOPT_INTLOW);
266 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG2, cfg2);
267
Carlo Caione4c29dc12019-02-08 17:25:07 +0000268 phy_write_mmd(phydev, DP83867_DEVADDR,
269 DP83867_RGMIICTL, 0x0);
Siva Durga Prasad Paladugu85b949f2016-03-25 12:53:43 +0530270
271 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
272 DP83867_PHYCTRL_SGMIIEN |
273 (DP83867_MDI_CROSSOVER_MDIX <<
274 DP83867_MDI_CROSSOVER) |
Dan Murphy085445c2016-05-02 15:45:59 -0500275 (dp83867->fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT) |
276 (dp83867->fifo_depth << DP83867_PHYCTRL_TXFIFO_SHIFT));
Siva Durga Prasad Paladugu85b949f2016-03-25 12:53:43 +0530277 phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0);
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700278 }
279
Phil Edworthy8abdead2016-12-09 10:46:02 +0000280 if (phy_interface_is_rgmii(phydev)) {
Carlo Caione4c29dc12019-02-08 17:25:07 +0000281 val = phy_read_mmd(phydev, DP83867_DEVADDR,
282 DP83867_RGMIICTL);
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700283
284 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
285 val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
286 DP83867_RGMII_RX_CLK_DELAY_EN);
287
288 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
289 val |= DP83867_RGMII_TX_CLK_DELAY_EN;
290
291 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
292 val |= DP83867_RGMII_RX_CLK_DELAY_EN;
293
Carlo Caione4c29dc12019-02-08 17:25:07 +0000294 phy_write_mmd(phydev, DP83867_DEVADDR,
295 DP83867_RGMIICTL, val);
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700296
Dan Murphy085445c2016-05-02 15:45:59 -0500297 delay = (dp83867->rx_id_delay |
298 (dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT));
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700299
Carlo Caione4c29dc12019-02-08 17:25:07 +0000300 phy_write_mmd(phydev, DP83867_DEVADDR,
301 DP83867_RGMIIDCTL, delay);
Mugunthan V N64631702017-01-24 11:15:40 -0600302
303 if (dp83867->io_impedance >= 0) {
Carlo Caione4c29dc12019-02-08 17:25:07 +0000304 val = phy_read_mmd(phydev,
305 DP83867_DEVADDR,
306 DP83867_IO_MUX_CFG);
Mugunthan V N64631702017-01-24 11:15:40 -0600307 val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
308 val |= dp83867->io_impedance &
309 DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
Carlo Caione4c29dc12019-02-08 17:25:07 +0000310 phy_write_mmd(phydev, DP83867_DEVADDR,
311 DP83867_IO_MUX_CFG, val);
Mugunthan V N64631702017-01-24 11:15:40 -0600312 }
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700313 }
314
Janine Hagemannfba725f2018-08-28 08:25:37 +0200315 if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP)
316 dp83867_config_port_mirroring(phydev);
317
Grygorii Strashkob3b9b122019-11-18 23:04:43 +0200318 /* Clock output selection if muxing property is set */
319 if (dp83867->set_clk_output) {
320 val = phy_read_mmd(phydev, DP83867_DEVADDR,
321 DP83867_IO_MUX_CFG);
322
323 if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) {
324 val |= DP83867_IO_MUX_CFG_CLK_O_DISABLE;
325 } else {
326 val &= ~(DP83867_IO_MUX_CFG_CLK_O_SEL_MASK |
327 DP83867_IO_MUX_CFG_CLK_O_DISABLE);
328 val |= dp83867->clk_output_sel <<
329 DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT;
330 }
331 phy_write_mmd(phydev, DP83867_DEVADDR,
332 DP83867_IO_MUX_CFG, val);
333 }
334
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700335 genphy_config_aneg(phydev);
336 return 0;
Dan Murphy085445c2016-05-02 15:45:59 -0500337
338err_out:
Dan Murphy085445c2016-05-02 15:45:59 -0500339 return ret;
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700340}
341
Grygorii Strashkoee622f02019-11-18 23:04:41 +0200342static int dp83867_probe(struct phy_device *phydev)
343{
344 struct dp83867_private *dp83867;
345
346 dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL);
347 if (!dp83867)
348 return -ENOMEM;
349
350 phydev->priv = dp83867;
351 return 0;
352}
353
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700354static struct phy_driver DP83867_driver = {
355 .name = "TI DP83867",
356 .uid = 0x2000a231,
357 .mask = 0xfffffff0,
358 .features = PHY_GBIT_FEATURES,
Grygorii Strashkoee622f02019-11-18 23:04:41 +0200359 .probe = dp83867_probe,
Edgar E. Iglesias721aed72015-09-25 23:46:08 -0700360 .config = &dp83867_config,
361 .startup = &genphy_startup,
362 .shutdown = &genphy_shutdown,
363};
364
365int phy_ti_init(void)
366{
367 phy_register(&DP83867_driver);
368 return 0;
369}