1 | /* |
2 | * AMD 10Gb Ethernet driver |
3 | * |
4 | * This file is available to you under your choice of the following two |
5 | * licenses: |
6 | * |
7 | * License 1: GPLv2 |
8 | * |
9 | * Copyright (c) 2016 Advanced Micro Devices, Inc. |
10 | * |
11 | * This file is free software; you may copy, redistribute and/or modify |
12 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation, either version 2 of the License, or (at |
14 | * your option) any later version. |
15 | * |
16 | * This file is distributed in the hope that it will be useful, but |
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 | * General Public License for more details. |
20 | * |
21 | * You should have received a copy of the GNU General Public License |
22 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
23 | * |
24 | * This file incorporates work covered by the following copyright and |
25 | * permission notice: |
26 | * The Synopsys DWC ETHER XGMAC Software Driver and documentation |
27 | * (hereinafter "Software") is an unsupported proprietary work of Synopsys, |
28 | * Inc. unless otherwise expressly agreed to in writing between Synopsys |
29 | * and you. |
30 | * |
31 | * The Software IS NOT an item of Licensed Software or Licensed Product |
32 | * under any End User Software License Agreement or Agreement for Licensed |
33 | * Product with Synopsys or any supplement thereto. Permission is hereby |
34 | * granted, free of charge, to any person obtaining a copy of this software |
35 | * annotated with this license and the Software, to deal in the Software |
36 | * without restriction, including without limitation the rights to use, |
37 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
38 | * of the Software, and to permit persons to whom the Software is furnished |
39 | * to do so, subject to the following conditions: |
40 | * |
41 | * The above copyright notice and this permission notice shall be included |
42 | * in all copies or substantial portions of the Software. |
43 | * |
44 | * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" |
45 | * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
46 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
47 | * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS |
48 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
49 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
50 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
51 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
52 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
53 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
54 | * THE POSSIBILITY OF SUCH DAMAGE. |
55 | * |
56 | * |
57 | * License 2: Modified BSD |
58 | * |
59 | * Copyright (c) 2016 Advanced Micro Devices, Inc. |
60 | * All rights reserved. |
61 | * |
62 | * Redistribution and use in source and binary forms, with or without |
63 | * modification, are permitted provided that the following conditions are met: |
64 | * * Redistributions of source code must retain the above copyright |
65 | * notice, this list of conditions and the following disclaimer. |
66 | * * Redistributions in binary form must reproduce the above copyright |
67 | * notice, this list of conditions and the following disclaimer in the |
68 | * documentation and/or other materials provided with the distribution. |
69 | * * Neither the name of Advanced Micro Devices, Inc. nor the |
70 | * names of its contributors may be used to endorse or promote products |
71 | * derived from this software without specific prior written permission. |
72 | * |
73 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
74 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
75 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
76 | * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY |
77 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
78 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
79 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
80 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
81 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
82 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
83 | * |
84 | * This file incorporates work covered by the following copyright and |
85 | * permission notice: |
86 | * The Synopsys DWC ETHER XGMAC Software Driver and documentation |
87 | * (hereinafter "Software") is an unsupported proprietary work of Synopsys, |
88 | * Inc. unless otherwise expressly agreed to in writing between Synopsys |
89 | * and you. |
90 | * |
91 | * The Software IS NOT an item of Licensed Software or Licensed Product |
92 | * under any End User Software License Agreement or Agreement for Licensed |
93 | * Product with Synopsys or any supplement thereto. Permission is hereby |
94 | * granted, free of charge, to any person obtaining a copy of this software |
95 | * annotated with this license and the Software, to deal in the Software |
96 | * without restriction, including without limitation the rights to use, |
97 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
98 | * of the Software, and to permit persons to whom the Software is furnished |
99 | * to do so, subject to the following conditions: |
100 | * |
101 | * The above copyright notice and this permission notice shall be included |
102 | * in all copies or substantial portions of the Software. |
103 | * |
104 | * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" |
105 | * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
106 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
107 | * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS |
108 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
109 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
110 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
111 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
112 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
113 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
114 | * THE POSSIBILITY OF SUCH DAMAGE. |
115 | */ |
116 | |
117 | #include <linux/module.h> |
118 | #include <linux/interrupt.h> |
119 | #include <linux/kmod.h> |
120 | #include <linux/delay.h> |
121 | #include <linux/completion.h> |
122 | #include <linux/mutex.h> |
123 | |
124 | #include "xgbe.h" |
125 | #include "xgbe-common.h" |
126 | |
127 | #define XGBE_ABORT_COUNT 500 |
128 | #define XGBE_DISABLE_COUNT 1000 |
129 | |
130 | #define XGBE_STD_SPEED 1 |
131 | |
132 | #define XGBE_INTR_RX_FULL BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX) |
133 | #define XGBE_INTR_TX_EMPTY BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX) |
134 | #define XGBE_INTR_TX_ABRT BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX) |
135 | #define XGBE_INTR_STOP_DET BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX) |
136 | #define XGBE_DEFAULT_INT_MASK (XGBE_INTR_RX_FULL | \ |
137 | XGBE_INTR_TX_EMPTY | \ |
138 | XGBE_INTR_TX_ABRT | \ |
139 | XGBE_INTR_STOP_DET) |
140 | |
141 | #define XGBE_I2C_READ BIT(8) |
142 | #define XGBE_I2C_STOP BIT(9) |
143 | |
144 | static int xgbe_i2c_abort(struct xgbe_prv_data *pdata) |
145 | { |
146 | unsigned int wait = XGBE_ABORT_COUNT; |
147 | |
148 | /* Must be enabled to recognize the abort request */ |
149 | XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1); |
150 | |
151 | /* Issue the abort */ |
152 | XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1); |
153 | |
154 | while (wait--) { |
155 | if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT)) |
156 | return 0; |
157 | |
158 | usleep_range(min: 500, max: 600); |
159 | } |
160 | |
161 | return -EBUSY; |
162 | } |
163 | |
164 | static int xgbe_i2c_set_enable(struct xgbe_prv_data *pdata, bool enable) |
165 | { |
166 | unsigned int wait = XGBE_DISABLE_COUNT; |
167 | unsigned int mode = enable ? 1 : 0; |
168 | |
169 | while (wait--) { |
170 | XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode); |
171 | if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode) |
172 | return 0; |
173 | |
174 | usleep_range(min: 100, max: 110); |
175 | } |
176 | |
177 | return -EBUSY; |
178 | } |
179 | |
180 | static int xgbe_i2c_disable(struct xgbe_prv_data *pdata) |
181 | { |
182 | unsigned int ret; |
183 | |
184 | ret = xgbe_i2c_set_enable(pdata, enable: false); |
185 | if (ret) { |
186 | /* Disable failed, try an abort */ |
187 | ret = xgbe_i2c_abort(pdata); |
188 | if (ret) |
189 | return ret; |
190 | |
191 | /* Abort succeeded, try to disable again */ |
192 | ret = xgbe_i2c_set_enable(pdata, enable: false); |
193 | } |
194 | |
195 | return ret; |
196 | } |
197 | |
198 | static int xgbe_i2c_enable(struct xgbe_prv_data *pdata) |
199 | { |
200 | return xgbe_i2c_set_enable(pdata, enable: true); |
201 | } |
202 | |
203 | static void xgbe_i2c_clear_all_interrupts(struct xgbe_prv_data *pdata) |
204 | { |
205 | XI2C_IOREAD(pdata, IC_CLR_INTR); |
206 | } |
207 | |
208 | static void xgbe_i2c_disable_interrupts(struct xgbe_prv_data *pdata) |
209 | { |
210 | XI2C_IOWRITE(pdata, IC_INTR_MASK, 0); |
211 | } |
212 | |
213 | static void xgbe_i2c_enable_interrupts(struct xgbe_prv_data *pdata) |
214 | { |
215 | XI2C_IOWRITE(pdata, IC_INTR_MASK, XGBE_DEFAULT_INT_MASK); |
216 | } |
217 | |
218 | static void xgbe_i2c_write(struct xgbe_prv_data *pdata) |
219 | { |
220 | struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; |
221 | unsigned int tx_slots; |
222 | unsigned int cmd; |
223 | |
224 | /* Configured to never receive Rx overflows, so fill up Tx fifo */ |
225 | tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR); |
226 | while (tx_slots && state->tx_len) { |
227 | if (state->op->cmd == XGBE_I2C_CMD_READ) |
228 | cmd = XGBE_I2C_READ; |
229 | else |
230 | cmd = *state->tx_buf++; |
231 | |
232 | if (state->tx_len == 1) |
233 | XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1); |
234 | |
235 | XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd); |
236 | |
237 | tx_slots--; |
238 | state->tx_len--; |
239 | } |
240 | |
241 | /* No more Tx operations, so ignore TX_EMPTY and return */ |
242 | if (!state->tx_len) |
243 | XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0); |
244 | } |
245 | |
246 | static void xgbe_i2c_read(struct xgbe_prv_data *pdata) |
247 | { |
248 | struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; |
249 | unsigned int rx_slots; |
250 | |
251 | /* Anything to be read? */ |
252 | if (state->op->cmd != XGBE_I2C_CMD_READ) |
253 | return; |
254 | |
255 | rx_slots = XI2C_IOREAD(pdata, IC_RXFLR); |
256 | while (rx_slots && state->rx_len) { |
257 | *state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD); |
258 | state->rx_len--; |
259 | rx_slots--; |
260 | } |
261 | } |
262 | |
263 | static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata, |
264 | unsigned int isr) |
265 | { |
266 | struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; |
267 | |
268 | if (isr & XGBE_INTR_TX_ABRT) { |
269 | state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE); |
270 | XI2C_IOREAD(pdata, IC_CLR_TX_ABRT); |
271 | } |
272 | |
273 | if (isr & XGBE_INTR_STOP_DET) |
274 | XI2C_IOREAD(pdata, IC_CLR_STOP_DET); |
275 | } |
276 | |
277 | static void xgbe_i2c_isr_task(struct tasklet_struct *t) |
278 | { |
279 | struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_i2c); |
280 | struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; |
281 | unsigned int isr; |
282 | |
283 | isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT); |
284 | if (!isr) |
285 | goto reissue_check; |
286 | |
287 | netif_dbg(pdata, intr, pdata->netdev, |
288 | "I2C interrupt received: status=%#010x\n" , isr); |
289 | |
290 | xgbe_i2c_clear_isr_interrupts(pdata, isr); |
291 | |
292 | if (isr & XGBE_INTR_TX_ABRT) { |
293 | netif_dbg(pdata, link, pdata->netdev, |
294 | "I2C TX_ABRT received (%#010x) for target %#04x\n" , |
295 | state->tx_abort_source, state->op->target); |
296 | |
297 | xgbe_i2c_disable_interrupts(pdata); |
298 | |
299 | state->ret = -EIO; |
300 | goto out; |
301 | } |
302 | |
303 | /* Check for data in the Rx fifo */ |
304 | xgbe_i2c_read(pdata); |
305 | |
306 | /* Fill up the Tx fifo next */ |
307 | xgbe_i2c_write(pdata); |
308 | |
309 | out: |
310 | /* Complete on an error or STOP condition */ |
311 | if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET)) |
312 | complete(&pdata->i2c_complete); |
313 | |
314 | reissue_check: |
315 | /* Reissue interrupt if status is not clear */ |
316 | if (pdata->vdata->irq_reissue_support) |
317 | XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 2); |
318 | } |
319 | |
320 | static irqreturn_t xgbe_i2c_isr(int irq, void *data) |
321 | { |
322 | struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; |
323 | |
324 | if (pdata->isr_as_tasklet) |
325 | tasklet_schedule(t: &pdata->tasklet_i2c); |
326 | else |
327 | xgbe_i2c_isr_task(t: &pdata->tasklet_i2c); |
328 | |
329 | return IRQ_HANDLED; |
330 | } |
331 | |
332 | static void xgbe_i2c_set_mode(struct xgbe_prv_data *pdata) |
333 | { |
334 | unsigned int reg; |
335 | |
336 | reg = XI2C_IOREAD(pdata, IC_CON); |
337 | XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1); |
338 | XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1); |
339 | XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1); |
340 | XI2C_SET_BITS(reg, IC_CON, SPEED, XGBE_STD_SPEED); |
341 | XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1); |
342 | XI2C_IOWRITE(pdata, IC_CON, reg); |
343 | } |
344 | |
345 | static void xgbe_i2c_get_features(struct xgbe_prv_data *pdata) |
346 | { |
347 | struct xgbe_i2c *i2c = &pdata->i2c; |
348 | unsigned int reg; |
349 | |
350 | reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1); |
351 | i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, |
352 | MAX_SPEED_MODE); |
353 | i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, |
354 | RX_BUFFER_DEPTH); |
355 | i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, |
356 | TX_BUFFER_DEPTH); |
357 | |
358 | if (netif_msg_probe(pdata)) |
359 | dev_dbg(pdata->dev, "I2C features: %s=%u, %s=%u, %s=%u\n" , |
360 | "MAX_SPEED_MODE" , i2c->max_speed_mode, |
361 | "RX_BUFFER_DEPTH" , i2c->rx_fifo_size, |
362 | "TX_BUFFER_DEPTH" , i2c->tx_fifo_size); |
363 | } |
364 | |
365 | static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr) |
366 | { |
367 | XI2C_IOWRITE(pdata, IC_TAR, addr); |
368 | } |
369 | |
370 | static irqreturn_t xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata) |
371 | { |
372 | xgbe_i2c_isr_task(t: &pdata->tasklet_i2c); |
373 | |
374 | return IRQ_HANDLED; |
375 | } |
376 | |
377 | static int xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op) |
378 | { |
379 | struct xgbe_i2c_op_state *state = &pdata->i2c.op_state; |
380 | int ret; |
381 | |
382 | mutex_lock(&pdata->i2c_mutex); |
383 | |
384 | reinit_completion(x: &pdata->i2c_complete); |
385 | |
386 | ret = xgbe_i2c_disable(pdata); |
387 | if (ret) { |
388 | netdev_err(dev: pdata->netdev, format: "failed to disable i2c master\n" ); |
389 | goto unlock; |
390 | } |
391 | |
392 | xgbe_i2c_set_target(pdata, addr: op->target); |
393 | |
394 | memset(state, 0, sizeof(*state)); |
395 | state->op = op; |
396 | state->tx_len = op->len; |
397 | state->tx_buf = op->buf; |
398 | state->rx_len = op->len; |
399 | state->rx_buf = op->buf; |
400 | |
401 | xgbe_i2c_clear_all_interrupts(pdata); |
402 | ret = xgbe_i2c_enable(pdata); |
403 | if (ret) { |
404 | netdev_err(dev: pdata->netdev, format: "failed to enable i2c master\n" ); |
405 | goto unlock; |
406 | } |
407 | |
408 | /* Enabling the interrupts will cause the TX FIFO empty interrupt to |
409 | * fire and begin to process the command via the ISR. |
410 | */ |
411 | xgbe_i2c_enable_interrupts(pdata); |
412 | |
413 | if (!wait_for_completion_timeout(x: &pdata->i2c_complete, HZ)) { |
414 | netdev_err(dev: pdata->netdev, format: "i2c operation timed out\n" ); |
415 | ret = -ETIMEDOUT; |
416 | goto disable; |
417 | } |
418 | |
419 | ret = state->ret; |
420 | if (ret) { |
421 | if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK) |
422 | ret = -ENOTCONN; |
423 | else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST) |
424 | ret = -EAGAIN; |
425 | } |
426 | |
427 | disable: |
428 | xgbe_i2c_disable_interrupts(pdata); |
429 | xgbe_i2c_disable(pdata); |
430 | |
431 | unlock: |
432 | mutex_unlock(lock: &pdata->i2c_mutex); |
433 | |
434 | return ret; |
435 | } |
436 | |
437 | static void xgbe_i2c_stop(struct xgbe_prv_data *pdata) |
438 | { |
439 | if (!pdata->i2c.started) |
440 | return; |
441 | |
442 | netif_dbg(pdata, link, pdata->netdev, "stopping I2C\n" ); |
443 | |
444 | pdata->i2c.started = 0; |
445 | |
446 | xgbe_i2c_disable_interrupts(pdata); |
447 | xgbe_i2c_disable(pdata); |
448 | xgbe_i2c_clear_all_interrupts(pdata); |
449 | |
450 | if (pdata->dev_irq != pdata->i2c_irq) { |
451 | devm_free_irq(dev: pdata->dev, irq: pdata->i2c_irq, dev_id: pdata); |
452 | tasklet_kill(t: &pdata->tasklet_i2c); |
453 | } |
454 | } |
455 | |
456 | static int xgbe_i2c_start(struct xgbe_prv_data *pdata) |
457 | { |
458 | int ret; |
459 | |
460 | if (pdata->i2c.started) |
461 | return 0; |
462 | |
463 | netif_dbg(pdata, link, pdata->netdev, "starting I2C\n" ); |
464 | |
465 | /* If we have a separate I2C irq, enable it */ |
466 | if (pdata->dev_irq != pdata->i2c_irq) { |
467 | tasklet_setup(t: &pdata->tasklet_i2c, callback: xgbe_i2c_isr_task); |
468 | |
469 | ret = devm_request_irq(dev: pdata->dev, irq: pdata->i2c_irq, |
470 | handler: xgbe_i2c_isr, irqflags: 0, devname: pdata->i2c_name, |
471 | dev_id: pdata); |
472 | if (ret) { |
473 | netdev_err(dev: pdata->netdev, format: "i2c irq request failed\n" ); |
474 | return ret; |
475 | } |
476 | } |
477 | |
478 | pdata->i2c.started = 1; |
479 | |
480 | return 0; |
481 | } |
482 | |
483 | static int xgbe_i2c_init(struct xgbe_prv_data *pdata) |
484 | { |
485 | int ret; |
486 | |
487 | xgbe_i2c_disable_interrupts(pdata); |
488 | |
489 | ret = xgbe_i2c_disable(pdata); |
490 | if (ret) { |
491 | dev_err(pdata->dev, "failed to disable i2c master\n" ); |
492 | return ret; |
493 | } |
494 | |
495 | xgbe_i2c_get_features(pdata); |
496 | |
497 | xgbe_i2c_set_mode(pdata); |
498 | |
499 | xgbe_i2c_clear_all_interrupts(pdata); |
500 | |
501 | return 0; |
502 | } |
503 | |
504 | void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *i2c_if) |
505 | { |
506 | i2c_if->i2c_init = xgbe_i2c_init; |
507 | |
508 | i2c_if->i2c_start = xgbe_i2c_start; |
509 | i2c_if->i2c_stop = xgbe_i2c_stop; |
510 | |
511 | i2c_if->i2c_xfer = xgbe_i2c_xfer; |
512 | |
513 | i2c_if->i2c_isr = xgbe_i2c_combined_isr; |
514 | } |
515 | |