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