File Index
Files and directories
Sign in
FILE

xgbe-i2c.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c C
  1// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
  2/*
  3 * Copyright (c) 2014-2025, Advanced Micro Devices, Inc.
  4 * Copyright (c) 2014, Synopsys, Inc.
  5 * All rights reserved
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/interrupt.h>
 10#include <linux/kmod.h>
 11#include <linux/delay.h>
 12#include <linux/completion.h>
 13#include <linux/mutex.h>
 14
 15#include "xgbe.h"
 16#include "xgbe-common.h"
 17
 18#define XGBE_ABORT_COUNT	500
 19#define XGBE_DISABLE_COUNT	1000
 20
 21#define XGBE_STD_SPEED		1
 22
 23#define XGBE_INTR_RX_FULL	BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX)
 24#define XGBE_INTR_TX_EMPTY	BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX)
 25#define XGBE_INTR_TX_ABRT	BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX)
 26#define XGBE_INTR_STOP_DET	BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX)
 27#define XGBE_DEFAULT_INT_MASK	(XGBE_INTR_RX_FULL  |	\
 28				 XGBE_INTR_TX_EMPTY |	\
 29				 XGBE_INTR_TX_ABRT  |	\
 30				 XGBE_INTR_STOP_DET)
 31
 32#define XGBE_I2C_READ		BIT(8)
 33#define XGBE_I2C_STOP		BIT(9)
 34
 35static int xgbe_i2c_abort(struct xgbe_prv_data *pdata)
 36{
 37	unsigned int wait = XGBE_ABORT_COUNT;
 38
 39	/* Must be enabled to recognize the abort request */
 40	XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1);
 41
 42	/* Issue the abort */
 43	XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1);
 44
 45	while (wait--) {
 46		if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT))
 47			return 0;
 48
 49		usleep_range(500, 600);
 50	}
 51
 52	return -EBUSY;
 53}
 54
 55static int xgbe_i2c_set_enable(struct xgbe_prv_data *pdata, bool enable)
 56{
 57	unsigned int wait = XGBE_DISABLE_COUNT;
 58	unsigned int mode = enable ? 1 : 0;
 59
 60	while (wait--) {
 61		XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode);
 62		if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode)
 63			return 0;
 64
 65		usleep_range(100, 110);
 66	}
 67
 68	return -EBUSY;
 69}
 70
 71static int xgbe_i2c_disable(struct xgbe_prv_data *pdata)
 72{
 73	int ret;
 74
 75	ret = xgbe_i2c_set_enable(pdata, false);
 76	if (ret) {
 77		/* Disable failed, try an abort */
 78		ret = xgbe_i2c_abort(pdata);
 79		if (ret)
 80			return ret;
 81
 82		/* Abort succeeded, try to disable again */
 83		ret = xgbe_i2c_set_enable(pdata, false);
 84	}
 85
 86	return ret;
 87}
 88
 89static int xgbe_i2c_enable(struct xgbe_prv_data *pdata)
 90{
 91	return xgbe_i2c_set_enable(pdata, true);
 92}
 93
 94static void xgbe_i2c_clear_all_interrupts(struct xgbe_prv_data *pdata)
 95{
 96	XI2C_IOREAD(pdata, IC_CLR_INTR);
 97}
 98
 99static void xgbe_i2c_disable_interrupts(struct xgbe_prv_data *pdata)
100{
101	XI2C_IOWRITE(pdata, IC_INTR_MASK, 0);
102}
103
104static void xgbe_i2c_enable_interrupts(struct xgbe_prv_data *pdata)
105{
106	XI2C_IOWRITE(pdata, IC_INTR_MASK, XGBE_DEFAULT_INT_MASK);
107}
108
109static void xgbe_i2c_write(struct xgbe_prv_data *pdata)
110{
111	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
112	unsigned int tx_slots;
113	unsigned int cmd;
114
115	/* Configured to never receive Rx overflows, so fill up Tx fifo */
116	tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR);
117	while (tx_slots && state->tx_len) {
118		if (state->op->cmd == XGBE_I2C_CMD_READ)
119			cmd = XGBE_I2C_READ;
120		else
121			cmd = *state->tx_buf++;
122
123		if (state->tx_len == 1)
124			XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1);
125
126		XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd);
127
128		tx_slots--;
129		state->tx_len--;
130	}
131
132	/* No more Tx operations, so ignore TX_EMPTY and return */
133	if (!state->tx_len)
134		XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0);
135}
136
137static void xgbe_i2c_read(struct xgbe_prv_data *pdata)
138{
139	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
140	unsigned int rx_slots;
141
142	/* Anything to be read? */
143	if (state->op->cmd != XGBE_I2C_CMD_READ)
144		return;
145
146	rx_slots = XI2C_IOREAD(pdata, IC_RXFLR);
147	while (rx_slots && state->rx_len) {
148		*state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD);
149		state->rx_len--;
150		rx_slots--;
151	}
152}
153
154static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata,
155					  unsigned int isr)
156{
157	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
158
159	if (isr & XGBE_INTR_TX_ABRT) {
160		state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE);
161		XI2C_IOREAD(pdata, IC_CLR_TX_ABRT);
162	}
163
164	if (isr & XGBE_INTR_STOP_DET)
165		XI2C_IOREAD(pdata, IC_CLR_STOP_DET);
166}
167
168static void xgbe_i2c_isr_bh_work(struct work_struct *work)
169{
170	struct xgbe_prv_data *pdata = from_work(pdata, work, i2c_bh_work);
171	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
172	unsigned int isr;
173
174	isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT);
175	if (!isr)
176		goto reissue_check;
177
178	netif_dbg(pdata, intr, pdata->netdev,
179		  "I2C interrupt received: status=%#010x\n", isr);
180
181	xgbe_i2c_clear_isr_interrupts(pdata, isr);
182
183	if (isr & XGBE_INTR_TX_ABRT) {
184		netif_dbg(pdata, link, pdata->netdev,
185			  "I2C TX_ABRT received (%#010x) for target %#04x\n",
186			  state->tx_abort_source, state->op->target);
187
188		xgbe_i2c_disable_interrupts(pdata);
189
190		state->ret = -EIO;
191		goto out;
192	}
193
194	/* Check for data in the Rx fifo */
195	xgbe_i2c_read(pdata);
196
197	/* Fill up the Tx fifo next */
198	xgbe_i2c_write(pdata);
199
200out:
201	/* Complete on an error or STOP condition */
202	if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET))
203		complete(&pdata->i2c_complete);
204
205reissue_check:
206	/* Reissue interrupt if status is not clear */
207	if (pdata->vdata->irq_reissue_support)
208		XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 2);
209}
210
211static irqreturn_t xgbe_i2c_isr(int irq, void *data)
212{
213	struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
214
215	if (pdata->isr_as_bh_work)
216		queue_work(system_bh_wq, &pdata->i2c_bh_work);
217	else
218		xgbe_i2c_isr_bh_work(&pdata->i2c_bh_work);
219
220	return IRQ_HANDLED;
221}
222
223static void xgbe_i2c_set_mode(struct xgbe_prv_data *pdata)
224{
225	unsigned int reg;
226
227	reg = XI2C_IOREAD(pdata, IC_CON);
228	XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1);
229	XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1);
230	XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1);
231	XI2C_SET_BITS(reg, IC_CON, SPEED, XGBE_STD_SPEED);
232	XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1);
233	XI2C_IOWRITE(pdata, IC_CON, reg);
234}
235
236static void xgbe_i2c_get_features(struct xgbe_prv_data *pdata)
237{
238	struct xgbe_i2c *i2c = &pdata->i2c;
239	unsigned int reg;
240
241	reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1);
242	i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
243					    MAX_SPEED_MODE);
244	i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
245					  RX_BUFFER_DEPTH);
246	i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
247					  TX_BUFFER_DEPTH);
248
249	if (netif_msg_probe(pdata))
250		dev_dbg(pdata->dev, "I2C features: %s=%u, %s=%u, %s=%u\n",
251			"MAX_SPEED_MODE", i2c->max_speed_mode,
252			"RX_BUFFER_DEPTH", i2c->rx_fifo_size,
253			"TX_BUFFER_DEPTH", i2c->tx_fifo_size);
254}
255
256static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr)
257{
258	XI2C_IOWRITE(pdata, IC_TAR, addr);
259}
260
261static irqreturn_t xgbe_i2c_combined_isr(struct xgbe_prv_data *pdata)
262{
263	xgbe_i2c_isr_bh_work(&pdata->i2c_bh_work);
264
265	return IRQ_HANDLED;
266}
267
268static int xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op)
269{
270	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
271	int ret;
272
273	mutex_lock(&pdata->i2c_mutex);
274
275	reinit_completion(&pdata->i2c_complete);
276
277	ret = xgbe_i2c_disable(pdata);
278	if (ret) {
279		netdev_err(pdata->netdev, "failed to disable i2c master\n");
280		goto unlock;
281	}
282
283	xgbe_i2c_set_target(pdata, op->target);
284
285	memset(state, 0, sizeof(*state));
286	state->op = op;
287	state->tx_len = op->len;
288	state->tx_buf = op->buf;
289	state->rx_len = op->len;
290	state->rx_buf = op->buf;
291
292	xgbe_i2c_clear_all_interrupts(pdata);
293	ret = xgbe_i2c_enable(pdata);
294	if (ret) {
295		netdev_err(pdata->netdev, "failed to enable i2c master\n");
296		goto unlock;
297	}
298
299	/* Enabling the interrupts will cause the TX FIFO empty interrupt to
300	 * fire and begin to process the command via the ISR.
301	 */
302	xgbe_i2c_enable_interrupts(pdata);
303
304	if (!wait_for_completion_timeout(&pdata->i2c_complete, HZ)) {
305		netdev_err(pdata->netdev, "i2c operation timed out\n");
306		ret = -ETIMEDOUT;
307		goto disable;
308	}
309
310	ret = state->ret;
311	if (ret) {
312		if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK)
313			ret = -ENOTCONN;
314		else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST)
315			ret = -EAGAIN;
316	}
317
318disable:
319	xgbe_i2c_disable_interrupts(pdata);
320	xgbe_i2c_disable(pdata);
321
322unlock:
323	mutex_unlock(&pdata->i2c_mutex);
324
325	return ret;
326}
327
328static void xgbe_i2c_stop(struct xgbe_prv_data *pdata)
329{
330	if (!pdata->i2c.started)
331		return;
332
333	netif_dbg(pdata, link, pdata->netdev, "stopping I2C\n");
334
335	pdata->i2c.started = 0;
336
337	xgbe_i2c_disable_interrupts(pdata);
338	xgbe_i2c_disable(pdata);
339	xgbe_i2c_clear_all_interrupts(pdata);
340
341	if (pdata->dev_irq != pdata->i2c_irq) {
342		devm_free_irq(pdata->dev, pdata->i2c_irq, pdata);
343		cancel_work_sync(&pdata->i2c_bh_work);
344	}
345}
346
347static int xgbe_i2c_start(struct xgbe_prv_data *pdata)
348{
349	int ret;
350
351	if (pdata->i2c.started)
352		return 0;
353
354	netif_dbg(pdata, link, pdata->netdev, "starting I2C\n");
355
356	/* If we have a separate I2C irq, enable it */
357	if (pdata->dev_irq != pdata->i2c_irq) {
358		INIT_WORK(&pdata->i2c_bh_work, xgbe_i2c_isr_bh_work);
359
360		ret = devm_request_irq(pdata->dev, pdata->i2c_irq,
361				       xgbe_i2c_isr, 0, pdata->i2c_name,
362				       pdata);
363		if (ret) {
364			netdev_err(pdata->netdev, "i2c irq request failed\n");
365			return ret;
366		}
367	}
368
369	pdata->i2c.started = 1;
370
371	return 0;
372}
373
374static int xgbe_i2c_init(struct xgbe_prv_data *pdata)
375{
376	int ret;
377
378	xgbe_i2c_disable_interrupts(pdata);
379
380	ret = xgbe_i2c_disable(pdata);
381	if (ret) {
382		dev_err(pdata->dev, "failed to disable i2c master\n");
383		return ret;
384	}
385
386	xgbe_i2c_get_features(pdata);
387
388	xgbe_i2c_set_mode(pdata);
389
390	xgbe_i2c_clear_all_interrupts(pdata);
391
392	return 0;
393}
394
395void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *i2c_if)
396{
397	i2c_if->i2c_init		= xgbe_i2c_init;
398
399	i2c_if->i2c_start		= xgbe_i2c_start;
400	i2c_if->i2c_stop		= xgbe_i2c_stop;
401
402	i2c_if->i2c_xfer		= xgbe_i2c_xfer;
403
404	i2c_if->i2c_isr			= xgbe_i2c_combined_isr;
405}
~/ Read-only file preview.